Merge "Override modules should always override source modules" into main
diff --git a/aconfig/build_flags/Android.bp b/aconfig/build_flags/Android.bp
index 69e4316..b3c7339 100644
--- a/aconfig/build_flags/Android.bp
+++ b/aconfig/build_flags/Android.bp
@@ -14,6 +14,7 @@
],
srcs: [
"all_build_flag_declarations.go",
+ "build_flags.go",
"declarations.go",
"init.go",
],
diff --git a/aconfig/build_flags/build_flags.go b/aconfig/build_flags/build_flags.go
new file mode 100644
index 0000000..e878b5a
--- /dev/null
+++ b/aconfig/build_flags/build_flags.go
@@ -0,0 +1,71 @@
+// Copyright 2024 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 build_flags
+
+import (
+ "fmt"
+
+ "android/soong/android"
+)
+
+const (
+ outJsonFileName = "build_flags.json"
+)
+
+func init() {
+ registerBuildFlagsModuleType(android.InitRegistrationContext)
+}
+
+func registerBuildFlagsModuleType(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("build_flags_json", buildFlagsFactory)
+}
+
+type buildFlags struct {
+ android.ModuleBase
+
+ outputPath android.OutputPath
+}
+
+func buildFlagsFactory() android.Module {
+ module := &buildFlags{}
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ return module
+}
+
+func (m *buildFlags) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ // Read the build_flags_<partition>.json file generated by soong
+ // 'release-config' command.
+ srcPath := android.PathForOutput(ctx, "release-config", fmt.Sprintf("build_flags_%s.json", m.PartitionTag(ctx.DeviceConfig())))
+ m.outputPath = android.PathForModuleOut(ctx, outJsonFileName).OutputPath
+
+ // The 'release-config' command is called for every build, and generates the
+ // build_flags_<partition>.json file.
+ // Update the output file only if the source file is changed.
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.CpIfChanged,
+ Input: srcPath,
+ Output: m.outputPath,
+ })
+
+ installPath := android.PathForModuleInstall(ctx, "etc")
+ ctx.InstallFile(installPath, outJsonFileName, m.outputPath)
+}
+
+func (m *buildFlags) AndroidMkEntries() []android.AndroidMkEntries {
+ return []android.AndroidMkEntries{android.AndroidMkEntries{
+ Class: "ETC",
+ OutputFile: android.OptionalPathForPath(m.outputPath),
+ }}
+}
diff --git a/aconfig/build_flags/init.go b/aconfig/build_flags/init.go
index 5907f4e..dc1369c 100644
--- a/aconfig/build_flags/init.go
+++ b/aconfig/build_flags/init.go
@@ -69,6 +69,7 @@
func init() {
RegisterBuildComponents(android.InitRegistrationContext)
+ pctx.Import("android/soong/android")
pctx.HostBinToolVariable("buildFlagDeclarations", "build-flag-declarations")
}
diff --git a/android/module.go b/android/module.go
index c4cc5e6..fed1d0e 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1076,6 +1076,12 @@
return
}
+ // ... also don't make a dependency between native bridge arch and non-native bridge
+ // arches. b/342945184
+ if ctx.Target().NativeBridge != target.NativeBridge {
+ return
+ }
+
variation := target.Variations()
if ctx.OtherModuleFarDependencyVariantExists(variation, depName) {
ctx.AddFarVariationDependencies(variation, RequiredDepTag, depName)
diff --git a/cc/config/global.go b/cc/config/global.go
index b7ee768..290a27d 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -370,6 +370,8 @@
"-Wno-unqualified-std-cast-call",
"-Wno-array-parameter",
"-Wno-gnu-offsetof-extensions",
+ // TODO: Enable this warning http://b/315245071
+ "-Wno-fortify-source",
}
llvmNextExtraCommonGlobalCflags = []string{
diff --git a/cmd/release_config/release_config/main.go b/cmd/release_config/release_config/main.go
index 0617838..762f561 100644
--- a/cmd/release_config/release_config/main.go
+++ b/cmd/release_config/release_config/main.go
@@ -120,7 +120,7 @@
panic(err)
}
}
- if err = config.WritePartitionBuildFlags(outputDir, product, targetRelease); err != nil {
+ if err = config.WritePartitionBuildFlags(outputDir); err != nil {
panic(err)
}
diff --git a/cmd/release_config/release_config_lib/release_config.go b/cmd/release_config/release_config_lib/release_config.go
index 547f0dc..3e2348f 100644
--- a/cmd/release_config/release_config_lib/release_config.go
+++ b/cmd/release_config/release_config_lib/release_config.go
@@ -284,13 +284,15 @@
return nil
}
-func (config *ReleaseConfig) WritePartitionBuildFlags(outDir, product, targetRelease string) error {
+func (config *ReleaseConfig) WritePartitionBuildFlags(outDir string) error {
var err error
for partition, flags := range config.PartitionBuildFlags {
slices.SortFunc(flags.FlagArtifacts, func(a, b *rc_proto.FlagArtifact) int {
return cmp.Compare(*a.FlagDeclaration.Name, *b.FlagDeclaration.Name)
})
- if err = WriteMessage(filepath.Join(outDir, fmt.Sprintf("build_flags_%s-%s-%s.json", partition, config.Name, product)), flags); err != nil {
+ // The json file name must not be modified as this is read from
+ // build_flags_json module
+ if err = WriteMessage(filepath.Join(outDir, fmt.Sprintf("build_flags_%s.json", partition)), flags); err != nil {
return err
}
}
diff --git a/java/base.go b/java/base.go
index b9e236c..056dbd5 100644
--- a/java/base.go
+++ b/java/base.go
@@ -1650,11 +1650,23 @@
classesJar: implementationAndResourcesJar,
jarName: jarName,
}
- dexOutputFile = j.dexer.compileDex(ctx, params)
+ if j.EnableProfileRewriting() {
+ profile := j.GetProfile()
+ if profile == "" || !j.GetProfileGuided() {
+ ctx.PropertyErrorf("enable_profile_rewriting", "Profile and Profile_guided must be set when enable_profile_rewriting is true")
+ }
+ params.artProfileInput = &profile
+ }
+ dexOutputFile, dexArtProfileOutput := j.dexer.compileDex(ctx, params)
if ctx.Failed() {
return
}
+ // If r8/d8 provides a profile that matches the optimized dex, use that for dexpreopt.
+ if dexArtProfileOutput != nil {
+ j.dexpreopter.SetRewrittenProfile(*dexArtProfileOutput)
+ }
+
// merge dex jar with resources if necessary
if j.resourceJar != nil {
jars := android.Paths{dexOutputFile, j.resourceJar}
diff --git a/java/dex.go b/java/dex.go
index 8cfffaf..f072226 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -253,17 +253,25 @@
return flags, deps
}
-func d8Flags(flags javaBuilderFlags) (d8Flags []string, d8Deps android.Paths) {
+func (d *dexer) d8Flags(ctx android.ModuleContext, dexParams *compileDexParams) (d8Flags []string, d8Deps android.Paths, artProfileOutput *android.OutputPath) {
+ flags := dexParams.flags
d8Flags = append(d8Flags, flags.bootClasspath.FormRepeatedClassPath("--lib ")...)
d8Flags = append(d8Flags, flags.dexClasspath.FormRepeatedClassPath("--lib ")...)
d8Deps = append(d8Deps, flags.bootClasspath...)
d8Deps = append(d8Deps, flags.dexClasspath...)
- return d8Flags, d8Deps
+ if flags, deps, profileOutput := d.addArtProfile(ctx, dexParams); profileOutput != nil {
+ d8Flags = append(d8Flags, flags...)
+ d8Deps = append(d8Deps, deps...)
+ artProfileOutput = profileOutput
+ }
+
+ return d8Flags, d8Deps, artProfileOutput
}
-func (d *dexer) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Flags []string, r8Deps android.Paths) {
+func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams) (r8Flags []string, r8Deps android.Paths, artProfileOutput *android.OutputPath) {
+ flags := dexParams.flags
opt := d.dexProperties.Optimize
// When an app contains references to APIs that are not in the SDK specified by
@@ -375,18 +383,44 @@
}
}
- return r8Flags, r8Deps
+ if flags, deps, profileOutput := d.addArtProfile(ctx, dexParams); profileOutput != nil {
+ r8Flags = append(r8Flags, flags...)
+ r8Deps = append(r8Deps, deps...)
+ artProfileOutput = profileOutput
+ }
+
+ return r8Flags, r8Deps, artProfileOutput
}
type compileDexParams struct {
- flags javaBuilderFlags
- sdkVersion android.SdkSpec
- minSdkVersion android.ApiLevel
- classesJar android.Path
- jarName string
+ flags javaBuilderFlags
+ sdkVersion android.SdkSpec
+ minSdkVersion android.ApiLevel
+ classesJar android.Path
+ jarName string
+ artProfileInput *string
}
-func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParams) android.OutputPath {
+// Adds --art-profile to r8/d8 command.
+// r8/d8 will output a generated profile file to match the optimized dex code.
+func (d *dexer) addArtProfile(ctx android.ModuleContext, dexParams *compileDexParams) (flags []string, deps android.Paths, artProfileOutputPath *android.OutputPath) {
+ if dexParams.artProfileInput != nil {
+ artProfileInputPath := android.PathForModuleSrc(ctx, *dexParams.artProfileInput)
+ artProfileOutputPathValue := android.PathForModuleOut(ctx, "profile.prof.txt").OutputPath
+ artProfileOutputPath = &artProfileOutputPathValue
+ flags = []string{
+ "--art-profile",
+ artProfileInputPath.String(),
+ artProfileOutputPath.String(),
+ }
+ deps = append(deps, artProfileInputPath)
+ }
+ return flags, deps, artProfileOutputPath
+
+}
+
+// Return the compiled dex jar and (optional) profile _after_ r8 optimization
+func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParams) (android.OutputPath, *android.OutputPath) {
// Compile classes.jar into classes.dex and then javalib.jar
javalibJar := android.PathForModuleOut(ctx, "dex", dexParams.jarName).OutputPath
@@ -406,6 +440,7 @@
}
useR8 := d.effectiveOptimizeEnabled()
+ var artProfileOutputPath *android.OutputPath
if useR8 {
proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary")
d.proguardDictionary = android.OptionalPathForPath(proguardDictionary)
@@ -418,8 +453,19 @@
d.proguardUsageZip = android.OptionalPathForPath(proguardUsageZip)
resourcesOutput := android.PathForModuleOut(ctx, "package-res-shrunken.apk")
d.resourcesOutput = android.OptionalPathForPath(resourcesOutput)
- r8Flags, r8Deps := d.r8Flags(ctx, dexParams.flags)
- r8Deps = append(r8Deps, commonDeps...)
+ implicitOutputs := android.WritablePaths{
+ proguardDictionary,
+ proguardUsageZip,
+ proguardConfiguration,
+ }
+ r8Flags, r8Deps, r8ArtProfileOutputPath := d.r8Flags(ctx, dexParams)
+ if r8ArtProfileOutputPath != nil {
+ artProfileOutputPath = r8ArtProfileOutputPath
+ implicitOutputs = append(
+ implicitOutputs,
+ artProfileOutputPath,
+ )
+ }
rule := r8
args := map[string]string{
"r8Flags": strings.Join(append(commonFlags, r8Flags...), " "),
@@ -436,10 +482,6 @@
rule = r8RE
args["implicits"] = strings.Join(r8Deps.Strings(), ",")
}
- implicitOutputs := android.WritablePaths{
- proguardDictionary,
- proguardUsageZip,
- proguardConfiguration}
if d.resourcesInput.Valid() {
implicitOutputs = append(implicitOutputs, resourcesOutput)
args["resourcesOutput"] = resourcesOutput.String()
@@ -454,18 +496,27 @@
Args: args,
})
} else {
- d8Flags, d8Deps := d8Flags(dexParams.flags)
+ implicitOutputs := android.WritablePaths{}
+ d8Flags, d8Deps, d8ArtProfileOutputPath := d.d8Flags(ctx, dexParams)
+ if d8ArtProfileOutputPath != nil {
+ artProfileOutputPath = d8ArtProfileOutputPath
+ implicitOutputs = append(
+ implicitOutputs,
+ artProfileOutputPath,
+ )
+ }
d8Deps = append(d8Deps, commonDeps...)
rule := d8
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_D8") {
rule = d8RE
}
ctx.Build(pctx, android.BuildParams{
- Rule: rule,
- Description: "d8",
- Output: javalibJar,
- Input: dexParams.classesJar,
- Implicits: d8Deps,
+ Rule: rule,
+ Description: "d8",
+ Output: javalibJar,
+ Input: dexParams.classesJar,
+ ImplicitOutputs: implicitOutputs,
+ Implicits: d8Deps,
Args: map[string]string{
"d8Flags": strings.Join(append(commonFlags, d8Flags...), " "),
"zipFlags": zipFlags,
@@ -480,5 +531,5 @@
javalibJar = alignedJavalibJar
}
- return javalibJar
+ return javalibJar, artProfileOutputPath
}
diff --git a/java/dex_test.go b/java/dex_test.go
index 1ecdae0..eb017d5 100644
--- a/java/dex_test.go
+++ b/java/dex_test.go
@@ -662,3 +662,30 @@
android.AssertStringDoesContain(t, "expected aarimports's proguard flags",
appR8.Args["r8Flags"], "proguard.txt")
}
+
+func TestR8FlagsArtProfile(t *testing.T) {
+ result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, `
+ android_app {
+ name: "app",
+ srcs: ["foo.java"],
+ platform_apis: true,
+ dex_preopt: {
+ profile_guided: true,
+ profile: "profile.txt.prof",
+ enable_profile_rewriting: true,
+ },
+ }
+ `)
+
+ app := result.ModuleForTests("app", "android_common")
+ appR8 := app.Rule("r8")
+ android.AssertStringDoesContain(t, "expected --art-profile in app r8 flags",
+ appR8.Args["r8Flags"], "--art-profile")
+
+ appDexpreopt := app.Rule("dexpreopt")
+ android.AssertStringDoesContain(t,
+ "expected --art-profile output to be used to create .prof binary",
+ appDexpreopt.RuleParams.Command,
+ "--create-profile-from=out/soong/.intermediates/app/android_common/profile.prof.txt --output-profile-type=app",
+ )
+}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 4d6dbff..832b850 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -19,6 +19,8 @@
"sort"
"strings"
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
"android/soong/dexpreopt"
)
@@ -139,6 +141,10 @@
// The path to the profile that dexpreopter accepts. It must be in the binary format. If this is
// set, it overrides the profile settings in `dexpreoptProperties`.
inputProfilePathOnHost android.Path
+
+ // The path to the profile that matches the dex optimized by r8/d8. It is in text format. If this is
+ // set, it will be converted to a binary profile which will be subsequently used for dexpreopt.
+ rewrittenProfile android.Path
}
type DexpreoptProperties struct {
@@ -158,6 +164,11 @@
// defaults to searching for a file that matches the name of this module in the default
// profile location set by PRODUCT_DEX_PREOPT_PROFILE_DIR, or empty if not found.
Profile *string `android:"path"`
+
+ // If set to true, r8/d8 will use `profile` as input to generate a new profile that matches
+ // the optimized dex.
+ // The new profile will be subsequently used as the profile to dexpreopt the dex file.
+ Enable_profile_rewriting *bool
}
Dex_preopt_result struct {
@@ -421,13 +432,17 @@
if d.inputProfilePathOnHost != nil {
profileClassListing = android.OptionalPathForPath(d.inputProfilePathOnHost)
} else if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) && !forPrebuiltApex(ctx) {
- // If dex_preopt.profile_guided is not set, default it based on the existence of the
- // dexprepot.profile option or the profile class listing.
- if String(d.dexpreoptProperties.Dex_preopt.Profile) != "" {
+ // If enable_profile_rewriting is set, use the rewritten profile instead of the checked-in profile
+ if d.EnableProfileRewriting() {
+ profileClassListing = android.OptionalPathForPath(d.GetRewrittenProfile())
+ profileIsTextListing = true
+ } else if profile := d.GetProfile(); profile != "" {
+ // If dex_preopt.profile_guided is not set, default it based on the existence of the
+ // dexprepot.profile option or the profile class listing.
profileClassListing = android.OptionalPathForPath(
- android.PathForModuleSrc(ctx, String(d.dexpreoptProperties.Dex_preopt.Profile)))
+ android.PathForModuleSrc(ctx, profile))
profileBootListing = android.ExistentPathForSource(ctx,
- ctx.ModuleDir(), String(d.dexpreoptProperties.Dex_preopt.Profile)+"-boot")
+ ctx.ModuleDir(), profile+"-boot")
profileIsTextListing = true
} else if global.ProfileDir != "" {
profileClassListing = android.ExistentPathForSource(ctx,
@@ -588,3 +603,23 @@
func (d *dexpreopter) disableDexpreopt() {
d.shouldDisableDexpreopt = true
}
+
+func (d *dexpreopter) EnableProfileRewriting() bool {
+ return proptools.Bool(d.dexpreoptProperties.Dex_preopt.Enable_profile_rewriting)
+}
+
+func (d *dexpreopter) GetProfile() string {
+ return proptools.String(d.dexpreoptProperties.Dex_preopt.Profile)
+}
+
+func (d *dexpreopter) GetProfileGuided() bool {
+ return proptools.Bool(d.dexpreoptProperties.Dex_preopt.Profile_guided)
+}
+
+func (d *dexpreopter) GetRewrittenProfile() android.Path {
+ return d.rewrittenProfile
+}
+
+func (d *dexpreopter) SetRewrittenProfile(p android.Path) {
+ d.rewrittenProfile = p
+}
diff --git a/java/java.go b/java/java.go
index 9fe7a2f..9fa6175 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2339,7 +2339,7 @@
classesJar: al.stubsJar,
jarName: ctx.ModuleName() + ".jar",
}
- dexOutputFile := al.dexer.compileDex(ctx, dexParams)
+ dexOutputFile, _ := al.dexer.compileDex(ctx, dexParams)
uncompressed := true
al.initHiddenAPI(ctx, makeDexJarPathFromPath(dexOutputFile), al.stubsJar, &uncompressed)
dexOutputFile = al.hiddenAPIEncodeDex(ctx, dexOutputFile)
@@ -2723,7 +2723,7 @@
jarName: jarName,
}
- dexOutputFile = j.dexer.compileDex(ctx, dexParams)
+ dexOutputFile, _ = j.dexer.compileDex(ctx, dexParams)
if ctx.Failed() {
return
}