diff options
| -rw-r--r-- | bp2build/prebuilt_etc_conversion_test.go | 40 | ||||
| -rw-r--r-- | etc/prebuilt_etc.go | 12 | ||||
| -rw-r--r-- | genrule/allowlists.go | 1 | ||||
| -rw-r--r-- | java/bootclasspath_fragment_test.go | 54 | ||||
| -rw-r--r-- | java/hiddenapi_modular.go | 16 | ||||
| -rw-r--r-- | java/testing.go | 1 | ||||
| -rw-r--r-- | ui/build/build.go | 2 | ||||
| -rw-r--r-- | ui/build/cleanbuild.go | 44 | ||||
| -rw-r--r-- | ui/build/config.go | 5 | ||||
| -rw-r--r-- | ui/build/kati.go | 2 | ||||
| -rw-r--r-- | ui/build/test_build.go | 5 |
11 files changed, 164 insertions, 18 deletions
diff --git a/bp2build/prebuilt_etc_conversion_test.go b/bp2build/prebuilt_etc_conversion_test.go index 1f372706b..c8cfd87ce 100644 --- a/bp2build/prebuilt_etc_conversion_test.go +++ b/bp2build/prebuilt_etc_conversion_test.go @@ -26,10 +26,17 @@ func runPrebuiltEtcTestCase(t *testing.T, tc Bp2buildTestCase) { t.Helper() (&tc).ModuleTypeUnderTest = "prebuilt_etc" (&tc).ModuleTypeUnderTestFactory = etc.PrebuiltEtcFactory - RunBp2BuildTestCase(t, registerPrebuiltEtcModuleTypes, tc) + RunBp2BuildTestCase(t, registerPrebuiltModuleTypes, tc) } -func registerPrebuiltEtcModuleTypes(ctx android.RegistrationContext) { +func runPrebuiltRootHostTestCase(t *testing.T, tc Bp2buildTestCase) { + t.Helper() + (&tc).ModuleTypeUnderTest = "prebuilt_root_host" + (&tc).ModuleTypeUnderTestFactory = etc.PrebuiltRootHostFactory + RunBp2BuildTestCase(t, registerPrebuiltModuleTypes, tc) +} + +func registerPrebuiltModuleTypes(ctx android.RegistrationContext) { } func TestPrebuiltEtcSimple(t *testing.T) { @@ -160,7 +167,7 @@ func runPrebuiltUsrShareTestCase(t *testing.T, tc Bp2buildTestCase) { t.Helper() (&tc).ModuleTypeUnderTest = "prebuilt_usr_share" (&tc).ModuleTypeUnderTestFactory = etc.PrebuiltUserShareFactory - RunBp2BuildTestCase(t, registerPrebuiltEtcModuleTypes, tc) + RunBp2BuildTestCase(t, registerPrebuiltModuleTypes, tc) } func registerPrebuiltUsrShareModuleTypes(ctx android.RegistrationContext) { @@ -360,3 +367,30 @@ prebuilt_etc { ExpectedBazelTargets: []string{}, }) } + +func TestPrebuiltRootHostWithWildCardInSrc(t *testing.T) { + runPrebuiltRootHostTestCase(t, Bp2buildTestCase{ + Description: "prebuilt_root_host - src string has wild card", + Filesystem: map[string]string{ + "prh.dat": "", + }, + Blueprint: ` +prebuilt_root_host { + name: "prh_test", + src: "*.dat", + filename_from_src: true, + relative_install_path: "test/install/path", + bazel_module: { bp2build_available: true }, +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("prebuilt_file", "prh_test", AttrNameToString{ + "filename": `"prh.dat"`, + "src": `"prh.dat"`, + "dir": `"./test/install/path"`, + "target_compatible_with": `select({ + "//build/bazel_common_rules/platforms/os:android": ["@platforms//:incompatible"], + "//conditions:default": [], + })`, + })}}) +} diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go index 94235319a..ca2844244 100644 --- a/etc/prebuilt_etc.go +++ b/etc/prebuilt_etc.go @@ -508,6 +508,7 @@ func PrebuiltRootHostFactory() android.Module { // This module is host-only android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon) android.InitDefaultableModule(module) + android.InitBazelModule(module) return module } @@ -759,7 +760,7 @@ func (module *PrebuiltEtc) Bp2buildHelper(ctx android.Bp2buildMutatorContext) (* filename = *moduleProps.Filename } else if moduleProps.Filename_from_src != nil && *moduleProps.Filename_from_src { if moduleProps.Src != nil { - filename = *moduleProps.Src + filename = android.BazelLabelForModuleSrcSingle(ctx, *moduleProps.Src).Label } filenameFromSrc = true } else { @@ -767,8 +768,8 @@ func (module *PrebuiltEtc) Bp2buildHelper(ctx android.Bp2buildMutatorContext) (* } var dir = module.installDirBase - if subDir := module.subdirProperties.Sub_dir; subDir != nil { - dir = dir + "/" + *subDir + if module.SubDir() != "" { + dir = dir + "/" + module.SubDir() } var installable bazel.BoolAttribute @@ -796,8 +797,9 @@ func (module *PrebuiltEtc) Bp2buildHelper(ctx android.Bp2buildMutatorContext) (* // which we treat as *PrebuiltFile* func (module *PrebuiltEtc) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { var dir = module.installDirBase - // prebuilt_file supports only `etc` or `usr/share` - if !(dir == "etc" || dir == "usr/share") { + // prebuilt_file only supports "etc" or "usr/share" or "." as module installDirBase + if !(dir == "etc" || dir == "usr/share" || dir == ".") { + ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "") return } diff --git a/genrule/allowlists.go b/genrule/allowlists.go index 8c78528ed..8552173a3 100644 --- a/genrule/allowlists.go +++ b/genrule/allowlists.go @@ -58,6 +58,7 @@ var ( "BlueberryFacadeGeneratedStub_h", "BluetoothGeneratedDumpsysBinarySchema_bfbs", "BluetoothGeneratedDumpsysDataSchema_h", + "CompilationTestCases_package-dex-usage", "ControlEnvProxyServerProto_cc", "ControlEnvProxyServerProto_h", "CtsApkVerityTestDebugFiles", diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go index 888caad16..828de2179 100644 --- a/java/bootclasspath_fragment_test.go +++ b/java/bootclasspath_fragment_test.go @@ -316,6 +316,60 @@ func TestBootclasspathFragment_StubLibs(t *testing.T) { android.AssertPathsRelativeToTopEquals(t, "widest dex stubs jar", expectedWidestPaths, info.TransitiveStubDexJarsByScope.StubDexJarsForWidestAPIScope()) } +func TestFromTextWidestApiScope(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForTestWithBootclasspathFragment, + PrepareForTestWithJavaSdkLibraryFiles, + android.FixtureModifyConfig(func(config android.Config) { + config.SetBuildFromTextStub(true) + }), + FixtureWithLastReleaseApis("mysdklibrary", "android-non-updatable"), + FixtureConfigureApexBootJars("someapex:mysdklibrary"), + ).RunTestWithBp(t, ` + bootclasspath_fragment { + name: "myfragment", + contents: ["mysdklibrary"], + additional_stubs: [ + "android-non-updatable", + ], + hidden_api: { + split_packages: ["*"], + }, + } + java_sdk_library { + name: "mysdklibrary", + srcs: ["a.java"], + shared_library: false, + public: {enabled: true}, + system: {enabled: true}, + } + java_sdk_library { + name: "android-non-updatable", + srcs: ["b.java"], + compile_dex: true, + public: { + enabled: true, + }, + system: { + enabled: true, + }, + test: { + enabled: true, + }, + module_lib: { + enabled: true, + }, + } + `) + + fragment := result.ModuleForTests("myfragment", "android_common") + dependencyStubDexFlag := "--dependency-stub-dex=out/soong/.intermediates/default/java/android-non-updatable.stubs.test_module_lib/android_common/dex/android-non-updatable.stubs.test_module_lib.jar" + stubFlagsCommand := fragment.Output("modular-hiddenapi/stub-flags.csv").RuleParams.Command + android.AssertStringDoesContain(t, + "Stub flags generating command does not include the expected dependency stub dex file", + stubFlagsCommand, dependencyStubDexFlag) +} + func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithBootclasspathFragment, diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go index f31f5d1a8..81be33dd1 100644 --- a/java/hiddenapi_modular.go +++ b/java/hiddenapi_modular.go @@ -38,10 +38,14 @@ type HiddenAPIScope struct { // The option needed to passed to "hiddenapi list". hiddenAPIListOption string - // The name sof the source stub library modules that contain the API provided by the platform, + // The names of the source stub library modules that contain the API provided by the platform, // i.e. by modules that are not in an APEX. nonUpdatableSourceModule string + // The names of from-text stub library modules that contain the API provided by the platform, + // i.e. by modules that are not in an APEX. + nonUpdatableFromTextModule string + // The names of the prebuilt stub library modules that contain the API provided by the platform, // i.e. by modules that are not in an APEX. nonUpdatablePrebuiltModule string @@ -86,6 +90,9 @@ func (l *HiddenAPIScope) scopeSpecificStubModule(ctx android.BaseModuleContext, if ctx.Config().AlwaysUsePrebuiltSdks() { return l.nonUpdatablePrebuiltModule } else { + if l.nonUpdatableFromTextModule != "" && ctx.Config().BuildFromTextStub() { + return l.nonUpdatableFromTextModule + } return l.nonUpdatableSourceModule } } else { @@ -117,8 +124,9 @@ var ( hiddenAPIListOption: "--test-stub-classpath", }) ModuleLibHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{ - name: "module-lib", - sdkKind: android.SdkModule, + name: "module-lib", + sdkKind: android.SdkModule, + nonUpdatableFromTextModule: "android-non-updatable.stubs.test_module_lib", }) CorePlatformHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{ name: "core-platform", @@ -647,7 +655,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 == scope.nonUpdatableSourceModule || name == scope.nonUpdatableFromTextModule { // 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/testing.go b/java/testing.go index 446135116..16bdd80a1 100644 --- a/java/testing.go +++ b/java/testing.go @@ -491,6 +491,7 @@ func gatherRequiredDepsForTest() string { "android-non-updatable.stubs.system.from-text": systemDroidstubs, "android-non-updatable.stubs.test.from-text": testDroidstubs, "android-non-updatable.stubs.module_lib.from-text": moduleLibDroidstubs, + "android-non-updatable.stubs.test_module_lib": moduleLibDroidstubs, } for _, droidstubs := range droidstubsStructs { diff --git a/ui/build/build.go b/ui/build/build.go index 9d5c330e1..15cff5f0b 100644 --- a/ui/build/build.go +++ b/ui/build/build.go @@ -298,6 +298,8 @@ func Build(ctx Context, config Config) { runMakeProductConfig(ctx, config) } + checkForCleanPartitions(ctx, config) + // Everything below here depends on product config. if inList("installclean", config.Arguments()) || diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go index 41cb5ab6d..71149639e 100644 --- a/ui/build/cleanbuild.go +++ b/ui/build/cleanbuild.go @@ -218,6 +218,50 @@ func installCleanIfNecessary(ctx Context, config Config) { writeConfig() } +// Writes out/partitions_were_clean_at_start_of_build.txt. +// This file will contain "true" if there were no partition staging directories at the start of +// the build (most likely from having just run `m installclean`) and "false" otherwise. +// It's used to make a test that the staging directories are correct. That test can only be +// correctly run directly after `m installclean`, and this is how we check for that. +func checkForCleanPartitions(ctx Context, config Config) { + productOutPath := config.ProductOut() + productOut := func(path string) string { + return filepath.Join(productOutPath, path) + } + + notExists := func(path string) bool { + _, err := os.Stat(path) + return os.IsNotExist(err) + } + + clean := notExists(productOut("ramdisk")) && + notExists(productOut("ramdisk_16k")) && + notExists(productOut("debug_ramdisk")) && + notExists(productOut("vendor_ramdisk")) && + notExists(productOut("vendor_debug_ramdisk")) && + notExists(productOut("vendor_kernel_ramdisk")) && + notExists(productOut("test_harness_ramdisk")) && + notExists(productOut("data")) && + notExists(productOut("recovery")) && + notExists(productOut("root")) && + notExists(productOut("system")) && + notExists(productOut("system_dlkm")) && + notExists(productOut("system_other")) && + notExists(productOut("vendor")) && + notExists(productOut("vendor_dlkm")) && + notExists(productOut("product")) && + notExists(productOut("system_ext")) && + notExists(productOut("oem")) && + notExists(productOut("breakpad")) && + notExists(productOut("cache")) && + notExists(productOut("coverage")) && + notExists(productOut("installer")) && + notExists(productOut("odm")) && + notExists(productOut("odm_dlkm")) + + writeValueIfChanged(ctx, config, config.OutDir(), "partitions_were_clean_at_start_of_build.txt", fmt.Sprintf("%t\n", clean)) +} + // cleanOldFiles takes an input file (with all paths relative to basePath), and removes files from // the filesystem if they were removed from the input file since the last execution. func cleanOldFiles(ctx Context, basePath, newFile string) { diff --git a/ui/build/config.go b/ui/build/config.go index 2e5921a2c..264d83e70 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -472,11 +472,6 @@ func NewConfig(ctx Context, args ...string) Config { } } - if ret.BuildFromTextStub() { - // TODO(b/271443071): support hidden api check for from-text stub build - ret.environ.Set("UNSAFE_DISABLE_HIDDENAPI_FLAGS", "true") - } - bpd := ret.BazelMetricsDir() if err := os.RemoveAll(bpd); err != nil { ctx.Fatalf("Unable to remove bazel profile directory %q: %v", bpd, err) diff --git a/ui/build/kati.go b/ui/build/kati.go index 31e744029..7f0ea247c 100644 --- a/ui/build/kati.go +++ b/ui/build/kati.go @@ -102,6 +102,8 @@ func runKati(ctx Context, config Config, extraSuffix string, args []string, envF "--use_ninja_phony_output", // Support declaring symlink outputs in AOSP Ninja. "--use_ninja_symlink_outputs", + // Support ninja validation actions with .KATI_VALIDATIONS: https://ninja-build.org/manual.html#validations + "--use_ninja_validations", // Regenerate the Ninja file if environment inputs have changed. e.g. // CLI flags, .mk file timestamps, env vars, $(wildcard ..) and some // $(shell ..) results. diff --git a/ui/build/test_build.go b/ui/build/test_build.go index 2efc732c2..af60e0d76 100644 --- a/ui/build/test_build.go +++ b/ui/build/test_build.go @@ -103,8 +103,10 @@ func testForDanglingRules(ctx Context, config Config) { // treated as an source file. dexpreoptConfigFilePath := filepath.Join(outDir, "soong", "dexpreopt.config") - // out/build_date.txt is considered a "source file" + // These files are written by soong_ui at the beginning of every build. + // Ninja considers them "source files" buildDatetimeFilePath := filepath.Join(outDir, "build_date.txt") + cleanPartitionsFilePath := filepath.Join(outDir, "partitions_were_clean_at_start_of_build.txt") // bpglob is built explicitly using Microfactory bpglob := filepath.Join(config.SoongOutDir(), "bpglob") @@ -122,6 +124,7 @@ func testForDanglingRules(ctx Context, config Config) { line == variablesFilePath || line == dexpreoptConfigFilePath || line == buildDatetimeFilePath || + line == cleanPartitionsFilePath || line == bpglob { // Leaf node is in one of Soong's bootstrap directories, which do not have // full build rules in the primary build.ninja file. |