diff options
30 files changed, 588 insertions, 632 deletions
diff --git a/android/bazel.go b/android/bazel.go index cc021527f..51ff3cb27 100644 --- a/android/bazel.go +++ b/android/bazel.go @@ -130,48 +130,48 @@ var ( // Per-module denylist to always opt modules out. bp2buildModuleDoNotConvertList = []string{ - "generated_android_ids", - "libBionicBenchmarksUtils", - "libbionic_spawn_benchmark", - "libc_jemalloc_wrapper", - "libc_bootstrap", - "libc_init_static", - "libc_init_dynamic", - "libc_tzcode", - "libc_freebsd", - "libc_freebsd_large_stack", - "libc_netbsd", - "libc_openbsd_ndk", - "libc_openbsd_large_stack", - "libc_openbsd", - "libc_gdtoa", - "libc_fortify", - "libc_bionic", - "libc_bionic_ndk", - "libc_bionic_systrace", - "libc_pthread", - "libc_syscalls", - "libc_aeabi", - "libc_ndk", - "libc_nopthread", - "libc_common", - "libc_static_dispatch", - "libc_dynamic_dispatch", - "libc_common_static", - "libc_common_shared", - "libc_unwind_static", - "libc_nomalloc", - "libasync_safe", - "libc_malloc_debug_backtrace", - "libsystemproperties", - "libdl_static", - "liblinker_main", - "liblinker_malloc", - "liblinker_debuggerd_stub", - "libbionic_tests_headers_posix", - "libc_dns", - "note_memtag_heap_async", - "note_memtag_heap_sync", + "libBionicBenchmarksUtils", // ruperts@, cc_library_static + "libbionic_spawn_benchmark", // ruperts@, cc_library_static, depends on //system/libbase + "libc_jemalloc_wrapper", // ruperts@, cc_library_static, depends on //external/jemalloc_new + "libc_bootstrap", // ruperts@, cc_library_static + "libc_init_static", // ruperts@, cc_library_static + "libc_init_dynamic", // ruperts@, cc_library_static + "libc_tzcode", // ruperts@, cc_library_static + "libc_freebsd", // ruperts@, cc_library_static + "libc_freebsd_large_stack", // ruperts@, cc_library_static + "libc_netbsd", // ruperts@, cc_library_static + "libc_openbsd_ndk", // ruperts@, cc_library_static + "libc_openbsd_large_stack", // ruperts@, cc_library_static + "libc_openbsd", // ruperts@, cc_library_static + "libc_gdtoa", // ruperts@, cc_library_static + "libc_fortify", // ruperts@, cc_library_static + "libc_bionic", // ruperts@, cc_library_static + "libc_bionic_ndk", // ruperts@, cc_library_static, depends on //bionic/libc/system_properties + "libc_bionic_systrace", // ruperts@, cc_library_static + "libc_pthread", // ruperts@, cc_library_static + "libc_syscalls", // ruperts@, cc_library_static + "libc_aeabi", // ruperts@, cc_library_static + "libc_ndk", // ruperts@, cc_library_static, depends on //bionic/libm:libm + "libc_nopthread", // ruperts@, cc_library_static, depends on //external/arm-optimized-routines + "libc_common", // ruperts@, cc_library_static, depends on //bionic/libc:libc_nopthread + "libc_static_dispatch", // ruperts@, cc_library_static + "libc_dynamic_dispatch", // ruperts@, cc_library_static + "libc_common_static", // ruperts@, cc_library_static, depends on //bionic/libc:libc_common + "libc_common_shared", // ruperts@, cc_library_static, depends on //bionic/libc:libc_common + "libc_unwind_static", // ruperts@, cc_library_static + "libc_nomalloc", // ruperts@, cc_library_static, depends on //bionic/libc:libc_common + "libasync_safe", // ruperts@, cc_library_static + "libc_malloc_debug_backtrace", // ruperts@, cc_library_static, depends on //system/libbase + "libsystemproperties", // ruperts@, cc_library_static, depends on //system/core/property_service/libpropertyinfoparser + "libdl_static", // ruperts@, cc_library_static + "liblinker_main", // ruperts@, cc_library_static, depends on //system/libbase + "liblinker_malloc", // ruperts@, cc_library_static, depends on //system/logging/liblog:liblog + "liblinker_debuggerd_stub", // ruperts@, cc_library_static, depends on //system/libbase + "libbionic_tests_headers_posix", // ruperts@, cc_library_static + "libc_dns", // ruperts@, cc_library_static + "generated_android_ids", // cparsons@, genrule + "note_memtag_heap_async", // cparsons@, cc_library_static + "note_memtag_heap_sync", // cparsons@, cc_library_static } // Used for quicker lookups diff --git a/android/fixture.go b/android/fixture.go index 303c95c2e..5fc668a8b 100644 --- a/android/fixture.go +++ b/android/fixture.go @@ -26,16 +26,9 @@ import ( // Fixture // ======= // These determine the environment within which a test can be run. Fixtures are mutable and are -// created by FixtureFactory instances and mutated by FixturePreparer instances. They are created by -// first creating a base Fixture (which is essentially empty) and then applying FixturePreparer -// instances to it to modify the environment. -// -// FixtureFactory (deprecated) -// =========================== -// These are responsible for creating fixtures. Factories are immutable and are intended to be -// initialized once and reused to create multiple fixtures. Each factory has a list of fixture -// preparers that prepare a fixture for running a test. Factories can also be used to create other -// factories by extending them with additional fixture preparers. +// created and mutated by FixturePreparer instances. They are created by first creating a base +// Fixture (which is essentially empty) and then applying FixturePreparer instances to it to modify +// the environment. // // FixturePreparer // =============== @@ -169,77 +162,6 @@ import ( // PrepareForApex, // ) // -// // FixtureFactory instances have been deprecated, this remains for informational purposes to -// // help explain some of the existing code but will be removed along with FixtureFactory. -// -// var javaFixtureFactory = android.NewFixtureFactory( -// PrepareForIntegrationTestWithJava, -// FixtureRegisterWithContext(func(ctx android.RegistrationContext) { -// ctx.RegisterModuleType("test_module", testModule) -// }), -// javaMockFS.AddToFixture(), -// ... -// } -// -// func TestJavaStuff(t *testing.T) { -// result := javaFixtureFactory.RunTest(t, -// android.FixtureWithRootAndroidBp(`java_library {....}`), -// android.MockFS{...}.AddToFixture(), -// ) -// ... test result ... -// } -// -// package cc -// var PrepareForTestWithCC = GroupFixturePreparers( -// android.PrepareForArchMutator, -// android.prepareForPrebuilts, -// FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest), -// ... -// ) -// -// package apex -// -// var PrepareForApex = GroupFixturePreparers( -// ... -// ) -// -// Use modules and mutators from java, cc and apex. Any duplicate preparers (like -// android.PrepareForArchMutator) will be automatically deduped. -// -// var apexFixtureFactory = android.NewFixtureFactory( -// PrepareForJava, -// PrepareForCC, -// PrepareForApex, -// ) - -// Factory for Fixture objects. -// -// This is configured with a set of FixturePreparer objects that are used to -// initialize each Fixture instance this creates. -// -// deprecated: Use FixturePreparer instead. -type FixtureFactory interface { - FixturePreparer -} - -// Create a new FixtureFactory that will apply the supplied preparers. -// -// The buildDirSupplier is a pointer to the package level buildDir variable that is initialized by -// the package level setUp method. It has to be a pointer to the variable as the variable will not -// have been initialized at the time the factory is created. If it is nil then a test specific -// temporary directory will be created instead. -// -// deprecated: The functionality provided by FixtureFactory will be merged into FixturePreparer -func NewFixtureFactory(buildDirSupplier *string, preparers ...FixturePreparer) FixtureFactory { - f := &fixtureFactory{ - buildDirSupplier: buildDirSupplier, - compositeFixturePreparer: compositeFixturePreparer{ - preparers: dedupAndFlattenPreparers(nil, preparers), - }, - } - f.initBaseFixturePreparer(f) - return f -} // A set of mock files to add to the mock file system. type MockFS map[string][]byte @@ -445,15 +367,6 @@ type FixturePreparer interface { // Return the flattened and deduped list of simpleFixturePreparer pointers. list() []*simpleFixturePreparer - // Creates a copy of this instance and adds some additional preparers. - // - // Before the preparers are used they are combined with the preparers provided when the factory - // was created, any groups of preparers are flattened, and the list is deduped so that each - // preparer is only used once. See the file documentation in android/fixture.go for more details. - // - // deprecated: Use GroupFixturePreparers() instead. - Extend(preparers ...FixturePreparer) FixturePreparer - // Create a Fixture. Fixture(t *testing.T) Fixture @@ -734,17 +647,12 @@ func (b *baseFixturePreparer) initBaseFixturePreparer(self FixturePreparer) { b.self = self } -func (b *baseFixturePreparer) Extend(preparers ...FixturePreparer) FixturePreparer { - all := dedupAndFlattenPreparers(b.self.list(), preparers) - return newFixturePreparer(all) -} - func (b *baseFixturePreparer) Fixture(t *testing.T) Fixture { return createFixture(t, t.TempDir(), b.self.list()) } func (b *baseFixturePreparer) ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixturePreparer { - return b.self.Extend(newSimpleFixturePreparer(func(fixture *fixture) { + return GroupFixturePreparers(b.self, newSimpleFixturePreparer(func(fixture *fixture) { fixture.errorHandler = errorHandler })) } @@ -782,46 +690,6 @@ func (b *baseFixturePreparer) RunTestWithConfig(t *testing.T, config Config) *Te return fixture.RunTest() } -var _ FixtureFactory = (*fixtureFactory)(nil) - -type fixtureFactory struct { - compositeFixturePreparer - - buildDirSupplier *string -} - -// Override to preserve the buildDirSupplier. -func (f *fixtureFactory) Extend(preparers ...FixturePreparer) FixturePreparer { - // If there is no buildDirSupplier then just use the default implementation. - if f.buildDirSupplier == nil { - return f.baseFixturePreparer.Extend(preparers...) - } - - all := dedupAndFlattenPreparers(f.preparers, preparers) - - // Create a new factory which uses the same buildDirSupplier as the previous one. - extendedFactory := &fixtureFactory{ - buildDirSupplier: f.buildDirSupplier, - compositeFixturePreparer: compositeFixturePreparer{ - preparers: all, - }, - } - extendedFactory.initBaseFixturePreparer(extendedFactory) - return extendedFactory -} - -func (f *fixtureFactory) Fixture(t *testing.T) Fixture { - // If there is no buildDirSupplier then just use the default implementation. - if f.buildDirSupplier == nil { - return f.baseFixturePreparer.Fixture(t) - } - - // Retrieve the buildDir from the supplier. - buildDir := *f.buildDirSupplier - - return createFixture(t, buildDir, f.preparers) -} - type fixture struct { // The preparers used to create this fixture. preparers []*simpleFixturePreparer @@ -936,10 +804,10 @@ func (r *TestResult) NormalizePathsForTesting(paths Paths) []string { // that produced this result. // // e.g. assuming that this result was created by running: -// factory.Extend(preparer1, preparer2).RunTest(t, preparer3, preparer4) +// GroupFixturePreparers(preparer1, preparer2, preparer3).RunTest(t) // // Then this method will be equivalent to running: -// GroupFixturePreparers(preparer1, preparer2, preparer3, preparer4) +// GroupFixturePreparers(preparer1, preparer2, preparer3) // // This is intended for use by tests whose output is Android.bp files to verify that those files // are valid, e.g. tests of the snapshots produced by the sdk module type. diff --git a/android/fixture_test.go b/android/fixture_test.go index 8f0471560..5b810e0b7 100644 --- a/android/fixture_test.go +++ b/android/fixture_test.go @@ -41,7 +41,7 @@ func TestFixtureDedup(t *testing.T) { group := GroupFixturePreparers(preparer1, preparer2, preparer1, preparer1Then2) - extension := group.Extend(preparer4, preparer2) + extension := GroupFixturePreparers(group, preparer4, preparer2) GroupFixturePreparers(extension, preparer1, preparer2, preparer2Then1, preparer3).Fixture(t) diff --git a/android/mutator.go b/android/mutator.go index a06e0ee46..e25e2e8f1 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -202,7 +202,7 @@ var postDeps = []RegisterMutatorFunc{ RegisterPrebuiltsPostDepsMutators, RegisterVisibilityRuleEnforcer, RegisterLicensesDependencyChecker, - RegisterNeverallowMutator, + registerNeverallowMutator, RegisterOverridePostDepsMutators, } diff --git a/android/neverallow.go b/android/neverallow.go index 7455e6a78..a385bbc0c 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -42,7 +42,7 @@ import ( // counts as a match // - it has none of the "Without" properties matched (same rules as above) -func RegisterNeverallowMutator(ctx RegisterMutatorsContext) { +func registerNeverallowMutator(ctx RegisterMutatorsContext) { ctx.BottomUp("neverallow", neverallowMutator).Parallel() } @@ -661,6 +661,22 @@ func neverallowRules(config Config) []Rule { // Overrides the default neverallow rules for the supplied config. // // For testing only. -func SetTestNeverallowRules(config Config, testRules []Rule) { +func setTestNeverallowRules(config Config, testRules []Rule) { config.Once(neverallowRulesKey, func() interface{} { return testRules }) } + +// Prepares for a test by setting neverallow rules and enabling the mutator. +// +// If the supplied rules are nil then the default rules are used. +func PrepareForTestWithNeverallowRules(testRules []Rule) FixturePreparer { + return GroupFixturePreparers( + FixtureModifyConfig(func(config Config) { + if testRules != nil { + setTestNeverallowRules(config, testRules) + } + }), + FixtureRegisterWithContext(func(ctx RegistrationContext) { + ctx.PostDepsMutators(registerNeverallowMutator) + }), + ) +} diff --git a/android/neverallow_test.go b/android/neverallow_test.go index de0197a80..268346a7b 100644 --- a/android/neverallow_test.go +++ b/android/neverallow_test.go @@ -292,7 +292,6 @@ var prepareForNeverAllowTest = GroupFixturePreparers( ctx.RegisterModuleType("java_library_host", newMockJavaLibraryModule) ctx.RegisterModuleType("java_device_for_host", newMockJavaLibraryModule) ctx.RegisterModuleType("makefile_goal", newMockMakefileGoalModule) - ctx.PostDepsMutators(RegisterNeverallowMutator) }), ) @@ -301,12 +300,7 @@ func TestNeverallow(t *testing.T) { t.Run(test.name, func(t *testing.T) { GroupFixturePreparers( prepareForNeverAllowTest, - FixtureModifyConfig(func(config Config) { - // If the test has its own rules then use them instead of the default ones. - if test.rules != nil { - SetTestNeverallowRules(config, test.rules) - } - }), + PrepareForTestWithNeverallowRules(test.rules), test.fs.AddToFixture(), ). ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)). diff --git a/apex/apex_test.go b/apex/apex_test.go index a220a063c..98b40fd5b 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -22,6 +22,7 @@ import ( "reflect" "regexp" "sort" + "strconv" "strings" "testing" @@ -49,18 +50,28 @@ func names(s string) (ns []string) { func testApexError(t *testing.T, pattern, bp string, preparers ...android.FixturePreparer) { t.Helper() - apexFixtureFactory.Extend(preparers...). + android.GroupFixturePreparers( + prepareForApexTest, + android.GroupFixturePreparers(preparers...), + ). ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)). RunTestWithBp(t, bp) } func testApex(t *testing.T, bp string, preparers ...android.FixturePreparer) *android.TestContext { t.Helper() - factory := apexFixtureFactory.Extend(preparers...) + + optionalBpPreparer := android.NullFixturePreparer if bp != "" { - factory = factory.Extend(android.FixtureWithRootAndroidBp(bp)) + optionalBpPreparer = android.FixtureWithRootAndroidBp(bp) } - result := factory.RunTest(t) + + result := android.GroupFixturePreparers( + prepareForApexTest, + android.GroupFixturePreparers(preparers...), + optionalBpPreparer, + ).RunTest(t) + return result.TestContext } @@ -114,8 +125,16 @@ var withUnbundledBuild = android.FixtureModifyProductVariables( }, ) -var apexFixtureFactory = android.NewFixtureFactory( - nil, +// Legacy preparer used for running tests within the apex package. +// +// This includes everything that was needed to run any test in the apex package prior to the +// introduction of the test fixtures. Tests that are being converted to use fixtures directly +// rather than through the testApex...() methods should avoid using this and instead use the +// various preparers directly, using android.GroupFixturePreparers(...) to group them when +// necessary. +// +// deprecated +var prepareForApexTest = android.GroupFixturePreparers( // General preparers in alphabetical order as test infrastructure will enforce correct // registration order. android.PrepareForTestWithAndroidBuildComponents, @@ -801,7 +820,7 @@ func TestApexWithStubs(t *testing.T) { mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"] // Ensure that mylib is linking with the latest version of stubs for mylib2 - ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_3/mylib2.so") + ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_current/mylib2.so") // ... and not linking to the non-stub (impl) variant of mylib2 ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so") @@ -1279,15 +1298,15 @@ func TestApexDependsOnLLNDKTransitively(t *testing.T) { name: "unspecified version links to the latest", minSdkVersion: "", apexVariant: "apex10000", - shouldLink: "30", - shouldNotLink: []string{"29"}, + shouldLink: "current", + shouldNotLink: []string{"29", "30"}, }, { name: "always use the latest", minSdkVersion: "min_sdk_version: \"29\",", apexVariant: "apex29", - shouldLink: "30", - shouldNotLink: []string{"29"}, + shouldLink: "current", + shouldNotLink: []string{"29", "30"}, }, } for _, tc := range testcases { @@ -1354,7 +1373,11 @@ func TestApexDependsOnLLNDKTransitively(t *testing.T) { } mylibCFlags := ctx.ModuleForTests("mylib", "android_vendor.VER_arm64_armv8-a_static_"+tc.apexVariant).Rule("cc").Args["cFlags"] - ensureContains(t, mylibCFlags, "__LIBBAR_API__="+tc.shouldLink) + ver := tc.shouldLink + if tc.shouldLink == "current" { + ver = strconv.Itoa(android.FutureApiLevelInt) + } + ensureContains(t, mylibCFlags, "__LIBBAR_API__="+ver) }) } } @@ -1416,12 +1439,12 @@ func TestApexWithSystemLibsStubs(t *testing.T) { // For dependency to libc // Ensure that mylib is linking with the latest version of stubs - ensureContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_29/libc.so") + ensureContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_current/libc.so") // ... and not linking to the non-stub (impl) variant ensureNotContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared/libc.so") // ... Cflags from stub is correctly exported to mylib - ensureContains(t, mylibCFlags, "__LIBC_API__=29") - ensureContains(t, mylibSharedCFlags, "__LIBC_API__=29") + ensureContains(t, mylibCFlags, "__LIBC_API__=10000") + ensureContains(t, mylibSharedCFlags, "__LIBC_API__=10000") // For dependency to libm // Ensure that mylib is linking with the non-stub (impl) variant @@ -1527,12 +1550,14 @@ func TestApexMinSdkVersion_NativeModulesShouldBeBuiltAgainstStubs(t *testing.T) } // platform liba is linked to non-stub version expectLink("liba", "shared", "libz", "shared") - // liba in myapex is linked to #30 - expectLink("liba", "shared_apex29", "libz", "shared_30") + // liba in myapex is linked to current + expectLink("liba", "shared_apex29", "libz", "shared_current") + expectNoLink("liba", "shared_apex29", "libz", "shared_30") expectNoLink("liba", "shared_apex29", "libz", "shared_28") expectNoLink("liba", "shared_apex29", "libz", "shared") - // liba in otherapex is linked to #30 - expectLink("liba", "shared_apex30", "libz", "shared_30") + // liba in otherapex is linked to current + expectLink("liba", "shared_apex30", "libz", "shared_current") + expectNoLink("liba", "shared_apex30", "libz", "shared_30") expectNoLink("liba", "shared_apex30", "libz", "shared_28") expectNoLink("liba", "shared_apex30", "libz", "shared") } @@ -1583,7 +1608,8 @@ func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) { ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"] ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so") } - expectLink("libx", "shared_apex10000", "libz", "shared_R") + expectLink("libx", "shared_apex10000", "libz", "shared_current") + expectNoLink("libx", "shared_apex10000", "libz", "shared_R") expectNoLink("libx", "shared_apex10000", "libz", "shared_29") expectNoLink("libx", "shared_apex10000", "libz", "shared") } @@ -1629,8 +1655,9 @@ func TestApexMinSdkVersion_DefaultsToLatest(t *testing.T) { ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"] ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so") } - expectLink("libx", "shared_apex10000", "libz", "shared_2") + expectLink("libx", "shared_apex10000", "libz", "shared_current") expectNoLink("libx", "shared_apex10000", "libz", "shared_1") + expectNoLink("libx", "shared_apex10000", "libz", "shared_2") expectNoLink("libx", "shared_apex10000", "libz", "shared") } @@ -1677,7 +1704,8 @@ func TestPlatformUsesLatestStubsFromApexes(t *testing.T) { ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"] ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so") } - expectLink("libz", "shared", "libx", "shared_2") + expectLink("libz", "shared", "libx", "shared_current") + expectNoLink("libz", "shared", "libx", "shared_2") expectNoLink("libz", "shared", "libz", "shared_1") expectNoLink("libz", "shared", "libz", "shared") } @@ -1724,7 +1752,7 @@ func TestQApexesUseLatestStubsInBundledBuildsAndHWASAN(t *testing.T) { libFlags := ld.Args["libFlags"] ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so") } - expectLink("libx", "shared_hwasan_apex29", "libbar", "shared_30") + expectLink("libx", "shared_hwasan_apex29", "libbar", "shared_current") } func TestQTargetApexUsesStaticUnwinder(t *testing.T) { @@ -2106,7 +2134,7 @@ func TestApexMinSdkVersion_OkayEvenWhenDepIsNewer_IfItSatisfiesApexMinSdkVersion private_key: "testkey.pem", } - // mylib in myapex will link to mylib2#30 + // mylib in myapex will link to mylib2#current // mylib in otherapex will link to mylib2(non-stub) in otherapex as well cc_library { name: "mylib", @@ -2140,7 +2168,7 @@ func TestApexMinSdkVersion_OkayEvenWhenDepIsNewer_IfItSatisfiesApexMinSdkVersion libFlags := ld.Args["libFlags"] ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so") } - expectLink("mylib", "shared_apex29", "mylib2", "shared_30") + expectLink("mylib", "shared_apex29", "mylib2", "shared_current") expectLink("mylib", "shared_apex30", "mylib2", "shared_apex30") } @@ -2208,10 +2236,10 @@ func TestApexMinSdkVersion_WorksWithActiveCodenames(t *testing.T) { } `, withSAsActiveCodeNames) - // ensure libfoo is linked with "S" version of libbar stub + // ensure libfoo is linked with current version of libbar stub libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared_apex10000") libFlags := libfoo.Rule("ld").Args["libFlags"] - ensureContains(t, libFlags, "android_arm64_armv8-a_shared_T/libbar.so") + ensureContains(t, libFlags, "android_arm64_armv8-a_shared_current/libbar.so") } func TestFilesInSubDir(t *testing.T) { @@ -4513,14 +4541,11 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { if filepath.Base(output) == base { foundLibfooJar = true buildRule := s.Output(output) - actual := android.NormalizePathForTesting(buildRule.Input) - if actual != bootDexJarPath { - t.Errorf("Incorrect boot dex jar path '%s', expected '%s'", actual, bootDexJarPath) - } + android.AssertStringEquals(t, "boot dex jar path", bootDexJarPath, buildRule.Input.String()) } } if !foundLibfooJar { - t.Errorf("Rule for libfoo.jar missing in dex_bootjars singleton outputs") + t.Errorf("Rule for libfoo.jar missing in dex_bootjars singleton outputs %q", android.StringPathsRelativeToTop(ctx.Config().BuildDir(), s.AllOutputs())) } } @@ -4562,8 +4587,8 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { ` ctx := testDexpreoptWithApexes(t, bp, "", transform) - checkBootDexJarPath(t, ctx, "libfoo", ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") - checkBootDexJarPath(t, ctx, "libbar", ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar") + checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") + checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar") // Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file. checkHiddenAPIIndexInputs(t, ctx, ` @@ -4669,8 +4694,8 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { ` ctx := testDexpreoptWithApexes(t, bp, "", transform) - checkBootDexJarPath(t, ctx, "libfoo", ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") - checkBootDexJarPath(t, ctx, "libbar", ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar") + checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") + checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar") // Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file. checkHiddenAPIIndexInputs(t, ctx, ` @@ -4736,8 +4761,8 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { ` ctx := testDexpreoptWithApexes(t, bp, "", transform) - checkBootDexJarPath(t, ctx, "libfoo", ".intermediates/libfoo/android_common_apex10000/hiddenapi/libfoo.jar") - checkBootDexJarPath(t, ctx, "libbar", ".intermediates/libbar/android_common_myapex/hiddenapi/libbar.jar") + checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/libfoo/android_common_apex10000/hiddenapi/libfoo.jar") + checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/libbar/android_common_myapex/hiddenapi/libbar.jar") // Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file. checkHiddenAPIIndexInputs(t, ctx, ` @@ -4805,8 +4830,8 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { ` ctx := testDexpreoptWithApexes(t, bp, "", transform) - checkBootDexJarPath(t, ctx, "libfoo", ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") - checkBootDexJarPath(t, ctx, "libbar", ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar") + checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") + checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar") // Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file. checkHiddenAPIIndexInputs(t, ctx, ` @@ -5912,9 +5937,10 @@ func TestJavaSDKLibrary_ImportOnly(t *testing.T) { } func TestCompatConfig(t *testing.T) { - result := apexFixtureFactory. - Extend(java.PrepareForTestWithPlatformCompatConfig). - RunTestWithBp(t, ` + result := android.GroupFixturePreparers( + prepareForApexTest, + java.PrepareForTestWithPlatformCompatConfig, + ).RunTestWithBp(t, ` apex { name: "myapex", key: "myapex.key", @@ -6457,68 +6483,46 @@ func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, transformDexpre func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, transformDexpreoptConfig func(*dexpreopt.GlobalConfig)) *android.TestContext { t.Helper() - bp += cc.GatherRequiredDepsForTest(android.Android) - bp += java.GatherRequiredDepsForTest() - - fs := map[string][]byte{ - "a.java": nil, - "a.jar": nil, - "build/make/target/product/security": nil, - "apex_manifest.json": nil, - "AndroidManifest.xml": nil, + fs := android.MockFS{ + "a.java": nil, + "a.jar": nil, + "apex_manifest.json": nil, + "AndroidManifest.xml": nil, "system/sepolicy/apex/myapex-file_contexts": nil, "system/sepolicy/apex/some-updatable-apex-file_contexts": nil, "system/sepolicy/apex/some-non-updatable-apex-file_contexts": nil, "system/sepolicy/apex/com.android.art.debug-file_contexts": nil, "framework/aidl/a.aidl": nil, } - cc.GatherRequiredFilesForTest(fs) - for k, v := range filesForSdkLibrary { - fs[k] = v - } - config := android.TestArchConfig(t.TempDir(), nil, bp, fs) - - ctx := android.NewTestArchContext(config) - ctx.RegisterModuleType("apex", BundleFactory) - ctx.RegisterModuleType("apex_key", ApexKeyFactory) - ctx.RegisterModuleType("prebuilt_apex", PrebuiltFactory) - ctx.RegisterModuleType("filegroup", android.FileGroupFactory) - ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators) - ctx.PreArchMutators(android.RegisterComponentsMutator) - android.RegisterPrebuiltMutators(ctx) - cc.RegisterRequiredBuildComponentsForTest(ctx) - java.RegisterRequiredBuildComponentsForTest(ctx) - java.RegisterHiddenApiSingletonComponents(ctx) - ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators) - ctx.PreDepsMutators(RegisterPreDepsMutators) - ctx.PostDepsMutators(RegisterPostDepsMutators) - - ctx.Register() - - pathCtx := android.PathContextForTesting(config) - dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx) - transformDexpreoptConfig(dexpreoptConfig) - dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig) - - // Make sure that any changes to these dexpreopt properties are mirrored in the corresponding - // product variables. - config.TestProductVariables.BootJars = dexpreoptConfig.BootJars - config.TestProductVariables.UpdatableBootJars = dexpreoptConfig.UpdatableBootJars - - _, errs := ctx.ParseBlueprintsFiles("Android.bp") - android.FailIfErrored(t, errs) - - _, errs = ctx.PrepareBuildActions(config) - if errmsg == "" { - android.FailIfErrored(t, errs) - } else if len(errs) > 0 { - android.FailIfNoMatchingErrors(t, errmsg, errs) - } else { - t.Fatalf("missing expected error %q (0 errors are returned)", errmsg) + errorHandler := android.FixtureExpectsNoErrors + if errmsg != "" { + errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(errmsg) } - return ctx + result := android.GroupFixturePreparers( + cc.PrepareForTestWithCcDefaultModules, + java.PrepareForTestWithHiddenApiBuildComponents, + java.PrepareForTestWithJavaDefaultModules, + java.PrepareForTestWithJavaSdkLibraryFiles, + PrepareForTestWithApexBuildComponents, + android.FixtureModifyConfig(func(config android.Config) { + pathCtx := android.PathContextForTesting(config) + dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx) + transformDexpreoptConfig(dexpreoptConfig) + dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig) + + // Make sure that any changes to these dexpreopt properties are mirrored in the corresponding + // product variables. + config.TestProductVariables.BootJars = dexpreoptConfig.BootJars + config.TestProductVariables.UpdatableBootJars = dexpreoptConfig.UpdatableBootJars + }), + fs.AddToFixture(), + ). + ExtendWithErrorHandler(errorHandler). + RunTestWithBp(t, bp) + + return result.TestContext } func TestUpdatable_should_set_min_sdk_version(t *testing.T) { @@ -6692,45 +6696,33 @@ func testApexPermittedPackagesRules(t *testing.T, errmsg, bp string, apexBootJar public_key: "testkey.avbpubkey", private_key: "testkey.pem", }` - fs := map[string][]byte{ + fs := android.MockFS{ "lib1/src/A.java": nil, "lib2/src/B.java": nil, "system/sepolicy/apex/myapex-file_contexts": nil, } - config := android.TestArchConfig(t.TempDir(), nil, bp, fs) - android.SetTestNeverallowRules(config, rules) - updatableBootJars := make([]string, 0, len(apexBootJars)) - for _, apexBootJar := range apexBootJars { - updatableBootJars = append(updatableBootJars, "myapex:"+apexBootJar) - } - config.TestProductVariables.UpdatableBootJars = android.CreateTestConfiguredJarList(updatableBootJars) - - ctx := android.NewTestArchContext(config) - ctx.RegisterModuleType("apex", BundleFactory) - ctx.RegisterModuleType("apex_key", ApexKeyFactory) - ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators) - cc.RegisterRequiredBuildComponentsForTest(ctx) - java.RegisterRequiredBuildComponentsForTest(ctx) - ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators) - ctx.PreDepsMutators(RegisterPreDepsMutators) - ctx.PostDepsMutators(RegisterPostDepsMutators) - ctx.PostDepsMutators(android.RegisterNeverallowMutator) - - ctx.Register() - - _, errs := ctx.ParseBlueprintsFiles("Android.bp") - android.FailIfErrored(t, errs) - - _, errs = ctx.PrepareBuildActions(config) - if errmsg == "" { - android.FailIfErrored(t, errs) - } else if len(errs) > 0 { - android.FailIfNoMatchingErrors(t, errmsg, errs) - return - } else { - t.Fatalf("missing expected error %q (0 errors are returned)", errmsg) + errorHandler := android.FixtureExpectsNoErrors + if errmsg != "" { + errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(errmsg) } + + android.GroupFixturePreparers( + android.PrepareForTestWithAndroidBuildComponents, + java.PrepareForTestWithJavaBuildComponents, + PrepareForTestWithApexBuildComponents, + android.PrepareForTestWithNeverallowRules(rules), + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + updatableBootJars := make([]string, 0, len(apexBootJars)) + for _, apexBootJar := range apexBootJars { + updatableBootJars = append(updatableBootJars, "myapex:"+apexBootJar) + } + variables.UpdatableBootJars = android.CreateTestConfiguredJarList(updatableBootJars) + }), + fs.AddToFixture(), + ). + ExtendWithErrorHandler(errorHandler). + RunTestWithBp(t, bp) } func TestApexPermittedPackagesRules(t *testing.T) { @@ -7462,7 +7454,7 @@ func TestPrebuiltStubLibDep(t *testing.T) { t.Errorf("AndroidMk entry for \"stublib\" has LOCAL_NOT_AVAILABLE_FOR_PLATFORM set: %+v", entry.mkEntries) } cflags := entry.mkEntries.EntryMap["LOCAL_EXPORT_CFLAGS"] - expected := "-D__STUBLIB_API__=1" + expected := "-D__STUBLIB_API__=10000" if !android.InList(expected, cflags) { t.Errorf("LOCAL_EXPORT_CFLAGS expected to have %q, but got %q", expected, cflags) } diff --git a/cc/cc_test.go b/cc/cc_test.go index 19596c3f2..76e75daff 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -2672,9 +2672,11 @@ func TestLlndkLibrary(t *testing.T) { expected := []string{ "android_vendor.VER_arm64_armv8-a_shared_1", "android_vendor.VER_arm64_armv8-a_shared_2", + "android_vendor.VER_arm64_armv8-a_shared_current", "android_vendor.VER_arm64_armv8-a_shared", "android_vendor.VER_arm_armv7-a-neon_shared_1", "android_vendor.VER_arm_armv7-a-neon_shared_2", + "android_vendor.VER_arm_armv7-a-neon_shared_current", "android_vendor.VER_arm_armv7-a-neon_shared", } checkEquals(t, "variants for llndk stubs", expected, actual) @@ -3174,10 +3176,12 @@ func TestVersionedStubs(t *testing.T) { "android_arm64_armv8-a_shared_1", "android_arm64_armv8-a_shared_2", "android_arm64_armv8-a_shared_3", + "android_arm64_armv8-a_shared_current", "android_arm_armv7-a-neon_shared", "android_arm_armv7-a-neon_shared_1", "android_arm_armv7-a-neon_shared_2", "android_arm_armv7-a-neon_shared_3", + "android_arm_armv7-a-neon_shared_current", } variantsMismatch := false if len(variants) != len(expectedVariants) { diff --git a/cc/library.go b/cc/library.go index f459e80ff..091acfe08 100644 --- a/cc/library.go +++ b/cc/library.go @@ -65,7 +65,8 @@ type LibraryProperties struct { // symbols that are exported for stubs variant of this library. Symbol_file *string `android:"path"` - // List versions to generate stubs libs for. + // List versions to generate stubs libs for. The version name "current" is always + // implicitly added. Versions []string } @@ -171,6 +172,8 @@ type LibraryMutatedProperties struct { // This variant is a stubs lib BuildStubs bool `blueprint:"mutated"` + // This variant is the latest version + IsLatestVersion bool `blueprint:"mutated"` // Version of the stubs lib StubsVersion string `blueprint:"mutated"` // List of all stubs versions associated with an implementation lib @@ -775,7 +778,7 @@ type libraryInterface interface { type versionedInterface interface { buildStubs() bool - setBuildStubs() + setBuildStubs(isLatest bool) hasStubsVariants() bool setStubsVersion(string) stubsVersion() string @@ -1493,7 +1496,7 @@ func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) { if ctx.isVndk() && !ctx.IsVndkExt() { return } - } else if len(library.Properties.Stubs.Versions) > 0 && !ctx.Host() && ctx.directlyInAnyApex() { + } else if library.hasStubsVariants() && !ctx.Host() && ctx.directlyInAnyApex() { // Bionic libraries (e.g. libc.so) is installed to the bootstrap subdirectory. // The original path becomes a symlink to the corresponding file in the // runtime APEX. @@ -1609,11 +1612,29 @@ func (library *libraryDecorator) symbolFileForAbiCheck(ctx ModuleContext) *strin } func (library *libraryDecorator) hasStubsVariants() bool { - return len(library.Properties.Stubs.Versions) > 0 + // Just having stubs.symbol_file is enough to create a stub variant. In that case + // the stub for the future API level is created. + return library.Properties.Stubs.Symbol_file != nil || + len(library.Properties.Stubs.Versions) > 0 } func (library *libraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []string { - return library.Properties.Stubs.Versions + if !library.hasStubsVariants() { + return nil + } + + // Future API level is implicitly added if there isn't + vers := library.Properties.Stubs.Versions + if inList(android.FutureApiLevel.String(), vers) { + return vers + } + // In some cases, people use the raw value "10000" in the versions property. + // We shouldn't add the future API level in that case, otherwise there will + // be two identical versions. + if inList(strconv.Itoa(android.FutureApiLevel.FinalOrFutureInt()), vers) { + return vers + } + return append(vers, android.FutureApiLevel.String()) } func (library *libraryDecorator) setStubsVersion(version string) { @@ -1624,8 +1645,9 @@ func (library *libraryDecorator) stubsVersion() string { return library.MutatedProperties.StubsVersion } -func (library *libraryDecorator) setBuildStubs() { +func (library *libraryDecorator) setBuildStubs(isLatest bool) { library.MutatedProperties.BuildStubs = true + library.MutatedProperties.IsLatestVersion = isLatest } func (library *libraryDecorator) setAllStubsVersions(versions []string) { @@ -1637,8 +1659,7 @@ func (library *libraryDecorator) allStubsVersions() []string { } func (library *libraryDecorator) isLatestStubVersion() bool { - versions := library.Properties.Stubs.Versions - return versions[len(versions)-1] == library.stubsVersion() + return library.MutatedProperties.IsLatestVersion } func (library *libraryDecorator) availableFor(what string) bool { @@ -1881,7 +1902,8 @@ func createVersionVariations(mctx android.BottomUpMutatorContext, versions []str c.stl = nil c.Properties.PreventInstall = true lib := moduleLibraryInterface(m) - lib.setBuildStubs() + isLatest := i == (len(versions) - 1) + lib.setBuildStubs(isLatest) if variants[i] != "" { // A non-LLNDK stubs module is hidden from make and has a dependency from the diff --git a/cc/linker.go b/cc/linker.go index 6d0d4160b..21281d2ce 100644 --- a/cc/linker.go +++ b/cc/linker.go @@ -599,21 +599,20 @@ var ( _ = pctx.SourcePathVariable("genSortedBssSymbolsPath", "build/soong/scripts/gen_sorted_bss_symbols.sh") genSortedBssSymbols = pctx.AndroidStaticRule("gen_sorted_bss_symbols", blueprint.RuleParams{ - Command: "CROSS_COMPILE=$crossCompile $genSortedBssSymbolsPath ${in} ${out}", - CommandDeps: []string{"$genSortedBssSymbolsPath", "${crossCompile}nm"}, + Command: "CLANG_BIN=${clangBin} $genSortedBssSymbolsPath ${in} ${out}", + CommandDeps: []string{"$genSortedBssSymbolsPath", "${clangBin}/llvm-nm"}, }, - "crossCompile") + "clangBin") ) func (linker *baseLinker) sortBssSymbolsBySize(ctx ModuleContext, in android.Path, symbolOrderingFile android.ModuleOutPath, flags builderFlags) string { - crossCompile := gccCmd(flags.toolchain, "") ctx.Build(pctx, android.BuildParams{ Rule: genSortedBssSymbols, Description: "generate bss symbol order " + symbolOrderingFile.Base(), Output: symbolOrderingFile, Input: in, Args: map[string]string{ - "crossCompile": crossCompile, + "clangBin": "${config.ClangBin}", }, }) return "-Wl,--symbol-ordering-file," + symbolOrderingFile.String() diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go index fcc80a94e..7bd086882 100644 --- a/cmd/sbox/sbox.go +++ b/cmd/sbox/sbox.go @@ -387,6 +387,14 @@ func copyOneFile(from string, to string, executable bool) error { } defer in.Close() + // Remove the target before copying. In most cases the file won't exist, but if there are + // duplicate copy rules for a file and the source file was read-only the second copy could + // fail. + err = os.Remove(to) + if err != nil && !os.IsNotExist(err) { + return err + } + out, err := os.Create(to) if err != nil { return err diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go index e2fc78cef..3abf9783e 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -24,7 +24,6 @@ import ( "time" "android/soong/shared" - "github.com/google/blueprint/bootstrap" "android/soong/android" @@ -65,16 +64,10 @@ func newNameResolver(config android.Config) *android.NameResolver { return android.NewNameResolver(exportFilter) } -// bazelConversionRequested checks that the user is intending to convert -// Blueprint to Bazel BUILD files. -func bazelConversionRequested(configuration android.Config) bool { - return configuration.IsEnvTrue("GENERATE_BAZEL_FILES") -} - -func newContext(configuration android.Config) *android.Context { +func newContext(configuration android.Config, prepareBuildActions bool) *android.Context { ctx := android.NewContext(configuration) ctx.Register() - if !shouldPrepareBuildActions(configuration) { + if !prepareBuildActions { configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions) } ctx.SetNameInterface(newNameResolver(configuration)) @@ -91,6 +84,84 @@ func newConfig(srcDir string) android.Config { return configuration } +// Bazel-enabled mode. Soong runs in two passes. +// First pass: Analyze the build tree, but only store all bazel commands +// needed to correctly evaluate the tree in the second pass. +// TODO(cparsons): Don't output any ninja file, as the second pass will overwrite +// the incorrect results from the first pass, and file I/O is expensive. +func runMixedModeBuild(configuration android.Config, firstCtx *android.Context, extraNinjaDeps []string) { + configuration.SetStopBefore(bootstrap.StopBeforeWriteNinja) + bootstrap.Main(firstCtx.Context, configuration, false, extraNinjaDeps...) + // Invoke bazel commands and save results for second pass. + if err := configuration.BazelContext.InvokeBazel(); err != nil { + fmt.Fprintf(os.Stderr, "%s", err) + os.Exit(1) + } + // Second pass: Full analysis, using the bazel command results. Output ninja file. + secondPassConfig, err := android.ConfigForAdditionalRun(configuration) + if err != nil { + fmt.Fprintf(os.Stderr, "%s", err) + os.Exit(1) + } + secondCtx := newContext(secondPassConfig, true) + bootstrap.Main(secondCtx.Context, secondPassConfig, false, extraNinjaDeps...) +} + +// Run the code-generation phase to convert BazelTargetModules to BUILD files. +func runQueryView(configuration android.Config, ctx *android.Context) { + codegenContext := bp2build.NewCodegenContext(configuration, *ctx, bp2build.QueryView) + absoluteQueryViewDir := shared.JoinPath(topDir, bazelQueryViewDir) + if err := createBazelQueryView(codegenContext, absoluteQueryViewDir); err != nil { + fmt.Fprintf(os.Stderr, "%s", err) + os.Exit(1) + } +} + +func runSoongDocs(configuration android.Config, extraNinjaDeps []string) { + ctx := newContext(configuration, false) + bootstrap.Main(ctx.Context, configuration, false, extraNinjaDeps...) + if err := writeDocs(ctx, configuration, docFile); err != nil { + fmt.Fprintf(os.Stderr, "%s", err) + os.Exit(1) + } +} + +func writeMetrics(configuration android.Config) { + metricsFile := filepath.Join(bootstrap.CmdlineBuildDir(), "soong_build_metrics.pb") + err := android.WriteMetrics(configuration, metricsFile) + if err != nil { + fmt.Fprintf(os.Stderr, "error writing soong_build metrics %s: %s", metricsFile, err) + os.Exit(1) + } +} + +func doChosenActivity(configuration android.Config, extraNinjaDeps []string) { + bazelConversionRequested := configuration.IsEnvTrue("GENERATE_BAZEL_FILES") + mixedModeBuild := configuration.BazelContext.BazelEnabled() + generateQueryView := bazelQueryViewDir != "" + + if bazelConversionRequested { + // Run the alternate pipeline of bp2build mutators and singleton to convert + // Blueprint to BUILD files before everything else. + runBp2Build(configuration, extraNinjaDeps) + return + } + + ctx := newContext(configuration, !generateQueryView) + if mixedModeBuild { + runMixedModeBuild(configuration, ctx, extraNinjaDeps) + } else { + bootstrap.Main(ctx.Context, configuration, false, extraNinjaDeps...) + } + + // Convert the Soong module graph into Bazel BUILD files. + if generateQueryView { + runQueryView(configuration, ctx) + return + } + writeMetrics(configuration) +} + func main() { flag.Parse() @@ -101,7 +172,6 @@ func main() { usedVariablesFile := shared.JoinPath(outDir, "soong.environment.used") // The top-level Blueprints file is passed as the first argument. srcDir := filepath.Dir(flag.Arg(0)) - var ctx *android.Context configuration := newConfig(srcDir) extraNinjaDeps := []string{ configuration.ProductVariablesFileName, @@ -122,72 +192,17 @@ func main() { extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.BuildDir(), "always_rerun_for_delve")) } - bazelConversionRequested := bazelConversionRequested(configuration) - if bazelConversionRequested { - // Run the alternate pipeline of bp2build mutators and singleton to convert Blueprint to BUILD files - // before everything else. - runBp2Build(srcDir, configuration, extraNinjaDeps) - } else if configuration.BazelContext.BazelEnabled() { - // Bazel-enabled mode. Soong runs in two passes. - // First pass: Analyze the build tree, but only store all bazel commands - // needed to correctly evaluate the tree in the second pass. - // TODO(cparsons): Don't output any ninja file, as the second pass will overwrite - // the incorrect results from the first pass, and file I/O is expensive. - firstCtx := newContext(configuration) - configuration.SetStopBefore(bootstrap.StopBeforeWriteNinja) - bootstrap.Main(firstCtx.Context, configuration, false, extraNinjaDeps...) - // Invoke bazel commands and save results for second pass. - if err := configuration.BazelContext.InvokeBazel(); err != nil { - fmt.Fprintf(os.Stderr, "%s", err) - os.Exit(1) - } - // Second pass: Full analysis, using the bazel command results. Output ninja file. - secondPassConfig, err := android.ConfigForAdditionalRun(configuration) - if err != nil { - fmt.Fprintf(os.Stderr, "%s", err) - os.Exit(1) - } - ctx = newContext(secondPassConfig) - bootstrap.Main(ctx.Context, secondPassConfig, false, extraNinjaDeps...) - } else { - ctx = newContext(configuration) - bootstrap.Main(ctx.Context, configuration, false, extraNinjaDeps...) - } - - // Convert the Soong module graph into Bazel BUILD files. - if !bazelConversionRequested && bazelQueryViewDir != "" { - // Run the code-generation phase to convert BazelTargetModules to BUILD files. - codegenContext := bp2build.NewCodegenContext(configuration, *ctx, bp2build.QueryView) - absoluteQueryViewDir := shared.JoinPath(topDir, bazelQueryViewDir) - if err := createBazelQueryView(codegenContext, absoluteQueryViewDir); err != nil { - fmt.Fprintf(os.Stderr, "%s", err) - os.Exit(1) - } - } - - if !bazelConversionRequested && docFile != "" { - if err := writeDocs(ctx, configuration, docFile); err != nil { - fmt.Fprintf(os.Stderr, "%s", err) - os.Exit(1) - } - } - - // TODO(ccross): make this a command line argument. Requires plumbing through blueprint - // to affect the command line of the primary builder. - if !bazelConversionRequested && shouldPrepareBuildActions(configuration) { - metricsFile := filepath.Join(bootstrap.CmdlineBuildDir(), "soong_build_metrics.pb") - err := android.WriteMetrics(configuration, metricsFile) - if err != nil { - fmt.Fprintf(os.Stderr, "error writing soong_build metrics %s: %s", metricsFile, err) - os.Exit(1) - } + if docFile != "" { + // We don't write an used variables file when generating documentation + // because that is done from within the actual builds as a Ninja action and + // thus it would overwrite the actual used variables file so this is + // special-cased. + runSoongDocs(configuration, extraNinjaDeps) + return } - if docFile == "" { - // Let's not overwrite the used variables file when generating - // documentation - writeUsedVariablesFile(shared.JoinPath(topDir, usedVariablesFile), configuration) - } + doChosenActivity(configuration, extraNinjaDeps) + writeUsedVariablesFile(shared.JoinPath(topDir, usedVariablesFile), configuration) } func writeUsedVariablesFile(path string, configuration android.Config) { @@ -218,7 +233,7 @@ func writeUsedVariablesFile(path string, configuration android.Config) { // Run Soong in the bp2build mode. This creates a standalone context that registers // an alternate pipeline of mutators and singletons specifically for generating // Bazel BUILD files instead of Ninja files. -func runBp2Build(srcDir string, configuration android.Config, extraNinjaDeps []string) { +func runBp2Build(configuration android.Config, extraNinjaDeps []string) { // Register an alternate set of singletons and mutators for bazel // conversion for Bazel conversion. bp2buildCtx := android.NewContext(configuration) @@ -233,7 +248,7 @@ func runBp2Build(srcDir string, configuration android.Config, extraNinjaDeps []s // configurations or variables, since those will generate different BUILD // files based on how the user has configured their tree. bp2buildCtx.SetModuleListFile(bootstrap.CmdlineModuleListFile()) - modulePaths, err := bp2buildCtx.ListModulePaths(srcDir) + modulePaths, err := bp2buildCtx.ListModulePaths(configuration.SrcDir()) if err != nil { panic(err) } @@ -283,20 +298,3 @@ func runBp2Build(srcDir string, configuration android.Config, extraNinjaDeps []s []byte(fmt.Sprintf("%s: \\\n %s\n", ninjaFileName, extraNinjaDepsString)), 0666) } - -// shouldPrepareBuildActions reads configuration and flags if build actions -// should be generated. -func shouldPrepareBuildActions(configuration android.Config) bool { - // Generating Soong docs - if docFile != "" { - return false - } - - // Generating a directory for Soong query (queryview) - if bazelQueryViewDir != "" { - return false - } - - // Generating a directory for converted Bazel BUILD files - return !bazelConversionRequested(configuration) -} diff --git a/filesystem/logical_partition.go b/filesystem/logical_partition.go index 20d9622dc..dbbc1d88a 100644 --- a/filesystem/logical_partition.go +++ b/filesystem/logical_partition.go @@ -43,6 +43,10 @@ type logicalPartitionProperties struct { // Total size of the logical partition Size *string + // List of partitions for default group. Default group has no size limit and automatically + // minimized when creating an image. + Default_group []partitionProperties + // List of groups. A group defines a fixed sized region. It can host one or more logical // partitions and their total size is limited by the size of the group they are in. Groups []groupProperties @@ -52,7 +56,7 @@ type logicalPartitionProperties struct { } type groupProperties struct { - // Name of the partition group + // Name of the partition group. Can't be "default"; use default_group instead. Name *string // Size of the partition group @@ -92,8 +96,9 @@ func (l *logicalPartition) GenerateAndroidBuildActions(ctx android.ModuleContext // Sparse the filesystem images and calculate their sizes sparseImages := make(map[string]android.OutputPath) sparseImageSizes := make(map[string]android.OutputPath) - for _, group := range l.properties.Groups { - for _, part := range group.Partitions { + + sparsePartitions := func(partitions []partitionProperties) { + for _, part := range partitions { sparseImg, sizeTxt := sparseFilesystem(ctx, part, builder) pName := proptools.String(part.Name) sparseImages[pName] = sparseImg @@ -101,6 +106,12 @@ func (l *logicalPartition) GenerateAndroidBuildActions(ctx android.ModuleContext } } + for _, group := range l.properties.Groups { + sparsePartitions(group.Partitions) + } + + sparsePartitions(l.properties.Default_group) + cmd := builder.Command().BuiltTool("lpmake") size := proptools.String(l.properties.Size) @@ -123,10 +134,32 @@ func (l *logicalPartition) GenerateAndroidBuildActions(ctx android.ModuleContext groupNames := make(map[string]bool) partitionNames := make(map[string]bool) + addPartitionsToGroup := func(partitions []partitionProperties, gName string) { + for _, part := range partitions { + pName := proptools.String(part.Name) + if pName == "" { + ctx.PropertyErrorf("groups.partitions.name", "must be set") + } + if _, ok := partitionNames[pName]; ok { + ctx.PropertyErrorf("groups.partitions.name", "already exists") + } else { + partitionNames[pName] = true + } + // Get size of the partition by reading the -size.txt file + pSize := fmt.Sprintf("$(cat %s)", sparseImageSizes[pName]) + cmd.FlagWithArg("--partition=", fmt.Sprintf("%s:readonly:%s:%s", pName, pSize, gName)) + cmd.FlagWithInput("--image="+pName+"=", sparseImages[pName]) + } + } + + addPartitionsToGroup(l.properties.Default_group, "default") + for _, group := range l.properties.Groups { gName := proptools.String(group.Name) if gName == "" { ctx.PropertyErrorf("groups.name", "must be set") + } else if gName == "default" { + ctx.PropertyErrorf("groups.name", `can't use "default" as a group name. Use default_group instead`) } if _, ok := groupNames[gName]; ok { ctx.PropertyErrorf("group.name", "already exists") @@ -142,21 +175,7 @@ func (l *logicalPartition) GenerateAndroidBuildActions(ctx android.ModuleContext } cmd.FlagWithArg("--group=", gName+":"+gSize) - for _, part := range group.Partitions { - pName := proptools.String(part.Name) - if pName == "" { - ctx.PropertyErrorf("groups.partitions.name", "must be set") - } - if _, ok := partitionNames[pName]; ok { - ctx.PropertyErrorf("groups.partitions.name", "already exists") - } else { - partitionNames[pName] = true - } - // Get size of the partition by reading the -size.txt file - pSize := fmt.Sprintf("$(cat %s)", sparseImageSizes[pName]) - cmd.FlagWithArg("--partition=", fmt.Sprintf("%s:readonly:%s:%s", pName, pSize, gName)) - cmd.FlagWithInput("--image="+pName+"=", sparseImages[pName]) - } + addPartitionsToGroup(group.Partitions, gName) } l.output = android.PathForModuleOut(ctx, l.installFileName()).OutputPath diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go index 2ee456d56..3f1e9f3b9 100644 --- a/genrule/genrule_test.go +++ b/genrule/genrule_test.go @@ -670,7 +670,8 @@ func TestGenruleAllowMissingDependencies(t *testing.T) { cmd: "cat $(in) > $(out)", } ` - result := prepareForGenRuleTest.Extend( + result := android.GroupFixturePreparers( + prepareForGenRuleTest, android.FixtureModifyConfigAndContext( func(config android.Config, ctx *android.TestContext) { config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true) diff --git a/java/Android.bp b/java/Android.bp index b6c14ac37..8334b85ec 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -50,6 +50,7 @@ bootstrap_go_package { "kotlin.go", "lint.go", "legacy_core_platform_api_usage.go", + "platform_bootclasspath.go", "platform_compat_config.go", "plugin.go", "prebuilt_apis.go", @@ -79,6 +80,7 @@ bootstrap_go_package { "java_test.go", "jdeps_test.go", "kotlin_test.go", + "platform_bootclasspath_test.go", "platform_compat_config_test.go", "plugin_test.go", "rro_test.go", diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go index dc4e8aaff..5c449e506 100644 --- a/java/hiddenapi_singleton_test.go +++ b/java/hiddenapi_singleton_test.go @@ -39,7 +39,8 @@ var hiddenApiFixtureFactory = android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithHiddenApiBuildComponents) func TestHiddenAPISingleton(t *testing.T) { - result := hiddenApiFixtureFactory.Extend( + result := android.GroupFixturePreparers( + hiddenApiFixtureFactory, fixtureSetBootJarsProductVariable("platform:foo"), ).RunTestWithBp(t, ` java_library { @@ -56,7 +57,8 @@ func TestHiddenAPISingleton(t *testing.T) { } func TestHiddenAPIIndexSingleton(t *testing.T) { - result := hiddenApiFixtureFactory.Extend( + result := android.GroupFixturePreparers( + hiddenApiFixtureFactory, PrepareForTestWithJavaSdkLibraryFiles, FixtureWithLastReleaseApis("bar"), fixtureSetBootJarsProductVariable("platform:foo", "platform:bar"), @@ -115,7 +117,8 @@ func TestHiddenAPISingletonWithSourceAndPrebuiltPreferredButNoDex(t *testing.T) " replaced by the prebuilt module \"prebuilt_foo\" but unfortunately it does not provide a" + " suitable boot dex jar" - hiddenApiFixtureFactory.Extend( + android.GroupFixturePreparers( + hiddenApiFixtureFactory, fixtureSetBootJarsProductVariable("platform:foo"), ).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(expectedErrorMessage)). RunTestWithBp(t, ` @@ -134,7 +137,8 @@ func TestHiddenAPISingletonWithSourceAndPrebuiltPreferredButNoDex(t *testing.T) } func TestHiddenAPISingletonWithPrebuilt(t *testing.T) { - result := hiddenApiFixtureFactory.Extend( + result := android.GroupFixturePreparers( + hiddenApiFixtureFactory, fixtureSetBootJarsProductVariable("platform:foo"), ).RunTestWithBp(t, ` java_import { @@ -151,7 +155,8 @@ func TestHiddenAPISingletonWithPrebuilt(t *testing.T) { } func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) { - result := hiddenApiFixtureFactory.Extend( + result := android.GroupFixturePreparers( + hiddenApiFixtureFactory, fixtureSetBootJarsProductVariable("platform:foo"), ).RunTestWithBp(t, ` java_library { @@ -178,7 +183,8 @@ func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) { } func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) { - result := hiddenApiFixtureFactory.Extend( + result := android.GroupFixturePreparers( + hiddenApiFixtureFactory, fixtureSetBootJarsProductVariable("platform:foo"), ).RunTestWithBp(t, ` java_library { @@ -236,7 +242,8 @@ func TestHiddenAPISingletonSdks(t *testing.T) { } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - result := hiddenApiFixtureFactory.Extend( + result := android.GroupFixturePreparers( + hiddenApiFixtureFactory, tc.preparer, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { variables.Always_use_prebuilt_sdks = proptools.BoolPtr(tc.unbundledBuild) @@ -286,7 +293,8 @@ func TestHiddenAPISingletonWithPrebuiltCsvFile(t *testing.T) { // Where to find the prebuilt hiddenapi files: prebuiltHiddenApiDir := "path/to/prebuilt/hiddenapi" - result := hiddenApiFixtureFactory.Extend( + result := android.GroupFixturePreparers( + hiddenApiFixtureFactory, fixtureSetBootJarsProductVariable("platform:foo"), fixtureSetPrebuiltHiddenApiDirProductVariable(&prebuiltHiddenApiDir), ).RunTestWithBp(t, ` diff --git a/java/java.go b/java/java.go index a7fbed2cb..26e5091b6 100644 --- a/java/java.go +++ b/java/java.go @@ -33,12 +33,12 @@ import ( ) func init() { - RegisterJavaBuildComponents(android.InitRegistrationContext) + registerJavaBuildComponents(android.InitRegistrationContext) RegisterJavaSdkMemberTypes() } -func RegisterJavaBuildComponents(ctx android.RegistrationContext) { +func registerJavaBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("java_defaults", DefaultsFactory) ctx.RegisterModuleType("java_library", LibraryFactory) diff --git a/java/java_test.go b/java/java_test.go index 3aafdda75..fdf757902 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -74,23 +74,6 @@ func testJavaError(t *testing.T, pattern string, bp string) (*android.TestContex return result.TestContext, result.Config } -// testJavaErrorWithConfig is a legacy way of running tests of java modules that expect errors. -// -// See testJava for an explanation as to how to stop using this deprecated method. -// -// deprecated -func testJavaErrorWithConfig(t *testing.T, pattern string, config android.Config) (*android.TestContext, android.Config) { - t.Helper() - // This must be done on the supplied config and not as part of the fixture because any changes to - // the fixture's config will be ignored when RunTestWithConfig replaces it. - pathCtx := android.PathContextForTesting(config) - dexpreopt.SetTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx)) - result := prepareForJavaTest. - ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)). - RunTestWithConfig(t, config) - return result.TestContext, result.Config -} - // testJavaWithFS runs tests using the prepareForJavaTest // // See testJava for an explanation as to how to stop using this deprecated method. diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go new file mode 100644 index 000000000..550707754 --- /dev/null +++ b/java/platform_bootclasspath.go @@ -0,0 +1,74 @@ +// Copyright 2021 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package java + +import ( + "android/soong/android" + "android/soong/dexpreopt" +) + +func init() { + registerPlatformBootclasspathBuildComponents(android.InitRegistrationContext) +} + +func registerPlatformBootclasspathBuildComponents(ctx android.RegistrationContext) { + ctx.RegisterModuleType("platform_bootclasspath", platformBootclasspathFactory) +} + +type platformBootclasspathModule struct { + android.ModuleBase +} + +func platformBootclasspathFactory() android.Module { + m := &platformBootclasspathModule{} + android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) + return m +} + +func (b *platformBootclasspathModule) DepsMutator(ctx android.BottomUpMutatorContext) { + if SkipDexpreoptBootJars(ctx) { + return + } + + // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The + // path is retrieved from the dependency by GetGlobalSoongConfig(ctx). + dexpreopt.RegisterToolDeps(ctx) +} + +func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { + // Nothing to do if skipping the dexpreopt of boot image jars. + if SkipDexpreoptBootJars(ctx) { + return + } + + // Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars + // GenerateSingletonBuildActions method as it cannot create it for itself. + dexpreopt.GetGlobalSoongConfig(ctx) + + imageConfig := b.getImageConfig(ctx) + if imageConfig == nil { + return + } + + // Construct the boot image info from the config. + info := BootImageInfo{imageConfig: imageConfig} + + // Make it available for other modules. + ctx.SetProvider(BootImageInfoProvider, info) +} + +func (b *platformBootclasspathModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig { + return defaultBootImageConfig(ctx) +} diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go new file mode 100644 index 000000000..1c81cfdc2 --- /dev/null +++ b/java/platform_bootclasspath_test.go @@ -0,0 +1,38 @@ +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package java + +import ( + "testing" + + "android/soong/android" + "android/soong/dexpreopt" +) + +// Contains some simple tests for platform_bootclasspath. + +var prepareForTestWithPlatformBootclasspath = android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + dexpreopt.PrepareForTestByEnablingDexpreopt, +) + +func TestPlatformBootclasspath(t *testing.T) { + prepareForTestWithPlatformBootclasspath. + RunTestWithBp(t, ` + platform_bootclasspath { + name: "platform-bootclasspath", + } + `) +} diff --git a/java/sdk_test.go b/java/sdk_test.go index e1ec41bdc..2b1846592 100644 --- a/java/sdk_test.go +++ b/java/sdk_test.go @@ -402,14 +402,16 @@ func TestClasspath(t *testing.T) { // Test again with PLATFORM_VERSION_CODENAME=REL, javac -source 8 -target 8 t.Run("REL + Java language level 8", func(t *testing.T) { - result := fixtureFactory.Extend(prepareWithPlatformVersionRel).RunTestWithBp(t, bpJava8) + result := android.GroupFixturePreparers( + fixtureFactory, prepareWithPlatformVersionRel).RunTestWithBp(t, bpJava8) checkClasspath(t, result, true /* isJava8 */) }) // Test again with PLATFORM_VERSION_CODENAME=REL, javac -source 9 -target 9 t.Run("REL + Java language level 9", func(t *testing.T) { - result := fixtureFactory.Extend(prepareWithPlatformVersionRel).RunTestWithBp(t, bp) + result := android.GroupFixturePreparers( + fixtureFactory, prepareWithPlatformVersionRel).RunTestWithBp(t, bp) checkClasspath(t, result, false /* isJava8 */) }) diff --git a/java/testing.go b/java/testing.go index 221ceb118..80c107d12 100644 --- a/java/testing.go +++ b/java/testing.go @@ -160,28 +160,6 @@ func FixtureWithPrebuiltApis(release2Modules map[string][]string) android.Fixtur ) } -func TestConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) android.Config { - bp += GatherRequiredDepsForTest() - - mockFS := android.MockFS{} - - cc.GatherRequiredFilesForTest(mockFS) - - for k, v := range fs { - mockFS[k] = v - } - - if env == nil { - env = make(map[string]string) - } - if env["ANDROID_JAVA8_HOME"] == "" { - env["ANDROID_JAVA8_HOME"] = "jdk8" - } - config := android.TestArchConfig(buildDir, env, bp, mockFS) - - return config -} - func prebuiltApisFilesForLibs(apiLevels []string, sdkLibs []string) map[string][]byte { fs := make(map[string][]byte) for _, level := range apiLevels { @@ -200,19 +178,6 @@ func prebuiltApisFilesForLibs(apiLevels []string, sdkLibs []string) map[string][ return fs } -// Register build components provided by this package that are needed by tests. -// -// In particular this must register all the components that are used in the `Android.bp` snippet -// returned by GatherRequiredDepsForTest() -// -// deprecated: Use test fixtures instead, e.g. PrepareForTestWithJavaBuildComponents -func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) { - registerRequiredBuildComponentsForTest(ctx) - - // Make sure that any tool related module types needed by dexpreopt have been registered. - dexpreopt.RegisterToolModulesForTest(ctx) -} - // registerRequiredBuildComponentsForTest registers the build components used by // PrepareForTestWithJavaDefaultModules. // @@ -228,7 +193,8 @@ func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) { RegisterDexpreoptBootJarsComponents(ctx) RegisterDocsBuildComponents(ctx) RegisterGenRuleBuildComponents(ctx) - RegisterJavaBuildComponents(ctx) + registerJavaBuildComponents(ctx) + registerPlatformBootclasspathBuildComponents(ctx) RegisterPrebuiltApisBuildComponents(ctx) RegisterRuntimeResourceOverlayBuildComponents(ctx) RegisterSdkLibraryBuildComponents(ctx) @@ -236,23 +202,6 @@ func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) { RegisterSystemModulesBuildComponents(ctx) } -// Gather the module definitions needed by tests that depend upon code from this package. -// -// Returns an `Android.bp` snippet that defines the modules that are needed by this package. -// -// deprecated: Use test fixtures instead, e.g. PrepareForTestWithJavaDefaultModules -func GatherRequiredDepsForTest() string { - bp := gatherRequiredDepsForTest() - - // For class loader context and <uses-library> tests. - bp += dexpreopt.CompatLibDefinitionsForTest() - - // Make sure that any tools needed for dexpreopting are defined. - bp += dexpreopt.BpToolModulesForTest() - - return bp -} - // gatherRequiredDepsForTest gathers the module definitions used by // PrepareForTestWithJavaDefaultModules. // diff --git a/rust/clippy_test.go b/rust/clippy_test.go index e90564f63..bd3bfb151 100644 --- a/rust/clippy_test.go +++ b/rust/clippy_test.go @@ -18,7 +18,6 @@ import ( "testing" "android/soong/android" - "android/soong/cc" ) func TestClippy(t *testing.T) { @@ -45,15 +44,6 @@ func TestClippy(t *testing.T) { clippy_lints: "none", }` - bp = bp + GatherRequiredDepsForTest() - bp = bp + cc.GatherRequiredDepsForTest(android.NoOsType) - - fs := map[string][]byte{ - // Reuse the same blueprint file for subdirectories. - "external/Android.bp": []byte(bp), - "hardware/Android.bp": []byte(bp), - } - var clippyLintTests = []struct { modulePath string fooFlags string @@ -66,29 +56,22 @@ func TestClippy(t *testing.T) { for _, tc := range clippyLintTests { t.Run("path="+tc.modulePath, func(t *testing.T) { - config := android.TestArchConfig(t.TempDir(), nil, bp, fs) - ctx := CreateTestContext(config) - ctx.Register() - _, errs := ctx.ParseFileList(".", []string{tc.modulePath + "Android.bp"}) - android.FailIfErrored(t, errs) - _, errs = ctx.PrepareBuildActions(config) - android.FailIfErrored(t, errs) + result := android.GroupFixturePreparers( + prepareForRustTest, + // Test with the blueprint file in different directories. + android.FixtureAddTextFile(tc.modulePath+"Android.bp", bp), + ).RunTest(t) - r := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("clippy") - if r.Args["clippyFlags"] != tc.fooFlags { - t.Errorf("Incorrect flags for libfoo: %q, want %q", r.Args["clippyFlags"], tc.fooFlags) - } + r := result.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("clippy") + android.AssertStringEquals(t, "libfoo flags", tc.fooFlags, r.Args["clippyFlags"]) - r = ctx.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("clippy") - if r.Args["clippyFlags"] != "${config.ClippyDefaultLints}" { - t.Errorf("Incorrect flags for libbar: %q, want %q", r.Args["clippyFlags"], "${config.ClippyDefaultLints}") - } + r = result.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("clippy") + android.AssertStringEquals(t, "libbar flags", "${config.ClippyDefaultLints}", r.Args["clippyFlags"]) - r = ctx.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("clippy") + r = result.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("clippy") if r.Rule != nil { t.Errorf("libfoobar is setup to use clippy when explicitly disabled: clippyFlags=%q", r.Args["clippyFlags"]) } - }) } } diff --git a/rust/compiler_test.go b/rust/compiler_test.go index 3ed086f20..c75276239 100644 --- a/rust/compiler_test.go +++ b/rust/compiler_test.go @@ -19,7 +19,6 @@ import ( "testing" "android/soong/android" - "android/soong/cc" ) // Test that feature flags are being correctly generated. @@ -132,15 +131,6 @@ func TestLints(t *testing.T) { lints: "none", }` - bp = bp + GatherRequiredDepsForTest() - bp = bp + cc.GatherRequiredDepsForTest(android.NoOsType) - - fs := map[string][]byte{ - // Reuse the same blueprint file for subdirectories. - "external/Android.bp": []byte(bp), - "hardware/Android.bp": []byte(bp), - } - var lintTests = []struct { modulePath string fooFlags string @@ -153,29 +143,20 @@ func TestLints(t *testing.T) { for _, tc := range lintTests { t.Run("path="+tc.modulePath, func(t *testing.T) { - config := android.TestArchConfig(t.TempDir(), nil, bp, fs) - ctx := CreateTestContext(config) - ctx.Register() - _, errs := ctx.ParseFileList(".", []string{tc.modulePath + "Android.bp"}) - android.FailIfErrored(t, errs) - _, errs = ctx.PrepareBuildActions(config) - android.FailIfErrored(t, errs) - - r := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("rustc") - if !strings.Contains(r.Args["rustcFlags"], tc.fooFlags) { - t.Errorf("Incorrect flags for libfoo: %q, want %q", r.Args["rustcFlags"], tc.fooFlags) - } - - r = ctx.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("rustc") - if !strings.Contains(r.Args["rustcFlags"], "${config.RustDefaultLints}") { - t.Errorf("Incorrect flags for libbar: %q, want %q", r.Args["rustcFlags"], "${config.RustDefaultLints}") - } - - r = ctx.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("rustc") - if !strings.Contains(r.Args["rustcFlags"], "${config.RustAllowAllLints}") { - t.Errorf("Incorrect flags for libfoobar: %q, want %q", r.Args["rustcFlags"], "${config.RustAllowAllLints}") - } + result := android.GroupFixturePreparers( + prepareForRustTest, + // Test with the blueprint file in different directories. + android.FixtureAddTextFile(tc.modulePath+"Android.bp", bp), + ).RunTest(t) + + r := result.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("rustc") + android.AssertStringDoesContain(t, "libfoo flags", r.Args["rustcFlags"], tc.fooFlags) + + r = result.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("rustc") + android.AssertStringDoesContain(t, "libbar flags", r.Args["rustcFlags"], "${config.RustDefaultLints}") + r = result.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("rustc") + android.AssertStringDoesContain(t, "libfoobar flags", r.Args["rustcFlags"], "${config.RustAllowAllLints}") }) } } diff --git a/rust/project_json_test.go b/rust/project_json_test.go index 7af463528..09d30dbde 100644 --- a/rust/project_json_test.go +++ b/rust/project_json_test.go @@ -28,9 +28,10 @@ import ( // testProjectJson run the generation of rust-project.json. It returns the raw // content of the generated file. func testProjectJson(t *testing.T, bp string) []byte { - result := prepareForRustTest. - Extend(android.FixtureMergeEnv(map[string]string{"SOONG_GEN_RUST_PROJECT": "1"})). - RunTestWithBp(t, bp) + result := android.GroupFixturePreparers( + prepareForRustTest, + android.FixtureMergeEnv(map[string]string{"SOONG_GEN_RUST_PROJECT": "1"}), + ).RunTestWithBp(t, bp) // The JSON file is generated via WriteFileToOutputDir. Therefore, it // won't appear in the Output of the TestingSingleton. Manually verify diff --git a/rust/testing.go b/rust/testing.go index 5be71c90e..75adcfce9 100644 --- a/rust/testing.go +++ b/rust/testing.go @@ -17,13 +17,12 @@ package rust import ( "android/soong/android" "android/soong/cc" - "android/soong/genrule" ) // Preparer that will define all cc module types and a limited set of mutators and singletons that // make those module types usable. var PrepareForTestWithRustBuildComponents = android.GroupFixturePreparers( - android.FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest), + android.FixtureRegisterWithContext(registerRequiredBuildComponentsForTest), ) // The directory in which rust test default modules will be defined. @@ -197,7 +196,7 @@ func GatherRequiredDepsForTest() string { return bp } -func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) { +func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) { ctx.RegisterModuleType("rust_binary", RustBinaryFactory) ctx.RegisterModuleType("rust_binary_host", RustBinaryHostFactory) ctx.RegisterModuleType("rust_bindgen", RustBindgenFactory) @@ -231,14 +230,3 @@ func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) { }) ctx.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton) } - -func CreateTestContext(config android.Config) *android.TestContext { - ctx := android.NewTestArchContext(config) - android.RegisterPrebuiltMutators(ctx) - ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators) - genrule.RegisterGenruleBuildComponents(ctx) - cc.RegisterRequiredBuildComponentsForTest(ctx) - RegisterRequiredBuildComponentsForTest(ctx) - - return ctx -} diff --git a/scripts/gen_sorted_bss_symbols.sh b/scripts/gen_sorted_bss_symbols.sh index 244ed0dea..a9b61a1ad 100755 --- a/scripts/gen_sorted_bss_symbols.sh +++ b/scripts/gen_sorted_bss_symbols.sh @@ -18,11 +18,11 @@ # their sizes. # Inputs: # Environment: -# CROSS_COMPILE: prefix added to nm tools +# CLANG_BIN: path to the clang bin directory # Arguments: # $1: Input ELF file # $2: Output symbol ordering file set -o pipefail -${CROSS_COMPILE}nm --size-sort $1 | awk '{if ($2 == "b" || $2 == "B") print $3}' > $2 +${CLANG_BIN}/llvm-nm --size-sort $1 | awk '{if ($2 == "b" || $2 == "B") print $3}' > $2 diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py index 907f239cf..8168fbf6a 100755 --- a/scripts/manifest_check.py +++ b/scripts/manifest_check.py @@ -74,7 +74,7 @@ def parse_args(): return parser.parse_args() -def enforce_uses_libraries(manifest, required, optional, relax, is_apk = False): +def enforce_uses_libraries(manifest, required, optional, relax, is_apk, path): """Verify that the <uses-library> tags in the manifest match those provided by the build system. @@ -86,26 +86,36 @@ def enforce_uses_libraries(manifest, required, optional, relax, is_apk = False): is_apk: if the manifest comes from an APK or an XML file """ if is_apk: - manifest_required, manifest_optional = extract_uses_libs_apk(manifest) + manifest_required, manifest_optional, tags = extract_uses_libs_apk(manifest) else: - manifest_required, manifest_optional = extract_uses_libs_xml(manifest) - - err = [] - if manifest_required != required: - err.append('Expected required <uses-library> tags "%s", got "%s"' % - (', '.join(required), ', '.join(manifest_required))) - - if manifest_optional != optional: - err.append('Expected optional <uses-library> tags "%s", got "%s"' % - (', '.join(optional), ', '.join(manifest_optional))) - - if err: - errmsg = '\n'.join(err) - if not relax: - raise ManifestMismatchError(errmsg) - return errmsg - - return None + manifest_required, manifest_optional, tags = extract_uses_libs_xml(manifest) + + if manifest_required == required and manifest_optional == optional: + return None + + errmsg = ''.join([ + 'mismatch in the <uses-library> tags between the build system and the ' + 'manifest:\n', + '\t- required libraries in build system: [%s]\n' % ', '.join(required), + '\t vs. in the manifest: [%s]\n' % ', '.join(manifest_required), + '\t- optional libraries in build system: [%s]\n' % ', '.join(optional), + '\t vs. in the manifest: [%s]\n' % ', '.join(manifest_optional), + '\t- tags in the manifest (%s):\n' % path, + '\t\t%s\n' % '\t\t'.join(tags), + 'note: the following options are available:\n', + '\t- to temporarily disable the check on command line, rebuild with ', + 'RELAX_USES_LIBRARY_CHECK=true (this will set compiler filter "verify" ', + 'and disable AOT-compilation in dexpreopt)\n', + '\t- to temporarily disable the check for the whole product, set ', + 'PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true in the product makefiles\n', + '\t- to fix the check, make build system properties coherent with the ' + 'manifest\n', + '\t- see build/make/Changes.md for details\n']) + + if not relax: + raise ManifestMismatchError(errmsg) + + return errmsg def extract_uses_libs_apk(badging): @@ -115,14 +125,19 @@ def extract_uses_libs_apk(badging): required = [] optional = [] + lines = [] for match in re.finditer(pattern, badging): + lines.append(match.group(0)) libname = match.group(2) if match.group(1) == None: required.append(libname) else: optional.append(libname) - return first_unique_elements(required), first_unique_elements(optional) + required = first_unique_elements(required) + optional = first_unique_elements(optional) + tags = first_unique_elements(lines) + return required, optional, tags def extract_uses_libs_xml(xml): @@ -143,7 +158,15 @@ def extract_uses_libs_xml(xml): required = [uses_library_name(x) for x in libs if uses_library_required(x)] optional = [uses_library_name(x) for x in libs if not uses_library_required(x)] - return first_unique_elements(required), first_unique_elements(optional) + # render <uses-library> tags as XML for a pretty error message + tags = [] + for lib in libs: + tags.append(lib.toprettyxml()) + + required = first_unique_elements(required) + optional = first_unique_elements(optional) + tags = first_unique_elements(tags) + return required, optional, tags def first_unique_elements(l): @@ -278,7 +301,7 @@ def main(): # in the manifest. Raise an exception on mismatch, unless the script was # passed a special parameter to suppress exceptions. errmsg = enforce_uses_libraries(manifest, required, optional, - args.enforce_uses_libraries_relax, is_apk) + args.enforce_uses_libraries_relax, is_apk, args.input) # Create a status file that is empty on success, or contains an error # message on failure. When exceptions are suppressed, dexpreopt command diff --git a/scripts/manifest_check_test.py b/scripts/manifest_check_test.py index 635ba9d1d..7159bdd74 100755 --- a/scripts/manifest_check_test.py +++ b/scripts/manifest_check_test.py @@ -49,9 +49,9 @@ class EnforceUsesLibrariesTest(unittest.TestCase): try: relax = False manifest_check.enforce_uses_libraries(doc, uses_libraries, - optional_uses_libraries, relax, is_apk=False) + optional_uses_libraries, relax, False, 'path/to/X/AndroidManifest.xml') manifest_check.enforce_uses_libraries(apk, uses_libraries, - optional_uses_libraries, relax, is_apk=True) + optional_uses_libraries, relax, True, 'path/to/X/X.apk') return True except manifest_check.ManifestMismatchError: return False diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go index a886a18ce..b19fcc5cb 100644 --- a/sdk/cc_sdk_test.go +++ b/sdk/cc_sdk_test.go @@ -2407,6 +2407,7 @@ cc_prebuilt_library_shared { "1", "2", "3", + "current", ], }, arch: { @@ -2461,6 +2462,7 @@ cc_prebuilt_library_shared { "1", "2", "3", + "current", ], }, target: { @@ -2500,6 +2502,7 @@ cc_prebuilt_library_shared { "1", "2", "3", + "current", ], }, target: { |