diff options
| -rw-r--r-- | android/env.go | 41 | ||||
| -rw-r--r-- | android/module.go | 1 | ||||
| -rw-r--r-- | android/neverallow.go | 10 | ||||
| -rw-r--r-- | android/neverallow_test.go | 28 | ||||
| -rw-r--r-- | apex/apex_test.go | 111 | ||||
| -rw-r--r-- | apex/builder.go | 2 | ||||
| -rw-r--r-- | cmd/soong_build/main.go | 42 | ||||
| -rw-r--r-- | genrule/genrule.go | 7 | ||||
| -rw-r--r-- | java/androidmk.go | 12 | ||||
| -rwxr-xr-x | java/app.go | 12 | ||||
| -rw-r--r-- | java/app_test.go | 26 | ||||
| -rw-r--r-- | java/builder.go | 38 | ||||
| -rw-r--r-- | java/config/config.go | 1 | ||||
| -rw-r--r-- | java/dex.go | 5 | ||||
| -rw-r--r-- | java/droiddoc.go | 2 | ||||
| -rw-r--r-- | java/java.go | 27 | ||||
| -rw-r--r-- | java/java_test.go | 26 | ||||
| -rw-r--r-- | java/jdeps.go | 1 | ||||
| -rw-r--r-- | java/sdk_library.go | 40 | ||||
| -rw-r--r-- | remoteexec/remoteexec.go | 11 |
20 files changed, 344 insertions, 99 deletions
diff --git a/android/env.go b/android/env.go index 46bd3d6c5..c7c96d5cf 100644 --- a/android/env.go +++ b/android/env.go @@ -15,9 +15,11 @@ package android import ( + "fmt" "os" "os/exec" "strings" + "syscall" "android/soong/env" ) @@ -30,28 +32,59 @@ import ( // a manifest regeneration. var originalEnv map[string]string -var SoongDelveListen string -var SoongDelvePath string +var soongDelveListen string +var soongDelvePath string +var soongDelveEnv []string func init() { // Delve support needs to read this environment variable very early, before NewConfig has created a way to // access originalEnv with dependencies. Store the value where soong_build can find it, it will manually // ensure the dependencies are created. - SoongDelveListen = os.Getenv("SOONG_DELVE") - SoongDelvePath, _ = exec.LookPath("dlv") + soongDelveListen = os.Getenv("SOONG_DELVE") + soongDelvePath, _ = exec.LookPath("dlv") originalEnv = make(map[string]string) + soongDelveEnv = []string{} for _, env := range os.Environ() { idx := strings.IndexRune(env, '=') if idx != -1 { originalEnv[env[:idx]] = env[idx+1:] + if env[:idx] != "SOONG_DELVE" { + soongDelveEnv = append(soongDelveEnv, env) + } } } + // Clear the environment to prevent use of os.Getenv(), which would not provide dependencies on environment // variable values. The environment is available through ctx.Config().Getenv, ctx.Config().IsEnvTrue, etc. os.Clearenv() } +func ReexecWithDelveMaybe() { + if soongDelveListen == "" { + return + } + + if soongDelvePath == "" { + fmt.Fprintln(os.Stderr, "SOONG_DELVE is set but failed to find dlv") + os.Exit(1) + } + dlvArgv := []string{ + soongDelvePath, + "--listen=:" + soongDelveListen, + "--headless=true", + "--api-version=2", + "exec", + os.Args[0], + "--", + } + dlvArgv = append(dlvArgv, os.Args[1:]...) + os.Chdir(absSrcDir) + syscall.Exec(soongDelvePath, dlvArgv, soongDelveEnv) + fmt.Fprintln(os.Stderr, "exec() failed while trying to reexec with Delve") + os.Exit(1) +} + // getenv checks either os.Getenv or originalEnv so that it works before or after the init() // function above. It doesn't add any dependencies on the environment variable, so it should // only be used for values that won't change. For values that might change use ctx.Config().Getenv. diff --git a/android/module.go b/android/module.go index 45477ea80..6239d272b 100644 --- a/android/module.go +++ b/android/module.go @@ -2366,6 +2366,7 @@ type IdeInfo struct { Classes []string `json:"class,omitempty"` Installed_paths []string `json:"installed,omitempty"` SrcJars []string `json:"srcjars,omitempty"` + Paths []string `json:"path,omitempty"` } func CheckBlueprintSyntax(ctx BaseModuleContext, filename string, contents string) []error { diff --git a/android/neverallow.go b/android/neverallow.go index f9fc03caa..9e075b719 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -55,6 +55,7 @@ func init() { AddNeverAllowRules(createMediaRules()...) AddNeverAllowRules(createJavaDeviceForHostRules()...) AddNeverAllowRules(createCcSdkVariantRules()...) + AddNeverAllowRules(createUncompressDexRules()...) } // Add a NeverAllow rule to the set of rules to apply. @@ -210,6 +211,15 @@ func createCcSdkVariantRules() []Rule { } } +func createUncompressDexRules() []Rule { + return []Rule{ + NeverAllow(). + NotIn("art"). + WithMatcher("uncompress_dex", isSetMatcherInstance). + Because("uncompress_dex is only allowed for certain jars for test in art."), + } +} + func neverallowMutator(ctx BottomUpMutatorContext) { m, ok := ctx.Module().(Module) if !ok { diff --git a/android/neverallow_test.go b/android/neverallow_test.go index 2fc42e31f..85c8c5908 100644 --- a/android/neverallow_test.go +++ b/android/neverallow_test.go @@ -303,6 +303,29 @@ var neverallowTests = []struct { `module "outside_whitelist": violates neverallow`, }, }, + { + name: "uncompress_dex inside art", + fs: map[string][]byte{ + "art/Android.bp": []byte(` + java_library { + name: "inside_art_libraries", + uncompress_dex: true, + }`), + }, + }, + { + name: "uncompress_dex outside art", + fs: map[string][]byte{ + "other/Android.bp": []byte(` + java_library { + name: "outside_art_libraries", + uncompress_dex: true, + }`), + }, + expectedErrors: []string{ + "module \"outside_art_libraries\": violates neverallow", + }, + }, } func TestNeverallow(t *testing.T) { @@ -396,8 +419,9 @@ func (p *mockCcLibraryModule) GenerateAndroidBuildActions(ModuleContext) { } type mockJavaLibraryProperties struct { - Libs []string - Sdk_version *string + Libs []string + Sdk_version *string + Uncompress_dex *bool } type mockJavaLibraryModule struct { diff --git a/apex/apex_test.go b/apex/apex_test.go index cbe59531d..5d08f37ab 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -19,6 +19,7 @@ import ( "os" "path" "reflect" + "regexp" "sort" "strings" "testing" @@ -4256,6 +4257,15 @@ func TestLegacyAndroid10Support(t *testing.T) { } } +var filesForSdkLibrary = map[string][]byte{ + "api/current.txt": nil, + "api/removed.txt": nil, + "api/system-current.txt": nil, + "api/system-removed.txt": nil, + "api/test-current.txt": nil, + "api/test-removed.txt": nil, +} + func TestJavaSDKLibrary(t *testing.T) { ctx, _ := testApex(t, ` apex { @@ -4276,14 +4286,7 @@ func TestJavaSDKLibrary(t *testing.T) { api_packages: ["foo"], apex_available: [ "myapex" ], } - `, withFiles(map[string][]byte{ - "api/current.txt": nil, - "api/removed.txt": nil, - "api/system-current.txt": nil, - "api/system-removed.txt": nil, - "api/test-current.txt": nil, - "api/test-removed.txt": nil, - })) + `, withFiles(filesForSdkLibrary)) // java_sdk_library installs both impl jar and permission XML ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{ @@ -4295,6 +4298,98 @@ func TestJavaSDKLibrary(t *testing.T) { ensureContains(t, sdkLibrary.RuleParams.Command, `<library name=\"foo\" file=\"/apex/myapex/javalib/foo.jar\"`) } +func TestJavaSDKLibrary_WithinApex(t *testing.T) { + ctx, _ := testApex(t, ` + apex { + name: "myapex", + key: "myapex.key", + java_libs: ["foo", "bar"], + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + java_sdk_library { + name: "foo", + srcs: ["a.java"], + api_packages: ["foo"], + apex_available: ["myapex"], + sdk_version: "none", + system_modules: "none", + } + + java_library { + name: "bar", + srcs: ["a.java"], + libs: ["foo"], + apex_available: ["myapex"], + sdk_version: "none", + system_modules: "none", + } + `, withFiles(filesForSdkLibrary)) + + // java_sdk_library installs both impl jar and permission XML + ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{ + "javalib/bar.jar", + "javalib/foo.jar", + "etc/permissions/foo.xml", + }) + + // The bar library should depend on the implementation jar. + barLibrary := ctx.ModuleForTests("bar", "android_common_myapex").Rule("javac") + if expected, actual := `^-classpath /[^:]*/turbine-combined/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) { + t.Errorf("expected %q, found %#q", expected, actual) + } +} + +func TestJavaSDKLibrary_CrossBoundary(t *testing.T) { + ctx, _ := testApex(t, ` + apex { + name: "myapex", + key: "myapex.key", + java_libs: ["foo"], + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + java_sdk_library { + name: "foo", + srcs: ["a.java"], + api_packages: ["foo"], + apex_available: ["myapex"], + sdk_version: "none", + system_modules: "none", + } + + java_library { + name: "bar", + srcs: ["a.java"], + libs: ["foo"], + sdk_version: "none", + system_modules: "none", + } + `, withFiles(filesForSdkLibrary)) + + // java_sdk_library installs both impl jar and permission XML + ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{ + "javalib/foo.jar", + "etc/permissions/foo.xml", + }) + + // The bar library should depend on the stubs jar. + barLibrary := ctx.ModuleForTests("bar", "android_common").Rule("javac") + if expected, actual := `^-classpath /[^:]*/turbine-combined/foo\.stubs\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) { + t.Errorf("expected %q, found %#q", expected, actual) + } +} + func TestCompatConfig(t *testing.T) { ctx, _ := testApex(t, ` apex { diff --git a/apex/builder.go b/apex/builder.go index 3d0e9b254..11652bc67 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -470,11 +470,11 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { } targetSdkVersion := ctx.Config().DefaultAppTargetSdk() + // TODO(b/157078772): propagate min_sdk_version to apexer. minSdkVersion := ctx.Config().DefaultAppTargetSdk() if a.minSdkVersion(ctx) == android.SdkVersion_Android10 { minSdkVersion = strconv.Itoa(a.minSdkVersion(ctx)) - targetSdkVersion = strconv.Itoa(a.minSdkVersion(ctx)) } if java.UseApiFingerprint(ctx) { diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go index bd1a9edfa..905f2068b 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -18,12 +18,7 @@ import ( "flag" "fmt" "os" - "os/exec" "path/filepath" - "strconv" - "strings" - "syscall" - "time" "github.com/google/blueprint/bootstrap" @@ -55,42 +50,7 @@ func newNameResolver(config android.Config) *android.NameResolver { } func main() { - if android.SoongDelveListen != "" { - if android.SoongDelvePath == "" { - fmt.Fprintln(os.Stderr, "SOONG_DELVE is set but failed to find dlv") - os.Exit(1) - } - pid := strconv.Itoa(os.Getpid()) - cmd := []string{android.SoongDelvePath, - "attach", pid, - "--headless", - "-l", android.SoongDelveListen, - "--api-version=2", - "--accept-multiclient", - "--log", - } - - fmt.Println("Starting", strings.Join(cmd, " ")) - dlv := exec.Command(cmd[0], cmd[1:]...) - dlv.Stdout = os.Stdout - dlv.Stderr = os.Stderr - dlv.Stdin = nil - - // Put dlv into its own process group so we can kill it and the child process it starts. - dlv.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} - - err := dlv.Start() - if err != nil { - // Print the error starting dlv and continue. - fmt.Println(err) - } else { - // Kill the process group for dlv when soong_build exits. - defer syscall.Kill(-dlv.Process.Pid, syscall.SIGKILL) - // Wait to give dlv a chance to connect and pause the process. - time.Sleep(time.Second) - } - } - + android.ReexecWithDelveMaybe() flag.Parse() // The top-level Blueprints file is passed as the first argument. diff --git a/genrule/genrule.go b/genrule/genrule.go index fe877fe8d..f6904f195 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -144,6 +144,9 @@ type Module struct { subName string subDir string + + // Collect the module directory for IDE info in java/jdeps.go. + modulePaths []string } type taskFunc func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) []generateTask @@ -190,6 +193,9 @@ func toolDepsMutator(ctx android.BottomUpMutatorContext) { func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) { g.subName = ctx.ModuleSubDir() + // Collect the module directory for IDE info in java/jdeps.go. + g.modulePaths = append(g.modulePaths, ctx.ModuleDir()) + if len(g.properties.Export_include_dirs) > 0 { for _, dir := range g.properties.Export_include_dirs { g.exportedIncludeDirs = append(g.exportedIncludeDirs, @@ -529,6 +535,7 @@ func (g *Module) IDEInfo(dpInfo *android.IdeInfo) { dpInfo.Deps = append(dpInfo.Deps, src) } } + dpInfo.Paths = append(dpInfo.Paths, g.modulePaths...) } func (g *Module) AndroidMk() android.AndroidMkData { diff --git a/java/androidmk.go b/java/androidmk.go index 6747b30b0..5e3b7d2cb 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -512,14 +512,12 @@ func (ddoc *Droiddoc) AndroidMkEntries() []android.AndroidMkEntries { fmt.Fprintln(w, ddoc.Name()+"-check-last-released-api:", ddoc.checkLastReleasedApiTimestamp.String()) - if ddoc.Name() == "api-stubs-docs" || ddoc.Name() == "system-api-stubs-docs" { - fmt.Fprintln(w, ".PHONY: checkapi") - fmt.Fprintln(w, "checkapi:", - ddoc.checkLastReleasedApiTimestamp.String()) + fmt.Fprintln(w, ".PHONY: checkapi") + fmt.Fprintln(w, "checkapi:", + ddoc.checkLastReleasedApiTimestamp.String()) - fmt.Fprintln(w, ".PHONY: droidcore") - fmt.Fprintln(w, "droidcore: checkapi") - } + fmt.Fprintln(w, ".PHONY: droidcore") + fmt.Fprintln(w, "droidcore: checkapi") } }, }, diff --git a/java/app.go b/java/app.go index 8241b6842..40815dea6 100755 --- a/java/app.go +++ b/java/app.go @@ -568,16 +568,17 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path { installDir = filepath.Join("app", a.installApkName) } a.dexpreopter.installPath = android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk") - a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx) - + if a.deviceProperties.Uncompress_dex == nil { + // If the value was not force-set by the user, use reasonable default based on the module. + a.deviceProperties.Uncompress_dex = proptools.BoolPtr(a.shouldUncompressDex(ctx)) + } + a.dexpreopter.uncompressedDex = *a.deviceProperties.Uncompress_dex a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries() a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx) a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx) a.dexpreopter.manifestFile = a.mergedManifestFile - a.deviceProperties.UncompressDex = a.dexpreopter.uncompressedDex - if ctx.ModuleName() != "framework-res" { a.Module.compile(ctx, a.aaptSrcJar) } @@ -1613,7 +1614,8 @@ func AndroidAppImportFactory() android.Module { }) android.InitApexModule(module) - InitJavaModule(module, android.DeviceSupported) + android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) + android.InitDefaultableModule(module) android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk") return module diff --git a/java/app_test.go b/java/app_test.go index 1a718f4b3..105afd292 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -2806,6 +2806,32 @@ func TestUncompressDex(t *testing.T) { uncompressedPlatform: true, uncompressedUnbundled: true, }, + { + name: "normal_uncompress_dex_true", + bp: ` + android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "current", + uncompress_dex: true, + } + `, + uncompressedPlatform: true, + uncompressedUnbundled: true, + }, + { + name: "normal_uncompress_dex_false", + bp: ` + android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "current", + uncompress_dex: false, + } + `, + uncompressedPlatform: false, + uncompressedUnbundled: false, + }, } test := func(t *testing.T, bp string, want bool, unbundled bool) { diff --git a/java/builder.go b/java/builder.go index b8340295b..b6cb2aeeb 100644 --- a/java/builder.go +++ b/java/builder.go @@ -116,10 +116,10 @@ var ( }, "abis", "allow-prereleased", "screen-densities", "sdk-version", "stem") - turbine = pctx.AndroidStaticRule("turbine", + turbine, turbineRE = remoteexec.StaticRules(pctx, "turbine", blueprint.RuleParams{ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + - `${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.TurbineJar} --output $out.tmp ` + + `$reTemplate${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.TurbineJar} --output $out.tmp ` + `--temp_dir "$outDir" --sources @$out.rsp --source_jars $srcJars ` + `--javacopts ${config.CommonJdkFlags} ` + `$javacFlags -source $javaVersion -target $javaVersion -- $bootClasspath $classpath && ` + @@ -134,7 +134,15 @@ var ( RspfileContent: "$in", Restat: true, }, - "javacFlags", "bootClasspath", "classpath", "srcJars", "outDir", "javaVersion") + &remoteexec.REParams{Labels: map[string]string{"type": "tool", "name": "turbine"}, + ExecStrategy: "${config.RETurbineExecStrategy}", + Inputs: []string{"${config.TurbineJar}", "${out}.rsp", "$implicits"}, + RSPFile: "${out}.rsp", + OutputFiles: []string{"$out.tmp"}, + OutputDirectories: []string{"$outDir"}, + ToolchainInputs: []string{"${config.JavaCmd}"}, + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, []string{"javacFlags", "bootClasspath", "classpath", "srcJars", "outDir", "javaVersion"}, []string{"implicits"}) jar = pctx.AndroidStaticRule("jar", blueprint.RuleParams{ @@ -346,20 +354,26 @@ func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android. deps = append(deps, classpath...) deps = append(deps, flags.processorPath...) + rule := turbine + args := map[string]string{ + "javacFlags": flags.javacFlags, + "bootClasspath": bootClasspath, + "srcJars": strings.Join(srcJars.Strings(), " "), + "classpath": classpath.FormTurbineClassPath("--classpath "), + "outDir": android.PathForModuleOut(ctx, "turbine", "classes").String(), + "javaVersion": flags.javaVersion.String(), + } + if ctx.Config().IsEnvTrue("RBE_TURBINE") { + rule = turbineRE + args["implicits"] = strings.Join(deps.Strings(), ",") + } ctx.Build(pctx, android.BuildParams{ - Rule: turbine, + Rule: rule, Description: "turbine", Output: outputFile, Inputs: srcFiles, Implicits: deps, - Args: map[string]string{ - "javacFlags": flags.javacFlags, - "bootClasspath": bootClasspath, - "srcJars": strings.Join(srcJars.Strings(), " "), - "classpath": classpath.FormTurbineClassPath("--classpath "), - "outDir": android.PathForModuleOut(ctx, "turbine", "classes").String(), - "javaVersion": flags.javaVersion.String(), - }, + Args: args, }) } diff --git a/java/config/config.go b/java/config/config.go index 1344ceb22..fa19afbf5 100644 --- a/java/config/config.go +++ b/java/config/config.go @@ -148,6 +148,7 @@ func init() { pctx.VariableFunc("REJavacExecStrategy", remoteexec.EnvOverrideFunc("RBE_JAVAC_EXEC_STRATEGY", remoteexec.LocalExecStrategy)) pctx.VariableFunc("RED8ExecStrategy", remoteexec.EnvOverrideFunc("RBE_D8_EXEC_STRATEGY", remoteexec.LocalExecStrategy)) pctx.VariableFunc("RER8ExecStrategy", remoteexec.EnvOverrideFunc("RBE_R8_EXEC_STRATEGY", remoteexec.LocalExecStrategy)) + pctx.VariableFunc("RETurbineExecStrategy", remoteexec.EnvOverrideFunc("RBE_TURBINE_EXEC_STRATEGY", remoteexec.LocalExecStrategy)) pctx.HostJavaToolVariable("JacocoCLIJar", "jacoco-cli.jar") diff --git a/java/dex.go b/java/dex.go index 27ec6ee41..e2a8e7eae 100644 --- a/java/dex.go +++ b/java/dex.go @@ -18,6 +18,7 @@ import ( "strings" "github.com/google/blueprint" + "github.com/google/blueprint/proptools" "android/soong/android" "android/soong/remoteexec" @@ -188,7 +189,7 @@ func (j *Module) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, outDir := android.PathForModuleOut(ctx, "dex") zipFlags := "--ignore_missing_files" - if j.deviceProperties.UncompressDex { + if proptools.Bool(j.deviceProperties.Uncompress_dex) { zipFlags += " -L 0" } @@ -235,7 +236,7 @@ func (j *Module) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, }, }) } - if j.deviceProperties.UncompressDex { + if proptools.Bool(j.deviceProperties.Uncompress_dex) { alignedJavalibJar := android.PathForModuleOut(ctx, "aligned", jarName) TransformZipAlign(ctx, alignedJavalibJar, javalibJar) javalibJar = alignedJavalibJar diff --git a/java/droiddoc.go b/java/droiddoc.go index a5a678522..821bb6d7d 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -546,7 +546,7 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps { case libTag: switch dep := module.(type) { case SdkLibraryDependency: - deps.classpath = append(deps.classpath, dep.SdkImplementationJars(ctx, j.sdkVersion())...) + deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...) case Dependency: deps.classpath = append(deps.classpath, dep.HeaderJars()...) deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...) diff --git a/java/java.go b/java/java.go index b97defa88..466132e1e 100644 --- a/java/java.go +++ b/java/java.go @@ -342,8 +342,13 @@ type CompilerDeviceProperties struct { // set the name of the output Stem *string - UncompressDex bool `blueprint:"mutated"` - IsSDKLibrary bool `blueprint:"mutated"` + // Keep the data uncompressed. We always need uncompressed dex for execution, + // so this might actually save space by avoiding storing the same data twice. + // This defaults to reasonable value based on module and should not be set. + // It exists only to support ART tests. + Uncompress_dex *bool + + IsSDKLibrary bool `blueprint:"mutated"` } func (me *CompilerDeviceProperties) EffectiveOptimizeEnabled() bool { @@ -471,6 +476,9 @@ type Module struct { kytheFiles android.Paths distFile android.Path + + // Collect the module directory for IDE info in java/jdeps.go. + modulePaths []string } func (j *Module) OutputFiles(tag string) (android.Paths, error) { @@ -1567,7 +1575,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { // Hidden API CSV generation and dex encoding dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, dexOutputFile, j.implementationJarFile, - j.deviceProperties.UncompressDex) + proptools.Bool(j.deviceProperties.Uncompress_dex)) // merge dex jar with resources if necessary if j.resourceJar != nil { @@ -1575,7 +1583,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName) TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{}, false, nil, nil) - if j.deviceProperties.UncompressDex { + if *j.deviceProperties.Uncompress_dex { combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName) TransformZipAlign(ctx, combinedAlignedJar, combinedJar) dexOutputFile = combinedAlignedJar @@ -1776,6 +1784,7 @@ func (j *Module) IDEInfo(dpInfo *android.IdeInfo) { if j.expandJarjarRules != nil { dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, j.expandJarjarRules.String()) } + dpInfo.Paths = append(dpInfo.Paths, j.modulePaths...) } func (j *Module) CompilerDeps() []string { @@ -1852,10 +1861,16 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.checkSdkVersions(ctx) j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar") j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary - j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter) - j.deviceProperties.UncompressDex = j.dexpreopter.uncompressedDex + if j.deviceProperties.Uncompress_dex == nil { + // If the value was not force-set by the user, use reasonable default based on the module. + j.deviceProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter)) + } + j.dexpreopter.uncompressedDex = *j.deviceProperties.Uncompress_dex j.compile(ctx, nil) + // Collect the module directory for IDE info in java/jdeps.go. + j.modulePaths = append(j.modulePaths, ctx.ModuleDir()) + exclusivelyForApex := android.InAnyApex(ctx.ModuleName()) && !j.IsForPlatform() if (Bool(j.properties.Installable) || ctx.Host()) && !exclusivelyForApex { var extraInstallDeps android.Paths diff --git a/java/java_test.go b/java/java_test.go index ab6d88ed6..e03e57b78 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -19,6 +19,7 @@ import ( "os" "path/filepath" "reflect" + "regexp" "sort" "strconv" "strings" @@ -1261,6 +1262,31 @@ func TestJavaSdkLibrary(t *testing.T) { } } +func TestJavaSdkLibrary_DoNotAccessImplWhenItIsNotBuilt(t *testing.T) { + ctx, _ := testJava(t, ` + java_sdk_library { + name: "foo", + srcs: ["a.java"], + api_only: true, + public: { + enabled: true, + }, + } + + java_library { + name: "bar", + srcs: ["b.java"], + libs: ["foo"], + } + `) + + // The bar library should depend on the stubs jar. + barLibrary := ctx.ModuleForTests("bar", "android_common").Rule("javac") + if expected, actual := `^-classpath .*:/[^:]*/turbine-combined/foo\.stubs\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) { + t.Errorf("expected %q, found %#q", expected, actual) + } +} + func TestJavaSdkLibrary_UseSourcesFromAnotherSdkLibrary(t *testing.T) { testJava(t, ` java_sdk_library { diff --git a/java/jdeps.go b/java/jdeps.go index 49e3de3cc..9f4388733 100644 --- a/java/jdeps.go +++ b/java/jdeps.go @@ -72,6 +72,7 @@ func (j *jdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCont dpInfo.Jarjar_rules = android.FirstUniqueStrings(dpInfo.Jarjar_rules) dpInfo.Jars = android.FirstUniqueStrings(dpInfo.Jars) dpInfo.SrcJars = android.FirstUniqueStrings(dpInfo.SrcJars) + dpInfo.Paths = android.FirstUniqueStrings(dpInfo.Paths) moduleInfos[name] = dpInfo mkProvider, ok := module.(android.AndroidMkDataProvider) diff --git a/java/sdk_library.go b/java/sdk_library.go index 823127896..b487efdbd 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -1293,17 +1293,39 @@ func PrebuiltJars(ctx android.BaseModuleContext, baseName string, s sdkSpec) and return android.Paths{jarPath.Path()} } +// Get the apex name for module, "" if it is for platform. +func getApexNameForModule(module android.Module) string { + if apex, ok := module.(android.ApexModule); ok { + return apex.ApexName() + } + + return "" +} + +// Check to see if the other module is within the same named APEX as this module. +// +// If either this or the other module are on the platform then this will return +// false. +func (module *SdkLibrary) withinSameApexAs(other android.Module) bool { + name := module.ApexName() + return name != "" && getApexNameForModule(other) == name +} + func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion sdkSpec, headerJars bool) android.Paths { - // Check any special cases for java_sdk_library. - // - // Only allow access to the implementation library in the following condition: - // * No sdk_version specified on the referencing module. - if sdkVersion.kind == sdkPrivate { - if headerJars { - return module.HeaderJars() - } else { - return module.ImplementationJars() + // Only provide access to the implementation library if it is actually built. + if module.requiresRuntimeImplementationLibrary() { + // Check any special cases for java_sdk_library. + // + // Only allow access to the implementation library in the following condition: + // * No sdk_version specified on the referencing module. + // * The referencing module is in the same apex as this. + if sdkVersion.kind == sdkPrivate || module.withinSameApexAs(ctx.Module()) { + if headerJars { + return module.HeaderJars() + } else { + return module.ImplementationJars() + } } } diff --git a/remoteexec/remoteexec.go b/remoteexec/remoteexec.go index 99e29dc0f..2b513b244 100644 --- a/remoteexec/remoteexec.go +++ b/remoteexec/remoteexec.go @@ -75,6 +75,9 @@ type REParams struct { // OutputFiles is a list of output file paths or ninja variables as placeholders for rule // outputs. OutputFiles []string + // OutputDirectories is a list of output directory paths or ninja variables as placeholders + // for rule outputs. + OutputDirectories []string // ToolchainInputs is a list of paths or ninja variables pointing to the location of // toolchain binaries used by the rule. ToolchainInputs []string @@ -151,6 +154,10 @@ func (r *REParams) wrapperArgs() string { args += " --output_files=" + strings.Join(r.OutputFiles, ",") } + if len(r.OutputDirectories) > 0 { + args += " --output_directories=" + strings.Join(r.OutputDirectories, ",") + } + if len(r.ToolchainInputs) > 0 { args += " --toolchain_inputs=" + strings.Join(r.ToolchainInputs, ",") } @@ -159,7 +166,9 @@ func (r *REParams) wrapperArgs() string { } // StaticRules returns a pair of rules based on the given RuleParams, where the first rule is a -// locally executable rule and the second rule is a remotely executable rule. +// locally executable rule and the second rule is a remotely executable rule. commonArgs are args +// used for both the local and remotely executable rules. reArgs are used only for remote +// execution. func StaticRules(ctx android.PackageContext, name string, ruleParams blueprint.RuleParams, reParams *REParams, commonArgs []string, reArgs []string) (blueprint.Rule, blueprint.Rule) { ruleParamsRE := ruleParams ruleParams.Command = strings.ReplaceAll(ruleParams.Command, "$reTemplate", "") |