Merge changes from topic "rust-made-to-order-staticlibs" into main
* changes:
rust: made-to-order rust staticlibs
rust: refactored transformSrctoCrate
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 317f5c4..e8cad7d 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -4,3 +4,4 @@
[Hook Scripts]
do_not_use_DO_NOT_MERGE = ${REPO_ROOT}/build/soong/scripts/check_do_not_merge.sh ${PREUPLOAD_COMMIT}
+aosp_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "."
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 9f386ca..6eabd7c 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -3,5 +3,14 @@
{
"path": "packages/modules/SdkExtensions"
}
+ ],
+
+ "postsubmit": [
+ {
+ "name": "MicrodroidHostTestCases"
+ },
+ {
+ "name": "MicrodroidTestApp"
+ }
]
}
diff --git a/aconfig/aconfig_declarations.go b/aconfig/aconfig_declarations.go
index d29e312..71a64dd 100644
--- a/aconfig/aconfig_declarations.go
+++ b/aconfig/aconfig_declarations.go
@@ -73,8 +73,9 @@
if len(module.properties.Package) == 0 {
ctx.PropertyErrorf("package", "missing package property")
}
- // TODO(b/311155208): Add mandatory check for container after all pre-existing
- // ones are changed.
+ if len(module.properties.Container) == 0 {
+ ctx.PropertyErrorf("container", "missing container property")
+ }
// Add a dependency on the aconfig_value_sets defined in
// RELEASE_ACONFIG_VALUE_SETS, and add any aconfig_values that
diff --git a/aconfig/aconfig_declarations_test.go b/aconfig/aconfig_declarations_test.go
index 5201fed..c37274c 100644
--- a/aconfig/aconfig_declarations_test.go
+++ b/aconfig/aconfig_declarations_test.go
@@ -88,19 +88,49 @@
android.AssertStringEquals(t, "rule must contain container", rule.Args["container"], "--container com.android.foo")
}
-func TestAconfigDeclarationsWithoutContainer(t *testing.T) {
- bp := `
- aconfig_declarations {
- name: "module_name",
- package: "com.example.package",
- srcs: [
- "foo.aconfig",
- ],
- }
- `
- result := runTest(t, android.FixtureExpectsNoErrors, bp)
-
- module := result.ModuleForTests("module_name", "")
- rule := module.Rule("aconfig")
- android.AssertIntEquals(t, "rule must not contain container", len(rule.Args["container"]), 0)
+func TestMandatoryProperties(t *testing.T) {
+ testCases := []struct {
+ name string
+ expectedError string
+ bp string
+ }{
+ {
+ name: "Srcs missing from aconfig_declarations",
+ bp: `
+ aconfig_declarations {
+ name: "my_aconfig_declarations_foo",
+ package: "com.example.package",
+ container: "otherapex",
+ }`,
+ expectedError: `missing source files`,
+ },
+ {
+ name: "Package missing from aconfig_declarations",
+ bp: `
+ aconfig_declarations {
+ name: "my_aconfig_declarations_foo",
+ container: "otherapex",
+ srcs: ["foo.aconfig"],
+ }`,
+ expectedError: `missing package property`,
+ },
+ {
+ name: "Container missing from aconfig_declarations",
+ bp: `
+ aconfig_declarations {
+ name: "my_aconfig_declarations_foo",
+ package: "com.example.package",
+ srcs: ["foo.aconfig"],
+ }`,
+ expectedError: `missing container property`,
+ },
+ }
+ for _, test := range testCases {
+ t.Run(test.name, func(t *testing.T) {
+ errorHandler := android.FixtureExpectsAtLeastOneErrorMatchingPattern(test.expectedError)
+ android.GroupFixturePreparers(PrepareForTestWithAconfigBuildComponents).
+ ExtendWithErrorHandler(errorHandler).
+ RunTestWithBp(t, test.bp)
+ })
+ }
}
diff --git a/aconfig/codegen/aconfig_declarations_group_test.go b/aconfig/codegen/aconfig_declarations_group_test.go
index ec7cea3..c69d21f 100644
--- a/aconfig/codegen/aconfig_declarations_group_test.go
+++ b/aconfig/codegen/aconfig_declarations_group_test.go
@@ -15,9 +15,10 @@
package codegen
import (
+ "testing"
+
"android/soong/android"
"android/soong/java"
- "testing"
)
func TestAconfigDeclarationsGroup(t *testing.T) {
@@ -28,6 +29,7 @@
aconfig_declarations {
name: "foo-aconfig",
package: "com.example.package",
+ container: "com.android.foo",
srcs: ["foo.aconfig"],
}
@@ -39,6 +41,7 @@
aconfig_declarations {
name: "bar-aconfig",
package: "com.example.package",
+ container: "com.android.foo",
srcs: ["foo.aconfig"],
}
diff --git a/aconfig/codegen/cc_aconfig_library_test.go b/aconfig/codegen/cc_aconfig_library_test.go
index cf9ffbd..d01d13b 100644
--- a/aconfig/codegen/cc_aconfig_library_test.go
+++ b/aconfig/codegen/cc_aconfig_library_test.go
@@ -50,6 +50,7 @@
aconfig_declarations {
name: "my_aconfig_declarations",
package: "com.example.package",
+ container: "com.android.foo",
srcs: ["foo.aconfig"],
}
@@ -112,6 +113,7 @@
aconfig_declarations {
name: "my_aconfig_declarations",
package: "com.example.package",
+ container: "com.android.foo",
srcs: ["foo.aconfig"],
}
@@ -167,6 +169,7 @@
aconfig_declarations {
name: "my_aconfig_declarations_bar",
package: "com.example.package",
+ container: "com.android.foo",
srcs: ["bar.aconfig"],
}
@@ -241,6 +244,7 @@
aconfig_declarations {
name: "my_aconfig_declarations",
package: "com.example.package",
+ container: "com.android.foo",
srcs: ["foo.aconfig"],
}
diff --git a/aconfig/codegen/java_aconfig_library_test.go b/aconfig/codegen/java_aconfig_library_test.go
index de45b5c..87b54a4 100644
--- a/aconfig/codegen/java_aconfig_library_test.go
+++ b/aconfig/codegen/java_aconfig_library_test.go
@@ -35,6 +35,7 @@
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package.foo",
+ container: "system",
srcs: ["foo.aconfig"],
}
@@ -46,6 +47,7 @@
aconfig_declarations {
name: "my_aconfig_declarations_bar",
package: "com.example.package.bar",
+ container: "system",
srcs: ["bar.aconfig"],
}
@@ -60,7 +62,7 @@
entry := android.AndroidMkEntriesForTest(t, result.TestContext, module)[0]
makeVar := entry.EntryMap["LOCAL_ACONFIG_FILES"]
- android.EnsureListContainsSuffix(t, makeVar, "android_common/aconfig_merged.pb")
+ android.EnsureListContainsSuffix(t, makeVar, "android_common/system/aconfig_merged.pb")
}
func TestAndroidMkJavaLibrary(t *testing.T) {
@@ -175,6 +177,7 @@
aconfig_declarations {
name: "my_aconfig_declarations",
package: "com.example.package",
+ container: "com.android.foo",
srcs: ["foo.aconfig"],
exportable: true,
}
@@ -200,6 +203,7 @@
aconfig_declarations {
name: "my_aconfig_declarations",
package: "com.example.package",
+ container: "com.android.foo",
srcs: ["foo.aconfig"],
}
@@ -234,3 +238,52 @@
func TestUnsupportedMode(t *testing.T) {
testCodegenModeWithError(t, "mode: `unsupported`,", "mode: \"unsupported\" is not a supported mode")
}
+
+func TestMkEntriesMatchedContainer(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithAconfigBuildComponents,
+ java.PrepareForTestWithJavaDefaultModules).
+ ExtendWithErrorHandler(android.FixtureExpectsNoErrors).
+ RunTestWithBp(t, `
+ aconfig_declarations {
+ name: "my_aconfig_declarations_foo",
+ package: "com.example.package.foo",
+ container: "system",
+ srcs: ["foo.aconfig"],
+ }
+
+ java_aconfig_library {
+ name: "my_java_aconfig_library_foo",
+ aconfig_declarations: "my_aconfig_declarations_foo",
+ }
+
+ aconfig_declarations {
+ name: "my_aconfig_declarations_bar",
+ package: "com.example.package.bar",
+ container: "system_ext",
+ srcs: ["bar.aconfig"],
+ }
+
+ java_aconfig_library {
+ name: "my_java_aconfig_library_bar",
+ aconfig_declarations: "my_aconfig_declarations_bar",
+ }
+
+ java_library {
+ name: "my_module",
+ srcs: [
+ "src/foo.java",
+ ],
+ static_libs: [
+ "my_java_aconfig_library_foo",
+ "my_java_aconfig_library_bar",
+ ],
+ platform_apis: true,
+ }
+ `)
+
+ module := result.ModuleForTests("my_module", "android_common").Module()
+ entry := android.AndroidMkEntriesForTest(t, result.TestContext, module)[0]
+ makeVar := entry.EntryMap["LOCAL_ACONFIG_FILES"]
+ android.EnsureListContainsSuffix(t, makeVar, "my_aconfig_declarations_foo/intermediate.pb")
+}
diff --git a/aconfig/codegen/rust_aconfig_library_test.go b/aconfig/codegen/rust_aconfig_library_test.go
index fe28f94..523b464 100644
--- a/aconfig/codegen/rust_aconfig_library_test.go
+++ b/aconfig/codegen/rust_aconfig_library_test.go
@@ -46,6 +46,7 @@
aconfig_declarations {
name: "my_aconfig_declarations",
package: "com.example.package",
+ container: "com.android.foo",
srcs: ["foo.aconfig"],
}
@@ -131,6 +132,7 @@
aconfig_declarations {
name: "my_aconfig_declarations",
package: "com.example.package",
+ container: "com.android.foo",
srcs: ["foo.aconfig"],
}
rust_aconfig_library {
@@ -193,6 +195,7 @@
aconfig_declarations {
name: "my_aconfig_declarations",
package: "com.example.package",
+ container: "com.android.foo",
srcs: ["foo.aconfig"],
}
rust_aconfig_library {
diff --git a/android/Android.bp b/android/Android.bp
index f130d3a..9ce8cdc 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -41,6 +41,7 @@
"buildinfo_prop.go",
"config.go",
"test_config.go",
+ "configurable_properties.go",
"configured_jars.go",
"csuite_config.go",
"deapexer.go",
@@ -60,6 +61,7 @@
"license_metadata.go",
"license_sdk_member.go",
"licenses.go",
+ "logtags.go",
"makevars.go",
"metrics.go",
"module.go",
diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go
index 4c1782b..ee9891d 100644
--- a/android/aconfig_providers.go
+++ b/android/aconfig_providers.go
@@ -43,14 +43,6 @@
var AconfigDeclarationsProviderKey = blueprint.NewProvider[AconfigDeclarationsProviderData]()
-// This is used to collect the aconfig declarations info on the transitive closure,
-// the data is keyed on the container.
-type AconfigTransitiveDeclarationsInfo struct {
- AconfigFiles map[string]Paths
-}
-
-var AconfigTransitiveDeclarationsInfoProvider = blueprint.NewProvider[AconfigTransitiveDeclarationsInfo]()
-
type ModeInfo struct {
Container string
Mode string
@@ -80,54 +72,15 @@
}
}
-// CollectDependencyAconfigFiles is used by some module types to provide finer dependency graphing than
-// we can do in ModuleBase.
-func CollectDependencyAconfigFiles(ctx ModuleContext, mergedAconfigFiles *map[string]Paths) {
- if *mergedAconfigFiles == nil {
- *mergedAconfigFiles = make(map[string]Paths)
- }
- ctx.VisitDirectDepsIgnoreBlueprint(func(module Module) {
- if dep, _ := OtherModuleProvider(ctx, module, AconfigDeclarationsProviderKey); dep.IntermediateCacheOutputPath != nil {
- (*mergedAconfigFiles)[dep.Container] = append((*mergedAconfigFiles)[dep.Container], dep.IntermediateCacheOutputPath)
- return
- }
- if dep, ok := OtherModuleProvider(ctx, module, aconfigPropagatingProviderKey); ok {
- for container, v := range dep.AconfigFiles {
- (*mergedAconfigFiles)[container] = append((*mergedAconfigFiles)[container], v...)
- }
- }
- // We process these last, so that they determine the final value, eliminating any duplicates that we picked up
- // from UpdateAndroidBuildActions.
- if dep, ok := OtherModuleProvider(ctx, module, AconfigTransitiveDeclarationsInfoProvider); ok {
- for container, v := range dep.AconfigFiles {
- (*mergedAconfigFiles)[container] = append((*mergedAconfigFiles)[container], v...)
- }
- }
- })
-
- for _, container := range SortedKeys(*mergedAconfigFiles) {
- aconfigFiles := (*mergedAconfigFiles)[container]
- (*mergedAconfigFiles)[container] = mergeAconfigFiles(ctx, container, aconfigFiles, false)
- }
-
- SetProvider(ctx, AconfigTransitiveDeclarationsInfoProvider, AconfigTransitiveDeclarationsInfo{
- AconfigFiles: *mergedAconfigFiles,
- })
-}
-
-func SetAconfigFileMkEntries(m *ModuleBase, entries *AndroidMkEntries, aconfigFiles map[string]Paths) {
- setAconfigFileMkEntries(m, entries, aconfigFiles)
-}
-
type aconfigPropagatingDeclarationsInfo struct {
AconfigFiles map[string]Paths
ModeInfos map[string]ModeInfo
}
-var aconfigPropagatingProviderKey = blueprint.NewProvider[aconfigPropagatingDeclarationsInfo]()
+var AconfigPropagatingProviderKey = blueprint.NewProvider[aconfigPropagatingDeclarationsInfo]()
func VerifyAconfigBuildMode(ctx ModuleContext, container string, module blueprint.Module, asError bool) {
- if dep, ok := OtherModuleProvider(ctx, module, aconfigPropagatingProviderKey); ok {
+ if dep, ok := OtherModuleProvider(ctx, module, AconfigPropagatingProviderKey); ok {
for k, v := range dep.ModeInfos {
msg := fmt.Sprintf("%s/%s depends on %s/%s/%s across containers\n",
module.Name(), container, k, v.Container, v.Mode)
@@ -159,17 +112,12 @@
if dep, ok := OtherModuleProvider(ctx, module, AconfigDeclarationsProviderKey); ok {
mergedAconfigFiles[dep.Container] = append(mergedAconfigFiles[dep.Container], dep.IntermediateCacheOutputPath)
}
- if dep, ok := OtherModuleProvider(ctx, module, aconfigPropagatingProviderKey); ok {
+ if dep, ok := OtherModuleProvider(ctx, module, AconfigPropagatingProviderKey); ok {
for container, v := range dep.AconfigFiles {
mergedAconfigFiles[container] = append(mergedAconfigFiles[container], v...)
}
propagateModeInfos(ctx, module, mergedModeInfos, dep.ModeInfos)
}
- if dep, ok := OtherModuleProvider(ctx, module, AconfigTransitiveDeclarationsInfoProvider); ok {
- for container, v := range dep.AconfigFiles {
- mergedAconfigFiles[container] = append(mergedAconfigFiles[container], v...)
- }
- }
})
// We only need to set the provider if we have aconfig files.
if len(mergedAconfigFiles) > 0 {
@@ -178,15 +126,16 @@
mergedAconfigFiles[container] = mergeAconfigFiles(ctx, container, aconfigFiles, true)
}
- SetProvider(ctx, aconfigPropagatingProviderKey, aconfigPropagatingDeclarationsInfo{
+ SetProvider(ctx, AconfigPropagatingProviderKey, aconfigPropagatingDeclarationsInfo{
AconfigFiles: mergedAconfigFiles,
ModeInfos: mergedModeInfos,
})
+ ctx.Module().base().aconfigFilePaths = getAconfigFilePaths(ctx.Module().base(), mergedAconfigFiles)
}
}
func aconfigUpdateAndroidMkData(ctx fillInEntriesContext, mod Module, data *AndroidMkData) {
- info, ok := SingletonModuleProvider(ctx, mod, aconfigPropagatingProviderKey)
+ info, ok := SingletonModuleProvider(ctx, mod, AconfigPropagatingProviderKey)
// If there is no aconfigPropagatingProvider, or there are no AconfigFiles, then we are done.
if !ok || len(info.AconfigFiles) == 0 {
return
@@ -217,7 +166,7 @@
if len(*entries) == 0 {
return
}
- info, ok := SingletonModuleProvider(ctx, mod, aconfigPropagatingProviderKey)
+ info, ok := SingletonModuleProvider(ctx, mod, AconfigPropagatingProviderKey)
if !ok || len(info.AconfigFiles) == 0 {
return
}
@@ -225,7 +174,7 @@
for idx, _ := range *entries {
(*entries)[idx].ExtraEntries = append((*entries)[idx].ExtraEntries,
func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries) {
- setAconfigFileMkEntries(mod.base(), entries, info.AconfigFiles)
+ entries.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths(mod.base(), info.AconfigFiles))
},
)
@@ -255,10 +204,6 @@
return Paths{output}
}
-func setAconfigFileMkEntries(m *ModuleBase, entries *AndroidMkEntries, aconfigFiles map[string]Paths) {
- entries.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths(m, aconfigFiles))
-}
-
func getAconfigFilePaths(m *ModuleBase, aconfigFiles map[string]Paths) (paths Paths) {
// TODO(b/311155208): The default container here should be system.
container := "system"
diff --git a/android/androidmk.go b/android/androidmk.go
index 07f7c58..66f42f9 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -36,6 +36,7 @@
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/pathtools"
+ "github.com/google/blueprint/proptools"
)
func init() {
@@ -541,6 +542,11 @@
a.SetPath("LOCAL_SOONG_INSTALLED_MODULE", base.katiInstalls[len(base.katiInstalls)-1].to)
a.SetString("LOCAL_SOONG_INSTALL_PAIRS", base.katiInstalls.BuiltInstalled())
a.SetPaths("LOCAL_SOONG_INSTALL_SYMLINKS", base.katiSymlinks.InstallPaths().Paths())
+ } else {
+ // Soong may not have generated the install rule also when `no_full_install: true`.
+ // Mark this module as uninstallable in order to prevent Make from creating an
+ // install rule there.
+ a.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", proptools.Bool(base.commonProperties.No_full_install))
}
if len(base.testData) > 0 {
@@ -849,7 +855,7 @@
mod blueprint.Module, provider AndroidMkDataProvider) error {
amod := mod.(Module).base()
- if shouldSkipAndroidMkProcessing(amod) {
+ if shouldSkipAndroidMkProcessing(ctx, amod) {
return nil
}
@@ -939,7 +945,7 @@
func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON,
mod blueprint.Module, provider AndroidMkEntriesProvider) error {
- if shouldSkipAndroidMkProcessing(mod.(Module).base()) {
+ if shouldSkipAndroidMkProcessing(ctx, mod.(Module).base()) {
return nil
}
@@ -961,11 +967,11 @@
return nil
}
-func ShouldSkipAndroidMkProcessing(module Module) bool {
- return shouldSkipAndroidMkProcessing(module.base())
+func ShouldSkipAndroidMkProcessing(ctx ConfigAndErrorContext, module Module) bool {
+ return shouldSkipAndroidMkProcessing(ctx, module.base())
}
-func shouldSkipAndroidMkProcessing(module *ModuleBase) bool {
+func shouldSkipAndroidMkProcessing(ctx ConfigAndErrorContext, module *ModuleBase) bool {
if !module.commonProperties.NamespaceExportedToMake {
// TODO(jeffrygaston) do we want to validate that there are no modules being
// exported to Kati that depend on this module?
@@ -984,7 +990,7 @@
return true
}
- return !module.Enabled() ||
+ return !module.Enabled(ctx) ||
module.commonProperties.HideFromMake ||
// Make does not understand LinuxBionic
module.Os() == LinuxBionic ||
diff --git a/android/apex_contributions.go b/android/apex_contributions.go
index f5c50d3..91549e5 100644
--- a/android/apex_contributions.go
+++ b/android/apex_contributions.go
@@ -101,12 +101,12 @@
}
var (
- acDepTag = apexContributionsDepTag{}
+ AcDepTag = apexContributionsDepTag{}
)
// Creates a dep to each selected apex_contributions
func (a *allApexContributions) DepsMutator(ctx BottomUpMutatorContext) {
- ctx.AddDependency(ctx.Module(), acDepTag, ctx.Config().AllApexContributions()...)
+ ctx.AddDependency(ctx.Module(), AcDepTag, ctx.Config().AllApexContributions()...)
}
// Set PrebuiltSelectionInfoProvider in post deps phase
@@ -131,7 +131,7 @@
// (e.g. shiba and shiba_fullmte)
// Eventually these product variants will have their own release config maps.
if !proptools.Bool(ctx.Config().BuildIgnoreApexContributionContents()) {
- ctx.VisitDirectDepsWithTag(acDepTag, func(child Module) {
+ ctx.VisitDirectDepsWithTag(AcDepTag, func(child Module) {
if m, ok := child.(*apexContributions); ok {
addContentsToProvider(&p, m)
} else {
diff --git a/android/arch.go b/android/arch.go
index cd8882b..e0c6908 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -486,7 +486,7 @@
// dependencies on OsType variants that are explicitly disabled in their
// properties. The CommonOS variant will still depend on disabled variants
// if they are disabled afterwards, e.g. in archMutator if
- if module.Enabled() {
+ if module.Enabled(mctx) {
mctx.AddInterVariantDependency(commonOsToOsSpecificVariantTag, commonOSVariant, module)
}
}
@@ -511,7 +511,7 @@
var variants []Module
mctx.VisitDirectDeps(func(m Module) {
if mctx.OtherModuleDependencyTag(m) == commonOsToOsSpecificVariantTag {
- if m.Enabled() {
+ if m.Enabled(mctx) {
variants = append(variants, m)
}
}
diff --git a/android/arch_test.go b/android/arch_test.go
index 5021a67..f0a58a9 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -423,7 +423,7 @@
variants := ctx.ModuleVariantsForTests(name)
for _, variant := range variants {
m := ctx.ModuleForTests(name, variant)
- if m.Module().Enabled() {
+ if m.Module().Enabled(PanickingConfigAndErrorContext(ctx)) {
ret = append(ret, variant)
}
}
@@ -533,7 +533,7 @@
variants := ctx.ModuleVariantsForTests(name)
for _, variant := range variants {
m := ctx.ModuleForTests(name, variant)
- if m.Module().Enabled() {
+ if m.Module().Enabled(PanickingConfigAndErrorContext(ctx)) {
ret = append(ret, variant)
}
}
diff --git a/android/base_module_context.go b/android/base_module_context.go
index c5fe585..5506000 100644
--- a/android/base_module_context.go
+++ b/android/base_module_context.go
@@ -325,7 +325,7 @@
return nil
}
- if !aModule.Enabled() {
+ if !aModule.Enabled(b) {
if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependency(aModule) {
if b.Config().AllowMissingDependencies() {
b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
@@ -536,7 +536,7 @@
return true
} else if tag == licensesTag {
return true
- } else if tag == acDepTag {
+ } else if tag == AcDepTag {
return true
}
return false
diff --git a/android/config.go b/android/config.go
index 3ea9d4d..76c590a 100644
--- a/android/config.go
+++ b/android/config.go
@@ -818,12 +818,12 @@
}
func (c *config) IsEnvTrue(key string) bool {
- value := c.Getenv(key)
+ value := strings.ToLower(c.Getenv(key))
return value == "1" || value == "y" || value == "yes" || value == "on" || value == "true"
}
func (c *config) IsEnvFalse(key string) bool {
- value := c.Getenv(key)
+ value := strings.ToLower(c.Getenv(key))
return value == "0" || value == "n" || value == "no" || value == "off" || value == "false"
}
@@ -2109,6 +2109,7 @@
"RELEASE_APEX_CONTRIBUTIONS_NEURALNETWORKS",
"RELEASE_APEX_CONTRIBUTIONS_ONDEVICEPERSONALIZATION",
"RELEASE_APEX_CONTRIBUTIONS_PERMISSION",
+ "RELEASE_APEX_CONTRIBUTIONS_PRIMARY_LIBS",
"RELEASE_APEX_CONTRIBUTIONS_REMOTEKEYPROVISIONING",
"RELEASE_APEX_CONTRIBUTIONS_RESOLV",
"RELEASE_APEX_CONTRIBUTIONS_SCHEDULING",
diff --git a/android/configurable_properties.go b/android/configurable_properties.go
new file mode 100644
index 0000000..dad42fa
--- /dev/null
+++ b/android/configurable_properties.go
@@ -0,0 +1,28 @@
+package android
+
+import "github.com/google/blueprint/proptools"
+
+// CreateSelectOsToBool is a utility function that makes it easy to create a
+// Configurable property value that maps from os to a bool. Use an empty string
+// to indicate a "default" case.
+func CreateSelectOsToBool(cases map[string]*bool) proptools.Configurable[bool] {
+ var resultCases []proptools.ConfigurableCase[bool]
+ for pattern, value := range cases {
+ if pattern == "" {
+ resultCases = append(resultCases, proptools.NewConfigurableCase(
+ []proptools.ConfigurablePattern{proptools.NewDefaultConfigurablePattern()},
+ value,
+ ))
+ } else {
+ resultCases = append(resultCases, proptools.NewConfigurableCase(
+ []proptools.ConfigurablePattern{proptools.NewStringConfigurablePattern(pattern)},
+ value,
+ ))
+ }
+ }
+
+ return proptools.NewConfigurable(
+ []proptools.ConfigurableCondition{proptools.NewConfigurableCondition("os", nil)},
+ resultCases,
+ )
+}
diff --git a/android/early_module_context.go b/android/early_module_context.go
index cf1b5fc..23f4c90 100644
--- a/android/early_module_context.go
+++ b/android/early_module_context.go
@@ -173,5 +173,5 @@
}
func (e *earlyModuleContext) OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{}) {
- e.EarlyModuleContext.OtherModulePropertyErrorf(module, property, fmt, args)
+ e.EarlyModuleContext.OtherModulePropertyErrorf(module, property, fmt, args...)
}
diff --git a/android/filegroup.go b/android/filegroup.go
index 86d7b4b..a8326d4 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -56,9 +56,6 @@
DefaultableModuleBase
properties fileGroupProperties
srcs Paths
-
- // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo
- mergedAconfigFiles map[string]Paths
}
var _ SourceFileProducer = (*fileGroup)(nil)
@@ -97,7 +94,6 @@
fg.srcs = PathsWithModuleSrcSubDir(ctx, fg.srcs, String(fg.properties.Path))
}
SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: fg.srcs.Strings()})
- CollectDependencyAconfigFiles(ctx, &fg.mergedAconfigFiles)
var aconfigDeclarations []string
var intermediateCacheOutputPaths Paths
diff --git a/android/gen_notice.go b/android/gen_notice.go
index 1acc638..6815f64 100644
--- a/android/gen_notice.go
+++ b/android/gen_notice.go
@@ -62,7 +62,7 @@
if mod == nil {
continue
}
- if !mod.Enabled() { // don't depend on variants without build rules
+ if !mod.Enabled(ctx) { // don't depend on variants without build rules
continue
}
modules = append(modules, mod)
diff --git a/android/license_metadata.go b/android/license_metadata.go
index eabb1b1..3fea029 100644
--- a/android/license_metadata.go
+++ b/android/license_metadata.go
@@ -36,7 +36,7 @@
func buildLicenseMetadata(ctx ModuleContext, licenseMetadataFile WritablePath) {
base := ctx.Module().base()
- if !base.Enabled() {
+ if !base.Enabled(ctx) {
return
}
@@ -69,7 +69,7 @@
if dep == nil {
return
}
- if !dep.Enabled() {
+ if !dep.Enabled(ctx) {
return
}
@@ -195,7 +195,7 @@
for _, path := range paths {
switch path.Ext() {
- case ".zip", ".tar", ".tgz", ".tar.gz", ".img", ".srcszip", ".apex":
+ case ".zip", ".tar", ".tgz", ".tar.gz", ".img", ".srcszip", ".apex", ".capex":
return true
}
}
diff --git a/android/logtags.go b/android/logtags.go
new file mode 100644
index 0000000..d11cccf
--- /dev/null
+++ b/android/logtags.go
@@ -0,0 +1,56 @@
+// 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 android
+
+import "github.com/google/blueprint"
+
+func init() {
+ RegisterParallelSingletonType("logtags", LogtagsSingleton)
+}
+
+type LogtagsInfo struct {
+ Logtags Paths
+}
+
+var LogtagsProviderKey = blueprint.NewProvider[*LogtagsInfo]()
+
+func LogtagsSingleton() Singleton {
+ return &logtagsSingleton{}
+}
+
+type logtagsSingleton struct{}
+
+func MergedLogtagsPath(ctx PathContext) OutputPath {
+ return PathForIntermediates(ctx, "all-event-log-tags.txt")
+}
+
+func (l *logtagsSingleton) GenerateBuildActions(ctx SingletonContext) {
+ var allLogtags Paths
+ ctx.VisitAllModules(func(module Module) {
+ if !module.ExportedToMake() {
+ return
+ }
+ if logtagsInfo, ok := SingletonModuleProvider(ctx, module, LogtagsProviderKey); ok {
+ allLogtags = append(allLogtags, logtagsInfo.Logtags...)
+ }
+ })
+
+ builder := NewRuleBuilder(pctx, ctx)
+ builder.Command().
+ BuiltTool("merge-event-log-tags").
+ FlagWithOutput("-o ", MergedLogtagsPath(ctx)).
+ Inputs(SortedUniquePaths(allLogtags))
+ builder.Build("all-event-log-tags.txt", "merge logtags")
+}
diff --git a/android/makevars.go b/android/makevars.go
index 4039e7e..f92f458 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -98,6 +98,7 @@
BlueprintFile(module blueprint.Module) string
ModuleErrorf(module blueprint.Module, format string, args ...interface{})
+ OtherModulePropertyErrorf(module Module, property, format string, args ...interface{})
Errorf(format string, args ...interface{})
VisitAllModules(visit func(Module))
@@ -265,7 +266,7 @@
}
ctx.VisitAllModules(func(m Module) {
- if provider, ok := m.(ModuleMakeVarsProvider); ok && m.Enabled() {
+ if provider, ok := m.(ModuleMakeVarsProvider); ok && m.Enabled(ctx) {
mctx := &makeVarsContext{
SingletonContext: ctx,
}
@@ -472,7 +473,7 @@
# Values written by Soong to generate install rules that can be amended by Kati.
-
+EXTRA_INSTALL_ZIPS :=
`)
preserveSymlinksFlag := "-d"
@@ -506,9 +507,13 @@
if extraFiles := install.extraFiles; extraFiles != nil {
fmt.Fprintf(buf, "\t( unzip -qDD -d '%s' '%s' 2>&1 | grep -v \"zipfile is empty\"; exit $${PIPESTATUS[0]} ) || \\\n", extraFiles.dir.String(), extraFiles.zip.String())
fmt.Fprintf(buf, "\t ( code=$$?; if [ $$code -ne 0 -a $$code -ne 1 ]; then exit $$code; fi )\n")
+ fmt.Fprintf(buf, "EXTRA_INSTALL_ZIPS += %s:%s:%s\n", install.to.String(), extraFiles.dir.String(), extraFiles.zip.String())
}
+
fmt.Fprintln(buf)
}
+ fmt.Fprintf(buf, ".KATI_READONLY := EXTRA_INSTALL_ZIPS\n")
+ fmt.Fprintf(buf, "$(KATI_visibility_prefix EXTRA_INSTALL_ZIPS,build/make/core/Makefile)\n")
for _, symlink := range symlinks {
fmt.Fprintf(buf, "%s:", symlink.to.String())
diff --git a/android/module.go b/android/module.go
index effca03..d4e4c2d 100644
--- a/android/module.go
+++ b/android/module.go
@@ -60,7 +60,7 @@
base() *ModuleBase
Disable()
- Enabled() bool
+ Enabled(ctx ConfigAndErrorContext) bool
Target() Target
MultiTargets() []Target
@@ -287,7 +287,7 @@
// but are not usually required (e.g. superceded by a prebuilt) should not be
// disabled as that will prevent them from being built by the checkbuild target
// and so prevent early detection of changes that have broken those modules.
- Enabled *bool `android:"arch_variant"`
+ Enabled proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"`
// Controls the visibility of this module to other modules. Allowable values are one or more of
// these formats:
@@ -484,6 +484,11 @@
// Set by osMutator.
CommonOSVariant bool `blueprint:"mutated"`
+ // When set to true, this module is not installed to the full install path (ex: under
+ // out/target/product/<name>/<partition>). It can be installed only to the packaging
+ // modules like android_filesystem.
+ No_full_install *bool
+
// When HideFromMake is set to true, no entry for this variant will be emitted in the
// generated Android.mk file.
HideFromMake bool `blueprint:"mutated"`
@@ -897,6 +902,9 @@
installedInitRcPaths InstallPaths
installedVintfFragmentsPaths InstallPaths
+ // Merged Aconfig files for all transitive deps.
+ aconfigFilePaths Paths
+
// set of dependency module:location mappings used to populate the license metadata for
// apex containers.
licenseInstallMap []string
@@ -1061,7 +1069,8 @@
// TODO(jiyong): the Make-side does this only when the required module is a shared
// library or a native test.
bothInAndroid := ctx.Device() && target.Os.Class == Device
- nativeArch := InList(ctx.Arch().ArchType.Multilib, []string{"lib32", "lib64"})
+ nativeArch := InList(ctx.Arch().ArchType.Multilib, []string{"lib32", "lib64"}) &&
+ InList(target.Arch.ArchType.Multilib, []string{"lib32", "lib64"})
sameBitness := ctx.Arch().ArchType.Multilib == target.Arch.ArchType.Multilib
if bothInAndroid && nativeArch && !sameBitness {
return
@@ -1392,14 +1401,11 @@
return partition
}
-func (m *ModuleBase) Enabled() bool {
+func (m *ModuleBase) Enabled(ctx ConfigAndErrorContext) bool {
if m.commonProperties.ForcedDisabled {
return false
}
- if m.commonProperties.Enabled == nil {
- return !m.Os().DefaultDisabled
- }
- return *m.commonProperties.Enabled
+ return m.commonProperties.Enabled.GetOrDefault(m.ConfigurableEvaluator(ctx), !m.Os().DefaultDisabled)
}
func (m *ModuleBase) Disable() {
@@ -1643,7 +1649,7 @@
// not be created if the module is not exported to make.
// Those could depend on the build target and fail to compile
// for the current build target.
- if !ctx.Config().KatiEnabled() || !shouldSkipAndroidMkProcessing(a) {
+ if !ctx.Config().KatiEnabled() || !shouldSkipAndroidMkProcessing(ctx, a) {
allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...)
}
})
@@ -1835,7 +1841,7 @@
checkDistProperties(ctx, fmt.Sprintf("dists[%d]", i), &m.distProperties.Dists[i])
}
- if m.Enabled() {
+ if m.Enabled(ctx) {
// ensure all direct android.Module deps are enabled
ctx.VisitDirectDepsBlueprint(func(bm blueprint.Module) {
if m, ok := bm.(Module); ok {
@@ -1890,12 +1896,14 @@
}
}
- m.module.GenerateAndroidBuildActions(ctx)
+ // Call aconfigUpdateAndroidBuildActions to collect merged aconfig files before being used
+ // in m.module.GenerateAndroidBuildActions
+ aconfigUpdateAndroidBuildActions(ctx)
if ctx.Failed() {
return
}
- aconfigUpdateAndroidBuildActions(ctx)
+ m.module.GenerateAndroidBuildActions(ctx)
if ctx.Failed() {
return
}
@@ -2136,16 +2144,16 @@
}
func (e configurationEvalutor) PropertyErrorf(property string, fmt string, args ...interface{}) {
- e.ctx.OtherModulePropertyErrorf(e.m, property, fmt, args)
+ e.ctx.OtherModulePropertyErrorf(e.m, property, fmt, args...)
}
func (e configurationEvalutor) EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue {
ctx := e.ctx
m := e.m
switch condition.FunctionName() {
- case "release_variable":
+ case "release_flag":
if condition.NumArgs() != 1 {
- ctx.OtherModulePropertyErrorf(m, property, "release_variable requires 1 argument, found %d", condition.NumArgs())
+ ctx.OtherModulePropertyErrorf(m, property, "release_flag requires 1 argument, found %d", condition.NumArgs())
return proptools.ConfigurableValueUndefined()
}
if v, ok := ctx.Config().productVariables.BuildFlags[condition.Arg(0)]; ok {
@@ -2535,7 +2543,7 @@
}
osDeps := map[osAndCross]Paths{}
ctx.VisitAllModules(func(module Module) {
- if module.Enabled() {
+ if module.Enabled(ctx) {
key := osAndCross{os: module.Target().Os, hostCross: module.Target().HostCross}
osDeps[key] = append(osDeps[key], module.base().checkbuildFiles...)
}
diff --git a/android/module_context.go b/android/module_context.go
index dea22ba..18adb30 100644
--- a/android/module_context.go
+++ b/android/module_context.go
@@ -444,6 +444,21 @@
return false
}
+// Tells whether this module is installed to the full install path (ex:
+// out/target/product/<name>/<partition>) or not. If this returns false, the install build rule is
+// not created and this module can only be installed to packaging modules like android_filesystem.
+func (m *moduleContext) requiresFullInstall() bool {
+ if m.skipInstall() {
+ return false
+ }
+
+ if proptools.Bool(m.module.base().commonProperties.No_full_install) {
+ return false
+ }
+
+ return true
+}
+
func (m *moduleContext) InstallFile(installPath InstallPath, name string, srcPath Path,
deps ...InstallPath) InstallPath {
return m.installFile(installPath, name, srcPath, deps, false, true, nil)
@@ -467,6 +482,10 @@
return m.packageFile(fullInstallPath, srcPath, false)
}
+func (m *moduleContext) getAconfigPaths() *Paths {
+ return &m.module.base().aconfigFilePaths
+}
+
func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, executable bool) PackagingSpec {
licenseFiles := m.Module().EffectiveLicenseFiles()
spec := PackagingSpec{
@@ -477,6 +496,8 @@
effectiveLicenseFiles: &licenseFiles,
partition: fullInstallPath.partition,
skipInstall: m.skipInstall(),
+ aconfigPaths: m.getAconfigPaths(),
+ archType: m.target.Arch.ArchType,
}
m.packagingSpecs = append(m.packagingSpecs, spec)
return spec
@@ -490,7 +511,7 @@
m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, false)
}
- if !m.skipInstall() {
+ if m.requiresFullInstall() {
deps = append(deps, InstallPaths(m.module.base().installFilesDepSet.ToList())...)
deps = append(deps, m.module.base().installedInitRcPaths...)
deps = append(deps, m.module.base().installedVintfFragmentsPaths...)
@@ -563,7 +584,7 @@
if err != nil {
panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err))
}
- if !m.skipInstall() {
+ if m.requiresFullInstall() {
if m.Config().KatiEnabled() {
// When creating the symlink rule in Soong but embedding in Make, write the rule to a
@@ -601,6 +622,8 @@
executable: false,
partition: fullInstallPath.partition,
skipInstall: m.skipInstall(),
+ aconfigPaths: m.getAconfigPaths(),
+ archType: m.target.Arch.ArchType,
})
return fullInstallPath
@@ -612,7 +635,7 @@
fullInstallPath := installPath.Join(m, name)
m.module.base().hooks.runInstallHooks(m, nil, fullInstallPath, true)
- if !m.skipInstall() {
+ if m.requiresFullInstall() {
if m.Config().KatiEnabled() {
// When creating the symlink rule in Soong but embedding in Make, write the rule to a
// makefile instead of directly to the ninja file so that main.mk can add the
@@ -643,6 +666,8 @@
executable: false,
partition: fullInstallPath.partition,
skipInstall: m.skipInstall(),
+ aconfigPaths: m.getAconfigPaths(),
+ archType: m.target.Arch.ArchType,
})
return fullInstallPath
diff --git a/android/mutator.go b/android/mutator.go
index 75ba650..440b906 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -293,15 +293,14 @@
// WalkDeps, etc.
AddInterVariantDependency(tag blueprint.DependencyTag, from, to blueprint.Module)
- // ReplaceDependencies replaces all dependencies on the identical variant of the module with the
- // specified name with the current variant of this module. Replacements don't take effect until
- // after the mutator pass is finished.
+ // ReplaceDependencies finds all the variants of the module with the specified name, then
+ // replaces all dependencies onto those variants with the current variant of this module.
+ // Replacements don't take effect until after the mutator pass is finished.
ReplaceDependencies(string)
- // ReplaceDependencies replaces all dependencies on the identical variant of the module with the
- // specified name with the current variant of this module as long as the supplied predicate returns
- // true.
- //
+ // ReplaceDependenciesIf finds all the variants of the module with the specified name, then
+ // replaces all dependencies onto those variants with the current variant of this module
+ // as long as the supplied predicate returns true.
// Replacements don't take effect until after the mutator pass is finished.
ReplaceDependenciesIf(string, blueprint.ReplaceDependencyPredicate)
@@ -595,11 +594,16 @@
func (a *androidTransitionMutator) Mutate(ctx blueprint.BottomUpMutatorContext, variation string) {
if am, ok := ctx.Module().(Module); ok {
+ if variation != "" {
+ // TODO: this should really be checking whether the TransitionMutator affected this module, not
+ // the empty variant, but TransitionMutator has no concept of skipping a module.
+ base := am.base()
+ base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, a.name)
+ base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variation)
+ }
+
mctx := bottomUpMutatorContextFactory(ctx, am, a.finalPhase)
defer bottomUpMutatorContextPool.Put(mctx)
- base := am.base()
- base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, a.name)
- base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variation)
a.mutator.Mutate(mctx, variation)
}
}
@@ -674,13 +678,11 @@
// on component modules to be added so that they can depend directly on a prebuilt
// module.
func componentDepsMutator(ctx BottomUpMutatorContext) {
- if m := ctx.Module(); m.Enabled() {
- m.ComponentDepsMutator(ctx)
- }
+ ctx.Module().ComponentDepsMutator(ctx)
}
func depsMutator(ctx BottomUpMutatorContext) {
- if m := ctx.Module(); m.Enabled() {
+ if m := ctx.Module(); m.Enabled(ctx) {
m.base().baseDepsMutator(ctx)
m.DepsMutator(ctx)
}
diff --git a/android/override_module.go b/android/override_module.go
index 1341f53..21cf381 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -322,7 +322,7 @@
}
func overridableModuleDepsMutator(ctx BottomUpMutatorContext) {
- if b, ok := ctx.Module().(OverridableModule); ok && b.Enabled() {
+ if b, ok := ctx.Module().(OverridableModule); ok && b.Enabled(ctx) {
b.OverridablePropertiesDepsMutator(ctx)
}
}
diff --git a/android/packaging.go b/android/packaging.go
index 6677218..080dcfe 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -48,6 +48,31 @@
// is created via InstallFile or InstallSymlink) or a simple packaging (i.e. created via
// PackageFile).
skipInstall bool
+
+ // Paths of aconfig files for the built artifact
+ aconfigPaths *Paths
+
+ // ArchType of the module which produced this packaging spec
+ archType ArchType
+}
+
+func (p *PackagingSpec) Equals(other *PackagingSpec) bool {
+ if other == nil {
+ return false
+ }
+ if p.relPathInPackage != other.relPathInPackage {
+ return false
+ }
+ if p.srcPath != other.srcPath || p.symlinkTarget != other.symlinkTarget {
+ return false
+ }
+ if p.executable != other.executable {
+ return false
+ }
+ if p.partition != other.partition {
+ return false
+ }
+ return true
}
// Get file name of installed package
@@ -83,6 +108,11 @@
return p.skipInstall
}
+// Paths of aconfig files for the built artifact
+func (p *PackagingSpec) GetAconfigPaths() Paths {
+ return *p.aconfigPaths
+}
+
type PackageModule interface {
Module
packagingBase() *PackagingBase
@@ -112,6 +142,10 @@
// for rare cases like when there's a dependency to a module which exists in certain repo
// checkouts, this is needed.
IgnoreMissingDependencies bool
+
+ // If this is set to true by a module type inheriting PackagingBase, the deps property
+ // collects the first target only even with compile_multilib: true.
+ DepsCollectFirstTargetOnly bool
}
type depsProperty struct {
@@ -124,6 +158,7 @@
Common depsProperty `android:"arch_variant"`
Lib32 depsProperty `android:"arch_variant"`
Lib64 depsProperty `android:"arch_variant"`
+ Both depsProperty `android:"arch_variant"`
}
type packagingArchProperties struct {
@@ -164,11 +199,28 @@
ret = append(ret, p.properties.Multilib.Common.Deps...)
}
- for i, t := range ctx.MultiTargets() {
- if t.Arch.ArchType == arch {
- ret = append(ret, p.properties.Deps...)
- if i == 0 {
- ret = append(ret, p.properties.Multilib.First.Deps...)
+ if p.DepsCollectFirstTargetOnly {
+ if len(p.properties.Multilib.First.Deps) > 0 {
+ ctx.PropertyErrorf("multilib.first.deps", "not supported. use \"deps\" instead")
+ }
+ for i, t := range ctx.MultiTargets() {
+ if t.Arch.ArchType == arch {
+ ret = append(ret, p.properties.Multilib.Both.Deps...)
+ if i == 0 {
+ ret = append(ret, p.properties.Deps...)
+ }
+ }
+ }
+ } else {
+ if len(p.properties.Multilib.Both.Deps) > 0 {
+ ctx.PropertyErrorf("multilib.both.deps", "not supported. use \"deps\" instead")
+ }
+ for i, t := range ctx.MultiTargets() {
+ if t.Arch.ArchType == arch {
+ ret = append(ret, p.properties.Deps...)
+ if i == 0 {
+ ret = append(ret, p.properties.Multilib.First.Deps...)
+ }
}
}
}
@@ -233,19 +285,45 @@
func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec {
m := make(map[string]PackagingSpec)
+
+ var arches []ArchType
+ for _, target := range p.getSupportedTargets(ctx) {
+ arches = append(arches, target.Arch.ArchType)
+ }
+
+ // filter out packaging specs for unsupported architecture
+ filterArch := func(ps PackagingSpec) bool {
+ for _, arch := range arches {
+ if arch == ps.archType {
+ return true
+ }
+ }
+ return false
+ }
+
ctx.VisitDirectDeps(func(child Module) {
if pi, ok := ctx.OtherModuleDependencyTag(child).(PackagingItem); !ok || !pi.IsPackagingItem() {
return
}
for _, ps := range child.TransitivePackagingSpecs() {
+ if !filterArch(ps) {
+ continue
+ }
+
if filter != nil {
if !filter(ps) {
continue
}
}
- if _, ok := m[ps.relPathInPackage]; !ok {
- m[ps.relPathInPackage] = ps
+ dstPath := ps.relPathInPackage
+ if existingPs, ok := m[dstPath]; ok {
+ if !existingPs.Equals(&ps) {
+ ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
+ }
+ continue
}
+
+ m[dstPath] = ps
}
})
return m
diff --git a/android/packaging_test.go b/android/packaging_test.go
index 3833437..f99bb91 100644
--- a/android/packaging_test.go
+++ b/android/packaging_test.go
@@ -67,18 +67,15 @@
entries []string
}
-func packageMultiTargetTestModuleFactory() Module {
+func packageTestModuleFactory(multiTarget bool, depsCollectFirstTargetOnly bool) Module {
module := &packageTestModule{}
InitPackageModule(module)
- InitAndroidMultiTargetsArchModule(module, DeviceSupported, MultilibCommon)
- module.AddProperties(&module.properties)
- return module
-}
-
-func packageTestModuleFactory() Module {
- module := &packageTestModule{}
- InitPackageModule(module)
- InitAndroidArchModule(module, DeviceSupported, MultilibBoth)
+ module.DepsCollectFirstTargetOnly = depsCollectFirstTargetOnly
+ if multiTarget {
+ InitAndroidMultiTargetsArchModule(module, DeviceSupported, MultilibCommon)
+ } else {
+ InitAndroidArchModule(module, DeviceSupported, MultilibBoth)
+ }
module.AddProperties(&module.properties)
return module
}
@@ -98,17 +95,23 @@
m.entries = m.CopyDepsToZip(ctx, m.GatherPackagingSpecs(ctx), zipFile)
}
-func runPackagingTest(t *testing.T, multitarget bool, bp string, expected []string) {
+type packageTestModuleConfig struct {
+ multiTarget bool
+ depsCollectFirstTargetOnly bool
+}
+
+func runPackagingTest(t *testing.T, config packageTestModuleConfig, bp string, expected []string) {
t.Helper()
var archVariant string
- var moduleFactory ModuleFactory
- if multitarget {
+ if config.multiTarget {
archVariant = "android_common"
- moduleFactory = packageMultiTargetTestModuleFactory
} else {
archVariant = "android_arm64_armv8-a"
- moduleFactory = packageTestModuleFactory
+ }
+
+ moduleFactory := func() Module {
+ return packageTestModuleFactory(config.multiTarget, config.depsCollectFirstTargetOnly)
}
result := GroupFixturePreparers(
@@ -128,8 +131,11 @@
}
func TestPackagingBaseMultiTarget(t *testing.T) {
- multiTarget := true
- runPackagingTest(t, multiTarget,
+ config := packageTestModuleConfig{
+ multiTarget: true,
+ depsCollectFirstTargetOnly: false,
+ }
+ runPackagingTest(t, config,
`
component {
name: "foo",
@@ -141,7 +147,7 @@
}
`, []string{"lib64/foo"})
- runPackagingTest(t, multiTarget,
+ runPackagingTest(t, config,
`
component {
name: "foo",
@@ -158,7 +164,7 @@
}
`, []string{"lib64/foo", "lib64/bar"})
- runPackagingTest(t, multiTarget,
+ runPackagingTest(t, config,
`
component {
name: "foo",
@@ -176,7 +182,7 @@
}
`, []string{"lib32/foo", "lib32/bar", "lib64/foo", "lib64/bar"})
- runPackagingTest(t, multiTarget,
+ runPackagingTest(t, config,
`
component {
name: "foo",
@@ -199,7 +205,7 @@
}
`, []string{"lib32/foo", "lib32/bar", "lib64/foo"})
- runPackagingTest(t, multiTarget,
+ runPackagingTest(t, config,
`
component {
name: "foo",
@@ -221,7 +227,7 @@
}
`, []string{"lib32/foo", "lib64/foo", "lib64/bar"})
- runPackagingTest(t, multiTarget,
+ runPackagingTest(t, config,
`
component {
name: "foo",
@@ -252,8 +258,11 @@
}
func TestPackagingBaseSingleTarget(t *testing.T) {
- multiTarget := false
- runPackagingTest(t, multiTarget,
+ config := packageTestModuleConfig{
+ multiTarget: false,
+ depsCollectFirstTargetOnly: false,
+ }
+ runPackagingTest(t, config,
`
component {
name: "foo",
@@ -265,7 +274,7 @@
}
`, []string{"lib64/foo"})
- runPackagingTest(t, multiTarget,
+ runPackagingTest(t, config,
`
component {
name: "foo",
@@ -282,7 +291,7 @@
}
`, []string{"lib64/foo", "lib64/bar"})
- runPackagingTest(t, multiTarget,
+ runPackagingTest(t, config,
`
component {
name: "foo",
@@ -304,7 +313,7 @@
}
`, []string{"lib64/foo"})
- runPackagingTest(t, multiTarget,
+ runPackagingTest(t, config,
`
component {
name: "foo",
@@ -325,7 +334,7 @@
}
`, []string{"lib64/foo", "lib64/bar"})
- runPackagingTest(t, multiTarget,
+ runPackagingTest(t, config,
`
component {
name: "foo",
@@ -353,7 +362,7 @@
}
`, []string{"lib64/foo", "lib64/bar"})
- runPackagingTest(t, multiTarget,
+ runPackagingTest(t, config,
`
component {
name: "foo",
@@ -374,8 +383,11 @@
func TestPackagingWithSkipInstallDeps(t *testing.T) {
// package -[dep]-> foo -[dep]-> bar -[dep]-> baz
// Packaging should continue transitively through modules that are not installed.
- multiTarget := false
- runPackagingTest(t, multiTarget,
+ config := packageTestModuleConfig{
+ multiTarget: false,
+ depsCollectFirstTargetOnly: false,
+ }
+ runPackagingTest(t, config,
`
component {
name: "foo",
@@ -398,3 +410,130 @@
}
`, []string{"lib64/foo", "lib64/bar", "lib64/baz"})
}
+
+func TestPackagingWithDepsCollectFirstTargetOnly(t *testing.T) {
+ config := packageTestModuleConfig{
+ multiTarget: true,
+ depsCollectFirstTargetOnly: true,
+ }
+ runPackagingTest(t, config,
+ `
+ component {
+ name: "foo",
+ }
+
+ package_module {
+ name: "package",
+ deps: ["foo"],
+ }
+ `, []string{"lib64/foo"})
+
+ runPackagingTest(t, config,
+ `
+ component {
+ name: "foo",
+ deps: ["bar"],
+ }
+
+ component {
+ name: "bar",
+ }
+
+ package_module {
+ name: "package",
+ deps: ["foo"],
+ }
+ `, []string{"lib64/foo", "lib64/bar"})
+
+ runPackagingTest(t, config,
+ `
+ component {
+ name: "foo",
+ deps: ["bar"],
+ }
+
+ component {
+ name: "bar",
+ }
+
+ package_module {
+ name: "package",
+ deps: ["foo"],
+ compile_multilib: "both",
+ }
+ `, []string{"lib64/foo", "lib64/bar"})
+
+ runPackagingTest(t, config,
+ `
+ component {
+ name: "foo",
+ }
+
+ component {
+ name: "bar",
+ compile_multilib: "32",
+ }
+
+ package_module {
+ name: "package",
+ deps: ["foo"],
+ multilib: {
+ lib32: {
+ deps: ["bar"],
+ },
+ },
+ compile_multilib: "both",
+ }
+ `, []string{"lib32/bar", "lib64/foo"})
+
+ runPackagingTest(t, config,
+ `
+ component {
+ name: "foo",
+ }
+
+ component {
+ name: "bar",
+ }
+
+ package_module {
+ name: "package",
+ deps: ["foo"],
+ multilib: {
+ both: {
+ deps: ["bar"],
+ },
+ },
+ compile_multilib: "both",
+ }
+ `, []string{"lib64/foo", "lib32/bar", "lib64/bar"})
+
+ runPackagingTest(t, config,
+ `
+ component {
+ name: "foo",
+ }
+
+ component {
+ name: "bar",
+ }
+
+ component {
+ name: "baz",
+ }
+
+ package_module {
+ name: "package",
+ deps: ["foo"],
+ arch: {
+ arm64: {
+ deps: ["bar"],
+ },
+ x86_64: {
+ deps: ["baz"],
+ },
+ },
+ compile_multilib: "both",
+ }
+ `, []string{"lib64/foo", "lib64/bar"})
+}
diff --git a/android/paths.go b/android/paths.go
index 2b33f67..8d92aa4 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -60,6 +60,7 @@
ModuleDir() string
ModuleErrorf(fmt string, args ...interface{})
+ OtherModulePropertyErrorf(module Module, property, fmt string, args ...interface{})
}
var _ EarlyModulePathContext = ModuleContext(nil)
@@ -277,6 +278,7 @@
type genPathProvider interface {
genPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleGenPath
+ genPathWithExtAndTrimExt(ctx ModuleOutPathContext, subdir, ext string, trimExt string) ModuleGenPath
}
type objPathProvider interface {
objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath
@@ -295,6 +297,16 @@
return PathForModuleGen(ctx)
}
+// GenPathWithExtAndTrimExt derives a new file path in ctx's generated sources directory
+// from the current path, but with the new extension and trim the suffix.
+func GenPathWithExtAndTrimExt(ctx ModuleOutPathContext, subdir string, p Path, ext string, trimExt string) ModuleGenPath {
+ if path, ok := p.(genPathProvider); ok {
+ return path.genPathWithExtAndTrimExt(ctx, subdir, ext, trimExt)
+ }
+ ReportPathErrorf(ctx, "Tried to create generated file from unsupported path: %s(%s)", reflect.TypeOf(p).Name(), p)
+ return PathForModuleGen(ctx)
+}
+
// ObjPathWithExt derives a new file path in ctx's object directory from the
// current path, but with the new extension.
func ObjPathWithExt(ctx ModuleOutPathContext, subdir string, p Path, ext string) ModuleObjPath {
@@ -550,7 +562,7 @@
if module == nil {
return nil, missingDependencyError{[]string{moduleName}}
}
- if aModule, ok := module.(Module); ok && !aModule.Enabled() {
+ if aModule, ok := module.(Module); ok && !aModule.Enabled(ctx) {
return nil, missingDependencyError{[]string{moduleName}}
}
if outProducer, ok := module.(OutputFileProducer); ok {
@@ -1507,6 +1519,17 @@
return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
}
+func (p SourcePath) genPathWithExtAndTrimExt(ctx ModuleOutPathContext, subdir, ext string, trimExt string) ModuleGenPath {
+ // If Trim_extension being set, force append Output_extension without replace original extension.
+ if trimExt != "" {
+ if ext != "" {
+ return PathForModuleGen(ctx, subdir, strings.TrimSuffix(p.path, trimExt)+"."+ext)
+ }
+ return PathForModuleGen(ctx, subdir, strings.TrimSuffix(p.path, trimExt))
+ }
+ return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
+}
+
func (p SourcePath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath {
return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
}
@@ -1594,6 +1617,17 @@
return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
}
+func (p ModuleGenPath) genPathWithExtAndTrimExt(ctx ModuleOutPathContext, subdir, ext string, trimExt string) ModuleGenPath {
+ // If Trim_extension being set, force append Output_extension without replace original extension.
+ if trimExt != "" {
+ if ext != "" {
+ return PathForModuleGen(ctx, subdir, strings.TrimSuffix(p.path, trimExt)+"."+ext)
+ }
+ return PathForModuleGen(ctx, subdir, strings.TrimSuffix(p.path, trimExt))
+ }
+ return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
+}
+
func (p ModuleGenPath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath {
return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
}
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 2b7b55b..51b86a5 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -275,7 +275,7 @@
srcPropertyName := proptools.PropertyNameForField(srcField)
srcsSupplier := func(ctx BaseModuleContext, _ Module) []string {
- if !module.Enabled() {
+ if !module.Enabled(ctx) {
return nil
}
value := srcPropsValue.FieldByIndex(srcFieldIndex)
@@ -425,7 +425,7 @@
m := ctx.Module()
// If this module is a prebuilt, is enabled and has not been renamed to source then add a
// dependency onto the source if it is present.
- if p := GetEmbeddedPrebuilt(m); p != nil && m.Enabled() && !p.properties.PrebuiltRenamedToSource {
+ if p := GetEmbeddedPrebuilt(m); p != nil && m.Enabled(ctx) && !p.properties.PrebuiltRenamedToSource {
bmn, _ := m.(baseModuleName)
name := bmn.BaseModuleName()
if ctx.OtherModuleReverseDependencyVariantExists(name) {
@@ -437,7 +437,7 @@
// TODO: When all branches contain this singleton module, make this strict
// TODO: Add this dependency only for mainline prebuilts and not every prebuilt module
if ctx.OtherModuleExists("all_apex_contributions") {
- ctx.AddDependency(m, acDepTag, "all_apex_contributions")
+ ctx.AddDependency(m, AcDepTag, "all_apex_contributions")
}
}
@@ -474,7 +474,7 @@
}
// Propagate the provider received from `all_apex_contributions`
// to the source module
- ctx.VisitDirectDepsWithTag(acDepTag, func(am Module) {
+ ctx.VisitDirectDepsWithTag(AcDepTag, func(am Module) {
psi, _ := OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider)
SetProvider(ctx, PrebuiltSelectionInfoProvider, psi)
})
@@ -580,7 +580,7 @@
bmn, _ := m.(baseModuleName)
name := bmn.BaseModuleName()
psi := PrebuiltSelectionInfoMap{}
- ctx.VisitDirectDepsWithTag(acDepTag, func(am Module) {
+ ctx.VisitDirectDepsWithTag(AcDepTag, func(am Module) {
psi, _ = OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider)
})
@@ -702,7 +702,7 @@
}
// If source is not available or is disabled then always use the prebuilt.
- if source == nil || !source.Enabled() {
+ if source == nil || !source.Enabled(ctx) {
return true
}
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index 575b926..d775ac3 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -351,7 +351,7 @@
}
})
- moduleIsDisabled := !foo.Module().Enabled()
+ moduleIsDisabled := !foo.Module().Enabled(PanickingConfigAndErrorContext(result.TestContext))
deps := foo.Module().(*sourceModule).deps
if moduleIsDisabled {
if len(deps) > 0 {
diff --git a/android/register.go b/android/register.go
index d00c15f..aeb3b4c 100644
--- a/android/register.go
+++ b/android/register.go
@@ -16,8 +16,9 @@
import (
"fmt"
- "github.com/google/blueprint"
"reflect"
+
+ "github.com/google/blueprint"
)
// A sortable component is one whose registration order affects the order in which it is executed
diff --git a/android/sdk_version.go b/android/sdk_version.go
index b2ff960..01b55d0 100644
--- a/android/sdk_version.go
+++ b/android/sdk_version.go
@@ -40,9 +40,15 @@
// SdkKind represents a particular category of an SDK spec like public, system, test, etc.
type SdkKind int
+// These are generally ordered from the narrower sdk version to the wider sdk version,
+// but not all entries have a strict subset/superset relationship.
+// For example, SdkTest and SdkModule do not have a strict subset/superset relationship but both
+// are supersets of SdkSystem.
+// The general trend should be kept when an additional sdk kind is added.
const (
SdkInvalid SdkKind = iota
SdkNone
+ SdkToolchain // API surface provided by ART to compile other API domains
SdkCore
SdkCorePlatform
SdkIntraCore // API surface provided by one core module to another
@@ -53,7 +59,6 @@
SdkModule
SdkSystemServer
SdkPrivate
- SdkToolchain // API surface provided by ART to compile other API domains
)
// String returns the string representation of this SdkKind
diff --git a/android/selects_test.go b/android/selects_test.go
index 8563285..d9499a5 100644
--- a/android/selects_test.go
+++ b/android/selects_test.go
@@ -633,6 +633,61 @@
},
expectedError: "Expected all branches of a select on condition boolean_var_for_testing\\(\\) to have type bool, found string",
},
+ {
+ name: "Assigning select to nonconfigurable bool",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_nonconfigurable_bool: select(arch(), {
+ "x86_64": true,
+ default: false,
+ }),
+ }
+ `,
+ expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_bool"`,
+ },
+ {
+ name: "Assigning select to nonconfigurable string",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_nonconfigurable_string: select(arch(), {
+ "x86_64": "x86!",
+ default: "unknown!",
+ }),
+ }
+ `,
+ expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string"`,
+ },
+ {
+ name: "Assigning appended selects to nonconfigurable string",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_nonconfigurable_string: select(arch(), {
+ "x86_64": "x86!",
+ default: "unknown!",
+ }) + select(os(), {
+ "darwin": "_darwin!",
+ default: "unknown!",
+ }),
+ }
+ `,
+ expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string"`,
+ },
+ {
+ name: "Assigning select to nonconfigurable string list",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_nonconfigurable_string_list: select(arch(), {
+ "x86_64": ["foo", "bar"],
+ default: ["baz", "qux"],
+ }),
+ }
+ `,
+ expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string_list"`,
+ },
}
for _, tc := range testCases {
@@ -674,11 +729,14 @@
}
type selectsTestProvider struct {
- my_bool *bool
- my_string *string
- my_string_list *[]string
- my_paths *[]string
- replacing_string_list *[]string
+ my_bool *bool
+ my_string *string
+ my_string_list *[]string
+ my_paths *[]string
+ replacing_string_list *[]string
+ my_nonconfigurable_bool *bool
+ my_nonconfigurable_string *string
+ my_nonconfigurable_string_list []string
}
func (p *selectsTestProvider) String() string {
@@ -690,23 +748,42 @@
if p.my_string != nil {
myStringStr = *p.my_string
}
+ myNonconfigurableStringStr := "nil"
+ if p.my_string != nil {
+ myNonconfigurableStringStr = *p.my_nonconfigurable_string
+ }
return fmt.Sprintf(`selectsTestProvider {
my_bool: %v,
my_string: %s,
my_string_list: %s,
my_paths: %s,
replacing_string_list %s,
-}`, myBoolStr, myStringStr, p.my_string_list, p.my_paths, p.replacing_string_list)
+ my_nonconfigurable_bool: %v,
+ my_nonconfigurable_string: %s,
+ my_nonconfigurable_string_list: %s,
+}`,
+ myBoolStr,
+ myStringStr,
+ p.my_string_list,
+ p.my_paths,
+ p.replacing_string_list,
+ p.my_nonconfigurable_bool,
+ myNonconfigurableStringStr,
+ p.my_nonconfigurable_string_list,
+ )
}
var selectsTestProviderKey = blueprint.NewProvider[selectsTestProvider]()
type selectsMockModuleProperties struct {
- My_bool proptools.Configurable[bool]
- My_string proptools.Configurable[string]
- My_string_list proptools.Configurable[[]string]
- My_paths proptools.Configurable[[]string] `android:"path"`
- Replacing_string_list proptools.Configurable[[]string] `android:"replace_instead_of_append,arch_variant"`
+ My_bool proptools.Configurable[bool]
+ My_string proptools.Configurable[string]
+ My_string_list proptools.Configurable[[]string]
+ My_paths proptools.Configurable[[]string] `android:"path"`
+ Replacing_string_list proptools.Configurable[[]string] `android:"replace_instead_of_append,arch_variant"`
+ My_nonconfigurable_bool *bool
+ My_nonconfigurable_string *string
+ My_nonconfigurable_string_list []string
}
type selectsMockModule struct {
@@ -717,11 +794,14 @@
func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) {
SetProvider(ctx, selectsTestProviderKey, selectsTestProvider{
- my_bool: p.properties.My_bool.Get(ctx),
- my_string: p.properties.My_string.Get(ctx),
- my_string_list: p.properties.My_string_list.Get(ctx),
- my_paths: p.properties.My_paths.Get(ctx),
- replacing_string_list: p.properties.Replacing_string_list.Get(ctx),
+ my_bool: p.properties.My_bool.Get(ctx),
+ my_string: p.properties.My_string.Get(ctx),
+ my_string_list: p.properties.My_string_list.Get(ctx),
+ my_paths: p.properties.My_paths.Get(ctx),
+ replacing_string_list: p.properties.Replacing_string_list.Get(ctx),
+ my_nonconfigurable_bool: p.properties.My_nonconfigurable_bool,
+ my_nonconfigurable_string: p.properties.My_nonconfigurable_string,
+ my_nonconfigurable_string_list: p.properties.My_nonconfigurable_string_list,
})
}
diff --git a/android/singleton.go b/android/singleton.go
index 76df1eb..d364384 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -284,5 +284,5 @@
}
func (s *singletonContextAdaptor) OtherModulePropertyErrorf(module Module, property string, format string, args ...interface{}) {
- s.blueprintSingletonContext().OtherModulePropertyErrorf(module, property, format, args)
+ s.blueprintSingletonContext().OtherModulePropertyErrorf(module, property, format, args...)
}
diff --git a/android/testing.go b/android/testing.go
index 7b4411e..6518f4a 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -1122,7 +1122,7 @@
entriesList := p.AndroidMkEntries()
aconfigUpdateAndroidMkEntries(ctx, mod.(Module), &entriesList)
- for i, _ := range entriesList {
+ for i := range entriesList {
entriesList[i].fillInEntries(ctx, mod)
}
return entriesList
@@ -1287,3 +1287,21 @@
t.Errorf("%q is not found in %v", expected, result)
}
}
+
+type panickingConfigAndErrorContext struct {
+ ctx *TestContext
+}
+
+func (ctx *panickingConfigAndErrorContext) OtherModulePropertyErrorf(module Module, property, fmt string, args ...interface{}) {
+ panic(ctx.ctx.PropertyErrorf(module, property, fmt, args...).Error())
+}
+
+func (ctx *panickingConfigAndErrorContext) Config() Config {
+ return ctx.ctx.Config()
+}
+
+func PanickingConfigAndErrorContext(ctx *TestContext) ConfigAndErrorContext {
+ return &panickingConfigAndErrorContext{
+ ctx: ctx,
+ }
+}
diff --git a/android/variable.go b/android/variable.go
index 599f88e..419bd61 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -58,16 +58,16 @@
// unbundled_build is a catch-all property to annotate modules that don't build in one or
// more unbundled branches, usually due to dependencies missing from the manifest.
Unbundled_build struct {
- Enabled *bool `android:"arch_variant"`
+ Enabled proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"`
} `android:"arch_variant"`
// similar to `Unbundled_build`, but `Always_use_prebuilt_sdks` means that it uses prebuilt
// sdk specifically.
Always_use_prebuilt_sdks struct {
- Enabled *bool `android:"arch_variant"`
+ Enabled proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"`
} `android:"arch_variant"`
- Malloc_not_svelte struct {
+ Malloc_low_memory struct {
Cflags []string `android:"arch_variant"`
Shared_libs []string `android:"arch_variant"`
Whole_static_libs []string `android:"arch_variant"`
@@ -278,7 +278,7 @@
Unbundled_build_image *bool `json:",omitempty"`
Always_use_prebuilt_sdks *bool `json:",omitempty"`
Skip_boot_jars_check *bool `json:",omitempty"`
- Malloc_not_svelte *bool `json:",omitempty"`
+ Malloc_low_memory *bool `json:",omitempty"`
Malloc_zero_contents *bool `json:",omitempty"`
Malloc_pattern_fill_contents *bool `json:",omitempty"`
Safestack *bool `json:",omitempty"`
@@ -612,7 +612,7 @@
AAPTCharacteristics: stringPtr("nosdcard"),
AAPTPrebuiltDPI: []string{"xhdpi", "xxhdpi"},
- Malloc_not_svelte: boolPtr(true),
+ Malloc_low_memory: boolPtr(false),
Malloc_zero_contents: boolPtr(true),
Malloc_pattern_fill_contents: boolPtr(false),
Safestack: boolPtr(false),
diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go
index 9d61e1c..8a8bb2e 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -151,7 +151,7 @@
"LOCAL_CLANG_CFLAGS": "clang_cflags",
"LOCAL_YACCFLAGS": "yacc.flags",
"LOCAL_SANITIZE_RECOVER": "sanitize.recover",
- "LOCAL_LOGTAGS_FILES": "logtags",
+ "LOCAL_SOONG_LOGTAGS_FILES": "logtags",
"LOCAL_EXPORT_HEADER_LIBRARY_HEADERS": "export_header_lib_headers",
"LOCAL_EXPORT_SHARED_LIBRARY_HEADERS": "export_shared_lib_headers",
"LOCAL_EXPORT_STATIC_LIBRARY_HEADERS": "export_static_lib_headers",
diff --git a/apex/apex.go b/apex/apex.go
index 0fc5a5e..bc2b032 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -490,9 +490,6 @@
javaApisUsedByModuleFile android.ModuleOutPath
aconfigFiles []android.Path
-
- // Single aconfig "cache file" merged from this module and all dependencies.
- mergedAconfigFiles map[string]android.Paths
}
// apexFileClass represents a type of file that can be included in APEX.
@@ -1082,7 +1079,7 @@
// specific variant to modules that support the ApexInfoMutator.
// It also propagates updatable=true to apps of updatable apexes
func apexInfoMutator(mctx android.TopDownMutatorContext) {
- if !mctx.Module().Enabled() {
+ if !mctx.Module().Enabled(mctx) {
return
}
@@ -1099,7 +1096,7 @@
// apexStrictUpdatibilityLintMutator propagates strict_updatability_linting to transitive deps of a mainline module
// This check is enforced for updatable modules
func apexStrictUpdatibilityLintMutator(mctx android.TopDownMutatorContext) {
- if !mctx.Module().Enabled() {
+ if !mctx.Module().Enabled(mctx) {
return
}
if apex, ok := mctx.Module().(*apexBundle); ok && apex.checkStrictUpdatabilityLinting() {
@@ -1126,7 +1123,7 @@
// enforceAppUpdatability propagates updatable=true to apps of updatable apexes
func enforceAppUpdatability(mctx android.TopDownMutatorContext) {
- if !mctx.Module().Enabled() {
+ if !mctx.Module().Enabled(mctx) {
return
}
if apex, ok := mctx.Module().(*apexBundle); ok && apex.Updatable() {
@@ -1204,7 +1201,7 @@
// unique apex variations for this module. See android/apex.go for more about unique apex variant.
// TODO(jiyong): move this to android/apex.go?
func apexUniqueVariationsMutator(mctx android.BottomUpMutatorContext) {
- if !mctx.Module().Enabled() {
+ if !mctx.Module().Enabled(mctx) {
return
}
if am, ok := mctx.Module().(android.ApexModule); ok {
@@ -1216,7 +1213,7 @@
// the apex in order to retrieve its contents later.
// TODO(jiyong): move this to android/apex.go?
func apexTestForDepsMutator(mctx android.BottomUpMutatorContext) {
- if !mctx.Module().Enabled() {
+ if !mctx.Module().Enabled(mctx) {
return
}
if am, ok := mctx.Module().(android.ApexModule); ok {
@@ -1231,7 +1228,7 @@
// TODO(jiyong): move this to android/apex.go?
func apexTestForMutator(mctx android.BottomUpMutatorContext) {
- if !mctx.Module().Enabled() {
+ if !mctx.Module().Enabled(mctx) {
return
}
if _, ok := mctx.Module().(android.ApexModule); ok {
@@ -1345,7 +1342,7 @@
// See android.UpdateDirectlyInAnyApex
// TODO(jiyong): move this to android/apex.go?
func apexDirectlyInAnyMutator(mctx android.BottomUpMutatorContext) {
- if !mctx.Module().Enabled() {
+ if !mctx.Module().Enabled(mctx) {
return
}
if am, ok := mctx.Module().(android.ApexModule); ok {
@@ -1644,7 +1641,8 @@
func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt prebuilt_etc.PrebuiltEtcModule, outputFile android.Path) apexFile {
dirInApex := filepath.Join(prebuilt.BaseDir(), prebuilt.SubDir())
- return newApexFile(ctx, outputFile, outputFile.Base(), dirInApex, etc, prebuilt)
+ makeModuleName := strings.ReplaceAll(filepath.Join(dirInApex, outputFile.Base()), "/", "_")
+ return newApexFile(ctx, outputFile, makeModuleName, dirInApex, etc, prebuilt)
}
func apexFileForCompatConfig(ctx android.BaseModuleContext, config java.PlatformCompatConfigIntf, depName string) apexFile {
@@ -1682,7 +1680,13 @@
af.jacocoReportClassesFile = module.JacocoReportClassesFile()
af.lintDepSets = module.LintDepSets()
af.customStem = module.Stem() + ".jar"
- if dexpreopter, ok := module.(java.DexpreopterInterface); ok {
+ // TODO: b/338641779 - Remove special casing of sdkLibrary once bcpf and sscpf depends
+ // on the implementation library
+ if sdkLib, ok := module.(*java.SdkLibrary); ok {
+ for _, install := range sdkLib.BuiltInstalledForApex() {
+ af.requiredModuleNames = append(af.requiredModuleNames, install.FullModuleName())
+ }
+ } else if dexpreopter, ok := module.(java.DexpreopterInterface); ok {
for _, install := range dexpreopter.DexpreoptBuiltInstalledForApex() {
af.requiredModuleNames = append(af.requiredModuleNames, install.FullModuleName())
}
@@ -1973,7 +1977,7 @@
if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
return false
}
- if mod, ok := child.(android.Module); ok && !mod.Enabled() {
+ if mod, ok := child.(android.Module); ok && !mod.Enabled(ctx) {
return false
}
depName := ctx.OtherModuleName(child)
@@ -2325,7 +2329,7 @@
}
func addAconfigFiles(vctx *visitorContext, ctx android.ModuleContext, module blueprint.Module) {
- if dep, ok := android.OtherModuleProvider(ctx, module, android.AconfigTransitiveDeclarationsInfoProvider); ok {
+ if dep, ok := android.OtherModuleProvider(ctx, module, android.AconfigPropagatingProviderKey); ok {
if len(dep.AconfigFiles) > 0 && dep.AconfigFiles[ctx.ModuleName()] != nil {
vctx.aconfigFiles = append(vctx.aconfigFiles, dep.AconfigFiles[ctx.ModuleName()]...)
}
@@ -2413,7 +2417,6 @@
return
}
}
- android.CollectDependencyAconfigFiles(ctx, &a.mergedAconfigFiles)
////////////////////////////////////////////////////////////////////////////////////////////
// 3) some fields in apexBundle struct are configured
@@ -2585,9 +2588,6 @@
type Defaults struct {
android.ModuleBase
android.DefaultsModuleBase
-
- // Single aconfig "cache file" merged from this module and all dependencies.
- mergedAconfigFiles map[string]android.Paths
}
// apex_defaults provides defaultable properties to other apex modules.
@@ -2610,10 +2610,6 @@
android.OverrideModuleBase
}
-func (d *Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- android.CollectDependencyAconfigFiles(ctx, &d.mergedAconfigFiles)
-}
-
func (o *OverrideApex) GenerateAndroidBuildActions(_ android.ModuleContext) {
// All the overrides happen in the base module.
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 3e284b1..a758caf 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -3671,34 +3671,13 @@
func vndkLibrariesTxtFiles(vers ...string) (result string) {
for _, v := range vers {
- if v == "current" {
- for _, txt := range []string{"vndkcore", "vndksp", "vndkprivate", "vndkproduct"} {
- result += `
- ` + txt + `_libraries_txt {
- name: "` + txt + `.libraries.txt",
- insert_vndk_version: true,
- }
- `
- }
+ for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate", "vndkproduct"} {
result += `
- llndk_libraries_txt {
- name: "llndk.libraries.txt",
- }
- llndk_libraries_txt_for_apex {
- name: "llndk.libraries.txt.apex",
- stem: "llndk.libraries.txt",
- insert_vndk_version: true,
- }
- `
- } else {
- for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate", "vndkproduct"} {
- result += `
prebuilt_etc {
name: "` + txt + `.libraries.` + v + `.txt",
src: "dummy.txt",
}
`
- }
}
}
return
@@ -5622,8 +5601,21 @@
compile_dex: true,
}
`
+ // This test disables libbar, which causes the ComponentDepsMutator to add
+ // deps on libbar.stubs and other sub-modules that don't exist. We can
+ // enable AllowMissingDependencies to work around that, but enabling that
+ // causes extra checks for missing source files to dex_bootjars, so add those
+ // to the mock fs as well.
+ preparer2 := android.GroupFixturePreparers(
+ preparer,
+ android.PrepareForTestWithAllowMissingDependencies,
+ android.FixtureMergeMockFs(map[string][]byte{
+ "build/soong/scripts/check_boot_jars/package_allowed_list.txt": nil,
+ "frameworks/base/config/boot-profile.txt": nil,
+ }),
+ )
- ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
+ ctx := testDexpreoptWithApexes(t, bp, "", preparer2, fragment)
checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
@@ -5916,6 +5908,7 @@
srcs: ["foo/bar/MyClass.java"],
sdk_version: "current",
system_modules: "none",
+ use_embedded_native_libs: true,
jni_libs: ["libjni"],
stl: "none",
apex_available: [ "myapex" ],
@@ -7167,7 +7160,7 @@
// 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\.impl\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+ if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
t.Errorf("expected %q, found %#q", expected, actual)
}
}
@@ -7308,7 +7301,7 @@
// 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\.impl\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+ if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
t.Errorf("expected %q, found %#q", expected, actual)
}
}
@@ -9241,7 +9234,7 @@
continue
}
mod := ctx.ModuleForTests(modName, variant).Module().(*cc.Module)
- if !mod.Enabled() || mod.IsHideFromMake() {
+ if !mod.Enabled(android.PanickingConfigAndErrorContext(ctx)) || mod.IsHideFromMake() {
continue
}
for _, ent := range android.AndroidMkEntriesForTest(t, ctx, mod) {
@@ -11428,6 +11421,7 @@
aconfig_declarations {
name: "%[1]s",
package: "com.example.package",
+ container: "system",
srcs: [
"%[1]s.aconfig",
],
@@ -11538,3 +11532,42 @@
"depend on java_aconfig_library not passed as an input",
aconfigFlagArgs, fmt.Sprintf("%s/%s/intermediate.pb", outDir, "quux"))
}
+
+func TestMultiplePrebuiltsWithSameBase(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ prebuilts: ["myetc", "myetc2"],
+ min_sdk_version: "29",
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ prebuilt_etc {
+ name: "myetc",
+ src: "myprebuilt",
+ filename: "myfilename",
+ }
+ prebuilt_etc {
+ name: "myetc2",
+ sub_dir: "mysubdir",
+ src: "myprebuilt",
+ filename: "myfilename",
+ }
+ `, withFiles(android.MockFS{
+ "packages/modules/common/build/allowed_deps.txt": nil,
+ }))
+
+ ab := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
+ data := android.AndroidMkDataForTest(t, ctx, ab)
+ var builder strings.Builder
+ data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
+ androidMk := builder.String()
+
+ android.AssertStringDoesContain(t, "not found", androidMk, "LOCAL_MODULE := etc_myfilename.myapex")
+ android.AssertStringDoesContain(t, "not found", androidMk, "LOCAL_MODULE := etc_mysubdir_myfilename.myapex")
+}
diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go
index 2be9c10..9f1e1e1 100644
--- a/apex/platform_bootclasspath_test.go
+++ b/apex/platform_bootclasspath_test.go
@@ -795,3 +795,127 @@
}
`)
}
+
+// Source and prebuilt apex provide different set of boot jars
+func TestNonBootJarMissingInPrebuiltFragment(t *testing.T) {
+ bp := `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ bootclasspath_fragments: ["apex-fragment"],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_library {
+ name: "foo",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: ["myapex"],
+ permitted_packages: ["foo"],
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: ["myapex"],
+ permitted_packages: ["bar"],
+ }
+
+ bootclasspath_fragment {
+ name: "apex-fragment",
+ contents: ["foo", "bar"],
+ apex_available:[ "myapex" ],
+ hidden_api: {
+ split_packages: ["*"],
+ },
+ }
+
+ prebuilt_apex {
+ name: "com.google.android.myapex", // mainline prebuilt selection logic in soong relies on the naming convention com.google.android
+ apex_name: "myapex",
+ source_apex_name: "myapex",
+ src: "myapex.apex",
+ exported_bootclasspath_fragments: ["apex-fragment"],
+ }
+
+ java_import {
+ name: "foo",
+ jars: ["foo.jar"],
+ apex_available: ["myapex"],
+ permitted_packages: ["foo"],
+ }
+
+ prebuilt_bootclasspath_fragment {
+ name: "apex-fragment",
+ contents: ["foo"], // Unlike the source fragment, this is missing bar
+ apex_available:[ "myapex" ],
+ hidden_api: {
+ annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
+ metadata: "my-bootclasspath-fragment/metadata.csv",
+ index: "my-bootclasspath-fragment/index.csv",
+ stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
+ all_flags: "my-bootclasspath-fragment/all-flags.csv",
+ },
+ }
+
+ apex_contributions {
+ name: "my_apex_contributions",
+ api_domain: "myapex",
+ contents: [%v],
+ }
+ `
+ testCases := []struct {
+ desc string
+ configuredBootJars []string
+ apexContributionContents string
+ errorExpected bool
+ }{
+ {
+ desc: "Source apex is selected, and APEX_BOOT_JARS is correctly configured for source apex builds",
+ configuredBootJars: []string{"myapex:foo", "myapex:bar"},
+ },
+ {
+ desc: "Source apex is selected, and APEX_BOOT_JARS is missing bar",
+ configuredBootJars: []string{"myapex:foo"},
+ errorExpected: true,
+ },
+ {
+ desc: "Prebuilt apex is selected, and APEX_BOOT_JARS is correctly configured for prebuilt apex build",
+ configuredBootJars: []string{"myapex:foo"},
+ apexContributionContents: `"prebuilt_com.google.android.myapex"`,
+ },
+ {
+ desc: "Prebuilt apex is selected, and APEX_BOOT_JARS is missing foo",
+ configuredBootJars: []string{"myapex:bar"},
+ apexContributionContents: `"prebuilt_com.google.android.myapex"`,
+ errorExpected: true,
+ },
+ }
+
+ for _, tc := range testCases {
+ fixture := android.GroupFixturePreparers(
+ prepareForTestWithPlatformBootclasspath,
+ PrepareForTestWithApexBuildComponents,
+ prepareForTestWithMyapex,
+ java.FixtureConfigureApexBootJars(tc.configuredBootJars...),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ART": "my_apex_contributions",
+ }
+ }),
+ )
+ if tc.errorExpected {
+ fixture = fixture.ExtendWithErrorHandler(
+ android.FixtureExpectsAtLeastOneErrorMatchingPattern(`in contents.*must also be declared in PRODUCT_APEX_BOOT_JARS`),
+ )
+ }
+ fixture.RunTestWithBp(t, fmt.Sprintf(bp, tc.apexContributionContents))
+ }
+}
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index ea847e1..b2afa39 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -503,9 +503,6 @@
inputApex android.Path
provenanceMetaDataFile android.OutputPath
-
- // Single aconfig "cache file" merged from this module and all dependencies.
- mergedAconfigFiles map[string]android.Paths
}
type ApexFileProperties struct {
@@ -838,7 +835,21 @@
android.SetProvider(ctx, android.PrebuiltInfoProvider, info)
}
+// Uses an object provided by its deps to validate that the contents of bcpf have been added to the global
+// PRODUCT_APEX_BOOT_JARS
+// This validation will only run on the apex which is active for this product/release_config
+func validateApexClasspathFragments(ctx android.ModuleContext) {
+ ctx.VisitDirectDeps(func(m android.Module) {
+ if info, exists := android.OtherModuleProvider(ctx, m, java.ClasspathFragmentValidationInfoProvider); exists {
+ ctx.ModuleErrorf("%s in contents of %s must also be declared in PRODUCT_APEX_BOOT_JARS", info.UnknownJars, info.ClasspathFragmentModuleName)
+ }
+ })
+}
+
func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ // Validate contents of classpath fragments
+ validateApexClasspathFragments(ctx)
+
p.apexKeysPath = writeApexKeys(ctx, p)
// TODO(jungjw): Check the key validity.
p.inputApex = android.OptionalPathForModuleSrc(ctx, p.prebuiltCommonProperties.Selected_apex).Path()
@@ -881,8 +892,6 @@
p.installedFile = ctx.InstallFile(p.installDir, p.installFilename, p.inputApex, p.compatSymlinks...)
p.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, p.inputApex, p.installedFile)
}
-
- android.CollectDependencyAconfigFiles(ctx, &p.mergedAconfigFiles)
}
func (p *Prebuilt) ProvenanceMetaDataFile() android.OutputPath {
@@ -1064,6 +1073,9 @@
}
func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ // Validate contents of classpath fragments
+ validateApexClasspathFragments(ctx)
+
a.apexKeysPath = writeApexKeys(ctx, a)
a.installFilename = a.InstallFilename()
if !strings.HasSuffix(a.installFilename, imageApexSuffix) && !strings.HasSuffix(a.installFilename, imageCapexSuffix) {
diff --git a/bin/aninja b/bin/aninja
new file mode 100755
index 0000000..cceb794
--- /dev/null
+++ b/bin/aninja
@@ -0,0 +1,25 @@
+#!/bin/bash -e
+
+# Copyright (C) 2022 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Common script utilities
+source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../../make/shell_utils.sh
+
+require_top
+require_lunch
+
+cd $(gettop)
+prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-${TARGET_PRODUCT}.ninja "$@"
+
diff --git a/bin/overrideflags b/bin/overrideflags
new file mode 100755
index 0000000..e16537b
--- /dev/null
+++ b/bin/overrideflags
@@ -0,0 +1,100 @@
+#!/bin/bash -e
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../../make/shell_utils.sh
+
+require_top
+
+function print_help() {
+ echo -e "overrideflags is used to set default value for local build."
+ echo -e "\nOptions:"
+ echo -e "\t--release-config \tPath to release configuration directory. Required"
+ echo -e "\t--no-edit \tIf present, skip editing flag value file."
+ echo -e "\t-h/--help \tShow this help."
+}
+
+function main() {
+ while (($# > 0)); do
+ case $1 in
+ --release-config)
+ if [[ $# -le 1 ]]; then
+ echo "--release-config requires a path"
+ return 1
+ fi
+ local release_config_dir="$2"
+ shift 2
+ ;;
+ --no-edit)
+ local no_edit="true"
+ shift 1
+ ;;
+ -h|--help)
+ print_help
+ return
+ ;;
+ *)
+ echo "$1 is unrecognized"
+ print_help
+ return 1
+ ;;
+ esac
+ done
+
+
+
+ case $(uname -s) in
+ Darwin)
+ local host_arch=darwin-x86
+ ;;
+ Linux)
+ local host_arch=linux-x86
+ ;;
+ *)
+ >&2 echo Unknown host $(uname -s)
+ return
+ ;;
+ esac
+
+ if [[ -z "${release_config_dir}" ]]; then
+ echo "Please provide release configuration path by --release-config"
+ exit 1
+ elif [ ! -d "${release_config_dir}" ]; then
+ echo "${release_config_dir} is an invalid directory"
+ exit 1
+ fi
+ local T="$(gettop)"
+ local aconfig_dir="${T}"/build/make/tools/aconfig/
+ local overrideflag_py="${aconfig_dir}"/overrideflags/overrideflags.py
+ local overridefile="${release_config_dir}/aconfig/override_values.textproto"
+
+ # Edit override file
+ if [[ -z "${no_edit}" ]]; then
+ editor="${EDITOR:-$(which vim)}"
+
+ eval "${editor} ${overridefile}"
+ if [ $? -ne 0 ]; then
+ echo "Fail to set override values"
+ return 1
+ fi
+ fi
+
+ ${T}/prebuilts/build-tools/${host_arch}/bin/py3-cmd -u "${overrideflag_py}" \
+ --overrides "${overridefile}" \
+ --out "${release_config_dir}/aconfig"
+}
+
+
+main "$@"
diff --git a/cc/Android.bp b/cc/Android.bp
index 9ce8933..3bbcaa9 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -51,6 +51,7 @@
"vndk.go",
"vndk_prebuilt.go",
+ "cmake_snapshot.go",
"cmakelists.go",
"compdb.go",
"compiler.go",
@@ -92,6 +93,7 @@
"binary_test.go",
"cc_test.go",
"cc_test_only_property_test.go",
+ "cmake_snapshot_test.go",
"compiler_test.go",
"gen_test.go",
"genrule_test.go",
@@ -109,5 +111,12 @@
"tidy_test.go",
"vendor_public_library_test.go",
],
+ embedSrcs: [
+ "cmake_ext_add_aidl_library.txt",
+ "cmake_ext_append_flags.txt",
+ "cmake_main.txt",
+ "cmake_module_aidl.txt",
+ "cmake_module_cc.txt",
+ ],
pluginFor: ["soong_build"],
}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index ef26366..0c6f97c 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -88,7 +88,7 @@
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
if len(c.Properties.Logtags) > 0 {
- entries.AddStrings("LOCAL_LOGTAGS_FILES", c.Properties.Logtags...)
+ entries.AddStrings("LOCAL_SOONG_LOGTAGS_FILES", c.logtagsPaths.Strings()...)
}
// Note: Pass the exact value of AndroidMkSystemSharedLibs to the Make
// world, even if it is an empty list. In the Make world,
@@ -119,16 +119,13 @@
} else if c.InProduct() {
entries.SetBool("LOCAL_IN_PRODUCT", true)
}
- if c.Properties.IsSdkVariant && c.Properties.SdkAndPlatformVariantVisibleToMake {
- // Make the SDK variant uninstallable so that there are not two rules to install
- // to the same location.
- entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
+ if c.Properties.SdkAndPlatformVariantVisibleToMake {
// Add the unsuffixed name to SOONG_SDK_VARIANT_MODULES so that Make can rewrite
// dependencies to the .sdk suffix when building a module that uses the SDK.
entries.SetString("SOONG_SDK_VARIANT_MODULES",
"$(SOONG_SDK_VARIANT_MODULES) $(patsubst %.sdk,%,$(LOCAL_MODULE))")
}
- android.SetAconfigFileMkEntries(c.AndroidModuleBase(), entries, c.mergedAconfigFiles)
+ entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", c.IsSkipInstall())
},
},
ExtraFooters: []android.AndroidMkExtraFootersFunc{
diff --git a/cc/builder.go b/cc/builder.go
index 3eed1f2..42aa4b6 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -618,6 +618,10 @@
ccCmd = "clang++"
moduleFlags = cppflags
moduleToolingFlags = toolingCppflags
+ case ".rs":
+ // A source provider (e.g. rust_bindgen) may provide both rs and c files.
+ // Ignore the rs files.
+ continue
case ".h", ".hpp":
ctx.PropertyErrorf("srcs", "Header file %s is not supported, instead use export_include_dirs or local_include_dirs.", srcFile)
continue
diff --git a/cc/cc.go b/cc/cc.go
index 6dd2682..89cf093 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -50,6 +50,7 @@
ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("sdk", sdkMutator).Parallel()
ctx.BottomUp("vndk", VndkMutator).Parallel()
+ ctx.BottomUp("llndk", llndkMutator).Parallel()
ctx.BottomUp("link", LinkageMutator).Parallel()
ctx.BottomUp("test_per_src", TestPerSrcMutator).Parallel()
ctx.BottomUp("version", versionMutator).Parallel()
@@ -335,7 +336,7 @@
// *.logtags files, to combine together in order to generate the /system/etc/event-log-tags
// file
- Logtags []string
+ Logtags []string `android:"path"`
// Make this module available when building for ramdisk.
// On device without a dedicated recovery partition, the module is only
@@ -368,6 +369,10 @@
// for building binaries that are started before APEXes are activated.
Bootstrap *bool
+ // Allows this module to be included in CMake release snapshots to be built outside of Android
+ // build system and source tree.
+ Cmake_snapshot_supported *bool
+
// Even if DeviceConfig().VndkUseCoreVariant() is set, this module must use vendor variant.
// see soong/cc/config/vndk.go
MustUseVendorVariant bool `blueprint:"mutated"`
@@ -603,6 +608,7 @@
compilerDeps(ctx DepsContext, deps Deps) Deps
compilerFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags
compilerProps() []interface{}
+ baseCompilerProps() BaseCompilerProperties
appendCflags([]string)
appendAsflags([]string)
@@ -617,6 +623,7 @@
linkerDeps(ctx DepsContext, deps Deps) Deps
linkerFlags(ctx ModuleContext, flags Flags) Flags
linkerProps() []interface{}
+ baseLinkerProps() BaseLinkerProperties
useClangLld(actx ModuleContext) bool
link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path
@@ -930,8 +937,7 @@
hideApexVariantFromMake bool
- // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo
- mergedAconfigFiles map[string]android.Paths
+ logtagsPaths android.Paths
}
func (c *Module) AddJSONData(d *map[string]interface{}) {
@@ -2022,13 +2028,14 @@
return false
}
-func (d *Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- android.CollectDependencyAconfigFiles(ctx, &d.mergedAconfigFiles)
-}
-
func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
ctx := moduleContextFromAndroidModuleContext(actx, c)
+ c.logtagsPaths = android.PathsForModuleSrc(actx, c.Properties.Logtags)
+ android.SetProvider(ctx, android.LogtagsProviderKey, &android.LogtagsInfo{
+ Logtags: c.logtagsPaths,
+ })
+
// If Test_only is set on a module in bp file, respect the setting, otherwise
// see if is a known test module type.
testOnly := c.testModule || c.testLibrary()
@@ -2187,7 +2194,9 @@
android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: deps.GeneratedSources.Strings()})
- android.CollectDependencyAconfigFiles(ctx, &c.mergedAconfigFiles)
+ if Bool(c.Properties.Cmake_snapshot_supported) {
+ android.SetProvider(ctx, cmakeSnapshotSourcesProvider, android.GlobFiles(ctx, ctx.ModuleDir()+"/**/*", nil))
+ }
c.maybeInstall(ctx, apexInfo)
@@ -2541,7 +2550,7 @@
}
func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
- if !c.Enabled() {
+ if !c.Enabled(actx) {
return
}
@@ -2798,7 +2807,7 @@
}
func BeginMutator(ctx android.BottomUpMutatorContext) {
- if c, ok := ctx.Module().(*Module); ok && c.Enabled() {
+ if c, ok := ctx.Module().(*Module); ok && c.Enabled(ctx) {
c.beginMutator(ctx)
}
}
@@ -4120,9 +4129,6 @@
android.ModuleBase
android.DefaultsModuleBase
android.ApexModuleBase
-
- // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo
- mergedAconfigFiles map[string]android.Paths
}
// cc_defaults provides a set of properties that can be inherited by other cc
diff --git a/cc/cmake_ext_add_aidl_library.txt b/cc/cmake_ext_add_aidl_library.txt
new file mode 100644
index 0000000..af5bdf6
--- /dev/null
+++ b/cc/cmake_ext_add_aidl_library.txt
@@ -0,0 +1,68 @@
+function(add_aidl_library NAME LANG AIDLROOT SOURCES AIDLFLAGS)
+ if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.20")
+ cmake_policy(SET CMP0116 NEW)
+ endif()
+
+ # Strip trailing slash
+ get_filename_component(AIDLROOT_TRAILING "${AIDLROOT}" NAME)
+ if ("${AIDLROOT_TRAILING}" STREQUAL "")
+ get_filename_component(AIDLROOT "${AIDLROOT}foo" DIRECTORY)
+ endif()
+
+ set(GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/.intermediates/${NAME}-source")
+ set(GEN_SOURCES)
+ foreach (SOURCE ${SOURCES})
+ set(SOURCE_FULL ${AIDLROOT}/${SOURCE})
+ get_filename_component(SOURCE_WLE ${SOURCE} NAME_WLE)
+ get_filename_component(SOURCE_SUBDIR ${SOURCE} DIRECTORY)
+ set(GEN_SOURCE "${GEN_DIR}/${SOURCE_SUBDIR}/${SOURCE_WLE}.cpp")
+
+ file(READ "${SOURCE}" SOURCE_CONTENTS)
+ string(FIND "${SOURCE_CONTENTS}" "@VintfStability" VINTF_MATCH)
+ set(STABILITY_FLAG)
+ if (${VINTF_MATCH} GREATER_EQUAL 0)
+ set(STABILITY_FLAG --stability vintf)
+ endif()
+
+ set(DEPFILE_ARG)
+ if (NOT ${CMAKE_GENERATOR} MATCHES "Unix Makefiles")
+ set(DEPFILE_ARG DEPFILE "${GEN_SOURCE}.d")
+ endif()
+
+ add_custom_command(
+ OUTPUT "${GEN_SOURCE}"
+ MAIN_DEPENDENCY "${SOURCE_FULL}"
+ ${DEPFILE_ARG}
+ COMMAND "${AIDL_BIN}"
+ ARGS
+ --lang=${LANG}
+ --include="${AIDLROOT}"
+ --dep="${GEN_SOURCE}.d"
+ --out="${GEN_DIR}"
+ --header_out="${GEN_DIR}/include"
+ --ninja
+ --structured
+ --min_sdk_version=current
+ ${STABILITY_FLAG}
+ ${AIDLFLAGS}
+ "${SOURCE_FULL}"
+ )
+ list(APPEND GEN_SOURCES "${GEN_SOURCE}")
+ endforeach()
+
+ add_library(${NAME} ${GEN_SOURCES})
+
+ target_include_directories(${NAME}
+ PUBLIC
+ "${GEN_DIR}/include"
+ )
+
+ if (${LANG} MATCHES "ndk")
+ set(BINDER_LIB_NAME "libbinder_ndk_sdk")
+ else()
+ set(BINDER_LIB_NAME "libbinder_sdk")
+ endif()
+ target_link_libraries(${NAME}
+ ${BINDER_LIB_NAME}
+ )
+endfunction()
diff --git a/cc/cmake_ext_append_flags.txt b/cc/cmake_ext_append_flags.txt
new file mode 100644
index 0000000..2cfb1ac
--- /dev/null
+++ b/cc/cmake_ext_append_flags.txt
@@ -0,0 +1,10 @@
+include(CheckCXXCompilerFlag)
+
+macro(append_cxx_flags_if_supported VAR)
+ foreach(FLAG ${ARGN})
+ check_cxx_compiler_flag(${FLAG} HAS_FLAG${FLAG})
+ if(${HAS_FLAG${FLAG}})
+ list(APPEND ${VAR} ${FLAG})
+ endif()
+ endforeach()
+endmacro()
diff --git a/cc/cmake_main.txt b/cc/cmake_main.txt
new file mode 100644
index 0000000..deb1de1
--- /dev/null
+++ b/cc/cmake_main.txt
@@ -0,0 +1,29 @@
+cmake_minimum_required(VERSION 3.18)
+project(<<.M.Name>> CXX)
+set(CMAKE_CXX_STANDARD 20)
+
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+include(AddAidlLibrary)
+include(AppendCxxFlagsIfSupported)
+
+if (NOT ANDROID_BUILD_TOP)
+ set(ANDROID_BUILD_TOP "${CMAKE_CURRENT_SOURCE_DIR}")
+endif()
+
+set(PREBUILTS_BIN_DIR "${CMAKE_CURRENT_SOURCE_DIR}/prebuilts/host/linux-x86/bin")
+if (NOT AIDL_BIN)
+ find_program(AIDL_BIN aidl REQUIRED HINTS "${PREBUILTS_BIN_DIR}")
+endif()
+
+<<cflagsList .M.Name "_CFLAGS" .M.Properties.Cflags .M.Properties.Unportable_flags .M.Properties.Cflags_ignored>>
+
+<<range .Pprop.SystemPackages ->>
+find_package(<<.>> REQUIRED)
+<<end >>
+<<range .Pprop.PregeneratedPackages ->>
+add_subdirectory("${ANDROID_BUILD_TOP}/<<.>>" "<<.>>/build" EXCLUDE_FROM_ALL)
+<<end>>
+add_compile_options(${<<.M.Name>>_CFLAGS})
+<<range $moduleDir, $value := .ModuleDirs ->>
+add_subdirectory(<<$moduleDir>>)
+<<end>>
diff --git a/cc/cmake_module_aidl.txt b/cc/cmake_module_aidl.txt
new file mode 100644
index 0000000..84755a3
--- /dev/null
+++ b/cc/cmake_module_aidl.txt
@@ -0,0 +1,11 @@
+# <<.M.Name>>
+
+<<setList .M.Name "_SRCS" "" (getAidlSources .M)>>
+
+<<setList .M.Name "_AIDLFLAGS" "" (getCompilerProperties .M).AidlInterface.Flags>>
+
+add_aidl_library(<<.M.Name>> <<(getCompilerProperties .M).AidlInterface.Lang>>
+ "${ANDROID_BUILD_TOP}/<<.Ctx.OtherModuleDir .M>>/<<(getCompilerProperties .M).AidlInterface.AidlRoot>>"
+ "${<<.M.Name>>_SRCS}"
+ "${<<.M.Name>>_AIDLFLAGS}")
+add_library(android::<<.M.Name>> ALIAS <<.M.Name>>)
diff --git a/cc/cmake_module_cc.txt b/cc/cmake_module_cc.txt
new file mode 100644
index 0000000..488e5e1
--- /dev/null
+++ b/cc/cmake_module_cc.txt
@@ -0,0 +1,35 @@
+<<$srcs := getSources .M>>
+<<$includeDirs := getIncludeDirs .Ctx .M>>
+<<$cflags := (getCompilerProperties .M).Cflags>>
+<<$deps := mapLibraries .Ctx .M (concat5
+(getLinkerProperties .M).Whole_static_libs
+(getLinkerProperties .M).Static_libs
+(getLinkerProperties .M).Shared_libs
+(getLinkerProperties .M).Header_libs
+(getExtraLibs .M)
+) .Pprop.LibraryMapping>>
+
+# <<.M.Name>>
+<<if $srcs>>
+<<setList .M.Name "_SRCS" "${ANDROID_BUILD_TOP}/" (toStrings $srcs)>>
+add_<<getModuleType .M>>(<<.M.Name>> ${<<.M.Name>>_SRCS})
+<<- else>>
+add_<<getModuleType .M>>(<<.M.Name>> INTERFACE)
+<<- end>>
+add_<<getModuleType .M>>(android::<<.M.Name>> ALIAS <<.M.Name>>)
+<<print "">>
+
+<<- if $includeDirs>>
+<<setList .M.Name "_INCLUDES" "${ANDROID_BUILD_TOP}/" $includeDirs>>
+target_include_directories(<<.M.Name>> <<if $srcs>>PUBLIC<<else>>INTERFACE<<end>> ${<<.M.Name>>_INCLUDES})
+<<end>>
+
+<<- if and $srcs $cflags>>
+<<cflagsList .M.Name "_CFLAGS" $cflags .Snapshot.Properties.Unportable_flags .Snapshot.Properties.Cflags_ignored>>
+target_compile_options(<<.M.Name>> PRIVATE ${<<.M.Name>>_CFLAGS})
+<<end>>
+
+<<- if $deps>>
+<<setList .M.Name "_DEPENDENCIES" "" $deps>>
+target_link_libraries(<<.M.Name>> <<if not $srcs>>INTERFACE <<end ->> ${<<.M.Name>>_DEPENDENCIES})
+<<end>>
diff --git a/cc/cmake_snapshot.go b/cc/cmake_snapshot.go
new file mode 100644
index 0000000..c21a46f
--- /dev/null
+++ b/cc/cmake_snapshot.go
@@ -0,0 +1,544 @@
+// 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 cc
+
+import (
+ "android/soong/android"
+ "bytes"
+ _ "embed"
+ "fmt"
+ "path/filepath"
+ "slices"
+ "sort"
+ "strings"
+ "text/template"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+const veryVerbose bool = false
+
+//go:embed cmake_main.txt
+var templateCmakeMainRaw string
+var templateCmakeMain *template.Template = parseTemplate(templateCmakeMainRaw)
+
+//go:embed cmake_module_cc.txt
+var templateCmakeModuleCcRaw string
+var templateCmakeModuleCc *template.Template = parseTemplate(templateCmakeModuleCcRaw)
+
+//go:embed cmake_module_aidl.txt
+var templateCmakeModuleAidlRaw string
+var templateCmakeModuleAidl *template.Template = parseTemplate(templateCmakeModuleAidlRaw)
+
+//go:embed cmake_ext_add_aidl_library.txt
+var cmakeExtAddAidlLibrary string
+
+//go:embed cmake_ext_append_flags.txt
+var cmakeExtAppendFlags string
+
+var defaultUnportableFlags []string = []string{
+ "-Wno-class-memaccess",
+ "-Wno-exit-time-destructors",
+ "-Wno-inconsistent-missing-override",
+ "-Wreorder-init-list",
+ "-Wno-reorder-init-list",
+ "-Wno-restrict",
+ "-Wno-stringop-overread",
+ "-Wno-subobject-linkage",
+}
+
+var ignoredSystemLibs []string = []string{
+ "libc++",
+ "libc++_static",
+ "prebuilt_libclang_rt.builtins",
+ "prebuilt_libclang_rt.ubsan_minimal",
+}
+
+// Mapping entry between Android's library name and the one used when building outside Android tree.
+type LibraryMappingProperty struct {
+ // Android library name.
+ Android_name string
+
+ // Library name used when building outside Android.
+ Mapped_name string
+
+ // If the make file is already present in Android source tree, specify its location.
+ Package_pregenerated string
+
+ // If the package is expected to be installed on the build host OS, specify its name.
+ Package_system string
+}
+
+type CmakeSnapshotProperties struct {
+ // Modules to add to the snapshot package. Their dependencies are pulled in automatically.
+ Modules []string
+
+ // Host prebuilts to bundle with the snapshot. These are tools needed to build outside Android.
+ Prebuilts []string
+
+ // Global cflags to add when building outside Android.
+ Cflags []string
+
+ // Flags to skip when building outside Android.
+ Cflags_ignored []string
+
+ // Mapping between library names used in Android tree and externally.
+ Library_mapping []LibraryMappingProperty
+
+ // List of cflags that are not portable between compilers that could potentially be used to
+ // build a generated package. If left empty, it's initialized with a default list.
+ Unportable_flags []string
+
+ // Whether to include source code as part of the snapshot package.
+ Include_sources bool
+}
+
+var cmakeSnapshotSourcesProvider = blueprint.NewProvider[android.Paths]()
+
+type CmakeSnapshot struct {
+ android.ModuleBase
+
+ Properties CmakeSnapshotProperties
+
+ zipPath android.WritablePath
+}
+
+type cmakeProcessedProperties struct {
+ LibraryMapping map[string]LibraryMappingProperty
+ PregeneratedPackages []string
+ SystemPackages []string
+}
+
+type cmakeSnapshotDependencyTag struct {
+ blueprint.BaseDependencyTag
+ name string
+}
+
+var (
+ cmakeSnapshotModuleTag = cmakeSnapshotDependencyTag{name: "cmake-snapshot-module"}
+ cmakeSnapshotPrebuiltTag = cmakeSnapshotDependencyTag{name: "cmake-snapshot-prebuilt"}
+)
+
+func parseTemplate(templateContents string) *template.Template {
+ funcMap := template.FuncMap{
+ "setList": func(name string, nameSuffix string, itemPrefix string, items []string) string {
+ var list strings.Builder
+ list.WriteString("set(" + name + nameSuffix)
+ templateListBuilder(&list, itemPrefix, items)
+ return list.String()
+ },
+ "toStrings": func(files android.Paths) []string {
+ strings := make([]string, len(files))
+ for idx, file := range files {
+ strings[idx] = file.String()
+ }
+ return strings
+ },
+ "concat5": func(list1 []string, list2 []string, list3 []string, list4 []string, list5 []string) []string {
+ return append(append(append(append(list1, list2...), list3...), list4...), list5...)
+ },
+ "cflagsList": func(name string, nameSuffix string, flags []string,
+ unportableFlags []string, ignoredFlags []string) string {
+ if len(unportableFlags) == 0 {
+ unportableFlags = defaultUnportableFlags
+ }
+
+ var filteredPortable []string
+ var filteredUnportable []string
+ for _, flag := range flags {
+ if slices.Contains(ignoredFlags, flag) {
+ continue
+ } else if slices.Contains(unportableFlags, flag) {
+ filteredUnportable = append(filteredUnportable, flag)
+ } else {
+ filteredPortable = append(filteredPortable, flag)
+ }
+ }
+
+ var list strings.Builder
+
+ list.WriteString("set(" + name + nameSuffix)
+ templateListBuilder(&list, "", filteredPortable)
+
+ if len(filteredUnportable) > 0 {
+ list.WriteString("\nappend_cxx_flags_if_supported(" + name + nameSuffix)
+ templateListBuilder(&list, "", filteredUnportable)
+ }
+
+ return list.String()
+ },
+ "getSources": func(m *Module) android.Paths {
+ return m.compiler.(CompiledInterface).Srcs()
+ },
+ "getModuleType": getModuleType,
+ "getCompilerProperties": func(m *Module) BaseCompilerProperties {
+ return m.compiler.baseCompilerProps()
+ },
+ "getLinkerProperties": func(m *Module) BaseLinkerProperties {
+ return m.linker.baseLinkerProps()
+ },
+ "getExtraLibs": getExtraLibs,
+ "getIncludeDirs": getIncludeDirs,
+ "mapLibraries": func(ctx android.ModuleContext, m *Module, libs []string, mapping map[string]LibraryMappingProperty) []string {
+ var mappedLibs []string
+ for _, lib := range libs {
+ mappedLib, exists := mapping[lib]
+ if exists {
+ lib = mappedLib.Mapped_name
+ } else {
+ if !ctx.OtherModuleExists(lib) {
+ ctx.OtherModuleErrorf(m, "Dependency %s doesn't exist", lib)
+ }
+ lib = "android::" + lib
+ }
+ if lib == "" {
+ continue
+ }
+ mappedLibs = append(mappedLibs, lib)
+ }
+ sort.Strings(mappedLibs)
+ mappedLibs = slices.Compact(mappedLibs)
+ return mappedLibs
+ },
+ "getAidlSources": func(m *Module) []string {
+ aidlInterface := m.compiler.baseCompilerProps().AidlInterface
+ aidlRoot := aidlInterface.AidlRoot + string(filepath.Separator)
+ if aidlInterface.AidlRoot == "" {
+ aidlRoot = ""
+ }
+ var sources []string
+ for _, src := range aidlInterface.Sources {
+ if !strings.HasPrefix(src, aidlRoot) {
+ panic(fmt.Sprintf("Aidl source '%v' doesn't start with '%v'", src, aidlRoot))
+ }
+ sources = append(sources, src[len(aidlRoot):])
+ }
+ return sources
+ },
+ }
+
+ return template.Must(template.New("").Delims("<<", ">>").Funcs(funcMap).Parse(templateContents))
+}
+
+func sliceWithPrefix(prefix string, slice []string) []string {
+ output := make([]string, len(slice))
+ for i, elem := range slice {
+ output[i] = prefix + elem
+ }
+ return output
+}
+
+func templateListBuilder(builder *strings.Builder, itemPrefix string, items []string) {
+ if len(items) > 0 {
+ builder.WriteString("\n")
+ for _, item := range items {
+ builder.WriteString(" " + itemPrefix + item + "\n")
+ }
+ }
+ builder.WriteString(")")
+}
+
+func executeTemplate(templ *template.Template, buffer *bytes.Buffer, data any) string {
+ buffer.Reset()
+ if err := templ.Execute(buffer, data); err != nil {
+ panic(err)
+ }
+ output := strings.TrimSpace(buffer.String())
+ buffer.Reset()
+ return output
+}
+
+func (m *CmakeSnapshot) DepsMutator(ctx android.BottomUpMutatorContext) {
+ variations := []blueprint.Variation{
+ {"os", "linux_glibc"},
+ {"arch", "x86_64"},
+ }
+ ctx.AddVariationDependencies(variations, cmakeSnapshotModuleTag, m.Properties.Modules...)
+ ctx.AddVariationDependencies(variations, cmakeSnapshotPrebuiltTag, m.Properties.Prebuilts...)
+}
+
+func (m *CmakeSnapshot) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ var templateBuffer bytes.Buffer
+ var pprop cmakeProcessedProperties
+ m.zipPath = android.PathForModuleOut(ctx, ctx.ModuleName()+".zip")
+
+ // Process Library_mapping for more efficient lookups
+ pprop.LibraryMapping = map[string]LibraryMappingProperty{}
+ for _, elem := range m.Properties.Library_mapping {
+ pprop.LibraryMapping[elem.Android_name] = elem
+
+ if elem.Package_pregenerated != "" {
+ pprop.PregeneratedPackages = append(pprop.PregeneratedPackages, elem.Package_pregenerated)
+ }
+ sort.Strings(pprop.PregeneratedPackages)
+ pprop.PregeneratedPackages = slices.Compact(pprop.PregeneratedPackages)
+
+ if elem.Package_system != "" {
+ pprop.SystemPackages = append(pprop.SystemPackages, elem.Package_system)
+ }
+ sort.Strings(pprop.SystemPackages)
+ pprop.SystemPackages = slices.Compact(pprop.SystemPackages)
+ }
+
+ // Generating CMakeLists.txt rules for all modules in dependency tree
+ moduleDirs := map[string][]string{}
+ sourceFiles := map[string]android.Path{}
+ visitedModules := map[string]bool{}
+ var pregeneratedModules []*Module
+ ctx.WalkDeps(func(dep_a android.Module, parent android.Module) bool {
+ moduleName := ctx.OtherModuleName(dep_a)
+ if visited := visitedModules[moduleName]; visited {
+ return false // visit only once
+ }
+ visitedModules[moduleName] = true
+ dep, ok := dep_a.(*Module)
+ if !ok {
+ return false // not a cc module
+ }
+ if mapping, ok := pprop.LibraryMapping[moduleName]; ok {
+ if mapping.Package_pregenerated != "" {
+ pregeneratedModules = append(pregeneratedModules, dep)
+ }
+ return false // mapped to system or pregenerated (we'll handle these later)
+ }
+ if ctx.OtherModuleDependencyTag(dep) == cmakeSnapshotPrebuiltTag {
+ return false // we'll handle cmakeSnapshotPrebuiltTag later
+ }
+ if slices.Contains(ignoredSystemLibs, moduleName) {
+ return false // system libs built in-tree for Android
+ }
+ if dep.compiler == nil {
+ return false // unsupported module type (e.g. prebuilt)
+ }
+ isAidlModule := dep.compiler.baseCompilerProps().AidlInterface.Lang != ""
+
+ if !proptools.Bool(dep.Properties.Cmake_snapshot_supported) {
+ ctx.OtherModulePropertyErrorf(dep, "cmake_snapshot_supported",
+ "CMake snapshots not supported, despite being a dependency for %s",
+ ctx.OtherModuleName(parent))
+ return false
+ }
+
+ if veryVerbose {
+ fmt.Println("WalkDeps: " + ctx.OtherModuleName(parent) + " -> " + moduleName)
+ }
+
+ // Generate CMakeLists.txt fragment for this module
+ templateToUse := templateCmakeModuleCc
+ if isAidlModule {
+ templateToUse = templateCmakeModuleAidl
+ }
+ moduleFragment := executeTemplate(templateToUse, &templateBuffer, struct {
+ Ctx *android.ModuleContext
+ M *Module
+ Snapshot *CmakeSnapshot
+ Pprop *cmakeProcessedProperties
+ }{
+ &ctx,
+ dep,
+ m,
+ &pprop,
+ })
+ moduleDir := ctx.OtherModuleDir(dep)
+ moduleDirs[moduleDir] = append(moduleDirs[moduleDir], moduleFragment)
+
+ if m.Properties.Include_sources {
+ files, _ := android.OtherModuleProvider(ctx, dep, cmakeSnapshotSourcesProvider)
+ for _, file := range files {
+ sourceFiles[file.String()] = file
+ }
+ }
+
+ // if it's AIDL module, no need to dive into their dependencies
+ return !isAidlModule
+ })
+
+ // Enumerate sources for pregenerated modules
+ if m.Properties.Include_sources {
+ for _, dep := range pregeneratedModules {
+ if !proptools.Bool(dep.Properties.Cmake_snapshot_supported) {
+ ctx.OtherModulePropertyErrorf(dep, "cmake_snapshot_supported",
+ "Pregenerated CMake snapshots not supported, despite being requested for %s",
+ ctx.ModuleName())
+ continue
+ }
+
+ files, _ := android.OtherModuleProvider(ctx, dep, cmakeSnapshotSourcesProvider)
+ for _, file := range files {
+ sourceFiles[file.String()] = file
+ }
+ }
+ }
+
+ // Merging CMakeLists.txt contents for every module directory
+ var makefilesList android.Paths
+ for moduleDir, fragments := range moduleDirs {
+ moduleCmakePath := android.PathForModuleGen(ctx, moduleDir, "CMakeLists.txt")
+ makefilesList = append(makefilesList, moduleCmakePath)
+ sort.Strings(fragments)
+ android.WriteFileRule(ctx, moduleCmakePath, strings.Join(fragments, "\n\n\n"))
+ }
+
+ // Generating top-level CMakeLists.txt
+ mainCmakePath := android.PathForModuleGen(ctx, "CMakeLists.txt")
+ makefilesList = append(makefilesList, mainCmakePath)
+ mainContents := executeTemplate(templateCmakeMain, &templateBuffer, struct {
+ Ctx *android.ModuleContext
+ M *CmakeSnapshot
+ ModuleDirs map[string][]string
+ Pprop *cmakeProcessedProperties
+ }{
+ &ctx,
+ m,
+ moduleDirs,
+ &pprop,
+ })
+ android.WriteFileRule(ctx, mainCmakePath, mainContents)
+
+ // Generating CMake extensions
+ extPath := android.PathForModuleGen(ctx, "cmake", "AppendCxxFlagsIfSupported.cmake")
+ makefilesList = append(makefilesList, extPath)
+ android.WriteFileRuleVerbatim(ctx, extPath, cmakeExtAppendFlags)
+ extPath = android.PathForModuleGen(ctx, "cmake", "AddAidlLibrary.cmake")
+ makefilesList = append(makefilesList, extPath)
+ android.WriteFileRuleVerbatim(ctx, extPath, cmakeExtAddAidlLibrary)
+
+ // Generating the final zip file
+ zipRule := android.NewRuleBuilder(pctx, ctx)
+ zipCmd := zipRule.Command().
+ BuiltTool("soong_zip").
+ FlagWithOutput("-o ", m.zipPath)
+
+ // Packaging all sources into the zip file
+ if m.Properties.Include_sources {
+ var sourcesList android.Paths
+ for _, file := range sourceFiles {
+ sourcesList = append(sourcesList, file)
+ }
+
+ sourcesRspFile := android.PathForModuleObj(ctx, ctx.ModuleName()+"_sources.rsp")
+ zipCmd.FlagWithRspFileInputList("-r ", sourcesRspFile, sourcesList)
+ }
+
+ // Packaging all make files into the zip file
+ makefilesRspFile := android.PathForModuleObj(ctx, ctx.ModuleName()+"_makefiles.rsp")
+ zipCmd.
+ FlagWithArg("-C ", android.PathForModuleGen(ctx).OutputPath.String()).
+ FlagWithRspFileInputList("-r ", makefilesRspFile, makefilesList)
+
+ // Packaging all prebuilts into the zip file
+ if len(m.Properties.Prebuilts) > 0 {
+ var prebuiltsList android.Paths
+
+ ctx.VisitDirectDepsWithTag(cmakeSnapshotPrebuiltTag, func(dep android.Module) {
+ for _, file := range dep.FilesToInstall() {
+ prebuiltsList = append(prebuiltsList, file)
+ }
+ })
+
+ prebuiltsRspFile := android.PathForModuleObj(ctx, ctx.ModuleName()+"_prebuilts.rsp")
+ zipCmd.
+ FlagWithArg("-C ", android.PathForArbitraryOutput(ctx).String()).
+ FlagWithArg("-P ", "prebuilts").
+ FlagWithRspFileInputList("-r ", prebuiltsRspFile, prebuiltsList)
+ }
+
+ // Finish generating the final zip file
+ zipRule.Build(m.zipPath.String(), "archiving "+ctx.ModuleName())
+}
+
+func (m *CmakeSnapshot) OutputFiles(tag string) (android.Paths, error) {
+ switch tag {
+ case "":
+ return android.Paths{m.zipPath}, nil
+ default:
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+ }
+}
+
+func (m *CmakeSnapshot) AndroidMkEntries() []android.AndroidMkEntries {
+ return []android.AndroidMkEntries{{
+ Class: "DATA",
+ OutputFile: android.OptionalPathForPath(m.zipPath),
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
+ },
+ },
+ }}
+}
+
+func getModuleType(m *Module) string {
+ switch m.linker.(type) {
+ case *binaryDecorator:
+ return "executable"
+ case *libraryDecorator:
+ return "library"
+ case *testBinary:
+ return "executable"
+ }
+ panic(fmt.Sprintf("Unexpected module type: %T", m.compiler))
+}
+
+func getExtraLibs(m *Module) []string {
+ switch decorator := m.linker.(type) {
+ case *testBinary:
+ if decorator.testDecorator.gtest() {
+ return []string{"libgtest"}
+ }
+ }
+ return nil
+}
+
+func getIncludeDirs(ctx android.ModuleContext, m *Module) []string {
+ moduleDir := ctx.OtherModuleDir(m) + string(filepath.Separator)
+ switch decorator := m.compiler.(type) {
+ case *libraryDecorator:
+ return sliceWithPrefix(moduleDir, decorator.flagExporter.Properties.Export_include_dirs)
+ }
+ return nil
+}
+
+func cmakeSnapshotLoadHook(ctx android.LoadHookContext) {
+ props := struct {
+ Target struct {
+ Darwin struct {
+ Enabled *bool
+ }
+ Windows struct {
+ Enabled *bool
+ }
+ }
+ }{}
+ props.Target.Darwin.Enabled = proptools.BoolPtr(false)
+ props.Target.Windows.Enabled = proptools.BoolPtr(false)
+ ctx.AppendProperties(&props)
+}
+
+// cmake_snapshot allows defining source packages for release outside of Android build tree.
+// As a result of cmake_snapshot module build, a zip file is generated with CMake build definitions
+// for selected source modules, their dependencies and optionally also the source code itself.
+func CmakeSnapshotFactory() android.Module {
+ module := &CmakeSnapshot{}
+ module.AddProperties(&module.Properties)
+ android.AddLoadHook(module, cmakeSnapshotLoadHook)
+ android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
+ return module
+}
+
+func init() {
+ android.InitRegistrationContext.RegisterModuleType("cc_cmake_snapshot", CmakeSnapshotFactory)
+}
diff --git a/cc/cmake_snapshot_test.go b/cc/cmake_snapshot_test.go
new file mode 100644
index 0000000..8fca6c1
--- /dev/null
+++ b/cc/cmake_snapshot_test.go
@@ -0,0 +1,115 @@
+// 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 cc
+
+import (
+ "runtime"
+ "strings"
+ "testing"
+
+ "android/soong/android"
+)
+
+func wasGenerated(t *testing.T, m *android.TestingModule, fileName string, ruleType string) {
+ t.Helper()
+ ruleName := "<nil>"
+ if rule := m.MaybeOutput(fileName).Rule; rule != nil {
+ ruleName = rule.String()
+ }
+ if !strings.HasSuffix(ruleName, ruleType) {
+ t.Errorf("Main Cmake file wasn't generated properly, expected rule %v, found %v", ruleType, ruleName)
+ }
+}
+
+func TestEmptyCmakeSnapshot(t *testing.T) {
+ t.Parallel()
+ result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, `
+ cc_cmake_snapshot {
+ name: "foo",
+ modules: [],
+ prebuilts: ["libc++"],
+ include_sources: true,
+ }`)
+
+ if runtime.GOOS != "linux" {
+ t.Skip("CMake snapshots are only supported on Linux")
+ }
+
+ snapshotModule := result.ModuleForTests("foo", "linux_glibc_x86_64")
+
+ wasGenerated(t, &snapshotModule, "CMakeLists.txt", "rawFileCopy")
+ wasGenerated(t, &snapshotModule, "foo.zip", "")
+}
+
+func TestCmakeSnapshotWithBinary(t *testing.T) {
+ t.Parallel()
+ xtra := android.FixtureAddTextFile("some/module/Android.bp", `
+ cc_binary {
+ name: "foo_binary",
+ host_supported: true,
+ cmake_snapshot_supported: true,
+ }
+ `)
+ result := android.GroupFixturePreparers(PrepareForIntegrationTestWithCc, xtra).RunTestWithBp(t, `
+ cc_cmake_snapshot {
+ name: "foo",
+ modules: [
+ "foo_binary",
+ ],
+ include_sources: true,
+ }`)
+
+ if runtime.GOOS != "linux" {
+ t.Skip("CMake snapshots are only supported on Linux")
+ }
+
+ snapshotModule := result.ModuleForTests("foo", "linux_glibc_x86_64")
+
+ wasGenerated(t, &snapshotModule, "some/module/CMakeLists.txt", "rawFileCopy")
+}
+
+func TestCmakeSnapshotAsTestData(t *testing.T) {
+ t.Parallel()
+ result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, `
+ cc_test {
+ name: "foo_test",
+ gtest: false,
+ srcs: [
+ "foo_test.c",
+ ],
+ data: [
+ ":foo",
+ ],
+ target: {
+ android: {enabled: false},
+ },
+ }
+
+ cc_cmake_snapshot {
+ name: "foo",
+ modules: [],
+ prebuilts: ["libc++"],
+ include_sources: true,
+ }`)
+
+ if runtime.GOOS != "linux" {
+ t.Skip("CMake snapshots are only supported on Linux")
+ }
+
+ snapshotModule := result.ModuleForTests("foo", "linux_glibc_x86_64")
+
+ wasGenerated(t, &snapshotModule, "CMakeLists.txt", "rawFileCopy")
+ wasGenerated(t, &snapshotModule, "foo.zip", "")
+}
diff --git a/cc/compiler.go b/cc/compiler.go
index e52a6c3..21b8f2e 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -141,6 +141,22 @@
Flags []string
}
+ // Populated by aidl_interface CPP backend to let other modules (e.g. cc_cmake_snapshot)
+ // access actual source files and not generated cpp intermediary sources.
+ AidlInterface struct {
+ // list of aidl_interface sources
+ Sources []string `blueprint:"mutated"`
+
+ // root directory of AIDL sources
+ AidlRoot string `blueprint:"mutated"`
+
+ // AIDL backend language (e.g. "cpp", "ndk")
+ Lang string `blueprint:"mutated"`
+
+ // list of flags passed to AIDL generator
+ Flags []string `blueprint:"mutated"`
+ } `blueprint:"mutated"`
+
Renderscript struct {
// list of directories that will be added to the llvm-rs-cc include paths
Include_dirs []string
@@ -265,6 +281,10 @@
return []interface{}{&compiler.Properties, &compiler.Proto}
}
+func (compiler *baseCompiler) baseCompilerProps() BaseCompilerProperties {
+ return compiler.Properties
+}
+
func includeBuildDirectory(prop *bool) bool {
return proptools.BoolDefault(prop, true)
}
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 2f00aa7..164ec99 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -433,7 +433,7 @@
return
}
// Discard non-fuzz targets.
- if ok := fuzz.IsValid(ccModule.FuzzModuleStruct()); !ok {
+ if ok := fuzz.IsValid(ctx, ccModule.FuzzModuleStruct()); !ok {
return
}
diff --git a/cc/library.go b/cc/library.go
index 2fd3ded..cc8fafe 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1334,7 +1334,7 @@
// sourceAbiDiff registers a build statement to compare linked sAbi dump files (.lsdump).
func (library *libraryDecorator) sourceAbiDiff(ctx android.ModuleContext,
sourceDump, referenceDump android.Path,
- baseName, nameExt string, isLlndkOrNdk, allowExtensions bool,
+ baseName, nameExt string, isLlndk, allowExtensions bool,
sourceVersion, errorMessage string) {
extraFlags := []string{"-target-version", sourceVersion}
@@ -1346,7 +1346,7 @@
"-allow-unreferenced-changes",
"-allow-unreferenced-elf-symbol-changes")
}
- if isLlndkOrNdk {
+ if isLlndk {
extraFlags = append(extraFlags, "-consider-opaque-types-different")
}
if allowExtensions {
@@ -1362,23 +1362,23 @@
func (library *libraryDecorator) crossVersionAbiDiff(ctx android.ModuleContext,
sourceDump, referenceDump android.Path,
- baseName string, isLlndkOrNdk bool, sourceVersion, prevVersion string) {
+ baseName string, isLlndk bool, sourceVersion, prevVersion string) {
errorMessage := "error: Please follow https://android.googlesource.com/platform/development/+/main/vndk/tools/header-checker/README.md#configure-cross_version-abi-check to resolve the ABI difference between your source code and version " + prevVersion + "."
library.sourceAbiDiff(ctx, sourceDump, referenceDump, baseName, prevVersion,
- isLlndkOrNdk, true /* allowExtensions */, sourceVersion, errorMessage)
+ isLlndk, true /* allowExtensions */, sourceVersion, errorMessage)
}
func (library *libraryDecorator) sameVersionAbiDiff(ctx android.ModuleContext,
sourceDump, referenceDump android.Path,
- baseName, nameExt string, isLlndkOrNdk bool) {
+ baseName, nameExt string, isLlndk bool) {
libName := strings.TrimSuffix(baseName, filepath.Ext(baseName))
errorMessage := "error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l " + libName
library.sourceAbiDiff(ctx, sourceDump, referenceDump, baseName, nameExt,
- isLlndkOrNdk, false /* allowExtensions */, "current", errorMessage)
+ isLlndk, false /* allowExtensions */, "current", errorMessage)
}
func (library *libraryDecorator) optInAbiDiff(ctx android.ModuleContext,
@@ -1393,7 +1393,7 @@
}
library.sourceAbiDiff(ctx, sourceDump, referenceDump, baseName, nameExt,
- false /* isLlndkOrNdk */, false /* allowExtensions */, "current", errorMessage)
+ false /* isLlndk */, false /* allowExtensions */, "current", errorMessage)
}
func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, deps PathDeps, objs Objects, fileName string, soFile android.Path) {
@@ -1448,7 +1448,6 @@
dumpDir := filepath.Join("prebuilts", "abi-dumps", dumpDirName)
isLlndk := (tag == llndkLsdumpTag)
isApex := (tag == apexLsdumpTag)
- isNdk := (tag == ndkLsdumpTag)
binderBitness := ctx.DeviceConfig().BinderBitness()
nameExt := ""
if isLlndk {
@@ -1480,7 +1479,7 @@
prevDumpFile := getRefAbiDumpFile(ctx, prevDumpDir, fileName)
if prevDumpFile.Valid() {
library.crossVersionAbiDiff(ctx, sourceDump, prevDumpFile.Path(),
- fileName, isLlndk || isNdk, currVersion, nameExt+prevVersion)
+ fileName, isLlndk, currVersion, nameExt+prevVersion)
}
// Check against the current version.
sourceDump = implDump
@@ -1500,9 +1499,14 @@
currDumpFile := getRefAbiDumpFile(ctx, currDumpDir, fileName)
if currDumpFile.Valid() {
library.sameVersionAbiDiff(ctx, sourceDump, currDumpFile.Path(),
- fileName, nameExt, isLlndk || isNdk)
+ fileName, nameExt, isLlndk)
}
}
+ // Ensure that a module tagged with only platformLsdumpTag has ref_dump_dirs.
+ // Android.bp in vendor projects should be cleaned up before this is enforced for vendorLsdumpTag and productLsdumpTag.
+ if len(headerAbiChecker.Ref_dump_dirs) == 0 && len(tags) == 1 && tags[0] == platformLsdumpTag {
+ ctx.ModuleErrorf("header_abi_checker is explicitly enabled, but no ref_dump_dirs are specified.")
+ }
// Check against the opt-in reference dumps.
for i, optInDumpDir := range headerAbiChecker.Ref_dump_dirs {
optInDumpDirPath := android.PathForModuleSrc(ctx, optInDumpDir)
diff --git a/cc/linker.go b/cc/linker.go
index 3896c78..f325c12 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -310,6 +310,10 @@
return []interface{}{&linker.Properties, &linker.dynamicProperties}
}
+func (linker *baseLinker) baseLinkerProps() BaseLinkerProperties {
+ return linker.Properties
+}
+
func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs...)
deps.HeaderLibs = append(deps.HeaderLibs, linker.Properties.Header_libs...)
@@ -354,6 +358,7 @@
deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Vendor.Exclude_static_libs)
deps.HeaderLibs = append(deps.HeaderLibs, linker.Properties.Target.Vendor.Header_libs...)
deps.HeaderLibs = removeListFromList(deps.HeaderLibs, linker.Properties.Target.Vendor.Exclude_header_libs)
+ deps.ReexportHeaderLibHeaders = removeListFromList(deps.ReexportHeaderLibHeaders, linker.Properties.Target.Vendor.Exclude_header_libs)
deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Vendor.Exclude_static_libs)
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Vendor.Exclude_static_libs)
deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Target.Vendor.Exclude_runtime_libs)
@@ -367,6 +372,7 @@
deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Target.Product.Static_libs...)
deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Product.Exclude_static_libs)
deps.HeaderLibs = removeListFromList(deps.HeaderLibs, linker.Properties.Target.Product.Exclude_header_libs)
+ deps.ReexportHeaderLibHeaders = removeListFromList(deps.ReexportHeaderLibHeaders, linker.Properties.Target.Product.Exclude_header_libs)
deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Product.Exclude_static_libs)
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Product.Exclude_static_libs)
deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Target.Product.Exclude_runtime_libs)
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 9e727a1..5b86c64 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -16,12 +16,12 @@
import (
"android/soong/android"
+ "android/soong/etc"
"strings"
)
var (
llndkLibrarySuffix = ".llndk"
- llndkHeadersSuffix = ".llndk"
)
// Holds properties to describe a stub shared library based on the provided version file.
@@ -78,3 +78,143 @@
ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES",
strings.Join(android.SortedKeys(movedToApexLlndkLibraries), " "))
}
+
+func init() {
+ RegisterLlndkLibraryTxtType(android.InitRegistrationContext)
+}
+
+func RegisterLlndkLibraryTxtType(ctx android.RegistrationContext) {
+ ctx.RegisterParallelSingletonModuleType("llndk_libraries_txt", llndkLibrariesTxtFactory)
+}
+
+type llndkLibrariesTxtModule struct {
+ android.SingletonModuleBase
+
+ outputFile android.OutputPath
+ moduleNames []string
+ fileNames []string
+}
+
+var _ etc.PrebuiltEtcModule = &llndkLibrariesTxtModule{}
+var _ android.OutputFileProducer = &llndkLibrariesTxtModule{}
+
+// llndk_libraries_txt is a singleton module whose content is a list of LLNDK libraries
+// generated by Soong but can be referenced by other modules.
+// For example, apex_vndk can depend on these files as prebuilt.
+// Make uses LLNDK_LIBRARIES to determine which libraries to install.
+// HWASAN is only part of the LL-NDK in builds in which libc depends on HWASAN.
+// Therefore, by removing the library here, we cause it to only be installed if libc
+// depends on it.
+func llndkLibrariesTxtFactory() android.SingletonModule {
+ m := &llndkLibrariesTxtModule{}
+ android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
+ return m
+}
+
+func (txt *llndkLibrariesTxtModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ filename := txt.Name()
+
+ txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath
+
+ installPath := android.PathForModuleInstall(ctx, "etc")
+ ctx.InstallFile(installPath, filename, txt.outputFile)
+}
+
+func (txt *llndkLibrariesTxtModule) GenerateSingletonBuildActions(ctx android.SingletonContext) {
+ if txt.outputFile.String() == "" {
+ // Skip if target file path is empty
+ return
+ }
+
+ ctx.VisitAllModules(func(m android.Module) {
+ if c, ok := m.(*Module); ok && c.VendorProperties.IsLLNDK && !c.Header() && !c.IsVndkPrebuiltLibrary() {
+ filename, err := getVndkFileName(c)
+ if err != nil {
+ ctx.ModuleErrorf(m, "%s", err)
+ }
+
+ if !strings.HasPrefix(ctx.ModuleName(m), "libclang_rt.hwasan") {
+ txt.moduleNames = append(txt.moduleNames, ctx.ModuleName(m))
+ }
+ txt.fileNames = append(txt.fileNames, filename)
+ }
+ })
+ txt.moduleNames = android.SortedUniqueStrings(txt.moduleNames)
+ txt.fileNames = android.SortedUniqueStrings(txt.fileNames)
+
+ android.WriteFileRule(ctx, txt.outputFile, strings.Join(txt.fileNames, "\n"))
+}
+
+func (txt *llndkLibrariesTxtModule) AndroidMkEntries() []android.AndroidMkEntries {
+ return []android.AndroidMkEntries{{
+ Class: "ETC",
+ OutputFile: android.OptionalPathForPath(txt.outputFile),
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.SetString("LOCAL_MODULE_STEM", txt.outputFile.Base())
+ },
+ },
+ }}
+}
+
+func (txt *llndkLibrariesTxtModule) MakeVars(ctx android.MakeVarsContext) {
+ ctx.Strict("LLNDK_LIBRARIES", strings.Join(txt.moduleNames, " "))
+}
+
+// PrebuiltEtcModule interface
+func (txt *llndkLibrariesTxtModule) OutputFile() android.OutputPath {
+ return txt.outputFile
+}
+
+// PrebuiltEtcModule interface
+func (txt *llndkLibrariesTxtModule) BaseDir() string {
+ return "etc"
+}
+
+// PrebuiltEtcModule interface
+func (txt *llndkLibrariesTxtModule) SubDir() string {
+ return ""
+}
+
+func (txt *llndkLibrariesTxtModule) OutputFiles(tag string) (android.Paths, error) {
+ return android.Paths{txt.outputFile}, nil
+}
+
+func llndkMutator(mctx android.BottomUpMutatorContext) {
+ m, ok := mctx.Module().(*Module)
+ if !ok {
+ return
+ }
+
+ if shouldSkipLlndkMutator(mctx, m) {
+ return
+ }
+
+ lib, isLib := m.linker.(*libraryDecorator)
+ prebuiltLib, isPrebuiltLib := m.linker.(*prebuiltLibraryLinker)
+
+ if m.InVendorOrProduct() && isLib && lib.hasLLNDKStubs() {
+ m.VendorProperties.IsLLNDK = true
+ }
+ if m.InVendorOrProduct() && isPrebuiltLib && prebuiltLib.hasLLNDKStubs() {
+ m.VendorProperties.IsLLNDK = true
+ }
+
+ if m.IsVndkPrebuiltLibrary() && !m.IsVndk() {
+ m.VendorProperties.IsLLNDK = true
+ }
+}
+
+// Check for modules that mustn't be LLNDK
+func shouldSkipLlndkMutator(mctx android.BottomUpMutatorContext, m *Module) bool {
+ if !m.Enabled(mctx) {
+ return true
+ }
+ if !m.Device() {
+ return true
+ }
+ if m.Target().NativeBridge == android.NativeBridgeEnabled {
+ return true
+ }
+ return false
+}
diff --git a/cc/makevars.go b/cc/makevars.go
index 9251d6a..51bcbf0 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -279,7 +279,7 @@
sanitizerLibs := android.SortedStringValues(sanitizerVariables)
var sanitizerLibStems []string
ctx.VisitAllModules(func(m android.Module) {
- if !m.Enabled() {
+ if !m.Enabled(ctx) {
return
}
diff --git a/cc/ndk_abi.go b/cc/ndk_abi.go
index 86166dc..5beeab1 100644
--- a/cc/ndk_abi.go
+++ b/cc/ndk_abi.go
@@ -40,7 +40,7 @@
func (n *ndkAbiDumpSingleton) GenerateBuildActions(ctx android.SingletonContext) {
var depPaths android.Paths
ctx.VisitAllModules(func(module android.Module) {
- if !module.Enabled() {
+ if !module.Enabled(ctx) {
return
}
@@ -78,7 +78,7 @@
func (n *ndkAbiDiffSingleton) GenerateBuildActions(ctx android.SingletonContext) {
var depPaths android.Paths
ctx.VisitAllModules(func(module android.Module) {
- if m, ok := module.(android.Module); ok && !m.Enabled() {
+ if m, ok := module.(android.Module); ok && !m.Enabled(ctx) {
return
}
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 25231fd..f326068 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -148,7 +148,7 @@
}
func (this *stubDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
- if !ctx.Module().Enabled() {
+ if !ctx.Module().Enabled(ctx) {
return nil
}
if ctx.Target().NativeBridge == android.NativeBridgeEnabled {
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index e815172..3c48f68 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -150,7 +150,7 @@
var installPaths android.Paths
var licensePaths android.Paths
ctx.VisitAllModules(func(module android.Module) {
- if m, ok := module.(android.Module); ok && !m.Enabled() {
+ if m, ok := module.(android.Module); ok && !m.Enabled(ctx) {
return
}
diff --git a/cc/sabi.go b/cc/sabi.go
index cd9bf63..64eab41 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -31,7 +31,6 @@
const (
apexLsdumpTag lsdumpTag = "APEX"
llndkLsdumpTag lsdumpTag = "LLNDK"
- ndkLsdumpTag lsdumpTag = "NDK"
platformLsdumpTag lsdumpTag = "PLATFORM"
productLsdumpTag lsdumpTag = "PRODUCT"
vendorLsdumpTag lsdumpTag = "VENDOR"
@@ -42,12 +41,8 @@
switch *tag {
case apexLsdumpTag:
return "platform"
- case ndkLsdumpTag:
- return "ndk"
case llndkLsdumpTag:
return "vndk"
- case platformLsdumpTag:
- return "platform"
default:
return ""
}
@@ -137,13 +132,10 @@
if m.isImplementationForLLNDKPublic() {
result = append(result, llndkLsdumpTag)
}
- if m.IsNdk(ctx.Config()) {
- result = append(result, ndkLsdumpTag)
- }
- // APEX and opt-in platform dumps are placed in the same directory.
if m.library.hasStubsVariants() {
result = append(result, apexLsdumpTag)
- } else if headerAbiChecker.enabled() {
+ }
+ if headerAbiChecker.enabled() {
result = append(result, platformLsdumpTag)
}
} else if headerAbiChecker.enabled() {
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 2a1ee3c..1a94729 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -82,7 +82,7 @@
hwasanGlobalOptions = []string{"heap_history_size=1023", "stack_history_size=512",
"export_memory_stats=0", "max_malloc_fill_size=131072", "malloc_fill_byte=0"}
memtagStackCommonFlags = []string{"-march=armv8-a+memtag"}
- memtagStackLlvmFlags = []string{"-dom-tree-reachability-max-bbs-to-explore=128"}
+ memtagStackLlvmFlags = []string{"-dom-tree-reachability-max-bbs-to-explore=128"}
hostOnlySanitizeFlags = []string{"-fno-sanitize-recover=all"}
deviceOnlySanitizeFlags = []string{"-fsanitize-trap=all"}
@@ -176,11 +176,11 @@
func (t SanitizerType) registerMutators(ctx android.RegisterMutatorsContext) {
switch t {
- case cfi, Hwasan, Asan, tsan, Fuzzer, scs:
+ case cfi, Hwasan, Asan, tsan, Fuzzer, scs, Memtag_stack:
sanitizer := &sanitizerSplitMutator{t}
ctx.TopDown(t.variationName()+"_markapexes", sanitizer.markSanitizableApexesMutator)
ctx.Transition(t.variationName(), sanitizer)
- case Memtag_heap, Memtag_stack, Memtag_globals, intOverflow:
+ case Memtag_heap, Memtag_globals, intOverflow:
// do nothing
default:
panic(fmt.Errorf("unknown SanitizerType %d", t))
@@ -407,6 +407,7 @@
android.RegisterMakeVarsProvider(pctx, cfiMakeVarsProvider)
android.RegisterMakeVarsProvider(pctx, hwasanMakeVarsProvider)
+ android.RegisterMakeVarsProvider(pctx, memtagStackMakeVarsProvider)
}
func (sanitize *sanitize) props() []interface{} {
@@ -683,10 +684,14 @@
s.Diag.Cfi = nil
}
- // HWASan ramdisk (which is built from recovery) goes over some bootloader limit.
- // Keep libc instrumented so that ramdisk / vendor_ramdisk / recovery can run hwasan-instrumented code if necessary.
- if (ctx.inRamdisk() || ctx.inVendorRamdisk() || ctx.inRecovery()) && !strings.HasPrefix(ctx.ModuleDir(), "bionic/libc") {
- s.Hwaddress = nil
+ if ctx.inRamdisk() || ctx.inVendorRamdisk() || ctx.inRecovery() {
+ // HWASan ramdisk (which is built from recovery) goes over some bootloader limit.
+ // Keep libc instrumented so that ramdisk / vendor_ramdisk / recovery can run hwasan-instrumented code if necessary.
+ if !strings.HasPrefix(ctx.ModuleDir(), "bionic/libc") {
+ s.Hwaddress = nil
+ }
+ // Memtag stack in ramdisk makes pKVM unhappy.
+ s.Memtag_stack = nil
}
if ctx.staticBinary() {
@@ -858,7 +863,7 @@
flags.Local.CFlags = append(flags.Local.CFlags, cfiCflags...)
flags.Local.AsFlags = append(flags.Local.AsFlags, cfiAsflags...)
- flags.CFlagsDeps = append(flags.CFlagsDeps, android.PathForSource(ctx, cfiBlocklistPath + "/" + cfiBlocklistFilename))
+ flags.CFlagsDeps = append(flags.CFlagsDeps, android.PathForSource(ctx, cfiBlocklistPath+"/"+cfiBlocklistFilename))
if Bool(s.Properties.Sanitize.Config.Cfi_assembly_support) {
flags.Local.CFlags = append(flags.Local.CFlags, cfiAssemblySupportFlag)
}
@@ -1310,6 +1315,8 @@
hwasanStaticLibs(mctx.Config()).add(c, c.Module().Name())
} else if s.sanitizer == cfi {
cfiStaticLibs(mctx.Config()).add(c, c.Module().Name())
+ } else if s.sanitizer == Memtag_stack {
+ memtagStackStaticLibs(mctx.Config()).add(c, c.Module().Name());
}
}
} else if c.IsSanitizerEnabled(s.sanitizer) {
@@ -1378,7 +1385,7 @@
// Add the dependency to the runtime library for each of the sanitizer variants
func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) {
if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
- if !c.Enabled() {
+ if !c.Enabled(mctx) {
return
}
var sanitizers []string
@@ -1559,7 +1566,7 @@
addStaticDeps(config.BuiltinsRuntimeLibrary(toolchain), true)
}
- if runtimeSharedLibrary != "" && (toolchain.Bionic() || toolchain.Musl() || c.sanitize.Properties.UbsanRuntimeDep) {
+ if runtimeSharedLibrary != "" && (toolchain.Bionic() || toolchain.Musl()) {
// UBSan is supported on non-bionic linux host builds as well
// Adding dependency to the runtime library. We are using *FarVariation*
@@ -1722,6 +1729,14 @@
}).(*sanitizerStaticLibsMap)
}
+var memtagStackStaticLibsKey = android.NewOnceKey("memtagStackStaticLibs")
+
+func memtagStackStaticLibs(config android.Config) *sanitizerStaticLibsMap {
+ return config.Once(memtagStackStaticLibsKey, func() interface{} {
+ return newSanitizerStaticLibsMap(Memtag_stack)
+ }).(*sanitizerStaticLibsMap)
+}
+
func enableMinimalRuntime(sanitize *sanitize) bool {
if sanitize.isSanitizerEnabled(Asan) {
return false
@@ -1768,3 +1783,7 @@
func hwasanMakeVarsProvider(ctx android.MakeVarsContext) {
hwasanStaticLibs(ctx.Config()).exportToMake(ctx)
}
+
+func memtagStackMakeVarsProvider(ctx android.MakeVarsContext) {
+ memtagStackStaticLibs(ctx.Config()).exportToMake(ctx)
+}
diff --git a/cc/sdk.go b/cc/sdk.go
index ce0fdc2..4925ce1 100644
--- a/cc/sdk.go
+++ b/cc/sdk.go
@@ -49,15 +49,18 @@
modules[1].(*Module).Properties.IsSdkVariant = true
if ctx.Config().UnbundledBuildApps() {
- // For an unbundled apps build, hide the platform variant from Make.
+ // For an unbundled apps build, hide the platform variant from Make
+ // so that other Make modules don't link against it, but against the
+ // SDK variant.
modules[0].(*Module).Properties.HideFromMake = true
- modules[0].(*Module).Properties.PreventInstall = true
} else {
// For a platform build, mark the SDK variant so that it gets a ".sdk" suffix when
// exposed to Make.
modules[1].(*Module).Properties.SdkAndPlatformVariantVisibleToMake = true
- modules[1].(*Module).Properties.PreventInstall = true
}
+ // SDK variant never gets installed because the variant is to be embedded in
+ // APKs, not to be installed to the platform.
+ modules[1].(*Module).Properties.PreventInstall = true
ctx.AliasVariation("")
} else {
if isCcModule {
diff --git a/cc/test.go b/cc/test.go
index 3a1a3af..a96af31 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -359,6 +359,12 @@
func (test *testBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
flags = test.binaryDecorator.linkerFlags(ctx, flags)
flags = test.testDecorator.linkerFlags(ctx, flags)
+
+ // Add a default rpath to allow tests to dlopen libraries specified in data_libs.
+ // Host modules already get an rpath specified in linker.go.
+ if !ctx.Host() {
+ flags.Global.LdFlags = append(flags.Global.LdFlags, `-Wl,-rpath,\$$ORIGIN`)
+ }
return flags
}
diff --git a/cc/testing.go b/cc/testing.go
index 55d3e71..989be02 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -35,6 +35,7 @@
ctx.RegisterModuleType("prebuilt_build_tool", android.NewPrebuiltBuildTool)
ctx.RegisterModuleType("cc_benchmark", BenchmarkFactory)
+ ctx.RegisterModuleType("cc_cmake_snapshot", CmakeSnapshotFactory)
ctx.RegisterModuleType("cc_object", ObjectFactory)
ctx.RegisterModuleType("cc_genrule", GenRuleFactory)
ctx.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory)
@@ -555,6 +556,7 @@
ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
RegisterVndkLibraryTxtTypes(ctx)
+ RegisterLlndkLibraryTxtType(ctx)
}),
// Additional files needed in tests that disallow non-existent source files.
@@ -703,6 +705,7 @@
ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
RegisterVndkLibraryTxtTypes(ctx)
+ RegisterLlndkLibraryTxtType(ctx)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
android.RegisterPrebuiltMutators(ctx)
diff --git a/cc/tidy.go b/cc/tidy.go
index 76ac7d5..ec1e8a2 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -220,7 +220,7 @@
// (1) Collect all obj/tidy files into OS-specific groups.
ctx.VisitAllModuleVariants(module, func(variant android.Module) {
- if ctx.Config().KatiEnabled() && android.ShouldSkipAndroidMkProcessing(variant) {
+ if ctx.Config().KatiEnabled() && android.ShouldSkipAndroidMkProcessing(ctx, variant) {
return
}
if m, ok := variant.(*Module); ok {
diff --git a/cc/vndk.go b/cc/vndk.go
index 14b44b6..548992d 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -219,7 +219,6 @@
type moduleListerFunc func(ctx android.SingletonContext) (moduleNames, fileNames []string)
var (
- llndkLibraries = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsLLNDK && !m.Header() })
vndkSPLibraries = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKSP })
vndkCoreLibraries = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKCore })
vndkPrivateLibraries = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKPrivate })
@@ -323,8 +322,8 @@
}
// Check for modules that mustn't be VNDK
-func shouldSkipVndkMutator(m *Module) bool {
- if !m.Enabled() {
+func shouldSkipVndkMutator(ctx android.ConfigAndErrorContext, m *Module) bool {
+ if !m.Enabled(ctx) {
return true
}
if !m.Device() {
@@ -339,7 +338,7 @@
}
func IsForVndkApex(mctx android.BottomUpMutatorContext, m *Module) bool {
- if shouldSkipVndkMutator(m) {
+ if shouldSkipVndkMutator(mctx, m) {
return false
}
@@ -370,7 +369,7 @@
return
}
- if shouldSkipVndkMutator(m) {
+ if shouldSkipVndkMutator(mctx, m) {
return
}
@@ -378,19 +377,12 @@
prebuiltLib, isPrebuiltLib := m.linker.(*prebuiltLibraryLinker)
if m.InVendorOrProduct() && isLib && lib.hasLLNDKStubs() {
- m.VendorProperties.IsLLNDK = true
m.VendorProperties.IsVNDKPrivate = Bool(lib.Properties.Llndk.Private)
}
if m.InVendorOrProduct() && isPrebuiltLib && prebuiltLib.hasLLNDKStubs() {
- m.VendorProperties.IsLLNDK = true
m.VendorProperties.IsVNDKPrivate = Bool(prebuiltLib.Properties.Llndk.Private)
}
- if m.IsVndkPrebuiltLibrary() && !m.IsVndk() {
- m.VendorProperties.IsLLNDK = true
- // TODO(b/280697209): copy "llndk.private" flag to vndk_prebuilt_shared
- }
-
if (isLib && lib.buildShared()) || (isPrebuiltLib && prebuiltLib.buildShared()) {
if m.vndkdep != nil && m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() {
processVndkLibrary(mctx, m)
@@ -404,8 +396,6 @@
}
func RegisterVndkLibraryTxtTypes(ctx android.RegistrationContext) {
- ctx.RegisterParallelSingletonModuleType("llndk_libraries_txt", llndkLibrariesTxtFactory)
- ctx.RegisterParallelSingletonModuleType("llndk_libraries_txt_for_apex", llndkLibrariesTxtApexOnlyFactory)
ctx.RegisterParallelSingletonModuleType("vndksp_libraries_txt", vndkSPLibrariesTxtFactory)
ctx.RegisterParallelSingletonModuleType("vndkcore_libraries_txt", vndkCoreLibrariesTxtFactory)
ctx.RegisterParallelSingletonModuleType("vndkprivate_libraries_txt", vndkPrivateLibrariesTxtFactory)
@@ -435,25 +425,6 @@
var _ etc.PrebuiltEtcModule = &vndkLibrariesTxt{}
var _ android.OutputFileProducer = &vndkLibrariesTxt{}
-// llndk_libraries_txt is a singleton module whose content is a list of LLNDK libraries
-// generated by Soong.
-// Make uses LLNDK_LIBRARIES to determine which libraries to install.
-// HWASAN is only part of the LLNDK in builds in which libc depends on HWASAN.
-// Therefore, by removing the library here, we cause it to only be installed if libc
-// depends on it.
-func llndkLibrariesTxtFactory() android.SingletonModule {
- return newVndkLibrariesWithMakeVarFilter(llndkLibraries, "LLNDK_LIBRARIES", "libclang_rt.hwasan")
-}
-
-// llndk_libraries_txt_for_apex is a singleton module that provide the same LLNDK libraries list
-// with the llndk_libraries_txt, but skips setting make variable LLNDK_LIBRARIES. So, it must not
-// be used without installing llndk_libraries_txt singleton.
-// We include llndk_libraries_txt by default to install the llndk.libraries.txt file to system/etc.
-// This singleton module is to install the llndk.libraries.<ver>.txt file to vndk apex.
-func llndkLibrariesTxtApexOnlyFactory() android.SingletonModule {
- return newVndkLibrariesWithMakeVarFilter(llndkLibraries, "", "libclang_rt.hwasan")
-}
-
// vndksp_libraries_txt is a singleton module whose content is a list of VNDKSP libraries
// generated by Soong but can be referenced by other modules.
// For example, apex_vndk can depend on these files as prebuilt.
@@ -577,6 +548,7 @@
func (txt *vndkLibrariesTxt) OutputFiles(tag string) (android.Paths, error) {
return android.Paths{txt.outputFile}, nil
}
+
func getVndkFileName(m *Module) (string, error) {
if library, ok := m.linker.(*libraryDecorator); ok {
return library.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil
diff --git a/cmd/release_config/build_flag/main.go b/cmd/release_config/build_flag/main.go
index ec7d64f..cc2b57a 100644
--- a/cmd/release_config/build_flag/main.go
+++ b/cmd/release_config/build_flag/main.go
@@ -266,7 +266,7 @@
return fmt.Errorf("Unknown build flag %s", name)
}
if valueDir == "" {
- mapDir, err := GetMapDir(*flagArtifact.Traces[len(flagArtifact.Traces)-1].Source)
+ mapDir, err := configs.GetFlagValueDirectory(release, flagArtifact)
if err != nil {
return err
}
@@ -325,7 +325,12 @@
}
if len(commonFlags.targetReleases) == 0 {
- commonFlags.targetReleases = rc_lib.StringList{"trunk_staging"}
+ release, ok := os.LookupEnv("TARGET_RELEASE")
+ if ok {
+ commonFlags.targetReleases = rc_lib.StringList{release}
+ } else {
+ commonFlags.targetReleases = rc_lib.StringList{"trunk_staging"}
+ }
}
if err = os.Chdir(commonFlags.top); err != nil {
diff --git a/cmd/release_config/crunch_flags/main.go b/cmd/release_config/crunch_flags/main.go
index 95342b1..8a80a02 100644
--- a/cmd/release_config/crunch_flags/main.go
+++ b/cmd/release_config/crunch_flags/main.go
@@ -16,11 +16,12 @@
)
var (
- // When a flag declaration has an initial value that is a string, the default workflow is PREBUILT.
- // If the flag name starts with any of prefixes in manualFlagNamePrefixes, it is MANUAL.
+ // When a flag declaration has an initial value that is a string, the default workflow is WorkflowPrebuilt.
+ // If the flag name starts with any of prefixes in manualFlagNamePrefixes, it is WorkflowManual.
manualFlagNamePrefixes []string = []string{
"RELEASE_ACONFIG_",
"RELEASE_PLATFORM_",
+ "RELEASE_BUILD_FLAGS_",
}
// Set `aconfig_flags_only: true` in these release configs.
@@ -132,28 +133,30 @@
Containers: containers,
}
description = ""
- // Most build flags are `workflow: PREBUILT`.
- workflow := rc_proto.Workflow(rc_proto.Workflow_PREBUILT)
+ // Most build flags are `workflow: WorkflowPrebuilt`.
+ workflow := rc_proto.Workflow(rc_proto.Workflow_WorkflowPrebuilt)
switch {
case declName == "RELEASE_ACONFIG_VALUE_SETS":
- rootAconfigModule = declValue[1 : len(declValue)-1]
+ if strings.HasPrefix(declValue, "\"") {
+ rootAconfigModule = declValue[1 : len(declValue)-1]
+ }
continue
case strings.HasPrefix(declValue, "\""):
- // String values mean that the flag workflow is (most likely) either MANUAL or PREBUILT.
+ // String values mean that the flag workflow is (most likely) either WorkflowManual or WorkflowPrebuilt.
declValue = declValue[1 : len(declValue)-1]
flagDeclaration.Value = &rc_proto.Value{Val: &rc_proto.Value_StringValue{declValue}}
for _, prefix := range manualFlagNamePrefixes {
if strings.HasPrefix(declName, prefix) {
- workflow = rc_proto.Workflow(rc_proto.Workflow_MANUAL)
+ workflow = rc_proto.Workflow(rc_proto.Workflow_WorkflowManual)
break
}
}
case declValue == "False" || declValue == "True":
- // Boolean values are LAUNCH flags.
+ // Boolean values are WorkflowLaunch flags.
flagDeclaration.Value = &rc_proto.Value{Val: &rc_proto.Value_BoolValue{declValue == "True"}}
- workflow = rc_proto.Workflow(rc_proto.Workflow_LAUNCH)
+ workflow = rc_proto.Workflow(rc_proto.Workflow_WorkflowLaunch)
case declValue == "None":
- // Use PREBUILT workflow with no initial value.
+ // Use WorkflowPrebuilt workflow with no initial value.
default:
fmt.Printf("%s: Unexpected value %s=%s\n", path, declName, declValue)
}
diff --git a/cmd/release_config/release_config/main.go b/cmd/release_config/release_config/main.go
index c443257..0617838 100644
--- a/cmd/release_config/release_config/main.go
+++ b/cmd/release_config/release_config/main.go
@@ -35,6 +35,7 @@
var product string
var allMake bool
var useBuildVar bool
+ var guard bool
defaultRelease := os.Getenv("TARGET_RELEASE")
if defaultRelease == "" {
@@ -50,8 +51,9 @@
flag.BoolVar(&textproto, "textproto", true, "write artifacts as text protobuf")
flag.BoolVar(&json, "json", true, "write artifacts as json")
flag.BoolVar(&pb, "pb", true, "write artifacts as binary protobuf")
- flag.BoolVar(&allMake, "all_make", true, "write makefiles for all release configs")
+ flag.BoolVar(&allMake, "all_make", false, "write makefiles for all release configs")
flag.BoolVar(&useBuildVar, "use_get_build_var", false, "use get_build_var PRODUCT_RELEASE_CONFIG_MAPS")
+ flag.BoolVar(&guard, "guard", true, "whether to guard with RELEASE_BUILD_FLAGS_IN_PROTOBUF")
flag.Parse()
@@ -70,30 +72,35 @@
if err != nil {
panic(err)
}
- releaseName := config.Name
err = os.MkdirAll(outputDir, 0775)
if err != nil {
panic(err)
}
- if err = config.WritePartitionBuildFlags(outputDir, product, targetRelease); err != nil {
+ makefilePath := filepath.Join(outputDir, fmt.Sprintf("release_config-%s-%s.varmk", product, targetRelease))
+ useProto, ok := config.FlagArtifacts["RELEASE_BUILD_FLAGS_IN_PROTOBUF"]
+ if guard && (!ok || rc_lib.MarshalValue(useProto.Value) == "") {
+ // We were told to guard operation and either we have no build flag, or it is False.
+ // Write an empty file so that release_config.mk will use the old process.
+ os.WriteFile(makefilePath, []byte{}, 0644)
+ return
+ }
+ // Write the makefile where release_config.mk is going to look for it.
+ err = configs.WriteMakefile(makefilePath, targetRelease)
+ if err != nil {
panic(err)
}
-
if allMake {
- for k, _ := range configs.ReleaseConfigs {
- makefilePath := filepath.Join(outputDir, fmt.Sprintf("release_config-%s-%s.mk", product, k))
- err = configs.WriteMakefile(makefilePath, k)
- if err != nil {
- panic(err)
+ // Write one makefile per release config, using the canonical release name.
+ for _, c := range configs.GetSortedReleaseConfigs() {
+ if c.Name != targetRelease {
+ makefilePath = filepath.Join(outputDir, fmt.Sprintf("release_config-%s-%s.varmk", product, c.Name))
+ err = configs.WriteMakefile(makefilePath, c.Name)
+ if err != nil {
+ panic(err)
+ }
}
}
- } else {
- makefilePath := filepath.Join(outputDir, fmt.Sprintf("release_config-%s-%s.mk", product, releaseName))
- err = configs.WriteMakefile(makefilePath, targetRelease)
- if err != nil {
- panic(err)
- }
}
if json {
err = configs.WriteArtifact(outputDir, product, "json")
@@ -113,4 +120,8 @@
panic(err)
}
}
+ if err = config.WritePartitionBuildFlags(outputDir, product, targetRelease); err != nil {
+ panic(err)
+ }
+
}
diff --git a/cmd/release_config/release_config_lib/flag_value.go b/cmd/release_config/release_config_lib/flag_value.go
index e155e77..59021e2 100644
--- a/cmd/release_config/release_config_lib/flag_value.go
+++ b/cmd/release_config/release_config_lib/flag_value.go
@@ -52,6 +52,9 @@
}
func MarshalValue(value *rc_proto.Value) string {
+ if value == nil {
+ return ""
+ }
switch val := value.Val.(type) {
case *rc_proto.Value_UnspecifiedValue:
// Value was never set.
diff --git a/cmd/release_config/release_config_lib/flag_value_test.go b/cmd/release_config/release_config_lib/flag_value_test.go
index aaa4caf..8a98baf 100644
--- a/cmd/release_config/release_config_lib/flag_value_test.go
+++ b/cmd/release_config/release_config_lib/flag_value_test.go
@@ -24,7 +24,7 @@
"google.golang.org/protobuf/proto"
)
-type testCaseFlagValue struct {
+type testCaseFlagValueFactory struct {
protoPath string
name string
data []byte
@@ -32,14 +32,14 @@
err error
}
-func (tc testCaseFlagValue) assertProtoEqual(t *testing.T, expected, actual proto.Message) {
+func (tc testCaseFlagValueFactory) assertProtoEqual(t *testing.T, expected, actual proto.Message) {
if !proto.Equal(expected, actual) {
t.Errorf("Expected %q found %q", expected, actual)
}
}
-func TestFlagValue(t *testing.T) {
- testCases := []testCaseFlagValue{
+func TestFlagValueFactory(t *testing.T) {
+ testCases := []testCaseFlagValueFactory{
{
name: "stringVal",
protoPath: "build/release/flag_values/test/RELEASE_FOO.textproto",
@@ -65,3 +65,50 @@
tc.assertProtoEqual(t, &tc.expected, &actual.proto)
}
}
+
+type testCaseMarshalValue struct {
+ name string
+ value *rc_proto.Value
+ expected string
+}
+
+func TestMarshalValue(t *testing.T) {
+ testCases := []testCaseMarshalValue{
+ {
+ name: "nil",
+ value: nil,
+ expected: "",
+ },
+ {
+ name: "unspecified",
+ value: &rc_proto.Value{},
+ expected: "",
+ },
+ {
+ name: "false",
+ value: &rc_proto.Value{Val: &rc_proto.Value_BoolValue{false}},
+ expected: "",
+ },
+ {
+ name: "true",
+ value: &rc_proto.Value{Val: &rc_proto.Value_BoolValue{true}},
+ expected: "true",
+ },
+ {
+ name: "string",
+ value: &rc_proto.Value{Val: &rc_proto.Value_StringValue{"BAR"}},
+ expected: "BAR",
+ },
+ {
+ name: "obsolete",
+ value: &rc_proto.Value{Val: &rc_proto.Value_Obsolete{true}},
+ expected: " #OBSOLETE",
+ },
+ }
+ for _, tc := range testCases {
+ actual := MarshalValue(tc.value)
+ if actual != tc.expected {
+ t.Errorf("Expected %q found %q", tc.expected, actual)
+ }
+ }
+}
diff --git a/cmd/release_config/release_config_lib/release_config.go b/cmd/release_config/release_config_lib/release_config.go
index e51ff08..82adc34 100644
--- a/cmd/release_config/release_config_lib/release_config.go
+++ b/cmd/release_config/release_config_lib/release_config.go
@@ -29,7 +29,7 @@
// One directory's contribution to the a release config.
type ReleaseConfigContribution struct {
- // Paths to files providing this config.
+ // Path of the file providing this config contribution.
path string
// The index of the config directory where this release config
@@ -69,6 +69,9 @@
// Unmarshalled flag artifacts
FlagArtifacts FlagArtifacts
+ // The files used by this release config
+ FilesUsedMap map[string]bool
+
// Generated release config
ReleaseConfigArtifact *rc_proto.ReleaseConfigArtifact
@@ -80,17 +83,31 @@
}
func ReleaseConfigFactory(name string, index int) (c *ReleaseConfig) {
- return &ReleaseConfig{Name: name, DeclarationIndex: index}
+ return &ReleaseConfig{
+ Name: name,
+ DeclarationIndex: index,
+ FilesUsedMap: make(map[string]bool),
+ }
}
func (config *ReleaseConfig) InheritConfig(iConfig *ReleaseConfig) error {
+ for f := range iConfig.FilesUsedMap {
+ config.FilesUsedMap[f] = true
+ }
for _, fa := range iConfig.FlagArtifacts {
name := *fa.FlagDeclaration.Name
myFa, ok := config.FlagArtifacts[name]
if !ok {
return fmt.Errorf("Could not inherit flag %s from %s", name, iConfig.Name)
}
- if len(fa.Traces) > 1 {
+ if name == "RELEASE_ACONFIG_VALUE_SETS" {
+ // If there is a value assigned, add the trace.
+ if len(fa.Value.GetStringValue()) > 0 {
+ myFa.Traces = append(myFa.Traces, fa.Traces...)
+ myFa.Value = &rc_proto.Value{Val: &rc_proto.Value_StringValue{
+ myFa.Value.GetStringValue() + " " + fa.Value.GetStringValue()}}
+ }
+ } else if len(fa.Traces) > 1 {
// A value was assigned. Set our value.
myFa.Traces = append(myFa.Traces, fa.Traces[1:]...)
myFa.Value = fa.Value
@@ -99,6 +116,17 @@
return nil
}
+func (config *ReleaseConfig) GetSortedFileList() []string {
+ ret := []string{}
+ for k := range config.FilesUsedMap {
+ ret = append(ret, k)
+ }
+ slices.SortFunc(ret, func(a, b string) int {
+ return cmp.Compare(a, b)
+ })
+ return ret
+}
+
func (config *ReleaseConfig) GenerateReleaseConfig(configs *ReleaseConfigs) error {
if config.ReleaseConfigArtifact != nil {
return nil
@@ -111,21 +139,7 @@
// Start with only the flag declarations.
config.FlagArtifacts = configs.FlagArtifacts.Clone()
- // Add RELEASE_ACONFIG_VALUE_SETS
- workflowManual := rc_proto.Workflow(rc_proto.Workflow_MANUAL)
- releaseAconfigValueSets := FlagArtifact{
- FlagDeclaration: &rc_proto.FlagDeclaration{
- Name: proto.String("RELEASE_ACONFIG_VALUE_SETS"),
- Namespace: proto.String("android_UNKNOWN"),
- Description: proto.String("Aconfig value sets assembled by release-config"),
- Workflow: &workflowManual,
- Containers: []string{"system", "system_ext", "product", "vendor"},
- Value: &rc_proto.Value{Val: &rc_proto.Value_UnspecifiedValue{false}},
- },
- DeclarationIndex: -1,
- Traces: []*rc_proto.Tracepoint{},
- }
- config.FlagArtifacts["RELEASE_ACONFIG_VALUE_SETS"] = &releaseAconfigValueSets
+ releaseAconfigValueSets := config.FlagArtifacts["RELEASE_ACONFIG_VALUE_SETS"]
// Generate any configs we need to inherit. This will detect loops in
// the config.
@@ -152,29 +166,33 @@
return err
}
}
+
+ // If we inherited nothing, then we need to mark the global files as used for this
+ // config. If we inherited, then we already marked them as part of inheritance.
+ if len(config.InheritNames) == 0 {
+ for f := range configs.FilesUsedMap {
+ config.FilesUsedMap[f] = true
+ }
+ }
+
contributionsToApply = append(contributionsToApply, config.Contributions...)
- myAconfigValueSets := strings.Split(releaseAconfigValueSets.Value.GetStringValue(), " ")
- myAconfigValueSetsMap := map[string]bool{}
- for _, v := range myAconfigValueSets {
- myAconfigValueSetsMap[v] = true
- }
+ workflowManual := rc_proto.Workflow(rc_proto.Workflow_WorkflowManual)
myDirsMap := make(map[int]bool)
for _, contrib := range contributionsToApply {
contribAconfigValueSets := []string{}
- // Gather the aconfig_value_sets from this contribution that are not already in the list.
+ // Gather the aconfig_value_sets from this contribution, allowing duplicates for simplicity.
for _, v := range contrib.proto.AconfigValueSets {
- if _, ok := myAconfigValueSetsMap[v]; !ok {
- contribAconfigValueSets = append(contribAconfigValueSets, v)
- myAconfigValueSetsMap[v] = true
- }
+ contribAconfigValueSets = append(contribAconfigValueSets, v)
}
- myAconfigValueSets = append(myAconfigValueSets, contribAconfigValueSets...)
+ contribAconfigValueSetsString := strings.Join(contribAconfigValueSets, " ")
+ releaseAconfigValueSets.Value = &rc_proto.Value{Val: &rc_proto.Value_StringValue{
+ releaseAconfigValueSets.Value.GetStringValue() + " " + contribAconfigValueSetsString}}
releaseAconfigValueSets.Traces = append(
releaseAconfigValueSets.Traces,
&rc_proto.Tracepoint{
Source: proto.String(contrib.path),
- Value: &rc_proto.Value{Val: &rc_proto.Value_StringValue{strings.Join(contribAconfigValueSets, " ")}},
+ Value: &rc_proto.Value{Val: &rc_proto.Value_StringValue{contribAconfigValueSetsString}},
})
myDirsMap[contrib.DeclarationIndex] = true
@@ -193,8 +211,8 @@
return fmt.Errorf("Setting value for flag %s not allowed in %s\n", name, value.path)
}
if isRoot && *fa.FlagDeclaration.Workflow != workflowManual {
- // The "root" release config can only contain workflow: MANUAL flags.
- return fmt.Errorf("Setting value for non-MANUAL flag %s is not allowed in %s", name, value.path)
+ // The "root" release config can only contain workflow: WorkflowManual flags.
+ return fmt.Errorf("Setting value for non-WorkflowManual flag %s is not allowed in %s", name, value.path)
}
if err := fa.UpdateValue(*value); err != nil {
return err
@@ -204,6 +222,16 @@
}
}
}
+ // Now remove any duplicates from the actual value of RELEASE_ACONFIG_VALUE_SETS
+ myAconfigValueSets := []string{}
+ myAconfigValueSetsMap := map[string]bool{}
+ for _, v := range strings.Split(releaseAconfigValueSets.Value.GetStringValue(), " ") {
+ if myAconfigValueSetsMap[v] {
+ continue
+ }
+ myAconfigValueSetsMap[v] = true
+ myAconfigValueSets = append(myAconfigValueSets, v)
+ }
releaseAconfigValueSets.Value = &rc_proto.Value{Val: &rc_proto.Value_StringValue{strings.TrimSpace(strings.Join(myAconfigValueSets, " "))}}
directories := []string{}
diff --git a/cmd/release_config/release_config_lib/release_configs.go b/cmd/release_config/release_config_lib/release_configs.go
index cedf247..65e6d90 100644
--- a/cmd/release_config/release_config_lib/release_configs.go
+++ b/cmd/release_config/release_config_lib/release_configs.go
@@ -67,6 +67,9 @@
// Map of directory to *ReleaseConfigMap
releaseConfigMapsMap map[string]*ReleaseConfigMap
+ // The files used by all release configs
+ FilesUsedMap map[string]bool
+
// The list of config directories used.
configDirs []string
@@ -95,14 +98,40 @@
}
func ReleaseConfigsFactory() (c *ReleaseConfigs) {
- return &ReleaseConfigs{
+ configs := ReleaseConfigs{
Aliases: make(map[string]*string),
FlagArtifacts: make(map[string]*FlagArtifact),
ReleaseConfigs: make(map[string]*ReleaseConfig),
releaseConfigMapsMap: make(map[string]*ReleaseConfigMap),
configDirs: []string{},
configDirIndexes: make(ReleaseConfigDirMap),
+ FilesUsedMap: make(map[string]bool),
}
+ workflowManual := rc_proto.Workflow(rc_proto.Workflow_WorkflowManual)
+ releaseAconfigValueSets := FlagArtifact{
+ FlagDeclaration: &rc_proto.FlagDeclaration{
+ Name: proto.String("RELEASE_ACONFIG_VALUE_SETS"),
+ Namespace: proto.String("android_UNKNOWN"),
+ Description: proto.String("Aconfig value sets assembled by release-config"),
+ Workflow: &workflowManual,
+ Containers: []string{"system", "system_ext", "product", "vendor"},
+ Value: &rc_proto.Value{Val: &rc_proto.Value_UnspecifiedValue{false}},
+ },
+ DeclarationIndex: -1,
+ Traces: []*rc_proto.Tracepoint{},
+ }
+ configs.FlagArtifacts["RELEASE_ACONFIG_VALUE_SETS"] = &releaseAconfigValueSets
+ return &configs
+}
+
+func (configs *ReleaseConfigs) GetSortedReleaseConfigs() (ret []*ReleaseConfig) {
+ for _, config := range configs.ReleaseConfigs {
+ ret = append(ret, config)
+ }
+ slices.SortFunc(ret, func(a, b *ReleaseConfig) int {
+ return cmp.Compare(a.Name, b.Name)
+ })
+ return ret
}
func ReleaseConfigMapFactory(protoPath string) (m *ReleaseConfigMap) {
@@ -116,6 +145,32 @@
return m
}
+// Find the top of the release config contribution directory.
+// Returns the parent of the flag_declarations and flag_values directories.
+func (configs *ReleaseConfigs) GetDirIndex(path string) (int, error) {
+ for p := path; p != "."; p = filepath.Dir(p) {
+ if idx, ok := configs.configDirIndexes[p]; ok {
+ return idx, nil
+ }
+ }
+ return -1, fmt.Errorf("Could not determine release config directory from %s", path)
+}
+
+// Determine the default directory for writing a flag value.
+//
+// Returns the path of the highest-Indexed one of:
+// - Where the flag is declared
+// - Where the release config is first declared
+// - The last place the value is being written.
+func (configs *ReleaseConfigs) GetFlagValueDirectory(config *ReleaseConfig, flag *FlagArtifact) (string, error) {
+ current, err := configs.GetDirIndex(*flag.Traces[len(flag.Traces)-1].Source)
+ if err != nil {
+ return "", err
+ }
+ index := max(flag.DeclarationIndex, config.DeclarationIndex, current)
+ return configs.configDirs[index], nil
+}
+
func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex int) error {
if _, err := os.Stat(path); err != nil {
return fmt.Errorf("%s does not exist\n", path)
@@ -129,6 +184,7 @@
return fmt.Errorf("Release config map %s has invalid container %s", path, container)
}
}
+ configs.FilesUsedMap[path] = true
dir := filepath.Dir(path)
// Record any aliases, checking for duplicates.
for _, alias := range m.proto.Aliases {
@@ -166,17 +222,21 @@
}
m.FlagDeclarations = append(m.FlagDeclarations, *flagDeclaration)
name := *flagDeclaration.Name
+ if name == "RELEASE_ACONFIG_VALUE_SETS" {
+ return fmt.Errorf("%s: %s is a reserved build flag", path, name)
+ }
if def, ok := configs.FlagArtifacts[name]; !ok {
configs.FlagArtifacts[name] = &FlagArtifact{FlagDeclaration: flagDeclaration, DeclarationIndex: ConfigDirIndex}
} else if !proto.Equal(def.FlagDeclaration, flagDeclaration) {
return fmt.Errorf("Duplicate definition of %s", *flagDeclaration.Name)
}
// Set the initial value in the flag artifact.
+ configs.FilesUsedMap[path] = true
configs.FlagArtifacts[name].UpdateValue(
FlagValue{path: path, proto: rc_proto.FlagValue{
Name: proto.String(name), Value: flagDeclaration.Value}})
if configs.FlagArtifacts[name].Redacted {
- return fmt.Errorf("%s may not be redacted by default.", *flagDeclaration.Name)
+ return fmt.Errorf("%s may not be redacted by default.", name)
}
return nil
})
@@ -195,6 +255,7 @@
configs.ReleaseConfigs[name] = ReleaseConfigFactory(name, ConfigDirIndex)
}
config := configs.ReleaseConfigs[name]
+ config.FilesUsedMap[path] = true
config.InheritNames = append(config.InheritNames, releaseConfigContribution.proto.Inherits...)
// Only walk flag_values/{RELEASE} for defined releases.
@@ -203,6 +264,10 @@
if fmt.Sprintf("%s.textproto", *flagValue.proto.Name) != filepath.Base(path) {
return fmt.Errorf("%s incorrectly sets value for flag %s", path, *flagValue.proto.Name)
}
+ if *flagValue.proto.Name == "RELEASE_ACONFIG_VALUE_SETS" {
+ return fmt.Errorf("%s: %s is a reserved build flag", path, *flagValue.proto.Name)
+ }
+ config.FilesUsedMap[path] = true
releaseConfigContribution.FlagValues = append(releaseConfigContribution.FlagValues, flagValue)
return nil
})
@@ -236,14 +301,21 @@
return nil, fmt.Errorf("Missing config %s. Trace=%v", name, trace)
}
-// Write the makefile for this targetRelease.
-func (configs *ReleaseConfigs) WriteMakefile(outFile, targetRelease string) error {
- makeVars := make(map[string]string)
+func (configs *ReleaseConfigs) GetAllReleaseNames() []string {
var allReleaseNames []string
for _, v := range configs.ReleaseConfigs {
allReleaseNames = append(allReleaseNames, v.Name)
allReleaseNames = append(allReleaseNames, v.OtherNames...)
}
+ slices.SortFunc(allReleaseNames, func(a, b string) int {
+ return cmp.Compare(a, b)
+ })
+ return allReleaseNames
+}
+
+// Write the makefile for this targetRelease.
+func (configs *ReleaseConfigs) WriteMakefile(outFile, targetRelease string) error {
+ makeVars := make(map[string]string)
config, err := configs.GetReleaseConfig(targetRelease)
if err != nil {
return err
@@ -306,7 +378,8 @@
data += fmt.Sprintf("# User specified TARGET_RELEASE=%s\n", targetRelease)
}
// The variable _all_release_configs will get deleted during processing, so do not mark it read-only.
- data += fmt.Sprintf("_all_release_configs := %s\n", strings.Join(allReleaseNames, " "))
+ data += fmt.Sprintf("_all_release_configs := %s\n", strings.Join(configs.GetAllReleaseNames(), " "))
+ data += fmt.Sprintf("_used_files := %s\n", strings.Join(config.GetSortedFileList(), " "))
data += fmt.Sprintf("_ALL_RELEASE_FLAGS :=$= %s\n", strings.Join(names, " "))
for _, pName := range pNames {
data += fmt.Sprintf("_ALL_RELEASE_FLAGS.PARTITIONS.%s :=$= %s\n", pName, strings.Join(partitions[pName], " "))
@@ -338,8 +411,9 @@
configs.ReleaseConfigs[name].OtherNames = aliases
}
- for _, config := range configs.ReleaseConfigs {
- err := config.GenerateReleaseConfig(configs)
+ sortedReleaseConfigs := configs.GetSortedReleaseConfigs()
+ for _, c := range sortedReleaseConfigs {
+ err := c.GenerateReleaseConfig(configs)
if err != nil {
return err
}
@@ -349,17 +423,16 @@
if err != nil {
return err
}
+ orc := []*rc_proto.ReleaseConfigArtifact{}
+ for _, c := range sortedReleaseConfigs {
+ if c.Name != releaseConfig.Name {
+ orc = append(orc, c.ReleaseConfigArtifact)
+ }
+ }
+
configs.Artifact = rc_proto.ReleaseConfigsArtifact{
- ReleaseConfig: releaseConfig.ReleaseConfigArtifact,
- OtherReleaseConfigs: func() []*rc_proto.ReleaseConfigArtifact {
- orc := []*rc_proto.ReleaseConfigArtifact{}
- for name, config := range configs.ReleaseConfigs {
- if name != releaseConfig.Name {
- orc = append(orc, config.ReleaseConfigArtifact)
- }
- }
- return orc
- }(),
+ ReleaseConfig: releaseConfig.ReleaseConfigArtifact,
+ OtherReleaseConfigs: orc,
ReleaseConfigMapsMap: func() map[string]*rc_proto.ReleaseConfigMap {
ret := make(map[string]*rc_proto.ReleaseConfigMap)
for k, v := range configs.releaseConfigMapsMap {
@@ -382,12 +455,15 @@
if len(releaseConfigMapPaths) == 0 {
return nil, fmt.Errorf("No maps found")
}
- warnf("No --map argument provided. Using: --map %s\n", strings.Join(releaseConfigMapPaths, " --map "))
+ if !useBuildVar {
+ warnf("No --map argument provided. Using: --map %s\n", strings.Join(releaseConfigMapPaths, " --map "))
+ }
}
configs := ReleaseConfigsFactory()
mapsRead := make(map[string]bool)
- for idx, releaseConfigMapPath := range releaseConfigMapPaths {
+ var idx int
+ for _, releaseConfigMapPath := range releaseConfigMapPaths {
// Maintain an ordered list of release config directories.
configDir := filepath.Dir(releaseConfigMapPath)
if mapsRead[configDir] {
@@ -402,6 +478,7 @@
if err != nil {
return nil, err
}
+ idx += 1
}
// Now that we have all of the release config maps, can meld them and generate the artifacts.
diff --git a/cmd/release_config/release_config_proto/build_flags_out.pb.go b/cmd/release_config/release_config_proto/build_flags_out.pb.go
index 483cffa..8fa75aa 100644
--- a/cmd/release_config/release_config_proto/build_flags_out.pb.go
+++ b/cmd/release_config/release_config_proto/build_flags_out.pb.go
@@ -11,7 +11,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.30.0
+// protoc-gen-go v1.33.0
// protoc v3.21.12
// source: build_flags_out.proto
diff --git a/cmd/release_config/release_config_proto/build_flags_src.pb.go b/cmd/release_config/release_config_proto/build_flags_src.pb.go
index dded975..c52a238 100644
--- a/cmd/release_config/release_config_proto/build_flags_src.pb.go
+++ b/cmd/release_config/release_config_proto/build_flags_src.pb.go
@@ -11,7 +11,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.30.0
+// protoc-gen-go v1.33.0
// protoc v3.21.12
// source: build_flags_src.proto
@@ -34,30 +34,30 @@
type Workflow int32
const (
- Workflow_UNSPECIFIED_workflow Workflow = 0
+ Workflow_WorkflowUnspecified Workflow = 0
// Boolean value flags that progress from false to true.
- Workflow_LAUNCH Workflow = 1
+ Workflow_WorkflowLaunch Workflow = 1
// String value flags that get updated with new version strings to control
// prebuilt inclusion.
- Workflow_PREBUILT Workflow = 2
+ Workflow_WorkflowPrebuilt Workflow = 2
// Manually managed outside flags. These are likely to be found in a
// different directory than flags with other workflows.
- Workflow_MANUAL Workflow = 3
+ Workflow_WorkflowManual Workflow = 3
)
// Enum value maps for Workflow.
var (
Workflow_name = map[int32]string{
- 0: "UNSPECIFIED_workflow",
- 1: "LAUNCH",
- 2: "PREBUILT",
- 3: "MANUAL",
+ 0: "WorkflowUnspecified",
+ 1: "WorkflowLaunch",
+ 2: "WorkflowPrebuilt",
+ 3: "WorkflowManual",
}
Workflow_value = map[string]int32{
- "UNSPECIFIED_workflow": 0,
- "LAUNCH": 1,
- "PREBUILT": 2,
- "MANUAL": 3,
+ "WorkflowUnspecified": 0,
+ "WorkflowLaunch": 1,
+ "WorkflowPrebuilt": 2,
+ "WorkflowManual": 3,
}
)
@@ -295,7 +295,7 @@
if x != nil && x.Workflow != nil {
return *x.Workflow
}
- return Workflow_UNSPECIFIED_workflow
+ return Workflow_WorkflowUnspecified
}
func (x *FlagDeclaration) GetContainers() []string {
@@ -642,15 +642,17 @@
0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x0a,
0x12, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x64, 0x65, 0x66, 0x61, 0x75,
- 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2a, 0x4a, 0x0a, 0x08,
- 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x18, 0x0a, 0x14, 0x55, 0x4e, 0x53, 0x50,
- 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
- 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x41, 0x55, 0x4e, 0x43, 0x48, 0x10, 0x01, 0x12, 0x0c,
- 0x0a, 0x08, 0x50, 0x52, 0x45, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06,
- 0x4d, 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x10, 0x03, 0x42, 0x33, 0x5a, 0x31, 0x61, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73,
- 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65,
- 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2a, 0x61, 0x0a, 0x08,
+ 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x17, 0x0a, 0x13, 0x57, 0x6f, 0x72, 0x6b,
+ 0x66, 0x6c, 0x6f, 0x77, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x10,
+ 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4c, 0x61, 0x75,
+ 0x6e, 0x63, 0x68, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f,
+ 0x77, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x57,
+ 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x10, 0x03, 0x42,
+ 0x33, 0x5a, 0x31, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67,
+ 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f,
+ 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f,
}
var (
diff --git a/cmd/release_config/release_config_proto/build_flags_src.proto b/cmd/release_config/release_config_proto/build_flags_src.proto
index 0ef1a5f..81c6ae3 100644
--- a/cmd/release_config/release_config_proto/build_flags_src.proto
+++ b/cmd/release_config/release_config_proto/build_flags_src.proto
@@ -39,18 +39,18 @@
// com.android.1mypackage are invalid
enum workflow {
- UNSPECIFIED_workflow = 0;
+ WorkflowUnspecified = 0;
// Boolean value flags that progress from false to true.
- LAUNCH = 1;
+ WorkflowLaunch = 1;
// String value flags that get updated with new version strings to control
// prebuilt inclusion.
- PREBUILT = 2;
+ WorkflowPrebuilt = 2;
// Manually managed outside flags. These are likely to be found in a
// different directory than flags with other workflows.
- MANUAL = 3;
+ WorkflowManual = 3;
}
message value {
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index d64010e..4490dd2 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -108,7 +108,7 @@
case "always":
return true
case "depend":
- if _, err := os.Stat(filepath.Join(ctx.Config().OutDir(), ".ninja_log")); errors.Is(err, os.ErrNotExist) {
+ if _, err := os.Stat(filepath.Join(topDir, ctx.Config().OutDir(), ".ninja_log")); errors.Is(err, os.ErrNotExist) {
return true
}
}
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index d1c1d85..e168edc 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -55,7 +55,11 @@
ctx.RegisterModuleType("prebuilt_usr_share", PrebuiltUserShareFactory)
ctx.RegisterModuleType("prebuilt_usr_share_host", PrebuiltUserShareHostFactory)
ctx.RegisterModuleType("prebuilt_usr_hyphendata", PrebuiltUserHyphenDataFactory)
+ ctx.RegisterModuleType("prebuilt_usr_keylayout", PrebuiltUserKeyLayoutFactory)
+ ctx.RegisterModuleType("prebuilt_usr_keychars", PrebuiltUserKeyCharsFactory)
+ ctx.RegisterModuleType("prebuilt_usr_idc", PrebuiltUserIdcFactory)
ctx.RegisterModuleType("prebuilt_font", PrebuiltFontFactory)
+ ctx.RegisterModuleType("prebuilt_overlay", PrebuiltOverlayFactory)
ctx.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory)
ctx.RegisterModuleType("prebuilt_dsp", PrebuiltDSPFactory)
ctx.RegisterModuleType("prebuilt_rfsa", PrebuiltRFSAFactory)
@@ -155,9 +159,6 @@
additionalDependencies *android.Paths
makeClass string
-
- // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo
- mergedAconfigFiles map[string]android.Paths
}
type Defaults struct {
@@ -418,7 +419,6 @@
for _, ip := range installs {
ip.addInstallRules(ctx)
}
- android.CollectDependencyAconfigFiles(ctx, &p.mergedAconfigFiles)
}
type installProperties struct {
@@ -483,7 +483,6 @@
if p.additionalDependencies != nil {
entries.AddStrings("LOCAL_ADDITIONAL_DEPENDENCIES", p.additionalDependencies.Strings()...)
}
- android.SetAconfigFileMkEntries(p.AndroidModuleBase(), entries, p.mergedAconfigFiles)
},
},
}}
@@ -609,6 +608,39 @@
return module
}
+// prebuilt_usr_keylayout is for a prebuilt artifact that is installed in
+// <partition>/usr/keylayout/<sub_dir> directory.
+func PrebuiltUserKeyLayoutFactory() android.Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module, "usr/keylayout")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ android.InitDefaultableModule(module)
+ return module
+}
+
+// prebuilt_usr_keychars is for a prebuilt artifact that is installed in
+// <partition>/usr/keychars/<sub_dir> directory.
+func PrebuiltUserKeyCharsFactory() android.Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module, "usr/keychars")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ android.InitDefaultableModule(module)
+ return module
+}
+
+// prebuilt_usr_idc is for a prebuilt artifact that is installed in
+// <partition>/usr/idc/<sub_dir> directory.
+func PrebuiltUserIdcFactory() android.Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module, "usr/idc")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ android.InitDefaultableModule(module)
+ return module
+}
+
// prebuilt_font installs a font in <partition>/fonts directory.
func PrebuiltFontFactory() android.Module {
module := &PrebuiltEtc{}
@@ -619,6 +651,15 @@
return module
}
+// prebuilt_overlay is for a prebuilt artifact in <partition>/overlay directory.
+func PrebuiltOverlayFactory() android.Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module, "overlay")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ return module
+}
+
// prebuilt_firmware installs a firmware file to <partition>/etc/firmware directory for system
// image.
// If soc_specific property is set to true, the firmware file is installed to the
diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go
index dd9958c..c44574a 100644
--- a/etc/prebuilt_etc_test.go
+++ b/etc/prebuilt_etc_test.go
@@ -287,6 +287,48 @@
android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
}
+func TestPrebuiltPrebuiltUserKeyLayoutInstallDirPath(t *testing.T) {
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
+ prebuilt_usr_keylayout {
+ name: "foo.conf",
+ src: "foo.conf",
+ sub_dir: "bar",
+ }
+ `)
+
+ p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
+ expected := "out/soong/target/product/test_device/system/usr/keylayout/bar"
+ android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
+}
+
+func TestPrebuiltPrebuiltUserKeyCharsInstallDirPath(t *testing.T) {
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
+ prebuilt_usr_keychars {
+ name: "foo.conf",
+ src: "foo.conf",
+ sub_dir: "bar",
+ }
+ `)
+
+ p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
+ expected := "out/soong/target/product/test_device/system/usr/keychars/bar"
+ android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
+}
+
+func TestPrebuiltPrebuiltUserIdcInstallDirPath(t *testing.T) {
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
+ prebuilt_usr_idc {
+ name: "foo.conf",
+ src: "foo.conf",
+ sub_dir: "bar",
+ }
+ `)
+
+ p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
+ expected := "out/soong/target/product/test_device/system/usr/idc/bar"
+ android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
+}
+
func TestPrebuiltFontInstallDirPath(t *testing.T) {
result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
prebuilt_font {
@@ -300,6 +342,19 @@
android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
}
+func TestPrebuiltOverlayInstallDirPath(t *testing.T) {
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
+ prebuilt_overlay {
+ name: "foo.conf",
+ src: "foo.conf",
+ }
+ `)
+
+ p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
+ expected := "out/soong/target/product/test_device/system/overlay"
+ android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
+}
+
func TestPrebuiltFirmwareDirPath(t *testing.T) {
targetPath := "out/soong/target/product/test_device"
tests := []struct {
diff --git a/filesystem/Android.bp b/filesystem/Android.bp
index 854a366..a08f7cf 100644
--- a/filesystem/Android.bp
+++ b/filesystem/Android.bp
@@ -15,6 +15,7 @@
"soong-phony", // for testing
],
srcs: [
+ "aconfig_files.go",
"avb_add_hash_footer.go",
"avb_gen_vbmeta_image.go",
"bootimg.go",
diff --git a/filesystem/aconfig_files.go b/filesystem/aconfig_files.go
new file mode 100644
index 0000000..8daee85
--- /dev/null
+++ b/filesystem/aconfig_files.go
@@ -0,0 +1,82 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package filesystem
+
+import (
+ "android/soong/android"
+ "path/filepath"
+ "strings"
+
+ "github.com/google/blueprint/proptools"
+)
+
+func (f *filesystem) buildAconfigFlagsFiles(ctx android.ModuleContext, builder *android.RuleBuilder, specs map[string]android.PackagingSpec, dir android.OutputPath) {
+ if !proptools.Bool(f.properties.Gen_aconfig_flags_pb) {
+ return
+ }
+
+ aconfigFlagsBuilderPath := android.PathForModuleOut(ctx, "aconfig_flags_builder.sh")
+ aconfigToolPath := ctx.Config().HostToolPath(ctx, "aconfig")
+ cmd := builder.Command().Tool(aconfigFlagsBuilderPath).Implicit(aconfigToolPath)
+
+ var caches []string
+ for _, ps := range specs {
+ cmd.Implicits(ps.GetAconfigPaths())
+ caches = append(caches, ps.GetAconfigPaths().Strings()...)
+ }
+ caches = android.SortedUniqueStrings(caches)
+
+ var sbCaches strings.Builder
+ for _, cache := range caches {
+ sbCaches.WriteString(" --cache ")
+ sbCaches.WriteString(cache)
+ sbCaches.WriteString(" \\\n")
+ }
+ sbCaches.WriteRune('\n')
+
+ var sb strings.Builder
+ sb.WriteString("set -e\n")
+
+ installAconfigFlagsPath := dir.Join(ctx, "etc", "aconfig_flags.pb")
+ sb.WriteString(aconfigToolPath.String())
+ sb.WriteString(" dump-cache --dedup --format protobuf --out ")
+ sb.WriteString(installAconfigFlagsPath.String())
+ sb.WriteString(" \\\n")
+ sb.WriteString(sbCaches.String())
+ cmd.ImplicitOutput(installAconfigFlagsPath)
+
+ installAconfigStorageDir := dir.Join(ctx, "etc", "aconfig")
+ sb.WriteString("mkdir -p ")
+ sb.WriteString(installAconfigStorageDir.String())
+ sb.WriteRune('\n')
+
+ generatePartitionAconfigStorageFile := func(fileType, fileName string) {
+ sb.WriteString(aconfigToolPath.String())
+ sb.WriteString(" create-storage --container ")
+ sb.WriteString(f.PartitionType())
+ sb.WriteString(" --file ")
+ sb.WriteString(fileType)
+ sb.WriteString(" --out ")
+ sb.WriteString(filepath.Join(installAconfigStorageDir.String(), fileName))
+ sb.WriteString(" \\\n")
+ sb.WriteString(sbCaches.String())
+ cmd.ImplicitOutput(installAconfigStorageDir.Join(ctx, fileName))
+ }
+ generatePartitionAconfigStorageFile("package_map", "package.map")
+ generatePartitionAconfigStorageFile("flag_map", "flag.map")
+ generatePartitionAconfigStorageFile("flag_val", "flag.val")
+
+ android.WriteExecutableFileRuleVerbatim(ctx, aconfigFlagsBuilderPath, sb.String())
+}
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index cadf9c24..8b71e85 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -127,6 +127,13 @@
// the make version.
Include_make_built_files string
+ // When set, builds etc/event-log-tags file by merging logtags from all dependencies.
+ // Default is false
+ Build_logtags *bool
+
+ // Install aconfig_flags.pb file for the modules installed in this partition.
+ Gen_aconfig_flags_pb *bool
+
Fsverity fsverityProperties
}
@@ -137,6 +144,7 @@
// partitions like system.img. For example, cc_library modules are placed under ./lib[64] directory.
func filesystemFactory() android.Module {
module := &filesystem{}
+ module.filterPackagingSpec = module.filterInstallablePackagingSpec
initFilesystemModule(module)
return module
}
@@ -144,6 +152,7 @@
func initFilesystemModule(module *filesystem) {
module.AddProperties(&module.properties)
android.InitPackageModule(module)
+ module.PackagingBase.DepsCollectFirstTargetOnly = true
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
}
@@ -189,6 +198,12 @@
return proptools.StringDefault(f.properties.Partition_name, f.Name())
}
+func (f *filesystem) filterInstallablePackagingSpec(ps android.PackagingSpec) bool {
+ // Filesystem module respects the installation semantic. A PackagingSpec from a module with
+ // IsSkipInstall() is skipped.
+ return !ps.SkipInstall()
+}
+
var pctx = android.NewPackageContext("android/soong/filesystem")
func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -288,6 +303,8 @@
f.buildNonDepsFiles(ctx, builder, rootDir)
f.addMakeBuiltFiles(ctx, builder, rootDir)
f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir)
+ f.buildEventLogtagsFile(ctx, builder, rebasedDir)
+ f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir)
// run host_init_verifier
// Ideally we should have a concept of pluggable linters that verify the generated image.
@@ -428,6 +445,8 @@
f.buildNonDepsFiles(ctx, builder, rootDir)
f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir)
+ f.buildEventLogtagsFile(ctx, builder, rebasedDir)
+ f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir)
output := android.PathForModuleOut(ctx, f.installFileName()).OutputPath
cmd := builder.Command().
@@ -485,6 +504,37 @@
Text(android.PathForArbitraryOutput(ctx, stagingDir).String())
}
+func (f *filesystem) buildEventLogtagsFile(ctx android.ModuleContext, builder *android.RuleBuilder, rebasedDir android.OutputPath) {
+ if !proptools.Bool(f.properties.Build_logtags) {
+ return
+ }
+
+ logtagsFilePaths := make(map[string]bool)
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ if logtagsInfo, ok := android.OtherModuleProvider(ctx, child, android.LogtagsProviderKey); ok {
+ for _, path := range logtagsInfo.Logtags {
+ logtagsFilePaths[path.String()] = true
+ }
+ }
+ return true
+ })
+
+ if len(logtagsFilePaths) == 0 {
+ return
+ }
+
+ etcPath := rebasedDir.Join(ctx, "etc")
+ eventLogtagsPath := etcPath.Join(ctx, "event-log-tags")
+ builder.Command().Text("mkdir").Flag("-p").Text(etcPath.String())
+ cmd := builder.Command().BuiltTool("merge-event-log-tags").
+ FlagWithArg("-o ", eventLogtagsPath.String()).
+ FlagWithInput("-m ", android.MergedLogtagsPath(ctx))
+
+ for _, path := range android.SortedKeys(logtagsFilePaths) {
+ cmd.Text(path)
+ }
+}
+
type partition interface {
PartitionType() string
}
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index 1215048..2dc8c21 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -442,3 +442,121 @@
}
`)
}
+
+func TestPreventDuplicatedEntries(t *testing.T) {
+ fixture.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(
+ "packaging conflict at")).
+ RunTestWithBp(t, `
+ android_filesystem {
+ name: "fs",
+ deps: [
+ "foo",
+ "foo_dup",
+ ],
+ }
+
+ cc_binary {
+ name: "foo",
+ }
+
+ cc_binary {
+ name: "foo_dup",
+ stem: "foo",
+ }
+ `)
+}
+
+func TestTrackPhonyAsRequiredDep(t *testing.T) {
+ result := fixture.RunTestWithBp(t, `
+ android_filesystem {
+ name: "fs",
+ deps: ["foo"],
+ }
+
+ cc_binary {
+ name: "foo",
+ required: ["phony"],
+ }
+
+ phony {
+ name: "phony",
+ required: ["libbar"],
+ }
+
+ cc_library {
+ name: "libbar",
+ }
+ `)
+
+ fs := result.ModuleForTests("fs", "android_common").Module().(*filesystem)
+ expected := []string{
+ "bin/foo",
+ "lib64/libbar.so",
+ }
+ for _, e := range expected {
+ android.AssertStringListContains(t, "missing entry", fs.entries, e)
+ }
+}
+
+func TestFilterOutUnsupportedArches(t *testing.T) {
+ result := fixture.RunTestWithBp(t, `
+ android_filesystem {
+ name: "fs_64_only",
+ deps: ["foo"],
+ }
+
+ android_filesystem {
+ name: "fs_64_32",
+ compile_multilib: "both",
+ deps: ["foo"],
+ }
+
+ cc_binary {
+ name: "foo",
+ required: ["phony"],
+ }
+
+ phony {
+ name: "phony",
+ required: [
+ "libbar",
+ "app",
+ ],
+ }
+
+ cc_library {
+ name: "libbar",
+ }
+
+ android_app {
+ name: "app",
+ srcs: ["a.java"],
+ platform_apis: true,
+ }
+ `)
+ testcases := []struct {
+ fsName string
+ expected []string
+ unexpected []string
+ }{
+ {
+ fsName: "fs_64_only",
+ expected: []string{"app/app/app.apk", "bin/foo", "lib64/libbar.so"},
+ unexpected: []string{"lib/libbar.so"},
+ },
+ {
+ fsName: "fs_64_32",
+ expected: []string{"app/app/app.apk", "bin/foo", "lib64/libbar.so", "lib/libbar.so"},
+ unexpected: []string{},
+ },
+ }
+ for _, c := range testcases {
+ fs := result.ModuleForTests(c.fsName, "android_common").Module().(*filesystem)
+ for _, e := range c.expected {
+ android.AssertStringListContains(t, "missing entry", fs.entries, e)
+ }
+ for _, e := range c.unexpected {
+ android.AssertStringListDoesNotContain(t, "unexpected entry", fs.entries, e)
+ }
+ }
+}
diff --git a/filesystem/system_image.go b/filesystem/system_image.go
index 5028a49..15cacfb 100644
--- a/filesystem/system_image.go
+++ b/filesystem/system_image.go
@@ -98,5 +98,5 @@
// Note that "apex" module installs its contents to "apex"(fake partition) as well
// for symbol lookup by imitating "activated" paths.
func (s *systemImage) filterPackagingSpec(ps android.PackagingSpec) bool {
- return ps.Partition() == "system"
+ return s.filesystem.filterInstallablePackagingSpec(ps) && ps.Partition() == "system"
}
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index 47fd8f4..306d65e 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -449,10 +449,10 @@
}
}
-func IsValid(fuzzModule FuzzModule) bool {
+func IsValid(ctx android.ConfigAndErrorContext, fuzzModule FuzzModule) bool {
// Discard ramdisk + vendor_ramdisk + recovery modules, they're duplicates of
// fuzz targets we're going to package anyway.
- if !fuzzModule.Enabled() || fuzzModule.InRamdisk() || fuzzModule.InVendorRamdisk() || fuzzModule.InRecovery() {
+ if !fuzzModule.Enabled(ctx) || fuzzModule.InRamdisk() || fuzzModule.InVendorRamdisk() || fuzzModule.InRecovery() {
return false
}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 43f4fe5..dd980cb 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -180,9 +180,6 @@
subName string
subDir string
-
- // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo
- mergedAconfigFiles map[string]android.Paths
}
type taskFunc func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) []generateTask
@@ -299,7 +296,7 @@
case android.HostToolProvider:
// A HostToolProvider provides the path to a tool, which will be copied
// into the sandbox.
- if !t.(android.Module).Enabled() {
+ if !t.(android.Module).Enabled(ctx) {
if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{tool})
} else {
@@ -588,24 +585,6 @@
})
g.outputDeps = android.Paths{phonyFile}
}
- android.CollectDependencyAconfigFiles(ctx, &g.mergedAconfigFiles)
-}
-
-func (g *Module) AndroidMkEntries() []android.AndroidMkEntries {
- ret := android.AndroidMkEntries{
- OutputFile: android.OptionalPathForPath(g.outputFiles[0]),
- ExtraEntries: []android.AndroidMkExtraEntriesFunc{
- func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- android.SetAconfigFileMkEntries(g.AndroidModuleBase(), entries, g.mergedAconfigFiles)
- },
- },
- }
-
- return []android.AndroidMkEntries{ret}
-}
-
-func (g *Module) AndroidModuleBase() *android.ModuleBase {
- return &g.ModuleBase
}
// Collect information for opening IDE project files in java/jdeps.go.
@@ -714,13 +693,13 @@
rule := getSandboxedRuleBuilder(ctx, android.NewRuleBuilder(pctx, ctx).Sbox(genDir, nil))
for _, in := range shard {
- outFile := android.GenPathWithExt(ctx, finalSubDir, in, String(properties.Output_extension))
+ outFile := android.GenPathWithExtAndTrimExt(ctx, finalSubDir, in, String(properties.Output_extension), String(properties.Trim_extension))
// If sharding is enabled, then outFile is the path to the output file in
// the shard directory, and copyTo is the path to the output file in the
// final directory.
if len(shards) > 1 {
- shardFile := android.GenPathWithExt(ctx, genSubDir, in, String(properties.Output_extension))
+ shardFile := android.GenPathWithExtAndTrimExt(ctx, genSubDir, in, String(properties.Output_extension), String(properties.Trim_extension))
copyTo = append(copyTo, outFile)
outFile = shardFile
}
@@ -786,6 +765,9 @@
// Additional files needed for build that are not tooling related.
Data []string `android:"path"`
+
+ // Trim the matched extension for each input file, and it should start with ".".
+ Trim_extension *string
}
const defaultShardSize = 50
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 2dc6a79..1df887b 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -894,6 +894,155 @@
)
}
+func TestGenSrcsWithTrimExtAndOutpuExtension(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForGenRuleTest,
+ android.FixtureMergeMockFs(android.MockFS{
+ "external-protos/path/Android.bp": []byte(`
+ filegroup {
+ name: "external-protos",
+ srcs: [
+ "baz.a.b.c.proto/baz.a.b.c.proto",
+ "bar.a.b.c.proto",
+ "qux.ext.a.b.c.proto",
+ ],
+ }
+ `),
+ "package-dir/Android.bp": []byte(`
+ gensrcs {
+ name: "module-name",
+ cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
+ srcs: [
+ "src/foo.a.b.c.proto",
+ ":external-protos",
+ ],
+
+ trim_extension: ".a.b.c.proto",
+ output_extension: "proto.h",
+ }
+ `),
+ }),
+ ).RunTest(t)
+
+ exportedIncludeDir := "out/soong/.intermediates/package-dir/module-name/gen/gensrcs"
+ gen := result.Module("module-name", "").(*Module)
+
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "include path",
+ []string{exportedIncludeDir},
+ gen.exportedIncludeDirs,
+ )
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "files",
+ []string{
+ exportedIncludeDir + "/package-dir/src/foo.proto.h",
+ exportedIncludeDir + "/external-protos/path/baz.a.b.c.proto/baz.proto.h",
+ exportedIncludeDir + "/external-protos/path/bar.proto.h",
+ exportedIncludeDir + "/external-protos/path/qux.ext.proto.h",
+ },
+ gen.outputFiles,
+ )
+}
+
+func TestGenSrcsWithTrimExtButNoOutpuExtension(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForGenRuleTest,
+ android.FixtureMergeMockFs(android.MockFS{
+ "external-protos/path/Android.bp": []byte(`
+ filegroup {
+ name: "external-protos",
+ srcs: [
+ "baz.a.b.c.proto/baz.a.b.c.proto",
+ "bar.a.b.c.proto",
+ "qux.ext.a.b.c.proto",
+ ],
+ }
+ `),
+ "package-dir/Android.bp": []byte(`
+ gensrcs {
+ name: "module-name",
+ cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
+ srcs: [
+ "src/foo.a.b.c.proto",
+ ":external-protos",
+ ],
+
+ trim_extension: ".a.b.c.proto",
+ }
+ `),
+ }),
+ ).RunTest(t)
+
+ exportedIncludeDir := "out/soong/.intermediates/package-dir/module-name/gen/gensrcs"
+ gen := result.Module("module-name", "").(*Module)
+
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "include path",
+ []string{exportedIncludeDir},
+ gen.exportedIncludeDirs,
+ )
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "files",
+ []string{
+ exportedIncludeDir + "/package-dir/src/foo",
+ exportedIncludeDir + "/external-protos/path/baz.a.b.c.proto/baz",
+ exportedIncludeDir + "/external-protos/path/bar",
+ exportedIncludeDir + "/external-protos/path/qux.ext",
+ },
+ gen.outputFiles,
+ )
+}
+
+func TestGenSrcsWithOutpuExtension(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForGenRuleTest,
+ android.FixtureMergeMockFs(android.MockFS{
+ "external-protos/path/Android.bp": []byte(`
+ filegroup {
+ name: "external-protos",
+ srcs: ["baz/baz.a.b.c.proto", "bar.a.b.c.proto"],
+ }
+ `),
+ "package-dir/Android.bp": []byte(`
+ gensrcs {
+ name: "module-name",
+ cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
+ srcs: [
+ "src/foo.a.b.c.proto",
+ ":external-protos",
+ ],
+
+ output_extension: "proto.h",
+ }
+ `),
+ }),
+ ).RunTest(t)
+
+ exportedIncludeDir := "out/soong/.intermediates/package-dir/module-name/gen/gensrcs"
+ gen := result.Module("module-name", "").(*Module)
+
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "include path",
+ []string{exportedIncludeDir},
+ gen.exportedIncludeDirs,
+ )
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "files",
+ []string{
+ exportedIncludeDir + "/package-dir/src/foo.a.b.c.proto.h",
+ exportedIncludeDir + "/external-protos/path/baz/baz.a.b.c.proto.h",
+ exportedIncludeDir + "/external-protos/path/bar.a.b.c.proto.h",
+ },
+ gen.outputFiles,
+ )
+}
+
func TestPrebuiltTool(t *testing.T) {
testcases := []struct {
name string
diff --git a/java/aar.go b/java/aar.go
index 47c64bf..07392f6 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -1014,9 +1014,6 @@
usesLibrary
classLoaderContexts dexpreopt.ClassLoaderContextMap
-
- // Single aconfig "cache file" merged from this module and all dependencies.
- mergedAconfigFiles map[string]android.Paths
}
var _ android.OutputFileProducer = (*AARImport)(nil)
@@ -1386,7 +1383,6 @@
android.SetProvider(ctx, JniPackageProvider, JniPackageInfo{
JniPackages: a.jniPackages,
})
- android.CollectDependencyAconfigFiles(ctx, &a.mergedAconfigFiles)
}
func (a *AARImport) HeaderJars() android.Paths {
diff --git a/java/aar_test.go b/java/aar_test.go
index d6dbe3c..18efd20 100644
--- a/java/aar_test.go
+++ b/java/aar_test.go
@@ -15,8 +15,9 @@
package java
import (
- "android/soong/android"
"testing"
+
+ "android/soong/android"
)
func TestAarImportProducesJniPackages(t *testing.T) {
@@ -98,6 +99,7 @@
aconfig_declarations {
name: "bar",
package: "com.example.package.bar",
+ container: "com.android.foo",
srcs: [
"bar.aconfig",
],
@@ -105,6 +107,7 @@
aconfig_declarations {
name: "baz",
package: "com.example.package.baz",
+ container: "com.android.foo",
srcs: [
"baz.aconfig",
],
diff --git a/java/androidmk.go b/java/androidmk.go
index a52d439..4316074 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -17,7 +17,6 @@
import (
"fmt"
"io"
- "strings"
"android/soong/android"
@@ -92,11 +91,7 @@
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
if len(library.logtagsSrcs) > 0 {
- var logtags []string
- for _, l := range library.logtagsSrcs {
- logtags = append(logtags, l.Rel())
- }
- entries.AddStrings("LOCAL_LOGTAGS_FILES", logtags...)
+ entries.AddStrings("LOCAL_SOONG_LOGTAGS_FILES", library.logtagsSrcs.Strings()...)
}
if library.installFile == nil {
@@ -128,7 +123,6 @@
if library.dexpreopter.configPath != nil {
entries.SetPath("LOCAL_SOONG_DEXPREOPT_CONFIG", library.dexpreopter.configPath)
}
- android.SetAconfigFileMkEntries(&library.ModuleBase, entries, library.mergedAconfigFiles)
},
},
})
@@ -302,7 +296,6 @@
if len(binary.dexpreopter.builtInstalled) > 0 {
entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", binary.dexpreopter.builtInstalled)
}
- android.SetAconfigFileMkEntries(&binary.ModuleBase, entries, binary.mergedAconfigFiles)
},
},
ExtraFooters: []android.AndroidMkExtraFootersFunc{
@@ -419,23 +412,6 @@
if app.embeddedJniLibs {
jniSymbols := app.JNISymbolsInstalls(app.installPathForJNISymbols.String())
entries.SetString("LOCAL_SOONG_JNI_LIBS_SYMBOLS", jniSymbols.String())
- } else {
- for _, jniLib := range app.jniLibs {
- entries.AddStrings("LOCAL_SOONG_JNI_LIBS_"+jniLib.target.Arch.ArchType.String(), jniLib.name)
- var partitionTag string
-
- // Mimic the creation of partition_tag in build/make,
- // which defaults to an empty string when the partition is system.
- // Otherwise, capitalize with a leading _
- if jniLib.partition == "system" {
- partitionTag = ""
- } else {
- split := strings.Split(jniLib.partition, "/")
- partitionTag = "_" + strings.ToUpper(split[len(split)-1])
- }
- entries.AddStrings("LOCAL_SOONG_JNI_LIBS_PARTITION_"+jniLib.target.Arch.ArchType.String(),
- jniLib.name+":"+partitionTag)
- }
}
if len(app.jniCoverageOutputs) > 0 {
@@ -454,9 +430,7 @@
entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", app.linter.reports)
- if app.Name() != "framework-res" {
- android.SetAconfigFileMkEntries(&app.ModuleBase, entries, app.mergedAconfigFiles)
- }
+ entries.AddStrings("LOCAL_SOONG_LOGTAGS_FILES", app.logtagsSrcs.Strings()...)
},
},
ExtraFooters: []android.AndroidMkExtraFootersFunc{
@@ -533,7 +507,6 @@
entries.SetPath("LOCAL_FULL_MANIFEST_FILE", a.mergedManifestFile)
entries.SetPath("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", a.combinedExportedProguardFlagsFile)
entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", true)
- android.SetAconfigFileMkEntries(&a.ModuleBase, entries, a.mergedAconfigFiles)
})
return entriesList
diff --git a/java/androidmk_test.go b/java/androidmk_test.go
index 1232cd1..875e06f 100644
--- a/java/androidmk_test.go
+++ b/java/androidmk_test.go
@@ -19,9 +19,6 @@
"testing"
"android/soong/android"
- "android/soong/cc"
-
- "github.com/google/blueprint/proptools"
)
func TestRequired(t *testing.T) {
@@ -161,8 +158,8 @@
moduleName string
expected []string
}{
- {"foo-shared_library", []string{"foo-shared_library.xml"}},
- {"foo-no_shared_library", nil},
+ {"foo-shared_library", []string{"foo-shared_library.impl", "foo-shared_library.xml"}},
+ {"foo-no_shared_library", []string{"foo-no_shared_library.impl"}},
}
for _, tc := range testCases {
mod := result.ModuleForTests(tc.moduleName, "android_common").Module()
@@ -255,149 +252,3 @@
android.AssertDeepEquals(t, "overrides property", expected.overrides, actual)
}
}
-
-func TestJniPartition(t *testing.T) {
- bp := `
- cc_library {
- name: "libjni_system",
- system_shared_libs: [],
- sdk_version: "current",
- stl: "none",
- }
-
- cc_library {
- name: "libjni_system_ext",
- system_shared_libs: [],
- sdk_version: "current",
- stl: "none",
- system_ext_specific: true,
- }
-
- cc_library {
- name: "libjni_odm",
- system_shared_libs: [],
- sdk_version: "current",
- stl: "none",
- device_specific: true,
- }
-
- cc_library {
- name: "libjni_product",
- system_shared_libs: [],
- sdk_version: "current",
- stl: "none",
- product_specific: true,
- }
-
- cc_library {
- name: "libjni_vendor",
- system_shared_libs: [],
- sdk_version: "current",
- stl: "none",
- soc_specific: true,
- }
-
- android_app {
- name: "test_app_system_jni_system",
- privileged: true,
- platform_apis: true,
- certificate: "platform",
- jni_libs: ["libjni_system"],
- }
-
- android_app {
- name: "test_app_system_jni_system_ext",
- privileged: true,
- platform_apis: true,
- certificate: "platform",
- jni_libs: ["libjni_system_ext"],
- }
-
- android_app {
- name: "test_app_system_ext_jni_system",
- privileged: true,
- platform_apis: true,
- certificate: "platform",
- jni_libs: ["libjni_system"],
- system_ext_specific: true
- }
-
- android_app {
- name: "test_app_system_ext_jni_system_ext",
- sdk_version: "core_platform",
- jni_libs: ["libjni_system_ext"],
- system_ext_specific: true
- }
-
- android_app {
- name: "test_app_product_jni_product",
- sdk_version: "core_platform",
- jni_libs: ["libjni_product"],
- product_specific: true
- }
-
- android_app {
- name: "test_app_vendor_jni_odm",
- sdk_version: "core_platform",
- jni_libs: ["libjni_odm"],
- soc_specific: true
- }
-
- android_app {
- name: "test_app_odm_jni_vendor",
- sdk_version: "core_platform",
- jni_libs: ["libjni_vendor"],
- device_specific: true
- }
- android_app {
- name: "test_app_system_jni_multiple",
- privileged: true,
- platform_apis: true,
- certificate: "platform",
- jni_libs: ["libjni_system", "libjni_system_ext"],
- }
- android_app {
- name: "test_app_vendor_jni_multiple",
- sdk_version: "core_platform",
- jni_libs: ["libjni_odm", "libjni_vendor"],
- soc_specific: true
- }
- `
- arch := "arm64"
- ctx := android.GroupFixturePreparers(
- PrepareForTestWithJavaDefaultModules,
- cc.PrepareForTestWithCcDefaultModules,
- android.PrepareForTestWithAndroidMk,
- android.FixtureModifyConfig(func(config android.Config) {
- config.TestProductVariables.DeviceArch = proptools.StringPtr(arch)
- }),
- ).
- RunTestWithBp(t, bp)
- testCases := []struct {
- name string
- partitionNames []string
- partitionTags []string
- }{
- {"test_app_system_jni_system", []string{"libjni_system"}, []string{""}},
- {"test_app_system_jni_system_ext", []string{"libjni_system_ext"}, []string{"_SYSTEM_EXT"}},
- {"test_app_system_ext_jni_system", []string{"libjni_system"}, []string{""}},
- {"test_app_system_ext_jni_system_ext", []string{"libjni_system_ext"}, []string{"_SYSTEM_EXT"}},
- {"test_app_product_jni_product", []string{"libjni_product"}, []string{"_PRODUCT"}},
- {"test_app_vendor_jni_odm", []string{"libjni_odm"}, []string{"_ODM"}},
- {"test_app_odm_jni_vendor", []string{"libjni_vendor"}, []string{"_VENDOR"}},
- {"test_app_system_jni_multiple", []string{"libjni_system", "libjni_system_ext"}, []string{"", "_SYSTEM_EXT"}},
- {"test_app_vendor_jni_multiple", []string{"libjni_odm", "libjni_vendor"}, []string{"_ODM", "_VENDOR"}},
- }
-
- for _, test := range testCases {
- t.Run(test.name, func(t *testing.T) {
- mod := ctx.ModuleForTests(test.name, "android_common").Module()
- entry := android.AndroidMkEntriesForTest(t, ctx.TestContext, mod)[0]
- for i := range test.partitionNames {
- actual := entry.EntryMap["LOCAL_SOONG_JNI_LIBS_PARTITION_"+arch][i]
- expected := test.partitionNames[i] + ":" + test.partitionTags[i]
- android.AssertStringEquals(t, "Expected and actual differ", expected, actual)
- }
- })
- }
-}
diff --git a/java/app.go b/java/app.go
index 50d1a2f..377851e 100644
--- a/java/app.go
+++ b/java/app.go
@@ -274,16 +274,37 @@
variation := append(jniTarget.Variations(),
blueprint.Variation{Mutator: "link", Variation: "shared"})
- // If the app builds against an Android SDK use the SDK variant of JNI dependencies
- // unless jni_uses_platform_apis is set.
- // Don't require the SDK variant for apps that are shipped on vendor, etc., as they already
- // have stable APIs through the VNDK.
- if (usesSDK && !a.RequiresStableAPIs(ctx) &&
- !Bool(a.appProperties.Jni_uses_platform_apis)) ||
- Bool(a.appProperties.Jni_uses_sdk_apis) {
+ // Test whether to use the SDK variant or the non-SDK variant of JNI dependencies.
+ // Many factors are considered here.
+ // 1. Basically, the selection follows whether the app has sdk_version set or not.
+ jniUsesSdkVariant := usesSDK
+ // 2. However, jni_uses_platform_apis and jni_uses_sdk_apis can override it
+ if Bool(a.appProperties.Jni_uses_sdk_apis) {
+ jniUsesSdkVariant = true
+ }
+ if Bool(a.appProperties.Jni_uses_platform_apis) {
+ jniUsesSdkVariant = false
+ }
+ // 3. Then the use of SDK variant is again prohibited for the following cases:
+ // 3.1. the app is shipped on unbundled partitions like vendor. Since the entire
+ // partition (not only the app) is considered unbudled, there's no need to use the
+ // SDK variant.
+ // 3.2. the app doesn't support embedding the JNI libs
+ if a.RequiresStableAPIs(ctx) || !a.shouldEmbedJnis(ctx) {
+ jniUsesSdkVariant = false
+ }
+ if jniUsesSdkVariant {
variation = append(variation, blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
}
- ctx.AddFarVariationDependencies(variation, jniLibTag, a.appProperties.Jni_libs...)
+
+ // Use the installable dep tag when the JNIs are not embedded
+ var tag dependencyTag
+ if a.shouldEmbedJnis(ctx) {
+ tag = jniLibTag
+ } else {
+ tag = jniInstallTag
+ }
+ ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs...)
}
for _, aconfig_declaration := range a.aaptProperties.Flags_packages {
ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
@@ -334,6 +355,7 @@
func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.checkAppSdkVersions(ctx)
+ a.checkEmbedJnis(ctx)
a.generateAndroidBuildActions(ctx)
a.generateJavaUsedByApex(ctx)
}
@@ -378,6 +400,17 @@
a.checkSdkVersions(ctx)
}
+// Ensures that use_embedded_native_libs are set for apk-in-apex
+func (a *AndroidApp) checkEmbedJnis(ctx android.BaseModuleContext) {
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ apkInApex := !apexInfo.IsForPlatform()
+ hasJnis := len(a.appProperties.Jni_libs) > 0
+
+ if apkInApex && hasJnis && !Bool(a.appProperties.Use_embedded_native_libs) {
+ ctx.ModuleErrorf("APK in APEX should have use_embedded_native_libs: true")
+ }
+}
+
// If an updatable APK sets min_sdk_version, min_sdk_vesion of JNI libs should match with it.
// This check is enforced for "updatable" APKs (including APK-in-APEX).
func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVersion android.ApiLevel) {
@@ -433,9 +466,9 @@
}
func (a *AndroidApp) shouldEmbedJnis(ctx android.BaseModuleContext) bool {
- apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
return ctx.Config().UnbundledBuild() || Bool(a.appProperties.Use_embedded_native_libs) ||
- !apexInfo.IsForPlatform() || a.appProperties.AlwaysPackageNativeLibs
+ Bool(a.appProperties.Updatable) ||
+ a.appProperties.AlwaysPackageNativeLibs
}
func generateAaptRenamePackageFlags(packageName string, renameResourcesPackage bool) []string {
@@ -521,7 +554,7 @@
}
// Use non final ids if we are doing optimized shrinking and are using R8.
- nonFinalIds := Bool(a.dexProperties.Optimize.Optimized_shrink_resources) && a.dexer.effectiveOptimizeEnabled()
+ nonFinalIds := a.dexProperties.optimizedResourceShrinkingEnabled(ctx) && a.dexer.effectiveOptimizeEnabled()
a.aapt.buildActions(ctx,
aaptBuildActionOptions{
sdkContext: android.SdkContext(a),
@@ -552,7 +585,7 @@
staticLibProguardFlagFiles = android.FirstUniquePaths(staticLibProguardFlagFiles)
a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, staticLibProguardFlagFiles...)
- if !Bool(a.dexProperties.Optimize.Optimized_shrink_resources) {
+ if !(a.dexProperties.optimizedResourceShrinkingEnabled(ctx)) {
// When using the optimized shrinking the R8 enqueuer will traverse the xml files that become
// live for code references and (transitively) mark these as live.
// In this case we explicitly don't wan't the aapt2 generated keep files (which would keep the now
@@ -591,7 +624,7 @@
var packageResources = a.exportPackage
if ctx.ModuleName() != "framework-res" {
- if a.dexProperties.resourceShrinkingEnabled() {
+ if a.dexProperties.resourceShrinkingEnabled(ctx) {
protoFile := android.PathForModuleOut(ctx, packageResources.Base()+".proto.apk")
aapt2Convert(ctx, protoFile, packageResources, "proto")
a.dexer.resourcesInput = android.OptionalPathForPath(protoFile)
@@ -614,7 +647,7 @@
}
a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars)
- if a.dexProperties.resourceShrinkingEnabled() {
+ if a.dexProperties.resourceShrinkingEnabled(ctx) {
binaryResources := android.PathForModuleOut(ctx, packageResources.Base()+".binary.out.apk")
aapt2Convert(ctx, binaryResources, a.dexer.resourcesOutput.Path(), "binary")
packageResources = binaryResources
@@ -829,7 +862,9 @@
dexJarFile, packageResources := a.dexBuildActions(ctx)
- jniLibs, prebuiltJniPackages, certificates := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis))
+ // No need to check the SDK version of the JNI deps unless we embed them
+ checkNativeSdkVersion := a.shouldEmbedJnis(ctx) && !Bool(a.appProperties.Jni_uses_platform_apis)
+ jniLibs, prebuiltJniPackages, certificates := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), checkNativeSdkVersion)
jniJarFile := a.jniBuildActions(jniLibs, prebuiltJniPackages, ctx)
if ctx.Failed() {
@@ -911,6 +946,22 @@
installed := ctx.InstallFile(a.installDir, extra.Base(), extra)
extraInstalledPaths = append(extraInstalledPaths, installed)
}
+ // If we don't embed jni libs, make sure that those are installed along with the
+ // app, and also place symlinks to the installed paths under the lib/<arch>
+ // directory of the app installation directory. ex:
+ // /system/app/MyApp/lib/arm64/libfoo.so -> /system/lib64/libfoo.so
+ if !a.embeddedJniLibs {
+ for _, jniLib := range jniLibs {
+ archStr := jniLib.target.Arch.ArchType.String()
+ symlinkDir := a.installDir.Join(ctx, "lib", archStr)
+ for _, installedLib := range jniLib.installPaths {
+ // install the symlink itself
+ symlinkName := installedLib.Base()
+ symlinkTarget := android.InstallPathToOnDevicePath(ctx, installedLib)
+ ctx.InstallAbsoluteSymlink(symlinkDir, symlinkName, symlinkTarget)
+ }
+ }
+ }
ctx.InstallFile(a.installDir, a.outputFile.Base(), a.outputFile, extraInstalledPaths...)
}
@@ -998,6 +1049,7 @@
coverageFile: dep.CoverageOutputFile(),
unstrippedFile: dep.UnstrippedOutputFile(),
partition: dep.Partition(),
+ installPaths: dep.FilesToInstall(),
})
} else if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{otherName})
diff --git a/java/app_import.go b/java/app_import.go
index bb07c42..dc8470d 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -87,9 +87,6 @@
hideApexVariantFromMake bool
provenanceMetaDataFile android.OutputPath
-
- // Single aconfig "cache file" merged from this module and all dependencies.
- mergedAconfigFiles map[string]android.Paths
}
type AndroidAppImportProperties struct {
@@ -416,7 +413,6 @@
artifactPath := android.PathForModuleSrc(ctx, *a.properties.Apk)
a.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, artifactPath, a.installPath)
}
- android.CollectDependencyAconfigFiles(ctx, &a.mergedAconfigFiles)
providePrebuiltInfo(ctx,
prebuiltInfoProps{
diff --git a/java/app_import_test.go b/java/app_import_test.go
index 5de50e7..496fc13 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -509,7 +509,7 @@
variant := ctx.ModuleForTests("foo", "android_common")
if test.expected == "" {
- if variant.Module().Enabled() {
+ if variant.Module().Enabled(android.PanickingConfigAndErrorContext(ctx)) {
t.Error("module should have been disabled, but wasn't")
}
rule := variant.MaybeRule("genProvenanceMetaData")
@@ -586,7 +586,7 @@
variant := ctx.ModuleForTests("foo", "android_common")
if test.expected == "" {
- if variant.Module().Enabled() {
+ if variant.Module().Enabled(android.PanickingConfigAndErrorContext(ctx)) {
t.Error("module should have been disabled, but wasn't")
}
rule := variant.MaybeRule("genProvenanceMetaData")
@@ -629,7 +629,7 @@
if !a.prebuilt.UsePrebuilt() {
t.Errorf("prebuilt foo module is not active")
}
- if !a.Enabled() {
+ if !a.Enabled(android.PanickingConfigAndErrorContext(ctx)) {
t.Errorf("prebuilt foo module is disabled")
}
}
diff --git a/java/app_test.go b/java/app_test.go
index eab40e7..a7c48a1 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -4382,6 +4382,7 @@
aconfig_declarations {
name: "bar",
package: "com.example.package.bar",
+ container: "com.android.foo",
srcs: [
"bar.aconfig",
],
@@ -4389,6 +4390,7 @@
aconfig_declarations {
name: "baz",
package: "com.example.package.baz",
+ container: "com.android.foo",
srcs: [
"baz.aconfig",
],
diff --git a/java/base.go b/java/base.go
index 938ac5e..0c28671 100644
--- a/java/base.go
+++ b/java/base.go
@@ -537,9 +537,6 @@
// or the module should override Stem().
stem string
- // Single aconfig "cache file" merged from this module and all dependencies.
- mergedAconfigFiles map[string]android.Paths
-
// Values that will be set in the JarJarProvider data for jarjar repackaging,
// and merged with our dependencies' rules.
jarjarRenameRules map[string]string
@@ -1682,7 +1679,11 @@
j.dexJarFile = makeDexJarPathFromPath(dexOutputFile)
// Dexpreopting
- j.dexpreopt(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), dexOutputFile)
+ libName := android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName())
+ if j.SdkLibraryName() != nil && strings.HasSuffix(ctx.ModuleName(), ".impl") {
+ libName = strings.TrimSuffix(libName, ".impl")
+ }
+ j.dexpreopt(ctx, libName, dexOutputFile)
outputFile = dexOutputFile
} else {
@@ -1730,8 +1731,6 @@
ctx.CheckbuildFile(outputFile)
- android.CollectDependencyAconfigFiles(ctx, &j.mergedAconfigFiles)
-
android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
HeaderJars: android.PathsIfNonNil(j.headerJarFile),
RepackagedHeaderJars: android.PathsIfNonNil(j.repackagedHeaderJarFile),
diff --git a/java/boot_jars.go b/java/boot_jars.go
index 5d40ec3..6223ded 100644
--- a/java/boot_jars.go
+++ b/java/boot_jars.go
@@ -21,8 +21,8 @@
// isActiveModule returns true if the given module should be considered for boot
// jars, i.e. if it's enabled and the preferred one in case of source and
// prebuilt alternatives.
-func isActiveModule(module android.Module) bool {
- if !module.Enabled() {
+func isActiveModule(ctx android.ConfigAndErrorContext, module android.Module) bool {
+ if !module.Enabled(ctx) {
return false
}
return android.IsModulePreferred(module)
diff --git a/java/bootclasspath.go b/java/bootclasspath.go
index c7dc3af..77ddf5c 100644
--- a/java/bootclasspath.go
+++ b/java/bootclasspath.go
@@ -127,7 +127,10 @@
// added by addDependencyOntoApexModulePair.
func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tag blueprint.DependencyTag) []android.Module {
var modules []android.Module
- ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
+ isActiveModulePred := func(module android.Module) bool {
+ return isActiveModule(ctx, module)
+ }
+ ctx.VisitDirectDepsIf(isActiveModulePred, func(module android.Module) {
t := ctx.OtherModuleDependencyTag(module)
if t == tag {
modules = append(modules, module)
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index cc3da76..4d3d794 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -474,7 +474,7 @@
// Only perform a consistency check if this module is the active module. That will prevent an
// unused prebuilt that was created without instrumentation from breaking an instrumentation
// build.
- if isActiveModule(ctx.Module()) {
+ if isActiveModule(ctx, ctx.Module()) {
b.bootclasspathFragmentPropertyCheck(ctx)
}
@@ -519,7 +519,7 @@
// empty string if this module should not provide a boot image profile.
func (b *BootclasspathFragmentModule) getProfileProviderApex(ctx android.BaseModuleContext) string {
// Only use the profile from the module that is preferred.
- if !isActiveModule(ctx.Module()) {
+ if !isActiveModule(ctx, ctx.Module()) {
return ""
}
@@ -590,13 +590,36 @@
// So ignore it even if it is not in PRODUCT_APEX_BOOT_JARS.
// TODO(b/202896428): Add better way to handle this.
_, unknown = android.RemoveFromList("android.car-module", unknown)
- if isActiveModule(ctx.Module()) && len(unknown) > 0 {
- ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown)
+ if isApexVariant(ctx) && len(unknown) > 0 {
+ if android.IsModulePrebuilt(ctx.Module()) {
+ // prebuilt bcpf. the validation of this will be done at the top-level apex
+ providerClasspathFragmentValidationInfoProvider(ctx, unknown)
+ } else if !disableSourceApexVariant(ctx) {
+ // source bcpf, and prebuilt apex are not selected.
+ ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown)
+ }
}
}
return jars
}
+var ClasspathFragmentValidationInfoProvider = blueprint.NewProvider[ClasspathFragmentValidationInfo]()
+
+type ClasspathFragmentValidationInfo struct {
+ ClasspathFragmentModuleName string
+ UnknownJars []string
+}
+
+// Set a provider with the list of jars that have not been added to PRODUCT_APEX_BOOT_JARS
+// The validation will be done in the ctx of the top-level _selected_ apex
+func providerClasspathFragmentValidationInfoProvider(ctx android.ModuleContext, unknown []string) {
+ info := ClasspathFragmentValidationInfo{
+ ClasspathFragmentModuleName: ctx.ModuleName(),
+ UnknownJars: unknown,
+ }
+ android.SetProvider(ctx, ClasspathFragmentValidationInfoProvider, info)
+}
+
// generateHiddenAPIBuildActions generates all the hidden API related build rules.
func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, contents []android.Module, fragments []android.Module) *HiddenAPIOutput {
diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go
index 0ebab4d..07bc5c1 100644
--- a/java/classpath_fragment.go
+++ b/java/classpath_fragment.go
@@ -151,10 +151,14 @@
return jars
}
+func (c *ClasspathFragmentBase) outputFilename() string {
+ return strings.ToLower(c.classpathType.String()) + ".pb"
+}
+
func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.ModuleContext, configuredJars android.ConfiguredJarList, jars []classpathJar) {
generateProto := proptools.BoolDefault(c.properties.Generate_classpaths_proto, true)
if generateProto {
- outputFilename := strings.ToLower(c.classpathType.String()) + ".pb"
+ outputFilename := c.outputFilename()
c.outputFilepath = android.PathForModuleOut(ctx, outputFilename).OutputPath
c.installDirPath = android.PathForModuleInstall(ctx, "etc", "classpaths")
@@ -181,6 +185,10 @@
android.SetProvider(ctx, ClasspathFragmentProtoContentInfoProvider, classpathProtoInfo)
}
+func (c *ClasspathFragmentBase) installClasspathProto(ctx android.ModuleContext) android.InstallPath {
+ return ctx.InstallFile(c.installDirPath, c.outputFilename(), c.outputFilepath)
+}
+
func writeClasspathsTextproto(ctx android.ModuleContext, output android.WritablePath, jars []classpathJar) {
var content strings.Builder
diff --git a/java/code_metadata_test.go b/java/code_metadata_test.go
index 0ef348a..99b1f52 100644
--- a/java/code_metadata_test.go
+++ b/java/code_metadata_test.go
@@ -7,6 +7,7 @@
"android/soong/android"
soongTesting "android/soong/testing"
"android/soong/testing/code_metadata_internal_proto"
+
"google.golang.org/protobuf/proto"
)
diff --git a/java/dex.go b/java/dex.go
index 6caaa7f..8cfffaf 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -111,8 +111,12 @@
return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault)
}
-func (d *DexProperties) resourceShrinkingEnabled() bool {
- return BoolDefault(d.Optimize.Optimized_shrink_resources, Bool(d.Optimize.Shrink_resources))
+func (d *DexProperties) resourceShrinkingEnabled(ctx android.ModuleContext) bool {
+ return !ctx.Config().Eng() && BoolDefault(d.Optimize.Optimized_shrink_resources, Bool(d.Optimize.Shrink_resources))
+}
+
+func (d *DexProperties) optimizedResourceShrinkingEnabled(ctx android.ModuleContext) bool {
+ return d.resourceShrinkingEnabled(ctx) && Bool(d.Optimize.Optimized_shrink_resources)
}
var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8",
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 25e95db..1acac1b 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -196,8 +196,10 @@
}
apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
psi := android.PrebuiltSelectionInfoMap{}
- ctx.VisitDirectDepsWithTag(android.PrebuiltDepTag, func(am android.Module) {
- psi, _ = android.OtherModuleProvider(ctx, am, android.PrebuiltSelectionInfoProvider)
+ ctx.VisitDirectDeps(func(am android.Module) {
+ if prebuiltSelectionInfo, ok := android.OtherModuleProvider(ctx, am, android.PrebuiltSelectionInfoProvider); ok {
+ psi = prebuiltSelectionInfo
+ }
})
// Find the apex variant for this module
_, apexVariantsWithoutTestApexes, _ := android.ListSetDifference(apexInfo.InApexVariants, apexInfo.TestApexes)
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index f7e3cb9..7229ca0 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -562,7 +562,7 @@
return ctx.Config().Once(dexBootJarsFragmentsKey, func() interface{} {
fragments := make(map[string]android.Module)
ctx.WalkDeps(func(child, parent android.Module) bool {
- if !isActiveModule(child) {
+ if !isActiveModule(ctx, child) {
return false
}
tag := ctx.OtherModuleDependencyTag(child)
@@ -1125,7 +1125,7 @@
image.unstrippedInstalls = unstrippedInstalls
// Only set the licenseMetadataFile from the active module.
- if isActiveModule(ctx.Module()) {
+ if isActiveModule(ctx, ctx.Module()) {
image.licenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile())
}
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 08caf91..ca81343 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -106,9 +106,6 @@
everythingArtifacts stubsArtifacts
exportableArtifacts stubsArtifacts
- // Single aconfig "cache file" merged from this module and all dependencies.
- mergedAconfigFiles map[string]android.Paths
-
exportableApiFile android.WritablePath
exportableRemovedApiFile android.WritablePath
}
@@ -604,6 +601,11 @@
}
}
+// AndroidPlusUpdatableJar is the name of some extra jars added into `module-lib` and
+// `system-server` directories that contain all the APIs provided by the platform and updatable
+// modules because the `android.jar` files do not. See b/337836752.
+const AndroidPlusUpdatableJar = "android-plus-updatable.jar"
+
func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
if len(d.properties.Api_levels_annotations_dirs) == 0 {
ctx.PropertyErrorf("api_levels_annotations_dirs",
@@ -621,7 +623,8 @@
// privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
// for older releases. Similarly, module-lib falls back to system API.
var sdkDirs []string
- switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") {
+ apiLevelsSdkType := proptools.StringDefault(d.properties.Api_levels_sdk_type, "public")
+ switch apiLevelsSdkType {
case "system-server":
sdkDirs = []string{"system-server", "module-lib", "system", "public"}
case "module-lib":
@@ -635,9 +638,22 @@
return
}
+ // Construct a pattern to match the appropriate extensions that should be included in the
+ // generated api-versions.xml file.
+ //
// Use the first item in the sdkDirs array as that is the sdk type for the target API levels
// being generated but has the advantage over `Api_levels_sdk_type` as it has been validated.
- extensionsPattern := fmt.Sprintf(`/extensions/[0-9]+/%s/.*\.jar`, sdkDirs[0])
+ // The exception is for system-server which needs to include module-lib and system-server. That
+ // is because while system-server extends module-lib the system-server extension directory only
+ // contains service-* modules which provide system-server APIs it does not list the modules which
+ // only provide a module-lib, so they have to be included separately.
+ extensionSurfacesPattern := sdkDirs[0]
+ if apiLevelsSdkType == "system-server" {
+ // Take the first two items in sdkDirs, which are system-server and module-lib, and construct
+ // a pattern that will match either.
+ extensionSurfacesPattern = strings.Join(sdkDirs[0:2], "|")
+ }
+ extensionsPattern := fmt.Sprintf(`/extensions/[0-9]+/(%s)/.*\.jar`, extensionSurfacesPattern)
var dirs []string
var extensions_dir string
@@ -648,16 +664,24 @@
// Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
// ideally this should be read from prebuiltApis.properties.Extensions_*
for _, dep := range t.deps {
+ // Check to see if it matches an extension first.
+ depBase := dep.Base()
if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
if extensions_dir == "" {
extensions_dir = t.dir.String() + "/extensions"
}
cmd.Implicit(dep)
- }
- if dep.Base() == filename {
+ } else if depBase == filename {
+ // Check to see if it matches a dessert release for an SDK, e.g. Android, Car, Wear, etc..
cmd.Implicit(dep)
- }
- if filename != "android.jar" && dep.Base() == "android.jar" {
+ } else if depBase == AndroidPlusUpdatableJar && d.properties.Extensions_info_file != nil {
+ // The output api-versions.xml has been requested to include information on SDK
+ // extensions. That means it also needs to include
+ // so
+ // The module-lib and system-server directories should use `android-plus-updatable.jar`
+ // instead of `android.jar`. See AndroidPlusUpdatableJar for more information.
+ cmd.Implicit(dep)
+ } else if filename != "android.jar" && depBase == "android.jar" {
// Metalava implicitly searches these patterns:
// prebuilts/tools/common/api-versions/android-%/android.jar
// prebuilts/sdk/%/public/android.jar
@@ -675,9 +699,25 @@
}
})
+ // Generate the list of --android-jar-pattern options. The order matters so the first one which
+ // matches will be the one that is used for a specific api level..
for _, sdkDir := range sdkDirs {
for _, dir := range dirs {
- cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, filename))
+ addPattern := func(jarFilename string) {
+ cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, jarFilename))
+ }
+
+ if sdkDir == "module-lib" || sdkDir == "system-server" {
+ // The module-lib and system-server android.jars do not include the updatable modules (as
+ // doing so in the source would introduce dependency cycles and the prebuilts have to
+ // match the sources). So, instead an additional `android-plus-updatable.jar` will be used
+ // that does include the updatable modules and this pattern will match that. This pattern
+ // is added in addition to the following pattern to decouple this change from the change
+ // to add the `android-plus-updatable.jar`.
+ addPattern(AndroidPlusUpdatableJar)
+ }
+
+ addPattern(filename)
}
}
@@ -1299,7 +1339,6 @@
rule.Build("nullabilityWarningsCheck", "nullability warnings check")
}
- android.CollectDependencyAconfigFiles(ctx, &d.mergedAconfigFiles)
}
func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
@@ -1327,7 +1366,7 @@
// use a strict naming convention
var (
droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
- //public is commented out since the core libraries use public in their java_sdk_library names
+ // public is commented out since the core libraries use public in their java_sdk_library names
"intracore": android.SdkIntraCore,
"intra.core": android.SdkIntraCore,
"system_server": android.SdkSystemServer,
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index 8da695f..6a14f36 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -379,6 +379,7 @@
aconfig_declarations {
name: "bar",
package: "com.example.package",
+ container: "com.android.foo",
srcs: [
"bar.aconfig",
],
@@ -434,6 +435,7 @@
aconfig_declarations {
name: "bar",
package: "com.example.package",
+ container: "com.android.foo",
srcs: [
"bar.aconfig",
],
diff --git a/java/fuzz.go b/java/fuzz.go
index fb31ce7..d37c558 100644
--- a/java/fuzz.go
+++ b/java/fuzz.go
@@ -179,7 +179,7 @@
javaFuzzModule.ApexModuleBase,
}
- if ok := fuzz.IsValid(fuzzModuleValidator); !ok {
+ if ok := fuzz.IsValid(ctx, fuzzModuleValidator); !ok {
return
}
diff --git a/java/gen.go b/java/gen.go
index 68a9b53..1b4f4c7 100644
--- a/java/gen.go
+++ b/java/gen.go
@@ -27,7 +27,6 @@
func init() {
pctx.SourcePathVariable("logtagsCmd", "build/make/tools/java-event-log-tags.py")
- pctx.SourcePathVariable("mergeLogtagsCmd", "build/make/tools/merge-event-log-tags.py")
pctx.SourcePathVariable("logtagsLib", "build/make/tools/event_log_tags.py")
}
@@ -37,12 +36,6 @@
Command: "$logtagsCmd -o $out $in",
CommandDeps: []string{"$logtagsCmd", "$logtagsLib"},
})
-
- mergeLogtags = pctx.AndroidStaticRule("mergeLogtags",
- blueprint.RuleParams{
- Command: "$mergeLogtagsCmd -o $out $in",
- CommandDeps: []string{"$mergeLogtagsCmd", "$logtagsLib"},
- })
)
func genAidl(ctx android.ModuleContext, aidlFiles android.Paths, aidlGlobalFlags string, aidlIndividualFlags map[string]string, deps android.Paths) android.Paths {
@@ -178,37 +171,9 @@
outSrcFiles = append(outSrcFiles, srcJarFiles...)
}
+ android.SetProvider(ctx, android.LogtagsProviderKey, &android.LogtagsInfo{
+ Logtags: j.logtagsSrcs,
+ })
+
return outSrcFiles
}
-
-func LogtagsSingleton() android.Singleton {
- return &logtagsSingleton{}
-}
-
-type logtagsProducer interface {
- logtags() android.Paths
-}
-
-func (j *Module) logtags() android.Paths {
- return j.logtagsSrcs
-}
-
-var _ logtagsProducer = (*Module)(nil)
-
-type logtagsSingleton struct{}
-
-func (l *logtagsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
- var allLogtags android.Paths
- ctx.VisitAllModules(func(module android.Module) {
- if logtags, ok := module.(logtagsProducer); ok {
- allLogtags = append(allLogtags, logtags.logtags()...)
- }
- })
-
- ctx.Build(pctx, android.BuildParams{
- Rule: mergeLogtags,
- Description: "merge logtags",
- Output: android.PathForIntermediates(ctx, "all-event-log-tags.txt"),
- Inputs: allLogtags,
- })
-}
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index ae587ea..cab5402 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -1428,7 +1428,7 @@
// should not contribute to anything. So, rather than have a missing dex jar cause a Soong
// failure defer the error reporting to Ninja. Unless the prebuilt build target is explicitly
// built Ninja should never use the dex jar file.
- if !isActiveModule(module) {
+ if !isActiveModule(ctx, module) {
return true
}
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 8cb78cd..7d21b7a 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -150,6 +150,10 @@
// Strip a prebuilt_ prefix so that this can match a prebuilt module that has not been renamed.
name = android.RemoveOptionalPrebuiltPrefix(name)
+ // Strip the ".impl" suffix, so that the implementation library of the java_sdk_library is
+ // treated identical to the top level java_sdk_library.
+ name = strings.TrimSuffix(name, ".impl")
+
// Ignore any module that is not listed in the boot image configuration.
index := configuredBootJars.IndexOfJar(name)
if index == -1 {
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index c1fee21..330013e 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -303,7 +303,7 @@
`)
checkDexEncoded := func(t *testing.T, name, unencodedDexJar, encodedDexJar string) {
- moduleForTests := result.ModuleForTests(name, "android_common")
+ moduleForTests := result.ModuleForTests(name+".impl", "android_common")
encodeDexRule := moduleForTests.Rule("hiddenAPIEncodeDex")
actualUnencodedDexJar := encodeDexRule.Input
@@ -319,18 +319,8 @@
// The java_library embedded with the java_sdk_library must be dex encoded.
t.Run("foo", func(t *testing.T) {
- expectedUnencodedDexJar := "out/soong/.intermediates/foo/android_common/aligned/foo.jar"
- expectedEncodedDexJar := "out/soong/.intermediates/foo/android_common/hiddenapi/foo.jar"
+ expectedUnencodedDexJar := "out/soong/.intermediates/foo.impl/android_common/aligned/foo.jar"
+ expectedEncodedDexJar := "out/soong/.intermediates/foo.impl/android_common/hiddenapi/foo.jar"
checkDexEncoded(t, "foo", expectedUnencodedDexJar, expectedEncodedDexJar)
})
-
- // The dex jar of the child implementation java_library of the java_sdk_library is not currently
- // dex encoded.
- t.Run("foo.impl", func(t *testing.T) {
- fooImpl := result.ModuleForTests("foo.impl", "android_common")
- encodeDexRule := fooImpl.MaybeRule("hiddenAPIEncodeDex")
- if encodeDexRule.Rule != nil {
- t.Errorf("foo.impl is not expected to be encoded")
- }
- })
}
diff --git a/java/jacoco.go b/java/jacoco.go
index a820b38..696a0cc 100644
--- a/java/jacoco.go
+++ b/java/jacoco.go
@@ -53,7 +53,7 @@
}
j, ok := ctx.Module().(instrumentable)
- if !ctx.Module().Enabled() || !ok {
+ if !ctx.Module().Enabled(ctx) || !ok {
return
}
diff --git a/java/java.go b/java/java.go
index 725e25a..05ef5d0 100644
--- a/java/java.go
+++ b/java/java.go
@@ -75,7 +75,6 @@
ctx.BottomUp("jacoco_deps", jacocoDepsMutator).Parallel()
})
- ctx.RegisterParallelSingletonType("logtags", LogtagsSingleton)
ctx.RegisterParallelSingletonType("kythe_java_extract", kytheExtractJavaFactory)
}
@@ -367,14 +366,14 @@
toolchain bool
static bool
+
+ installable bool
}
-// installDependencyTag is a dependency tag that is annotated to cause the installed files of the
-// dependency to be installed when the parent module is installed.
-type installDependencyTag struct {
- blueprint.BaseDependencyTag
- android.InstallAlwaysNeededDependencyTag
- name string
+var _ android.InstallNeededDependencyTag = (*dependencyTag)(nil)
+
+func (d dependencyTag) InstallDepNeeded() bool {
+ return d.installable
}
func (d dependencyTag) LicenseAnnotations() []android.LicenseAnnotation {
@@ -406,7 +405,7 @@
}
func IsJniDepTag(depTag blueprint.DependencyTag) bool {
- return depTag == jniLibTag
+ return depTag == jniLibTag || depTag == jniInstallTag
}
var (
@@ -435,8 +434,8 @@
javaApiContributionTag = dependencyTag{name: "java-api-contribution"}
depApiSrcsTag = dependencyTag{name: "dep-api-srcs"}
aconfigDeclarationTag = dependencyTag{name: "aconfig-declaration"}
- jniInstallTag = installDependencyTag{name: "jni install"}
- binaryInstallTag = installDependencyTag{name: "binary install"}
+ jniInstallTag = dependencyTag{name: "jni install", runtimeLinked: true, installable: true}
+ binaryInstallTag = dependencyTag{name: "binary install", runtimeLinked: true, installable: true}
usesLibReqTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false)
usesLibOptTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true)
usesLibCompat28OptTag = makeUsesLibraryDependencyTag(28, true)
@@ -492,6 +491,7 @@
coverageFile android.OptionalPath
unstrippedFile android.Path
partition string
+ installPaths android.InstallPaths
}
func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext, d dexer) {
@@ -675,6 +675,10 @@
var _ android.ApexModule = (*Library)(nil)
+func (j *Library) CheckDepsMinSdkVersion(ctx android.ModuleContext) {
+ CheckMinSdkVersion(ctx, j)
+}
+
// Provides access to the list of permitted packages from apex boot jars.
type PermittedPackagesForUpdatableBootJars interface {
PermittedPackagesForUpdatableBootJars() []string
@@ -903,6 +907,12 @@
j.minSdkVersion = j.MinSdkVersion(ctx)
j.maxSdkVersion = j.MaxSdkVersion(ctx)
+ // Check min_sdk_version of the transitive dependencies if this module is created from
+ // java_sdk_library.
+ if j.deviceProperties.Min_sdk_version != nil && j.SdkLibraryName() != nil {
+ j.CheckDepsMinSdkVersion(ctx)
+ }
+
// SdkLibrary.GenerateAndroidBuildActions(ctx) sets the stubsLinkType to Unknown.
// If the stubsLinkType has already been set to Unknown, the stubsLinkType should
// not be overridden.
@@ -933,8 +943,12 @@
j.checkSdkVersions(ctx)
j.checkHeadersOnly(ctx)
if ctx.Device() {
+ libName := j.Name()
+ if j.SdkLibraryName() != nil && strings.HasSuffix(libName, ".impl") {
+ libName = proptools.String(j.SdkLibraryName())
+ }
j.dexpreopter.installPath = j.dexpreopter.getInstallPath(
- ctx, j.Name(), android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar"))
+ ctx, libName, android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar"))
j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary
setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
@@ -945,8 +959,24 @@
}
j.compile(ctx, nil, nil, nil)
- exclusivelyForApex := !apexInfo.IsForPlatform()
- if (Bool(j.properties.Installable) || ctx.Host()) && !exclusivelyForApex {
+ // If this module is an impl library created from java_sdk_library,
+ // install the files under the java_sdk_library module outdir instead of this module outdir.
+ if j.SdkLibraryName() != nil && strings.HasSuffix(j.Name(), ".impl") {
+ j.setInstallRules(ctx, proptools.String(j.SdkLibraryName()))
+ } else {
+ j.setInstallRules(ctx, ctx.ModuleName())
+ }
+
+ android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
+ TestOnly: Bool(j.sourceProperties.Test_only),
+ TopLevelTarget: j.sourceProperties.Top_level_test_target,
+ })
+}
+
+func (j *Library) setInstallRules(ctx android.ModuleContext, installModuleName string) {
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+
+ if (Bool(j.properties.Installable) || ctx.Host()) && apexInfo.IsForPlatform() {
var extraInstallDeps android.InstallPaths
if j.InstallMixin != nil {
extraInstallDeps = j.InstallMixin(ctx, j.outputFile)
@@ -963,22 +993,27 @@
if !ctx.Host() {
archDir = ctx.DeviceConfig().DeviceArch()
}
- installDir = android.PathForModuleInstall(ctx, ctx.ModuleName(), archDir)
+ installDir = android.PathForModuleInstall(ctx, installModuleName, archDir)
} else {
installDir = android.PathForModuleInstall(ctx, "framework")
}
j.installFile = ctx.InstallFile(installDir, j.Stem()+".jar", j.outputFile, extraInstallDeps...)
}
-
- android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
- TestOnly: Bool(j.sourceProperties.Test_only),
- TopLevelTarget: j.sourceProperties.Top_level_test_target,
- })
}
func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
j.usesLibrary.deps(ctx, false)
j.deps(ctx)
+
+ if j.SdkLibraryName() != nil && strings.HasSuffix(j.Name(), ".impl") {
+ if dexpreopt.IsDex2oatNeeded(ctx) {
+ dexpreopt.RegisterToolDeps(ctx)
+ }
+ prebuiltSdkLibExists := ctx.OtherModuleExists(android.PrebuiltNameFromSource(proptools.String(j.SdkLibraryName())))
+ if prebuiltSdkLibExists && ctx.OtherModuleExists("all_apex_contributions") {
+ ctx.AddDependency(ctx.Module(), android.AcDepTag, "all_apex_contributions")
+ }
+ }
}
const (
diff --git a/java/java_test.go b/java/java_test.go
index a1192bb..2f27932 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -2801,6 +2801,7 @@
aconfig_declarations {
name: "bar",
package: "com.example.package",
+ container: "com.android.foo",
srcs: [
"bar.aconfig",
],
diff --git a/java/jdeps.go b/java/jdeps.go
index 91f7ce7..3400263 100644
--- a/java/jdeps.go
+++ b/java/jdeps.go
@@ -48,7 +48,7 @@
moduleInfos := make(map[string]android.IdeInfo)
ctx.VisitAllModules(func(module android.Module) {
- if !module.Enabled() {
+ if !module.Enabled(ctx) {
return
}
diff --git a/java/lint.go b/java/lint.go
index 31e7f35..82fac91 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -612,7 +612,7 @@
apiVersionsDb := findModuleOrErr(ctx, files.apiVersionsModule)
if apiVersionsDb == nil {
if !ctx.Config().AllowMissingDependencies() {
- ctx.Errorf("lint: missing module api_versions_public")
+ ctx.Errorf("lint: missing module %s", files.apiVersionsModule)
}
return
}
@@ -620,7 +620,7 @@
sdkAnnotations := findModuleOrErr(ctx, files.annotationsModule)
if sdkAnnotations == nil {
if !ctx.Config().AllowMissingDependencies() {
- ctx.Errorf("lint: missing module sdk-annotations.zip")
+ ctx.Errorf("lint: missing module %s", files.annotationsModule)
}
return
}
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 4db426e..b3c9ce5 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -221,6 +221,7 @@
// ART and platform boot jars must have a corresponding entry in DEX2OATBOOTCLASSPATH
classpathJars := configuredJarListToClasspathJars(ctx, configuredJars, BOOTCLASSPATH, DEX2OATBOOTCLASSPATH)
b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars)
+ b.classpathFragmentBase().installClasspathProto(ctx)
}
func (b *platformBootclasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList {
diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go
index 37ff639..0d2acae 100644
--- a/java/platform_bootclasspath_test.go
+++ b/java/platform_bootclasspath_test.go
@@ -353,7 +353,7 @@
// All the intermediate rules use the same inputs.
expectedIntermediateInputs := `
- out/soong/.intermediates/bar/android_common/javac/bar.jar
+ out/soong/.intermediates/bar.impl/android_common/javac/bar.jar
out/soong/.intermediates/foo-hiddenapi-annotations/android_common/javac/foo-hiddenapi-annotations.jar
out/soong/.intermediates/foo/android_common/javac/foo.jar
`
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index 2fc6c02..99fa092 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -19,6 +19,7 @@
"path/filepath"
"android/soong/android"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -233,7 +234,7 @@
var compatConfigMetadata android.Paths
ctx.VisitAllModules(func(module android.Module) {
- if !module.Enabled() {
+ if !module.Enabled(ctx) {
return
}
if c, ok := module.(platformCompatConfigMetadataProvider); ok {
diff --git a/java/rro_test.go b/java/rro_test.go
index d697ec6..742c839 100644
--- a/java/rro_test.go
+++ b/java/rro_test.go
@@ -421,6 +421,7 @@
aconfig_declarations {
name: "bar",
package: "com.example.package.bar",
+ container: "com.android.foo",
srcs: [
"bar.aconfig",
],
@@ -428,6 +429,7 @@
aconfig_declarations {
name: "baz",
package: "com.example.package.baz",
+ container: "com.android.foo",
srcs: [
"baz.aconfig",
],
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 113071f..677b32a 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -950,6 +950,10 @@
// Path to the header jars of the implementation library
// This is non-empty only when api_only is false.
implLibraryHeaderJars android.Paths
+
+ // The reference to the implementation library created by the source module.
+ // Is nil if the source module does not exist.
+ implLibraryModule *Library
}
func (c *commonToSdkLibraryAndImport) initCommon(module commonSdkLibraryAndImportModule) {
@@ -996,6 +1000,10 @@
c.doctagPaths = android.PathsForModuleSrc(ctx, c.commonSdkLibraryProperties.Doctag_files)
}
+func (c *commonToSdkLibraryAndImport) getImplLibraryModule() *Library {
+ return c.implLibraryModule
+}
+
// Module name of the runtime implementation library
func (c *commonToSdkLibraryAndImport) implLibraryModuleName() string {
return c.module.RootLibraryName() + ".impl"
@@ -1372,6 +1380,8 @@
// sharedLibrary returns true if this can be used as a shared library.
sharedLibrary() bool
+
+ getImplLibraryModule() *Library
}
type SdkLibrary struct {
@@ -1383,6 +1393,8 @@
scopeToProperties map[*apiScope]*ApiScopeProperties
commonToSdkLibraryAndImport
+
+ builtInstalledForApex []dexpreopterInstall
}
var _ SdkLibraryDependency = (*SdkLibrary)(nil)
@@ -1391,6 +1403,20 @@
return module.sdkLibraryProperties.Generate_system_and_test_apis
}
+func (module *SdkLibrary) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
+ if module.implLibraryModule != nil {
+ return module.implLibraryModule.DexJarBuildPath(ctx)
+ }
+ return makeUnsetDexJarPath()
+}
+
+func (module *SdkLibrary) DexJarInstallPath() android.Path {
+ if module.implLibraryModule != nil {
+ return module.implLibraryModule.DexJarInstallPath()
+ }
+ return nil
+}
+
func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext) apiScopes {
// Check to see if any scopes have been explicitly enabled. If any have then all
// must be.
@@ -1442,6 +1468,10 @@
var _ android.ModuleWithMinSdkVersionCheck = (*SdkLibrary)(nil)
func (module *SdkLibrary) CheckMinSdkVersion(ctx android.ModuleContext) {
+ CheckMinSdkVersion(ctx, &module.Library)
+}
+
+func CheckMinSdkVersion(ctx android.ModuleContext, module *Library) {
android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx), func(c android.ModuleContext, do android.PayloadDepsCallback) {
ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
isExternal := !module.depIsInSameApex(ctx, child)
@@ -1538,10 +1568,6 @@
m += "Please see the documentation of the prebuilt_apis module type (and a usage example in prebuilts/sdk) for a convenient way to generate these."
ctx.ModuleErrorf(m)
}
- if module.requiresRuntimeImplementationLibrary() {
- // Only add the deps for the library if it is actually going to be built.
- module.Library.deps(ctx)
- }
}
func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) {
@@ -1550,7 +1576,7 @@
return paths, err
}
if module.requiresRuntimeImplementationLibrary() {
- return module.Library.OutputFiles(tag)
+ return module.implLibraryModule.OutputFiles(tag)
}
if tag == "" {
return nil, nil
@@ -1565,18 +1591,12 @@
// TODO (b/331665856): Implement a principled solution for this.
module.HideFromMake()
}
- if proptools.String(module.deviceProperties.Min_sdk_version) != "" {
- module.CheckMinSdkVersion(ctx)
- }
module.generateCommonBuildActions(ctx)
- // Only build an implementation library if required.
- if module.requiresRuntimeImplementationLibrary() {
- // stubsLinkType must be set before calling Library.GenerateAndroidBuildActions
- module.Library.stubsLinkType = Unknown
- module.Library.GenerateAndroidBuildActions(ctx)
- }
+ module.stem = proptools.StringDefault(module.overridableProperties.Stem, ctx.ModuleName())
+
+ module.provideHiddenAPIPropertyInfo(ctx)
// Collate the components exported by this module. All scope specific modules are exported but
// the impl and xml component modules are not.
@@ -1603,10 +1623,40 @@
if tag == implLibraryTag {
if dep, ok := android.OtherModuleProvider(ctx, to, JavaInfoProvider); ok {
module.implLibraryHeaderJars = append(module.implLibraryHeaderJars, dep.HeaderJars...)
+ module.implLibraryModule = to.(*Library)
+ android.SetProvider(ctx, JavaInfoProvider, dep)
}
}
})
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ if !apexInfo.IsForPlatform() {
+ module.hideApexVariantFromMake = true
+ }
+
+ if module.implLibraryModule != nil {
+ if ctx.Device() {
+ module.classesJarPaths = android.Paths{module.implLibraryModule.implementationJarFile}
+ module.bootDexJarPath = module.implLibraryModule.bootDexJarPath
+ module.uncompressDexState = module.implLibraryModule.uncompressDexState
+ module.active = module.implLibraryModule.active
+ }
+
+ module.outputFile = module.implLibraryModule.outputFile
+ module.dexJarFile = makeDexJarPathFromPath(module.implLibraryModule.dexJarFile.Path())
+ module.headerJarFile = module.implLibraryModule.headerJarFile
+ module.implementationAndResourcesJar = module.implLibraryModule.implementationAndResourcesJar
+ module.builtInstalledForApex = module.implLibraryModule.builtInstalledForApex
+ module.dexpreopter.configPath = module.implLibraryModule.dexpreopter.configPath
+ module.dexpreopter.outputProfilePathOnHost = module.implLibraryModule.dexpreopter.outputProfilePathOnHost
+
+ if !module.Host() {
+ module.hostdexInstallFile = module.implLibraryModule.hostdexInstallFile
+ }
+
+ android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: module.implLibraryModule.uniqueSrcFiles.Strings()})
+ }
+
// Make the set of components exported by this module available for use elsewhere.
exportedComponentInfo := android.ExportedComponentsInfo{Components: android.SortedKeys(exportedComponents)}
android.SetProvider(ctx, android.ExportedComponentsInfoProvider, exportedComponentInfo)
@@ -1636,13 +1686,18 @@
android.SetProvider(ctx, android.AdditionalSdkInfoProvider, android.AdditionalSdkInfo{additionalSdkInfo})
}
+func (module *SdkLibrary) BuiltInstalledForApex() []dexpreopterInstall {
+ return module.builtInstalledForApex
+}
+
func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries {
if !module.requiresRuntimeImplementationLibrary() {
return nil
}
entriesList := module.Library.AndroidMkEntries()
+ entries := &entriesList[0]
+ entries.Required = append(entries.Required, module.implLibraryModuleName())
if module.sharedLibrary() {
- entries := &entriesList[0]
entries.Required = append(entries.Required, module.xmlPermissionsModuleName())
}
return entriesList
@@ -1763,20 +1818,21 @@
Libs []string
Static_libs []string
Apex_available []string
+ Stem *string
}{
Name: proptools.StringPtr(module.implLibraryModuleName()),
Visibility: visibility,
// Set the instrument property to ensure it is instrumented when instrumentation is required.
Instrument: true,
- // Set the impl_only libs. Note that the module's "Libs" get appended as well, via the
- // addition of &module.properties below.
- Libs: module.sdkLibraryProperties.Impl_only_libs,
- // Set the impl_only static libs. Note that the module's "static_libs" get appended as well, via the
- // addition of &module.properties below.
- Static_libs: module.sdkLibraryProperties.Impl_only_static_libs,
+
+ Libs: append(module.properties.Libs, module.sdkLibraryProperties.Impl_only_libs...),
+
+ Static_libs: append(module.properties.Static_libs, module.sdkLibraryProperties.Impl_only_static_libs...),
// Pass the apex_available settings down so that the impl library can be statically
// embedded within a library that is added to an APEX. Needed for updatable-media.
Apex_available: module.ApexAvailable(),
+
+ Stem: proptools.StringPtr(module.Name()),
}
properties := []interface{}{
@@ -2167,6 +2223,9 @@
if depTag == xmlPermissionsFileTag {
return true
}
+ if dep.Name() == module.implLibraryModuleName() {
+ return true
+ }
return module.Library.DepIsInSameApex(mctx, dep)
}
@@ -2294,7 +2353,7 @@
// once for public API level and once for system API level
func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookContext) {
// If the module has been disabled then don't create any child modules.
- if !module.Enabled() {
+ if !module.Enabled(mctx) {
return
}
@@ -2592,10 +2651,6 @@
commonToSdkLibraryAndImport
- // The reference to the implementation library created by the source module.
- // Is nil if the source module does not exist.
- implLibraryModule *Library
-
// The reference to the xml permissions module created by the source module.
// Is nil if the source module does not exist.
xmlPermissionsFileModule *sdkLibraryXml
@@ -3560,7 +3615,8 @@
s.Min_device_sdk = sdk.commonSdkLibraryProperties.Min_device_sdk
s.Max_device_sdk = sdk.commonSdkLibraryProperties.Max_device_sdk
- if sdk.dexpreopter.dexpreoptProperties.Dex_preopt_result.Profile_guided {
+ implLibrary := sdk.getImplLibraryModule()
+ if implLibrary != nil && implLibrary.dexpreopter.dexpreoptProperties.Dex_preopt_result.Profile_guided {
s.DexPreoptProfileGuided = proptools.BoolPtr(true)
}
}
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 0f163e6..d240e70 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -186,13 +186,13 @@
// test if quuz have created the api_contribution module
result.ModuleForTests(apiScopePublic.stubsSourceModuleName("quuz")+".api.contribution", "")
- fooDexJar := result.ModuleForTests("foo", "android_common").Rule("d8")
- // tests if kotlinc generated files are NOT excluded from output of foo.
- android.AssertStringDoesNotContain(t, "foo dex", fooDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module")
+ fooImplDexJar := result.ModuleForTests("foo.impl", "android_common").Rule("d8")
+ // tests if kotlinc generated files are NOT excluded from output of foo.impl.
+ android.AssertStringDoesNotContain(t, "foo.impl dex", fooImplDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module")
- barDexJar := result.ModuleForTests("bar", "android_common").Rule("d8")
- // tests if kotlinc generated files are excluded from output of bar.
- android.AssertStringDoesContain(t, "bar dex", barDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module")
+ barImplDexJar := result.ModuleForTests("bar.impl", "android_common").Rule("d8")
+ // tests if kotlinc generated files are excluded from output of bar.impl.
+ android.AssertStringDoesContain(t, "bar.impl dex", barImplDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module")
}
func TestJavaSdkLibrary_UpdatableLibrary(t *testing.T) {
@@ -1457,11 +1457,11 @@
preparer.RunTestWithBp(t, `
java_sdk_library {
name: "sdklib",
- srcs: ["a.java"],
- static_libs: ["util"],
- min_sdk_version: "30",
+ srcs: ["a.java"],
+ static_libs: ["util"],
+ min_sdk_version: "30",
unsafe_ignore_missing_latest_api: true,
- }
+ }
java_library {
name: "util",
@@ -1715,6 +1715,7 @@
aconfig_declarations {
name: "bar",
package: "com.example.package",
+ container: "com.android.foo",
srcs: [
"bar.aconfig",
],
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index b291e70..bad2cf1 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -69,6 +69,7 @@
configuredJars = configuredJars.AppendList(&standaloneConfiguredJars)
classpathJars = append(classpathJars, standaloneClasspathJars...)
p.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars)
+ p.classpathFragmentBase().installClasspathProto(ctx)
}
func (p *platformSystemServerClasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList {
diff --git a/provenance/provenance_singleton.go b/provenance/provenance_singleton.go
index 97345af..679632c 100644
--- a/provenance/provenance_singleton.go
+++ b/provenance/provenance_singleton.go
@@ -18,6 +18,7 @@
import (
"android/soong/android"
+
"github.com/google/blueprint"
)
@@ -68,6 +69,15 @@
func (p *provenanceInfoSingleton) GenerateBuildActions(context android.SingletonContext) {
allMetaDataFiles := make([]android.Path, 0)
+ moduleFilter := func(module android.Module) bool {
+ if !module.Enabled(context) || module.IsSkipInstall() {
+ return false
+ }
+ if p, ok := module.(ProvenanceMetadata); ok {
+ return p.ProvenanceMetaDataFile().String() != ""
+ }
+ return false
+ }
context.VisitAllModulesIf(moduleFilter, func(module android.Module) {
if p, ok := module.(ProvenanceMetadata); ok {
allMetaDataFiles = append(allMetaDataFiles, p.ProvenanceMetaDataFile())
@@ -91,16 +101,6 @@
context.Phony("droidcore", android.PathForPhony(context, "provenance_metadata"))
}
-func moduleFilter(module android.Module) bool {
- if !module.Enabled() || module.IsSkipInstall() {
- return false
- }
- if p, ok := module.(ProvenanceMetadata); ok {
- return p.ProvenanceMetaDataFile().String() != ""
- }
- return false
-}
-
func GenerateArtifactProvenanceMetaData(ctx android.ModuleContext, artifactPath android.Path, installedFile android.InstallPath) android.OutputPath {
onDevicePathOfInstalledFile := android.InstallPathToOnDevicePath(ctx, installedFile)
artifactMetaDataFile := android.PathForIntermediates(ctx, "provenance_metadata", ctx.ModuleDir(), ctx.ModuleName(), "provenance_metadata.textproto")
diff --git a/provenance/tools/Android.bp b/provenance/tools/Android.bp
index 0eddd76..b42e543 100644
--- a/provenance/tools/Android.bp
+++ b/provenance/tools/Android.bp
@@ -23,11 +23,6 @@
srcs: [
"gen_provenance_metadata.py",
],
- version: {
- py3: {
- embedded_launcher: true,
- },
- },
libs: [
"provenance_metadata_proto",
"libprotobuf-python",
diff --git a/python/binary.go b/python/binary.go
index c84eeee..b935aba 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -71,9 +71,6 @@
installedDest android.Path
androidMkSharedLibs []string
-
- // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo
- mergedAconfigFiles map[string]android.Paths
}
var _ android.AndroidMkEntriesProvider = (*PythonBinaryModule)(nil)
@@ -106,7 +103,6 @@
p.buildBinary(ctx)
p.installedDest = ctx.InstallFile(installDir(ctx, "bin", "", ""),
p.installSource.Base(), p.installSource)
- android.CollectDependencyAconfigFiles(ctx, &p.mergedAconfigFiles)
}
func (p *PythonBinaryModule) buildBinary(ctx android.ModuleContext) {
@@ -170,7 +166,6 @@
entries.SetString("LOCAL_MODULE_STEM", stem)
entries.AddStrings("LOCAL_SHARED_LIBRARIES", p.androidMkSharedLibs...)
entries.SetBool("LOCAL_CHECK_ELF_FILES", false)
- android.SetAconfigFileMkEntries(&p.ModuleBase, entries, p.mergedAconfigFiles)
})
return []android.AndroidMkEntries{entries}
diff --git a/python/python.go b/python/python.go
index e14fdf3..1ee533f 100644
--- a/python/python.go
+++ b/python/python.go
@@ -506,8 +506,8 @@
}
for _, d := range expandedData {
- if d.Ext() == pyExt || d.Ext() == protoExt {
- ctx.PropertyErrorf("data", "found (.py|.proto) file: %q!", d.String())
+ if d.Ext() == pyExt {
+ ctx.PropertyErrorf("data", "found (.py) file: %q!", d.String())
continue
}
runfilesPath := filepath.Join(pkgPath, d.Rel())
@@ -523,19 +523,19 @@
relativeRootMap := make(map[string]android.Paths)
var protoSrcs android.Paths
addPathMapping := func(path pathMapping) {
- // handle proto sources separately
- if path.src.Ext() == protoExt {
- protoSrcs = append(protoSrcs, path.src)
- } else {
- relativeRoot := strings.TrimSuffix(path.src.String(), path.src.Rel())
- relativeRootMap[relativeRoot] = append(relativeRootMap[relativeRoot], path.src)
- }
+ relativeRoot := strings.TrimSuffix(path.src.String(), path.src.Rel())
+ relativeRootMap[relativeRoot] = append(relativeRootMap[relativeRoot], path.src)
}
// "srcs" or "data" properties may contain filegroups so it might happen that
// the root directory for each source path is different.
for _, path := range p.srcsPathMappings {
- addPathMapping(path)
+ // handle proto sources separately
+ if path.src.Ext() == protoExt {
+ protoSrcs = append(protoSrcs, path.src)
+ } else {
+ addPathMapping(path)
+ }
}
for _, path := range p.dataPathMappings {
addPathMapping(path)
diff --git a/python/python_test.go b/python/python_test.go
index c0b7295..6a6bd1d 100644
--- a/python/python_test.go
+++ b/python/python_test.go
@@ -50,7 +50,7 @@
" Second file: in module %s at path %q."
noSrcFileErr = moduleVariantErrTemplate + "doesn't have any source files!"
badSrcFileExtErr = moduleVariantErrTemplate + "srcs: found non (.py|.proto) file: %q!"
- badDataFileExtErr = moduleVariantErrTemplate + "data: found (.py|.proto) file: %q!"
+ badDataFileExtErr = moduleVariantErrTemplate + "data: found (.py) file: %q!"
bpFile = "Android.bp"
data = []struct {
diff --git a/python/test.go b/python/test.go
index 2b939e7..85decf9 100644
--- a/python/test.go
+++ b/python/test.go
@@ -18,6 +18,7 @@
"fmt"
"android/soong/testing"
+
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -151,7 +152,6 @@
// just use buildBinary() so that the binary is not installed into the location
// it would be for regular binaries.
p.PythonLibraryModule.GenerateAndroidBuildActions(ctx)
- android.CollectDependencyAconfigFiles(ctx, &p.mergedAconfigFiles)
p.buildBinary(ctx)
var configs []tradefed.Option
@@ -227,7 +227,6 @@
}
entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !BoolDefault(p.binaryProperties.Auto_gen_config, true))
- android.SetAconfigFileMkEntries(&p.ModuleBase, entries, p.mergedAconfigFiles)
p.testProperties.Test_options.SetAndroidMkEntries(entries)
})
diff --git a/python/tests/Android.bp b/python/tests/Android.bp
index e5569ba..056f7ed 100644
--- a/python/tests/Android.bp
+++ b/python/tests/Android.bp
@@ -27,9 +27,4 @@
test_options: {
unit_test: false,
},
- version: {
- py3: {
- embedded_launcher: true,
- },
- },
}
diff --git a/python/tests/dont_import_folder_of_entrypoint/Android.bp b/python/tests/dont_import_folder_of_entrypoint/Android.bp
index e54e9b2..ab2e314 100644
--- a/python/tests/dont_import_folder_of_entrypoint/Android.bp
+++ b/python/tests/dont_import_folder_of_entrypoint/Android.bp
@@ -10,17 +10,3 @@
"mypkg/mymodule.py",
],
}
-
-python_test_host {
- name: "py_dont_import_folder_of_entrypoint_test_embedded_launcher",
- main: "mypkg/main.py",
- srcs: [
- "mypkg/main.py",
- "mypkg/mymodule.py",
- ],
- version: {
- py3: {
- embedded_launcher: true,
- },
- },
-}
diff --git a/rust/afdo.go b/rust/afdo.go
index 6116c5e..6bd4bae 100644
--- a/rust/afdo.go
+++ b/rust/afdo.go
@@ -39,7 +39,7 @@
return
}
- if mod, ok := ctx.Module().(*Module); ok && mod.Enabled() {
+ if mod, ok := ctx.Module().(*Module); ok && mod.Enabled(ctx) {
fdoProfileName, err := actx.DeviceConfig().AfdoProfile(actx.ModuleName())
if err != nil {
ctx.ModuleErrorf("%s", err.Error())
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 021dd60..8de6b60 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -69,7 +69,6 @@
} else if mod.InProduct() {
entries.SetBool("LOCAL_IN_PRODUCT", true)
}
- android.SetAconfigFileMkEntries(mod.AndroidModuleBase(), entries, mod.mergedAconfigFiles)
},
},
}
diff --git a/rust/bindgen.go b/rust/bindgen.go
index eaed1b9..4277753 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -102,8 +102,17 @@
// "my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]"
Custom_bindgen string
- // flag to indicate if bindgen should handle `static inline` functions (default is false)
- Handle_static_inline bool
+ // flag to indicate if bindgen should handle `static inline` functions (default is false).
+ // If true, Static_inline_library must be set.
+ Handle_static_inline *bool
+
+ // module name of the corresponding cc_library_static which includes the static_inline wrapper
+ // generated functions from bindgen. Must be used together with handle_static_inline.
+ //
+ // If there are no static inline functions provided through the header file,
+ // then bindgen (as of 0.69.2) will silently fail to output a .c file, and
+ // the cc_library_static depending on this module will fail compilation.
+ Static_inline_library *string
}
type bindgenDecorator struct {
@@ -159,6 +168,18 @@
var cflags []string
var implicits android.Paths
+ var implicitOutputs android.WritablePaths
+ var validations android.Paths
+
+ if Bool(b.Properties.Handle_static_inline) && b.Properties.Static_inline_library == nil {
+ ctx.PropertyErrorf("handle_static_inline",
+ "requires declaring static_inline_library to the corresponding cc_library module that includes the generated C source from bindgen.")
+ }
+
+ if b.Properties.Static_inline_library != nil && !Bool(b.Properties.Handle_static_inline) {
+ ctx.PropertyErrorf("static_inline_library",
+ "requires declaring handle_static_inline.")
+ }
implicits = append(implicits, deps.depGeneratedHeaders...)
@@ -235,8 +256,11 @@
bindgenFlags := defaultBindgenFlags
bindgenFlags = append(bindgenFlags, esc(b.Properties.Bindgen_flags)...)
- if b.Properties.Handle_static_inline {
- bindgenFlags = append(bindgenFlags, "--experimental --wrap-static-fns")
+ if Bool(b.Properties.Handle_static_inline) {
+ outputStaticFnsFile := android.PathForModuleOut(ctx, b.BaseSourceProvider.getStem(ctx)+".c")
+ implicitOutputs = append(implicitOutputs, outputStaticFnsFile)
+ validations = append(validations, outputStaticFnsFile)
+ bindgenFlags = append(bindgenFlags, []string{"--experimental", "--wrap-static-fns", "--wrap-static-fns-path=" + outputStaticFnsFile.String()}...)
}
// cat reads from stdin if its command line is empty,
@@ -285,11 +309,13 @@
}
ctx.Build(pctx, android.BuildParams{
- Rule: bindgen,
- Description: strings.Join([]string{cmdDesc, wrapperFile.Path().Rel()}, " "),
- Output: outputFile,
- Input: wrapperFile.Path(),
- Implicits: implicits,
+ Rule: bindgen,
+ Description: strings.Join([]string{cmdDesc, wrapperFile.Path().Rel()}, " "),
+ Output: outputFile,
+ Input: wrapperFile.Path(),
+ Implicits: implicits,
+ ImplicitOutputs: implicitOutputs,
+ Validations: validations,
Args: map[string]string{
"cmd": cmd,
"flags": strings.Join(bindgenFlags, " "),
@@ -299,6 +325,14 @@
})
b.BaseSourceProvider.OutputFiles = android.Paths{outputFile}
+
+ // Append any additional implicit outputs after the entry point source.
+ // We append any generated .c file here so it can picked up by cc_library_static modules.
+ // Those CC modules need to be sure not to pass any included .rs files to Clang.
+ // We don't have to worry about the additional .c files for Rust modules as only the entry point
+ // is passed to rustc.
+ b.BaseSourceProvider.OutputFiles = append(b.BaseSourceProvider.OutputFiles, implicitOutputs.Paths()...)
+
return outputFile
}
@@ -350,6 +384,14 @@
deps = muslDeps(ctx, deps, false)
}
+ if !ctx.RustModule().Source() && b.Properties.Static_inline_library != nil {
+ // This is not the source variant, so add the static inline library as a dependency.
+ //
+ // This is necessary to avoid a circular dependency between the source variant and the
+ // dependent cc module.
+ deps.StaticLibs = append(deps.StaticLibs, String(b.Properties.Static_inline_library))
+ }
+
deps.SharedLibs = append(deps.SharedLibs, b.ClangProperties.Shared_libs...)
deps.StaticLibs = append(deps.StaticLibs, b.ClangProperties.Static_libs...)
deps.HeaderLibs = append(deps.HeaderLibs, b.ClangProperties.Header_libs...)
diff --git a/rust/bindgen_test.go b/rust/bindgen_test.go
index 11cfe4e..2b7362f 100644
--- a/rust/bindgen_test.go
+++ b/rust/bindgen_test.go
@@ -228,7 +228,6 @@
// we may be able to check libbinder.RuleParams.Command to see if it contains $(cat /dev/null flag_file.txt)
}
-
func TestBindgenHandleStaticInlining(t *testing.T) {
ctx := testRust(t, `
rust_bindgen {
@@ -237,12 +236,54 @@
crate_name: "bindgen",
stem: "libbindgen",
source_stem: "bindings",
+ handle_static_inline: true,
+ static_inline_library: "libbindgen_staticfns"
+ }
+
+ cc_library_static {
+ name: "libbindgen_staticfns",
+ srcs: [":libbindgen"],
+ include_dirs: ["src/"],
+ }
+ `)
+ libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a_source").Output("bindings.rs")
+ // Make sure the flag to support `static inline` functions is present
+ if !strings.Contains(libbindgen.Args["flags"], "--wrap-static-fns") {
+ t.Errorf("missing flag to handle static inlining in rust_bindgen rule: flags %#v", libbindgen.Args["flags"])
+ }
+
+ if !strings.Contains(libbindgen.Args["flags"], "--wrap-static-fns-path") {
+ t.Errorf("missing flag to define path for static inlining C source from bindgen (--wrap-static-fns-path): flags %#v", libbindgen.Args["flags"])
+ }
+
+}
+
+func TestBindgenStaticInlineProperties(t *testing.T) {
+ // Make sure handle_static_inline without static_inline_library generates an error
+ testRustError(t, "requires declaring static_inline_library to the corresponding cc_library module that includes the generated C source from bindgen", `
+ rust_bindgen {
+ name: "libbindgen",
+ wrapper_src: "src/any.h",
+ crate_name: "bindgen",
+ stem: "libbindgen",
+ source_stem: "bindings",
handle_static_inline: true
}
`)
- libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a_source").Output("bindings.rs")
- // Make sure the flag to support `static inline` functions is present
- if !strings.Contains(libbindgen.Args["flags"], "--wrap-static-fns") {
- t.Errorf("missing flag to handle static inlining in rust_bindgen rule: flags %#v", libbindgen.Args["flags"])
- }
+ testRustError(t, "requires declaring handle_static_inline", `
+ rust_bindgen {
+ name: "libbindgen",
+ wrapper_src: "src/any.h",
+ crate_name: "bindgen",
+ stem: "libbindgen",
+ source_stem: "bindings",
+ static_inline_library: "libbindgen_staticfns"
+ }
+
+ cc_library_static {
+ name: "libbindgen_staticfns",
+ srcs: [":libbindgen"],
+ include_dirs: ["src/"],
+ }
+ `)
}
diff --git a/rust/config/global.go b/rust/config/global.go
index 03333b8..e83e23a 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
var (
pctx = android.NewPackageContext("android/soong/rust/config")
- RustDefaultVersion = "1.77.1"
+ RustDefaultVersion = "1.77.1.p1"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2021"
Stdlibs = []string{
diff --git a/rust/doc.go b/rust/doc.go
index 6970d79..fe20523 100644
--- a/rust/doc.go
+++ b/rust/doc.go
@@ -38,7 +38,7 @@
FlagWithArg("-D ", docDir.String())
ctx.VisitAllModules(func(module android.Module) {
- if !module.Enabled() {
+ if !module.Enabled(ctx) {
return
}
diff --git a/rust/library.go b/rust/library.go
index 7300001..1eb0c5e 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -790,7 +790,7 @@
if sourceVariant {
sv := modules[0]
for _, v := range modules[1:] {
- if !v.Enabled() {
+ if !v.Enabled(mctx) {
continue
}
mctx.AddInterVariantDependency(sourceDepTag, v, sv)
diff --git a/rust/project_json.go b/rust/project_json.go
index 05fc09b..24dcc89 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -119,7 +119,7 @@
if !ok {
return nil, false
}
- if !rModule.Enabled() {
+ if !rModule.Enabled(ctx) {
return nil, false
}
return rModule, true
diff --git a/rust/rust.go b/rust/rust.go
index 4edd807..93853e5 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -174,9 +174,6 @@
apexSdkVersion android.ApiLevel
transitiveAndroidMkSharedLibs *android.DepSet[string]
-
- // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo
- mergedAconfigFiles map[string]android.Paths
}
func (mod *Module) Header() bool {
@@ -1010,8 +1007,6 @@
if mod.testModule {
android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
}
-
- android.CollectDependencyAconfigFiles(ctx, &mod.mergedAconfigFiles)
}
func (mod *Module) deps(ctx DepsContext) Deps {
@@ -1724,7 +1719,7 @@
}
func BeginMutator(ctx android.BottomUpMutatorContext) {
- if mod, ok := ctx.Module().(*Module); ok && mod.Enabled() {
+ if mod, ok := ctx.Module().(*Module); ok && mod.Enabled(ctx) {
mod.beginMutator(ctx)
}
}
diff --git a/rust/sanitize.go b/rust/sanitize.go
index bfd3971..c086880 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -258,7 +258,7 @@
func rustSanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) {
if mod, ok := mctx.Module().(*Module); ok && mod.sanitize != nil {
- if !mod.Enabled() {
+ if !mod.Enabled(mctx) {
return
}
diff --git a/scripts/Android.bp b/scripts/Android.bp
index d039a81..80cd935 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -29,11 +29,6 @@
"manifest_fixer_test.py",
"manifest_fixer.py",
],
- version: {
- py3: {
- embedded_launcher: true,
- },
- },
libs: [
"manifest_utils",
],
@@ -214,11 +209,6 @@
srcs: [
"conv_linker_config.py",
],
- version: {
- py3: {
- embedded_launcher: true,
- },
- },
libs: [
"linker_config_proto",
],
@@ -299,20 +289,16 @@
srcs: [
"merge_directories.py",
],
- version: {
- py3: {
- embedded_launcher: true,
- },
- },
}
python_binary_host {
name: "buildinfo",
main: "buildinfo.py",
srcs: ["buildinfo.py"],
- version: {
- py3: {
- embedded_launcher: true,
- },
- },
+}
+
+python_binary_host {
+ name: "extra_install_zips_file_list",
+ main: "extra_install_zips_file_list.py",
+ srcs: ["extra_install_zips_file_list.py"],
}
diff --git a/scripts/extra_install_zips_file_list.py b/scripts/extra_install_zips_file_list.py
new file mode 100755
index 0000000..148d6cc
--- /dev/null
+++ b/scripts/extra_install_zips_file_list.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python3
+
+import argparse
+import os
+import sys
+import zipfile
+from typing import List
+
+def list_files_in_zip(zipfile_path: str) -> List[str]:
+ with zipfile.ZipFile(zipfile_path, 'r') as zf:
+ return zf.namelist()
+
+def main():
+ parser = argparse.ArgumentParser(
+ description='Lists paths to all files inside an EXTRA_INSTALL_ZIPS zip file relative to a partition staging directory. '
+ 'This script is just a helper because its difficult to implement this logic in make code.'
+ )
+ parser.add_argument('staging_dir',
+ help='Path to the partition staging directory')
+ parser.add_argument('extra_install_zips', nargs='*',
+ help='The value of EXTRA_INSTALL_ZIPS from make. '
+ 'It should be a list of primary_file:extraction_dir:zip_file trios. '
+ 'The primary file will be ignored by this script, you should ensure that '
+ 'the list of trios given to this script is already filtered by relevant primary files.')
+ args = parser.parse_args()
+
+ staging_dir = args.staging_dir.removesuffix('/') + '/'
+
+ for zip_trio in args.extra_install_zips:
+ _, d, z = zip_trio.split(':')
+ d = d.removesuffix('/') + '/'
+
+ if d.startswith(staging_dir):
+ d = os.path.relpath(d, staging_dir)
+ if d == '.':
+ d = ''
+ for f in list_files_in_zip(z):
+ print(os.path.join(d, f))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/gen-kotlin-build-file.py b/scripts/gen-kotlin-build-file.py
index 83b4cd8..99afdca 100644
--- a/scripts/gen-kotlin-build-file.py
+++ b/scripts/gen-kotlin-build-file.py
@@ -79,7 +79,7 @@
elif src.endswith('.kt'):
f.write(' <sources path="%s"/>\n' % path)
else:
- raise RuntimeError('unknown source file type %s' % file)
+ raise RuntimeError(f'unknown source file type {src} from rspfile {rsp_file}')
for rsp_file in args.common_srcs:
for src in NinjaRspFileReader(rsp_file):
diff --git a/scripts/hiddenapi/Android.bp b/scripts/hiddenapi/Android.bp
index 1e89efe..43edf44 100644
--- a/scripts/hiddenapi/Android.bp
+++ b/scripts/hiddenapi/Android.bp
@@ -18,19 +18,9 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-python_defaults {
- name: "hiddenapi_defaults",
- version: {
- py3: {
- embedded_launcher: true,
- },
- },
-}
-
python_binary_host {
name: "analyze_bcpf",
main: "analyze_bcpf.py",
- defaults: ["hiddenapi_defaults"],
srcs: ["analyze_bcpf.py"],
// Make sure that the bpmodify tool is built.
data: [":bpmodify"],
@@ -42,7 +32,6 @@
python_test_host {
name: "analyze_bcpf_test",
main: "analyze_bcpf_test.py",
- defaults: ["hiddenapi_defaults"],
srcs: [
"analyze_bcpf.py",
"analyze_bcpf_test.py",
@@ -60,21 +49,18 @@
python_binary_host {
name: "merge_csv",
main: "merge_csv.py",
- defaults: ["hiddenapi_defaults"],
srcs: ["merge_csv.py"],
}
python_binary_host {
name: "generate_hiddenapi_lists",
main: "generate_hiddenapi_lists.py",
- defaults: ["hiddenapi_defaults"],
srcs: ["generate_hiddenapi_lists.py"],
}
python_test_host {
name: "generate_hiddenapi_lists_test",
main: "generate_hiddenapi_lists_test.py",
- defaults: ["hiddenapi_defaults"],
srcs: [
"generate_hiddenapi_lists.py",
"generate_hiddenapi_lists_test.py",
@@ -92,7 +78,6 @@
python_test_host {
name: "signature_trie_test",
main: "signature_trie_test.py",
- defaults: ["hiddenapi_defaults"],
srcs: ["signature_trie_test.py"],
libs: ["signature_trie"],
test_options: {
@@ -103,7 +88,6 @@
python_binary_host {
name: "verify_overlaps",
main: "verify_overlaps.py",
- defaults: ["hiddenapi_defaults"],
srcs: ["verify_overlaps.py"],
libs: [
"signature_trie",
@@ -113,7 +97,6 @@
python_test_host {
name: "verify_overlaps_test",
main: "verify_overlaps_test.py",
- defaults: ["hiddenapi_defaults"],
srcs: [
"verify_overlaps.py",
"verify_overlaps_test.py",
@@ -129,14 +112,12 @@
python_binary_host {
name: "signature_patterns",
main: "signature_patterns.py",
- defaults: ["hiddenapi_defaults"],
srcs: ["signature_patterns.py"],
}
python_test_host {
name: "signature_patterns_test",
main: "signature_patterns_test.py",
- defaults: ["hiddenapi_defaults"],
srcs: [
"signature_patterns.py",
"signature_patterns_test.py",
diff --git a/scripts/run-soong-tests-with-go-tools.sh b/scripts/run-soong-tests-with-go-tools.sh
index 93c622e..1fbb1fc 100755
--- a/scripts/run-soong-tests-with-go-tools.sh
+++ b/scripts/run-soong-tests-with-go-tools.sh
@@ -74,6 +74,6 @@
(cd "$dir";
eval ${network_jail} -- ${GOROOT}/bin/go build ./...
eval ${network_jail} -- ${GOROOT}/bin/go test ./...
- eval ${network_jail} -- ${GOROOT}/bin/go test -race -short ./...
+ eval ${network_jail} -- ${GOROOT}/bin/go test -race -timeout 20m -short ./...
)
done
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 8d3bbfa..6e25122 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -1095,7 +1095,7 @@
bcpf := result.ModuleForTests("mybootclasspathfragment", "android_common")
rule := bcpf.Output("out/soong/.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi" + suffix + "/stub-flags.csv")
- android.AssertPathsRelativeToTopEquals(t, "stub flags inputs", expectedStubFlagsInputs, rule.Implicits)
+ android.AssertPathsRelativeToTopEquals(t, "stub flags inputs", android.SortedUniqueStrings(expectedStubFlagsInputs), android.SortedUniquePaths(rule.Implicits))
CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(expectedSdkSnapshot),
@@ -1153,7 +1153,7 @@
// of the snapshot.
expectedStubFlagsInputs := []string{
"out/soong/.intermediates/mysdklibrary.stubs.exportable/android_common/dex/mysdklibrary.stubs.exportable.jar",
- "out/soong/.intermediates/mysdklibrary/android_common/aligned/mysdklibrary.jar",
+ "out/soong/.intermediates/mysdklibrary.impl/android_common/aligned/mysdklibrary.jar",
}
testSnapshotWithBootClasspathFragment_MinSdkVersion(t, "S",
@@ -1234,9 +1234,9 @@
// they are both part of the snapshot.
expectedStubFlagsInputs := []string{
"out/soong/.intermediates/mynewsdklibrary.stubs.exportable/android_common/dex/mynewsdklibrary.stubs.exportable.jar",
- "out/soong/.intermediates/mynewsdklibrary/android_common/aligned/mynewsdklibrary.jar",
+ "out/soong/.intermediates/mynewsdklibrary.impl/android_common/aligned/mynewsdklibrary.jar",
"out/soong/.intermediates/mysdklibrary.stubs.exportable/android_common/dex/mysdklibrary.stubs.exportable.jar",
- "out/soong/.intermediates/mysdklibrary/android_common/aligned/mysdklibrary.jar",
+ "out/soong/.intermediates/mysdklibrary.impl/android_common/aligned/mysdklibrary.jar",
}
testSnapshotWithBootClasspathFragment_MinSdkVersion(t, "Tiramisu",
diff --git a/snapshot/host_fake_snapshot.go b/snapshot/host_fake_snapshot.go
index 63cd4e1..b416ebd 100644
--- a/snapshot/host_fake_snapshot.go
+++ b/snapshot/host_fake_snapshot.go
@@ -116,7 +116,7 @@
prebuilts[android.RemoveOptionalPrebuiltPrefix(module.Name())] = true
return
}
- if !module.Enabled() || module.IsHideFromMake() {
+ if !module.Enabled(ctx) || module.IsHideFromMake() {
return
}
apexInfo, _ := android.SingletonModuleProvider(ctx, module, android.ApexInfoProvider)
diff --git a/ui/build/rbe.go b/ui/build/rbe.go
index 5142a41..8fa147f 100644
--- a/ui/build/rbe.go
+++ b/ui/build/rbe.go
@@ -159,12 +159,6 @@
fmt.Fprintln(ctx.Writer, "")
return
}
- if config.GoogleProdCredsExist() {
- return
- }
- fmt.Fprintln(ctx.Writer, "")
- fmt.Fprintln(ctx.Writer, "\033[33mWARNING: Missing LOAS credentials, please run `gcert`. This is required for a successful build execution. See go/rbe-android-default-announcement for more information.\033[0m")
- fmt.Fprintln(ctx.Writer, "")
}
// DumpRBEMetrics creates a metrics protobuf file containing RBE related metrics.