diff options
70 files changed, 805 insertions, 160 deletions
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go index e22eec564..751a4cb83 100644 --- a/android/allowlists/allowlists.go +++ b/android/allowlists/allowlists.go @@ -223,6 +223,7 @@ var ( "frameworks/base/tools/streaming_proto": Bp2BuildDefaultTrueRecursively, "frameworks/hardware/interfaces/stats/aidl": Bp2BuildDefaultTrue, "frameworks/libs/modules-utils/build": Bp2BuildDefaultTrueRecursively, + "frameworks/libs/net/common/native": Bp2BuildDefaultTrueRecursively, "frameworks/native/libs/adbd_auth": Bp2BuildDefaultTrueRecursively, "frameworks/native/libs/arect": Bp2BuildDefaultTrueRecursively, "frameworks/native/libs/gui": Bp2BuildDefaultTrue, diff --git a/android/androidmk.go b/android/androidmk.go index aa411d116..62f82f247 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -42,7 +42,7 @@ func init() { } func RegisterAndroidMkBuildComponents(ctx RegistrationContext) { - ctx.RegisterSingletonType("androidmk", AndroidMkSingleton) + ctx.RegisterParallelSingletonType("androidmk", AndroidMkSingleton) } // Enable androidmk support. diff --git a/android/api_levels.go b/android/api_levels.go index fa919fda7..2391e6cc2 100644 --- a/android/api_levels.go +++ b/android/api_levels.go @@ -22,7 +22,7 @@ import ( ) func init() { - RegisterSingletonType("api_levels", ApiLevelsSingleton) + RegisterParallelSingletonType("api_levels", ApiLevelsSingleton) } const previewAPILevelBase = 9000 diff --git a/android/bazel.go b/android/bazel.go index 114b1f5c2..d32663483 100644 --- a/android/bazel.go +++ b/android/bazel.go @@ -46,6 +46,10 @@ const ( // that is not a platform incompatibility. Example: the module-type is not // enabled, or is not bp2build-converted. ModuleIncompatibility + + // Missing dependencies. We can't query Bazel for modules if it has missing dependencies, there + // will be failures. + ModuleMissingDeps ) // FileGroupAsLibrary describes a filegroup module that is converted to some library @@ -367,16 +371,26 @@ func GetBp2BuildAllowList() Bp2BuildConversionAllowlist { // As a side effect, calling this method will also log whether this module is // mixed build enabled for metrics reporting. func MixedBuildsEnabled(ctx BaseModuleContext) MixedBuildEnabledStatus { - module := ctx.Module() - apexInfo := ctx.Provider(ApexInfoProvider).(ApexInfo) - withinApex := !apexInfo.IsForPlatform() - platformIncompatible := isPlatformIncompatible(ctx.Os(), ctx.Arch().ArchType) if platformIncompatible { ctx.Config().LogMixedBuild(ctx, false) return TechnicalIncompatibility } + if ctx.Config().AllowMissingDependencies() { + missingDeps := ctx.getMissingDependencies() + // If there are missing dependencies, querying Bazel will fail. Soong instead fails at execution + // time, not loading/analysis. disable mixed builds and fall back to Soong to maintain that + // behavior. + if len(missingDeps) > 0 { + ctx.Config().LogMixedBuild(ctx, false) + return ModuleMissingDeps + } + } + + module := ctx.Module() + apexInfo := ctx.Provider(ApexInfoProvider).(ApexInfo) + withinApex := !apexInfo.IsForPlatform() mixedBuildEnabled := ctx.Config().IsMixedBuildsEnabled() && module.Enabled() && convertedToBazel(ctx, module) && diff --git a/android/bazel_handler.go b/android/bazel_handler.go index 10cf60a0a..35f880cf4 100644 --- a/android/bazel_handler.go +++ b/android/bazel_handler.go @@ -74,14 +74,12 @@ var ( } ) -func init() { - RegisterMixedBuildsMutator(InitRegistrationContext) +func registerMixedBuildsMutator(ctx RegisterMutatorsContext) { + ctx.BottomUp("mixed_builds_prep", mixedBuildsPrepareMutator).Parallel() } func RegisterMixedBuildsMutator(ctx RegistrationContext) { - ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) { - ctx.BottomUp("mixed_builds_prep", mixedBuildsPrepareMutator).Parallel() - }) + ctx.FinalDepsMutators(registerMixedBuildsMutator) } func mixedBuildsPrepareMutator(ctx BottomUpMutatorContext) { diff --git a/android/bazel_test.go b/android/bazel_test.go index 77e251575..13fd40849 100644 --- a/android/bazel_test.go +++ b/android/bazel_test.go @@ -436,3 +436,150 @@ func TestShouldKeepExistingBuildFileForDir(t *testing.T) { } } } + +type mixedBuildModule struct { + ModuleBase + BazelModuleBase + props struct { + Deps []string + Mixed_build_incompatible *bool + QueuedBazelCall bool `blueprint:"mutated"` + } +} + +type mixedBuildModuleInfo struct { + QueuedBazelCall bool +} + +var mixedBuildModuleProvider = blueprint.NewProvider(mixedBuildModuleInfo{}) + +func mixedBuildModuleFactory() Module { + m := &mixedBuildModule{} + m.AddProperties(&m.props) + InitAndroidArchModule(m, HostAndDeviceDefault, MultilibBoth) + InitBazelModule(m) + + return m +} + +func (m *mixedBuildModule) ConvertWithBp2build(ctx TopDownMutatorContext) { +} + +func (m *mixedBuildModule) DepsMutator(ctx BottomUpMutatorContext) { + ctx.AddDependency(ctx.Module(), installDepTag{}, m.props.Deps...) +} + +func (m *mixedBuildModule) GenerateAndroidBuildActions(ctx ModuleContext) { +} + +func (m *mixedBuildModule) IsMixedBuildSupported(ctx BaseModuleContext) bool { + return !proptools.Bool(m.props.Mixed_build_incompatible) +} + +func (m *mixedBuildModule) QueueBazelCall(ctx BaseModuleContext) { + m.props.QueuedBazelCall = true +} + +func (m *mixedBuildModule) ProcessBazelQueryResponse(ctx ModuleContext) { + ctx.SetProvider(mixedBuildModuleProvider, mixedBuildModuleInfo{ + QueuedBazelCall: m.props.QueuedBazelCall, + }) +} + +var prepareForMixedBuildTests = FixtureRegisterWithContext(func(ctx RegistrationContext) { + ctx.RegisterModuleType("deps", mixedBuildModuleFactory) + RegisterMixedBuildsMutator(ctx) +}) + +func TestMixedBuildsEnabledForType(t *testing.T) { + baseBp := ` + deps { + name: "foo", + deps: ["bar"], + target: { windows: { enabled: true } }, + %s + } +` + depBp := ` + deps { + name: "bar", + target: { + windows: { + enabled: true, + }, + }, + } +` + testCases := []struct { + desc string + variant *string + missingDeps bool + extraBpInfo string + mixedBuildsEnabled bool + }{ + { + desc: "mixed builds works", + mixedBuildsEnabled: true, + extraBpInfo: `bazel_module: { bp2build_available: true },`, + }, + { + desc: "missing deps", + missingDeps: true, + mixedBuildsEnabled: false, + extraBpInfo: `bazel_module: { bp2build_available: true },`, + }, + { + desc: "windows no mixed builds", + mixedBuildsEnabled: false, + variant: proptools.StringPtr("windows_x86"), + extraBpInfo: `bazel_module: { bp2build_available: true },`, + }, + { + desc: "mixed builds disabled by type", + mixedBuildsEnabled: false, + extraBpInfo: `mixed_build_incompatible: true, + bazel_module: { bp2build_available: true },`, + }, + { + desc: "mixed builds not bp2build available", + mixedBuildsEnabled: false, + extraBpInfo: `bazel_module: { bp2build_available: false },`, + }, + } + + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + handlers := GroupFixturePreparers( + prepareForMixedBuildTests, + PrepareForTestWithArchMutator, + FixtureModifyConfig(func(config Config) { + config.BazelContext = MockBazelContext{ + OutputBaseDir: "base", + } + config.Targets[Windows] = []Target{ + {Windows, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", true}, + {Windows, Arch{ArchType: X86}, NativeBridgeDisabled, "", "", true}, + } + }), + ) + bp := fmt.Sprintf(baseBp, tc.extraBpInfo) + if tc.missingDeps { + handlers = GroupFixturePreparers( + handlers, + PrepareForTestWithAllowMissingDependencies, + ) + } else { + bp += depBp + } + result := handlers.RunTestWithBp(t, bp) + + variant := proptools.StringDefault(tc.variant, "android_arm64_armv8-a") + + m := result.ModuleForTests("foo", variant) + mixedBuildModuleInfo := result.TestContext.ModuleProvider(m.Module(), mixedBuildModuleProvider).(mixedBuildModuleInfo) + if w, g := tc.mixedBuildsEnabled, mixedBuildModuleInfo.QueuedBazelCall; w != g { + t.Errorf("Expected mixed builds enabled %t, got mixed builds enabled %t", w, g) + } + }) + } +} diff --git a/android/buildinfo_prop.go b/android/buildinfo_prop.go index 46f648802..8e19ad5f4 100644 --- a/android/buildinfo_prop.go +++ b/android/buildinfo_prop.go @@ -23,7 +23,7 @@ import ( func init() { ctx := InitRegistrationContext - ctx.RegisterSingletonModuleType("buildinfo_prop", buildinfoPropFactory) + ctx.RegisterParallelSingletonModuleType("buildinfo_prop", buildinfoPropFactory) } type buildinfoPropProperties struct { diff --git a/android/config.go b/android/config.go index 01b8cfaa3..d0f2ea44c 100644 --- a/android/config.go +++ b/android/config.go @@ -302,6 +302,9 @@ type config struct { // modules that aren't mixed-built for at least one variant will cause a build // failure ensureAllowlistIntegrity bool + + // List of Api libraries that contribute to Api surfaces. + apiLibraries map[string]struct{} } type deviceConfig struct { @@ -622,6 +625,33 @@ func NewConfig(cmdArgs CmdArgs, availableEnv map[string]string) (Config, error) config.BazelContext, err = NewBazelContext(config) config.Bp2buildPackageConfig = GetBp2BuildAllowList() + // TODO(b/276958307): Replace the hardcoded list to a sdk_library local prop. + config.apiLibraries = map[string]struct{}{ + "android.net.ipsec.ike": {}, + "art.module.public.api": {}, + "conscrypt.module.public.api": {}, + "framework-adservices": {}, + "framework-appsearch": {}, + "framework-bluetooth": {}, + "framework-connectivity": {}, + "framework-connectivity-t": {}, + "framework-graphics": {}, + "framework-media": {}, + "framework-mediaprovider": {}, + "framework-ondevicepersonalization": {}, + "framework-permission": {}, + "framework-permission-s": {}, + "framework-scheduling": {}, + "framework-sdkextensions": {}, + "framework-statsd": {}, + "framework-sdksandbox": {}, + "framework-tethering": {}, + "framework-uwb": {}, + "framework-virtualization": {}, + "framework-wifi": {}, + "i18n.module.public.api": {}, + } + return Config{config}, err } @@ -1983,8 +2013,20 @@ func (c *config) BuildFromTextStub() bool { func (c *config) SetBuildFromTextStub(b bool) { c.buildFromTextStub = b } + func (c *config) AddForceEnabledModules(forceEnabled []string) { for _, forceEnabledModule := range forceEnabled { c.bazelForceEnabledModules[forceEnabledModule] = struct{}{} } } + +func (c *config) SetApiLibraries(libs []string) { + c.apiLibraries = make(map[string]struct{}) + for _, lib := range libs { + c.apiLibraries[lib] = struct{}{} + } +} + +func (c *config) GetApiLibraries() map[string]struct{} { + return c.apiLibraries +} diff --git a/android/gen_notice.go b/android/gen_notice.go index 091345b9f..1acc638e8 100644 --- a/android/gen_notice.go +++ b/android/gen_notice.go @@ -28,7 +28,7 @@ func init() { // Register the gen_notice module type. func RegisterGenNoticeBuildComponents(ctx RegistrationContext) { - ctx.RegisterSingletonType("gen_notice_build_rules", GenNoticeBuildRulesFactory) + ctx.RegisterParallelSingletonType("gen_notice_build_rules", GenNoticeBuildRulesFactory) ctx.RegisterModuleType("gen_notice", GenNoticeFactory) } diff --git a/android/metrics.go b/android/metrics.go index 3d41a1d6c..63c72cd97 100644 --- a/android/metrics.go +++ b/android/metrics.go @@ -42,7 +42,7 @@ func readSoongMetrics(config Config) (SoongMetrics, bool) { } func init() { - RegisterSingletonType("soong_metrics", soongMetricsSingletonFactory) + RegisterParallelSingletonType("soong_metrics", soongMetricsSingletonFactory) } func soongMetricsSingletonFactory() Singleton { return soongMetricsSingleton{} } diff --git a/android/module.go b/android/module.go index db602a0aa..604ba2401 100644 --- a/android/module.go +++ b/android/module.go @@ -354,6 +354,10 @@ type BaseModuleContext interface { AddMissingDependencies(missingDeps []string) + // getMissingDependencies returns the list of missing dependencies. + // Calling this function prevents adding new dependencies. + getMissingDependencies() []string + // AddUnconvertedBp2buildDep stores module name of a direct dependency that was not converted via bp2build AddUnconvertedBp2buildDep(dep string) @@ -939,7 +943,8 @@ type commonProperties struct { NamespaceExportedToMake bool `blueprint:"mutated"` - MissingDeps []string `blueprint:"mutated"` + MissingDeps []string `blueprint:"mutated"` + CheckedMissingDeps bool `blueprint:"mutated"` // Name and variant strings stored by mutators to enable Module.String() DebugName string `blueprint:"mutated"` @@ -2862,6 +2867,20 @@ func (b *baseModuleContext) AddMissingDependencies(deps []string) { } } +func (b *baseModuleContext) checkedMissingDeps() bool { + return b.Module().base().commonProperties.CheckedMissingDeps +} + +func (b *baseModuleContext) getMissingDependencies() []string { + checked := &b.Module().base().commonProperties.CheckedMissingDeps + *checked = true + var missingDeps []string + missingDeps = append(missingDeps, b.Module().base().commonProperties.MissingDeps...) + missingDeps = append(missingDeps, b.bp.EarlyGetMissingDependencies()...) + missingDeps = FirstUniqueStrings(missingDeps) + return missingDeps +} + type AllowDisabledModuleDependency interface { blueprint.DependencyTag AllowDisabledModuleDependency(target Module) bool @@ -3724,7 +3743,7 @@ func (m *moduleContext) TargetRequiredModuleNames() []string { } func init() { - RegisterSingletonType("buildtarget", BuildTargetSingleton) + RegisterParallelSingletonType("buildtarget", BuildTargetSingleton) } func BuildTargetSingleton() Singleton { diff --git a/android/mutator.go b/android/mutator.go index 0a091eb6f..41853154f 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -67,6 +67,8 @@ func registerMutatorsForBazelConversion(ctx *Context, bp2buildMutators []Registe // collateGloballyRegisteredMutators constructs the list of mutators that have been registered // with the InitRegistrationContext and will be used at runtime. func collateGloballyRegisteredMutators() sortableComponents { + // ensure mixed builds mutator is the last mutator + finalDeps = append(finalDeps, registerMixedBuildsMutator) return collateRegisteredMutators(preArch, preDeps, postDeps, finalDeps) } @@ -885,10 +887,16 @@ func (b *bottomUpMutatorContext) Rename(name string) { } func (b *bottomUpMutatorContext) AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) []blueprint.Module { + if b.baseModuleContext.checkedMissingDeps() { + panic("Adding deps not allowed after checking for missing deps") + } return b.bp.AddDependency(module, tag, name...) } func (b *bottomUpMutatorContext) AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string) { + if b.baseModuleContext.checkedMissingDeps() { + panic("Adding deps not allowed after checking for missing deps") + } b.bp.AddReverseDependency(module, tag, name) } @@ -938,11 +946,17 @@ func (b *bottomUpMutatorContext) SetDefaultDependencyVariation(variation *string func (b *bottomUpMutatorContext) AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag, names ...string) []blueprint.Module { + if b.baseModuleContext.checkedMissingDeps() { + panic("Adding deps not allowed after checking for missing deps") + } return b.bp.AddVariationDependencies(variations, tag, names...) } func (b *bottomUpMutatorContext) AddFarVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag, names ...string) []blueprint.Module { + if b.baseModuleContext.checkedMissingDeps() { + panic("Adding deps not allowed after checking for missing deps") + } return b.bp.AddFarVariationDependencies(variations, tag, names...) } @@ -952,10 +966,16 @@ func (b *bottomUpMutatorContext) AddInterVariantDependency(tag blueprint.Depende } func (b *bottomUpMutatorContext) ReplaceDependencies(name string) { + if b.baseModuleContext.checkedMissingDeps() { + panic("Adding deps not allowed after checking for missing deps") + } b.bp.ReplaceDependencies(name) } func (b *bottomUpMutatorContext) ReplaceDependenciesIf(name string, predicate blueprint.ReplaceDependencyPredicate) { + if b.baseModuleContext.checkedMissingDeps() { + panic("Adding deps not allowed after checking for missing deps") + } b.bp.ReplaceDependenciesIf(name, predicate) } diff --git a/android/register.go b/android/register.go index 1a3db9d90..64b0207e7 100644 --- a/android/register.go +++ b/android/register.go @@ -65,16 +65,19 @@ type singleton struct { // True if this should be registered as a pre-singleton, false otherwise. pre bool + // True if this should be registered as a parallel singleton. + parallel bool + name string factory SingletonFactory } -func newSingleton(name string, factory SingletonFactory) singleton { - return singleton{false, name, factory} +func newSingleton(name string, factory SingletonFactory, parallel bool) singleton { + return singleton{pre: false, parallel: parallel, name: name, factory: factory} } func newPreSingleton(name string, factory SingletonFactory) singleton { - return singleton{true, name, factory} + return singleton{pre: true, parallel: false, name: name, factory: factory} } func (s singleton) componentName() string { @@ -86,7 +89,7 @@ func (s singleton) register(ctx *Context) { if s.pre { ctx.RegisterPreSingletonType(s.name, adaptor) } else { - ctx.RegisterSingletonType(s.name, adaptor) + ctx.RegisterSingletonType(s.name, adaptor, s.parallel) } } @@ -145,8 +148,16 @@ func RegisterModuleTypeForDocs(name string, factory reflect.Value) { moduleTypeByFactory[factory] = name } +func registerSingletonType(name string, factory SingletonFactory, parallel bool) { + singletons = append(singletons, newSingleton(name, factory, parallel)) +} + func RegisterSingletonType(name string, factory SingletonFactory) { - singletons = append(singletons, newSingleton(name, factory)) + registerSingletonType(name, factory, false) +} + +func RegisterParallelSingletonType(name string, factory SingletonFactory) { + registerSingletonType(name, factory, true) } func RegisterPreSingletonType(name string, factory SingletonFactory) { @@ -220,17 +231,17 @@ func (ctx *Context) registerSingletonMakeVarsProvider(makevars SingletonMakeVars func collateGloballyRegisteredSingletons() sortableComponents { allSingletons := append(sortableComponents(nil), singletons...) allSingletons = append(allSingletons, - singleton{false, "bazeldeps", BazelSingleton}, + singleton{pre: false, parallel: true, name: "bazeldeps", factory: BazelSingleton}, // Register phony just before makevars so it can write out its phony rules as Make rules - singleton{false, "phony", phonySingletonFactory}, + singleton{pre: false, parallel: false, name: "phony", factory: phonySingletonFactory}, // Register makevars after other singletons so they can export values through makevars - singleton{false, "makevars", makeVarsSingletonFunc}, + singleton{pre: false, parallel: false, name: "makevars", factory: makeVarsSingletonFunc}, // Register env and ninjadeps last so that they can track all used environment variables and // Ninja file dependencies stored in the config. - singleton{false, "ninjadeps", ninjaDepsSingletonFactory}, + singleton{pre: false, parallel: false, name: "ninjadeps", factory: ninjaDepsSingletonFactory}, ) return allSingletons @@ -259,7 +270,9 @@ func ModuleTypeByFactory() map[reflect.Value]string { type RegistrationContext interface { RegisterModuleType(name string, factory ModuleFactory) RegisterSingletonModuleType(name string, factory SingletonModuleFactory) + RegisterParallelSingletonModuleType(name string, factory SingletonModuleFactory) RegisterPreSingletonType(name string, factory SingletonFactory) + RegisterParallelSingletonType(name string, factory SingletonFactory) RegisterSingletonType(name string, factory SingletonFactory) PreArchMutators(f RegisterMutatorFunc) @@ -315,8 +328,15 @@ func (ctx *initRegistrationContext) RegisterModuleType(name string, factory Modu } func (ctx *initRegistrationContext) RegisterSingletonModuleType(name string, factory SingletonModuleFactory) { + ctx.registerSingletonModuleType(name, factory, false) +} +func (ctx *initRegistrationContext) RegisterParallelSingletonModuleType(name string, factory SingletonModuleFactory) { + ctx.registerSingletonModuleType(name, factory, true) +} + +func (ctx *initRegistrationContext) registerSingletonModuleType(name string, factory SingletonModuleFactory, parallel bool) { s, m := SingletonModuleFactoryAdaptor(name, factory) - ctx.RegisterSingletonType(name, s) + ctx.registerSingletonType(name, s, parallel) ctx.RegisterModuleType(name, m) // Overwrite moduleTypesForDocs with the original factory instead of the lambda returned by // SingletonModuleFactoryAdaptor so that docs can find the module type documentation on the @@ -324,12 +344,20 @@ func (ctx *initRegistrationContext) RegisterSingletonModuleType(name string, fac RegisterModuleTypeForDocs(name, reflect.ValueOf(factory)) } -func (ctx *initRegistrationContext) RegisterSingletonType(name string, factory SingletonFactory) { +func (ctx *initRegistrationContext) registerSingletonType(name string, factory SingletonFactory, parallel bool) { if _, present := ctx.singletonTypes[name]; present { panic(fmt.Sprintf("singleton type %q is already registered", name)) } ctx.singletonTypes[name] = factory - RegisterSingletonType(name, factory) + registerSingletonType(name, factory, parallel) +} + +func (ctx *initRegistrationContext) RegisterSingletonType(name string, factory SingletonFactory) { + ctx.registerSingletonType(name, factory, false) +} + +func (ctx *initRegistrationContext) RegisterParallelSingletonType(name string, factory SingletonFactory) { + ctx.registerSingletonType(name, factory, true) } func (ctx *initRegistrationContext) RegisterPreSingletonType(name string, factory SingletonFactory) { diff --git a/android/test_suites.go b/android/test_suites.go index b570b2383..b48d71af6 100644 --- a/android/test_suites.go +++ b/android/test_suites.go @@ -15,7 +15,7 @@ package android func init() { - RegisterSingletonType("testsuites", testSuiteFilesFactory) + RegisterParallelSingletonType("testsuites", testSuiteFilesFactory) } func testSuiteFilesFactory() Singleton { diff --git a/android/testing.go b/android/testing.go index 2a9c6584e..5ad7ad07f 100644 --- a/android/testing.go +++ b/android/testing.go @@ -495,8 +495,18 @@ func (ctx *TestContext) RegisterSingletonModuleType(name string, factory Singlet ctx.RegisterModuleType(name, m) } +func (ctx *TestContext) RegisterParallelSingletonModuleType(name string, factory SingletonModuleFactory) { + s, m := SingletonModuleFactoryAdaptor(name, factory) + ctx.RegisterParallelSingletonType(name, s) + ctx.RegisterModuleType(name, m) +} + func (ctx *TestContext) RegisterSingletonType(name string, factory SingletonFactory) { - ctx.singletons = append(ctx.singletons, newSingleton(name, factory)) + ctx.singletons = append(ctx.singletons, newSingleton(name, factory, false)) +} + +func (ctx *TestContext) RegisterParallelSingletonType(name string, factory SingletonFactory) { + ctx.singletons = append(ctx.singletons, newSingleton(name, factory, true)) } func (ctx *TestContext) RegisterPreSingletonType(name string, factory SingletonFactory) { diff --git a/android_sdk/sdk_repo_host.go b/android_sdk/sdk_repo_host.go index 61058df09..9623a8bc4 100644 --- a/android_sdk/sdk_repo_host.go +++ b/android_sdk/sdk_repo_host.go @@ -242,7 +242,7 @@ func (s *sdkRepoHost) AndroidMk() android.AndroidMkData { fmt.Fprintln(w, ".PHONY:", name, "sdk_repo", "sdk-repo-"+name) fmt.Fprintln(w, "sdk_repo", "sdk-repo-"+name+":", strings.Join(s.FilesToInstall().Strings(), " ")) - fmt.Fprintf(w, "$(call dist-for-goals,sdk_repo sdk-repo-%s,%s:%s-$(FILE_NAME_TAG).zip)\n\n", s.BaseModuleName(), s.outputFile.String(), s.outputBaseName) + fmt.Fprintf(w, "$(call dist-for-goals,sdk_repo sdk-repo-%s,%s:%s-FILE_NAME_TAG_PLACEHOLDER.zip)\n\n", s.BaseModuleName(), s.outputFile.String(), s.outputBaseName) }, } } diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go index ebc35cf5c..a63344fc1 100644 --- a/apex/apex_singleton.go +++ b/apex/apex_singleton.go @@ -27,7 +27,7 @@ func init() { } func registerApexDepsInfoComponents(ctx android.RegistrationContext) { - ctx.RegisterSingletonType("apex_depsinfo_singleton", apexDepsInfoSingletonFactory) + ctx.RegisterParallelSingletonType("apex_depsinfo_singleton", apexDepsInfoSingletonFactory) } type apexDepsInfoSingleton struct { diff --git a/apex/key.go b/apex/key.go index 0a7e80f8f..3010d76be 100644 --- a/apex/key.go +++ b/apex/key.go @@ -33,7 +33,7 @@ func init() { func registerApexKeyBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("apex_key", ApexKeyFactory) - ctx.RegisterSingletonType("apex_keys_text", apexKeysTextFactory) + ctx.RegisterParallelSingletonType("apex_keys_text", apexKeysTextFactory) } type apexKey struct { diff --git a/bloaty/bloaty.go b/bloaty/bloaty.go index 50f241f44..3cff60fe6 100644 --- a/bloaty/bloaty.go +++ b/bloaty/bloaty.go @@ -51,7 +51,7 @@ func init() { pctx.VariableConfigMethod("hostPrebuiltTag", android.Config.PrebuiltOS) pctx.SourcePathVariable("bloaty", "prebuilts/build-tools/${hostPrebuiltTag}/bin/bloaty") pctx.HostBinToolVariable("bloatyMerger", "bloaty_merger") - android.RegisterSingletonType("file_metrics", fileSizesSingleton) + android.RegisterParallelSingletonType("file_metrics", fileSizesSingleton) fileSizeMeasurerKey = blueprint.NewProvider(measuredFiles{}) } diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go index 6ec37031b..8a83cc0d5 100644 --- a/bp2build/cc_binary_conversion_test.go +++ b/bp2build/cc_binary_conversion_test.go @@ -222,6 +222,7 @@ func TestCcBinaryVersionScriptAndDynamicList(t *testing.T) { "-Wl,--version-script,$(location vs)", "-Wl,--dynamic-list,$(location dynamic.list)", ]`, + "features": `["android_cfi_exports_map"]`, }, }, }, @@ -249,6 +250,7 @@ func TestCcBinaryLdflagsSplitBySpaceExceptSoongAdded(t *testing.T) { "version_script", "dynamic.list", ]`, + "features": `["android_cfi_exports_map"]`, "linkopts": `[ "--nospace_flag", "-z", diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go index 0e8705b54..3dd937319 100644 --- a/bp2build/cc_library_conversion_test.go +++ b/bp2build/cc_library_conversion_test.go @@ -900,7 +900,8 @@ cc_library { "-Wl,--version-script,$(location v.map)", "-Wl,--dynamic-list,$(location dynamic.list)", ]`, - "srcs": `["a.cpp"]`, + "srcs": `["a.cpp"]`, + "features": `["android_cfi_exports_map"]`, }), }, ) @@ -958,6 +959,11 @@ cc_library { "//conditions:default": [], })`, "srcs": `["a.cpp"]`, + "features": `select({ + "//build/bazel/platforms/arch:arm": ["android_cfi_exports_map"], + "//build/bazel/platforms/arch:arm64": ["android_cfi_exports_map"], + "//conditions:default": [], + })`, }), }, ) @@ -985,12 +991,15 @@ cc_library { } `, ExpectedBazelTargets: []string{ - MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}), + MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ + "features": `["android_cfi_exports_map"]`, + }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ "additional_linker_inputs": `[ "version_script", "dynamic.list", ]`, + "features": `["android_cfi_exports_map"]`, "linkopts": `[ "--nospace_flag", "-z", diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go index 2ee9c99f9..6c9f9a18f 100644 --- a/bp2build/cc_library_shared_conversion_test.go +++ b/bp2build/cc_library_shared_conversion_test.go @@ -362,6 +362,7 @@ cc_library_shared { "-Wl,--version-script,$(location version_script)", "-Wl,--dynamic-list,$(location dynamic.list)", ]`, + "features": `["android_cfi_exports_map"]`, }), }, }) @@ -398,6 +399,7 @@ cc_library_shared { "-Wl,--version-script,$(location version_script)", "-Wl,--dynamic-list,$(location dynamic.list)", ]`, + "features": `["android_cfi_exports_map"]`, }), }, }) @@ -913,6 +915,7 @@ func TestCCLibraryFlagSpaceSplitting(t *testing.T) { "header.h", ]`, "linkopts": `["-Wl,--version-script,$(location version_script)"]`, + "features": `["android_cfi_exports_map"]`, }), }, }) diff --git a/cc/bp2build.go b/cc/bp2build.go index fa98df4cd..259ba397a 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -1257,6 +1257,7 @@ func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversion label := android.BazelLabelForModuleSrcSingle(ctx, *props.Version_script) additionalLinkerInputs.Add(&label) linkerFlags = append(linkerFlags, fmt.Sprintf("-Wl,--version-script,$(location %s)", label.Label)) + axisFeatures = append(axisFeatures, "android_cfi_exports_map") } if props.Dynamic_list != nil { @@ -83,7 +83,7 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) { ctx.TopDown("sabi_deps", sabiDepsMutator) }) - ctx.RegisterSingletonType("kythe_extract_all", kytheExtractAllFactory) + ctx.RegisterParallelSingletonType("kythe_extract_all", kytheExtractAllFactory) } // Deps is a struct containing module names of dependencies, separated by the kind of dependency. diff --git a/cc/ccdeps.go b/cc/ccdeps.go index 75e1faf0b..d30abbab7 100644 --- a/cc/ccdeps.go +++ b/cc/ccdeps.go @@ -30,7 +30,7 @@ import ( // The info file is generated in $OUT/module_bp_cc_depend.json. func init() { - android.RegisterSingletonType("ccdeps_generator", ccDepsGeneratorSingleton) + android.RegisterParallelSingletonType("ccdeps_generator", ccDepsGeneratorSingleton) } func ccDepsGeneratorSingleton() android.Singleton { diff --git a/cc/cmakelists.go b/cc/cmakelists.go index ad130baaa..0f3f02da5 100644 --- a/cc/cmakelists.go +++ b/cc/cmakelists.go @@ -29,7 +29,7 @@ import ( // structure (see variable CLionOutputProjectsDirectory for root). func init() { - android.RegisterSingletonType("cmakelists_generator", cMakeListsGeneratorSingleton) + android.RegisterParallelSingletonType("cmakelists_generator", cMakeListsGeneratorSingleton) } func cMakeListsGeneratorSingleton() android.Singleton { diff --git a/cc/compdb.go b/cc/compdb.go index ea124438e..617be1a19 100644 --- a/cc/compdb.go +++ b/cc/compdb.go @@ -32,7 +32,7 @@ import ( // make SOONG_GEN_COMPDB=1 nothing to get all targets. func init() { - android.RegisterSingletonType("compdb_generator", compDBGeneratorSingleton) + android.RegisterParallelSingletonType("compdb_generator", compDBGeneratorSingleton) } func compDBGeneratorSingleton() android.Singleton { diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go index 6a10e1474..a0ef57595 100644 --- a/cc/config/toolchain.go +++ b/cc/config/toolchain.go @@ -20,6 +20,12 @@ import ( "android/soong/android" ) +func init() { + exportedVars.ExportStringListStaticVariable("DarwinAvailableLibraries", darwinAvailableLibraries) + exportedVars.ExportStringListStaticVariable("LinuxAvailableLibraries", linuxAvailableLibraries) + exportedVars.ExportStringListStaticVariable("WindowsAvailableLibraries", windowsAvailableLibraries) +} + type toolchainFactory func(arch android.Arch) Toolchain var toolchainFactories = make(map[android.OsType]map[android.ArchType]toolchainFactory) diff --git a/cc/fuzz.go b/cc/fuzz.go index dfefc11f2..c897501e8 100644 --- a/cc/fuzz.go +++ b/cc/fuzz.go @@ -28,7 +28,7 @@ import ( func init() { android.RegisterModuleType("cc_fuzz", LibFuzzFactory) - android.RegisterSingletonType("cc_fuzz_packaging", fuzzPackagingFactory) + android.RegisterParallelSingletonType("cc_fuzz_packaging", fuzzPackagingFactory) } type FuzzProperties struct { @@ -398,7 +398,9 @@ func (s *ccRustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) } hostOrTargetString := "target" - if ccModule.Host() { + if ccModule.Target().HostCross { + hostOrTargetString = "host_cross" + } else if ccModule.Host() { hostOrTargetString = "host" } @@ -91,11 +91,6 @@ func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags { return flags } - // TODO(b/254713216): LTO doesn't work on riscv64 yet. - if ctx.Arch().ArchType == android.Riscv64 { - return flags - } - if lto.LTO(ctx) { var ltoCFlag string var ltoLdFlag string diff --git a/cc/ndk_abi.go b/cc/ndk_abi.go index 3456c32bb..86166dcbb 100644 --- a/cc/ndk_abi.go +++ b/cc/ndk_abi.go @@ -19,8 +19,8 @@ import ( ) func init() { - android.RegisterSingletonType("ndk_abi_dump", NdkAbiDumpSingleton) - android.RegisterSingletonType("ndk_abi_diff", NdkAbiDiffSingleton) + android.RegisterParallelSingletonType("ndk_abi_dump", NdkAbiDumpSingleton) + android.RegisterParallelSingletonType("ndk_abi_diff", NdkAbiDiffSingleton) } func getNdkAbiDumpInstallBase(ctx android.PathContext) android.OutputPath { diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go index dffc6c614..0cf21b65a 100644 --- a/cc/ndk_sysroot.go +++ b/cc/ndk_sysroot.go @@ -66,7 +66,7 @@ func RegisterNdkModuleTypes(ctx android.RegistrationContext) { ctx.RegisterModuleType("ndk_library", NdkLibraryFactory) ctx.RegisterModuleType("versioned_ndk_headers", versionedNdkHeadersFactory) ctx.RegisterModuleType("preprocessed_ndk_headers", preprocessedNdkHeadersFactory) - ctx.RegisterSingletonType("ndk", NdkSingleton) + ctx.RegisterParallelSingletonType("ndk", NdkSingleton) } func getNdkInstallBase(ctx android.PathContext) android.InstallPath { diff --git a/cc/sanitize.go b/cc/sanitize.go index 7fddc1b83..6e732b617 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -665,6 +665,21 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { s.Diag.Cfi = nil } + // TODO(b/280478629): runtimes don't exist for musl arm64 yet. + if ctx.toolchain().Musl() && ctx.Arch().ArchType == android.Arm64 { + s.Address = nil + s.Hwaddress = nil + s.Thread = nil + s.Scudo = nil + s.Fuzzer = nil + s.Cfi = nil + s.Diag.Cfi = nil + s.Misc_undefined = nil + s.Undefined = nil + s.All_undefined = nil + s.Integer_overflow = nil + } + // Also disable CFI for VNDK variants of components if ctx.isVndk() && ctx.useVndk() { s.Cfi = nil diff --git a/cc/stub_library.go b/cc/stub_library.go index f324dcc9b..3a6d0aeaa 100644 --- a/cc/stub_library.go +++ b/cc/stub_library.go @@ -23,7 +23,7 @@ import ( func init() { // Use singleton type to gather all generated soong modules. - android.RegisterSingletonType("stublibraries", stubLibrariesSingleton) + android.RegisterParallelSingletonType("stublibraries", stubLibrariesSingleton) } type stubLibraries struct { diff --git a/cc/tidy.go b/cc/tidy.go index bbcaece24..7b123cb57 100644 --- a/cc/tidy.go +++ b/cc/tidy.go @@ -201,7 +201,7 @@ func (tidy *tidyFeature) flags(ctx ModuleContext, flags Flags) Flags { } func init() { - android.RegisterSingletonType("tidy_phony_targets", TidyPhonySingleton) + android.RegisterParallelSingletonType("tidy_phony_targets", TidyPhonySingleton) } // This TidyPhonySingleton generates both tidy-* and obj-* phony targets for C/C++ files. diff --git a/cc/vndk.go b/cc/vndk.go index 9b70004c5..7a2286eb1 100644 --- a/cc/vndk.go +++ b/cc/vndk.go @@ -417,16 +417,16 @@ func VndkMutator(mctx android.BottomUpMutatorContext) { func init() { RegisterVndkLibraryTxtTypes(android.InitRegistrationContext) - android.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton) + android.RegisterParallelSingletonType("vndk-snapshot", VndkSnapshotSingleton) } func RegisterVndkLibraryTxtTypes(ctx android.RegistrationContext) { - ctx.RegisterSingletonModuleType("llndk_libraries_txt", llndkLibrariesTxtFactory) - ctx.RegisterSingletonModuleType("vndksp_libraries_txt", vndkSPLibrariesTxtFactory) - ctx.RegisterSingletonModuleType("vndkcore_libraries_txt", vndkCoreLibrariesTxtFactory) - ctx.RegisterSingletonModuleType("vndkprivate_libraries_txt", vndkPrivateLibrariesTxtFactory) - ctx.RegisterSingletonModuleType("vndkproduct_libraries_txt", vndkProductLibrariesTxtFactory) - ctx.RegisterSingletonModuleType("vndkcorevariant_libraries_txt", vndkUsingCoreVariantLibrariesTxtFactory) + ctx.RegisterParallelSingletonModuleType("llndk_libraries_txt", llndkLibrariesTxtFactory) + ctx.RegisterParallelSingletonModuleType("vndksp_libraries_txt", vndkSPLibrariesTxtFactory) + ctx.RegisterParallelSingletonModuleType("vndkcore_libraries_txt", vndkCoreLibrariesTxtFactory) + ctx.RegisterParallelSingletonModuleType("vndkprivate_libraries_txt", vndkPrivateLibrariesTxtFactory) + ctx.RegisterParallelSingletonModuleType("vndkproduct_libraries_txt", vndkProductLibrariesTxtFactory) + ctx.RegisterParallelSingletonModuleType("vndkcorevariant_libraries_txt", vndkUsingCoreVariantLibrariesTxtFactory) } type vndkLibrariesTxt struct { diff --git a/dexpreopt/config.go b/dexpreopt/config.go index 0cc3bd63b..e61ebe624 100644 --- a/dexpreopt/config.go +++ b/dexpreopt/config.go @@ -197,7 +197,7 @@ var pctx = android.NewPackageContext("android/soong/dexpreopt") func init() { pctx.Import("android/soong/android") - android.RegisterSingletonType("dexpreopt-soong-config", func() android.Singleton { + android.RegisterParallelSingletonType("dexpreopt-soong-config", func() android.Singleton { return &globalSoongConfigSingleton{} }) } diff --git a/java/app.go b/java/app.go index e09509299..366005ce3 100755 --- a/java/app.go +++ b/java/app.go @@ -977,6 +977,10 @@ func (a *AndroidApp) DepIsInSameApex(ctx android.BaseModuleContext, dep android. // For OutputFileProducer interface func (a *AndroidApp) OutputFiles(tag string) (android.Paths, error) { switch tag { + // In some instances, it can be useful to reference the aapt-generated flags from another + // target, e.g., system server implements services declared in the framework-res manifest. + case ".aapt.proguardOptionsFile": + return []android.Path{a.proguardOptionsFile}, nil case ".aapt.srcjar": return []android.Path{a.aaptSrcJar}, nil case ".export-package.apk": diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go index 2541f14ff..9bdef749b 100644 --- a/java/bootclasspath_fragment_test.go +++ b/java/bootclasspath_fragment_test.go @@ -432,3 +432,39 @@ func TestBootclasspathFragment_Test(t *testing.T) { fragment = result.Module("a_test_fragment", "android_common").(*BootclasspathFragmentModule) android.AssertBoolEquals(t, "is a test fragment by type", true, fragment.isTestFragment()) } + +func TestBootclassFragment_LinkTextStub(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForJavaTest, + prepareForTestWithBootclasspathFragment, + PrepareForTestWithJavaSdkLibraryFiles, + FixtureWithLastReleaseApis("mysdklibrary"), + android.FixtureModifyConfig(func(config android.Config) { + config.SetBuildFromTextStub(true) + }), + ).RunTestWithBp(t, ` + bootclasspath_fragment { + name: "myfragment", + contents: ["mysdklibrary"], + hidden_api: {split_packages: ["*"]}, + additional_stubs: [ + "android-non-updatable", + ], + } + java_sdk_library { + name: "mysdklibrary", + srcs: ["a.java"], + shared_library: false, + public: {enabled: true}, + system: {enabled: true}, + } + `) + + fragment := result.ModuleForTests("myfragment", "android_common") + ruleCommand := fragment.Rule("modularHiddenAPIStubFlagsFile").RuleParams.Command + android.AssertStringDoesContain(t, "Command expected to contain library as dependency stub dex", + ruleCommand, "--dependency-stub-dex=out/soong/.intermediates/default/java/android-non-updatable.stubs.module_lib.from-text/android_common/dex/android-non-updatable.stubs.module_lib.from-text.jar") + android.AssertStringDoesNotContain(t, + "Command not expected to contain multiple api_library as dependency stub dex", ruleCommand, + "--dependency-stub-dex=out/soong/.intermediates/default/java/android-non-updatable.stubs.from-text/android_common/dex/android-non-updatable.stubs.from-text.jar") +} diff --git a/java/core-libraries/TxtStubLibraries.bp b/java/core-libraries/TxtStubLibraries.bp index 813187e54..0cf0f360b 100644 --- a/java/core-libraries/TxtStubLibraries.bp +++ b/java/core-libraries/TxtStubLibraries.bp @@ -22,8 +22,6 @@ java_system_modules { libs: [ "core-current-stubs-for-system-modules-no-annotations.from-text", ], - // TODO: Enable after stub generation from .txt file is available - enabled: false, } java_library { @@ -36,8 +34,6 @@ java_library { "core.current.stubs.from-text", "core-lambda-stubs.from-text", ], - // TODO: Enable after stub generation from .txt file is available - enabled: false, } // Same as core-module-lib-stubs-system-modules, but the stubs are generated from .txt files @@ -47,8 +43,6 @@ java_system_modules { libs: [ "core-module-lib-stubs-for-system-modules-no-annotations.from-text", ], - // TODO: Enable after stub generation from .txt file is available - enabled: false, } java_library { @@ -61,8 +55,6 @@ java_library { "core.module_lib.stubs.from-text", "core-lambda-stubs.from-text", ], - // TODO: Enable after stub generation from .txt file is available - enabled: false, } java_library { @@ -79,8 +71,6 @@ java_library { sdk_version: "none", system_modules: "none", visibility: ["//visibility:private"], - // TODO: Enable after stub generation from .txt file is available - enabled: false, } // Same as legacy-core-platform-api-stubs-system-modules, but the stubs are generated from .txt files @@ -91,8 +81,6 @@ java_system_modules { "legacy.core.platform.api.no.annotations.stubs.from-text", "core-lambda-stubs.from-text", ], - // TODO: Enable after stub generation from .txt file is available - enabled: false, } java_library { @@ -108,8 +96,6 @@ java_library { "legacy.core.platform.api.stubs.from-text", ], patch_module: "java.base", - // TODO: Enable after stub generation from .txt file is available - enabled: false, } // Same as stable-core-platform-api-stubs-system-modules, but the stubs are generated from .txt files @@ -120,8 +106,6 @@ java_system_modules { "stable.core.platform.api.no.annotations.stubs.from-text", "core-lambda-stubs.from-text", ], - // TODO: Enable after stub generation from .txt file is available - enabled: false, } java_library { @@ -137,8 +121,6 @@ java_library { "stable.core.platform.api.stubs.from-text", ], patch_module: "java.base", - // TODO: Enable after stub generation from .txt file is available - enabled: false, } java_api_library { @@ -151,6 +133,4 @@ java_api_library { // LambdaMetaFactory depends on CallSite etc. which is part of the Core API surface "core.current.stubs.from-text", ], - // TODO: Enable after stub generation from .txt file is available - enabled: false, } diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index f477f404e..116c833e0 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -465,7 +465,7 @@ func dexpreoptBootJarsFactory() android.SingletonModule { } func RegisterDexpreoptBootJarsComponents(ctx android.RegistrationContext) { - ctx.RegisterSingletonModuleType("dex_bootjars", dexpreoptBootJarsFactory) + ctx.RegisterParallelSingletonModuleType("dex_bootjars", dexpreoptBootJarsFactory) } func SkipDexpreoptBootJars(ctx android.PathContext) bool { diff --git a/java/dexpreopt_check.go b/java/dexpreopt_check.go index 83c088cd4..7499481de 100644 --- a/java/dexpreopt_check.go +++ b/java/dexpreopt_check.go @@ -28,7 +28,7 @@ func init() { } func RegisterDexpreoptCheckBuildComponents(ctx android.RegistrationContext) { - ctx.RegisterSingletonModuleType("dexpreopt_systemserver_check", dexpreoptSystemserverCheckFactory) + ctx.RegisterParallelSingletonModuleType("dexpreopt_systemserver_check", dexpreoptSystemserverCheckFactory) } // A build-time check to verify if all compilation artifacts of system server jars are installed diff --git a/java/fuzz.go b/java/fuzz.go index 4aa6dbffd..5c5f769a5 100644 --- a/java/fuzz.go +++ b/java/fuzz.go @@ -38,7 +38,7 @@ func init() { func RegisterJavaFuzzBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("java_fuzz", JavaFuzzFactory) - ctx.RegisterSingletonType("java_fuzz_packaging", javaFuzzPackagingFactory) + ctx.RegisterParallelSingletonType("java_fuzz_packaging", javaFuzzPackagingFactory) } type JavaFuzzTest struct { @@ -150,7 +150,9 @@ func (s *javaFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { } hostOrTargetString := "target" - if javaFuzzModule.Host() { + if javaFuzzModule.Target().HostCross { + hostOrTargetString = "host_cross" + } else if javaFuzzModule.Host() { hostOrTargetString = "host" } diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go index 96e084a20..e54275b88 100644 --- a/java/hiddenapi_modular.go +++ b/java/hiddenapi_modular.go @@ -647,7 +647,7 @@ func (s StubDexJarsByModule) addStubDexJar(ctx android.ModuleContext, module and // public version is provided by the art.module.public.api module. In those cases it is necessary // to treat all those modules as they were the same name, otherwise it will result in multiple // definitions of a single class being passed to hidden API processing which will cause an error. - if name == scope.nonUpdatablePrebuiltModule || name == scope.nonUpdatableSourceModule { + if name == scope.nonUpdatablePrebuiltModule || name == android.JavaApiLibraryName(ctx.Config(), scope.nonUpdatableSourceModule) { // Treat all *android-non-updatable* modules as if they were part of an android-non-updatable // java_sdk_library. // TODO(b/192067200): Remove once android-non-updatable is a java_sdk_library or equivalent. diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go index 52934a327..d4ee4fc9f 100644 --- a/java/hiddenapi_singleton.go +++ b/java/hiddenapi_singleton.go @@ -25,7 +25,7 @@ func init() { } func RegisterHiddenApiSingletonComponents(ctx android.RegistrationContext) { - ctx.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory) + ctx.RegisterParallelSingletonType("hiddenapi", hiddenAPISingletonFactory) } var PrepareForTestWithHiddenApiBuildComponents = android.FixtureRegisterWithContext(RegisterHiddenApiSingletonComponents) diff --git a/java/java.go b/java/java.go index 65bfce088..33846bec6 100644 --- a/java/java.go +++ b/java/java.go @@ -73,8 +73,8 @@ func registerJavaBuildComponents(ctx android.RegistrationContext) { ctx.BottomUp("jacoco_deps", jacocoDepsMutator).Parallel() }) - ctx.RegisterSingletonType("logtags", LogtagsSingleton) - ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory) + ctx.RegisterParallelSingletonType("logtags", LogtagsSingleton) + ctx.RegisterParallelSingletonType("kythe_java_extract", kytheExtractJavaFactory) } func RegisterJavaSdkMemberTypes() { @@ -1650,7 +1650,7 @@ type JavaApiLibraryProperties struct { // list of api.txt files relative to this directory that contribute to the // API surface. // This is a list of relative paths - Api_files []string + Api_files []string `android:"path"` // List of flags to be passed to the javac compiler to generate jar file Javacflags []string @@ -1832,9 +1832,7 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { // Add the api_files inputs for _, api := range al.properties.Api_files { - // Use MaybeExistentPathForSource since the api file might not exist during analysis. - // This will be provided by the orchestrator in the combined execution. - srcFiles = append(srcFiles, android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), api)) + srcFiles = append(srcFiles, android.PathForModuleSrc(ctx, api)) } if srcFiles == nil { diff --git a/java/java_test.go b/java/java_test.go index 2a4913ecd..ea89e6eb8 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -2252,6 +2252,29 @@ func TestJavaApiLibraryDepApiSrcs(t *testing.T) { android.AssertStringDoesContain(t, "Command expected to contain output files list text file flag", manifestCommand, "--out __SBOX_SANDBOX_DIR__/out/sources.txt") } +func TestJavaApiLibraryFilegroupInput(t *testing.T) { + ctx, _ := testJavaWithFS(t, ` + filegroup { + name: "default_current.txt", + srcs: ["current.txt"], + } + + java_api_library { + name: "foo", + api_files: [":default_current.txt"], + } + `, + map[string][]byte{ + "current.txt": nil, + }) + + m := ctx.ModuleForTests("foo", "android_common") + outputs := fmt.Sprint(m.AllOutputs()) + if !strings.Contains(outputs, "foo/foo.jar") { + t.Errorf("Module output does not contain expected jar %s", "foo/foo.jar") + } +} + func TestTradefedOptions(t *testing.T) { result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, ` java_test_host { diff --git a/java/jdeps.go b/java/jdeps.go index a52b86708..4c8c11c5d 100644 --- a/java/jdeps.go +++ b/java/jdeps.go @@ -26,7 +26,7 @@ import ( // called. Dependency info file is generated in $OUT/module_bp_java_depend.json. func init() { - android.RegisterSingletonType("jdeps_generator", jDepsGeneratorSingleton) + android.RegisterParallelSingletonType("jdeps_generator", jDepsGeneratorSingleton) } func jDepsGeneratorSingleton() android.Singleton { diff --git a/java/lint.go b/java/lint.go index 40ef48416..a0f99707a 100644 --- a/java/lint.go +++ b/java/lint.go @@ -705,7 +705,7 @@ func (l *lintSingleton) MakeVars(ctx android.MakeVarsContext) { var _ android.SingletonMakeVarsProvider = (*lintSingleton)(nil) func init() { - android.RegisterSingletonType("lint", + android.RegisterParallelSingletonType("lint", func() android.Singleton { return &lintSingleton{} }) registerLintBuildComponents(android.InitRegistrationContext) diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index 07fb92cfe..0d4db7ca1 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -26,7 +26,7 @@ func init() { } func registerPlatformBootclasspathBuildComponents(ctx android.RegistrationContext) { - ctx.RegisterSingletonModuleType("platform_bootclasspath", platformBootclasspathFactory) + ctx.RegisterParallelSingletonModuleType("platform_bootclasspath", platformBootclasspathFactory) } // The tags used for the dependencies between the platform bootclasspath and any configured boot diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go index d41729150..2197304a5 100644 --- a/java/platform_compat_config.go +++ b/java/platform_compat_config.go @@ -36,7 +36,7 @@ var CompatConfigSdkMemberType = &compatConfigMemberType{ } func registerPlatformCompatConfigBuildComponents(ctx android.RegistrationContext) { - ctx.RegisterSingletonType("platform_compat_config_singleton", platformCompatConfigSingletonFactory) + ctx.RegisterParallelSingletonType("platform_compat_config_singleton", platformCompatConfigSingletonFactory) ctx.RegisterModuleType("platform_compat_config", PlatformCompatConfigFactory) ctx.RegisterModuleType("prebuilt_platform_compat_config", prebuiltCompatConfigFactory) ctx.RegisterModuleType("global_compat_config", globalCompatConfigFactory) diff --git a/java/robolectric.go b/java/robolectric.go index 008b8b1c9..6bbe872bb 100644 --- a/java/robolectric.go +++ b/java/robolectric.go @@ -144,29 +144,37 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) roboTestConfig := android.PathForModuleGen(ctx, "robolectric"). Join(ctx, "com/android/tools/test_config.properties") + var ok bool + var instrumentedApp *AndroidApp + // TODO: this inserts paths to built files into the test, it should really be inserting the contents. instrumented := ctx.GetDirectDepsWithTag(instrumentationForTag) - if len(instrumented) != 1 { + if len(instrumented) == 1 { + instrumentedApp, ok = instrumented[0].(*AndroidApp) + if !ok { + ctx.PropertyErrorf("instrumentation_for", "dependency must be an android_app") + } + } else if !ctx.Config().AllowMissingDependencies() { panic(fmt.Errorf("expected exactly 1 instrumented dependency, got %d", len(instrumented))) } - instrumentedApp, ok := instrumented[0].(*AndroidApp) - if !ok { - ctx.PropertyErrorf("instrumentation_for", "dependency must be an android_app") - } - - r.manifest = instrumentedApp.mergedManifestFile - r.resourceApk = instrumentedApp.outputFile + if instrumentedApp != nil { + r.manifest = instrumentedApp.mergedManifestFile + r.resourceApk = instrumentedApp.outputFile - generateRoboTestConfig(ctx, roboTestConfig, instrumentedApp) - r.extraResources = android.Paths{roboTestConfig} + generateRoboTestConfig(ctx, roboTestConfig, instrumentedApp) + r.extraResources = android.Paths{roboTestConfig} + } r.Library.GenerateAndroidBuildActions(ctx) roboSrcJar := android.PathForModuleGen(ctx, "robolectric", ctx.ModuleName()+".srcjar") - r.generateRoboSrcJar(ctx, roboSrcJar, instrumentedApp) - r.roboSrcJar = roboSrcJar + + if instrumentedApp != nil { + r.generateRoboSrcJar(ctx, roboSrcJar, instrumentedApp) + r.roboSrcJar = roboSrcJar + } roboTestConfigJar := android.PathForModuleOut(ctx, "robolectric_samedir", "samedir_config.jar") generateSameDirRoboTestConfigJar(ctx, roboTestConfigJar) @@ -177,7 +185,10 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) // once the Make test runner is removed. roboTestConfigJar, r.outputFile, - instrumentedApp.implementationAndResourcesJar, + } + + if instrumentedApp != nil { + combinedJarJars = append(combinedJarJars, instrumentedApp.implementationAndResourcesJar) } handleLibDeps := func(dep android.Module) { @@ -213,21 +224,28 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) r.tests = append(r.tests, s) } - r.data = append(r.data, r.manifest, r.resourceApk) - - runtimes := ctx.GetDirectDepWithTag("robolectric-android-all-prebuilts", roboRuntimesTag) - installPath := android.PathForModuleInstall(ctx, r.BaseModuleName()) + var installDeps android.Paths - installedResourceApk := ctx.InstallFile(installPath, ctx.ModuleName()+".apk", r.resourceApk) - installedManifest := ctx.InstallFile(installPath, ctx.ModuleName()+"-AndroidManifest.xml", r.manifest) - installedConfig := ctx.InstallFile(installPath, ctx.ModuleName()+".config", r.testConfig) + if r.manifest != nil { + r.data = append(r.data, r.manifest) + installedManifest := ctx.InstallFile(installPath, ctx.ModuleName()+"-AndroidManifest.xml", r.manifest) + installDeps = append(installDeps, installedManifest) + } - var installDeps android.Paths + if r.resourceApk != nil { + r.data = append(r.data, r.resourceApk) + installedResourceApk := ctx.InstallFile(installPath, ctx.ModuleName()+".apk", r.resourceApk) + installDeps = append(installDeps, installedResourceApk) + } + + runtimes := ctx.GetDirectDepWithTag("robolectric-android-all-prebuilts", roboRuntimesTag) for _, runtime := range runtimes.(*robolectricRuntimes).runtimes { installDeps = append(installDeps, runtime) } - installDeps = append(installDeps, installedResourceApk, installedManifest, installedConfig) + + installedConfig := ctx.InstallFile(installPath, ctx.ModuleName()+".config", r.testConfig) + installDeps = append(installDeps, installedConfig) for _, data := range android.PathsForModuleSrc(ctx, r.testProperties.Data) { installedData := ctx.InstallFile(installPath, data.Rel(), data) @@ -340,7 +358,9 @@ func (r *robolectricTest) writeTestRunner(w io.Writer, module, name string, test fmt.Fprintln(w, "LOCAL_MODULE :=", name) android.AndroidMkEmitAssignList(w, "LOCAL_JAVA_LIBRARIES", []string{module}, r.libs) fmt.Fprintln(w, "LOCAL_TEST_PACKAGE :=", String(r.robolectricProperties.Instrumentation_for)) - fmt.Fprintln(w, "LOCAL_INSTRUMENT_SRCJARS :=", r.roboSrcJar.String()) + if r.roboSrcJar != nil { + fmt.Fprintln(w, "LOCAL_INSTRUMENT_SRCJARS :=", r.roboSrcJar.String()) + } android.AndroidMkEmitAssignList(w, "LOCAL_ROBOTEST_FILES", tests) if t := r.robolectricProperties.Test_options.Timeout; t != nil { fmt.Fprintln(w, "LOCAL_ROBOTEST_TIMEOUT :=", *t) diff --git a/java/sdk.go b/java/sdk.go index 8b4918add..7fa604fdb 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -28,7 +28,7 @@ import ( func init() { android.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory) - android.RegisterSingletonType("sdk", sdkSingletonFactory) + android.RegisterParallelSingletonType("sdk", sdkSingletonFactory) android.RegisterMakeVarsProvider(pctx, sdkMakeVars) } diff --git a/java/sdk_library.go b/java/sdk_library.go index 103f1ace7..89da19a19 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -156,6 +156,9 @@ type apiScope struct { // Whether the api scope can be treated as unstable, and should skip compat checks. unstable bool + + // Represents the SDK kind of this scope. + kind android.SdkKind } // Initialize a scope, creating and adding appropriate dependency tags @@ -229,6 +232,10 @@ func (scope *apiScope) stubsLibraryModuleNameSuffix() string { return ".stubs" + scope.moduleSuffix } +func (scope *apiScope) apiLibraryModuleName(baseName string) string { + return scope.stubsLibraryModuleName(baseName) + ".from-text" +} + func (scope *apiScope) stubsLibraryModuleName(baseName string) string { return baseName + scope.stubsLibraryModuleNameSuffix() } @@ -289,6 +296,7 @@ var ( return &module.sdkLibraryProperties.Public }, sdkVersion: "current", + kind: android.SdkPublic, }) apiScopeSystem = initApiScope(&apiScope{ name: "system", @@ -301,6 +309,7 @@ var ( moduleSuffix: ".system", sdkVersion: "system_current", annotation: "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS)", + kind: android.SdkSystem, }) apiScopeTest = initApiScope(&apiScope{ name: "test", @@ -314,6 +323,7 @@ var ( sdkVersion: "test_current", annotation: "android.annotation.TestApi", unstable: true, + kind: android.SdkTest, }) apiScopeModuleLib = initApiScope(&apiScope{ name: "module-lib", @@ -331,6 +341,7 @@ var ( moduleSuffix: ".module_lib", sdkVersion: "module_current", annotation: "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES)", + kind: android.SdkModule, }) apiScopeSystemServer = initApiScope(&apiScope{ name: "system-server", @@ -361,6 +372,7 @@ var ( // com.android.* classes are okay in this interface" "--hide", "InternalClasses", }, + kind: android.SdkSystemServer, }) allApiScopes = apiScopes{ apiScopePublic, @@ -842,6 +854,13 @@ func (c *commonToSdkLibraryAndImport) stubsSourceModuleName(apiScope *apiScope) return c.namingScheme.stubsSourceModuleName(apiScope, baseName) } +// Name of the java_api_library module that generates the from-text stubs source +// and compiles to a jar file. +func (c *commonToSdkLibraryAndImport) apiLibraryModuleName(apiScope *apiScope) string { + baseName := c.module.BaseModuleName() + return c.namingScheme.apiLibraryModuleName(apiScope, baseName) +} + // The component names for different outputs of the java_sdk_library. // // They are similar to the names used for the child modules it creates @@ -1269,7 +1288,9 @@ func (module *SdkLibrary) ComponentDepsMutator(ctx android.BottomUpMutatorContex // Add dependencies to the stubs library stubModuleName := module.stubsLibraryModuleName(apiScope) // Use JavaApiLibraryName function to be redirected to stubs generated from .txt if applicable - stubModuleName = android.JavaApiLibraryName(ctx.Config(), stubModuleName) + if module.contributesToApiSurface(ctx.Config()) { + stubModuleName = android.JavaApiLibraryName(ctx.Config(), stubModuleName) + } ctx.AddVariationDependencies(nil, apiScope.stubsTag, stubModuleName) // Add a dependency on the stubs source in order to access both stubs source and api information. @@ -1477,6 +1498,11 @@ func (module *SdkLibrary) latestIncompatibilitiesModuleName(apiScope *apiScope) return latestPrebuiltApiModuleName(module.distStem()+"-incompatibilities", apiScope) } +func (module *SdkLibrary) contributesToApiSurface(c android.Config) bool { + _, exists := c.GetApiLibraries()[module.Name()] + return exists +} + func childModuleVisibility(childVisibility []string) []string { if childVisibility == nil { // No child visibility set. The child will use the visibility of the sdk_library. @@ -1758,6 +1784,46 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC mctx.CreateModule(DroidstubsFactory, &props).(*Droidstubs).CallHookIfAvailable(mctx) } +func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) { + props := struct { + Name *string + Visibility []string + Api_contributions []string + Libs []string + Static_libs []string + Dep_api_srcs *string + }{} + + props.Name = proptools.StringPtr(module.apiLibraryModuleName(apiScope)) + props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility) + + apiContributions := []string{} + + // Api surfaces are not independent of each other, but have subset relationships, + // and so does the api files. To generate from-text stubs for api surfaces other than public, + // all subset api domains' api_contriubtions must be added as well. + scope := apiScope + for scope != nil { + apiContributions = append(apiContributions, module.stubsSourceModuleName(scope)+".api.contribution") + scope = scope.extends + } + + props.Api_contributions = apiContributions + props.Libs = module.properties.Libs + props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_libs...) + props.Libs = append(props.Libs, "stub-annotations") + props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs + props.Dep_api_srcs = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + ".from-text") + + // android_module_lib_stubs_current.from-text only comprises api contributions from art, conscrypt and i18n. + // Thus, replace with android_module_lib_stubs_current_full.from-text, which comprises every api domains. + if apiScope.kind == android.SdkModule { + props.Dep_api_srcs = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + "_full.from-text") + } + + mctx.CreateModule(ApiLibraryFactory, &props) +} + func (module *SdkLibrary) compareAgainstLatestApi(apiScope *apiScope) bool { return !(apiScope.unstable || module.sdkLibraryProperties.Unsafe_ignore_missing_latest_api) } @@ -1954,6 +2020,10 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont module.createStubsSourcesAndApi(mctx, scope, module.stubsSourceModuleName(scope), scope.droidstubsArgs) module.createStubsLibrary(mctx, scope) + + if module.contributesToApiSurface(mctx.Config()) { + module.createApiLibrary(mctx, scope) + } } if module.requiresRuntimeImplementationLibrary() { @@ -2006,6 +2076,8 @@ type sdkLibraryComponentNamingScheme interface { stubsLibraryModuleName(scope *apiScope, baseName string) string stubsSourceModuleName(scope *apiScope, baseName string) string + + apiLibraryModuleName(scope *apiScope, baseName string) string } type defaultNamingScheme struct { @@ -2019,6 +2091,10 @@ func (s *defaultNamingScheme) stubsSourceModuleName(scope *apiScope, baseName st return scope.stubsSourceModuleName(baseName) } +func (s *defaultNamingScheme) apiLibraryModuleName(scope *apiScope, baseName string) string { + return scope.apiLibraryModuleName(baseName) +} + var _ sdkLibraryComponentNamingScheme = (*defaultNamingScheme)(nil) func moduleStubLinkType(name string) (stub bool, ret sdkLinkType) { diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go index 1d0c13d4b..141e16bf7 100644 --- a/java/sdk_library_test.go +++ b/java/sdk_library_test.go @@ -35,6 +35,9 @@ func TestJavaSdkLibrary(t *testing.T) { "29": {"foo"}, "30": {"bar", "barney", "baz", "betty", "foo", "fred", "quuz", "wilma"}, }), + android.FixtureModifyConfig(func(config android.Config) { + config.SetApiLibraries([]string{"foo"}) + }), ).RunTestWithBp(t, ` droiddoc_exported_dir { name: "droiddoc-templates-sdk", @@ -121,6 +124,7 @@ func TestJavaSdkLibrary(t *testing.T) { result.ModuleForTests(apiScopeSystem.stubsSourceModuleName("foo"), "android_common") result.ModuleForTests(apiScopeTest.stubsSourceModuleName("foo"), "android_common") result.ModuleForTests(apiScopePublic.stubsSourceModuleName("foo")+".api.contribution", "") + result.ModuleForTests(apiScopePublic.apiLibraryModuleName("foo"), "android_common") result.ModuleForTests("foo"+sdkXmlFileSuffix, "android_common") result.ModuleForTests("foo.api.public.28", "") result.ModuleForTests("foo.api.system.28", "") @@ -1412,3 +1416,62 @@ func TestJavaSdkLibrary_StubOnlyLibs_PassedToDroidstubs(t *testing.T) { fooStubsSources := result.ModuleForTests("foo.stubs.source", "android_common").Module().(*Droidstubs) android.AssertStringListContains(t, "foo stubs should depend on bar-lib", fooStubsSources.Javadoc.properties.Libs, "bar-lib") } + +func TestJavaSdkLibrary_ApiLibrary(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForJavaTest, + PrepareForTestWithJavaSdkLibraryFiles, + FixtureWithLastReleaseApis("foo"), + android.FixtureModifyConfig(func(config android.Config) { + config.SetApiLibraries([]string{"foo"}) + }), + ).RunTestWithBp(t, ` + java_sdk_library { + name: "foo", + srcs: ["a.java", "b.java"], + api_packages: ["foo"], + system: { + enabled: true, + }, + module_lib: { + enabled: true, + }, + test: { + enabled: true, + }, + } + `) + + testCases := []struct { + scope *apiScope + apiContributions []string + depApiSrcs string + }{ + { + scope: apiScopePublic, + apiContributions: []string{"foo.stubs.source.api.contribution"}, + depApiSrcs: "android_stubs_current.from-text", + }, + { + scope: apiScopeSystem, + apiContributions: []string{"foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"}, + depApiSrcs: "android_system_stubs_current.from-text", + }, + { + scope: apiScopeTest, + apiContributions: []string{"foo.stubs.source.test.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"}, + depApiSrcs: "android_test_stubs_current.from-text", + }, + { + scope: apiScopeModuleLib, + apiContributions: []string{"foo.stubs.source.module_lib.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"}, + depApiSrcs: "android_module_lib_stubs_current_full.from-text", + }, + } + + for _, c := range testCases { + m := result.ModuleForTests(c.scope.apiLibraryModuleName("foo"), "android_common").Module().(*ApiLibrary) + android.AssertArrayString(t, "Module expected to contain api contributions", c.apiContributions, m.properties.Api_contributions) + android.AssertStringEquals(t, "Module expected to contain full api surface api library", c.depApiSrcs, *m.properties.Dep_api_srcs) + } +} diff --git a/java/testing.go b/java/testing.go index 6671bf0c7..3a238d76f 100644 --- a/java/testing.go +++ b/java/testing.go @@ -71,7 +71,12 @@ var prepareForTestWithFrameworkDeps = android.GroupFixturePreparers( // Needed for framework defaultJavaDir + "/framework/aidl": nil, // Needed for various deps defined in GatherRequiredDepsForTest() - defaultJavaDir + "/a.java": nil, + defaultJavaDir + "/a.java": nil, + defaultJavaDir + "/api/current.txt": nil, + defaultJavaDir + "/api/system-current.txt": nil, + defaultJavaDir + "/api/test-current.txt": nil, + defaultJavaDir + "/api/module-lib-current.txt": nil, + defaultJavaDir + "/api/system-server-current.txt": nil, // Needed for R8 rules on apps "build/make/core/proguard.flags": nil, @@ -395,16 +400,20 @@ func gatherRequiredDepsForTest() string { } extraApiLibraryModules := map[string]string{ - "android_stubs_current.from-text": "api/current.txt", - "android_system_stubs_current.from-text": "api/system-current.txt", - "android_test_stubs_current.from-text": "api/test-current.txt", - "android_module_lib_stubs_current.from-text": "api/module-lib-current.txt", - "android_module_lib_stubs_current_full.from-text": "api/module-lib-current.txt", - "android_system_server_stubs_current.from-text": "api/system-server-current.txt", - "core.current.stubs.from-text": "api/current.txt", - "legacy.core.platform.api.stubs.from-text": "api/current.txt", - "stable.core.platform.api.stubs.from-text": "api/current.txt", - "core-lambda-stubs.from-text": "api/current.txt", + "android_stubs_current.from-text": "api/current.txt", + "android_system_stubs_current.from-text": "api/system-current.txt", + "android_test_stubs_current.from-text": "api/test-current.txt", + "android_module_lib_stubs_current.from-text": "api/module-lib-current.txt", + "android_module_lib_stubs_current_full.from-text": "api/module-lib-current.txt", + "android_system_server_stubs_current.from-text": "api/system-server-current.txt", + "core.current.stubs.from-text": "api/current.txt", + "legacy.core.platform.api.stubs.from-text": "api/current.txt", + "stable.core.platform.api.stubs.from-text": "api/current.txt", + "core-lambda-stubs.from-text": "api/current.txt", + "android-non-updatable.stubs.from-text": "api/current.txt", + "android-non-updatable.stubs.system.from-text": "api/system-current.txt", + "android-non-updatable.stubs.test.from-text": "api/test-current.txt", + "android-non-updatable.stubs.module_lib.from-text": "api/module-lib-current.txt", } for libName, apiFile := range extraApiLibraryModules { diff --git a/multitree/metadata.go b/multitree/metadata.go index 3fd721599..0eb0efc95 100644 --- a/multitree/metadata.go +++ b/multitree/metadata.go @@ -20,7 +20,7 @@ import ( ) func init() { - android.RegisterSingletonType("update-meta", UpdateMetaSingleton) + android.RegisterParallelSingletonType("update-meta", UpdateMetaSingleton) } func UpdateMetaSingleton() android.Singleton { diff --git a/provenance/provenance_singleton.go b/provenance/provenance_singleton.go index fbb6212ff..5d27c0cf4 100644 --- a/provenance/provenance_singleton.go +++ b/provenance/provenance_singleton.go @@ -51,7 +51,7 @@ func init() { } func RegisterProvenanceSingleton(ctx android.RegistrationContext) { - ctx.RegisterSingletonType("provenance_metadata_singleton", provenanceInfoSingletonFactory) + ctx.RegisterParallelSingletonType("provenance_metadata_singleton", provenanceInfoSingletonFactory) } var PrepareForTestWithProvenanceSingleton = android.FixtureRegisterWithContext(RegisterProvenanceSingleton) diff --git a/python/test.go b/python/test.go index 31da17e61..6e23a447f 100644 --- a/python/test.go +++ b/python/test.go @@ -39,7 +39,7 @@ func NewTest(hod android.HostOrDeviceSupported) *PythonTestModule { } func PythonTestHostFactory() android.Module { - return NewTest(android.HostSupportedNoCross).init() + return NewTest(android.HostSupported).init() } func PythonTestFactory() android.Module { @@ -66,6 +66,10 @@ type TestProperties struct { // Test options. Test_options TestOptions + + // list of device binary modules that should be installed alongside the test + // This property adds 64bit AND 32bit variants of the dependency + Data_device_bins_both []string `android:"arch_variant"` } type TestOptions struct { @@ -98,12 +102,48 @@ func (p *PythonTestModule) init() android.Module { android.InitAndroidArchModule(p, p.hod, p.multilib) android.InitDefaultableModule(p) android.InitBazelModule(p) - if p.hod == android.HostSupportedNoCross && p.testProperties.Test_options.Unit_test == nil { + if p.isTestHost() && p.testProperties.Test_options.Unit_test == nil { p.testProperties.Test_options.Unit_test = proptools.BoolPtr(true) } return p } +func (p *PythonTestModule) isTestHost() bool { + return p.hod == android.HostSupported +} + +var dataDeviceBinsTag = dependencyTag{name: "dataDeviceBins"} + +// python_test_host DepsMutator uses this method to add multilib dependencies of +// data_device_bin_both +func (p *PythonTestModule) addDataDeviceBinsDeps(ctx android.BottomUpMutatorContext, filter string) { + if len(p.testProperties.Data_device_bins_both) < 1 { + return + } + + var maybeAndroidTarget *android.Target + androidTargetList := android.FirstTarget(ctx.Config().Targets[android.Android], filter) + if len(androidTargetList) > 0 { + maybeAndroidTarget = &androidTargetList[0] + } + + if maybeAndroidTarget != nil { + ctx.AddFarVariationDependencies( + maybeAndroidTarget.Variations(), + dataDeviceBinsTag, + p.testProperties.Data_device_bins_both..., + ) + } +} + +func (p *PythonTestModule) DepsMutator(ctx android.BottomUpMutatorContext) { + p.PythonBinaryModule.DepsMutator(ctx) + if p.isTestHost() { + p.addDataDeviceBinsDeps(ctx, "lib32") + p.addDataDeviceBinsDeps(ctx, "lib64") + } +} + func (p *PythonTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { // We inherit from only the library's GenerateAndroidBuildActions, and then // just use buildBinary() so that the binary is not installed into the location @@ -153,6 +193,12 @@ func (p *PythonTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext p.data = append(p.data, android.DataPath{SrcPath: dataSrcPath}) } + if p.isTestHost() && len(p.testProperties.Data_device_bins_both) > 0 { + ctx.VisitDirectDepsWithTag(dataDeviceBinsTag, func(dep android.Module) { + p.data = append(p.data, android.DataPath{SrcPath: android.OutputFileForModule(ctx, dep, "")}) + }) + } + // Emulate the data property for java_data dependencies. for _, javaData := range ctx.GetDirectDepsWithTag(javaDataTag) { for _, javaDataSrcPath := range android.OutputFilesForModule(ctx, javaData, "") { diff --git a/rust/doc.go b/rust/doc.go index fe3581b42..6970d7979 100644 --- a/rust/doc.go +++ b/rust/doc.go @@ -19,7 +19,7 @@ import ( ) func init() { - android.RegisterSingletonType("rustdoc", RustdocSingleton) + android.RegisterParallelSingletonType("rustdoc", RustdocSingleton) } func RustdocSingleton() android.Singleton { diff --git a/rust/project_json.go b/rust/project_json.go index fe259d6c2..40aa7c736 100644 --- a/rust/project_json.go +++ b/rust/project_json.go @@ -74,7 +74,7 @@ func rustProjectGeneratorSingleton() android.Singleton { } func init() { - android.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton) + android.RegisterParallelSingletonType("rust_project_generator", rustProjectGeneratorSingleton) } // sourceProviderVariantSource returns the path to the source file if this diff --git a/rust/rust.go b/rust/rust.go index dc53cc028..4324ecbb9 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -45,7 +45,7 @@ func init() { }) pctx.Import("android/soong/rust/config") pctx.ImportAs("cc_config", "android/soong/cc/config") - android.InitRegistrationContext.RegisterSingletonType("kythe_rust_extract", kytheExtractRustFactory) + android.InitRegistrationContext.RegisterParallelSingletonType("kythe_rust_extract", kytheExtractRustFactory) } type Flags struct { diff --git a/rust/testing.go b/rust/testing.go index 0a6a870d8..7f3056954 100644 --- a/rust/testing.go +++ b/rust/testing.go @@ -200,8 +200,8 @@ func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) { ctx.BottomUp("rust_stdlinkage", LibstdMutator).Parallel() ctx.BottomUp("rust_begin", BeginMutator).Parallel() }) - ctx.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton) - ctx.RegisterSingletonType("kythe_rust_extract", kytheExtractRustFactory) + ctx.RegisterParallelSingletonType("rust_project_generator", rustProjectGeneratorSingleton) + ctx.RegisterParallelSingletonType("kythe_rust_extract", kytheExtractRustFactory) ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator).Parallel() }) diff --git a/snapshot/host_fake_snapshot.go b/snapshot/host_fake_snapshot.go index b04657d3d..c4cfbb5ce 100644 --- a/snapshot/host_fake_snapshot.go +++ b/snapshot/host_fake_snapshot.go @@ -75,7 +75,7 @@ type hostSnapshotFakeJsonFlags struct { } func registerHostSnapshotComponents(ctx android.RegistrationContext) { - ctx.RegisterSingletonType("host-fake-snapshot", HostToolsFakeAndroidSingleton) + ctx.RegisterParallelSingletonType("host-fake-snapshot", HostToolsFakeAndroidSingleton) } type hostFakeSingleton struct { diff --git a/snapshot/recovery_snapshot.go b/snapshot/recovery_snapshot.go index ac002be9c..8ff59cbcf 100644 --- a/snapshot/recovery_snapshot.go +++ b/snapshot/recovery_snapshot.go @@ -68,7 +68,7 @@ var RecoverySnapshotImageName = "recovery" type RecoverySnapshotImage struct{} func (RecoverySnapshotImage) Init(ctx android.RegistrationContext) { - ctx.RegisterSingletonType("recovery-snapshot", RecoverySnapshotSingleton) + ctx.RegisterParallelSingletonType("recovery-snapshot", RecoverySnapshotSingleton) } func (RecoverySnapshotImage) RegisterAdditionalModule(ctx android.RegistrationContext, name string, factory android.ModuleFactory) { diff --git a/snapshot/vendor_snapshot.go b/snapshot/vendor_snapshot.go index 8f7b8c215..4484c855d 100644 --- a/snapshot/vendor_snapshot.go +++ b/snapshot/vendor_snapshot.go @@ -78,8 +78,8 @@ var VendorSnapshotImageName = "vendor" type VendorSnapshotImage struct{} func (VendorSnapshotImage) Init(ctx android.RegistrationContext) { - ctx.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton) - ctx.RegisterSingletonType("vendor-fake-snapshot", VendorFakeSnapshotSingleton) + ctx.RegisterParallelSingletonType("vendor-snapshot", VendorSnapshotSingleton) + ctx.RegisterParallelSingletonType("vendor-fake-snapshot", VendorFakeSnapshotSingleton) } func (VendorSnapshotImage) RegisterAdditionalModule(ctx android.RegistrationContext, name string, factory android.ModuleFactory) { diff --git a/tests/dcla_apex_comparison_test.sh b/tests/dcla_apex_comparison_test.sh index 97ae97ecb..667dde0b7 100755 --- a/tests/dcla_apex_comparison_test.sh +++ b/tests/dcla_apex_comparison_test.sh @@ -45,6 +45,11 @@ MODULES=( com.android.tethering ) +BAZEL_TARGETS=( + //packages/modules/adb/apex:com.android.adbd + //frameworks/av/apex:com.android.media.swcodec +) + DCLA_LIBS=( libbase.so libc++.so @@ -76,6 +81,10 @@ DEAPEXER="${DEAPEXER} --debugfs_path=${DEBUGFS}" ############ OUTPUT_DIR="$(mktemp -d tmp.XXXXXX)" +function call_bazel() { + build/bazel/bin/bazel $@ +} + function cleanup { rm -rf "${OUTPUT_DIR}" } @@ -87,7 +96,9 @@ trap cleanup EXIT function extract_dcla_libs() { local product=$1; shift - for module in "${MODULES[@]}"; do + local modules=("$@"); shift + + for module in "${modules[@]}"; do local apex="${OUTPUT_DIR}/${product}/${module}.apex" local extract_dir="${OUTPUT_DIR}/${product}/${module}/extract" @@ -97,11 +108,12 @@ function extract_dcla_libs() { function compare_dcla_libs() { local product=$1; shift + local modules=("$@"); shift for lib in "${DCLA_LIBS[@]}"; do for arch in lib lib64; do local prev_sha="" - for module in "${MODULES[@]}"; do + for module in "${modules[@]}"; do local file="${OUTPUT_DIR}/${product}/${module}/extract/${arch}/${lib}" if [[ ! -f "${file}" ]]; then # not all libs are present in a module @@ -112,7 +124,7 @@ function compare_dcla_libs() { sha="${sha% *}" if [ "${prev_sha}" == "" ]; then prev_sha="${sha}" - elif [ "${sha}" != "${prev_sha}" ] && { [ "${lib}" != "libcrypto.so" ] || [ "${module}" != "com.android.tethering" ]; }; then + elif [ "${sha}" != "${prev_sha}" ] && { [ "${lib}" != "libcrypto.so" ] || [[ "${module}" != *"com.android.tethering" ]]; }; then echo "Test failed, ${lib} has different hash value" exit 1 fi @@ -131,8 +143,22 @@ for product in "${TARGET_PRODUCTS[@]}"; do --product "${product}" \ --dist_dir "${OUTPUT_DIR}/${product}" - extract_dcla_libs "${product}" - compare_dcla_libs "${product}" + bazel_apexes=() + if [[ -n ${TEST_BAZEL+x} ]] && [ "${TEST_BAZEL}" = true ]; then + export TARGET_PRODUCT="${product/module/aosp}" + call_bazel build --config=bp2build --config=ci --config=android "${BAZEL_TARGETS[@]}" + for target in "${BAZEL_TARGETS[@]}"; do + apex_path="$(realpath $(call_bazel cquery --config=bp2build --config=android --config=ci --output=files $target))" + mkdir -p ${OUTPUT_DIR}/${product} + bazel_apex="bazel_$(basename $apex_path)" + mv $apex_path ${OUTPUT_DIR}/${product}/${bazel_apex} + bazel_apexes+=(${bazel_apex%".apex"}) + done + fi + + all_modeuls=(${MODULES[@]} ${bazel_apexes[@]}) + extract_dcla_libs "${product}" "${all_modeuls[@]}" + compare_dcla_libs "${product}" "${all_modeuls[@]}" done echo "Test passed" diff --git a/tests/lib.sh b/tests/lib.sh index 715eac143..7f3970eb7 100644 --- a/tests/lib.sh +++ b/tests/lib.sh @@ -99,6 +99,7 @@ function create_mock_soong { symlink_directory external/python symlink_directory external/sqlite symlink_directory external/spdx-tools + symlink_directory libcore touch "$MOCK_TOP/Android.bp" } diff --git a/tests/run_integration_tests.sh b/tests/run_integration_tests.sh index e1aa70c73..db14bd442 100755 --- a/tests/run_integration_tests.sh +++ b/tests/run_integration_tests.sh @@ -15,8 +15,8 @@ TOP="$(readlink -f "$(dirname "$0")"/../../..)" # mock client. "$TOP/build/soong/tests/apex_comparison_tests.sh" "$TOP/build/soong/tests/apex_comparison_tests.sh" "module_arm64only" -extra_build_params=--bazel-mode-staging "$TOP/build/soong/tests/dcla_apex_comparison_test.sh" -BUILD_BROKEN_DISABLE_BAZEL=true "$TOP/build/soong/tests/dcla_apex_comparison_test.sh" +TEST_BAZEL=true extra_build_params=--bazel-mode-staging "$TOP/build/soong/tests/dcla_apex_comparison_test.sh" +#BUILD_BROKEN_DISABLE_BAZEL=true "$TOP/build/soong/tests/dcla_apex_comparison_test.sh" "$TOP/build/soong/tests/apex_cc_module_arch_variant_tests.sh" "$TOP/build/soong/tests/apex_cc_module_arch_variant_tests.sh" "aosp_arm" "armv7-a" "$TOP/build/soong/tests/apex_cc_module_arch_variant_tests.sh" "aosp_cf_arm64_phone" "armv8-a" "cortex-a53" diff --git a/ui/build/kati.go b/ui/build/kati.go index dad68fac2..aea56d31a 100644 --- a/ui/build/kati.go +++ b/ui/build/kati.go @@ -22,6 +22,7 @@ import ( "os/user" "path/filepath" "strings" + "time" "android/soong/ui/metrics" "android/soong/ui/status" @@ -66,6 +67,21 @@ func genKatiSuffix(ctx Context, config Config) { } } +func writeValueIfChanged(ctx Context, config Config, dir string, filename string, value string) { + filePath := filepath.Join(dir, filename) + previousValue := "" + rawPreviousValue, err := ioutil.ReadFile(filePath) + if err == nil { + previousValue = string(rawPreviousValue) + } + + if previousValue != value { + if err = ioutil.WriteFile(filePath, []byte(value), 0666); err != nil { + ctx.Fatalf("Failed to write: %v", err) + } + } +} + // Base function to construct and run the Kati command line with additional // arguments, and a custom function closure to mutate the environment Kati runs // in. @@ -157,28 +173,60 @@ func runKati(ctx Context, config Config, extraSuffix string, args []string, envF } cmd.Stderr = cmd.Stdout - // Apply the caller's function closure to mutate the environment variables. - envFunc(cmd.Environment) - + var username string // Pass on various build environment metadata to Kati. - if _, ok := cmd.Environment.Get("BUILD_USERNAME"); !ok { - username := "unknown" + if usernameFromEnv, ok := cmd.Environment.Get("BUILD_USERNAME"); !ok { + username = "unknown" if u, err := user.Current(); err == nil { username = u.Username } else { ctx.Println("Failed to get current user:", err) } cmd.Environment.Set("BUILD_USERNAME", username) + } else { + username = usernameFromEnv } - if _, ok := cmd.Environment.Get("BUILD_HOSTNAME"); !ok { - hostname, err := os.Hostname() + hostname, ok := cmd.Environment.Get("BUILD_HOSTNAME") + // Unset BUILD_HOSTNAME during kati run to avoid kati rerun, kati will use BUILD_HOSTNAME from a file. + cmd.Environment.Unset("BUILD_HOSTNAME") + if !ok { + hostname, err = os.Hostname() if err != nil { ctx.Println("Failed to read hostname:", err) hostname = "unknown" } - cmd.Environment.Set("BUILD_HOSTNAME", hostname) } + writeValueIfChanged(ctx, config, config.SoongOutDir(), "build_hostname.txt", hostname) + + // BUILD_NUMBER should be set to the source control value that + // represents the current state of the source code. E.g., a + // perforce changelist number or a git hash. Can be an arbitrary string + // (to allow for source control that uses something other than numbers), + // but must be a single word and a valid file name. + // + // If no BUILD_NUMBER is set, create a useful "I am an engineering build + // from this date/time" value. Make it start with a non-digit so that + // anyone trying to parse it as an integer will probably get "0". + cmd.Environment.Unset("HAS_BUILD_NUMBER") + buildNumber, ok := cmd.Environment.Get("BUILD_NUMBER") + // Unset BUILD_NUMBER during kati run to avoid kati rerun, kati will use BUILD_NUMBER from a file. + cmd.Environment.Unset("BUILD_NUMBER") + if ok { + cmd.Environment.Set("HAS_BUILD_NUMBER", "true") + writeValueIfChanged(ctx, config, config.OutDir(), "file_name_tag.txt", buildNumber) + } else { + buildNumber = fmt.Sprintf("eng.%.6s.%s", username, time.Now().Format("20060102.150405" /* YYYYMMDD.HHMMSS */)) + cmd.Environment.Set("HAS_BUILD_NUMBER", "false") + writeValueIfChanged(ctx, config, config.OutDir(), "file_name_tag.txt", username) + } + // Write the build number to a file so it can be read back in + // without changing the command line every time. Avoids rebuilds + // when using ninja. + writeValueIfChanged(ctx, config, config.SoongOutDir(), "build_number.txt", buildNumber) + + // Apply the caller's function closure to mutate the environment variables. + envFunc(cmd.Environment) cmd.StartOrFatal() // Set up the ToolStatus command line reader for Kati for a consistent UI @@ -336,6 +384,7 @@ func runKatiPackage(ctx Context, config Config) { "ANDROID_BUILD_SHELL", "DIST_DIR", "OUT_DIR", + "FILE_NAME_TAG", }...) if config.Dist() { |