diff options
-rw-r--r-- | Blueprints | 25 | ||||
-rw-r--r-- | androidmk/cmd/androidmk/android.go | 17 | ||||
-rw-r--r-- | build.ninja.in | 74 | ||||
-rw-r--r-- | cmd/soong_build/main.go | 8 | ||||
-rw-r--r-- | cmd/soong_jar/soong_jar.go | 220 | ||||
-rw-r--r-- | common/arch.go | 25 | ||||
-rw-r--r-- | common/module.go | 5 | ||||
-rw-r--r-- | java/builder.go | 189 | ||||
-rw-r--r-- | java/java.go | 403 | ||||
-rw-r--r-- | java/resources.go | 45 | ||||
-rw-r--r-- | root.bp | 3 |
11 files changed, 996 insertions, 18 deletions
@@ -21,6 +21,7 @@ bootstrap_go_binary { "soong-config", "soong-env", "soong-genrule", + "soong-java", ], srcs: [ "cmd/soong_build/main.go", @@ -138,6 +139,30 @@ bootstrap_go_package { "genrule/genrule.go", ], } + +bootstrap_go_binary { + name: "soong_jar", + srcs: [ + "cmd/soong_jar/soong_jar.go", + ], +} + +bootstrap_go_package { + name: "soong-java", + pkgPath: "android/soong/java", + deps: [ + "blueprint", + "blueprint-pathtools", + "soong-common", + "soong-config", + ], + srcs: [ + "java/builder.go", + "java/java.go", + "java/resources.go", + ], +} + // // androidmk Android.mk to Blueprints translator // diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go index 4f2fca1a..9de0197f 100644 --- a/androidmk/cmd/androidmk/android.go +++ b/androidmk/cmd/androidmk/android.go @@ -18,6 +18,7 @@ var stringProperties = map[string]string{ "LOCAL_ARM_MODE_HACK": "instruction_set", "LOCAL_SDK_VERSION": "sdk_version", "LOCAL_NDK_STL_VARIANT": "stl", + "LOCAL_JAR_MANIFEST": "manifest", } var listProperties = map[string]string{ @@ -38,6 +39,12 @@ var listProperties = map[string]string{ "LOCAL_MODULE_TAGS": "tags", "LOCAL_LDLIBS": "host_ldlibs", "LOCAL_CLANG_CFLAGS": "clang_cflags", + + "LOCAL_JAVA_RESOURCE_DIRS": "resource_dirs", + "LOCAL_JAVACFLAGS": "javacflags", + "LOCAL_DX_FLAGS": "dxflags", + "LOCAL_JAVA_LIBRARIES": "java_libs", + "LOCAL_STATIC_JAVA_LIBRARIES": "java_static_libs", } var boolProperties = map[string]string{ @@ -49,6 +56,8 @@ var boolProperties = map[string]string{ "LOCAL_NO_CRT": "nocrt", "LOCAL_ALLOW_UNDEFINED_SYMBOLS": "allow_undefined_symbols", "LOCAL_RTTI_FLAG": "rtti", + + "LOCAL_NO_STANDARD_LIBRARIES": "no_standard_libraries", } var deleteProperties = map[string]struct{}{ @@ -103,7 +112,13 @@ var moduleTypes = map[string]string{ "BUILD_HOST_EXECUTABLE": "cc_binary_host", "BUILD_NATIVE_TEST": "cc_test", "BUILD_HOST_NATIVE_TEST": "cc_test_host", - "BUILD_PREBUILT": "prebuilt", + + "BUILD_JAVA_LIBRARY": "java_library", + "BUILD_STATIC_JAVA_LIBRARY": "java_library_static", + "BUILD_HOST_JAVA_LIBRARY": "java_library_host", + "BUILD_HOST_DALVIK_JAVA_LIBRARY": "java_library_host_dalvik", + + "BUILD_PREBUILT": "prebuilt", } var soongModuleTypes = map[string]bool{} diff --git a/build.ninja.in b/build.ninja.in index 4fb63250..cdc72fcd 100644 --- a/build.ninja.in +++ b/build.ninja.in @@ -53,7 +53,7 @@ rule g.bootstrap.link # Variant: # Type: bootstrap_go_binary # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModule -# Defined: build/soong/Blueprints:145:1 +# Defined: build/soong/Blueprints:170:1 build .bootstrap/androidmk/obj/androidmk.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/androidmk/cmd/androidmk/android.go $ @@ -79,7 +79,7 @@ default .bootstrap/bin/androidmk # Variant: # Type: bootstrap_go_package # Factory: github.com/google/blueprint/bootstrap.newGoPackageModule -# Defined: build/soong/Blueprints:158:1 +# Defined: build/soong/Blueprints:183:1 build .bootstrap/androidmk-parser/pkg/android/soong/androidmk/parser.a: $ g.bootstrap.gc $ @@ -310,7 +310,7 @@ default .bootstrap/soong-art/pkg/android/soong/art.a # Variant: # Type: bootstrap_go_package # Factory: github.com/google/blueprint/bootstrap.newGoPackageModule -# Defined: build/soong/Blueprints:104:1 +# Defined: build/soong/Blueprints:105:1 build .bootstrap/soong-cc/pkg/android/soong/cc.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/cc/builder.go $ @@ -342,7 +342,7 @@ default .bootstrap/soong-cc/pkg/android/soong/cc.a # Variant: # Type: bootstrap_go_package # Factory: github.com/google/blueprint/bootstrap.newGoPackageModule -# Defined: build/soong/Blueprints:71:1 +# Defined: build/soong/Blueprints:72:1 build .bootstrap/soong-common/pkg/android/soong/common.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/common/arch.go $ @@ -370,7 +370,7 @@ default .bootstrap/soong-common/pkg/android/soong/common.a # Variant: # Type: bootstrap_go_package # Factory: github.com/google/blueprint/bootstrap.newGoPackageModule -# Defined: build/soong/Blueprints:91:1 +# Defined: build/soong/Blueprints:92:1 build .bootstrap/soong-config/pkg/android/soong/config.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/config/config.go | $ @@ -393,7 +393,7 @@ default .bootstrap/soong-config/pkg/android/soong/config.a # Variant: # Type: bootstrap_go_package # Factory: github.com/google/blueprint/bootstrap.newGoPackageModule -# Defined: build/soong/Blueprints:41:1 +# Defined: build/soong/Blueprints:42:1 build .bootstrap/soong-env/pkg/android/soong/env.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/env/env.go | ${g.bootstrap.gcCmd} @@ -405,7 +405,7 @@ default .bootstrap/soong-env/pkg/android/soong/env.a # Variant: # Type: bootstrap_go_package # Factory: github.com/google/blueprint/bootstrap.newGoPackageModule -# Defined: build/soong/Blueprints:128:1 +# Defined: build/soong/Blueprints:129:1 build .bootstrap/soong-genrule/pkg/android/soong/genrule.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/genrule/genrule.go | $ @@ -429,7 +429,7 @@ default .bootstrap/soong-genrule/pkg/android/soong/genrule.a # Variant: # Type: bootstrap_go_package # Factory: github.com/google/blueprint/bootstrap.newGoPackageModule -# Defined: build/soong/Blueprints:60:1 +# Defined: build/soong/Blueprints:61:1 build .bootstrap/soong-glob/pkg/android/soong/glob.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/glob/glob.go | ${g.bootstrap.gcCmd} $ @@ -439,6 +439,32 @@ build .bootstrap/soong-glob/pkg/android/soong/glob.a: g.bootstrap.gc $ default .bootstrap/soong-glob/pkg/android/soong/glob.a # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# Module: soong-java +# Variant: +# Type: bootstrap_go_package +# Factory: github.com/google/blueprint/bootstrap.newGoPackageModule +# Defined: build/soong/Blueprints:150:1 + +build .bootstrap/soong-java/pkg/android/soong/java.a: g.bootstrap.gc $ + ${g.bootstrap.srcDir}/build/soong/java/builder.go $ + ${g.bootstrap.srcDir}/build/soong/java/java.go $ + ${g.bootstrap.srcDir}/build/soong/java/resources.go | $ + ${g.bootstrap.gcCmd} $ + .bootstrap/blueprint-parser/pkg/github.com/google/blueprint/parser.a $ + .bootstrap/blueprint-proptools/pkg/github.com/google/blueprint/proptools.a $ + .bootstrap/blueprint/pkg/github.com/google/blueprint.a $ + .bootstrap/blueprint-pathtools/pkg/github.com/google/blueprint/pathtools.a $ + .bootstrap/blueprint-deptools/pkg/github.com/google/blueprint/deptools.a $ + .bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a $ + .bootstrap/soong-env/pkg/android/soong/env.a $ + .bootstrap/soong-glob/pkg/android/soong/glob.a $ + .bootstrap/soong-common/pkg/android/soong/common.a $ + .bootstrap/soong-config/pkg/android/soong/config.a + incFlags = -I .bootstrap/blueprint-parser/pkg -I .bootstrap/blueprint-proptools/pkg -I .bootstrap/blueprint/pkg -I .bootstrap/blueprint-pathtools/pkg -I .bootstrap/blueprint-deptools/pkg -I .bootstrap/blueprint-bootstrap/pkg -I .bootstrap/soong-env/pkg -I .bootstrap/soong-glob/pkg -I .bootstrap/soong-common/pkg -I .bootstrap/soong-config/pkg + pkgPath = android/soong/java +default .bootstrap/soong-java/pkg/android/soong/java.a + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Module: soong_build # Variant: # Type: bootstrap_go_binary @@ -460,14 +486,15 @@ build .bootstrap/soong_build/obj/soong_build.a: g.bootstrap.gc $ .bootstrap/soong-config/pkg/android/soong/config.a $ .bootstrap/soong-genrule/pkg/android/soong/genrule.a $ .bootstrap/soong-cc/pkg/android/soong/cc.a $ - .bootstrap/soong-art/pkg/android/soong/art.a - incFlags = -I .bootstrap/blueprint-parser/pkg -I .bootstrap/blueprint-proptools/pkg -I .bootstrap/blueprint/pkg -I .bootstrap/blueprint-deptools/pkg -I .bootstrap/blueprint-pathtools/pkg -I .bootstrap/blueprint-bootstrap/pkg -I .bootstrap/soong-env/pkg -I .bootstrap/soong-glob/pkg -I .bootstrap/soong-common/pkg -I .bootstrap/soong-config/pkg -I .bootstrap/soong-genrule/pkg -I .bootstrap/soong-cc/pkg -I .bootstrap/soong-art/pkg + .bootstrap/soong-art/pkg/android/soong/art.a $ + .bootstrap/soong-java/pkg/android/soong/java.a + incFlags = -I .bootstrap/blueprint-parser/pkg -I .bootstrap/blueprint-proptools/pkg -I .bootstrap/blueprint/pkg -I .bootstrap/blueprint-deptools/pkg -I .bootstrap/blueprint-pathtools/pkg -I .bootstrap/blueprint-bootstrap/pkg -I .bootstrap/soong-env/pkg -I .bootstrap/soong-glob/pkg -I .bootstrap/soong-common/pkg -I .bootstrap/soong-config/pkg -I .bootstrap/soong-genrule/pkg -I .bootstrap/soong-cc/pkg -I .bootstrap/soong-art/pkg -I .bootstrap/soong-java/pkg pkgPath = soong_build default .bootstrap/soong_build/obj/soong_build.a build .bootstrap/soong_build/obj/a.out: g.bootstrap.link $ .bootstrap/soong_build/obj/soong_build.a | ${g.bootstrap.linkCmd} - libDirFlags = -L .bootstrap/blueprint-parser/pkg -L .bootstrap/blueprint-proptools/pkg -L .bootstrap/blueprint/pkg -L .bootstrap/blueprint-deptools/pkg -L .bootstrap/blueprint-pathtools/pkg -L .bootstrap/blueprint-bootstrap/pkg -L .bootstrap/soong-env/pkg -L .bootstrap/soong-glob/pkg -L .bootstrap/soong-common/pkg -L .bootstrap/soong-config/pkg -L .bootstrap/soong-genrule/pkg -L .bootstrap/soong-cc/pkg -L .bootstrap/soong-art/pkg + libDirFlags = -L .bootstrap/blueprint-parser/pkg -L .bootstrap/blueprint-proptools/pkg -L .bootstrap/blueprint/pkg -L .bootstrap/blueprint-deptools/pkg -L .bootstrap/blueprint-pathtools/pkg -L .bootstrap/blueprint-bootstrap/pkg -L .bootstrap/soong-env/pkg -L .bootstrap/soong-glob/pkg -L .bootstrap/soong-common/pkg -L .bootstrap/soong-config/pkg -L .bootstrap/soong-genrule/pkg -L .bootstrap/soong-cc/pkg -L .bootstrap/soong-art/pkg -L .bootstrap/soong-java/pkg default .bootstrap/soong_build/obj/a.out build .bootstrap/bin/soong_build: g.bootstrap.cp $ @@ -479,7 +506,7 @@ default .bootstrap/bin/soong_build # Variant: # Type: bootstrap_go_binary # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModule -# Defined: build/soong/Blueprints:31:1 +# Defined: build/soong/Blueprints:32:1 build .bootstrap/soong_env/obj/soong_env.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/cmd/soong_env/soong_env.go | $ @@ -501,7 +528,7 @@ default .bootstrap/bin/soong_env # Variant: # Type: bootstrap_go_binary # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModule -# Defined: build/soong/Blueprints:50:1 +# Defined: build/soong/Blueprints:51:1 build .bootstrap/soong_glob/obj/soong_glob.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/cmd/soong_glob/soong_glob.go | $ @@ -522,6 +549,25 @@ build .bootstrap/bin/soong_glob: g.bootstrap.cp $ default .bootstrap/bin/soong_glob # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# Module: soong_jar +# Variant: +# Type: bootstrap_go_binary +# Factory: github.com/google/blueprint/bootstrap.newGoBinaryModule +# Defined: build/soong/Blueprints:143:1 + +build .bootstrap/soong_jar/obj/soong_jar.a: g.bootstrap.gc $ + ${g.bootstrap.srcDir}/build/soong/cmd/soong_jar/soong_jar.go | $ + ${g.bootstrap.gcCmd} + pkgPath = soong_jar +default .bootstrap/soong_jar/obj/soong_jar.a + +build .bootstrap/soong_jar/obj/a.out: g.bootstrap.link $ + .bootstrap/soong_jar/obj/soong_jar.a | ${g.bootstrap.linkCmd} +default .bootstrap/soong_jar/obj/a.out +build .bootstrap/bin/soong_jar: g.bootstrap.cp .bootstrap/soong_jar/obj/a.out +default .bootstrap/bin/soong_jar + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Singleton: bootstrap # Factory: github.com/google/blueprint/bootstrap.newSingleton @@ -540,7 +586,7 @@ build .bootstrap/main.ninja.in: s.bootstrap.bigbp $ ${g.bootstrap.srcDir}/Blueprints | .bootstrap/bin/androidmk $ .bootstrap/bin/bpfmt .bootstrap/bin/bpmodify .bootstrap/bin/minibp $ .bootstrap/bin/soong_build .bootstrap/bin/soong_env $ - .bootstrap/bin/soong_glob + .bootstrap/bin/soong_glob .bootstrap/bin/soong_jar default .bootstrap/main.ninja.in build .bootstrap/notAFile: phony default .bootstrap/notAFile diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go index 23bcb561..01740d1c 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -28,6 +28,7 @@ import ( "android/soong/common" "android/soong/config" "android/soong/genrule" + "android/soong/java" ) func main() { @@ -61,6 +62,13 @@ func main() { ctx.RegisterModuleType("art_cc_library", art.ArtCCLibraryFactory) ctx.RegisterModuleType("art_cc_binary", art.ArtCCBinaryFactory) + ctx.RegisterModuleType("java_library", java.JavaLibraryFactory) + ctx.RegisterModuleType("java_library_static", java.JavaLibraryFactory) + ctx.RegisterModuleType("java_library_host", java.JavaLibraryHostFactory) + ctx.RegisterModuleType("java_binary", java.JavaBinaryFactory) + ctx.RegisterModuleType("java_binary_host", java.JavaBinaryHostFactory) + ctx.RegisterModuleType("prebuilt_java_library", java.JavaPrebuiltFactory) + // Mutators ctx.RegisterEarlyMutator("arch", common.ArchMutator) ctx.RegisterEarlyMutator("link", cc.LinkageMutator) diff --git a/cmd/soong_jar/soong_jar.go b/cmd/soong_jar/soong_jar.go new file mode 100644 index 00000000..23144969 --- /dev/null +++ b/cmd/soong_jar/soong_jar.go @@ -0,0 +1,220 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// 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. + +package main + +import ( + "archive/zip" + "flag" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" +) + +type fileArg struct { + relativeRoot, file string +} + +type fileArgs []fileArg + +func (l *fileArgs) String() string { + return `""` +} + +func (l *fileArgs) Set(s string) error { + if *relativeRoot == "" { + return fmt.Errorf("must pass -C before -f") + } + + *l = append(*l, fileArg{*relativeRoot, s}) + return nil +} + +func (l *fileArgs) Get() interface{} { + return l +} + +var ( + out = flag.String("o", "", "file to write jar file to") + manifest = flag.String("m", "", "input manifest file name") + directories = flag.Bool("d", false, "include directories in jar") + relativeRoot = flag.String("C", "", "path to use as relative root of files in next -f or -l argument") + listFiles fileArgs + files fileArgs +) + +func init() { + flag.Var(&listFiles, "l", "file containing list of .class files") + flag.Var(&files, "f", "file to include in jar") +} + +func usage() { + fmt.Fprintf(os.Stderr, "usage: soong_jar -o jarfile [-m manifest] -C dir [-f|-l file]...\n") + flag.PrintDefaults() + os.Exit(2) +} + +type zipInfo struct { + time time.Time + createdDirs map[string]bool + directories bool +} + +func main() { + flag.Parse() + + if *out == "" { + fmt.Fprintf(os.Stderr, "error: -o is required\n") + usage() + } + + info := zipInfo{ + time: time.Now(), + createdDirs: make(map[string]bool), + directories: *directories, + } + + // TODO: Go's zip implementation doesn't support increasing the compression level yet + err := writeZipFile(*out, listFiles, *manifest, info) + if err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + os.Exit(1) + } +} + +func writeZipFile(out string, listFiles fileArgs, manifest string, info zipInfo) error { + f, err := os.Create(out) + if err != nil { + return err + } + + defer f.Close() + defer func() { + if err != nil { + os.Remove(out) + } + }() + + zipFile := zip.NewWriter(f) + defer zipFile.Close() + + for _, listFile := range listFiles { + err = writeListFile(zipFile, listFile, info) + if err != nil { + return err + } + } + + for _, file := range files { + err = writeRelFile(zipFile, file.relativeRoot, file.file, info) + if err != nil { + return err + } + } + + if manifest != "" { + err = writeFile(zipFile, "META-INF/MANIFEST.MF", manifest, info) + if err != nil { + return err + } + } + + return nil +} + +func writeListFile(zipFile *zip.Writer, listFile fileArg, info zipInfo) error { + list, err := ioutil.ReadFile(listFile.file) + if err != nil { + return err + } + + files := strings.Split(string(list), "\n") + + for _, file := range files { + file = strings.TrimSpace(file) + if file == "" { + continue + } + err = writeRelFile(zipFile, listFile.relativeRoot, file, info) + if err != nil { + return err + } + } + + return nil +} + +func writeRelFile(zipFile *zip.Writer, root, file string, info zipInfo) error { + rel, err := filepath.Rel(root, file) + if err != nil { + return err + } + + err = writeFile(zipFile, rel, file, info) + if err != nil { + return err + } + + return nil +} + +func writeFile(zipFile *zip.Writer, rel, file string, info zipInfo) error { + if info.directories { + dir, _ := filepath.Split(rel) + for dir != "" && !info.createdDirs[dir] { + info.createdDirs[dir] = true + + dirHeader := &zip.FileHeader{ + Name: dir, + } + dirHeader.SetMode(os.ModeDir) + dirHeader.SetModTime(info.time) + + _, err := zipFile.CreateHeader(dirHeader) + if err != nil { + return err + } + + dir, _ = filepath.Split(dir) + } + } + + fileHeader := &zip.FileHeader{ + Name: rel, + Method: zip.Deflate, + } + fileHeader.SetModTime(info.time) + + out, err := zipFile.CreateHeader(fileHeader) + if err != nil { + return err + } + + in, err := os.Open(file) + if err != nil { + return err + } + defer in.Close() + + _, err = io.Copy(out, in) + if err != nil { + return err + } + + return nil +} diff --git a/common/arch.go b/common/arch.go index 1758c0db..d4c17cf0 100644 --- a/common/arch.go +++ b/common/arch.go @@ -31,6 +31,10 @@ var ( Mips64 = newArch64("Mips64") X86 = newArch32("X86") X86_64 = newArch64("X86_64") + + Common = ArchType{ + Name: "common", + } ) /* @@ -254,6 +258,14 @@ var ( HostOrDevice: Host, ArchType: X86_64, } + commonDevice = Arch{ + HostOrDevice: Device, + ArchType: Common, + } + commonHost = Arch{ + HostOrDevice: Host, + ArchType: Common, + } ) func ArchMutator(mctx blueprint.EarlyMutatorContext) { @@ -269,11 +281,18 @@ func ArchMutator(mctx blueprint.EarlyMutatorContext) { arches := []Arch{} if module.base().HostSupported() { - arches = append(arches, host64Arch) + switch module.base().commonProperties.Compile_multilib { + case "common": + arches = append(arches, commonHost) + default: + arches = append(arches, host64Arch) + } } if module.base().DeviceSupported() { switch module.base().commonProperties.Compile_multilib { + case "common": + arches = append(arches, commonDevice) case "both": arches = append(arches, arm64Arch, armArch) case "first", "64": @@ -345,6 +364,10 @@ func InitArchModule(m AndroidModule, defaultMultilib Multilib, // Rewrite the module's properties structs to contain arch-specific values. func (a *AndroidModuleBase) setArchProperties(ctx blueprint.EarlyMutatorContext, arch Arch) { + if arch.ArchType == Common { + return + } + for i := range a.generalProperties { generalPropsValue := reflect.ValueOf(a.generalProperties[i]).Elem() diff --git a/common/module.go b/common/module.go index a8343845..c008d7de 100644 --- a/common/module.go +++ b/common/module.go @@ -107,8 +107,9 @@ type hostAndDeviceProperties struct { type Multilib string const ( - MultilibBoth Multilib = "both" - MultilibFirst Multilib = "first" + MultilibBoth Multilib = "both" + MultilibFirst Multilib = "first" + MultilibCommon Multilib = "common" ) func InitAndroidModule(m AndroidModule, diff --git a/java/builder.go b/java/builder.go new file mode 100644 index 00000000..2f9d7018 --- /dev/null +++ b/java/builder.go @@ -0,0 +1,189 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// 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. + +package java + +// This file generates the final rules for compiling all Java. All properties related to +// compiling should have been translated into javaBuilderFlags or another argument to the Transform* +// functions. + +import ( + "path/filepath" + "strings" + + "android/soong/common" + + "github.com/google/blueprint" + "github.com/google/blueprint/bootstrap" +) + +var ( + pctx = blueprint.NewPackageContext("android/soong/java") + + // Compiling java is not conducive to proper dependency tracking. The path-matches-class-name + // requirement leads to unpredictable generated source file names, and a single .java file + // will get compiled into multiple .class files if it contains inner classes. To work around + // this, all java rules write into separate directories and then a post-processing step lists + // the files in the the directory into a list file that later rules depend on (and sometimes + // read from directly using @<listfile>) + cc = pctx.StaticRule("javac", + blueprint.RuleParams{ + Command: `$javacCmd -encoding UTF-8 $javacFlags $bootClasspath $classpath ` + + `-extdirs "" -d $outDir @$out.rsp || ( rm -rf $outDir; exit 41 ) && ` + + `find $outDir -name "*.class" > $out`, + Rspfile: "$out.rsp", + RspfileContent: "$in", + Description: "javac $outDir", + }, + "javacCmd", "javacFlags", "bootClasspath", "classpath", "outDir") + + jar = pctx.StaticRule("jar", + blueprint.RuleParams{ + Command: `$jarCmd -o $out $jarArgs`, + Description: "jar $out", + }, + "jarCmd", "jarArgs") + + dx = pctx.StaticRule("dx", + blueprint.RuleParams{ + Command: "$dxCmd --dex --output=$out $dxFlags $in", + Description: "dex $out", + }, + "outDir", "dxFlags") +) + +func init() { + pctx.StaticVariable("commonJdkFlags", "-source 1.7 -target 1.7 -Xmaxerrs 9999999") + pctx.StaticVariable("javacCmd", "javac -J-Xmx1024M $commonJdkFlags") + pctx.StaticVariable("jarCmd", filepath.Join(bootstrap.BinDir, "soong_jar")) + pctx.VariableFunc("dxCmd", func(c interface{}) (string, error) { + return c.(Config).HostBinTool("dx") + }) +} + +type javaBuilderFlags struct { + javacFlags string + dxFlags string + bootClasspath string + classpath string +} + +type jarSpec struct { + fileList, dir string +} + +func (j jarSpec) soongJarArgs() string { + return "-C " + j.dir + " -l " + j.fileList +} + +func TransformJavaToClasses(ctx common.AndroidModuleContext, srcFiles []string, + flags javaBuilderFlags, deps []string) jarSpec { + + classDir := filepath.Join(common.ModuleOutDir(ctx), "classes") + classFileList := filepath.Join(classDir, "classes.list") + + ctx.Build(pctx, blueprint.BuildParams{ + Rule: cc, + Outputs: []string{classFileList}, + Inputs: srcFiles, + Implicits: deps, + Args: map[string]string{ + "javacFlags": flags.javacFlags, + "bootClasspath": flags.bootClasspath, + "classpath": flags.classpath, + "outDir": classDir, + }, + }) + + return jarSpec{classFileList, classDir} +} + +func TransformClassesToJar(ctx common.AndroidModuleContext, classes []jarSpec, + manifest string) string { + + outputFile := filepath.Join(common.ModuleOutDir(ctx), "classes-full-debug.jar") + + deps := []string{} + jarArgs := []string{} + + for _, j := range classes { + deps = append(deps, j.fileList) + jarArgs = append(jarArgs, j.soongJarArgs()) + } + + if manifest != "" { + deps = append(deps, manifest) + jarArgs = append(jarArgs, "-m "+manifest) + } + + deps = append(deps, "$jarCmd") + + ctx.Build(pctx, blueprint.BuildParams{ + Rule: jar, + Outputs: []string{outputFile}, + Implicits: deps, + Args: map[string]string{ + "jarArgs": strings.Join(jarArgs, " "), + }, + }) + + return outputFile +} + +func TransformClassesJarToDex(ctx common.AndroidModuleContext, classesJar string, + flags javaBuilderFlags) string { + + outputFile := filepath.Join(common.ModuleOutDir(ctx), "classes.dex") + + ctx.Build(pctx, blueprint.BuildParams{ + Rule: dx, + Outputs: []string{outputFile}, + Inputs: []string{classesJar}, + Implicits: []string{"$dxCmd"}, + Args: map[string]string{ + "dxFlags": flags.dxFlags, + }, + }) + + return outputFile +} + +func TransformDexToJavaLib(ctx common.AndroidModuleContext, resources []jarSpec, + dexFile string) string { + + outputFile := filepath.Join(common.ModuleOutDir(ctx), "javalib.jar") + var deps []string + var jarArgs []string + + for _, j := range resources { + deps = append(deps, j.fileList) + jarArgs = append(jarArgs, j.soongJarArgs()) + } + + dexDir, _ := filepath.Split(dexFile) + jarArgs = append(jarArgs, "-C "+dexDir+" -f "+dexFile) + + deps = append(deps, "$jarCmd", dexFile) + + ctx.Build(pctx, blueprint.BuildParams{ + Rule: jar, + Outputs: []string{outputFile}, + Implicits: deps, + Args: map[string]string{ + "jarArgs": strings.Join(jarArgs, " "), + }, + }) + + return outputFile +} diff --git a/java/java.go b/java/java.go new file mode 100644 index 00000000..67bde045 --- /dev/null +++ b/java/java.go @@ -0,0 +1,403 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// 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. + +package java + +// This file contains the module types for compiling Java for Android, and converts the properties +// into the flags and filenames necessary to pass to the compiler. The final creation of the rules +// is handled in builder.go + +import ( + "fmt" + "path/filepath" + "strings" + + "github.com/google/blueprint" + "github.com/google/blueprint/pathtools" + + "android/soong/common" +) + +type Config interface { + SrcDir() string + PrebuiltOS() string + HostBinTool(string) (string, error) + Getenv(string) string +} + +// TODO: +// Autogenerated files: +// AIDL +// Proto +// Renderscript +// Post-jar passes: +// Proguard +// Emma +// Jarjar +// Dex +// Rmtypedefs +// Jack +// DroidDoc +// Findbugs + +// javaBase contains the properties and members used by all java module types, and implements +// the blueprint.Module interface. +type javaBase struct { + common.AndroidModuleBase + module JavaModuleType + + properties struct { + // srcs: list of source files used to compile the Java module. May be .java, .logtags, .proto, + // or .aidl files. + Srcs []string `android:"arch_variant,arch_subtract"` + + // resource_dirs: list of directories containing resources + Resource_dirs []string `android:"arch_variant"` + + // no_standard_libraries: don't build against the default libraries (core-libart, core-junit, + // ext, and framework for device targets) + No_standard_libraries bool + + // javacflags: list of module-specific flags that will be used for javac compiles + Javacflags []string `android:"arch_variant"` + + // dxflags: list of module-specific flags that will be used for dex compiles + Dxflags []string `android:"arch_variant"` + + // java_libs: list of of java libraries that will be in the classpath + Java_libs []string `android:"arch_variant"` + + // java_static_libs: list of java libraries that will be compiled into the resulting jar + Java_static_libs []string `android:"arch_variant"` + + // manifest: manifest file to be included in resulting jar + Manifest string + + // sdk_version: if not blank, set to the version of the sdk to compile against + Sdk_version string + + // Set for device java libraries, and for host versions of device java libraries + // built for testing + Dex bool `blueprint:"mutated"` + } + + // output file suitable for inserting into the classpath of another compile + classpathFile string + + // jarSpecs suitable for inserting classes from a static library into another jar + classJarSpecs []jarSpec + + // jarSpecs suitable for inserting resources from a static library into another jar + resourceJarSpecs []jarSpec + + // installed file for binary dependency + installFile string +} + +type JavaModuleType interface { + GenerateJavaBuildActions(ctx common.AndroidModuleContext) +} + +type JavaDependency interface { + ClasspathFile() string + ClassJarSpecs() []jarSpec + ResourceJarSpecs() []jarSpec +} + +func NewJavaBase(base *javaBase, module JavaModuleType, hod common.HostOrDeviceSupported, + props ...interface{}) (blueprint.Module, []interface{}) { + + base.module = module + + props = append(props, &base.properties) + + return common.InitAndroidArchModule(base, hod, common.MultilibCommon, props...) +} + +func (j *javaBase) BootClasspath(ctx common.AndroidBaseContext) string { + if ctx.Device() { + if j.properties.Sdk_version == "" { + return "core-libart" + } else if j.properties.Sdk_version == "current" { + // TODO: !TARGET_BUILD_APPS + return "android_stubs_current" + } else if j.properties.Sdk_version == "system_current" { + return "android_system_stubs_current" + } else { + return "sdk_v" + j.properties.Sdk_version + } + } else { + if j.properties.Dex { + return "core-libart" + } else { + return "" + } + } +} + +func (j *javaBase) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string { + var deps []string + + if !j.properties.No_standard_libraries { + bootClasspath := j.BootClasspath(ctx) + if bootClasspath != "" { + deps = append(deps, bootClasspath) + } + } + deps = append(deps, j.properties.Java_libs...) + deps = append(deps, j.properties.Java_static_libs...) + + return deps +} + +func (j *javaBase) collectDeps(ctx common.AndroidModuleContext) (classpath []string, + bootClasspath string, classJarSpecs, resourceJarSpecs []jarSpec) { + + ctx.VisitDirectDeps(func(module blueprint.Module) { + otherName := ctx.OtherModuleName(module) + if javaDep, ok := module.(JavaDependency); ok { + if inList(otherName, j.properties.Java_libs) { + classpath = append(classpath, javaDep.ClasspathFile()) + } else if inList(otherName, j.properties.Java_static_libs) { + classpath = append(classpath, javaDep.ClasspathFile()) + classJarSpecs = append(classJarSpecs, javaDep.ClassJarSpecs()...) + resourceJarSpecs = append(resourceJarSpecs, javaDep.ResourceJarSpecs()...) + } else if otherName == j.BootClasspath(ctx) { + bootClasspath = javaDep.ClasspathFile() + } else { + panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName())) + } + } else { + ctx.ModuleErrorf("unknown dependency module type for %q", otherName) + } + }) + + return classpath, bootClasspath, classJarSpecs, resourceJarSpecs +} + +func (j *javaBase) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) { + j.module.GenerateJavaBuildActions(ctx) +} + +func (j *javaBase) GenerateJavaBuildActions(ctx common.AndroidModuleContext) { + flags := javaBuilderFlags{ + javacFlags: strings.Join(j.properties.Javacflags, " "), + } + + var javacDeps []string + + srcFiles := j.properties.Srcs + srcFiles = pathtools.PrefixPaths(srcFiles, common.ModuleSrcDir(ctx)) + srcFiles = common.ExpandGlobs(ctx, srcFiles) + + classpath, bootClasspath, classJarSpecs, resourceJarSpecs := j.collectDeps(ctx) + + if bootClasspath != "" { + flags.bootClasspath = "-bootclasspath " + bootClasspath + javacDeps = append(javacDeps, bootClasspath) + } + + if len(classpath) > 0 { + flags.classpath = "-classpath " + strings.Join(classpath, ":") + javacDeps = append(javacDeps, classpath...) + } + + // Compile java sources into .class files + classes := TransformJavaToClasses(ctx, srcFiles, flags, javacDeps) + if ctx.Failed() { + return + } + + resourceJarSpecs = append(ResourceDirsToJarSpecs(ctx, j.properties.Resource_dirs), resourceJarSpecs...) + classJarSpecs = append([]jarSpec{classes}, classJarSpecs...) + + manifest := j.properties.Manifest + if manifest != "" { + manifest = filepath.Join(common.ModuleSrcDir(ctx), manifest) + } + + allJarSpecs := append([]jarSpec(nil), classJarSpecs...) + allJarSpecs = append(allJarSpecs, resourceJarSpecs...) + + // Combine classes + resources into classes-full-debug.jar + outputFile := TransformClassesToJar(ctx, allJarSpecs, manifest) + if ctx.Failed() { + return + } + j.classJarSpecs = classJarSpecs + j.resourceJarSpecs = resourceJarSpecs + j.classpathFile = outputFile + + if j.properties.Dex { + dxFlags := j.properties.Dxflags + if false /* emma enabled */ { + // If you instrument class files that have local variable debug information in + // them emma does not correctly maintain the local variable table. + // This will cause an error when you try to convert the class files for Android. + // The workaround here is to build different dex file here based on emma switch + // then later copy into classes.dex. When emma is on, dx is run with --no-locals + // option to remove local variable information + dxFlags = append(dxFlags, "--no-locals") + } + + if ctx.Config().(Config).Getenv("NO_OPTIMIZE_DX") != "" { + dxFlags = append(dxFlags, "--no-optimize") + } + + if ctx.Config().(Config).Getenv("GENERATE_DEX_DEBUG") != "" { + dxFlags = append(dxFlags, + "--debug", + "--verbose", + "--dump-to="+filepath.Join(common.ModuleOutDir(ctx), "classes.lst"), + "--dump-width=1000") + } + + flags.dxFlags = strings.Join(dxFlags, " ") + + // Compile classes.jar into classes.dex + dexFile := TransformClassesJarToDex(ctx, outputFile, flags) + if ctx.Failed() { + return + } + + // Combine classes.dex + resources into javalib.jar + outputFile = TransformDexToJavaLib(ctx, resourceJarSpecs, dexFile) + } + + j.installFile = ctx.InstallFileName("framework", ctx.ModuleName()+".jar", outputFile) +} + +var _ JavaDependency = (*JavaLibrary)(nil) + +func (j *javaBase) ClasspathFile() string { + return j.classpathFile +} + +func (j *javaBase) ClassJarSpecs() []jarSpec { + return j.classJarSpecs +} + +func (j *javaBase) ResourceJarSpecs() []jarSpec { + return j.resourceJarSpecs +} + +// +// Java libraries (.jar file) +// + +type JavaLibrary struct { + javaBase +} + +func JavaLibraryFactory() (blueprint.Module, []interface{}) { + module := &JavaLibrary{} + + module.properties.Dex = true + + return NewJavaBase(&module.javaBase, module, common.HostAndDeviceSupported) +} + +func JavaLibraryHostFactory() (blueprint.Module, []interface{}) { + module := &JavaLibrary{} + + return NewJavaBase(&module.javaBase, module, common.HostSupported) +} + +// +// Java Binaries (.jar file plus wrapper script) +// + +type JavaBinary struct { + JavaLibrary + + binaryProperties struct { + // wrapper: installable script to execute the resulting jar + Wrapper string + } +} + +func (j *JavaBinary) GenerateJavaBuildActions(ctx common.AndroidModuleContext) { + j.JavaLibrary.GenerateJavaBuildActions(ctx) + + // Depend on the installed jar (j.installFile) so that the wrapper doesn't get executed by + // another build rule before the jar has been installed. + ctx.InstallFile("bin", filepath.Join(common.ModuleSrcDir(ctx), j.binaryProperties.Wrapper), + j.installFile) +} + +func JavaBinaryFactory() (blueprint.Module, []interface{}) { + module := &JavaBinary{} + + module.properties.Dex = true + + return NewJavaBase(&module.javaBase, module, common.HostAndDeviceSupported, &module.binaryProperties) +} + +func JavaBinaryHostFactory() (blueprint.Module, []interface{}) { + module := &JavaBinary{} + + return NewJavaBase(&module.javaBase, module, common.HostSupported, &module.binaryProperties) +} + +// +// Java prebuilts +// + +type JavaPrebuilt struct { + common.AndroidModuleBase + + properties struct { + Srcs []string + } + + classpathFile string +} + +func (j *JavaPrebuilt) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) { + if len(j.properties.Srcs) != 1 { + ctx.ModuleErrorf("expected exactly one jar in srcs") + return + } + j.classpathFile = filepath.Join(common.ModuleSrcDir(ctx), j.properties.Srcs[0]) +} + +var _ JavaDependency = (*JavaPrebuilt)(nil) + +func (j *JavaPrebuilt) ClasspathFile() string { + return j.classpathFile +} + +func (j *JavaPrebuilt) ClassJarSpecs() []jarSpec { + return nil +} + +func (j *JavaPrebuilt) ResourceJarSpecs() []jarSpec { + return nil +} + +func JavaPrebuiltFactory() (blueprint.Module, []interface{}) { + module := &JavaPrebuilt{} + + return common.InitAndroidArchModule(module, common.HostAndDeviceSupported, + common.MultilibCommon, &module.properties) +} + +func inList(s string, l []string) bool { + for _, e := range l { + if e == s { + return true + } + } + return false +} diff --git a/java/resources.go b/java/resources.go new file mode 100644 index 00000000..2fbf54bf --- /dev/null +++ b/java/resources.go @@ -0,0 +1,45 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// 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. + +package java + +import ( + "path/filepath" + + "android/soong/common" +) + +var resourceExcludes = []string{ + "*.java", + "package.html", + "overview.html", + ".*.swp", + ".DS_Store", + "*~", +} + +func ResourceDirsToJarSpecs(ctx common.AndroidModuleContext, dirs []string) []jarSpec { + jarSpecs := make([]jarSpec, len(dirs)) + + for i, dir := range dirs { + fileListFile := filepath.Join(common.ModuleOutDir(ctx), "res", dir, "resources.list") + depFile := fileListFile + ".d" + dir := filepath.Join(common.ModuleSrcDir(ctx), dir) + glob := filepath.Join(dir, "**/*") + common.GlobRule(ctx, glob, resourceExcludes, fileListFile, depFile) + jarSpecs[i] = jarSpec{fileListFile, dir} + } + + return jarSpecs +} @@ -3,8 +3,11 @@ subdirs = [ "build/blueprint", "build/soong", "bionic", + "dalvik", "external/*", + "libcore", "libnativehelper", "prebuilts/ndk", + "prebuilts/sdk", "system/core/*", ] |