diff --git a/build/tools/mk_sdk_repo_xml.sh b/build/tools/mk_sdk_repo_xml.sh index 3220d45ec..e977a03fb 100755 --- a/build/tools/mk_sdk_repo_xml.sh +++ b/build/tools/mk_sdk_repo_xml.sh @@ -6,7 +6,7 @@ set -e PROG_DIR=$(dirname $0) -TYPES="tool platform-tool platform sample doc add-on system-image" +TYPES="tool platform-tool platform sample doc add-on system-image source" OSES="linux macosx windows any linux-x86 darwin" TMP_DIR=$(mktemp -d -t sdkrepo.tmp.XXXXXXXX) diff --git a/build/tools/mk_sources_zip.py b/build/tools/mk_sources_zip.py new file mode 100755 index 000000000..8abccb808 --- /dev/null +++ b/build/tools/mk_sources_zip.py @@ -0,0 +1,201 @@ +#!/usr/bin/python +# +# Copyright (C) 2011 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import re +import os +import sys +import getopt +import zipfile + +VERBOSE = False +TOP_FOLDER = "src" +_RE_PKG = re.compile("^\s*package\s+([^\s;]+)\s*;.*") + +# Holds cmd-line arguments and context information +class Params(object): + def __init__(self): + self.DRY = False + self.PROPS = None + self.SRC = None + self.DST = None + self.CNT_USED = 0 + self.CNT_NOPKG = 0 + # DIR is the list of directories to scan in TOPDIR. + self.DIR = "frameworks libcore" + # IGNORE is a list of namespaces to ignore. Must be java + # package definitions (e.g. "com.something.foo.") + self.IGNORE = [ "sun.", "com.", "libcore.", "dalvik.", + "coretestutils.", "test.", "test2.", "tests." ] + self.zipfile = None + + +def verbose(msg, *args): + """Prints a verbose message to stderr if --verbose is set.""" + global VERBOSE + if VERBOSE: + if args: + msg = msg % args + print >>sys.stderr, msg + + +# Prints a usage summary +def usage(error=None): + print """ + Description: + This script collects all framework Java sources from the current android + source code and places them in a source.zip file that can be distributed + by the SDK Manager. + + Usage: + %s [-n|-v] + + The source.properties file must exist and will be injected in the Zip file. + The source directory must already exist. + Use -v for verbose output (lists each file being picked up or ignored). + Use -n for a dry-run (doesn't write the zip file). + +""" % sys.argv[0] + + if error: + print >>sys.stderr, "Error:", error + + +# Parse command line args, returns a Params instance or sys.exit(2) on error +# after printing the error and the usage. +def parseArgs(argv): + global VERBOSE + p = Params() + error = None + + try: + opts, args = getopt.getopt(argv[1:], + "vns:", + [ "--verbose", "--dry", "--sourcedir=" ]) + except getopt.GetoptError, e: + error = str(e) + + if error is None: + for o, a in opts: + if o in [ "-n", "--dry" ]: + p.DRY = True + if o in [ "-v", "--verbose" ]: + VERBOSE = True + elif o in [ "-s", "--sourcedir" ]: + p.DIR = a + + if len(args) != 3: + error = "Missing arguments: " + else: + p.PROPS = args[0] + p.DST = args[1] + p.SRC = args[2] + + if not os.path.isfile(p.PROPS): + error = "%s is not a file" % p.PROPS + if not os.path.isdir(p.SRC): + error = "%s is not a directory" % p.SRC + + if error: + usage(error) + sys.exit(2) + + return p + + +# Recursively parses the given directory and processes java files found +def parseSrcDir(p, srcdir): + if not os.path.exists(srcdir): + verbose("Error: Skipping unknown directory %s", srcdir) + return + + for filename in os.listdir(srcdir): + filepath = os.path.join(srcdir, filename) + if filename.endswith(".java") and os.path.isfile(filepath): + pkg = checkJavaFile(filepath) + if not pkg: + verbose("No package found in %s", filepath) + if pkg: + # Should we ignore this package? + for ignore in p.IGNORE: + if pkg.startswith(ignore): + verbose("Ignore package %s [%s]", pkg, filepath) + pkg = None + break + + if pkg: + pkg = pkg.replace(".", os.path.sep) # e.g. android.view => android/view + copy(p, filepath, pkg) + p.CNT_USED += 1 + else: + p.CNT_NOPKG += 1 + elif os.path.isdir(filepath): + parseSrcDir(p, filepath) + + +# Check a java file to find its package declaration, if any +def checkJavaFile(path): + try: + f = None + try: + f = file(path) + for l in f.readlines(): + m = _RE_PKG.match(l) + if m: + return m.group(1) + finally: + if f: f.close() + except Exception: + pass + + return None + + +# Copy the given file (given its absolute filepath) to +# the relative desk_pkg directory in the zip file. +def copy(p, filepath, dest_pkg): + arc_path = os.path.join(TOP_FOLDER, dest_pkg, os.path.basename(filepath)) + if p.DRY: + print >>sys.stderr, "zip %s [%s]" % (arc_path, filepath) + elif p.zipfile is not None: + p.zipfile.write(filepath, arc_path) + + +def main(): + p = parseArgs(sys.argv) + z = None + try: + if not p.DRY: + p.zipfile = z = zipfile.ZipFile(p.DST, "w", zipfile.ZIP_DEFLATED) + z.write(p.PROPS, TOP_FOLDER + "/source.properties") + for d in p.DIR.split(): + if d: + parseSrcDir(p, os.path.join(p.SRC, d)) + finally: + if z is not None: + z.close() + print "%s: %d java files copied" % (p.DST, p.CNT_USED) + if p.CNT_NOPKG: + print "%s: %d java files ignored" % (p.DST, p.CNT_NOPKG) + if p.DRY: + print >>sys.stderr, "This was in *DRY* mode. No copies done." + + +if __name__ == "__main__": + main() + +# For emacs: +# -*- tab-width: 4; -*- diff --git a/build/tools/sdk_repo.mk b/build/tools/sdk_repo.mk index c49eefb48..549b66b93 100644 --- a/build/tools/sdk_repo.mk +++ b/build/tools/sdk_repo.mk @@ -56,6 +56,23 @@ SDK_REPO_XML_ARGS += $(3) $(1) \ $(call sdk-repo-pkg-zip,$(1),$(2),$(3)):$(notdir $(call sdk-repo-pkg-zip,$(1),$(2),$(3))) endef +# Defines the rule to build an SDK sources package. +# +# $1=OS (e.g. linux-x86, windows, etc) +# $2=sdk zip (e.g. out/host/linux.../android-eng-sdk.zip) +# $3=package to create, must be "sources" +# +define mk-sdk-repo-sources +$(call sdk-repo-pkg-zip,$(1),$(2),$(3)): $(2) $(TOPDIR)development/sdk/source_source.properties + @echo "Building SDK sources package" + $(hide) $(TOPDIR)development/build/tools/mk_sources_zip.py \ + $(TOPDIR)development/sdk/source_source.properties \ + $(call sdk-repo-pkg-zip,$(1),$(2),$(3)) \ + $(TOPDIR). +$(call dist-for-goals, sdk_repo, $(call sdk-repo-pkg-zip,$(1),$(2),$(3))) +SDK_REPO_XML_ARGS += $(3) $(1) \ + $(call sdk-repo-pkg-zip,$(1),$(2),$(3)):$(notdir $(call sdk-repo-pkg-zip,$(1),$(2),$(3))) +endef # ----------------------------------------------------------------- # Rules for win_sdk @@ -83,6 +100,7 @@ $(eval $(call mk-sdk-repo-pkg-1,$(HOST_OS),$(MAIN_SDK_ZIP),docs)) $(eval $(call mk-sdk-repo-pkg-2,$(HOST_OS),$(MAIN_SDK_ZIP),platforms)) $(eval $(call mk-sdk-repo-pkg-2,$(HOST_OS),$(MAIN_SDK_ZIP),samples)) $(eval $(call mk-sdk-repo-pkg-2,$(HOST_OS),$(MAIN_SDK_ZIP),system-images)) +$(eval $(call mk-sdk-repo-sources,$(HOST_OS),$(MAIN_SDK_ZIP),sources)) SDK_REPO_DEPS += \ $(call sdk-repo-pkg-zip,$(HOST_OS),$(MAIN_SDK_ZIP),tools) \ @@ -90,7 +108,8 @@ SDK_REPO_DEPS += \ $(call sdk-repo-pkg-zip,$(HOST_OS),$(MAIN_SDK_ZIP),docs) \ $(call sdk-repo-pkg-zip,$(HOST_OS),$(MAIN_SDK_ZIP),platforms) \ $(call sdk-repo-pkg-zip,$(HOST_OS),$(MAIN_SDK_ZIP),samples) \ - $(call sdk-repo-pkg-zip,$(HOST_OS),$(MAIN_SDK_ZIP),system-images) + $(call sdk-repo-pkg-zip,$(HOST_OS),$(MAIN_SDK_ZIP),system-images) \ + $(call sdk-repo-pkg-zip,$(HOST_OS),$(MAIN_SDK_ZIP),sources) endif diff --git a/sdk/source_source.properties b/sdk/source_source.properties new file mode 100644 index 000000000..7cb1d33df --- /dev/null +++ b/sdk/source_source.properties @@ -0,0 +1,4 @@ +Pkg.UserSrc=false +Pkg.Revision=1 +AndroidVersion.ApiLevel=14 +#AndroidVersion.CodeName=