diff options
45 files changed, 672 insertions, 419 deletions
diff --git a/android/arch.go b/android/arch.go index 9f937522f..d7b12bcb5 100644 --- a/android/arch.go +++ b/android/arch.go @@ -412,6 +412,54 @@ func (target Target) Variations() []blueprint.Variation { } } +func registerBp2buildArchPathDepsMutator(ctx RegisterMutatorsContext) { + ctx.BottomUp("bp2build-arch-pathdeps", bp2buildArchPathDepsMutator).Parallel() +} + +// add dependencies for architecture specific properties tagged with `android:"path"` +func bp2buildArchPathDepsMutator(ctx BottomUpMutatorContext) { + var module Module + module = ctx.Module() + + m := module.base() + if !m.ArchSpecific() { + return + } + + // addPathDepsForProps does not descend into sub structs, so we need to descend into the + // arch-specific properties ourselves + properties := []interface{}{} + for _, archProperties := range m.archProperties { + for _, archProps := range archProperties { + archPropValues := reflect.ValueOf(archProps).Elem() + // there are three "arch" variations, descend into each + for _, variant := range []string{"Arch", "Multilib", "Target"} { + // The properties are an interface, get the value (a pointer) that it points to + archProps := archPropValues.FieldByName(variant).Elem() + if archProps.IsNil() { + continue + } + // And then a pointer to a struct + archProps = archProps.Elem() + for i := 0; i < archProps.NumField(); i += 1 { + f := archProps.Field(i) + // If the value of the field is a struct (as opposed to a pointer to a struct) then step + // into the BlueprintEmbed field. + if f.Kind() == reflect.Struct { + f = f.FieldByName("BlueprintEmbed") + } + if f.IsZero() { + continue + } + props := f.Interface().(interface{}) + properties = append(properties, props) + } + } + } + } + addPathDepsForProps(ctx, properties) +} + // osMutator splits an arch-specific module into a variant for each OS that is enabled for the // module. It uses the HostOrDevice value passed to InitAndroidArchModule and the // device_supported and host_supported properties to determine which OsTypes are enabled for this @@ -617,7 +665,7 @@ func archMutator(bpctx blueprint.BottomUpMutatorContext) { } // only the primary arch in the ramdisk / vendor_ramdisk / recovery partition - if os == Android && (module.InstallInRecovery() || module.InstallInRamdisk() || module.InstallInVendorRamdisk() || module.InstallInDebugRamdisk()) { + if os == Android && (module.InstallInRecovery() || module.InstallInRamdisk() || module.InstallInVendorRamdisk()) { osTargets = []Target{osTargets[0]} } @@ -899,13 +947,17 @@ func filterArchStruct(field reflect.StructField, prefix string) (bool, reflect.S if string(field.Tag) != `android:"`+strings.Join(values, ",")+`"` { panic(fmt.Errorf("unexpected tag format %q", field.Tag)) } + // don't delete path tag as it is needed for bp2build // these tags don't need to be present in the runtime generated struct type. - values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend", "path"}) - if len(values) > 0 { + values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend"}) + if len(values) > 0 && values[0] != "path" { panic(fmt.Errorf("unknown tags %q in field %q", values, prefix+field.Name)) + } else if len(values) == 1 { + field.Tag = reflect.StructTag(`android:"` + strings.Join(values, ",") + `"`) + } else { + field.Tag = `` } - field.Tag = "" return true, field } return false, field diff --git a/android/arch_test.go b/android/arch_test.go index 633ddaa99..3aa4779fe 100644 --- a/android/arch_test.go +++ b/android/arch_test.go @@ -66,9 +66,9 @@ func TestFilterArchStruct(t *testing.T) { }{}, out: &struct { A *string - B *string - C *string - D *string + B *string `android:"path"` + C *string `android:"path"` + D *string `android:"path"` }{}, filtered: true, }, diff --git a/android/bazel.go b/android/bazel.go index 6800c9167..ba5ae3133 100644 --- a/android/bazel.go +++ b/android/bazel.go @@ -185,7 +185,7 @@ var ( "libc_bionic_ndk", // ruperts@, cc_library_static, depends on //bionic/libc/system_properties "libc_bionic_systrace", // ruperts@, cc_library_static, 'private/bionic_systrace.h' file not found "libc_pthread", // ruperts@, cc_library_static, 'private/bionic_defs.h' file not found - "libc_syscalls", // ruperts@, cc_library_static, mutator panic cannot get direct dep syscalls-arm64.S of libc_syscalls + "libc_syscalls", // eakammer@, cc_library_static, 'private/bionic_asm.h' file not found "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 @@ -212,8 +212,8 @@ var ( "libc_malloc_debug", // jingwen@, cc_library, fatal error: 'assert.h' file not found "libc_malloc_hooks", // jingwen@, cc_library, fatal error: 'errno.h' file not found "libdl", // jingwen@, cc_library, ld.lld: error: no input files - "libm", // jingwen@, cc_library, fatal error: 'freebsd-compat.h' file not found - "libseccomp_policy", // jingwen@, cc_library, fatal error: 'seccomp_policy.h' file not found + "libm", // lberki@, cc_library, compiler error: "Unexpected token in argument list" + "libseccomp_policy", // lberki@, cc_library, 'linux/filter.h' not found, caused by missing -isystem bionic/libc/kernel/uapi, dunno where it comes from in Soong "libstdc++", // jingwen@, cc_library, depends on //external/gwp_asan } diff --git a/android/bazel_paths.go b/android/bazel_paths.go index 9727cc7fe..63e2c50ed 100644 --- a/android/bazel_paths.go +++ b/android/bazel_paths.go @@ -351,3 +351,13 @@ func PathForBazelOut(ctx PathContext, paths ...string) BazelOutPath { OutputPath: outputPath.withRel(validatedExecRootPath), } } + +// PathsForBazelOut returns a list of paths representing the paths under an output directory +// dedicated to Bazel-owned outputs. +func PathsForBazelOut(ctx PathContext, paths []string) Paths { + outs := make(Paths, 0, len(paths)) + for _, p := range paths { + outs = append(outs, PathForBazelOut(ctx, p)) + } + return outs +} diff --git a/android/image.go b/android/image.go index bdb9be04d..1a1a423e2 100644 --- a/android/image.go +++ b/android/image.go @@ -30,11 +30,6 @@ type ImageInterface interface { // vendor ramdisk partition). VendorRamdiskVariantNeeded(ctx BaseModuleContext) bool - // DebugRamdiskVariantNeeded should return true if the module needs a debug ramdisk variant (installed on the - // debug ramdisk partition: $(PRODUCT_OUT)/debug_ramdisk/first_stage_ramdisk if BOARD_USES_RECOVERY_AS_ROOT is - // true, $(PRODUCT_OUT)/debug_ramdisk otherise). - DebugRamdiskVariantNeeded(ctx BaseModuleContext) bool - // RecoveryVariantNeeded should return true if the module needs a recovery variant (installed on the // recovery partition). RecoveryVariantNeeded(ctx BaseModuleContext) bool @@ -65,9 +60,6 @@ const ( // VendorRamdiskVariation means a module to be installed to vendor ramdisk image. VendorRamdiskVariation string = "vendor_ramdisk" - - // DebugRamdiskVariation means a module to be installed to debug ramdisk image. - DebugRamdiskVariation string = "debug_ramdisk" ) // imageMutator creates variants for modules that implement the ImageInterface that @@ -91,9 +83,6 @@ func imageMutator(ctx BottomUpMutatorContext) { if m.VendorRamdiskVariantNeeded(ctx) { variations = append(variations, VendorRamdiskVariation) } - if m.DebugRamdiskVariantNeeded(ctx) { - variations = append(variations, DebugRamdiskVariation) - } if m.RecoveryVariantNeeded(ctx) { variations = append(variations, RecoveryVariation) } diff --git a/android/module.go b/android/module.go index 942e07193..9f923e2d0 100644 --- a/android/module.go +++ b/android/module.go @@ -393,7 +393,6 @@ type ModuleContext interface { InstallInSanitizerDir() bool InstallInRamdisk() bool InstallInVendorRamdisk() bool - InstallInDebugRamdisk() bool InstallInRecovery() bool InstallInRoot() bool InstallBypassMake() bool @@ -451,7 +450,6 @@ type Module interface { InstallInSanitizerDir() bool InstallInRamdisk() bool InstallInVendorRamdisk() bool - InstallInDebugRamdisk() bool InstallInRecovery() bool InstallInRoot() bool InstallBypassMake() bool @@ -755,9 +753,6 @@ type commonProperties struct { // Whether this module is installed to vendor ramdisk Vendor_ramdisk *bool - // Whether this module is installed to debug ramdisk - Debug_ramdisk *bool - // Whether this module is built for non-native architectures (also known as native bridge binary) Native_bridge_supported *bool `android:"arch_variant"` @@ -1545,10 +1540,6 @@ func (m *ModuleBase) InstallInVendorRamdisk() bool { return Bool(m.commonProperties.Vendor_ramdisk) } -func (m *ModuleBase) InstallInDebugRamdisk() bool { - return Bool(m.commonProperties.Debug_ramdisk) -} - func (m *ModuleBase) InstallInRecovery() bool { return Bool(m.commonProperties.Recovery) } @@ -1602,10 +1593,6 @@ func (m *ModuleBase) InVendorRamdisk() bool { return m.base().commonProperties.ImageVariation == VendorRamdiskVariation } -func (m *ModuleBase) InDebugRamdisk() bool { - return m.base().commonProperties.ImageVariation == DebugRamdiskVariation -} - func (m *ModuleBase) InRecovery() bool { return m.base().commonProperties.ImageVariation == RecoveryVariation } @@ -2561,10 +2548,6 @@ func (m *moduleContext) InstallInVendorRamdisk() bool { return m.module.InstallInVendorRamdisk() } -func (m *moduleContext) InstallInDebugRamdisk() bool { - return m.module.InstallInDebugRamdisk() -} - func (m *moduleContext) InstallInRecovery() bool { return m.module.InstallInRecovery() } diff --git a/android/mutator.go b/android/mutator.go index e25e2e8f1..365bf290b 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -55,6 +55,7 @@ func RegisterMutatorsForBazelConversion(ctx *Context, preArchMutators, depsMutat bp2buildDepsMutators = append([]RegisterMutatorFunc{ registerDepsMutatorBp2Build, registerPathDepsMutator, + registerBp2buildArchPathDepsMutator, }, depsMutators...) for _, f := range bp2buildDepsMutators { diff --git a/android/path_properties.go b/android/path_properties.go index 2c8d27c56..44467730d 100644 --- a/android/path_properties.go +++ b/android/path_properties.go @@ -34,7 +34,10 @@ func registerPathDepsMutator(ctx RegisterMutatorsContext) { // ":module" module reference syntax in a property that is tagged with `android:"path"`. func pathDepsMutator(ctx BottomUpMutatorContext) { props := ctx.Module().base().generalProperties + addPathDepsForProps(ctx, props) +} +func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) { // Iterate through each property struct of the module extracting the contents of all properties // tagged with `android:"path"`. var pathProperties []string diff --git a/android/paths.go b/android/paths.go index 026cb8747..93c5684f3 100644 --- a/android/paths.go +++ b/android/paths.go @@ -106,7 +106,6 @@ type ModuleInstallPathContext interface { InstallInSanitizerDir() bool InstallInRamdisk() bool InstallInVendorRamdisk() bool - InstallInDebugRamdisk() bool InstallInRecovery() bool InstallInRoot() bool InstallBypassMake() bool @@ -1690,16 +1689,6 @@ func modulePartition(ctx ModuleInstallPathContext, os OsType) string { if !ctx.InstallInRoot() { partition += "/system" } - } else if ctx.InstallInDebugRamdisk() { - // The module is only available after switching root into - // /first_stage_ramdisk. To expose the module before switching root - // on a device without a dedicated recovery partition, install the - // recovery variant. - if ctx.DeviceConfig().BoardUsesRecoveryAsBoot() { - partition = "debug_ramdisk/first_stage_ramdisk" - } else { - partition = "debug_ramdisk" - } } else if ctx.InstallInRecovery() { if ctx.InstallInRoot() { partition = "recovery/root" @@ -1870,7 +1859,6 @@ type testModuleInstallPathContext struct { inSanitizerDir bool inRamdisk bool inVendorRamdisk bool - inDebugRamdisk bool inRecovery bool inRoot bool forceOS *OsType @@ -1903,10 +1891,6 @@ func (m testModuleInstallPathContext) InstallInVendorRamdisk() bool { return m.inVendorRamdisk } -func (m testModuleInstallPathContext) InstallInDebugRamdisk() bool { - return m.inDebugRamdisk -} - func (m testModuleInstallPathContext) InstallInRecovery() bool { return m.inRecovery } diff --git a/android/paths_test.go b/android/paths_test.go index cb9138b98..6ec75b42b 100644 --- a/android/paths_test.go +++ b/android/paths_test.go @@ -395,19 +395,6 @@ func TestPathForModuleInstall(t *testing.T) { partitionDir: "target/product/test_device/vendor_ramdisk", }, { - name: "debug_ramdisk binary", - ctx: &testModuleInstallPathContext{ - baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, - }, - inDebugRamdisk: true, - }, - in: []string{"my_test"}, - out: "target/product/test_device/debug_ramdisk/my_test", - partitionDir: "target/product/test_device/debug_ramdisk", - }, - { name: "system native test binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ @@ -746,19 +733,6 @@ func TestPathForModuleInstallRecoveryAsBoot(t *testing.T) { out: "target/product/test_device/vendor_ramdisk/first_stage_ramdisk/my_test", partitionDir: "target/product/test_device/vendor_ramdisk/first_stage_ramdisk", }, - { - name: "debug_ramdisk binary", - ctx: &testModuleInstallPathContext{ - baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, - }, - inDebugRamdisk: true, - }, - in: []string{"my_test"}, - out: "target/product/test_device/debug_ramdisk/first_stage_ramdisk/my_test", - partitionDir: "target/product/test_device/debug_ramdisk/first_stage_ramdisk", - }, } for _, tc := range testCases { diff --git a/apex/Android.bp b/apex/Android.bp index 7b5240286..e234181d3 100644 --- a/apex/Android.bp +++ b/apex/Android.bp @@ -30,7 +30,7 @@ bootstrap_go_package { ], testSrcs: [ "apex_test.go", - "boot_image_test.go", + "bootclasspath_fragment_test.go", "platform_bootclasspath_test.go", "vndk_test.go", ], diff --git a/apex/apex.go b/apex/apex.go index 088a462b3..762912ecf 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1695,7 +1695,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { } case bcpfTag: { - if _, ok := child.(*java.BootImageModule); !ok { + if _, ok := child.(*java.BootclasspathFragmentModule); !ok { ctx.PropertyErrorf("bootclasspath_fragments", "%q is not a boot_image module", depName) return false } diff --git a/apex/boot_image_test.go b/apex/bootclasspath_fragment_test.go index dab72f76b..87f013231 100644 --- a/apex/boot_image_test.go +++ b/apex/bootclasspath_fragment_test.go @@ -22,8 +22,8 @@ import ( "android/soong/java" ) -// Contains tests for boot_image logic from java/boot_image.go as the ART boot image requires -// modules from the ART apex. +// Contains tests for bootclasspath_fragment logic from java/bootclasspath_fragment.go as the ART +// bootclasspath_fragment requires modules from the ART apex. var prepareForTestWithBootclasspathFragment = android.GroupFixturePreparers( java.PrepareForTestWithDexpreopt, @@ -40,7 +40,7 @@ var prepareForTestWithArtApex = android.FixtureMergeMockFs(android.MockFS{ func TestBootclasspathFragments(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithBootclasspathFragment, - // Configure some libraries in the art and framework boot images. + // Configure some libraries in the art bootclasspath_fragment and platform_bootclasspath. java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "platform:foo", "platform:bar"), prepareForTestWithArtApex, @@ -141,9 +141,9 @@ test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-quuz.vde func checkBootclasspathFragment(t *testing.T, result *android.TestResult, moduleName string, expectedConfiguredModules string, expectedBootclasspathFragmentFiles string) { t.Helper() - bootImage := result.ModuleForTests(moduleName, "android_common").Module().(*java.BootImageModule) + bootclasspathFragment := result.ModuleForTests(moduleName, "android_common").Module().(*java.BootclasspathFragmentModule) - bootImageInfo := result.ModuleProvider(bootImage, java.BootImageInfoProvider).(java.BootImageInfo) + bootImageInfo := result.ModuleProvider(bootclasspathFragment, java.BootImageInfoProvider).(java.BootImageInfo) modules := bootImageInfo.Modules() android.AssertStringEquals(t, "invalid modules for "+moduleName, expectedConfiguredModules, modules.String()) @@ -166,7 +166,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) { prepareForTestWithBootclasspathFragment, prepareForTestWithArtApex, - // Configure some libraries in the art boot image. + // Configure some libraries in the art bootclasspath_fragment. java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"), ).RunTestWithBp(t, ` apex { @@ -176,8 +176,8 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) { "mybootclasspathfragment", ], // bar (like foo) should be transitively included in this apex because it is part of the - // mybootclasspathfragment boot_image. However, it is kept here to ensure that the apex dedups the files - // correctly. + // mybootclasspathfragment bootclasspath_fragment. However, it is kept here to ensure that the + // apex dedups the files correctly. java_libs: [ "bar", ], @@ -208,7 +208,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) { ], } - boot_image { + bootclasspath_fragment { name: "mybootclasspathfragment", image_name: "art", apex_available: [ @@ -233,7 +233,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) { } // Make sure that a preferred prebuilt doesn't affect the apex. - prebuilt_boot_image { + prebuilt_bootclasspath_fragment { name: "mybootclasspathfragment", image_name: "art", prefer: true, @@ -277,7 +277,7 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) { "com.android.art-arm.apex": nil, }), - // Configure some libraries in the art boot image. + // Configure some libraries in the art bootclasspath_fragment. java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"), ).RunTestWithBp(t, ` prebuilt_apex { @@ -309,7 +309,7 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) { ], } - prebuilt_boot_image { + prebuilt_bootclasspath_fragment { name: "mybootclasspathfragment", image_name: "art", apex_available: [ @@ -369,7 +369,7 @@ func TestBootclasspathFragmentContentsNoName(t *testing.T) { ], } - boot_image { + bootclasspath_fragment { name: "mybootclasspathfragment", contents: [ "foo", diff --git a/apex/deapexer.go b/apex/deapexer.go index 1db13f916..9bc57209e 100644 --- a/apex/deapexer.go +++ b/apex/deapexer.go @@ -44,9 +44,13 @@ import ( // module.` type DeapexerProperties struct { // List of java libraries that are embedded inside this prebuilt APEX bundle and for which this - // APEX bundle will provide dex implementation jars for use by dexpreopt and boot jars package - // check. + // APEX bundle will create an APEX variant and provide dex implementation jars for use by + // dexpreopt and boot jars package check. Exported_java_libs []string + + // List of bootclasspath fragments inside this prebuiltd APEX bundle and for which this APEX + // bundle will create an APEX variant. + Exported_bootclasspath_fragments []string } type SelectedApexProperties struct { diff --git a/apex/prebuilt.go b/apex/prebuilt.go index a9d24a7c5..7830f95af 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -97,10 +97,17 @@ func (p *prebuiltCommon) checkForceDisable(ctx android.ModuleContext) bool { func (p *prebuiltCommon) deapexerDeps(ctx android.BottomUpMutatorContext) { // Add dependencies onto the java modules that represent the java libraries that are provided by // and exported from this prebuilt apex. - for _, lib := range p.deapexerProperties.Exported_java_libs { - dep := prebuiltApexExportedModuleName(ctx, lib) + for _, exported := range p.deapexerProperties.Exported_java_libs { + dep := prebuiltApexExportedModuleName(ctx, exported) ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), exportedJavaLibTag, dep) } + + // Add dependencies onto the bootclasspath fragment modules that are exported from this prebuilt + // apex. + for _, exported := range p.deapexerProperties.Exported_bootclasspath_fragments { + dep := prebuiltApexExportedModuleName(ctx, exported) + ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), exportedBootclasspathFragmentTag, dep) + } } // apexInfoMutator marks any modules for which this apex exports a file as requiring an apex @@ -137,18 +144,19 @@ func (p *prebuiltCommon) apexInfoMutator(mctx android.TopDownMutatorContext) { var dependencies []android.ApexModule mctx.VisitDirectDeps(func(m android.Module) { tag := mctx.OtherModuleDependencyTag(m) - if tag == exportedJavaLibTag { + if exportedTag, ok := tag.(exportedDependencyTag); ok { + propertyName := exportedTag.name depName := mctx.OtherModuleName(m) // It is an error if the other module is not a prebuilt. if _, ok := m.(android.PrebuiltInterface); !ok { - mctx.PropertyErrorf("exported_java_libs", "%q is not a prebuilt module", depName) + mctx.PropertyErrorf(propertyName, "%q is not a prebuilt module", depName) return } // It is an error if the other module is not an ApexModule. if _, ok := m.(android.ApexModule); !ok { - mctx.PropertyErrorf("exported_java_libs", "%q is not usable within an apex", depName) + mctx.PropertyErrorf(propertyName, "%q is not usable within an apex", depName) return } @@ -451,7 +459,8 @@ type exportedDependencyTag struct { func (t exportedDependencyTag) ExcludeFromVisibilityEnforcement() {} var ( - exportedJavaLibTag = exportedDependencyTag{name: "exported_java_lib"} + exportedJavaLibTag = exportedDependencyTag{name: "exported_java_libs"} + exportedBootclasspathFragmentTag = exportedDependencyTag{name: "exported_bootclasspath_fragments"} ) func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) { diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go index 80491089d..c30abeb87 100644 --- a/bazel/cquery/request_type.go +++ b/bazel/cquery/request_type.go @@ -14,6 +14,8 @@ type CcInfo struct { OutputFiles []string CcObjectFiles []string CcStaticLibraryFiles []string + Includes []string + SystemIncludes []string } type getOutputFilesRequestType struct{} @@ -63,6 +65,9 @@ func (g getCcInfoType) StarlarkFunctionBody() string { return ` outputFiles = [f.path for f in target.files.to_list()] +includes = providers(target)["CcInfo"].compilation_context.includes.to_list() +system_includes = providers(target)["CcInfo"].compilation_context.system_includes.to_list() + ccObjectFiles = [] staticLibraries = [] linker_inputs = providers(target)["CcInfo"].linking_context.linker_inputs.to_list() @@ -78,6 +83,8 @@ returns = [ outputFiles, staticLibraries, ccObjectFiles, + includes, + system_includes, ] return "|".join([", ".join(r) for r in returns])` @@ -91,7 +98,7 @@ func (g getCcInfoType) ParseResult(rawString string) (CcInfo, error) { var ccObjects []string splitString := strings.Split(rawString, "|") - if expectedLen := 3; len(splitString) != expectedLen { + if expectedLen := 5; len(splitString) != expectedLen { return CcInfo{}, fmt.Errorf("Expected %d items, got %q", expectedLen, splitString) } outputFilesString := splitString[0] @@ -100,10 +107,14 @@ func (g getCcInfoType) ParseResult(rawString string) (CcInfo, error) { outputFiles = splitOrEmpty(outputFilesString, ", ") ccStaticLibraries := splitOrEmpty(ccStaticLibrariesString, ", ") ccObjects = splitOrEmpty(ccObjectsString, ", ") + includes := splitOrEmpty(splitString[3], ", ") + systemIncludes := splitOrEmpty(splitString[4], ", ") return CcInfo{ OutputFiles: outputFiles, CcObjectFiles: ccObjects, CcStaticLibraryFiles: ccStaticLibraries, + Includes: includes, + SystemIncludes: systemIncludes, }, nil } diff --git a/bazel/cquery/request_type_test.go b/bazel/cquery/request_type_test.go index 48edb9049..6369999fb 100644 --- a/bazel/cquery/request_type_test.go +++ b/bazel/cquery/request_type_test.go @@ -3,6 +3,7 @@ package cquery import ( "fmt" "reflect" + "strings" "testing" ) @@ -45,42 +46,48 @@ func TestGetCcInfoParseResults(t *testing.T) { }{ { description: "no result", - input: "||", + input: "||||", expectedOutput: CcInfo{ OutputFiles: []string{}, CcObjectFiles: []string{}, CcStaticLibraryFiles: []string{}, + Includes: []string{}, + SystemIncludes: []string{}, }, }, { description: "only output", - input: "test||", + input: "test||||", expectedOutput: CcInfo{ OutputFiles: []string{"test"}, CcObjectFiles: []string{}, CcStaticLibraryFiles: []string{}, + Includes: []string{}, + SystemIncludes: []string{}, }, }, { description: "all items set", - input: "out1, out2|static_lib1, static_lib2|object1, object2", + input: "out1, out2|static_lib1, static_lib2|object1, object2|., dir/subdir|system/dir, system/other/dir", expectedOutput: CcInfo{ OutputFiles: []string{"out1", "out2"}, CcObjectFiles: []string{"object1", "object2"}, CcStaticLibraryFiles: []string{"static_lib1", "static_lib2"}, + Includes: []string{".", "dir/subdir"}, + SystemIncludes: []string{"system/dir", "system/other/dir"}, }, }, { description: "too few result splits", input: "|", expectedOutput: CcInfo{}, - expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 3, []string{"", ""}), + expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 5, []string{"", ""}), }, { description: "too many result splits", - input: "|||", + input: strings.Repeat("|", 8), expectedOutput: CcInfo{}, - expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 3, []string{"", "", "", ""}), + expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 5, make([]string, 9)), }, } for _, tc := range testCases { diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go index 1ede4428a..21d7062fa 100644 --- a/bp2build/build_conversion_test.go +++ b/bp2build/build_conversion_test.go @@ -204,8 +204,9 @@ func TestGenerateSoongModuleTargets(t *testing.T) { func TestGenerateBazelTargetModules(t *testing.T) { testCases := []struct { - bp string - expectedBazelTarget string + name string + bp string + expectedBazelTargets []string }{ { bp: `custom { @@ -214,7 +215,7 @@ func TestGenerateBazelTargetModules(t *testing.T) { string_prop: "a", bazel_module: { bp2build_available: true }, }`, - expectedBazelTarget: `custom( + expectedBazelTargets: []string{`custom( name = "foo", string_list_prop = [ "a", @@ -222,6 +223,7 @@ func TestGenerateBazelTargetModules(t *testing.T) { ], string_prop = "a", )`, + }, }, { bp: `custom { @@ -230,7 +232,7 @@ func TestGenerateBazelTargetModules(t *testing.T) { string_prop: "a\t\n\r", bazel_module: { bp2build_available: true }, }`, - expectedBazelTarget: `custom( + expectedBazelTargets: []string{`custom( name = "control_characters", string_list_prop = [ "\t", @@ -238,6 +240,77 @@ func TestGenerateBazelTargetModules(t *testing.T) { ], string_prop = "a\t\n\r", )`, + }, + }, + { + bp: `custom { + name: "has_dep", + arch_paths: [":dep"], + bazel_module: { bp2build_available: true }, +} + +custom { + name: "dep", + arch_paths: ["abc"], + bazel_module: { bp2build_available: true }, +}`, + expectedBazelTargets: []string{`custom( + name = "dep", + arch_paths = ["abc"], +)`, + `custom( + name = "has_dep", + arch_paths = [":dep"], +)`, + }, + }, + { + bp: `custom { + name: "arch_paths", + arch: { + x86: { + arch_paths: ["abc"], + }, + }, + bazel_module: { bp2build_available: true }, +}`, + expectedBazelTargets: []string{`custom( + name = "arch_paths", + arch_paths = select({ + "//build/bazel/platforms/arch:x86": ["abc"], + "//conditions:default": [], + }), +)`, + }, + }, + { + bp: `custom { + name: "has_dep", + arch: { + x86: { + arch_paths: [":dep"], + }, + }, + bazel_module: { bp2build_available: true }, +} + +custom { + name: "dep", + arch_paths: ["abc"], + bazel_module: { bp2build_available: true }, +}`, + expectedBazelTargets: []string{`custom( + name = "dep", + arch_paths = ["abc"], +)`, + `custom( + name = "has_dep", + arch_paths = select({ + "//build/bazel/platforms/arch:x86": [":dep"], + "//conditions:default": [], + }), +)`, + }, }, } @@ -262,16 +335,18 @@ func TestGenerateBazelTargetModules(t *testing.T) { codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build) bazelTargets := generateBazelTargetsForDir(codegenCtx, dir) - if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount { + if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount { t.Errorf("Expected %d bazel target, got %d", expectedCount, actualCount) } else { - actualBazelTarget := bazelTargets[0] - if actualBazelTarget.content != testCase.expectedBazelTarget { - t.Errorf( - "Expected generated Bazel target to be '%s', got '%s'", - testCase.expectedBazelTarget, - actualBazelTarget.content, - ) + for i, expectedBazelTarget := range testCase.expectedBazelTargets { + actualBazelTarget := bazelTargets[i] + if actualBazelTarget.content != expectedBazelTarget { + t.Errorf( + "Expected generated Bazel target to be '%s', got '%s'", + expectedBazelTarget, + actualBazelTarget.content, + ) + } } } } diff --git a/bp2build/bzl_conversion_test.go b/bp2build/bzl_conversion_test.go index 30c1a5b6a..32b12e42e 100644 --- a/bp2build/bzl_conversion_test.go +++ b/bp2build/bzl_conversion_test.go @@ -86,6 +86,7 @@ custom = rule( "soong_module_name": attr.string(mandatory = True), "soong_module_variant": attr.string(), "soong_module_deps": attr.label_list(providers = [SoongModuleInfo]), + "arch_paths": attr.string_list(), # bazel_module start # "label": attr.string(), # "bp2build_available": attr.bool(), @@ -114,6 +115,7 @@ custom_defaults = rule( "soong_module_name": attr.string(mandatory = True), "soong_module_variant": attr.string(), "soong_module_deps": attr.label_list(providers = [SoongModuleInfo]), + "arch_paths": attr.string_list(), "bool_prop": attr.bool(), "bool_ptr_prop": attr.bool(), "int64_ptr_prop": attr.int(), @@ -138,6 +140,7 @@ custom_test_ = rule( "soong_module_name": attr.string(mandatory = True), "soong_module_variant": attr.string(), "soong_module_deps": attr.label_list(providers = [SoongModuleInfo]), + "arch_paths": attr.string_list(), "bool_prop": attr.bool(), "bool_ptr_prop": attr.bool(), "int64_ptr_prop": attr.int(), diff --git a/bp2build/testing.go b/bp2build/testing.go index c4661eaca..452f6ed1a 100644 --- a/bp2build/testing.go +++ b/bp2build/testing.go @@ -28,6 +28,8 @@ type customProps struct { Nested_props nestedProps Nested_props_ptr *nestedProps + + Arch_paths []string `android:"path,arch_variant"` } type customModule struct { @@ -56,7 +58,7 @@ func customModuleFactoryBase() android.Module { func customModuleFactory() android.Module { m := customModuleFactoryBase() - android.InitAndroidModule(m) + android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibBoth) return m } @@ -114,6 +116,7 @@ func customDefaultsModuleFactory() android.Module { type customBazelModuleAttributes struct { String_prop string String_list_prop []string + Arch_paths bazel.LabelListAttribute } type customBazelModule struct { @@ -137,9 +140,18 @@ func customBp2BuildMutator(ctx android.TopDownMutatorContext) { return } + paths := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.props.Arch_paths)) + + for arch, props := range m.GetArchProperties(&customProps{}) { + if archProps, ok := props.(*customProps); ok && archProps.Arch_paths != nil { + paths.SetValueForArch(arch.Name, android.BazelLabelForModuleSrc(ctx, archProps.Arch_paths)) + } + } + attrs := &customBazelModuleAttributes{ String_prop: m.props.String_prop, String_list_prop: m.props.String_list_prop, + Arch_paths: paths, } props := bazel.BazelTargetModuleProperties{ diff --git a/cc/androidmk.go b/cc/androidmk.go index 536efa433..8f3a652e6 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -191,17 +191,31 @@ func makeOverrideModuleNames(ctx AndroidMkContext, overrides []string) []string } func (library *libraryDecorator) androidMkWriteExportedFlags(entries *android.AndroidMkEntries) { - exportedFlags := library.flagExporter.flags - for _, dir := range library.flagExporter.dirs { + var exportedFlags []string + var includeDirs android.Paths + var systemIncludeDirs android.Paths + var exportedDeps android.Paths + + if library.flagExporterInfo != nil { + exportedFlags = library.flagExporterInfo.Flags + includeDirs = library.flagExporterInfo.IncludeDirs + systemIncludeDirs = library.flagExporterInfo.SystemIncludeDirs + exportedDeps = library.flagExporterInfo.Deps + } else { + exportedFlags = library.flagExporter.flags + includeDirs = library.flagExporter.dirs + systemIncludeDirs = library.flagExporter.systemDirs + exportedDeps = library.flagExporter.deps + } + for _, dir := range includeDirs { exportedFlags = append(exportedFlags, "-I"+dir.String()) } - for _, dir := range library.flagExporter.systemDirs { + for _, dir := range systemIncludeDirs { exportedFlags = append(exportedFlags, "-isystem "+dir.String()) } if len(exportedFlags) > 0 { entries.AddStrings("LOCAL_EXPORT_CFLAGS", exportedFlags...) } - exportedDeps := library.flagExporter.deps if len(exportedDeps) > 0 { entries.AddStrings("LOCAL_EXPORT_C_INCLUDE_DEPS", exportedDeps.Strings()...) } diff --git a/cc/genrule.go b/cc/genrule.go index 82d7205da..ca4fda7e2 100644 --- a/cc/genrule.go +++ b/cc/genrule.go @@ -75,10 +75,6 @@ func (g *GenruleExtraProperties) VendorRamdiskVariantNeeded(ctx android.BaseModu return Bool(g.Vendor_ramdisk_available) } -func (g *GenruleExtraProperties) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { - return false -} - func (g *GenruleExtraProperties) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { // If the build is using a snapshot, the recovery variant under AOSP directories // is not needed. diff --git a/cc/image.go b/cc/image.go index bf662c64f..c1e5dfeec 100644 --- a/cc/image.go +++ b/cc/image.go @@ -601,10 +601,6 @@ func (c *Module) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool return c.Properties.VendorRamdiskVariantNeeded } -func (c *Module) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { - return false -} - func (c *Module) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { return c.Properties.RecoveryVariantNeeded } diff --git a/cc/library.go b/cc/library.go index 8acd7c728..af92b24b7 100644 --- a/cc/library.go +++ b/cc/library.go @@ -426,7 +426,8 @@ type libraryDecorator struct { tocFile android.OptionalPath flagExporter - stripper Stripper + flagExporterInfo *FlagExporterInfo + stripper Stripper // For whole_static_libs objects Objects diff --git a/cc/library_headers.go b/cc/library_headers.go index 078242fab..f2cb52baf 100644 --- a/cc/library_headers.go +++ b/cc/library_headers.go @@ -43,6 +43,52 @@ func RegisterLibraryHeadersBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("cc_prebuilt_library_headers", prebuiltLibraryHeaderFactory) } +type libraryHeaderBazelHander struct { + bazelHandler + + module *Module + library *libraryDecorator +} + +func (h *libraryHeaderBazelHander) generateBazelBuildActions(ctx android.ModuleContext, label string) bool { + bazelCtx := ctx.Config().BazelContext + ccInfo, ok, err := bazelCtx.GetCcInfo(label, ctx.Arch().ArchType) + if err != nil { + ctx.ModuleErrorf("Error getting Bazel CcInfo: %s", err) + return false + } + if !ok { + return false + } + + outputPaths := ccInfo.OutputFiles + if len(outputPaths) != 1 { + ctx.ModuleErrorf("expected exactly one output file for %q, but got %q", label, outputPaths) + return false + } + + outputPath := android.PathForBazelOut(ctx, outputPaths[0]) + h.module.outputFile = android.OptionalPathForPath(outputPath) + + // HeaderLibraryInfo is an empty struct to indicate to dependencies that this is a header library + ctx.SetProvider(HeaderLibraryInfoProvider, HeaderLibraryInfo{}) + + flagExporterInfo := flagExporterInfoFromCcInfo(ctx, ccInfo) + // Store flag info to be passed along to androimk + // TODO(b/184387147): Androidmk should be done in Bazel, not Soong. + h.library.flagExporterInfo = &flagExporterInfo + // flag exporters consolidates properties like includes, flags, dependencies that should be + // exported from this module to other modules + ctx.SetProvider(FlagExporterInfoProvider, flagExporterInfo) + + // Dependencies on this library will expect collectedSnapshotHeaders to be set, otherwise + // validation will fail. For now, set this to an empty list. + // TODO(cparsons): More closely mirror the collectHeadersForSnapshot implementation. + h.library.collectedSnapshotHeaders = android.Paths{} + + return true +} + // cc_library_headers contains a set of c/c++ headers which are imported by // other soong cc modules using the header_libs property. For best practices, // use export_include_dirs property or LOCAL_EXPORT_C_INCLUDE_DIRS for @@ -51,6 +97,7 @@ func LibraryHeaderFactory() android.Module { module, library := NewLibrary(android.HostAndDeviceSupported) library.HeaderOnly() module.sdkMemberTypes = []android.SdkMemberType{headersLibrarySdkMemberType} + module.bazelHandler = &libraryHeaderBazelHander{module: module, library: library} return module.Init() } diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go index d5f2adf8b..9010a1a89 100644 --- a/cc/library_sdk_member.go +++ b/cc/library_sdk_member.go @@ -162,9 +162,16 @@ func (mt *librarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMembe return &nativeLibInfoProperties{memberType: mt} } +func isBazelOutDirectory(p android.Path) bool { + _, bazel := p.(android.BazelOutPath) + return bazel +} + func isGeneratedHeaderDirectory(p android.Path) bool { _, gen := p.(android.WritablePath) - return gen + // TODO(b/183213331): Here we assume that bazel-based headers are not generated; we need + // to support generated headers in mixed builds. + return gen && !isBazelOutDirectory(p) } type includeDirsProperty struct { diff --git a/cc/linkable.go b/cc/linkable.go index 0fb9c0944..2fa12f61c 100644 --- a/cc/linkable.go +++ b/cc/linkable.go @@ -2,6 +2,7 @@ package cc import ( "android/soong/android" + "android/soong/bazel/cquery" "github.com/google/blueprint" ) @@ -274,3 +275,15 @@ type FlagExporterInfo struct { } var FlagExporterInfoProvider = blueprint.NewProvider(FlagExporterInfo{}) + +// flagExporterInfoFromCcInfo populates FlagExporterInfo provider with information from Bazel. +func flagExporterInfoFromCcInfo(ctx android.ModuleContext, ccInfo cquery.CcInfo) FlagExporterInfo { + + includes := android.PathsForBazelOut(ctx, ccInfo.Includes) + systemIncludes := android.PathsForBazelOut(ctx, ccInfo.SystemIncludes) + + return FlagExporterInfo{ + IncludeDirs: includes, + SystemIncludeDirs: systemIncludes, + } +} diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go index 885a0ce6d..c12ad7920 100644 --- a/cc/snapshot_prebuilt.go +++ b/cc/snapshot_prebuilt.go @@ -308,10 +308,6 @@ func (s *snapshot) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) boo return false } -func (s *snapshot) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { - return false -} - func (s *snapshot) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { return false } diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go index 3204e706e..6e502b76a 100644 --- a/etc/prebuilt_etc.go +++ b/etc/prebuilt_etc.go @@ -84,13 +84,6 @@ type prebuiltEtcProperties struct { // the recovery variant instead. Vendor_ramdisk_available *bool - // Make this module available when building for debug ramdisk. - // On device without a dedicated recovery partition, the module is only - // available after switching root into - // /first_stage_ramdisk. To expose the module before switching root, install - // the recovery variant instead. - Debug_ramdisk_available *bool - // Make this module available when building for recovery. Recovery_available *bool @@ -166,18 +159,6 @@ func (p *PrebuiltEtc) InstallInVendorRamdisk() bool { return p.inVendorRamdisk() } -func (p *PrebuiltEtc) inDebugRamdisk() bool { - return p.ModuleBase.InDebugRamdisk() || p.ModuleBase.InstallInDebugRamdisk() -} - -func (p *PrebuiltEtc) onlyInDebugRamdisk() bool { - return p.ModuleBase.InstallInDebugRamdisk() -} - -func (p *PrebuiltEtc) InstallInDebugRamdisk() bool { - return p.inDebugRamdisk() -} - func (p *PrebuiltEtc) inRecovery() bool { return p.ModuleBase.InRecovery() || p.ModuleBase.InstallInRecovery() } @@ -196,7 +177,7 @@ func (p *PrebuiltEtc) ImageMutatorBegin(ctx android.BaseModuleContext) {} func (p *PrebuiltEtc) CoreVariantNeeded(ctx android.BaseModuleContext) bool { return !p.ModuleBase.InstallInRecovery() && !p.ModuleBase.InstallInRamdisk() && - !p.ModuleBase.InstallInVendorRamdisk() && !p.ModuleBase.InstallInDebugRamdisk() + !p.ModuleBase.InstallInVendorRamdisk() } func (p *PrebuiltEtc) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool { @@ -207,10 +188,6 @@ func (p *PrebuiltEtc) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) return proptools.Bool(p.properties.Vendor_ramdisk_available) || p.ModuleBase.InstallInVendorRamdisk() } -func (p *PrebuiltEtc) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { - return proptools.Bool(p.properties.Debug_ramdisk_available) || p.ModuleBase.InstallInDebugRamdisk() -} - func (p *PrebuiltEtc) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { return proptools.Bool(p.properties.Recovery_available) || p.ModuleBase.InstallInRecovery() } @@ -336,9 +313,6 @@ func (p *PrebuiltEtc) AndroidMkEntries() []android.AndroidMkEntries { if p.inVendorRamdisk() && !p.onlyInVendorRamdisk() { nameSuffix = ".vendor_ramdisk" } - if p.inDebugRamdisk() && !p.onlyInDebugRamdisk() { - nameSuffix = ".debug_ramdisk" - } if p.inRecovery() && !p.onlyInRecovery() { nameSuffix = ".recovery" } diff --git a/genrule/genrule.go b/genrule/genrule.go index 77dae755a..b426b207a 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -626,7 +626,6 @@ func (x noopImageInterface) ImageMutatorBegin(android.BaseModuleContext) func (x noopImageInterface) CoreVariantNeeded(android.BaseModuleContext) bool { return false } func (x noopImageInterface) RamdiskVariantNeeded(android.BaseModuleContext) bool { return false } func (x noopImageInterface) VendorRamdiskVariantNeeded(android.BaseModuleContext) bool { return false } -func (x noopImageInterface) DebugRamdiskVariantNeeded(android.BaseModuleContext) bool { return false } func (x noopImageInterface) RecoveryVariantNeeded(android.BaseModuleContext) bool { return false } func (x noopImageInterface) ExtraImageVariations(ctx android.BaseModuleContext) []string { return nil } func (x noopImageInterface) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) { diff --git a/java/Android.bp b/java/Android.bp index 8e3e10d9d..a17140ce1 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -29,8 +29,9 @@ bootstrap_go_package { "app_import.go", "app_set.go", "base.go", - "boot_image.go", "boot_jars.go", + "bootclasspath.go", + "bootclasspath_fragment.go", "builder.go", "classpath_fragment.go", "device_host_converter.go", @@ -72,7 +73,7 @@ bootstrap_go_package { "app_import_test.go", "app_set_test.go", "app_test.go", - "boot_image_test.go", + "bootclasspath_fragment_test.go", "device_host_converter_test.go", "dexpreopt_test.go", "dexpreopt_bootjars_test.go", diff --git a/java/bootclasspath.go b/java/bootclasspath.go new file mode 100644 index 000000000..6ca0f7533 --- /dev/null +++ b/java/bootclasspath.go @@ -0,0 +1,172 @@ +// 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 ( + "fmt" + + "android/soong/android" + "github.com/google/blueprint" + "github.com/google/blueprint/proptools" +) + +// Contains code that is common to both platform_bootclasspath and bootclasspath_fragment. + +func init() { + registerBootclasspathBuildComponents(android.InitRegistrationContext) +} + +func registerBootclasspathBuildComponents(ctx android.RegistrationContext) { + ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) { + ctx.BottomUp("bootclasspath_deps", bootclasspathDepsMutator) + }) +} + +// BootclasspathDepsMutator is the interface that a module must implement if it wants to add +// dependencies onto APEX specific variants of bootclasspath fragments or bootclasspath contents. +type BootclasspathDepsMutator interface { + // BootclasspathDepsMutator implementations should add dependencies using + // addDependencyOntoApexModulePair and addDependencyOntoApexVariants. + BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) +} + +// bootclasspathDepsMutator is called during the final deps phase after all APEX variants have +// been created so can add dependencies onto specific APEX variants of modules. +func bootclasspathDepsMutator(ctx android.BottomUpMutatorContext) { + m := ctx.Module() + if p, ok := m.(BootclasspathDepsMutator); ok { + p.BootclasspathDepsMutator(ctx) + } +} + +// addDependencyOntoApexVariants adds dependencies onto the appropriate apex specific variants of +// the module as specified in the ApexVariantReference list. +func addDependencyOntoApexVariants(ctx android.BottomUpMutatorContext, propertyName string, refs []ApexVariantReference, tag blueprint.DependencyTag) { + for i, ref := range refs { + apex := proptools.StringDefault(ref.Apex, "platform") + + if ref.Module == nil { + ctx.PropertyErrorf(propertyName, "missing module name at position %d", i) + continue + } + name := proptools.String(ref.Module) + + addDependencyOntoApexModulePair(ctx, apex, name, tag) + } +} + +// addDependencyOntoApexModulePair adds a dependency onto the specified APEX specific variant or the +// specified module. +// +// If apex="platform" then this adds a dependency onto the platform variant of the module. This adds +// dependencies onto the prebuilt and source modules with the specified name, depending on which +// ones are available. Visiting must use isActiveModule to select the preferred module when both +// source and prebuilt modules are available. +func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex string, name string, tag blueprint.DependencyTag) { + var variations []blueprint.Variation + if apex != "platform" { + // Pick the correct apex variant. + variations = []blueprint.Variation{ + {Mutator: "apex", Variation: apex}, + } + } + + addedDep := false + if ctx.OtherModuleDependencyVariantExists(variations, name) { + ctx.AddFarVariationDependencies(variations, tag, name) + addedDep = true + } + + // Add a dependency on the prebuilt module if it exists. + prebuiltName := android.PrebuiltNameFromSource(name) + if ctx.OtherModuleDependencyVariantExists(variations, prebuiltName) { + ctx.AddVariationDependencies(variations, tag, prebuiltName) + addedDep = true + } + + // If no appropriate variant existing for this, so no dependency could be added, then it is an + // error, unless missing dependencies are allowed. The simplest way to handle that is to add a + // dependency that will not be satisfied and the default behavior will handle it. + if !addedDep { + // Add dependency on the unprefixed (i.e. source or renamed prebuilt) module which we know does + // not exist. The resulting error message will contain useful information about the available + // variants. + reportMissingVariationDependency(ctx, variations, name) + + // Add dependency on the missing prefixed prebuilt variant too if a module with that name exists + // so that information about its available variants will be reported too. + if ctx.OtherModuleExists(prebuiltName) { + reportMissingVariationDependency(ctx, variations, prebuiltName) + } + } +} + +// reportMissingVariationDependency intentionally adds a dependency on a missing variation in order +// to generate an appropriate error message with information about the available variations. +func reportMissingVariationDependency(ctx android.BottomUpMutatorContext, variations []blueprint.Variation, name string) { + modules := ctx.AddFarVariationDependencies(variations, nil, name) + if len(modules) != 1 { + panic(fmt.Errorf("Internal Error: expected one module, found %d", len(modules))) + return + } + if modules[0] != nil { + panic(fmt.Errorf("Internal Error: expected module to be missing but was found: %q", modules[0])) + return + } +} + +// ApexVariantReference specifies a particular apex variant of a module. +type ApexVariantReference struct { + // The name of the module apex variant, i.e. the apex containing the module variant. + // + // If this is not specified then it defaults to "platform" which will cause a dependency to be + // added to the module's platform variant. + Apex *string + + // The name of the module. + Module *string +} + +// BootclasspathFragmentsDepsProperties contains properties related to dependencies onto fragments. +type BootclasspathFragmentsDepsProperties struct { + // The names of the bootclasspath_fragment modules that form part of this module. + Fragments []ApexVariantReference +} + +// addDependenciesOntoFragments adds dependencies to the fragments specified in this properties +// structure. +func (p *BootclasspathFragmentsDepsProperties) addDependenciesOntoFragments(ctx android.BottomUpMutatorContext) { + addDependencyOntoApexVariants(ctx, "fragments", p.Fragments, bootclasspathFragmentDepTag) +} + +// bootclasspathDependencyTag defines dependencies from/to bootclasspath_fragment, +// prebuilt_bootclasspath_fragment and platform_bootclasspath onto either source or prebuilt +// modules. +type bootclasspathDependencyTag struct { + blueprint.BaseDependencyTag + + name string +} + +func (t bootclasspathDependencyTag) ExcludeFromVisibilityEnforcement() { +} + +// Dependencies that use the bootclasspathDependencyTag instances are only added after all the +// visibility checking has been done so this has no functional effect. However, it does make it +// clear that visibility is not being enforced on these tags. +var _ android.ExcludeFromVisibilityEnforcementTag = bootclasspathDependencyTag{} + +// The tag used for dependencies onto bootclasspath_fragments. +var bootclasspathFragmentDepTag = bootclasspathDependencyTag{name: "fragment"} diff --git a/java/boot_image.go b/java/bootclasspath_fragment.go index d0862a961..619d47fcf 100644 --- a/java/boot_image.go +++ b/java/bootclasspath_fragment.go @@ -27,17 +27,9 @@ import ( ) func init() { - RegisterBootImageBuildComponents(android.InitRegistrationContext) + registerBootclasspathFragmentBuildComponents(android.InitRegistrationContext) - // TODO(b/177892522): Remove after has been replaced by bootclasspath_fragments - android.RegisterSdkMemberType(&bootImageMemberType{ - SdkMemberTypeBase: android.SdkMemberTypeBase{ - PropertyName: "boot_images", - SupportsSdk: true, - }, - }) - - android.RegisterSdkMemberType(&bootImageMemberType{ + android.RegisterSdkMemberType(&bootclasspathFragmentMemberType{ SdkMemberTypeBase: android.SdkMemberTypeBase{ PropertyName: "bootclasspath_fragments", SupportsSdk: true, @@ -45,23 +37,19 @@ func init() { }) } -func RegisterBootImageBuildComponents(ctx android.RegistrationContext) { - // TODO(b/177892522): Remove after has been replaced by bootclasspath_fragment - ctx.RegisterModuleType("boot_image", bootImageFactory) - ctx.RegisterModuleType("prebuilt_boot_image", prebuiltBootImageFactory) - - ctx.RegisterModuleType("bootclasspath_fragment", bootImageFactory) - ctx.RegisterModuleType("prebuilt_bootclasspath_fragment", prebuiltBootImageFactory) +func registerBootclasspathFragmentBuildComponents(ctx android.RegistrationContext) { + ctx.RegisterModuleType("bootclasspath_fragment", bootclasspathFragmentFactory) + ctx.RegisterModuleType("prebuilt_bootclasspath_fragment", prebuiltBootclasspathFragmentFactory) } type bootclasspathFragmentContentDependencyTag struct { blueprint.BaseDependencyTag } -// Avoid having to make boot image content visible to the boot image. +// Avoid having to make bootclasspath_fragment content visible to the bootclasspath_fragment. // -// This is a temporary workaround to make it easier to migrate to boot image modules with proper -// dependencies. +// This is a temporary workaround to make it easier to migrate to bootclasspath_fragment modules +// with proper dependencies. // TODO(b/177892522): Remove this and add needed visibility. func (b bootclasspathFragmentContentDependencyTag) ExcludeFromVisibilityEnforcement() { } @@ -71,7 +59,7 @@ func (b bootclasspathFragmentContentDependencyTag) ReplaceSourceWithPrebuilt() b return false } -// The tag used for the dependency between the boot image module and its contents. +// The tag used for the dependency between the bootclasspath_fragment module and its contents. var bootclasspathFragmentContentDepTag = bootclasspathFragmentContentDependencyTag{} var _ android.ExcludeFromVisibilityEnforcementTag = bootclasspathFragmentContentDepTag @@ -81,13 +69,13 @@ func IsBootclasspathFragmentContentDepTag(tag blueprint.DependencyTag) bool { return tag == bootclasspathFragmentContentDepTag } -type bootImageProperties struct { +type bootclasspathFragmentProperties struct { // The name of the image this represents. // // If specified then it must be one of "art" or "boot". Image_name *string - // The contents of this boot image, could be either java_library, java_sdk_library, or boot_image. + // The contents of this bootclasspath_fragment, could be either java_library, java_sdk_library, or boot_image. // // The order of this list matters as it is the order that is used in the bootclasspath. Contents []string @@ -95,28 +83,30 @@ type bootImageProperties struct { Hidden_api HiddenAPIFlagFileProperties } -type BootImageModule struct { +type BootclasspathFragmentModule struct { android.ModuleBase android.ApexModuleBase android.SdkBase - properties bootImageProperties + properties bootclasspathFragmentProperties } -func bootImageFactory() android.Module { - m := &BootImageModule{} +func bootclasspathFragmentFactory() android.Module { + m := &BootclasspathFragmentModule{} m.AddProperties(&m.properties) android.InitApexModule(m) android.InitSdkAwareModule(m) android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon) - // Perform some consistency checking to ensure that the configuration is correct. + // Initialize the contents property from the image_name. android.AddLoadHook(m, func(ctx android.LoadHookContext) { - bootImageConsistencyCheck(ctx, m) + bootclasspathFragmentInitContentsFromImage(ctx, m) }) return m } -func bootImageConsistencyCheck(ctx android.EarlyModuleContext, m *BootImageModule) { +// bootclasspathFragmentInitContentsFromImage will initialize the contents property from the image_name if +// necessary. +func bootclasspathFragmentInitContentsFromImage(ctx android.EarlyModuleContext, m *BootclasspathFragmentModule) { contents := m.properties.Contents if m.properties.Image_name == nil && len(contents) == 0 { ctx.ModuleErrorf(`neither of the "image_name" and "contents" properties have been supplied, please supply exactly one`) @@ -124,8 +114,22 @@ func bootImageConsistencyCheck(ctx android.EarlyModuleContext, m *BootImageModul if m.properties.Image_name != nil && len(contents) != 0 { ctx.ModuleErrorf(`both of the "image_name" and "contents" properties have been supplied, please supply exactly one`) } + imageName := proptools.String(m.properties.Image_name) if imageName == "art" { + // TODO(b/177892522): Prebuilts (versioned or not) should not use the image_name property. + if m.MemberName() != "" { + // The module is a versioned prebuilt so ignore it. This is done for a couple of reasons: + // 1. There is no way to use this at the moment so ignoring it is safe. + // 2. Attempting to initialize the contents property from the configuration will end up having + // the versioned prebuilt depending on the unversioned prebuilt. That will cause problems + // as the unversioned prebuilt could end up with an APEX variant created for the source + // APEX which will prevent it from having an APEX variant for the prebuilt APEX which in + // turn will prevent it from accessing the dex implementation jar from that which will + // break hidden API processing, amongst others. + return + } + // Get the configuration for the art apex jars. Do not use getImageConfig(ctx) here as this is // too early in the Soong processing for that to work. global := dexpreopt.GetGlobalConfig(ctx) @@ -192,7 +196,7 @@ func (i BootImageInfo) AndroidBootImageFilesByArchType() map[android.ArchType]an return files } -func (b *BootImageModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { +func (b *BootclasspathFragmentModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { tag := ctx.OtherModuleDependencyTag(dep) if IsBootclasspathFragmentContentDepTag(tag) { // Boot image contents are automatically added to apex. @@ -205,7 +209,7 @@ func (b *BootImageModule) DepIsInSameApex(ctx android.BaseModuleContext, dep and panic(fmt.Errorf("boot_image module %q should not have a dependency on %q via tag %s", b, dep, android.PrettyPrintTag(tag))) } -func (b *BootImageModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error { +func (b *BootclasspathFragmentModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error { return nil } @@ -213,9 +217,9 @@ func (b *BootImageModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, // corresponding source module are renamed. This means that adding a dependency using a name without // a prebuilt_ prefix will always resolve to a source module and when using a name with that prefix // it will always resolve to a prebuilt module. -func (b *BootImageModule) ComponentDepsMutator(ctx android.BottomUpMutatorContext) { +func (b *BootclasspathFragmentModule) ComponentDepsMutator(ctx android.BottomUpMutatorContext) { module := ctx.Module() - _, isSourceModule := module.(*BootImageModule) + _, isSourceModule := module.(*BootclasspathFragmentModule) for _, name := range b.properties.Contents { // A bootclasspath_fragment must depend only on other source modules, while the @@ -230,7 +234,7 @@ func (b *BootImageModule) ComponentDepsMutator(ctx android.BottomUpMutatorContex } -func (b *BootImageModule) DepsMutator(ctx android.BottomUpMutatorContext) { +func (b *BootclasspathFragmentModule) DepsMutator(ctx android.BottomUpMutatorContext) { if SkipDexpreoptBootJars(ctx) { return @@ -241,7 +245,7 @@ func (b *BootImageModule) DepsMutator(ctx android.BottomUpMutatorContext) { dexpreopt.RegisterToolDeps(ctx) } -func (b *BootImageModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { +func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { // Perform hidden API processing. b.generateHiddenAPIBuildActions(ctx) @@ -266,7 +270,7 @@ func (b *BootImageModule) GenerateAndroidBuildActions(ctx android.ModuleContext) ctx.SetProvider(BootImageInfoProvider, info) } -func (b *BootImageModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig { +func (b *BootclasspathFragmentModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig { // Get a map of the image configs that are supported. imageConfigs := genBootImageConfigs(ctx) @@ -286,7 +290,7 @@ func (b *BootImageModule) getImageConfig(ctx android.EarlyModuleContext) *bootIm } // generateHiddenAPIBuildActions generates all the hidden API related build rules. -func (b *BootImageModule) generateHiddenAPIBuildActions(ctx android.ModuleContext) { +func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext) { // Resolve the properties to paths. flagFileInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx) @@ -294,20 +298,20 @@ func (b *BootImageModule) generateHiddenAPIBuildActions(ctx android.ModuleContex ctx.SetProvider(hiddenAPIFlagFileInfoProvider, flagFileInfo) } -type bootImageMemberType struct { +type bootclasspathFragmentMemberType struct { android.SdkMemberTypeBase } -func (b *bootImageMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) { +func (b *bootclasspathFragmentMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) { mctx.AddVariationDependencies(nil, dependencyTag, names...) } -func (b *bootImageMemberType) IsInstance(module android.Module) bool { - _, ok := module.(*BootImageModule) +func (b *bootclasspathFragmentMemberType) IsInstance(module android.Module) bool { + _, ok := module.(*BootclasspathFragmentModule) return ok } -func (b *bootImageMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule { +func (b *bootclasspathFragmentMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule { if b.PropertyName == "boot_images" { return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_boot_image") } else { @@ -315,11 +319,11 @@ func (b *bootImageMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, me } } -func (b *bootImageMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties { - return &bootImageSdkMemberProperties{} +func (b *bootclasspathFragmentMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties { + return &bootclasspathFragmentSdkMemberProperties{} } -type bootImageSdkMemberProperties struct { +type bootclasspathFragmentSdkMemberProperties struct { android.SdkMemberPropertiesBase // The image name @@ -332,8 +336,8 @@ type bootImageSdkMemberProperties struct { Flag_files_by_category map[*hiddenAPIFlagFileCategory]android.Paths } -func (b *bootImageSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) { - module := variant.(*BootImageModule) +func (b *bootclasspathFragmentSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) { + module := variant.(*BootclasspathFragmentModule) b.Image_name = module.properties.Image_name if b.Image_name == nil { @@ -349,7 +353,7 @@ func (b *bootImageSdkMemberProperties) PopulateFromVariant(ctx android.SdkMember b.Flag_files_by_category = flagFileInfo.categoryToPaths } -func (b *bootImageSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) { +func (b *bootclasspathFragmentSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) { if b.Image_name != nil { propertySet.AddProperty("image_name", *b.Image_name) } @@ -376,28 +380,28 @@ func (b *bootImageSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberCon } } -var _ android.SdkMemberType = (*bootImageMemberType)(nil) +var _ android.SdkMemberType = (*bootclasspathFragmentMemberType)(nil) -// A prebuilt version of the boot image module. +// A prebuilt version of the bootclasspath_fragment module. // -// At the moment this is basically just a boot image module that can be used as a prebuilt. -// Eventually as more functionality is migrated into the boot image module from the singleton then -// this will diverge. -type prebuiltBootImageModule struct { - BootImageModule +// At the moment this is basically just a bootclasspath_fragment module that can be used as a +// prebuilt. Eventually as more functionality is migrated into the bootclasspath_fragment module +// type from the various singletons then this will diverge. +type prebuiltBootclasspathFragmentModule struct { + BootclasspathFragmentModule prebuilt android.Prebuilt } -func (module *prebuiltBootImageModule) Prebuilt() *android.Prebuilt { +func (module *prebuiltBootclasspathFragmentModule) Prebuilt() *android.Prebuilt { return &module.prebuilt } -func (module *prebuiltBootImageModule) Name() string { +func (module *prebuiltBootclasspathFragmentModule) Name() string { return module.prebuilt.Name(module.ModuleBase.Name()) } -func prebuiltBootImageFactory() android.Module { - m := &prebuiltBootImageModule{} +func prebuiltBootclasspathFragmentFactory() android.Module { + m := &prebuiltBootclasspathFragmentModule{} m.AddProperties(&m.properties) // This doesn't actually have any prebuilt files of its own so pass a placeholder for the srcs // array. @@ -406,9 +410,9 @@ func prebuiltBootImageFactory() android.Module { android.InitSdkAwareModule(m) android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon) - // Perform some consistency checking to ensure that the configuration is correct. + // Initialize the contents property from the image_name. android.AddLoadHook(m, func(ctx android.LoadHookContext) { - bootImageConsistencyCheck(ctx, &m.BootImageModule) + bootclasspathFragmentInitContentsFromImage(ctx, &m.BootclasspathFragmentModule) }) return m } diff --git a/java/boot_image_test.go b/java/bootclasspath_fragment_test.go index e1866dedc..524a2269b 100644 --- a/java/boot_image_test.go +++ b/java/bootclasspath_fragment_test.go @@ -21,60 +21,60 @@ import ( "android/soong/dexpreopt" ) -// Contains some simple tests for boot_image logic, additional tests can be found in -// apex/boot_image_test.go as the ART boot image requires modules from the ART apex. +// Contains some simple tests for bootclasspath_fragment logic, additional tests can be found in +// apex/bootclasspath_fragment_test.go as the ART boot image requires modules from the ART apex. -var prepareForTestWithBootImage = android.GroupFixturePreparers( +var prepareForTestWithBootclasspathFragment = android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, dexpreopt.PrepareForTestByEnablingDexpreopt, ) -func TestUnknownBootImage(t *testing.T) { - prepareForTestWithBootImage. +func TestUnknownBootclasspathFragment(t *testing.T) { + prepareForTestWithBootclasspathFragment. ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern( `\Qimage_name: Unknown image name "unknown", expected one of art, boot\E`)). RunTestWithBp(t, ` - boot_image { - name: "unknown-boot-image", + bootclasspath_fragment { + name: "unknown-bootclasspath-fragment", image_name: "unknown", } `) } func TestUnknownBootclasspathFragmentImageName(t *testing.T) { - prepareForTestWithBootImage. + prepareForTestWithBootclasspathFragment. ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern( `\Qimage_name: Unknown image name "unknown", expected one of art, boot\E`)). RunTestWithBp(t, ` bootclasspath_fragment { - name: "unknown-boot-image", + name: "unknown-bootclasspath-fragment", image_name: "unknown", } `) } -func TestUnknownPrebuiltBootImage(t *testing.T) { - prepareForTestWithBootImage. +func TestUnknownPrebuiltBootclasspathFragment(t *testing.T) { + prepareForTestWithBootclasspathFragment. ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern( `\Qimage_name: Unknown image name "unknown", expected one of art, boot\E`)). RunTestWithBp(t, ` - prebuilt_boot_image { - name: "unknown-boot-image", + prebuilt_bootclasspath_fragment { + name: "unknown-bootclasspath-fragment", image_name: "unknown", } `) } -func TestBootImageInconsistentArtConfiguration_Platform(t *testing.T) { +func TestBootclasspathFragmentInconsistentArtConfiguration_Platform(t *testing.T) { android.GroupFixturePreparers( - prepareForTestWithBootImage, + prepareForTestWithBootclasspathFragment, dexpreopt.FixtureSetArtBootJars("platform:foo", "apex:bar"), ). ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern( `\QArtApexJars is invalid as it requests a platform variant of "foo"\E`)). RunTestWithBp(t, ` - boot_image { - name: "boot-image", + bootclasspath_fragment { + name: "bootclasspath-fragment", image_name: "art", apex_available: [ "apex", @@ -83,16 +83,16 @@ func TestBootImageInconsistentArtConfiguration_Platform(t *testing.T) { `) } -func TestBootImageInconsistentArtConfiguration_ApexMixture(t *testing.T) { +func TestBootclasspathFragmentInconsistentArtConfiguration_ApexMixture(t *testing.T) { android.GroupFixturePreparers( - prepareForTestWithBootImage, + prepareForTestWithBootclasspathFragment, dexpreopt.FixtureSetArtBootJars("apex1:foo", "apex2:bar"), ). ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern( `\QArtApexJars configuration is inconsistent, expected all jars to be in the same apex but it specifies apex "apex1" and "apex2"\E`)). RunTestWithBp(t, ` - boot_image { - name: "boot-image", + bootclasspath_fragment { + name: "bootclasspath-fragment", image_name: "art", apex_available: [ "apex1", @@ -102,24 +102,24 @@ func TestBootImageInconsistentArtConfiguration_ApexMixture(t *testing.T) { `) } -func TestBootImageWithoutImageNameOrContents(t *testing.T) { - prepareForTestWithBootImage. +func TestBootclasspathFragmentWithoutImageNameOrContents(t *testing.T) { + prepareForTestWithBootclasspathFragment. ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern( `\Qneither of the "image_name" and "contents" properties\E`)). RunTestWithBp(t, ` - boot_image { - name: "boot-image", + bootclasspath_fragment { + name: "bootclasspath-fragment", } `) } -func TestBootImageWithImageNameAndContents(t *testing.T) { - prepareForTestWithBootImage. +func TestBootclasspathFragmentWithImageNameAndContents(t *testing.T) { + prepareForTestWithBootclasspathFragment. ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern( `\Qboth of the "image_name" and "contents" properties\E`)). RunTestWithBp(t, ` - boot_image { - name: "boot-image", + bootclasspath_fragment { + name: "bootclasspath-fragment", image_name: "boot", contents: ["other"], } diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go index 656f5ef71..0ab650287 100644 --- a/java/dexpreopt_config.go +++ b/java/dexpreopt_config.go @@ -236,9 +236,5 @@ func init() { } func dexpreoptConfigMakevars(ctx android.MakeVarsContext) { - ctx.Strict("PRODUCT_BOOTCLASSPATH", strings.Join(defaultBootclasspath(ctx), ":")) - ctx.Strict("PRODUCT_DEX2OAT_BOOTCLASSPATH", strings.Join(defaultBootImageConfig(ctx).getAnyAndroidVariant().dexLocationsDeps, ":")) - ctx.Strict("PRODUCT_SYSTEM_SERVER_CLASSPATH", strings.Join(systemServerClasspath(ctx), ":")) - ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules.CopyOfApexJarPairs(), ":")) } diff --git a/java/hiddenapi.go b/java/hiddenapi.go index e57508546..bc3b4746a 100644 --- a/java/hiddenapi.go +++ b/java/hiddenapi.go @@ -84,6 +84,11 @@ type hiddenAPI struct { // created by the unsupported app usage annotation processor during compilation of the class // implementation jar. indexCSVPath android.Path + + // The paths to the classes jars that contain classes and class members annotated with + // the UnsupportedAppUsage annotation that need to be extracted as part of the hidden API + // processing. + classesJarPaths android.Paths } func (h *hiddenAPI) flagsCSV() android.Path { @@ -102,11 +107,16 @@ func (h *hiddenAPI) indexCSV() android.Path { return h.indexCSVPath } +func (h *hiddenAPI) classesJars() android.Paths { + return h.classesJarPaths +} + type hiddenAPIIntf interface { bootDexJar() android.Path flagsCSV() android.Path indexCSV() android.Path metadataCSV() android.Path + classesJars() android.Paths } var _ hiddenAPIIntf = (*hiddenAPI)(nil) @@ -244,6 +254,7 @@ func (h *hiddenAPI) hiddenAPIExtractInformation(ctx android.ModuleContext, dexJa javaInfo := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo) classesJars = append(classesJars, javaInfo.ImplementationJars...) }) + h.classesJarPaths = classesJars stubFlagsCSV := hiddenAPISingletonPaths(ctx).stubFlags diff --git a/java/lint.go b/java/lint.go index 862c9b4d9..5e392742c 100644 --- a/java/lint.go +++ b/java/lint.go @@ -261,6 +261,7 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.Ru cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks) if BoolDefault(l.properties.Lint.Strict_updatability_linting, false) { + // Verify the module does not baseline issues that endanger safe updatability. if baselinePath := l.getBaselineFilepath(ctx); baselinePath.Valid() { cmd.FlagWithInput("--baseline ", baselinePath.Path()) cmd.FlagForEachArg("--disallowed_issues ", updatabilityChecks) diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index 568f5e406..b1a0ac43f 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -19,8 +19,6 @@ import ( "android/soong/android" "android/soong/dexpreopt" - "github.com/google/blueprint" - "github.com/google/blueprint/proptools" ) func init() { @@ -29,33 +27,10 @@ func init() { func registerPlatformBootclasspathBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("platform_bootclasspath", platformBootclasspathFactory) - - ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) { - ctx.BottomUp("platform_bootclasspath_deps", platformBootclasspathDepsMutator) - }) -} - -type platformBootclasspathDependencyTag struct { - blueprint.BaseDependencyTag - - name string -} - -// Avoid having to make platform bootclasspath content visible to the platform bootclasspath. -// -// This is a temporary workaround to make it easier to migrate to platform bootclasspath with proper -// dependencies. -// TODO(b/177892522): Remove this and add needed visibility. -func (t platformBootclasspathDependencyTag) ExcludeFromVisibilityEnforcement() { } // The tag used for the dependency between the platform bootclasspath and any configured boot jars. -var platformBootclasspathModuleDepTag = platformBootclasspathDependencyTag{name: "module"} - -// The tag used for the dependency between the platform bootclasspath and bootclasspath_fragments. -var platformBootclasspathFragmentDepTag = platformBootclasspathDependencyTag{name: "fragment"} - -var _ android.ExcludeFromVisibilityEnforcementTag = platformBootclasspathDependencyTag{} +var platformBootclasspathModuleDepTag = bootclasspathDependencyTag{name: "module"} type platformBootclasspathModule struct { android.ModuleBase @@ -83,22 +58,8 @@ type platformBootclasspathModule struct { hiddenAPIMetadataCSV android.OutputPath } -// ApexVariantReference specifies a particular apex variant of a module. -type ApexVariantReference struct { - // The name of the module apex variant, i.e. the apex containing the module variant. - // - // If this is not specified then it defaults to "platform" which will cause a dependency to be - // added to the module's platform variant. - Apex *string - - // The name of the module. - Module *string -} - type platformBootclasspathProperties struct { - // The names of the bootclasspath_fragment modules that form part of this - // platform_bootclasspath. - Fragments []ApexVariantReference + BootclasspathFragmentsDepsProperties Hidden_api HiddenAPIFlagFileProperties } @@ -161,92 +122,22 @@ func (b *platformBootclasspathModule) hiddenAPIDepsMutator(ctx android.BottomUpM hiddenAPIAddStubLibDependencies(ctx, sdkKindToStubLibModules) } -func platformBootclasspathDepsMutator(ctx android.BottomUpMutatorContext) { - m := ctx.Module() - if p, ok := m.(*platformBootclasspathModule); ok { - // Add dependencies on all the modules configured in the "art" boot image. - artImageConfig := genBootImageConfigs(ctx)[artBootImageName] - addDependenciesOntoBootImageModules(ctx, artImageConfig.modules) - - // Add dependencies on all the modules configured in the "boot" boot image. That does not - // include modules configured in the "art" boot image. - bootImageConfig := p.getImageConfig(ctx) - addDependenciesOntoBootImageModules(ctx, bootImageConfig.modules) - - // Add dependencies on all the updatable modules. - updatableModules := dexpreopt.GetGlobalConfig(ctx).UpdatableBootJars - addDependenciesOntoBootImageModules(ctx, updatableModules) - - // Add dependencies on all the fragments. - addDependencyOntoApexVariants(ctx, "fragments", p.properties.Fragments, platformBootclasspathFragmentDepTag) - } -} - -func addDependencyOntoApexVariants(ctx android.BottomUpMutatorContext, propertyName string, refs []ApexVariantReference, tag blueprint.DependencyTag) { - for i, ref := range refs { - apex := proptools.StringDefault(ref.Apex, "platform") - - if ref.Module == nil { - ctx.PropertyErrorf(propertyName, "missing module name at position %d", i) - continue - } - name := proptools.String(ref.Module) - - addDependencyOntoApexModulePair(ctx, apex, name, tag) - } -} +func (b *platformBootclasspathModule) BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) { + // Add dependencies on all the modules configured in the "art" boot image. + artImageConfig := genBootImageConfigs(ctx)[artBootImageName] + addDependenciesOntoBootImageModules(ctx, artImageConfig.modules) -func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex string, name string, tag blueprint.DependencyTag) { - var variations []blueprint.Variation - if apex != "platform" { - // Pick the correct apex variant. - variations = []blueprint.Variation{ - {Mutator: "apex", Variation: apex}, - } - } + // Add dependencies on all the modules configured in the "boot" boot image. That does not + // include modules configured in the "art" boot image. + bootImageConfig := b.getImageConfig(ctx) + addDependenciesOntoBootImageModules(ctx, bootImageConfig.modules) - addedDep := false - if ctx.OtherModuleDependencyVariantExists(variations, name) { - ctx.AddFarVariationDependencies(variations, tag, name) - addedDep = true - } + // Add dependencies on all the updatable modules. + updatableModules := dexpreopt.GetGlobalConfig(ctx).UpdatableBootJars + addDependenciesOntoBootImageModules(ctx, updatableModules) - // Add a dependency on the prebuilt module if it exists. - prebuiltName := android.PrebuiltNameFromSource(name) - if ctx.OtherModuleDependencyVariantExists(variations, prebuiltName) { - ctx.AddVariationDependencies(variations, tag, prebuiltName) - addedDep = true - } - - // If no appropriate variant existing for this, so no dependency could be added, then it is an - // error, unless missing dependencies are allowed. The simplest way to handle that is to add a - // dependency that will not be satisfied and the default behavior will handle it. - if !addedDep { - // Add dependency on the unprefixed (i.e. source or renamed prebuilt) module which we know does - // not exist. The resulting error message will contain useful information about the available - // variants. - reportMissingVariationDependency(ctx, variations, name) - - // Add dependency on the missing prefixed prebuilt variant too if a module with that name exists - // so that information about its available variants will be reported too. - if ctx.OtherModuleExists(prebuiltName) { - reportMissingVariationDependency(ctx, variations, prebuiltName) - } - } -} - -// reportMissingVariationDependency intentionally adds a dependency on a missing variation in order -// to generate an appropriate error message with information about the available variations. -func reportMissingVariationDependency(ctx android.BottomUpMutatorContext, variations []blueprint.Variation, name string) { - modules := ctx.AddFarVariationDependencies(variations, nil, name) - if len(modules) != 1 { - panic(fmt.Errorf("Internal Error: expected one module, found %d", len(modules))) - return - } - if modules[0] != nil { - panic(fmt.Errorf("Internal Error: expected module to be missing but was found: %q", modules[0])) - return - } + // Add dependencies on all the fragments. + b.properties.BootclasspathFragmentsDepsProperties.addDependenciesOntoFragments(ctx) } func addDependenciesOntoBootImageModules(ctx android.BottomUpMutatorContext, modules android.ConfiguredJarList) { @@ -265,7 +156,7 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo tag := ctx.OtherModuleDependencyTag(module) if tag == platformBootclasspathModuleDepTag { b.configuredModules = append(b.configuredModules, module) - } else if tag == platformBootclasspathFragmentDepTag { + } else if tag == bootclasspathFragmentDepTag { b.fragments = append(b.fragments, module) } }) diff --git a/java/testing.go b/java/testing.go index 08a71b880..649d27bf5 100644 --- a/java/testing.go +++ b/java/testing.go @@ -232,7 +232,8 @@ func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) { RegisterAppBuildComponents(ctx) RegisterAppImportBuildComponents(ctx) RegisterAppSetBuildComponents(ctx) - RegisterBootImageBuildComponents(ctx) + registerBootclasspathBuildComponents(ctx) + registerBootclasspathFragmentBuildComponents(ctx) RegisterDexpreoptBootJarsComponents(ctx) RegisterDocsBuildComponents(ctx) RegisterGenRuleBuildComponents(ctx) diff --git a/rust/bindgen.go b/rust/bindgen.go index ba0ab93d0..f9e6cd0a3 100644 --- a/rust/bindgen.go +++ b/rust/bindgen.go @@ -144,6 +144,7 @@ func (b *bindgenDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) andr // Toolchain clang flags cflags = append(cflags, "-target "+ccToolchain.ClangTriple()) + cflags = append(cflags, strings.ReplaceAll(ccToolchain.ClangCflags(), "${config.", "${cc_config.")) cflags = append(cflags, strings.ReplaceAll(ccToolchain.ToolchainClangCflags(), "${config.", "${cc_config.")) // Dependency clang flags and include paths diff --git a/rust/image.go b/rust/image.go index 900842ec8..7eb49d962 100644 --- a/rust/image.go +++ b/rust/image.go @@ -97,10 +97,6 @@ func (mod *Module) RamdiskVariantNeeded(android.BaseModuleContext) bool { return mod.InRamdisk() } -func (mod *Module) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { - return false -} - func (mod *Module) RecoveryVariantNeeded(android.BaseModuleContext) bool { return mod.InRecovery() } diff --git a/scripts/lint_project_xml.py b/scripts/lint_project_xml.py index 74aebc10a..3b0158d0b 100755 --- a/scripts/lint_project_xml.py +++ b/scripts/lint_project_xml.py @@ -144,12 +144,12 @@ def check_baseline_for_disallowed_issues(baseline, forced_checks): if issues_element.tagName != 'issues': raise RuntimeError('expected issues tag at root') issues = issues_element.getElementsByTagName('issue') - disallwed = set() + disallowed = set() for issue in issues: id = issue.getAttribute('id') if id in forced_checks: - disallwed.add(id) - return disallwed + disallowed.add(id) + return disallowed def main(): @@ -158,10 +158,10 @@ def main(): if args.baseline_path: baseline = minidom.parse(args.baseline_path) - diallowed_issues = check_baseline_for_disallowed_issues(baseline, args.disallowed_issues) - if bool(diallowed_issues): + disallowed_issues = check_baseline_for_disallowed_issues(baseline, args.disallowed_issues) + if bool(disallowed_issues): raise RuntimeError('disallowed issues %s found in lint baseline file %s for module %s' - % (diallowed_issues, args.baseline_path, args.name)) + % (disallowed_issues, args.baseline_path, args.name)) if args.project_out: with open(args.project_out, 'w') as f: diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go index 0ce4351eb..ef4d7cd45 100644 --- a/sdk/bootclasspath_fragment_sdk_test.go +++ b/sdk/bootclasspath_fragment_sdk_test.go @@ -24,6 +24,7 @@ import ( func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) { result := android.GroupFixturePreparers( prepareForSdkTestWithJava, + java.PrepareForTestWithJavaDefaultModules, prepareForSdkTestWithApex, // Some additional files needed for the art apex. @@ -32,6 +33,20 @@ func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) { "com.android.art.pem": nil, "system/sepolicy/apex/com.android.art-file_contexts": nil, }), + + // platform_bootclasspath that depends on the fragment. + android.FixtureAddTextFile("frameworks/base/boot/Android.bp", ` + platform_bootclasspath { + name: "platform-bootclasspath", + fragments: [ + { + apex: "com.android.art", + module: "mybootclasspathfragment", + }, + ], + } + `), + java.FixtureConfigureBootJars("com.android.art:mybootlib"), android.FixtureWithRootAndroidBp(` sdk { @@ -72,6 +87,23 @@ func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) { `), ).RunTest(t) + // A preparer to add a prebuilt apex to the test fixture. + prepareWithPrebuiltApex := android.GroupFixturePreparers( + android.FixtureAddTextFile("prebuilts/apex/Android.bp", ` + prebuilt_apex { + name: "com.android.art", + src: "art.apex", + exported_java_libs: [ + "mybootlib", + ], + exported_bootclasspath_fragments: [ + "mybootclasspathfragment", + ], + } + `), + android.FixtureAddFile("prebuilts/apex/art.apex", nil), + ) + CheckSnapshot(t, result, "mysdk", "", checkUnversionedAndroidBpContents(` // This is auto-generated. DO NOT EDIT. @@ -121,19 +153,9 @@ sdk_snapshot { checkAllCopyRules(` .intermediates/mybootlib/android_common/javac/mybootlib.jar -> java/mybootlib.jar `), - snapshotTestPreparer(checkSnapshotPreferredWithSource, android.GroupFixturePreparers( - android.FixtureAddTextFile("prebuilts/apex/Android.bp", ` - prebuilt_apex { - name: "com.android.art", - src: "art.apex", - exported_java_libs: [ - "mybootlib", - ], - } - `), - android.FixtureAddFile("prebuilts/apex/art.apex", nil), - ), - ), + snapshotTestPreparer(checkSnapshotWithoutSource, prepareWithPrebuiltApex), + snapshotTestPreparer(checkSnapshotWithSourcePreferred, prepareWithPrebuiltApex), + snapshotTestPreparer(checkSnapshotPreferredWithSource, prepareWithPrebuiltApex), ) } diff --git a/sdk/testing.go b/sdk/testing.go index bf59aeda0..f4e85c0cf 100644 --- a/sdk/testing.go +++ b/sdk/testing.go @@ -254,6 +254,7 @@ func CheckSnapshot(t *testing.T, result *android.TestResult, name string, dir st snapshotPreparer := android.GroupFixturePreparers(sourcePreparers, fs.AddToFixture()) var runSnapshotTestWithCheckers = func(t *testing.T, testConfig snapshotTest, extraPreparer android.FixturePreparer) { + t.Helper() customization := snapshotBuildInfo.snapshotTestCustomization(testConfig) customizedPreparers := android.GroupFixturePreparers(customization.preparers...) diff --git a/sh/sh_binary.go b/sh/sh_binary.go index 42d5680f1..662338133 100644 --- a/sh/sh_binary.go +++ b/sh/sh_binary.go @@ -210,10 +210,6 @@ func (s *ShBinary) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) boo return proptools.Bool(s.properties.Vendor_ramdisk_available) || s.ModuleBase.InstallInVendorRamdisk() } -func (s *ShBinary) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { - return false -} - func (s *ShBinary) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { return proptools.Bool(s.properties.Recovery_available) || s.ModuleBase.InstallInRecovery() } |