diff options
| -rw-r--r-- | android/all_teams.go | 6 | ||||
| -rw-r--r-- | android/all_teams_test.go | 78 | ||||
| -rw-r--r-- | android/apex.go | 39 | ||||
| -rw-r--r-- | android/rule_builder.go | 6 | ||||
| -rw-r--r-- | android/sdk.go | 1 | ||||
| -rw-r--r-- | apex/apex.go | 15 | ||||
| -rw-r--r-- | apex/apex_test.go | 93 | ||||
| -rw-r--r-- | cc/binary_sdk_member.go | 2 | ||||
| -rw-r--r-- | cc/cc.go | 2 | ||||
| -rw-r--r-- | cc/cmake_module_cc.txt | 8 | ||||
| -rw-r--r-- | cc/cmake_snapshot.go | 20 | ||||
| -rw-r--r-- | cc/compiler.go | 6 | ||||
| -rw-r--r-- | cc/library.go | 41 | ||||
| -rw-r--r-- | cc/library_sdk_member.go | 2 | ||||
| -rw-r--r-- | cc/linker.go | 21 | ||||
| -rw-r--r-- | cc/object.go | 19 | ||||
| -rw-r--r-- | genrule/genrule.go | 35 | ||||
| -rw-r--r-- | genrule/genrule_test.go | 63 | ||||
| -rw-r--r-- | mk2rbc/mk2rbc.go | 1 | ||||
| -rw-r--r-- | mk2rbc/mk2rbc_test.go | 2 | ||||
| -rw-r--r-- | rust/bindgen.go | 6 | ||||
| -rw-r--r-- | sdk/update.go | 8 | ||||
| -rw-r--r-- | ui/build/config.go | 19 | ||||
| -rw-r--r-- | ui/build/kati.go | 2 |
24 files changed, 429 insertions, 66 deletions
diff --git a/android/all_teams.go b/android/all_teams.go index e3c2e70bd..01be396d5 100644 --- a/android/all_teams.go +++ b/android/all_teams.go @@ -1,6 +1,7 @@ package android import ( + "path" "path/filepath" "android/soong/android/team_proto" @@ -153,6 +154,11 @@ func (t *allTeamsSingleton) lookupTeamForAllModules() *team_proto.AllTeams { } else { teamProperties, found = t.lookupDefaultTeam(m.bpFile) } + // Deal with one blueprint file including another by looking up the default + // in the main Android.bp rather than one listed with "build = [My.bp]" + if !found { + teamProperties, found = t.lookupDefaultTeam(path.Join(path.Dir(m.bpFile), "Android.bp")) + } trendy_team_id := "" if found { diff --git a/android/all_teams_test.go b/android/all_teams_test.go index 96ed92fc5..fa8c048d0 100644 --- a/android/all_teams_test.go +++ b/android/all_teams_test.go @@ -264,6 +264,84 @@ func TestPackageLookup(t *testing.T) { AssertDeepEquals(t, "compare maps", expectedTeams, actualTeams) } +func TestPackageLookupForIncludedBlueprintFiles(t *testing.T) { + t.Parallel() + rootBp := ` + package { default_team: "team_top"} + team { + name: "team_top", + trendy_team_id: "trendy://team_top", + } + build = ["include.bp"] + ` + includeBp := ` + fake { + name: "IncludedModule", + } ` + + ctx := GroupFixturePreparers( + prepareForTestWithTeamAndFakes, + PrepareForTestWithPackageModule, + FixtureRegisterWithContext(func(ctx RegistrationContext) { + ctx.RegisterParallelSingletonType("all_teams", AllTeamsFactory) + }), + FixtureAddTextFile("Android.bp", rootBp), + FixtureAddTextFile("include.bp", includeBp), + ).RunTest(t) + + var teams *team_proto.AllTeams + teams = getTeamProtoOutput(t, ctx) + + // map of module name -> trendy team name. + actualTeams := make(map[string]*string) + for _, teamProto := range teams.Teams { + actualTeams[teamProto.GetTargetName()] = teamProto.TrendyTeamId + } + expectedTeams := map[string]*string{ + "IncludedModule": proto.String("trendy://team_top"), + } + AssertDeepEquals(t, "compare maps", expectedTeams, actualTeams) +} + +func TestPackageLookupForIncludedBlueprintFilesWithPackageInChildBlueprint(t *testing.T) { + t.Parallel() + rootBp := ` + team { + name: "team_top", + trendy_team_id: "trendy://team_top", + } + build = ["include.bp"] + ` + includeBp := ` + package { default_team: "team_top"} + fake { + name: "IncludedModule", + } ` + + ctx := GroupFixturePreparers( + prepareForTestWithTeamAndFakes, + PrepareForTestWithPackageModule, + FixtureRegisterWithContext(func(ctx RegistrationContext) { + ctx.RegisterParallelSingletonType("all_teams", AllTeamsFactory) + }), + FixtureAddTextFile("Android.bp", rootBp), + FixtureAddTextFile("include.bp", includeBp), + ).RunTest(t) + + var teams *team_proto.AllTeams + teams = getTeamProtoOutput(t, ctx) + + // map of module name -> trendy team name. + actualTeams := make(map[string]*string) + for _, teamProto := range teams.Teams { + actualTeams[teamProto.GetTargetName()] = teamProto.TrendyTeamId + } + expectedTeams := map[string]*string{ + "IncludedModule": proto.String("trendy://team_top"), + } + AssertDeepEquals(t, "compare maps", expectedTeams, actualTeams) +} + type fakeForTests struct { ModuleBase diff --git a/android/apex.go b/android/apex.go index ef4cf82cd..028be57ec 100644 --- a/android/apex.go +++ b/android/apex.go @@ -280,6 +280,7 @@ type ApexProperties struct { // // "//apex_available:anyapex" is a pseudo APEX name that matches to any APEX. // "//apex_available:platform" refers to non-APEX partitions like "system.img". + // Prefix pattern (com.foo.*) can be used to match with any APEX name with the prefix(com.foo.). // Default is ["//apex_available:platform"]. Apex_available []string @@ -491,10 +492,27 @@ func CheckAvailableForApex(what string, apex_available []string) bool { if len(apex_available) == 0 { return what == AvailableToPlatform } - return InList(what, apex_available) || - (what != AvailableToPlatform && InList(AvailableToAnyApex, apex_available)) || - (what == "com.google.mainline.primary.libs") || // TODO b/248601389 - (what == "com.google.mainline.go.primary.libs") // TODO b/248601389 + + // TODO b/248601389 + if what == "com.google.mainline.primary.libs" || what == "com.google.mainline.go.primary.libs" { + return true + } + + for _, apex_name := range apex_available { + // exact match. + if apex_name == what { + return true + } + // //apex_available:anyapex matches with any apex name, but not //apex_available:platform + if apex_name == AvailableToAnyApex && what != AvailableToPlatform { + return true + } + // prefix match. + if strings.HasSuffix(apex_name, ".*") && strings.HasPrefix(what, strings.TrimSuffix(apex_name, "*")) { + return true + } + } + return false } // Implements ApexModule @@ -523,6 +541,19 @@ func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) { if n == AvailableToPlatform || n == AvailableToAnyApex { continue } + // Prefix pattern should end with .* and has at least two components. + if strings.Contains(n, "*") { + if !strings.HasSuffix(n, ".*") { + mctx.PropertyErrorf("apex_available", "Wildcard should end with .* like com.foo.*") + } + if strings.Count(n, ".") < 2 { + mctx.PropertyErrorf("apex_available", "Wildcard requires two or more components like com.foo.*") + } + if strings.Count(n, "*") != 1 { + mctx.PropertyErrorf("apex_available", "Wildcard is not allowed in the middle.") + } + continue + } if !mctx.OtherModuleExists(n) && !mctx.Config().AllowMissingDependencies() { mctx.PropertyErrorf("apex_available", "%q is not a valid module name", n) } diff --git a/android/rule_builder.go b/android/rule_builder.go index 8b03124bf..464aca4a0 100644 --- a/android/rule_builder.go +++ b/android/rule_builder.go @@ -554,6 +554,12 @@ func (r *RuleBuilder) build(name string, desc string, ninjaEscapeCommandString b To: proto.String(r.sboxPathForInputRel(input)), }) } + for _, input := range r.OrderOnlys() { + command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{ + From: proto.String(input.String()), + To: proto.String(r.sboxPathForInputRel(input)), + }) + } // If using rsp files copy them and their contents into the sbox directory with // the appropriate path mappings. diff --git a/android/sdk.go b/android/sdk.go index 4bcbe2e7a..d3f04a4f9 100644 --- a/android/sdk.go +++ b/android/sdk.go @@ -813,6 +813,7 @@ type SdkMemberProperties interface { // SdkMemberContext provides access to information common to a specific member. type SdkMemberContext interface { + ConfigAndErrorContext // SdkModuleContext returns the module context of the sdk common os variant which is creating the // snapshot. diff --git a/apex/apex.go b/apex/apex.go index dd1c0b52e..77ebf2624 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -2767,10 +2767,21 @@ func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) { if to.AvailableFor(apexName) || baselineApexAvailable(apexName, toName) { return true } + + // Let's give some hint for apex_available + hint := fmt.Sprintf("%q", apexName) + + if strings.HasPrefix(apexName, "com.") && !strings.HasPrefix(apexName, "com.android.") && strings.Count(apexName, ".") >= 2 { + // In case of a partner APEX, prefix format might be an option. + components := strings.Split(apexName, ".") + components[len(components)-1] = "*" + hint += fmt.Sprintf(" or %q", strings.Join(components, ".")) + } + ctx.ModuleErrorf("%q requires %q that doesn't list the APEX under 'apex_available'."+ "\n\nDependency path:%s\n\n"+ - "Consider adding %q to 'apex_available' property of %q", - fromName, toName, ctx.GetPathString(true), apexName, toName) + "Consider adding %s to 'apex_available' property of %q", + fromName, toName, ctx.GetPathString(true), hint, toName) // Visit this module's dependencies to check and report any issues with their availability. return true }) diff --git a/apex/apex_test.go b/apex/apex_test.go index c37c7d0c7..6b9944d76 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -6722,6 +6722,99 @@ func TestApexAvailable_CreatedForApex(t *testing.T) { } } +func TestApexAvailable_PrefixMatch(t *testing.T) { + + for _, tc := range []struct { + name string + apexAvailable string + expectedError string + }{ + { + name: "prefix matches correctly", + apexAvailable: "com.foo.*", + }, + { + name: "prefix doesn't match", + apexAvailable: "com.bar.*", + expectedError: `Consider .* "com.foo\.\*"`, + }, + { + name: "short prefix", + apexAvailable: "com.*", + expectedError: "requires two or more components", + }, + { + name: "wildcard not in the end", + apexAvailable: "com.*.foo", + expectedError: "should end with .*", + }, + { + name: "wildcard in the middle", + apexAvailable: "com.foo*.*", + expectedError: "not allowed in the middle", + }, + { + name: "hint with prefix pattern", + apexAvailable: "//apex_available:platform", + expectedError: "Consider adding \"com.foo.bar\" or \"com.foo.*\"", + }, + } { + t.Run(tc.name, func(t *testing.T) { + errorHandler := android.FixtureExpectsNoErrors + if tc.expectedError != "" { + errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(tc.expectedError) + } + context := android.GroupFixturePreparers( + prepareForApexTest, + android.FixtureMergeMockFs(android.MockFS{ + "system/sepolicy/apex/com.foo.bar-file_contexts": nil, + }), + ).ExtendWithErrorHandler(errorHandler) + + context.RunTestWithBp(t, ` + apex { + name: "com.foo.bar", + key: "myapex.key", + native_shared_libs: ["libfoo"], + updatable: false, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + cc_library { + name: "libfoo", + stl: "none", + system_shared_libs: [], + apex_available: ["`+tc.apexAvailable+`"], + }`) + }) + } + testApexError(t, `Consider adding "com.foo" to`, ` + apex { + name: "com.foo", // too short for a partner apex + key: "myapex.key", + native_shared_libs: ["libfoo"], + updatable: false, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + cc_library { + name: "libfoo", + stl: "none", + system_shared_libs: [], + } + `) +} + func TestOverrideApex(t *testing.T) { ctx := testApex(t, ` apex { diff --git a/cc/binary_sdk_member.go b/cc/binary_sdk_member.go index 71e0cd8ce..8a7ea8845 100644 --- a/cc/binary_sdk_member.go +++ b/cc/binary_sdk_member.go @@ -132,7 +132,7 @@ func (p *nativeBinaryInfoProperties) PopulateFromVariant(ctx android.SdkMemberCo if ccModule.linker != nil { specifiedDeps := specifiedDeps{} - specifiedDeps = ccModule.linker.linkerSpecifiedDeps(specifiedDeps) + specifiedDeps = ccModule.linker.linkerSpecifiedDeps(ctx, ccModule, specifiedDeps) p.SharedLibs = specifiedDeps.sharedLibs p.SystemSharedLibs = specifiedDeps.systemSharedLibs @@ -613,7 +613,7 @@ type linker interface { coverageOutputFilePath() android.OptionalPath // Get the deps that have been explicitly specified in the properties. - linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps + linkerSpecifiedDeps(ctx android.ConfigAndErrorContext, module *Module, specifiedDeps specifiedDeps) specifiedDeps moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) } diff --git a/cc/cmake_module_cc.txt b/cc/cmake_module_cc.txt index 0dc45aed1..0f6e62f10 100644 --- a/cc/cmake_module_cc.txt +++ b/cc/cmake_module_cc.txt @@ -2,10 +2,10 @@ <<$includeDirs := getIncludeDirs .Ctx .M>> <<$cflags := getCflagsProperty .Ctx .M>> <<$deps := mapLibraries .Ctx .M (concat5 -(getLinkerProperties .M).Whole_static_libs -(getLinkerProperties .M).Static_libs -(getLinkerProperties .M).Shared_libs -(getLinkerProperties .M).Header_libs +(getWholeStaticLibsProperty .Ctx .M) +(getStaticLibsProperty .Ctx .M) +(getSharedLibsProperty .Ctx .M) +(getHeaderLibsProperty .Ctx .M) (getExtraLibs .M) ) .Pprop.LibraryMapping>> <<$moduleType := getModuleType .M>> diff --git a/cc/cmake_snapshot.go b/cc/cmake_snapshot.go index 600ac47f7..61fa46d98 100644 --- a/cc/cmake_snapshot.go +++ b/cc/cmake_snapshot.go @@ -204,12 +204,28 @@ func parseTemplate(templateContents string) *template.Template { return m.compiler.baseCompilerProps() }, "getCflagsProperty": func(ctx android.ModuleContext, m *Module) []string { - cflags := m.compiler.baseCompilerProps().Cflags - return cflags.GetOrDefault(ctx, nil) + prop := m.compiler.baseCompilerProps().Cflags + return prop.GetOrDefault(ctx, nil) }, "getLinkerProperties": func(m *Module) BaseLinkerProperties { return m.linker.baseLinkerProps() }, + "getWholeStaticLibsProperty": func(ctx android.ModuleContext, m *Module) []string { + prop := m.linker.baseLinkerProps().Whole_static_libs + return prop.GetOrDefault(ctx, nil) + }, + "getStaticLibsProperty": func(ctx android.ModuleContext, m *Module) []string { + prop := m.linker.baseLinkerProps().Static_libs + return prop.GetOrDefault(ctx, nil) + }, + "getSharedLibsProperty": func(ctx android.ModuleContext, m *Module) []string { + prop := m.linker.baseLinkerProps().Shared_libs + return prop.GetOrDefault(ctx, nil) + }, + "getHeaderLibsProperty": func(ctx android.ModuleContext, m *Module) []string { + prop := m.linker.baseLinkerProps().Header_libs + return prop.GetOrDefault(ctx, nil) + }, "getExtraLibs": getExtraLibs, "getIncludeDirs": getIncludeDirs, "mapLibraries": func(ctx android.ModuleContext, m *Module, libs []string, mapping map[string]LibraryMappingProperty) []string { diff --git a/cc/compiler.go b/cc/compiler.go index 0e0b9a72d..396ec886b 100644 --- a/cc/compiler.go +++ b/cc/compiler.go @@ -798,13 +798,13 @@ type RustBindgenClangProperties struct { Local_include_dirs []string `android:"arch_variant,variant_prepend"` // list of static libraries that provide headers for this binding. - Static_libs []string `android:"arch_variant,variant_prepend"` + Static_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"` // list of shared libraries that provide headers for this binding. - Shared_libs []string `android:"arch_variant"` + Shared_libs proptools.Configurable[[]string] `android:"arch_variant"` // List of libraries which export include paths required for this module - Header_libs []string `android:"arch_variant,variant_prepend"` + Header_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"` // list of clang flags required to correctly interpret the headers. Cflags proptools.Configurable[[]string] `android:"arch_variant"` diff --git a/cc/library.go b/cc/library.go index de0070a15..60178484f 100644 --- a/cc/library.go +++ b/cc/library.go @@ -152,11 +152,11 @@ type StaticOrSharedProperties struct { Cflags proptools.Configurable[[]string] `android:"arch_variant"` - Enabled *bool `android:"arch_variant"` - Whole_static_libs []string `android:"arch_variant"` - Static_libs []string `android:"arch_variant"` - Shared_libs []string `android:"arch_variant"` - System_shared_libs []string `android:"arch_variant"` + Enabled *bool `android:"arch_variant"` + Whole_static_libs proptools.Configurable[[]string] `android:"arch_variant"` + Static_libs proptools.Configurable[[]string] `android:"arch_variant"` + Shared_libs proptools.Configurable[[]string] `android:"arch_variant"` + System_shared_libs []string `android:"arch_variant"` Export_shared_lib_headers []string `android:"arch_variant"` Export_static_lib_headers []string `android:"arch_variant"` @@ -837,9 +837,9 @@ func (library *libraryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps { if library.static() { deps.WholeStaticLibs = append(deps.WholeStaticLibs, - library.StaticProperties.Static.Whole_static_libs...) - deps.StaticLibs = append(deps.StaticLibs, library.StaticProperties.Static.Static_libs...) - deps.SharedLibs = append(deps.SharedLibs, library.StaticProperties.Static.Shared_libs...) + library.StaticProperties.Static.Whole_static_libs.GetOrDefault(ctx, nil)...) + deps.StaticLibs = append(deps.StaticLibs, library.StaticProperties.Static.Static_libs.GetOrDefault(ctx, nil)...) + deps.SharedLibs = append(deps.SharedLibs, library.StaticProperties.Static.Shared_libs.GetOrDefault(ctx, nil)...) deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, library.StaticProperties.Static.Export_shared_lib_headers...) deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.StaticProperties.Static.Export_static_lib_headers...) @@ -852,9 +852,9 @@ func (library *libraryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps { if library.baseLinker.Properties.crtPadSegment() { deps.CrtEnd = append(deps.CrtEnd, ctx.toolchain().CrtPadSegmentSharedLibrary()...) } - deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.SharedProperties.Shared.Whole_static_libs...) - deps.StaticLibs = append(deps.StaticLibs, library.SharedProperties.Shared.Static_libs...) - deps.SharedLibs = append(deps.SharedLibs, library.SharedProperties.Shared.Shared_libs...) + deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.SharedProperties.Shared.Whole_static_libs.GetOrDefault(ctx, nil)...) + deps.StaticLibs = append(deps.StaticLibs, library.SharedProperties.Shared.Static_libs.GetOrDefault(ctx, nil)...) + deps.SharedLibs = append(deps.SharedLibs, library.SharedProperties.Shared.Shared_libs.GetOrDefault(ctx, nil)...) deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, library.SharedProperties.Shared.Export_shared_lib_headers...) deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.SharedProperties.Shared.Export_static_lib_headers...) @@ -900,8 +900,8 @@ func (library *libraryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps { return deps } -func (library *libraryDecorator) linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps { - specifiedDeps = library.baseLinker.linkerSpecifiedDeps(specifiedDeps) +func (library *libraryDecorator) linkerSpecifiedDeps(ctx android.ConfigAndErrorContext, module *Module, specifiedDeps specifiedDeps) specifiedDeps { + specifiedDeps = library.baseLinker.linkerSpecifiedDeps(ctx, module, specifiedDeps) var properties StaticOrSharedProperties if library.static() { properties = library.StaticProperties.Static @@ -909,7 +909,8 @@ func (library *libraryDecorator) linkerSpecifiedDeps(specifiedDeps specifiedDeps properties = library.SharedProperties.Shared } - specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, properties.Shared_libs...) + eval := module.ConfigurableEvaluator(ctx) + specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, properties.Shared_libs.GetOrDefault(eval, nil)...) // Must distinguish nil and [] in system_shared_libs - ensure that [] in // either input list doesn't come out as nil. @@ -2079,12 +2080,12 @@ func reuseStaticLibrary(ctx android.BottomUpMutatorContext, shared *Module) { // include directories. if len(sharedCompiler.StaticProperties.Static.Cflags.GetOrDefault(ctx, nil)) == 0 && len(sharedCompiler.SharedProperties.Shared.Cflags.GetOrDefault(ctx, nil)) == 0 && - len(sharedCompiler.StaticProperties.Static.Whole_static_libs) == 0 && - len(sharedCompiler.SharedProperties.Shared.Whole_static_libs) == 0 && - len(sharedCompiler.StaticProperties.Static.Static_libs) == 0 && - len(sharedCompiler.SharedProperties.Shared.Static_libs) == 0 && - len(sharedCompiler.StaticProperties.Static.Shared_libs) == 0 && - len(sharedCompiler.SharedProperties.Shared.Shared_libs) == 0 && + len(sharedCompiler.StaticProperties.Static.Whole_static_libs.GetOrDefault(ctx, nil)) == 0 && + len(sharedCompiler.SharedProperties.Shared.Whole_static_libs.GetOrDefault(ctx, nil)) == 0 && + len(sharedCompiler.StaticProperties.Static.Static_libs.GetOrDefault(ctx, nil)) == 0 && + len(sharedCompiler.SharedProperties.Shared.Static_libs.GetOrDefault(ctx, nil)) == 0 && + len(sharedCompiler.StaticProperties.Static.Shared_libs.GetOrDefault(ctx, nil)) == 0 && + len(sharedCompiler.SharedProperties.Shared.Shared_libs.GetOrDefault(ctx, nil)) == 0 && // Compare System_shared_libs properties with nil because empty lists are // semantically significant for them. sharedCompiler.StaticProperties.Static.System_shared_libs == nil && diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go index e8a98274c..053c46069 100644 --- a/cc/library_sdk_member.go +++ b/cc/library_sdk_member.go @@ -543,7 +543,7 @@ func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberConte p.ExportedFlags = exportedInfo.Flags if ccModule.linker != nil { specifiedDeps := specifiedDeps{} - specifiedDeps = ccModule.linker.linkerSpecifiedDeps(specifiedDeps) + specifiedDeps = ccModule.linker.linkerSpecifiedDeps(ctx, ccModule, specifiedDeps) if lib := ccModule.library; lib != nil { if !lib.hasStubsVariants() { diff --git a/cc/linker.go b/cc/linker.go index d2974c204..00568177f 100644 --- a/cc/linker.go +++ b/cc/linker.go @@ -37,16 +37,16 @@ type BaseLinkerProperties struct { // in their entirety. For static library modules, all of the .o files from the intermediate // directory of the dependency will be linked into this modules .a file. For a shared library, // the dependency's .a file will be linked into this module using -Wl,--whole-archive. - Whole_static_libs []string `android:"arch_variant,variant_prepend"` + Whole_static_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"` // list of modules that should be statically linked into this module. - Static_libs []string `android:"arch_variant,variant_prepend"` + Static_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"` // list of modules that should be dynamically linked into this module. - Shared_libs []string `android:"arch_variant"` + Shared_libs proptools.Configurable[[]string] `android:"arch_variant"` // list of modules that should only provide headers for this module. - Header_libs []string `android:"arch_variant,variant_prepend"` + Header_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"` // list of module-specific flags that will be used for all link steps Ldflags []string `android:"arch_variant"` @@ -296,10 +296,10 @@ func (linker *baseLinker) baseLinkerProps() BaseLinkerProperties { } 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...) - deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Static_libs...) - deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Shared_libs...) + deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs.GetOrDefault(ctx, nil)...) + deps.HeaderLibs = append(deps.HeaderLibs, linker.Properties.Header_libs.GetOrDefault(ctx, nil)...) + deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Static_libs.GetOrDefault(ctx, nil)...) + deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Shared_libs.GetOrDefault(ctx, nil)...) deps.RuntimeLibs = append(deps.RuntimeLibs, linker.Properties.Runtime_libs...) deps.ReexportHeaderLibHeaders = append(deps.ReexportHeaderLibHeaders, linker.Properties.Export_header_lib_headers...) @@ -645,8 +645,9 @@ func (linker *baseLinker) link(ctx ModuleContext, panic(fmt.Errorf("baseLinker doesn't know how to link")) } -func (linker *baseLinker) linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps { - specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, linker.Properties.Shared_libs...) +func (linker *baseLinker) linkerSpecifiedDeps(ctx android.ConfigAndErrorContext, module *Module, specifiedDeps specifiedDeps) specifiedDeps { + eval := module.ConfigurableEvaluator(ctx) + specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, linker.Properties.Shared_libs.GetOrDefault(eval, nil)...) // Must distinguish nil and [] in system_shared_libs - ensure that [] in // either input list doesn't come out as nil. diff --git a/cc/object.go b/cc/object.go index 8b23295c7..a4f4c8408 100644 --- a/cc/object.go +++ b/cc/object.go @@ -19,6 +19,8 @@ import ( "strings" "android/soong/android" + + "github.com/google/blueprint/proptools" ) // @@ -50,13 +52,13 @@ type objectLinker struct { type ObjectLinkerProperties struct { // list of static library modules that should only provide headers for this module. - Static_libs []string `android:"arch_variant,variant_prepend"` + Static_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"` // list of shared library modules should only provide headers for this module. - Shared_libs []string `android:"arch_variant,variant_prepend"` + Shared_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"` // list of modules that should only provide headers for this module. - Header_libs []string `android:"arch_variant,variant_prepend"` + Header_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"` // list of default libraries that will provide headers for this module. If unset, generally // defaults to libc, libm, and libdl. Set to [] to prevent using headers from the defaults. @@ -116,9 +118,9 @@ func (object *objectLinker) linkerProps() []interface{} { func (*objectLinker) linkerInit(ctx BaseModuleContext) {} func (object *objectLinker) linkerDeps(ctx DepsContext, deps Deps) Deps { - deps.HeaderLibs = append(deps.HeaderLibs, object.Properties.Header_libs...) - deps.SharedLibs = append(deps.SharedLibs, object.Properties.Shared_libs...) - deps.StaticLibs = append(deps.StaticLibs, object.Properties.Static_libs...) + deps.HeaderLibs = append(deps.HeaderLibs, object.Properties.Header_libs.GetOrDefault(ctx, nil)...) + deps.SharedLibs = append(deps.SharedLibs, object.Properties.Shared_libs.GetOrDefault(ctx, nil)...) + deps.StaticLibs = append(deps.StaticLibs, object.Properties.Static_libs.GetOrDefault(ctx, nil)...) deps.ObjFiles = append(deps.ObjFiles, object.Properties.Objs...) deps.SystemSharedLibs = object.Properties.System_shared_libs @@ -201,8 +203,9 @@ func (object *objectLinker) link(ctx ModuleContext, return outputFile } -func (object *objectLinker) linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps { - specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, object.Properties.Shared_libs...) +func (object *objectLinker) linkerSpecifiedDeps(ctx android.ConfigAndErrorContext, module *Module, specifiedDeps specifiedDeps) specifiedDeps { + eval := module.ConfigurableEvaluator(ctx) + specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, object.Properties.Shared_libs.GetOrDefault(eval, nil)...) // Must distinguish nil and [] in system_shared_libs - ensure that [] in // either input list doesn't come out as nil. diff --git a/genrule/genrule.go b/genrule/genrule.go index 25579220d..919564399 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -147,6 +147,21 @@ type generatorProperties struct { // Enable restat to update the output only if the output is changed Write_if_changed *bool + + // When set to true, an additional $(build_number_file) label will be available + // to use in the cmd. This will be the location of a text file containing the + // build number. The dependency on this file will be "order-only", meaning that + // the genrule will not rerun when only this file changes, to avoid rerunning + // the genrule every build, because the build number changes every build. + // This also means that you should not attempt to consume the build number from + // the result of this genrule in another build rule. If you do, the build number + // in the second build rule will be stale when the second build rule rebuilds + // but this genrule does not. Only certain allowlisted modules are allowed to + // use this property, usages of the build number should be kept to the absolute + // minimum. Particularly no modules on the system image may include the build + // number. Prefer using libbuildversion via the use_version_lib property on + // cc modules. + Uses_order_only_build_number_file *bool } type Module struct { @@ -228,6 +243,15 @@ func toolDepsMutator(ctx android.BottomUpMutatorContext) { } } +// This allowlist should be kept to the bare minimum, it's +// intended for things that existed before the build number +// was tightly controlled. Prefer using libbuildversion +// via the use_version_lib property of cc modules. +var genrule_build_number_allowlist = map[string]bool{ + "build/soong/tests:gen": true, + "tools/tradefederation/core:tradefed_zip": true, +} + // generateCommonBuildActions contains build action generation logic // common to both the mixed build case and the legacy case of genrule processing. // To fully support genrule in mixed builds, the contents of this function should @@ -470,6 +494,11 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) { return strings.Join(proptools.ShellEscapeList(sandboxOuts), " "), nil case "genDir": return proptools.ShellEscape(cmd.PathForOutput(task.genDir)), nil + case "build_number_file": + if !proptools.Bool(g.properties.Uses_order_only_build_number_file) { + return reportError("to use the $(build_number_file) label, you must set uses_order_only_build_number_file: true") + } + return proptools.ShellEscape(cmd.PathForInput(ctx.Config().BuildNumberFile(ctx))), nil default: if strings.HasPrefix(name, "location ") { label := strings.TrimSpace(strings.TrimPrefix(name, "location ")) @@ -516,6 +545,12 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) { cmd.Implicits(task.in) cmd.ImplicitTools(tools) cmd.ImplicitPackagedTools(packagedTools) + if proptools.Bool(g.properties.Uses_order_only_build_number_file) { + if _, ok := genrule_build_number_allowlist[ctx.ModuleDir()+":"+ctx.ModuleName()]; !ok { + ctx.ModuleErrorf("Only allowlisted modules may use uses_order_only_build_number_file: true") + } + cmd.OrderOnly(ctx.Config().BuildNumberFile(ctx)) + } // Create the rule to run the genrule command inside sbox. rule.Build(name, desc) diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go index 444aedb90..9278f1574 100644 --- a/genrule/genrule_test.go +++ b/genrule/genrule_test.go @@ -19,6 +19,7 @@ import ( "os" "regexp" "strconv" + "strings" "testing" "android/soong/android" @@ -1192,6 +1193,68 @@ func TestGenruleWithGlobPaths(t *testing.T) { } } +func TestGenruleUsesOrderOnlyBuildNumberFile(t *testing.T) { + testCases := []struct { + name string + bp string + fs android.MockFS + expectedError string + expectedCommand string + }{ + { + name: "not allowed when not in allowlist", + fs: android.MockFS{ + "foo/Android.bp": []byte(` +genrule { + name: "gen", + uses_order_only_build_number_file: true, + cmd: "cp $(build_number_file) $(out)", + out: ["out.txt"], +} +`), + }, + expectedError: `Only allowlisted modules may use uses_order_only_build_number_file: true`, + }, + { + name: "normal", + fs: android.MockFS{ + "build/soong/tests/Android.bp": []byte(` +genrule { + name: "gen", + uses_order_only_build_number_file: true, + cmd: "cp $(build_number_file) $(out)", + out: ["out.txt"], +} +`), + }, + expectedCommand: `cp BUILD_NUMBER_FILE __SBOX_SANDBOX_DIR__/out/out.txt`, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + fixtures := android.GroupFixturePreparers( + prepareForGenRuleTest, + android.PrepareForTestWithVisibility, + android.FixtureMergeMockFs(tc.fs), + android.FixtureModifyConfigAndContext(func(config android.Config, ctx *android.TestContext) { + config.TestProductVariables.BuildNumberFile = proptools.StringPtr("build_number.txt") + }), + ) + if tc.expectedError != "" { + fixtures = fixtures.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(tc.expectedError)) + } + result := fixtures.RunTest(t) + + if tc.expectedError == "" { + tc.expectedCommand = strings.ReplaceAll(tc.expectedCommand, "BUILD_NUMBER_FILE", result.Config.SoongOutDir()+"/build_number.txt") + gen := result.Module("gen", "").(*Module) + android.AssertStringEquals(t, "raw commands", tc.expectedCommand, gen.rawCommands[0]) + } + }) + } +} + type testTool struct { android.ModuleBase outputFile android.Path diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go index 78ab771b9..2e408b767 100644 --- a/mk2rbc/mk2rbc.go +++ b/mk2rbc/mk2rbc.go @@ -72,6 +72,7 @@ var knownFunctions = map[string]interface { "add_soong_config_namespace": &simpleCallParser{name: baseName + ".soong_config_namespace", returnType: starlarkTypeVoid, addGlobals: true}, "add_soong_config_var_value": &simpleCallParser{name: baseName + ".soong_config_set", returnType: starlarkTypeVoid, addGlobals: true}, soongConfigAssign: &simpleCallParser{name: baseName + ".soong_config_set", returnType: starlarkTypeVoid, addGlobals: true}, + "soong_config_set_bool": &simpleCallParser{name: baseName + ".soong_config_set_bool", returnType: starlarkTypeVoid, addGlobals: true}, soongConfigAppend: &simpleCallParser{name: baseName + ".soong_config_append", returnType: starlarkTypeVoid, addGlobals: true}, "soong_config_get": &simpleCallParser{name: baseName + ".soong_config_get", returnType: starlarkTypeString, addGlobals: true}, "add-to-product-copy-files-if-exists": &simpleCallParser{name: baseName + ".copy_if_exists", returnType: starlarkTypeList}, diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go index 0c4d21375..c295c401a 100644 --- a/mk2rbc/mk2rbc_test.go +++ b/mk2rbc/mk2rbc_test.go @@ -853,6 +853,7 @@ $(info $(notdir foo/bar)) $(call add_soong_config_namespace,snsconfig) $(call add_soong_config_var_value,snsconfig,imagetype,odm_image) $(call soong_config_set, snsconfig, foo, foo_value) +$(call soong_config_set_bool, snsconfig, bar, true) $(call soong_config_append, snsconfig, bar, bar_value) PRODUCT_COPY_FILES := $(call copy-files,$(wildcard foo*.mk),etc) PRODUCT_COPY_FILES := $(call product-copy-files-by-pattern,from/%,to/%,a b c) @@ -880,6 +881,7 @@ def init(g, handle): rblf.soong_config_namespace(g, "snsconfig") rblf.soong_config_set(g, "snsconfig", "imagetype", "odm_image") rblf.soong_config_set(g, "snsconfig", "foo", "foo_value") + rblf.soong_config_set_bool(g, "snsconfig", "bar", "true") rblf.soong_config_append(g, "snsconfig", "bar", "bar_value") cfg["PRODUCT_COPY_FILES"] = rblf.copy_files(rblf.expand_wildcard("foo*.mk"), "etc") cfg["PRODUCT_COPY_FILES"] = rblf.product_copy_files_by_pattern("from/%", "to/%", "a b c") diff --git a/rust/bindgen.go b/rust/bindgen.go index a81024acd..31aa13725 100644 --- a/rust/bindgen.go +++ b/rust/bindgen.go @@ -393,8 +393,8 @@ func (b *bindgenDecorator) SourceProviderDeps(ctx DepsContext, deps Deps) Deps { 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...) + deps.SharedLibs = append(deps.SharedLibs, b.ClangProperties.Shared_libs.GetOrDefault(ctx, nil)...) + deps.StaticLibs = append(deps.StaticLibs, b.ClangProperties.Static_libs.GetOrDefault(ctx, nil)...) + deps.HeaderLibs = append(deps.HeaderLibs, b.ClangProperties.Header_libs.GetOrDefault(ctx, nil)...) return deps } diff --git a/sdk/update.go b/sdk/update.go index 198c8d4a8..a4b1967af 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -1989,6 +1989,14 @@ func (m *memberContext) IsTargetBuildBeforeTiramisu() bool { return m.builder.targetBuildRelease.EarlierThan(buildReleaseT) } +func (m *memberContext) Config() android.Config { + return m.sdkMemberContext.Config() +} + +func (m *memberContext) OtherModulePropertyErrorf(module android.Module, property string, fmt string, args ...interface{}) { + m.sdkMemberContext.OtherModulePropertyErrorf(module, property, fmt, args) +} + var _ android.SdkMemberContext = (*memberContext)(nil) func (s *sdk) createMemberSnapshot(ctx *memberContext, member *sdkMember, bpModule *bpModule) { diff --git a/ui/build/config.go b/ui/build/config.go index b8fcb6b5d..dfe0dfe96 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -1041,7 +1041,7 @@ func (c *configImpl) NamedGlobFile(name string) string { func (c *configImpl) UsedEnvFile(tag string) string { if v, ok := c.environ.Get("TARGET_PRODUCT"); ok { - return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+v+"."+tag) + return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+v+c.CoverageSuffix()+"."+tag) } return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+tag) } @@ -1149,6 +1149,13 @@ func (c *configImpl) TargetProductOrErr() (string, error) { return "", fmt.Errorf("TARGET_PRODUCT is not defined") } +func (c *configImpl) CoverageSuffix() string { + if v := c.environ.IsEnvTrue("EMMA_INSTRUMENT"); v { + return ".coverage" + } + return "" +} + func (c *configImpl) TargetDevice() string { return c.targetDevice } @@ -1520,7 +1527,7 @@ func (c *configImpl) SoongVarsFile() string { if err != nil { return filepath.Join(c.SoongOutDir(), "soong.variables") } else { - return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+".variables") + return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+c.CoverageSuffix()+".variables") } } @@ -1529,7 +1536,7 @@ func (c *configImpl) SoongExtraVarsFile() string { if err != nil { return filepath.Join(c.SoongOutDir(), "soong.extra.variables") } else { - return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+".extra.variables") + return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+c.CoverageSuffix()+".extra.variables") } } @@ -1538,7 +1545,7 @@ func (c *configImpl) SoongNinjaFile() string { if err != nil { return filepath.Join(c.SoongOutDir(), "build.ninja") } else { - return filepath.Join(c.SoongOutDir(), "build."+targetProduct+".ninja") + return filepath.Join(c.SoongOutDir(), "build."+targetProduct+c.CoverageSuffix()+".ninja") } } @@ -1550,11 +1557,11 @@ func (c *configImpl) CombinedNinjaFile() string { } func (c *configImpl) SoongAndroidMk() string { - return filepath.Join(c.SoongOutDir(), "Android-"+c.TargetProduct()+".mk") + return filepath.Join(c.SoongOutDir(), "Android-"+c.TargetProduct()+c.CoverageSuffix()+".mk") } func (c *configImpl) SoongMakeVarsMk() string { - return filepath.Join(c.SoongOutDir(), "make_vars-"+c.TargetProduct()+".mk") + return filepath.Join(c.SoongOutDir(), "make_vars-"+c.TargetProduct()+c.CoverageSuffix()+".mk") } func (c *configImpl) SoongBuildMetrics() string { diff --git a/ui/build/kati.go b/ui/build/kati.go index a0efd2c88..5743ff7a7 100644 --- a/ui/build/kati.go +++ b/ui/build/kati.go @@ -41,7 +41,7 @@ const katiPackageSuffix = "-package" // arguments. func genKatiSuffix(ctx Context, config Config) { // Construct the base suffix. - katiSuffix := "-" + config.TargetProduct() + katiSuffix := "-" + config.TargetProduct() + config.CoverageSuffix() // Append kati arguments to the suffix. if args := config.KatiArgs(); len(args) > 0 { |