Merge "Build with OpenJDK 9 -target 1.8 by default (attempt 4)."
diff --git a/Android.bp b/Android.bp
index ba71789..91e73aa 100644
--- a/Android.bp
+++ b/Android.bp
@@ -219,6 +219,7 @@
"java/app_builder.go",
"java/app.go",
"java/builder.go",
+ "java/dex.go",
"java/gen.go",
"java/genrule.go",
"java/jacoco.go",
diff --git a/android/module.go b/android/module.go
index cb068ab..0fb9479 100644
--- a/android/module.go
+++ b/android/module.go
@@ -139,6 +139,7 @@
VisitDirectDepsBlueprint(visit func(blueprint.Module))
VisitDirectDeps(visit func(Module))
+ VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
VisitDepsDepthFirst(visit func(Module))
VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
@@ -831,6 +832,16 @@
})
}
+func (a *androidModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
+ a.ModuleContext.VisitDirectDeps(func(module blueprint.Module) {
+ if aModule := a.validateAndroidModule(module); aModule != nil {
+ if a.ModuleContext.OtherModuleDependencyTag(aModule) == tag {
+ visit(aModule)
+ }
+ }
+ })
+}
+
func (a *androidModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
a.ModuleContext.VisitDirectDepsIf(
// pred
diff --git a/android/mutator.go b/android/mutator.go
index 8de57e1..2f13f6c 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -127,6 +127,7 @@
GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
VisitDirectDeps(visit func(Module))
+ VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
VisitDepsDepthFirst(visit func(Module))
VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
@@ -230,6 +231,16 @@
})
}
+func (a *androidTopDownMutatorContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
+ a.TopDownMutatorContext.VisitDirectDeps(func(module blueprint.Module) {
+ if aModule, _ := module.(Module); aModule != nil {
+ if a.TopDownMutatorContext.OtherModuleDependencyTag(aModule) == tag {
+ visit(aModule)
+ }
+ }
+ })
+}
+
func (a *androidTopDownMutatorContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
a.TopDownMutatorContext.VisitDirectDepsIf(
// pred
diff --git a/android/prebuilt.go b/android/prebuilt.go
index d3f9704..9356aab 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -109,13 +109,11 @@
p.properties.UsePrebuilt = p.usePrebuilt(ctx, nil)
}
} else if s, ok := ctx.Module().(Module); ok {
- ctx.VisitDirectDeps(func(m Module) {
- if ctx.OtherModuleDependencyTag(m) == prebuiltDepTag {
- p := m.(PrebuiltInterface).Prebuilt()
- if p.usePrebuilt(ctx, s) {
- p.properties.UsePrebuilt = true
- s.SkipInstall()
- }
+ ctx.VisitDirectDepsWithTag(prebuiltDepTag, func(m Module) {
+ p := m.(PrebuiltInterface).Prebuilt()
+ if p.usePrebuilt(ctx, s) {
+ p.properties.UsePrebuilt = true
+ s.SkipInstall()
}
})
}
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index 82b5eb9..3e134b6 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -53,6 +53,7 @@
"LOCAL_SANITIZE_DIAG": sanitize("diag."),
"LOCAL_CFLAGS": cflags,
"LOCAL_UNINSTALLABLE_MODULE": invert("installable"),
+ "LOCAL_PROGUARD_ENABLED": proguardEnabled,
// composite functions
"LOCAL_MODULE_TAGS": includeVariableIf(bpVariable{"tags", bpparser.ListType}, not(valueDumpEquals("optional"))),
@@ -136,6 +137,9 @@
"LOCAL_ANNOTATION_PROCESSORS": "annotation_processors",
"LOCAL_ANNOTATION_PROCESSOR_CLASSES": "annotation_processor_classes",
+
+ "LOCAL_PROGUARD_FLAGS": "optimize.proguard_flags",
+ "LOCAL_PROGUARD_FLAG_FILES": "optimize.proguard_flag_files",
})
addStandardProperties(bpparser.BoolType,
map[string]string{
@@ -517,6 +521,60 @@
return includeVariableNow(bpVariable{"cflags", bpparser.ListType}, ctx)
}
+func proguardEnabled(ctx variableAssignmentContext) error {
+ val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType)
+ if err != nil {
+ return err
+ }
+
+ list, ok := val.(*bpparser.List)
+ if !ok {
+ return fmt.Errorf("unsupported proguard expression")
+ }
+
+ set := func(prop string, value bool) {
+ bpValue := &bpparser.Bool{
+ Value: value,
+ }
+ setVariable(ctx.file, false, ctx.prefix, prop, bpValue, true)
+ }
+
+ enable := false
+
+ for _, v := range list.Values {
+ s, ok := v.(*bpparser.String)
+ if !ok {
+ return fmt.Errorf("unsupported proguard expression")
+ }
+
+ switch s.Value {
+ case "disabled":
+ set("optimize.enabled", false)
+ case "obfuscation":
+ enable = true
+ set("optimize.obfuscate", true)
+ case "optimization":
+ enable = true
+ set("optimize.optimize", true)
+ case "full":
+ enable = true
+ case "custom":
+ set("optimize.no_aapt_flags", true)
+ enable = true
+ default:
+ return fmt.Errorf("unsupported proguard value %q", s)
+ }
+ }
+
+ if enable {
+ // This is only necessary for libraries which default to false, but we can't
+ // tell the difference between a library and an app here.
+ set("optimize.enabled", true)
+ }
+
+ return nil
+}
+
func invert(name string) func(ctx variableAssignmentContext) error {
return func(ctx variableAssignmentContext) error {
val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.BoolType)
diff --git a/androidmk/cmd/androidmk/androidmk_test.go b/androidmk/cmd/androidmk/androidmk_test.go
index 22a52d4..c85aaaa 100644
--- a/androidmk/cmd/androidmk/androidmk_test.go
+++ b/androidmk/cmd/androidmk/androidmk_test.go
@@ -438,6 +438,42 @@
`,
expected: ``,
},
+ {
+ desc: "proguard options for java library",
+ in: `
+ include $(CLEAR_VARS)
+ # Empty
+ LOCAL_PROGUARD_ENABLED :=
+ # Disabled
+ LOCAL_PROGUARD_ENABLED := disabled
+ # Full
+ LOCAL_PROGUARD_ENABLED := full
+ # Obfuscation and optimization
+ LOCAL_PROGUARD_ENABLED := obfuscation optimization
+ # Custom
+ LOCAL_PROGUARD_ENABLED := custom
+ include $(BUILD_JAVA_LIBRARY)
+ `,
+ expected: `
+ java_library {
+ // Empty
+
+ // Disabled
+ optimize: {
+ enabled: false,
+ // Full
+ enabled: true,
+ // Obfuscation and optimization
+ obfuscate: true,
+ optimize: true,
+ enabled: true,
+ // Custom
+ no_aapt_flags: true,
+ enabled: true,
+ },
+ }
+ `,
+ },
}
func reformatBlueprint(input string) string {
diff --git a/cc/androidmk.go b/cc/androidmk.go
index efd4ee7..e78c419 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -355,7 +355,7 @@
func (c *vndkPrebuiltLibraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
ret.Class = "SHARED_LIBRARIES"
- ret.SubName = vndkSuffix + c.version()
+ ret.SubName = c.NameSuffix()
ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
c.libraryDecorator.androidMkWriteExportedFlags(w)
diff --git a/cc/coverage.go b/cc/coverage.go
index d2eede2..391b118 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -59,11 +59,7 @@
// For static libraries, the only thing that changes our object files
// are included whole static libraries, so check to see if any of
// those have coverage enabled.
- ctx.VisitDirectDeps(func(m android.Module) {
- if ctx.OtherModuleDependencyTag(m) != wholeStaticDepTag {
- return
- }
-
+ ctx.VisitDirectDepsWithTag(wholeStaticDepTag, func(m android.Module) {
if cc, ok := m.(*Module); ok && cc.coverage != nil {
if cc.coverage.linkCoverage {
cov.linkCoverage = true
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index 9ccab03..b4fcb57 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -47,8 +47,11 @@
// }
//
type vndkPrebuiltProperties struct {
- // VNDK snapshot version that is formated as {SDK_ver}.{Major}.{Minor}.
- Version string
+ // VNDK snapshot version.
+ Version *string
+
+ // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64_ab')
+ Target_arch *string
// Prebuilt files for each arch.
Srcs []string `android:"arch_variant"`
@@ -60,15 +63,26 @@
}
func (p *vndkPrebuiltLibraryDecorator) Name(name string) string {
- return name + vndkSuffix + p.version()
+ return name + p.NameSuffix()
+}
+
+func (p *vndkPrebuiltLibraryDecorator) NameSuffix() string {
+ if p.arch() != "" {
+ return vndkSuffix + p.version() + "." + p.arch()
+ }
+ return vndkSuffix + p.version()
}
func (p *vndkPrebuiltLibraryDecorator) version() string {
- return p.properties.Version
+ return String(p.properties.Version)
+}
+
+func (p *vndkPrebuiltLibraryDecorator) arch() string {
+ return String(p.properties.Target_arch)
}
func (p *vndkPrebuiltLibraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
- p.libraryDecorator.libName = strings.TrimSuffix(ctx.ModuleName(), vndkSuffix+p.version())
+ p.libraryDecorator.libName = strings.TrimSuffix(ctx.ModuleName(), p.NameSuffix())
return p.libraryDecorator.linkerFlags(ctx, flags)
}
diff --git a/java/androidmk.go b/java/androidmk.go
index 24fe43a..64ef505 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -165,6 +165,9 @@
if app.jacocoReportClassesFile != nil {
fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", app.jacocoReportClassesFile.String())
}
+ if app.proguardDictionary != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_PROGUARD_DICT :=", app.proguardDictionary.String())
+ }
if app.Name() == "framework-res" {
fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(TARGET_OUT_JAVA_LIBRARIES)")
diff --git a/java/app.go b/java/app.go
index df53375..234dcb7 100644
--- a/java/app.go
+++ b/java/app.go
@@ -125,14 +125,13 @@
// apps manifests are handled by aapt, don't let Module see them
a.properties.Manifest = nil
- //if !ctx.ContainsProperty("proguard.enabled") {
- // a.properties.Proguard.Enabled = true
- //}
-
if String(a.appProperties.Instrumentation_for) == "" {
a.properties.Instrument = true
}
+ a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles,
+ proguardOptionsFile)
+
if ctx.ModuleName() != "framework-res" {
a.Module.compile(ctx, a.aaptSrcJar)
}
@@ -324,6 +323,9 @@
func AndroidAppFactory() android.Module {
module := &AndroidApp{}
+ module.Module.deviceProperties.Optimize.Enabled = proptools.BoolPtr(true)
+ module.Module.deviceProperties.Optimize.Shrink = proptools.BoolPtr(true)
+
module.AddProperties(
&module.Module.properties,
&module.Module.deviceProperties,
diff --git a/java/builder.go b/java/builder.go
index 56c7b33..bf826e1 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -135,46 +135,6 @@
},
"jarArgs")
- desugar = pctx.AndroidStaticRule("desugar",
- blueprint.RuleParams{
- Command: `rm -rf $dumpDir && mkdir -p $dumpDir && ` +
- `${config.JavaCmd} ` +
- `-Djdk.internal.lambda.dumpProxyClasses=$$(cd $dumpDir && pwd) ` +
- `$javaFlags ` +
- `-jar ${config.DesugarJar} $classpathFlags $desugarFlags ` +
- `-i $in -o $out`,
- CommandDeps: []string{"${config.DesugarJar}", "${config.JavaCmd}"},
- },
- "javaFlags", "classpathFlags", "desugarFlags", "dumpDir")
-
- dx = pctx.AndroidStaticRule("dx",
- blueprint.RuleParams{
- Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
- `${config.DxCmd} --dex --output=$outDir $dxFlags $in && ` +
- `${config.SoongZipCmd} -o $outDir/classes.dex.jar -C $outDir -D $outDir && ` +
- `${config.MergeZipsCmd} -D -stripFile "*.class" $out $outDir/classes.dex.jar $in`,
- CommandDeps: []string{
- "${config.DxCmd}",
- "${config.SoongZipCmd}",
- "${config.MergeZipsCmd}",
- },
- },
- "outDir", "dxFlags")
-
- d8 = pctx.AndroidStaticRule("d8",
- blueprint.RuleParams{
- Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
- `${config.D8Cmd} --output $outDir $dxFlags $in && ` +
- `${config.SoongZipCmd} -o $outDir/classes.dex.jar -C $outDir -D $outDir && ` +
- `${config.MergeZipsCmd} -D -stripFile "*.class" $out $outDir/classes.dex.jar $in`,
- CommandDeps: []string{
- "${config.DxCmd}",
- "${config.SoongZipCmd}",
- "${config.MergeZipsCmd}",
- },
- },
- "outDir", "dxFlags")
-
jarjar = pctx.AndroidStaticRule("jarjar",
blueprint.RuleParams{
Command: "${config.JavaCmd} -jar ${config.JarjarCmd} process $rulesFile $in $out",
@@ -189,11 +149,9 @@
type javaBuilderFlags struct {
javacFlags string
- dxFlags string
bootClasspath classpath
classpath classpath
systemModules classpath
- desugarFlags string
aidlFlags string
javaVersion string
@@ -403,64 +361,6 @@
})
}
-func TransformDesugar(ctx android.ModuleContext, outputFile android.WritablePath,
- classesJar android.Path, flags javaBuilderFlags) {
-
- dumpDir := android.PathForModuleOut(ctx, "desugar", "classes")
-
- javaFlags := ""
- if ctx.Config().UseOpenJDK9() {
- javaFlags = "--add-opens java.base/java.lang.invoke=ALL-UNNAMED"
- }
-
- var desugarFlags []string
- desugarFlags = append(desugarFlags, flags.bootClasspath.FormDesugarClasspath("--bootclasspath_entry")...)
- desugarFlags = append(desugarFlags, flags.classpath.FormDesugarClasspath("--classpath_entry")...)
-
- var deps android.Paths
- deps = append(deps, flags.bootClasspath...)
- deps = append(deps, flags.classpath...)
-
- ctx.Build(pctx, android.BuildParams{
- Rule: desugar,
- Description: "desugar",
- Output: outputFile,
- Input: classesJar,
- Implicits: deps,
- Args: map[string]string{
- "dumpDir": dumpDir.String(),
- "javaFlags": javaFlags,
- "classpathFlags": strings.Join(desugarFlags, " "),
- "desugarFlags": flags.desugarFlags,
- },
- })
-}
-
-// Converts a classes.jar file to classes*.dex, then combines the dex files with any resources
-// in the classes.jar file into a dex jar.
-func TransformClassesJarToDexJar(ctx android.ModuleContext, outputFile android.WritablePath,
- classesJar android.Path, flags javaBuilderFlags) {
-
- outDir := android.PathForModuleOut(ctx, "dex")
-
- rule := dx
- desc := "dx"
- if ctx.Config().UseD8Desugar() {
- rule = d8
- desc = "d8"
- }
- ctx.Build(pctx, android.BuildParams{
- Rule: rule,
- Description: desc,
- Output: outputFile,
- Input: classesJar,
- Args: map[string]string{
- "dxFlags": flags.dxFlags,
- "outDir": outDir.String(),
- },
- })
-}
-
func TransformJarJar(ctx android.ModuleContext, outputFile android.WritablePath,
classesJar android.Path, rulesFile android.Path) {
ctx.Build(pctx, android.BuildParams{
diff --git a/java/config/config.go b/java/config/config.go
index c43f9a3..75176c9 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -106,13 +106,9 @@
return path.String(), nil
}
})
- pctx.VariableFunc("D8Cmd", func(config android.Config) (string, error) {
- path, err := pctx.HostBinToolPath(config, "d8")
- if err != nil {
- return "", err
- }
- return path.String(), nil
- })
+ pctx.HostBinToolVariable("D8Cmd", "d8")
+ pctx.HostBinToolVariable("R8Cmd", "r8-compat-proguard")
+
pctx.VariableFunc("TurbineJar", func(config android.Config) (string, error) {
turbine := "turbine.jar"
if config.UnbundledBuild() {
diff --git a/java/config/makevars.go b/java/config/makevars.go
index c382cc1..7e125d5 100644
--- a/java/config/makevars.go
+++ b/java/config/makevars.go
@@ -55,6 +55,7 @@
ctx.Strict("DX_COMMAND", "${DxCmd} -JXms16M -JXmx2048M")
ctx.Strict("USE_D8_DESUGAR", "false")
}
+ ctx.Strict("R8_COMPAT_PROGUARD", "${R8Cmd}")
ctx.Strict("TURBINE", "${TurbineJar}")
diff --git a/java/dex.go b/java/dex.go
new file mode 100644
index 0000000..2beb2ac
--- /dev/null
+++ b/java/dex.go
@@ -0,0 +1,272 @@
+// Copyright 2017 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 (
+ "strings"
+
+ "github.com/google/blueprint"
+
+ "android/soong/android"
+)
+
+var desugar = pctx.AndroidStaticRule("desugar",
+ blueprint.RuleParams{
+ Command: `rm -rf $dumpDir && mkdir -p $dumpDir && ` +
+ `${config.JavaCmd} ` +
+ `-Djdk.internal.lambda.dumpProxyClasses=$$(cd $dumpDir && pwd) ` +
+ `$javaFlags ` +
+ `-jar ${config.DesugarJar} $classpathFlags $desugarFlags ` +
+ `-i $in -o $out`,
+ CommandDeps: []string{"${config.DesugarJar}", "${config.JavaCmd}"},
+ },
+ "javaFlags", "classpathFlags", "desugarFlags", "dumpDir")
+
+func (j *Module) desugar(ctx android.ModuleContext, flags javaBuilderFlags,
+ classesJar android.Path, jarName string) android.Path {
+
+ desugarFlags := []string{
+ "--min_sdk_version " + j.minSdkVersionNumber(ctx),
+ "--desugar_try_with_resources_if_needed=false",
+ "--allow_empty_bootclasspath",
+ }
+
+ if inList("--core-library", j.deviceProperties.Dxflags) {
+ desugarFlags = append(desugarFlags, "--core_library")
+ }
+
+ desugarJar := android.PathForModuleOut(ctx, "desugar", jarName)
+ dumpDir := android.PathForModuleOut(ctx, "desugar", "classes")
+
+ javaFlags := ""
+ if ctx.Config().UseOpenJDK9() {
+ javaFlags = "--add-opens java.base/java.lang.invoke=ALL-UNNAMED"
+ }
+
+ var classpathFlags []string
+ classpathFlags = append(classpathFlags, flags.bootClasspath.FormDesugarClasspath("--bootclasspath_entry")...)
+ classpathFlags = append(classpathFlags, flags.classpath.FormDesugarClasspath("--classpath_entry")...)
+
+ var deps android.Paths
+ deps = append(deps, flags.bootClasspath...)
+ deps = append(deps, flags.classpath...)
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: desugar,
+ Description: "desugar",
+ Output: desugarJar,
+ Input: classesJar,
+ Implicits: deps,
+ Args: map[string]string{
+ "dumpDir": dumpDir.String(),
+ "javaFlags": javaFlags,
+ "classpathFlags": strings.Join(classpathFlags, " "),
+ "desugarFlags": strings.Join(desugarFlags, " "),
+ },
+ })
+
+ return desugarJar
+}
+
+var dx = pctx.AndroidStaticRule("dx",
+ blueprint.RuleParams{
+ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
+ `${config.DxCmd} --dex --output=$outDir $dxFlags $in && ` +
+ `${config.SoongZipCmd} -o $outDir/classes.dex.jar -C $outDir -D $outDir && ` +
+ `${config.MergeZipsCmd} -D -stripFile "*.class" $out $outDir/classes.dex.jar $in`,
+ CommandDeps: []string{
+ "${config.DxCmd}",
+ "${config.SoongZipCmd}",
+ "${config.MergeZipsCmd}",
+ },
+ },
+ "outDir", "dxFlags")
+
+var d8 = pctx.AndroidStaticRule("d8",
+ blueprint.RuleParams{
+ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
+ `${config.D8Cmd} --output $outDir $dxFlags $in && ` +
+ `${config.SoongZipCmd} -o $outDir/classes.dex.jar -C $outDir -D $outDir && ` +
+ `${config.MergeZipsCmd} -D -stripFile "*.class" $out $outDir/classes.dex.jar $in`,
+ CommandDeps: []string{
+ "${config.D8Cmd}",
+ "${config.SoongZipCmd}",
+ "${config.MergeZipsCmd}",
+ },
+ },
+ "outDir", "dxFlags")
+
+var r8 = pctx.AndroidStaticRule("r8",
+ blueprint.RuleParams{
+ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
+ `${config.R8Cmd} -injars $in --output $outDir ` +
+ `--force-proguard-compatibility ` +
+ `-printmapping $outDict ` +
+ `$dxFlags $r8Flags && ` +
+ `${config.SoongZipCmd} -o $outDir/classes.dex.jar -C $outDir -D $outDir && ` +
+ `${config.MergeZipsCmd} -D -stripFile "*.class" $out $outDir/classes.dex.jar $in`,
+ CommandDeps: []string{
+ "${config.R8Cmd}",
+ "${config.SoongZipCmd}",
+ "${config.MergeZipsCmd}",
+ },
+ },
+ "outDir", "outDict", "dxFlags", "r8Flags")
+
+func (j *Module) dxFlags(ctx android.ModuleContext, fullD8 bool) []string {
+ flags := j.deviceProperties.Dxflags
+ if fullD8 {
+ // Translate all the DX flags to D8 ones until all the build files have been migrated
+ // to D8 flags. See: b/69377755
+ flags = android.RemoveListFromList(flags,
+ []string{"--core-library", "--dex", "--multi-dex"})
+ }
+
+ if ctx.Config().Getenv("NO_OPTIMIZE_DX") != "" {
+ if fullD8 {
+ flags = append(flags, "--debug")
+ } else {
+ flags = append(flags, "--no-optimize")
+ }
+ }
+
+ if ctx.Config().Getenv("GENERATE_DEX_DEBUG") != "" {
+ flags = append(flags,
+ "--debug",
+ "--verbose")
+ if !fullD8 {
+ flags = append(flags,
+ "--dump-to="+android.PathForModuleOut(ctx, "classes.lst").String(),
+ "--dump-width=1000")
+ }
+ }
+
+ if fullD8 {
+ flags = append(flags, "--min-api "+j.minSdkVersionNumber(ctx))
+ } else {
+ flags = append(flags, "--min-sdk-version="+j.minSdkVersionNumber(ctx))
+ }
+ return flags
+}
+
+func (j *Module) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Flags []string, r8Deps android.Paths) {
+ opt := j.deviceProperties.Optimize
+
+ // When an app contains references to APIs that are not in the SDK specified by
+ // its LOCAL_SDK_VERSION for example added by support library or by runtime
+ // classes added by desugar, we artifically raise the "SDK version" "linked" by
+ // ProGuard, to
+ // - suppress ProGuard warnings of referencing symbols unknown to the lower SDK version.
+ // - prevent ProGuard stripping subclass in the support library that extends class added in the higher SDK version.
+ // See b/20667396
+ var proguardRaiseDeps classpath
+ ctx.VisitDirectDepsWithTag(proguardRaiseTag, func(dep android.Module) {
+ proguardRaiseDeps = append(proguardRaiseDeps, dep.(Dependency).HeaderJars()...)
+ })
+
+ r8Flags = append(r8Flags, proguardRaiseDeps.FormJavaClassPath("-libraryjars"))
+ r8Flags = append(r8Flags, flags.bootClasspath.FormJavaClassPath("-libraryjars"))
+ r8Flags = append(r8Flags, flags.classpath.FormJavaClassPath("-libraryjars"))
+ r8Flags = append(r8Flags, "-forceprocessing")
+
+ flagFiles := android.Paths{
+ android.PathForSource(ctx, "build/make/core/proguard.flags"),
+ }
+
+ flagFiles = append(flagFiles, j.extraProguardFlagFiles...)
+ // TODO(ccross): static android library proguard files
+
+ r8Flags = append(r8Flags, android.JoinWithPrefix(flagFiles.Strings(), "-include "))
+ r8Deps = append(r8Deps, flagFiles...)
+
+ // TODO(b/70942988): This is included from build/make/core/proguard.flags
+ r8Deps = append(r8Deps, android.PathForSource(ctx,
+ "build/make/core/proguard_basic_keeps.flags"))
+
+ r8Flags = append(r8Flags, j.deviceProperties.Optimize.Proguard_flags...)
+
+ // TODO(ccross): Don't shrink app instrumentation tests by default.
+ if !Bool(opt.Shrink) {
+ r8Flags = append(r8Flags, "-dontshrink")
+ }
+
+ if !Bool(opt.Optimize) {
+ r8Flags = append(r8Flags, "-dontoptimize")
+ }
+
+ // TODO(ccross): error if obufscation + app instrumentation test.
+ if !Bool(opt.Obfuscate) {
+ r8Flags = append(r8Flags, "-dontobfuscate")
+ }
+
+ return r8Flags, r8Deps
+}
+
+func (j *Module) compileDex(ctx android.ModuleContext, flags javaBuilderFlags,
+ classesJar android.Path, jarName string) android.Path {
+
+ useR8 := Bool(j.deviceProperties.Optimize.Enabled)
+ fullD8 := useR8 || ctx.Config().UseD8Desugar()
+
+ if !fullD8 {
+ classesJar = j.desugar(ctx, flags, classesJar, jarName)
+ }
+
+ dxFlags := j.dxFlags(ctx, fullD8)
+
+ // Compile classes.jar into classes.dex and then javalib.jar
+ javalibJar := android.PathForModuleOut(ctx, "dex", jarName)
+ outDir := android.PathForModuleOut(ctx, "dex")
+
+ if useR8 {
+ // TODO(ccross): if this is an instrumentation test of an obfuscated app, use the
+ // dictionary of the app and move the app from libraryjars to injars.
+ j.proguardDictionary = android.PathForModuleOut(ctx, "proguard_dictionary")
+ r8Flags, r8Deps := j.r8Flags(ctx, flags)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: r8,
+ Description: "r8",
+ Output: javalibJar,
+ Input: classesJar,
+ Implicits: r8Deps,
+ Args: map[string]string{
+ "dxFlags": strings.Join(dxFlags, " "),
+ "r8Flags": strings.Join(r8Flags, " "),
+ "outDict": j.proguardDictionary.String(),
+ "outDir": outDir.String(),
+ },
+ })
+ } else {
+ rule := dx
+ desc := "dx"
+ if fullD8 {
+ rule = d8
+ desc = "d8"
+ }
+ ctx.Build(pctx, android.BuildParams{
+ Rule: rule,
+ Description: desc,
+ Output: javalibJar,
+ Input: classesJar,
+ Args: map[string]string{
+ "dxFlags": strings.Join(dxFlags, " "),
+ "outDir": outDir.String(),
+ },
+ })
+ }
+
+ j.dexJarFile = javalibJar
+ return javalibJar
+}
diff --git a/java/jacoco.go b/java/jacoco.go
index 59f2fd3..8f1ceb2 100644
--- a/java/jacoco.go
+++ b/java/jacoco.go
@@ -18,6 +18,7 @@
import (
"fmt"
+ "path/filepath"
"strings"
"github.com/google/blueprint"
@@ -27,10 +28,12 @@
var (
jacoco = pctx.AndroidStaticRule("jacoco", blueprint.RuleParams{
- Command: `${config.Zip2ZipCmd} -i $in -o $strippedJar $stripSpec && ` +
- `${config.JavaCmd} -jar ${config.JacocoCLIJar} instrument -quiet -dest $instrumentedJar $strippedJar && ` +
- `${config.Ziptime} $instrumentedJar && ` +
- `${config.MergeZipsCmd} --ignore-duplicates -j $out $instrumentedJar $in`,
+ Command: `rm -rf $tmpDir && mkdir -p $tmpDir && ` +
+ `${config.Zip2ZipCmd} -i $in -o $strippedJar $stripSpec && ` +
+ `${config.JavaCmd} -jar ${config.JacocoCLIJar} ` +
+ ` instrument --quiet --dest $tmpDir $strippedJar && ` +
+ `${config.Ziptime} $tmpJar && ` +
+ `${config.MergeZipsCmd} --ignore-duplicates -j $out $tmpJar $in`,
CommandDeps: []string{
"${config.Zip2ZipCmd}",
"${config.JavaCmd}",
@@ -39,23 +42,30 @@
"${config.MergeZipsCmd}",
},
},
- "strippedJar", "stripSpec", "instrumentedJar")
+ "strippedJar", "stripSpec", "tmpDir", "tmpJar")
)
-func jacocoInstrumentJar(ctx android.ModuleContext, outputJar, strippedJar android.WritablePath,
+// Instruments a jar using the Jacoco command line interface. Uses stripSpec to extract a subset
+// of the classes in inputJar into strippedJar, instruments strippedJar into tmpJar, and then
+// combines the classes in tmpJar with inputJar (preferring the instrumented classes in tmpJar)
+// to produce instrumentedJar.
+func jacocoInstrumentJar(ctx android.ModuleContext, instrumentedJar, strippedJar android.WritablePath,
inputJar android.Path, stripSpec string) {
- instrumentedJar := android.PathForModuleOut(ctx, "jacoco/instrumented.jar")
+
+ // The basename of tmpJar has to be the same as the basename of strippedJar
+ tmpJar := android.PathForModuleOut(ctx, "jacoco", "tmp", strippedJar.Base())
ctx.Build(pctx, android.BuildParams{
Rule: jacoco,
Description: "jacoco",
- Output: outputJar,
+ Output: instrumentedJar,
ImplicitOutput: strippedJar,
Input: inputJar,
Args: map[string]string{
- "strippedJar": strippedJar.String(),
- "stripSpec": stripSpec,
- "instrumentedJar": instrumentedJar.String(),
+ "strippedJar": strippedJar.String(),
+ "stripSpec": stripSpec,
+ "tmpDir": filepath.Dir(tmpJar.String()),
+ "tmpJar": tmpJar.String(),
},
})
}
diff --git a/java/java.go b/java/java.go
index dbf202a..24debac 100644
--- a/java/java.go
+++ b/java/java.go
@@ -191,6 +191,32 @@
Profile *string
}
+ Optimize struct {
+ // If false, disable all optimization. Defaults to true for apps, false for
+ // libraries and tests.
+ Enabled *bool
+
+ // If true, optimize for size by removing unused code. Defaults to true for apps,
+ // false for libraries and tests.
+ Shrink *bool
+
+ // If true, optimize bytecode. Defaults to false.
+ Optimize *bool
+
+ // If true, obfuscate bytecode. Defaults to false.
+ Obfuscate *bool
+
+ // If true, do not use the flag files generated by aapt that automatically keep
+ // classes referenced by the app manifest. Defaults to false.
+ No_aapt_flags *bool
+
+ // Flags to pass to proguard.
+ Proguard_flags []string
+
+ // Specifies the locations of files containing proguard flags.
+ Proguard_flags_files []string
+ }
+
// When targeting 1.9, override the modules to use with --system
System_modules *string
}
@@ -216,6 +242,9 @@
// output file containing uninstrumented classes that will be instrumented by jacoco
jacocoReportClassesFile android.Path
+ // output file containing mapping of obfuscated names
+ proguardDictionary android.Path
+
// output file suitable for installing or running
outputFile android.Path
@@ -229,6 +258,9 @@
// list of .java files and srcjars that was passed to javac
compiledJavaSrcs android.Paths
compiledSrcJars android.Paths
+
+ // list of extra progurad flag files
+ extraProguardFlagFiles android.Paths
}
func (j *Module) Srcs() android.Paths {
@@ -260,6 +292,7 @@
systemModulesTag = dependencyTag{name: "system modules"}
frameworkResTag = dependencyTag{name: "framework-res"}
kotlinStdlibTag = dependencyTag{name: "kotlin-stdlib"}
+ proguardRaiseTag = dependencyTag{name: "proguard-raise"}
)
type sdkDep struct {
@@ -377,6 +410,10 @@
ctx.AddDependency(ctx.Module(), systemModulesTag, sdkDep.systemModules)
}
ctx.AddDependency(ctx.Module(), bootClasspathTag, sdkDep.module)
+ if Bool(j.deviceProperties.Optimize.Enabled) {
+ ctx.AddDependency(ctx.Module(), proguardRaiseTag, config.DefaultBootclasspathLibraries...)
+ ctx.AddDependency(ctx.Module(), proguardRaiseTag, config.DefaultLibraries...)
+ }
}
} else if j.deviceProperties.System_modules == nil {
ctx.PropertyErrorf("no_standard_libs",
@@ -597,6 +634,29 @@
// classpath
flags.bootClasspath.AddPaths(deps.bootClasspath)
flags.classpath.AddPaths(deps.classpath)
+
+ if len(flags.bootClasspath) == 0 && ctx.Host() && !ctx.Config().TargetOpenJDK9() &&
+ !Bool(j.properties.No_standard_libs) &&
+ inList(flags.javaVersion, []string{"1.6", "1.7", "1.8"}) {
+ // Give host-side tools a version of OpenJDK's standard libraries
+ // close to what they're targeting. As of Dec 2017, AOSP is only
+ // bundling OpenJDK 8 and 9, so nothing < 8 is available.
+ //
+ // When building with OpenJDK 8, the following should have no
+ // effect since those jars would be available by default.
+ //
+ // When building with OpenJDK 9 but targeting a version < 1.8,
+ // putting them on the bootclasspath means that:
+ // a) code can't (accidentally) refer to OpenJDK 9 specific APIs
+ // b) references to existing APIs are not reinterpreted in an
+ // OpenJDK 9-specific way, eg. calls to subclasses of
+ // java.nio.Buffer as in http://b/70862583
+ java8Home := ctx.Config().Getenv("ANDROID_JAVA8_HOME")
+ flags.bootClasspath = append(flags.bootClasspath,
+ android.PathForSource(ctx, java8Home, "jre/lib/jce.jar"),
+ android.PathForSource(ctx, java8Home, "jre/lib/rt.jar"))
+ }
+
// systemModules
if deps.systemModules != nil {
flags.systemModules = append(flags.systemModules, deps.systemModules)
@@ -677,7 +737,6 @@
// Store the list of .java files that was passed to javac
j.compiledJavaSrcs = uniqueSrcFiles
j.compiledSrcJars = srcJars
- fullD8 := ctx.Config().UseD8Desugar()
enable_sharding := false
if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") {
@@ -806,10 +865,6 @@
j.headerJarFile = j.implementationJarFile
}
- if !fullD8 && ctx.Device() && j.installable() {
- outputFile = j.desugar(ctx, flags, outputFile, jarName)
- }
-
if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
if inList(ctx.ModuleName(), config.InstrumentFrameworkModules) {
j.properties.Instrument = true
@@ -821,11 +876,7 @@
}
if ctx.Device() && j.installable() {
- if fullD8 {
- outputFile = j.compileDexFullD8(ctx, flags, outputFile, jarName)
- } else {
- outputFile = j.compileDex(ctx, flags, outputFile, jarName)
- }
+ outputFile = j.compileDex(ctx, flags, outputFile, jarName)
if ctx.Failed() {
return
}
@@ -873,33 +924,12 @@
return headerJar
}
-func (j *Module) desugar(ctx android.ModuleContext, flags javaBuilderFlags,
- classesJar android.Path, jarName string) android.Path {
-
- desugarFlags := []string{
- "--min_sdk_version " + j.minSdkVersionNumber(ctx),
- "--desugar_try_with_resources_if_needed=false",
- "--allow_empty_bootclasspath",
- }
-
- if inList("--core-library", j.deviceProperties.Dxflags) {
- desugarFlags = append(desugarFlags, "--core_library")
- }
-
- flags.desugarFlags = strings.Join(desugarFlags, " ")
-
- desugarJar := android.PathForModuleOut(ctx, "desugar", jarName)
- TransformDesugar(ctx, desugarJar, classesJar, flags)
-
- return desugarJar
-}
-
func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
classesJar android.Path, jarName string) android.Path {
specs := j.jacocoModuleToZipCommand(ctx)
- jacocoReportClassesFile := android.PathForModuleOut(ctx, "jacoco", "jacoco-report-classes.jar")
+ jacocoReportClassesFile := android.PathForModuleOut(ctx, "jacoco-report-classes", jarName)
instrumentedJar := android.PathForModuleOut(ctx, "jacoco", jarName)
jacocoInstrumentJar(ctx, instrumentedJar, jacocoReportClassesFile, classesJar, specs)
@@ -909,72 +939,6 @@
return instrumentedJar
}
-func (j *Module) compileDex(ctx android.ModuleContext, flags javaBuilderFlags,
- classesJar android.Path, jarName string) android.Path {
-
- dxFlags := j.deviceProperties.Dxflags
-
- if ctx.Config().Getenv("NO_OPTIMIZE_DX") != "" {
- dxFlags = append(dxFlags, "--no-optimize")
- }
-
- if ctx.Config().Getenv("GENERATE_DEX_DEBUG") != "" {
- dxFlags = append(dxFlags,
- "--debug",
- "--verbose",
- "--dump-to="+android.PathForModuleOut(ctx, "classes.lst").String(),
- "--dump-width=1000")
- }
-
- dxFlags = append(dxFlags, "--min-sdk-version="+j.minSdkVersionNumber(ctx))
-
- flags.dxFlags = strings.Join(dxFlags, " ")
-
- // Compile classes.jar into classes.dex and then javalib.jar
- javalibJar := android.PathForModuleOut(ctx, "dex", jarName)
- TransformClassesJarToDexJar(ctx, javalibJar, classesJar, flags)
-
- j.dexJarFile = javalibJar
- return javalibJar
-}
-
-func (j *Module) compileDexFullD8(ctx android.ModuleContext, flags javaBuilderFlags,
- classesJar android.Path, jarName string) android.Path {
-
- // Translate all the DX flags to D8 ones until all the build files have been migrated
- // to D8 flags. See: b/69377755
- var dxFlags []string
- for _, x := range j.deviceProperties.Dxflags {
- switch x {
- case "--core-library", "--dex", "--multi-dex":
- continue
- default:
- dxFlags = append(dxFlags, x)
- }
- }
-
- if ctx.AConfig().Getenv("NO_OPTIMIZE_DX") != "" {
- dxFlags = append(dxFlags, "--debug")
- }
-
- if ctx.AConfig().Getenv("GENERATE_DEX_DEBUG") != "" {
- dxFlags = append(dxFlags,
- "--debug",
- "--verbose")
- }
-
- dxFlags = append(dxFlags, "--min-api "+j.minSdkVersionNumber(ctx))
-
- flags.dxFlags = strings.Join(dxFlags, " ")
-
- // Compile classes.jar into classes.dex and then javalib.jar
- javalibJar := android.PathForModuleOut(ctx, "dex", jarName)
- TransformClassesJarToDexJar(ctx, javalibJar, classesJar, flags)
-
- j.dexJarFile = javalibJar
- return javalibJar
-}
-
// Returns a sdk version as a string that is guaranteed to be a parseable as a number. For
// modules targeting an unreleased SDK (meaning it does not yet have a number) it returns "10000".
func (j *Module) minSdkVersionNumber(ctx android.ModuleContext) string {
diff --git a/java/java_test.go b/java/java_test.go
index 84fe903..e8298a2 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -53,6 +53,12 @@
}
func testConfig(env map[string]string) android.Config {
+ if env == nil {
+ env = make(map[string]string)
+ }
+ if env["ANDROID_JAVA8_HOME"] == "" {
+ env["ANDROID_JAVA8_HOME"] = "jdk8"
+ }
return android.TestArchConfig(buildDir, env)
}
@@ -150,6 +156,12 @@
"build/target/product/security/testkey": nil,
"build/soong/scripts/jar-wrapper.sh": nil,
+
+ "build/make/core/proguard.flags": nil,
+ "build/make/core/proguard_basic_keeps.flags": nil,
+
+ "jdk8/jre/lib/jce.jar": nil,
+ "jdk8/jre/lib/rt.jar": nil,
}
for k, v := range fs {
@@ -364,11 +376,12 @@
},
{
- name: "host default",
- moduleType: "java_library_host",
- properties: ``,
- host: android.Host,
- classpath: []string{},
+ name: "host default",
+ moduleType: "java_library_host",
+ properties: ``,
+ host: android.Host,
+ bootclasspath: []string{"jdk8/jre/lib/jce.jar", "jdk8/jre/lib/rt.jar"},
+ classpath: []string{},
},
{
name: "host nostdlib",
@@ -379,10 +392,11 @@
},
{
- name: "host supported default",
- host: android.Host,
- properties: `host_supported: true,`,
- classpath: []string{},
+ name: "host supported default",
+ host: android.Host,
+ properties: `host_supported: true,`,
+ classpath: []string{},
+ bootclasspath: []string{"jdk8/jre/lib/jce.jar", "jdk8/jre/lib/rt.jar"},
},
{
name: "host supported nostdlib",
diff --git a/java/system_modules.go b/java/system_modules.go
index 5234d17..196d041 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -112,11 +112,9 @@
func (system *SystemModules) GenerateAndroidBuildActions(ctx android.ModuleContext) {
var jars android.Paths
- ctx.VisitDirectDeps(func(module android.Module) {
- if ctx.OtherModuleDependencyTag(module) == libTag {
- dep, _ := module.(Dependency)
- jars = append(jars, dep.HeaderJars()...)
- }
+ ctx.VisitDirectDepsWithTag(libTag, func(module android.Module) {
+ dep, _ := module.(Dependency)
+ jars = append(jars, dep.HeaderJars()...)
})
jars = append(jars, android.PathsForModuleSrc(ctx, system.properties.Jars)...)
diff --git a/python/binary.go b/python/binary.go
index 457c7fa..0314edb 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -133,10 +133,7 @@
var launcher_path android.Path
if embedded_launcher {
- ctx.VisitDirectDeps(func(m android.Module) {
- if ctx.OtherModuleDependencyTag(m) != launcherTag {
- return
- }
+ ctx.VisitDirectDepsWithTag(launcherTag, func(m android.Module) {
if provider, ok := m.(IntermPathProvider); ok {
if launcher_path != nil {
panic(fmt.Errorf("launcher path was found before: %q",