diff options
62 files changed, 2043 insertions, 869 deletions
diff --git a/android/androidmk.go b/android/androidmk.go index 0adc2a6eb..1f03aa812 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -887,6 +887,10 @@ func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, mod blue return nil } +func ShouldSkipAndroidMkProcessing(module Module) bool { + return shouldSkipAndroidMkProcessing(module.base()) +} + func shouldSkipAndroidMkProcessing(module *ModuleBase) bool { if !module.commonProperties.NamespaceExportedToMake { // TODO(jeffrygaston) do we want to validate that there are no modules being diff --git a/android/apex.go b/android/apex.go index 461faf760..cf1bcfef4 100644 --- a/android/apex.go +++ b/android/apex.go @@ -908,16 +908,18 @@ var minSdkVersionAllowlist = func(apiMap map[string]int) map[string]ApiLevel { // // Return true if the `to` module should be visited, false otherwise. type PayloadDepsCallback func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool +type WalkPayloadDepsFunc func(ctx ModuleContext, do PayloadDepsCallback) -// UpdatableModule represents updatable APEX/APK -type UpdatableModule interface { +// ModuleWithMinSdkVersionCheck represents a module that implements min_sdk_version checks +type ModuleWithMinSdkVersionCheck interface { Module - WalkPayloadDeps(ctx ModuleContext, do PayloadDepsCallback) + MinSdkVersion(ctx EarlyModuleContext) SdkSpec + CheckMinSdkVersion(ctx ModuleContext) } // CheckMinSdkVersion checks if every dependency of an updatable module sets min_sdk_version // accordingly -func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion ApiLevel) { +func CheckMinSdkVersion(ctx ModuleContext, minSdkVersion ApiLevel, walk WalkPayloadDepsFunc) { // do not enforce min_sdk_version for host if ctx.Host() { return @@ -933,7 +935,7 @@ func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion ApiL return } - m.WalkPayloadDeps(ctx, func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool { + walk(ctx, func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool { if externalDep { // external deps are outside the payload boundary, which is "stable" // interface. We don't have to check min_sdk_version for external @@ -943,6 +945,14 @@ func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion ApiL if am, ok := from.(DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) { return false } + if m, ok := to.(ModuleWithMinSdkVersionCheck); ok { + // This dependency performs its own min_sdk_version check, just make sure it sets min_sdk_version + // to trigger the check. + if !m.MinSdkVersion(ctx).Specified() { + ctx.OtherModuleErrorf(m, "must set min_sdk_version") + } + return false + } if err := to.ShouldSupportSdkVersion(ctx, minSdkVersion); err != nil { toName := ctx.OtherModuleName(to) if ver, ok := minSdkVersionAllowlist[toName]; !ok || ver.GreaterThan(minSdkVersion) { diff --git a/android/bazel.go b/android/bazel.go index 40c971f17..169f6ba29 100644 --- a/android/bazel.go +++ b/android/bazel.go @@ -226,13 +226,50 @@ var ( // Configure modules in these directories to enable bp2build_available: true or false by default. bp2buildDefaultConfig = Bp2BuildConfig{ - "art/libdexfile": Bp2BuildDefaultTrueRecursively, - "bionic": Bp2BuildDefaultTrueRecursively, + "art/libdexfile": Bp2BuildDefaultTrueRecursively, + "bionic": Bp2BuildDefaultTrueRecursively, + "bootable/recovery/tools/recovery_l10n": Bp2BuildDefaultTrue, "build/bazel/examples/soong_config_variables": Bp2BuildDefaultTrueRecursively, "build/bazel/examples/apex/minimal": Bp2BuildDefaultTrueRecursively, "build/soong": Bp2BuildDefaultTrue, "build/soong/cc/libbuildversion": Bp2BuildDefaultTrue, // Skip tests subdir + "build/soong/cc/ndkstubgen": Bp2BuildDefaultTrue, + "build/soong/cc/symbolfile": Bp2BuildDefaultTrue, "cts/common/device-side/nativetesthelper/jni": Bp2BuildDefaultTrueRecursively, + "development/apps/DevelopmentSettings": Bp2BuildDefaultTrue, + "development/apps/Fallback": Bp2BuildDefaultTrue, + "development/apps/WidgetPreview": Bp2BuildDefaultTrue, + "development/samples/BasicGLSurfaceView": Bp2BuildDefaultTrue, + "development/samples/BluetoothChat": Bp2BuildDefaultTrue, + "development/samples/BrokenKeyDerivation": Bp2BuildDefaultTrue, + "development/samples/Compass": Bp2BuildDefaultTrue, + "development/samples/ContactManager": Bp2BuildDefaultTrue, + "development/samples/FixedGridLayout": Bp2BuildDefaultTrue, + "development/samples/HelloEffects": Bp2BuildDefaultTrue, + "development/samples/Home": Bp2BuildDefaultTrue, + "development/samples/HoneycombGallery": Bp2BuildDefaultTrue, + "development/samples/JetBoy": Bp2BuildDefaultTrue, + "development/samples/KeyChainDemo": Bp2BuildDefaultTrue, + "development/samples/LceDemo": Bp2BuildDefaultTrue, + "development/samples/LunarLander": Bp2BuildDefaultTrue, + "development/samples/MultiResolution": Bp2BuildDefaultTrue, + "development/samples/MultiWindow": Bp2BuildDefaultTrue, + "development/samples/NotePad": Bp2BuildDefaultTrue, + "development/samples/Obb": Bp2BuildDefaultTrue, + "development/samples/RSSReader": Bp2BuildDefaultTrue, + "development/samples/ReceiveShareDemo": Bp2BuildDefaultTrue, + "development/samples/SearchableDictionary": Bp2BuildDefaultTrue, + "development/samples/SipDemo": Bp2BuildDefaultTrue, + "development/samples/SkeletonApp": Bp2BuildDefaultTrue, + "development/samples/Snake": Bp2BuildDefaultTrue, + "development/samples/SpellChecker/": Bp2BuildDefaultTrueRecursively, + "development/samples/ThemedNavBarKeyboard": Bp2BuildDefaultTrue, + "development/samples/ToyVpn": Bp2BuildDefaultTrue, + "development/samples/TtsEngine": Bp2BuildDefaultTrue, + "development/samples/USB/AdbTest": Bp2BuildDefaultTrue, + "development/samples/USB/MissileLauncher": Bp2BuildDefaultTrue, + "development/samples/VoiceRecognitionService": Bp2BuildDefaultTrue, + "development/samples/VoicemailProviderDemo": Bp2BuildDefaultTrue, "development/sdk": Bp2BuildDefaultTrueRecursively, "external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively, "external/boringssl": Bp2BuildDefaultTrueRecursively, @@ -259,9 +296,19 @@ var ( "external/selinux/libselinux": Bp2BuildDefaultTrueRecursively, "external/zlib": Bp2BuildDefaultTrueRecursively, "external/zstd": Bp2BuildDefaultTrueRecursively, + "frameworks/base/media/tests/MediaDump": Bp2BuildDefaultTrue, + "frameworks/base/startop/apps/test": Bp2BuildDefaultTrue, "frameworks/native/libs/adbd_auth": Bp2BuildDefaultTrueRecursively, + "frameworks/native/opengl/tests/gl2_cameraeye": Bp2BuildDefaultTrue, + "frameworks/native/opengl/tests/gl2_java": Bp2BuildDefaultTrue, + "frameworks/native/opengl/tests/testLatency": Bp2BuildDefaultTrue, + "frameworks/native/opengl/tests/testPauseResume": Bp2BuildDefaultTrue, + "frameworks/native/opengl/tests/testViewport": Bp2BuildDefaultTrue, "frameworks/proto_logging/stats/stats_log_api_gen": Bp2BuildDefaultTrueRecursively, "libnativehelper": Bp2BuildDefaultTrueRecursively, + "packages/apps/DevCamera": Bp2BuildDefaultTrue, + "packages/apps/HTMLViewer": Bp2BuildDefaultTrue, + "packages/apps/Protips": Bp2BuildDefaultTrue, "packages/modules/adb": Bp2BuildDefaultTrue, "packages/modules/adb/crypto": Bp2BuildDefaultTrueRecursively, "packages/modules/adb/libs": Bp2BuildDefaultTrueRecursively, @@ -269,6 +316,9 @@ var ( "packages/modules/adb/pairing_connection": Bp2BuildDefaultTrueRecursively, "packages/modules/adb/proto": Bp2BuildDefaultTrueRecursively, "packages/modules/adb/tls": Bp2BuildDefaultTrueRecursively, + "packages/providers/MediaProvider/tools/dialogs": Bp2BuildDefaultTrue, + "packages/screensavers/Basic": Bp2BuildDefaultTrue, + "packages/services/Car/tests/SampleRearViewCamera": Bp2BuildDefaultTrue, "prebuilts/clang/host/linux-x86": Bp2BuildDefaultTrueRecursively, "system/apex": Bp2BuildDefaultFalse, // TODO(b/207466993): flaky failures "system/core/debuggerd": Bp2BuildDefaultTrue, @@ -336,9 +386,8 @@ var ( "host_bionic_linker_asm", // depends on extract_linker, a go binary. "host_bionic_linker_script", // depends on extract_linker, a go binary. - "pbtombstone", // depends on libprotobuf-cpp-lite, libtombstone_proto - "crash_dump", // depends on unconverted module libprotobuf-cpp-lite - "libprotobuf-cpp-full", "libprotobuf-cpp-lite", // Unsupported product&vendor suffix. b/204811222 and b/204810610. + "pbtombstone", // depends on libprotobuf-cpp-lite, libtombstone_proto + "crash_dump", // depends on unconverted module libprotobuf-cpp-lite "libunwindstack_local", "libunwindstack_utils", // depends on unconverted module libunwindstack "libunwindstack", // depends on libdexfile_support, of unsupported module type art_cc_library_static @@ -373,19 +422,10 @@ var ( // APEX support "com.android.runtime", // http://b/194746715, apex, depends on 'libc_malloc_debug' - "libadb_crypto", // Depends on libadb_protos - "libadb_crypto_static", // Depends on libadb_protos_static - "libadb_pairing_connection", // Depends on libadb_protos - "libadb_pairing_connection_static", // Depends on libadb_protos_static - "libadb_pairing_server", // Depends on libadb_protos - "libadb_pairing_server_static", // Depends on libadb_protos_static - "libadbd", // Depends on libadbd_core - "libadbd_core", // Depends on libadb_protos - "libadbd_services", // Depends on libadb_protos + "libadbd_core", // http://b/208481704: requijres use_version_lib + "libadbd_services", // http://b/208481704: requires use_version_lib - "libadb_protos_static", // b/200601772: Requires cc_library proto support - "libadb_protos", // b/200601772: Requires cc_library proto support - "libapp_processes_protos_lite", // b/200601772: Requires cc_library proto support + "libadbd", // depends on unconverted modules: libadbd_core, libadbd_services "libgtest_ndk_c++", // b/201816222: Requires sdk_version support. "libgtest_main_ndk_c++", // b/201816222: Requires sdk_version support. @@ -401,6 +441,7 @@ var ( "mdnsd", // http://b/202876379 has arch-variant static_executable "acvp_modulewrapper", // disabled for android x86/x86_64 + "CarHTMLViewer", // depends on unconverted modules android.car-stubs, car-ui-lib } // Per-module denylist of cc_library modules to only generate the static @@ -418,6 +459,11 @@ var ( "cap_names.h", // TODO(b/204913827) runfiles need to be handled in mixed builds "libcap", // TODO(b/204913827) runfiles need to be handled in mixed builds "libprotobuf-cpp-full", "libprotobuf-cpp-lite", // Unsupported product&vendor suffix. b/204811222 and b/204810610. + + // Depends on libprotobuf-cpp-* + "libadb_pairing_connection", + "libadb_pairing_connection_static", + "libadb_pairing_server", "libadb_pairing_server_static", } // Used for quicker lookups diff --git a/android/bazel_paths.go b/android/bazel_paths.go index 729c73c8f..62e6156a4 100644 --- a/android/bazel_paths.go +++ b/android/bazel_paths.go @@ -279,6 +279,16 @@ func transformSubpackagePaths(ctx BazelConversionPathContext, paths bazel.LabelL return newPaths } +// Converts root-relative Paths to a list of bazel.Label relative to the module in ctx. +func RootToModuleRelativePaths(ctx BazelConversionPathContext, paths Paths) []bazel.Label { + var newPaths []bazel.Label + for _, path := range PathsWithModuleSrcSubDir(ctx, paths, "") { + s := path.Rel() + newPaths = append(newPaths, bazel.Label{Label: s}) + } + return newPaths +} + // expandSrcsForBazel returns bazel.LabelList with paths rooted from the module's local source // directory and Bazel target labels, excluding those included in the excludes argument (which // should already be expanded to resolve references to Soong-modules). Valid elements of paths @@ -328,12 +338,7 @@ func expandSrcsForBazel(ctx BazelConversionPathContext, paths, expandedExcludes // e.g. turn "math/*.c" in // external/arm-optimized-routines to external/arm-optimized-routines/math/*.c rootRelativeGlobPath := pathForModuleSrc(ctx, p).String() - globbedPaths := GlobFiles(ctx, rootRelativeGlobPath, rootRelativeExpandedExcludes) - globbedPaths = PathsWithModuleSrcSubDir(ctx, globbedPaths, "") - for _, path := range globbedPaths { - s := path.Rel() - expandedPaths = append(expandedPaths, bazel.Label{Label: s}) - } + expandedPaths = RootToModuleRelativePaths(ctx, GlobFiles(ctx, rootRelativeGlobPath, rootRelativeExpandedExcludes)) } else { if !InList(p, expandedExcludes) { expandedPaths = append(expandedPaths, bazel.Label{Label: p}) diff --git a/android/config.go b/android/config.go index ddad1f532..8e01e186b 100644 --- a/android/config.go +++ b/android/config.go @@ -1194,10 +1194,6 @@ func (c *deviceConfig) DeviceKernelHeaderDirs() []string { return c.config.productVariables.DeviceKernelHeaders } -func (c *deviceConfig) SamplingPGO() bool { - return Bool(c.config.productVariables.SamplingPGO) -} - // JavaCoverageEnabledForPath returns whether Java code coverage is enabled for // path. Coverage is enabled by default when the product variable // JavaCoveragePaths is empty. If JavaCoveragePaths is not empty, coverage is diff --git a/android/module.go b/android/module.go index b500f01c6..c2cb6179a 100644 --- a/android/module.go +++ b/android/module.go @@ -419,7 +419,6 @@ type ModuleContext interface { PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec CheckbuildFile(srcPath Path) - TidyFile(srcPath WritablePath) InstallInData() bool InstallInTestcases() bool @@ -1200,7 +1199,6 @@ type ModuleBase struct { installFiles InstallPaths installFilesDepSet *installPathsDepSet checkbuildFiles Paths - tidyFiles WritablePaths packagingSpecs []PackagingSpec packagingSpecsDepSet *packagingSpecsDepSet noticeFiles Paths @@ -1216,7 +1214,6 @@ type ModuleBase struct { // Only set on the final variant of each module installTarget WritablePath checkbuildTarget WritablePath - tidyTarget WritablePath blueprintDir string hooks hooks @@ -1779,17 +1776,15 @@ func (m *ModuleBase) VintfFragments() Paths { func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) { var allInstalledFiles InstallPaths var allCheckbuildFiles Paths - var allTidyFiles WritablePaths ctx.VisitAllModuleVariants(func(module Module) { a := module.base() allInstalledFiles = append(allInstalledFiles, a.installFiles...) - // A module's -{checkbuild,tidy} phony targets should + // A module's -checkbuild phony targets should // not be created if the module is not exported to make. // Those could depend on the build target and fail to compile // for the current build target. if !ctx.Config().KatiEnabled() || !shouldSkipAndroidMkProcessing(a) { allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...) - allTidyFiles = append(allTidyFiles, a.tidyFiles...) } }) @@ -1814,13 +1809,6 @@ func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) { deps = append(deps, m.checkbuildTarget) } - if len(allTidyFiles) > 0 { - name := namespacePrefix + ctx.ModuleName() + "-tidy" - ctx.Phony(name, allTidyFiles.Paths()...) - m.tidyTarget = PathForPhony(ctx, name) - deps = append(deps, m.tidyTarget) - } - if len(deps) > 0 { suffix := "" if ctx.Config().KatiEnabled() { @@ -2029,7 +2017,6 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) m.installFiles = append(m.installFiles, ctx.installFiles...) m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...) - m.tidyFiles = append(m.tidyFiles, ctx.tidyFiles...) m.packagingSpecs = append(m.packagingSpecs, ctx.packagingSpecs...) m.katiInstalls = append(m.katiInstalls, ctx.katiInstalls...) m.katiSymlinks = append(m.katiSymlinks, ctx.katiSymlinks...) @@ -2227,7 +2214,6 @@ type moduleContext struct { packagingSpecs []PackagingSpec installFiles InstallPaths checkbuildFiles Paths - tidyFiles WritablePaths module Module phonies map[string]Paths @@ -3065,10 +3051,6 @@ func (m *moduleContext) CheckbuildFile(srcPath Path) { m.checkbuildFiles = append(m.checkbuildFiles, srcPath) } -func (m *moduleContext) TidyFile(srcPath WritablePath) { - m.tidyFiles = append(m.tidyFiles, srcPath) -} - func (m *moduleContext) blueprintModuleContext() blueprint.ModuleContext { return m.bp } @@ -3327,9 +3309,10 @@ func parentDir(dir string) string { type buildTargetSingleton struct{} -func addAncestors(ctx SingletonContext, dirMap map[string]Paths, mmName func(string) string) []string { +func AddAncestors(ctx SingletonContext, dirMap map[string]Paths, mmName func(string) string) ([]string, []string) { // Ensure ancestor directories are in dirMap // Make directories build their direct subdirectories + // Returns a slice of all directories and a slice of top-level directories. dirs := SortedStringKeys(dirMap) for _, dir := range dirs { dir := parentDir(dir) @@ -3342,34 +3325,31 @@ func addAncestors(ctx SingletonContext, dirMap map[string]Paths, mmName func(str } } dirs = SortedStringKeys(dirMap) + var topDirs []string for _, dir := range dirs { p := parentDir(dir) if p != "." && p != "/" { dirMap[p] = append(dirMap[p], PathForPhony(ctx, mmName(dir))) + } else if dir != "." && dir != "/" && dir != "" { + topDirs = append(topDirs, dir) } } - return SortedStringKeys(dirMap) + return SortedStringKeys(dirMap), topDirs } func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) { var checkbuildDeps Paths - var tidyDeps Paths mmTarget := func(dir string) string { return "MODULES-IN-" + strings.Replace(filepath.Clean(dir), "/", "-", -1) } - mmTidyTarget := func(dir string) string { - return "tidy-" + strings.Replace(filepath.Clean(dir), "/", "-", -1) - } modulesInDir := make(map[string]Paths) - tidyModulesInDir := make(map[string]Paths) ctx.VisitAllModules(func(module Module) { blueprintDir := module.base().blueprintDir installTarget := module.base().installTarget checkbuildTarget := module.base().checkbuildTarget - tidyTarget := module.base().tidyTarget if checkbuildTarget != nil { checkbuildDeps = append(checkbuildDeps, checkbuildTarget) @@ -3379,16 +3359,6 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) { if installTarget != nil { modulesInDir[blueprintDir] = append(modulesInDir[blueprintDir], installTarget) } - - if tidyTarget != nil { - tidyDeps = append(tidyDeps, tidyTarget) - // tidyTarget is in modulesInDir so it will be built with "mm". - modulesInDir[blueprintDir] = append(modulesInDir[blueprintDir], tidyTarget) - // tidyModulesInDir contains tidyTarget but not checkbuildTarget - // or installTarget, so tidy targets in a directory can be built - // without other checkbuild or install targets. - tidyModulesInDir[blueprintDir] = append(tidyModulesInDir[blueprintDir], tidyTarget) - } }) suffix := "" @@ -3399,24 +3369,12 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) { // Create a top-level checkbuild target that depends on all modules ctx.Phony("checkbuild"+suffix, checkbuildDeps...) - // Create a top-level tidy target that depends on all modules - ctx.Phony("tidy"+suffix, tidyDeps...) - - dirs := addAncestors(ctx, tidyModulesInDir, mmTidyTarget) - - // Kati does not generate tidy-* phony targets yet. - // Create a tidy-<directory> target that depends on all subdirectories - // and modules in the directory. - for _, dir := range dirs { - ctx.Phony(mmTidyTarget(dir), tidyModulesInDir[dir]...) - } - // Make will generate the MODULES-IN-* targets if ctx.Config().KatiEnabled() { return } - dirs = addAncestors(ctx, modulesInDir, mmTarget) + dirs, _ := AddAncestors(ctx, modulesInDir, mmTarget) // Create a MODULES-IN-<directory> target that depends on all modules in a directory, and // depends on the MODULES-IN-* targets of all of its subdirectories that contain Android.bp diff --git a/android/mutator.go b/android/mutator.go index 0a9351745..bf1cf806e 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -221,6 +221,13 @@ var bp2buildMutators = map[string]RegisterMutatorFunc{} // See http://b/192523357 var bp2buildLock sync.Mutex +// A minimal context for Bp2build conversion +type Bp2buildMutatorContext interface { + BazelConversionPathContext + + CreateBazelTargetModule(bazel.BazelTargetModuleProperties, CommonAttributes, interface{}) +} + // RegisterBp2BuildMutator registers specially crafted mutators for // converting Blueprint/Android modules into special modules that can // be code-generated into Bazel BUILD targets. diff --git a/android/proto.go b/android/proto.go index 0be7893c8..64d4d057c 100644 --- a/android/proto.go +++ b/android/proto.go @@ -15,12 +15,17 @@ package android import ( + "android/soong/bazel" "strings" "github.com/google/blueprint" "github.com/google/blueprint/proptools" ) +const ( + canonicalPathFromRootDefault = true +) + // TODO(ccross): protos are often used to communicate between multiple modules. If the only // way to convert a proto to source is to reference it as a source file, and external modules cannot // reference source files in other modules, then every module that owns a proto file will need to @@ -90,7 +95,7 @@ func GetProtoFlags(ctx ModuleContext, p *ProtoProperties) ProtoFlags { Flags: flags, Deps: deps, OutTypeFlag: protoOutFlag, - CanonicalPathFromRoot: proptools.BoolDefault(p.Proto.Canonical_path_from_root, true), + CanonicalPathFromRoot: proptools.BoolDefault(p.Proto.Canonical_path_from_root, canonicalPathFromRootDefault), Dir: PathForModuleGen(ctx, "proto"), SubDir: PathForModuleGen(ctx, "proto", ctx.ModuleDir()), } @@ -146,3 +151,57 @@ func ProtoRule(rule *RuleBuilder, protoFile Path, flags ProtoFlags, deps Paths, rule.Command(). BuiltTool("dep_fixer").Flag(depFile.String()) } + +// Bp2buildProtoInfo contains information necessary to pass on to language specific conversion. +type Bp2buildProtoInfo struct { + Type *string + Name string +} + +type protoAttrs struct { + Srcs bazel.LabelListAttribute + Strip_import_prefix *string +} + +// Bp2buildProtoProperties converts proto properties, creating a proto_library and returning the +// information necessary for language-specific handling. +func Bp2buildProtoProperties(ctx Bp2buildMutatorContext, module Module, srcs bazel.LabelListAttribute) (Bp2buildProtoInfo, bool) { + var info Bp2buildProtoInfo + if srcs.IsEmpty() { + return info, false + } + m := module.base() + + info.Name = m.Name() + "_proto" + attrs := protoAttrs{ + Srcs: srcs, + } + + for axis, configToProps := range m.GetArchVariantProperties(ctx, &ProtoProperties{}) { + for _, rawProps := range configToProps { + var props *ProtoProperties + var ok bool + if props, ok = rawProps.(*ProtoProperties); !ok { + ctx.ModuleErrorf("Could not cast ProtoProperties to expected type") + } + if axis == bazel.NoConfigAxis { + info.Type = props.Proto.Type + + if proptools.BoolDefault(props.Proto.Canonical_path_from_root, canonicalPathFromRootDefault) { + // an empty string indicates to strips the package path + path := "" + attrs.Strip_import_prefix = &path + } + } else if props.Proto.Type != info.Type && props.Proto.Type != nil { + ctx.ModuleErrorf("Cannot handle arch-variant types for protos at this time.") + } + } + } + + ctx.CreateBazelTargetModule( + bazel.BazelTargetModuleProperties{Rule_class: "proto_library"}, + CommonAttributes{Name: info.Name}, + &attrs) + + return info, true +} diff --git a/android/variable.go b/android/variable.go index a29c6f86a..158d26453 100644 --- a/android/variable.go +++ b/android/variable.go @@ -299,8 +299,6 @@ type productVariables struct { ClangTidy *bool `json:",omitempty"` TidyChecks *string `json:",omitempty"` - SamplingPGO *bool `json:",omitempty"` - JavaCoveragePaths []string `json:",omitempty"` JavaCoverageExcludePaths []string `json:",omitempty"` diff --git a/apex/apex.go b/apex/apex.go index 89b5f2176..bb9207dc2 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -130,6 +130,13 @@ type apexBundleProperties struct { // symlinking to the system libs. Default is true. Updatable *bool + // Marks that this APEX is designed to be updatable in the future, although it's not + // updatable yet. This is used to mimic some of the build behaviors that are applied only to + // updatable APEXes. Currently, this disables the size optimization, so that the size of + // APEX will not increase when the APEX is actually marked as truly updatable. Default is + // false. + Future_updatable *bool + // Whether this APEX can use platform APIs or not. Can be set to true only when `updatable: // false`. Default is false. Platform_apis *bool @@ -1306,6 +1313,10 @@ func (a *apexBundle) Updatable() bool { return proptools.BoolDefault(a.properties.Updatable, true) } +func (a *apexBundle) FutureUpdatable() bool { + return proptools.BoolDefault(a.properties.Future_updatable, false) +} + func (a *apexBundle) UsePlatformApis() bool { return proptools.BoolDefault(a.properties.Platform_apis, false) } @@ -1670,7 +1681,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { // 1) do some validity checks such as apex_available, min_sdk_version, etc. a.checkApexAvailability(ctx) a.checkUpdatable(ctx) - a.checkMinSdkVersion(ctx) + a.CheckMinSdkVersion(ctx) a.checkStaticLinkingToStubLibraries(ctx) a.checkStaticExecutables(ctx) if len(a.properties.Tests) > 0 && !a.testApex { @@ -2105,10 +2116,11 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { } forced := ctx.Config().ForceApexSymlinkOptimization() + updatable := a.Updatable() || a.FutureUpdatable() // We don't need the optimization for updatable APEXes, as it might give false signal // to the system health when the APEXes are still bundled (b/149805758). - if !forced && a.Updatable() && a.properties.ApexType == imageApex { + if !forced && updatable && a.properties.ApexType == imageApex { a.linkToSystemLib = false } @@ -2174,6 +2186,40 @@ func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module blueprint. filesToAdd = append(filesToAdd, *af) } + if pathInApex := bootclasspathFragmentInfo.ProfileInstallPathInApex(); pathInApex != "" { + pathOnHost := bootclasspathFragmentInfo.ProfilePathOnHost() + tempPath := android.PathForModuleOut(ctx, "boot_image_profile", pathInApex) + + if pathOnHost != nil { + // We need to copy the profile to a temporary path with the right filename because the apexer + // will take the filename as is. + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cp, + Input: pathOnHost, + Output: tempPath, + }) + } else { + // At this point, the boot image profile cannot be generated. It is probably because the boot + // image profile source file does not exist on the branch, or it is not available for the + // current build target. + // However, we cannot enforce the boot image profile to be generated because some build + // targets (such as module SDK) do not need it. It is only needed when the APEX is being + // built. Therefore, we create an error rule so that an error will occur at the ninja phase + // only if the APEX is being built. + ctx.Build(pctx, android.BuildParams{ + Rule: android.ErrorRule, + Output: tempPath, + Args: map[string]string{ + "error": "Boot image profile cannot be generated", + }, + }) + } + + androidMkModuleName := filepath.Base(pathInApex) + af := newApexFile(ctx, tempPath, androidMkModuleName, filepath.Dir(pathInApex), etc, nil) + filesToAdd = append(filesToAdd, af) + } + return filesToAdd } @@ -2300,18 +2346,28 @@ func overrideApexFactory() android.Module { // // TODO(jiyong): move these checks to a separate go file. +var _ android.ModuleWithMinSdkVersionCheck = (*apexBundle)(nil) + // Entures that min_sdk_version of the included modules are equal or less than the min_sdk_version // of this apexBundle. -func (a *apexBundle) checkMinSdkVersion(ctx android.ModuleContext) { +func (a *apexBundle) CheckMinSdkVersion(ctx android.ModuleContext) { if a.testApex || a.vndkApex { return } // apexBundle::minSdkVersion reports its own errors. minSdkVersion := a.minSdkVersion(ctx) - android.CheckMinSdkVersion(a, ctx, minSdkVersion) + android.CheckMinSdkVersion(ctx, minSdkVersion, a.WalkPayloadDeps) } -func (a *apexBundle) minSdkVersion(ctx android.BaseModuleContext) android.ApiLevel { +func (a *apexBundle) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { + return android.SdkSpec{ + Kind: android.SdkNone, + ApiLevel: a.minSdkVersion(ctx), + Raw: String(a.properties.Min_sdk_version), + } +} + +func (a *apexBundle) minSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel { ver := proptools.String(a.properties.Min_sdk_version) if ver == "" { return android.NoneApiLevel @@ -2380,6 +2436,9 @@ func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) { if a.SocSpecific() || a.DeviceSpecific() { ctx.PropertyErrorf("updatable", "vendor APEXes are not updatable") } + if a.FutureUpdatable() { + ctx.PropertyErrorf("future_updatable", "Already updatable. Remove `future_updatable: true:`") + } a.checkJavaStableSdkVersion(ctx) a.checkClasspathFragments(ctx) } diff --git a/apex/apex_test.go b/apex/apex_test.go index b805cd91b..3b9b13acb 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -7037,6 +7037,7 @@ func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.F `, insert)) } }), + dexpreopt.FixtureSetBootImageProfiles("art/build/boot/boot-image-profile.txt"), ). ExtendWithErrorHandler(errorHandler). RunTestWithBp(t, bp) @@ -8409,6 +8410,184 @@ func TestAndroidMk_RequiredModules(t *testing.T) { ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES += otherapex") } +func TestSdkLibraryCanHaveHigherMinSdkVersion(t *testing.T) { + preparer := android.GroupFixturePreparers( + PrepareForTestWithApexBuildComponents, + prepareForTestWithMyapex, + java.PrepareForTestWithJavaSdkLibraryFiles, + java.PrepareForTestWithJavaDefaultModules, + android.PrepareForTestWithAndroidBuildComponents, + dexpreopt.FixtureSetApexBootJars("myapex:mybootclasspathlib"), + dexpreopt.FixtureSetApexSystemServerJars("myapex:mysystemserverclasspathlib"), + ) + + // Test java_sdk_library in bootclasspath_fragment may define higher min_sdk_version than the apex + t.Run("bootclasspath_fragment jar has higher min_sdk_version than apex", func(t *testing.T) { + preparer.RunTestWithBp(t, ` + apex { + name: "myapex", + key: "myapex.key", + bootclasspath_fragments: ["mybootclasspathfragment"], + min_sdk_version: "30", + updatable: false, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + bootclasspath_fragment { + name: "mybootclasspathfragment", + contents: ["mybootclasspathlib"], + apex_available: ["myapex"], + } + + java_sdk_library { + name: "mybootclasspathlib", + srcs: ["mybootclasspathlib.java"], + apex_available: ["myapex"], + compile_dex: true, + unsafe_ignore_missing_latest_api: true, + min_sdk_version: "31", + static_libs: ["util"], + } + + java_library { + name: "util", + srcs: ["a.java"], + apex_available: ["myapex"], + min_sdk_version: "31", + static_libs: ["another_util"], + } + + java_library { + name: "another_util", + srcs: ["a.java"], + min_sdk_version: "31", + apex_available: ["myapex"], + } + `) + }) + + // Test java_sdk_library in systemserverclasspath_fragment may define higher min_sdk_version than the apex + t.Run("systemserverclasspath_fragment jar has higher min_sdk_version than apex", func(t *testing.T) { + preparer.RunTestWithBp(t, ` + apex { + name: "myapex", + key: "myapex.key", + systemserverclasspath_fragments: ["mysystemserverclasspathfragment"], + min_sdk_version: "30", + updatable: false, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + systemserverclasspath_fragment { + name: "mysystemserverclasspathfragment", + contents: ["mysystemserverclasspathlib"], + apex_available: ["myapex"], + } + + java_sdk_library { + name: "mysystemserverclasspathlib", + srcs: ["mysystemserverclasspathlib.java"], + apex_available: ["myapex"], + compile_dex: true, + min_sdk_version: "32", + unsafe_ignore_missing_latest_api: true, + static_libs: ["util"], + } + + java_library { + name: "util", + srcs: ["a.java"], + apex_available: ["myapex"], + min_sdk_version: "31", + static_libs: ["another_util"], + } + + java_library { + name: "another_util", + srcs: ["a.java"], + min_sdk_version: "31", + apex_available: ["myapex"], + } + `) + }) + + t.Run("bootclasspath_fragment jar must set min_sdk_version", func(t *testing.T) { + preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "mybootclasspathlib".*must set min_sdk_version`)). + RunTestWithBp(t, ` + apex { + name: "myapex", + key: "myapex.key", + bootclasspath_fragments: ["mybootclasspathfragment"], + min_sdk_version: "30", + updatable: false, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + bootclasspath_fragment { + name: "mybootclasspathfragment", + contents: ["mybootclasspathlib"], + apex_available: ["myapex"], + } + + java_sdk_library { + name: "mybootclasspathlib", + srcs: ["mybootclasspathlib.java"], + apex_available: ["myapex"], + compile_dex: true, + unsafe_ignore_missing_latest_api: true, + } + `) + }) + + t.Run("systemserverclasspath_fragment jar must set min_sdk_version", func(t *testing.T) { + preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "mysystemserverclasspathlib".*must set min_sdk_version`)). + RunTestWithBp(t, ` + apex { + name: "myapex", + key: "myapex.key", + systemserverclasspath_fragments: ["mysystemserverclasspathfragment"], + min_sdk_version: "30", + updatable: false, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + systemserverclasspath_fragment { + name: "mysystemserverclasspathfragment", + contents: ["mysystemserverclasspathlib"], + apex_available: ["myapex"], + } + + java_sdk_library { + name: "mysystemserverclasspathlib", + srcs: ["mysystemserverclasspathlib.java"], + apex_available: ["myapex"], + compile_dex: true, + unsafe_ignore_missing_latest_api: true, + } + `) + }) +} + func TestMain(m *testing.M) { os.Exit(m.Run()) } diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go index cb7d3d113..9e030f10c 100644 --- a/apex/bootclasspath_fragment_test.go +++ b/apex/bootclasspath_fragment_test.go @@ -21,6 +21,7 @@ import ( "testing" "android/soong/android" + "android/soong/dexpreopt" "android/soong/java" "github.com/google/blueprint/proptools" @@ -35,11 +36,14 @@ var prepareForTestWithBootclasspathFragment = android.GroupFixturePreparers( ) // Some additional files needed for the art apex. -var prepareForTestWithArtApex = android.FixtureMergeMockFs(android.MockFS{ - "com.android.art.avbpubkey": nil, - "com.android.art.pem": nil, - "system/sepolicy/apex/com.android.art-file_contexts": nil, -}) +var prepareForTestWithArtApex = android.GroupFixturePreparers( + android.FixtureMergeMockFs(android.MockFS{ + "com.android.art.avbpubkey": nil, + "com.android.art.pem": nil, + "system/sepolicy/apex/com.android.art-file_contexts": nil, + }), + dexpreopt.FixtureSetBootImageProfiles("art/build/boot/boot-image-profile.txt"), +) func TestBootclasspathFragments(t *testing.T) { result := android.GroupFixturePreparers( @@ -408,6 +412,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) { ).RunTest(t) ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{ + "etc/boot-image.prof", "etc/classpaths/bootclasspath.pb", "javalib/arm/boot.art", "javalib/arm/boot.oat", @@ -451,6 +456,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) { ).RunTest(t) ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{ + "etc/boot-image.prof", "etc/classpaths/bootclasspath.pb", "javalib/arm/boot.art", "javalib/arm/boot.oat", diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go index 0bd71c63a..41f98862c 100644 --- a/bazel/cquery/request_type.go +++ b/bazel/cquery/request_type.go @@ -17,6 +17,7 @@ type CcInfo struct { CcStaticLibraryFiles []string Includes []string SystemIncludes []string + Headers []string // Archives owned by the current target (not by its dependencies). These will // be a subset of OutputFiles. (or static libraries, this will be equal to OutputFiles, // but general cc_library will also have dynamic libraries in output files). @@ -105,6 +106,7 @@ cc_info = providers(target)["CcInfo"] includes = cc_info.compilation_context.includes.to_list() system_includes = cc_info.compilation_context.system_includes.to_list() +headers = [f.path for f in cc_info.compilation_context.headers.to_list()] ccObjectFiles = [] staticLibraries = [] @@ -145,6 +147,7 @@ returns = [ ccObjectFiles, includes, system_includes, + headers, rootStaticArchives, rootDynamicLibraries, [toc_file] @@ -161,7 +164,7 @@ func (g getCcInfoType) ParseResult(rawString string) (CcInfo, error) { var ccObjects []string splitString := strings.Split(rawString, "|") - if expectedLen := 8; len(splitString) != expectedLen { + if expectedLen := 9; len(splitString) != expectedLen { return CcInfo{}, fmt.Errorf("Expected %d items, got %q", expectedLen, splitString) } outputFilesString := splitString[0] @@ -172,15 +175,17 @@ func (g getCcInfoType) ParseResult(rawString string) (CcInfo, error) { ccObjects = splitOrEmpty(ccObjectsString, ", ") includes := splitOrEmpty(splitString[3], ", ") systemIncludes := splitOrEmpty(splitString[4], ", ") - rootStaticArchives := splitOrEmpty(splitString[5], ", ") - rootDynamicLibraries := splitOrEmpty(splitString[6], ", ") - tocFile := splitString[7] // NOTE: Will be the empty string if there wasn't + headers := splitOrEmpty(splitString[5], ", ") + rootStaticArchives := splitOrEmpty(splitString[6], ", ") + rootDynamicLibraries := splitOrEmpty(splitString[7], ", ") + tocFile := splitString[8] // NOTE: Will be the empty string if there wasn't return CcInfo{ OutputFiles: outputFiles, CcObjectFiles: ccObjects, CcStaticLibraryFiles: ccStaticLibraries, Includes: includes, SystemIncludes: systemIncludes, + Headers: headers, RootStaticArchives: rootStaticArchives, RootDynamicLibraries: rootDynamicLibraries, TocFile: tocFile, diff --git a/bazel/cquery/request_type_test.go b/bazel/cquery/request_type_test.go index 34d083226..d3bcb45f4 100644 --- a/bazel/cquery/request_type_test.go +++ b/bazel/cquery/request_type_test.go @@ -71,13 +71,14 @@ func TestGetCcInfoParseResults(t *testing.T) { }{ { description: "no result", - input: "|||||||", + input: "||||||||", expectedOutput: CcInfo{ OutputFiles: []string{}, CcObjectFiles: []string{}, CcStaticLibraryFiles: []string{}, Includes: []string{}, SystemIncludes: []string{}, + Headers: []string{}, RootStaticArchives: []string{}, RootDynamicLibraries: []string{}, TocFile: "", @@ -85,13 +86,14 @@ func TestGetCcInfoParseResults(t *testing.T) { }, { description: "only output", - input: "test|||||||", + input: "test||||||||", expectedOutput: CcInfo{ OutputFiles: []string{"test"}, CcObjectFiles: []string{}, CcStaticLibraryFiles: []string{}, Includes: []string{}, SystemIncludes: []string{}, + Headers: []string{}, RootStaticArchives: []string{}, RootDynamicLibraries: []string{}, TocFile: "", @@ -99,13 +101,14 @@ func TestGetCcInfoParseResults(t *testing.T) { }, { description: "all items set", - input: "out1, out2|static_lib1, static_lib2|object1, object2|., dir/subdir|system/dir, system/other/dir|rootstaticarchive1|rootdynamiclibrary1|lib.so.toc", + input: "out1, out2|static_lib1, static_lib2|object1, object2|., dir/subdir|system/dir, system/other/dir|dir/subdir/hdr.h|rootstaticarchive1|rootdynamiclibrary1|lib.so.toc", 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"}, + Headers: []string{"dir/subdir/hdr.h"}, RootStaticArchives: []string{"rootstaticarchive1"}, RootDynamicLibraries: []string{"rootdynamiclibrary1"}, TocFile: "lib.so.toc", @@ -115,13 +118,13 @@ func TestGetCcInfoParseResults(t *testing.T) { description: "too few result splits", input: "|", expectedOutput: CcInfo{}, - expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 8, []string{"", ""}), + expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 9, []string{"", ""}), }, { description: "too many result splits", - input: strings.Repeat("|", 8), + input: strings.Repeat("|", 50), expectedOutput: CcInfo{}, - expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 8, make([]string, 9)), + expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 9, make([]string, 51)), }, } for _, tc := range testCases { diff --git a/bazel/properties.go b/bazel/properties.go index b370bbfb2..76be0581b 100644 --- a/bazel/properties.go +++ b/bazel/properties.go @@ -107,6 +107,14 @@ func (ll *LabelList) uniqueParentDirectories() []string { return dirs } +// Add inserts the label Label at the end of the LabelList. +func (ll *LabelList) Add(label *Label) { + if label == nil { + return + } + ll.Includes = append(ll.Includes, *label) +} + // Append appends the fields of other labelList to the corresponding fields of ll. func (ll *LabelList) Append(other LabelList) { if len(ll.Includes) > 0 || len(other.Includes) > 0 { @@ -366,9 +374,23 @@ func (ba *BoolAttribute) SortedConfigurationAxes() []ConfigurationAxis { // labelListSelectValues supports config-specific label_list typed Bazel attribute values. type labelListSelectValues map[string]LabelList -func (ll labelListSelectValues) appendSelects(other labelListSelectValues) { +func (ll labelListSelectValues) addSelects(label labelSelectValues) { + for k, v := range label { + if label == nil { + continue + } + l := ll[k] + (&l).Add(v) + ll[k] = l + } +} + +func (ll labelListSelectValues) appendSelects(other labelListSelectValues, forceSpecifyEmptyList bool) { for k, v := range other { l := ll[k] + if forceSpecifyEmptyList && l.IsNil() && !v.IsNil() { + l.Includes = []Label{} + } (&l).Append(v) ll[k] = l } @@ -424,17 +446,22 @@ func (cll configurableLabelLists) setValueForAxis(axis ConfigurationAxis, config cll[axis][config] = list } -func (cll configurableLabelLists) Append(other configurableLabelLists) { +func (cll configurableLabelLists) Append(other configurableLabelLists, forceSpecifyEmptyList bool) { for axis, otherSelects := range other { selects := cll[axis] if selects == nil { selects = make(labelListSelectValues, len(otherSelects)) } - selects.appendSelects(otherSelects) + selects.appendSelects(otherSelects, forceSpecifyEmptyList) cll[axis] = selects } } +func (lla *LabelListAttribute) Clone() *LabelListAttribute { + result := &LabelListAttribute{ForceSpecifyEmptyList: lla.ForceSpecifyEmptyList} + return result.Append(*lla) +} + // MakeLabelListAttribute initializes a LabelListAttribute with the non-arch specific value. func MakeLabelListAttribute(value LabelList) LabelListAttribute { return LabelListAttribute{ @@ -488,16 +515,37 @@ func (lla *LabelListAttribute) SortedConfigurationAxes() []ConfigurationAxis { } // Append all values, including os and arch specific ones, from another -// LabelListAttribute to this LabelListAttribute. -func (lla *LabelListAttribute) Append(other LabelListAttribute) { - if lla.ForceSpecifyEmptyList && !other.Value.IsNil() { +// LabelListAttribute to this LabelListAttribute. Returns this LabelListAttribute. +func (lla *LabelListAttribute) Append(other LabelListAttribute) *LabelListAttribute { + forceSpecifyEmptyList := lla.ForceSpecifyEmptyList || other.ForceSpecifyEmptyList + if forceSpecifyEmptyList && lla.Value.IsNil() && !other.Value.IsNil() { lla.Value.Includes = []Label{} } lla.Value.Append(other.Value) if lla.ConfigurableValues == nil { lla.ConfigurableValues = make(configurableLabelLists) } - lla.ConfigurableValues.Append(other.ConfigurableValues) + lla.ConfigurableValues.Append(other.ConfigurableValues, forceSpecifyEmptyList) + return lla +} + +// Add inserts the labels for each axis of LabelAttribute at the end of corresponding axis's +// LabelList within the LabelListAttribute +func (lla *LabelListAttribute) Add(label *LabelAttribute) { + if label == nil { + return + } + + lla.Value.Add(label.Value) + if lla.ConfigurableValues == nil && label.ConfigurableValues != nil { + lla.ConfigurableValues = make(configurableLabelLists) + } + for axis, _ := range label.ConfigurableValues { + if _, exists := lla.ConfigurableValues[axis]; !exists { + lla.ConfigurableValues[axis] = make(labelListSelectValues) + } + lla.ConfigurableValues[axis].addSelects(label.ConfigurableValues[axis]) + } } // HasConfigurableValues returns true if the attribute contains axis-specific label list values. @@ -566,7 +614,7 @@ type OtherModuleContext interface { // LabelMapper is a function that takes a OtherModuleContext and returns a (potentially changed) // label and whether it was changed. -type LabelMapper func(OtherModuleContext, string) (string, bool) +type LabelMapper func(OtherModuleContext, Label) (string, bool) // LabelPartition contains descriptions of a partition for labels type LabelPartition struct { @@ -588,7 +636,7 @@ type LabelPartitions map[string]LabelPartition // not. func (lf LabelPartition) filter(ctx OtherModuleContext, label Label) *Label { if lf.LabelMapper != nil { - if newLabel, changed := lf.LabelMapper(ctx, label.Label); changed { + if newLabel, changed := lf.LabelMapper(ctx, label); changed { return &Label{newLabel, label.OriginalModuleName} } } @@ -757,12 +805,18 @@ func (sla StringListAttribute) HasConfigurableValues() bool { // Append appends all values, including os and arch specific ones, from another // StringListAttribute to this StringListAttribute -func (sla *StringListAttribute) Append(other StringListAttribute) { +func (sla *StringListAttribute) Append(other StringListAttribute) *StringListAttribute { sla.Value = append(sla.Value, other.Value...) if sla.ConfigurableValues == nil { sla.ConfigurableValues = make(configurableStringLists) } sla.ConfigurableValues.Append(other.ConfigurableValues) + return sla +} + +func (sla *StringListAttribute) Clone() *StringListAttribute { + result := &StringListAttribute{} + return result.Append(*sla) } // SetSelectValue set a value for a bazel select for the given axis, config and value. diff --git a/bazel/properties_test.go b/bazel/properties_test.go index 7a7d6f3b8..c7f977678 100644 --- a/bazel/properties_test.go +++ b/bazel/properties_test.go @@ -313,16 +313,16 @@ func TestResolveExcludes(t *testing.T) { // labelAddSuffixForTypeMapper returns a LabelMapper that adds suffix to label name for modules of // typ func labelAddSuffixForTypeMapper(suffix, typ string) LabelMapper { - return func(omc OtherModuleContext, label string) (string, bool) { - m, ok := omc.ModuleFromName(label) + return func(omc OtherModuleContext, label Label) (string, bool) { + m, ok := omc.ModuleFromName(label.Label) if !ok { - return label, false + return label.Label, false } mTyp := omc.OtherModuleType(m) if typ == mTyp { - return label + suffix, true + return label.Label + suffix, true } - return label, false + return label.Label, false } } diff --git a/bp2build/android_app_conversion_test.go b/bp2build/android_app_conversion_test.go new file mode 100644 index 000000000..b12b567f3 --- /dev/null +++ b/bp2build/android_app_conversion_test.go @@ -0,0 +1,92 @@ +// 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 bp2build + +import ( + "android/soong/android" + "android/soong/java" + + "testing" +) + +func runAndroidAppTestCase(t *testing.T, tc bp2buildTestCase) { + t.Helper() + runBp2BuildTestCase(t, registerAndroidAppModuleTypes, tc) +} + +func registerAndroidAppModuleTypes(ctx android.RegistrationContext) { +} + +func TestMinimalAndroidApp(t *testing.T) { + runAndroidAppTestCase(t, bp2buildTestCase{ + description: "Android app - simple example", + moduleTypeUnderTest: "android_app", + moduleTypeUnderTestFactory: java.AndroidAppFactory, + moduleTypeUnderTestBp2BuildMutator: java.AppBp2Build, + filesystem: map[string]string{ + "app.java": "", + "res/res.png": "", + "AndroidManifest.xml": "", + }, + blueprint: ` +android_app { + name: "TestApp", + srcs: ["app.java"], + sdk_version: "current", +} +`, + expectedBazelTargets: []string{ + makeBazelTarget("android_binary", "TestApp", attrNameToString{ + "srcs": `["app.java"]`, + "manifest": `"AndroidManifest.xml"`, + "resource_files": `["res/res.png"]`, + }), + }}) +} + +func TestAndroidAppAllSupportedFields(t *testing.T) { + runAndroidAppTestCase(t, bp2buildTestCase{ + description: "Android app - all supported fields", + moduleTypeUnderTest: "android_app", + moduleTypeUnderTestFactory: java.AndroidAppFactory, + moduleTypeUnderTestBp2BuildMutator: java.AppBp2Build, + filesystem: map[string]string{ + "app.java": "", + "resa/res.png": "", + "resb/res.png": "", + "manifest/AndroidManifest.xml": "", + }, + blueprint: ` +android_app { + name: "TestApp", + srcs: ["app.java"], + sdk_version: "current", + package_name: "com.google", + resource_dirs: ["resa", "resb"], + manifest: "manifest/AndroidManifest.xml", +} +`, + expectedBazelTargets: []string{ + makeBazelTarget("android_binary", "TestApp", attrNameToString{ + "srcs": `["app.java"]`, + "manifest": `"manifest/AndroidManifest.xml"`, + "resource_files": `[ + "resa/res.png", + "resb/res.png", + ]`, + "custom_package": `"com.google"`, + }), + }}) +} diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go index f9abcba6f..24468506f 100644 --- a/bp2build/cc_binary_conversion_test.go +++ b/bp2build/cc_binary_conversion_test.go @@ -24,8 +24,7 @@ import ( ) const ( - ccBinaryTypePlaceHolder = "{rule_name}" - compatibleWithPlaceHolder = "{target_compatible_with}" + ccBinaryTypePlaceHolder = "{rule_name}" ) type testBazelTarget struct { @@ -84,12 +83,15 @@ func runCcBinaryTestCase(t *testing.T, tc ccBinaryBp2buildTestCase) { func runCcHostBinaryTestCase(t *testing.T, tc ccBinaryBp2buildTestCase) { t.Helper() testCase := tc - for i, t := range testCase.targets { - t.attrs["target_compatible_with"] = `select({ + for i, tar := range testCase.targets { + if tar.typ != "cc_binary" { + continue + } + tar.attrs["target_compatible_with"] = `select({ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"], "//conditions:default": [], })` - testCase.targets[i] = t + testCase.targets[i] = tar } moduleTypeUnderTest := "cc_binary_host" t.Run(testCase.description, func(t *testing.T) { @@ -448,3 +450,51 @@ func TestCcBinaryPropertiesToFeatures(t *testing.T) { }) } } + +func TestCcBinarySharedProto(t *testing.T) { + runCcBinaryTests(t, ccBinaryBp2buildTestCase{ + blueprint: soongCcProtoLibraries + `{rule_name} { + name: "foo", + srcs: ["foo.proto"], + proto: { + canonical_path_from_root: false, + }, + include_build_directory: false, +}`, + targets: []testBazelTarget{ + {"proto_library", "foo_proto", attrNameToString{ + "srcs": `["foo.proto"]`, + }}, {"cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{ + "deps": `[":foo_proto"]`, + }}, {"cc_binary", "foo", attrNameToString{ + "dynamic_deps": `[":libprotobuf-cpp-lite"]`, + "whole_archive_deps": `[":foo_cc_proto_lite"]`, + }}, + }, + }) +} + +func TestCcBinaryStaticProto(t *testing.T) { + runCcBinaryTests(t, ccBinaryBp2buildTestCase{ + blueprint: soongCcProtoLibraries + `{rule_name} { + name: "foo", + srcs: ["foo.proto"], + static_executable: true, + proto: { + canonical_path_from_root: false, + }, + include_build_directory: false, +}`, + targets: []testBazelTarget{ + {"proto_library", "foo_proto", attrNameToString{ + "srcs": `["foo.proto"]`, + }}, {"cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{ + "deps": `[":foo_proto"]`, + }}, {"cc_binary", "foo", attrNameToString{ + "deps": `[":libprotobuf-cpp-lite"]`, + "whole_archive_deps": `[":foo_cc_proto_lite"]`, + "linkshared": `False`, + }}, + }, + }) +} diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go index d23ea01ed..dcbe326e9 100644 --- a/bp2build/cc_library_conversion_test.go +++ b/bp2build/cc_library_conversion_test.go @@ -39,6 +39,19 @@ toolchain_library { native_bridge_supported: true, src: "", }` + + soongCcProtoLibraries = ` +cc_library { + name: "libprotobuf-cpp-lite", + bazel_module: { bp2build_available: false }, +} + +cc_library { + name: "libprotobuf-cpp-full", + bazel_module: { bp2build_available: false }, +}` + + soongCcProtoPreamble = soongCcLibraryPreamble + soongCcProtoLibraries ) func runCcLibraryTestCase(t *testing.T, tc bp2buildTestCase) { @@ -117,17 +130,16 @@ cc_library { include_build_directory: false, } `, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "foo-lib", attrNameToString{ - "copts": `["-Wall"]`, - "export_includes": `["foo-dir"]`, - "implementation_deps": `[":some-headers"]`, - "linkopts": `["-Wl,--exclude-libs=bar.a"] + select({ + expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{ + "copts": `["-Wall"]`, + "export_includes": `["foo-dir"]`, + "implementation_deps": `[":some-headers"]`, + "linkopts": `["-Wl,--exclude-libs=bar.a"] + select({ "//build/bazel/platforms/arch:x86": ["-Wl,--exclude-libs=baz.a"], "//build/bazel/platforms/arch:x86_64": ["-Wl,--exclude-libs=qux.a"], "//conditions:default": [], })`, - "srcs": `["impl.cpp"] + select({ + "srcs": `["impl.cpp"] + select({ "//build/bazel/platforms/arch:x86": ["x86.cpp"], "//build/bazel/platforms/arch:x86_64": ["x86_64.cpp"], "//conditions:default": [], @@ -141,8 +153,7 @@ cc_library { "//build/bazel/platforms/os:linux_bionic": ["bionic.cpp"], "//conditions:default": [], })`, - }), - }, + }), }) } @@ -190,17 +201,16 @@ cc_library { include_build_directory: false, } `, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "fake-ld-android", attrNameToString{ - "srcs": `["ld_android.cpp"]`, - "copts": `[ + expectedBazelTargets: makeCcLibraryTargets("fake-ld-android", attrNameToString{ + "srcs": `["ld_android.cpp"]`, + "copts": `[ "-Wall", "-Wextra", "-Wunused", "-Werror", ]`, - "implementation_deps": `[":libc_headers"]`, - "linkopts": `[ + "implementation_deps": `[":libc_headers"]`, + "linkopts": `[ "-Wl,--exclude-libs=libgcc.a", "-Wl,--exclude-libs=libgcc_stripped.a", "-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a", @@ -212,8 +222,7 @@ cc_library { "//build/bazel/platforms/arch:x86_64": ["-Wl,--exclude-libs=libgcc_eh.a"], "//conditions:default": [], })`, - }), - }, + }), }) } @@ -258,16 +267,14 @@ cc_library { `, }, blueprint: soongCcLibraryPreamble, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "fake-libarm-optimized-routines-math", attrNameToString{ - "copts": `select({ + expectedBazelTargets: makeCcLibraryTargets("fake-libarm-optimized-routines-math", attrNameToString{ + "copts": `select({ "//build/bazel/platforms/arch:arm64": ["-DHAVE_FAST_FMA=1"], "//conditions:default": [], })`, - "local_includes": `["."]`, - "srcs_c": `["math/cosf.c"]`, - }), - }, + "local_includes": `["."]`, + "srcs_c": `["math/cosf.c"]`, + }), }) } @@ -353,26 +360,48 @@ cc_library { } `, expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "a", attrNameToString{ - "copts": `["bothflag"]`, - "implementation_deps": `[":static_dep_for_both"]`, - "implementation_dynamic_deps": `[":shared_dep_for_both"]`, - "shared": `{ - "copts": ["sharedflag"], - "implementation_deps": [":static_dep_for_shared"], - "implementation_dynamic_deps": [":shared_dep_for_shared"], - "srcs": ["sharedonly.cpp"], - "whole_archive_deps": [":whole_static_lib_for_shared"], - }`, - "srcs": `["both.cpp"]`, - "static": `{ - "copts": ["staticflag"], - "implementation_deps": [":static_dep_for_static"], - "implementation_dynamic_deps": [":shared_dep_for_static"], - "srcs": ["staticonly.cpp"], - "whole_archive_deps": [":whole_static_lib_for_static"], - }`, - "whole_archive_deps": `[":whole_static_lib_for_both"]`, + makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", attrNameToString{ + "copts": `[ + "bothflag", + "staticflag", + ]`, + "implementation_deps": `[ + ":static_dep_for_both", + ":static_dep_for_static", + ]`, + "implementation_dynamic_deps": `[ + ":shared_dep_for_both", + ":shared_dep_for_static", + ]`, + "srcs": `[ + "both.cpp", + "staticonly.cpp", + ]`, + "whole_archive_deps": `[ + ":whole_static_lib_for_both", + ":whole_static_lib_for_static", + ]`}), + makeBazelTarget("cc_library_shared", "a", attrNameToString{ + "copts": `[ + "bothflag", + "sharedflag", + ]`, + "implementation_deps": `[ + ":static_dep_for_both", + ":static_dep_for_shared", + ]`, + "implementation_dynamic_deps": `[ + ":shared_dep_for_both", + ":shared_dep_for_shared", + ]`, + "srcs": `[ + "both.cpp", + "sharedonly.cpp", + ]`, + "whole_archive_deps": `[ + ":whole_static_lib_for_both", + ":whole_static_lib_for_shared", + ]`, }), }, }) @@ -438,44 +467,72 @@ cc_library { simpleModuleDoNotConvertBp2build("cc_library", "shared_dep_for_both") + simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_both"), expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "a", attrNameToString{ - "copts": `["bothflag"]`, - "deps": `[":static_dep_for_both"]`, - "dynamic_deps": `[":shared_dep_for_both"]`, - "implementation_deps": `[":implementation_static_dep_for_both"]`, - "implementation_dynamic_deps": `[":implementation_shared_dep_for_both"]`, - "shared": `{ - "copts": ["sharedflag"], - "deps": [":static_dep_for_shared"], - "dynamic_deps": [":shared_dep_for_shared"], - "implementation_deps": [":implementation_static_dep_for_shared"], - "implementation_dynamic_deps": [":implementation_shared_dep_for_shared"], - "srcs": ["sharedonly.cpp"], - "whole_archive_deps": [ - ":not_explicitly_exported_whole_static_dep_for_shared", - ":whole_static_dep_for_shared", - ], - }`, - "srcs": `["both.cpp"]`, - "static": `{ - "copts": ["staticflag"], - "deps": [":static_dep_for_static"], - "dynamic_deps": [":shared_dep_for_static"], - "implementation_deps": [":implementation_static_dep_for_static"], - "implementation_dynamic_deps": [":implementation_shared_dep_for_static"], - "srcs": ["staticonly.cpp"], - "whole_archive_deps": [ - ":not_explicitly_exported_whole_static_dep_for_static", - ":whole_static_dep_for_static", - ], - }`, + makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", attrNameToString{ + "copts": `[ + "bothflag", + "staticflag", + ]`, + "deps": `[ + ":static_dep_for_both", + ":static_dep_for_static", + ]`, + "dynamic_deps": `[ + ":shared_dep_for_both", + ":shared_dep_for_static", + ]`, + "implementation_deps": `[ + ":implementation_static_dep_for_both", + ":implementation_static_dep_for_static", + ]`, + "implementation_dynamic_deps": `[ + ":implementation_shared_dep_for_both", + ":implementation_shared_dep_for_static", + ]`, + "srcs": `[ + "both.cpp", + "staticonly.cpp", + ]`, "whole_archive_deps": `[ ":not_explicitly_exported_whole_static_dep_for_both", ":whole_static_dep_for_both", + ":not_explicitly_exported_whole_static_dep_for_static", + ":whole_static_dep_for_static", ]`, }), - }, - }) + makeBazelTarget("cc_library_shared", "a", attrNameToString{ + "copts": `[ + "bothflag", + "sharedflag", + ]`, + "deps": `[ + ":static_dep_for_both", + ":static_dep_for_shared", + ]`, + "dynamic_deps": `[ + ":shared_dep_for_both", + ":shared_dep_for_shared", + ]`, + "implementation_deps": `[ + ":implementation_static_dep_for_both", + ":implementation_static_dep_for_shared", + ]`, + "implementation_dynamic_deps": `[ + ":implementation_shared_dep_for_both", + ":implementation_shared_dep_for_shared", + ]`, + "srcs": `[ + "both.cpp", + "sharedonly.cpp", + ]`, + "whole_archive_deps": `[ + ":not_explicitly_exported_whole_static_dep_for_both", + ":whole_static_dep_for_both", + ":not_explicitly_exported_whole_static_dep_for_shared", + ":whole_static_dep_for_shared", + ]`, + })}, + }, + ) } func TestCcLibraryWholeStaticLibsAlwaysLink(t *testing.T) { @@ -508,17 +565,21 @@ cc_prebuilt_library_static { name: "whole_static_lib_for_both" } }, blueprint: soongCcLibraryPreamble, expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "a", attrNameToString{ - "shared": `{ - "whole_archive_deps": [":whole_static_lib_for_shared_alwayslink"], - }`, - "static": `{ - "whole_archive_deps": [":whole_static_lib_for_static_alwayslink"], - }`, - "whole_archive_deps": `[":whole_static_lib_for_both_alwayslink"]`, + makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", attrNameToString{ + "whole_archive_deps": `[ + ":whole_static_lib_for_both_alwayslink", + ":whole_static_lib_for_static_alwayslink", + ]`, + }), + makeBazelTarget("cc_library_shared", "a", attrNameToString{ + "whole_archive_deps": `[ + ":whole_static_lib_for_both_alwayslink", + ":whole_static_lib_for_shared_alwayslink", + ]`, }), }, - }) + }, + ) } func TestCcLibrarySharedStaticPropsInArch(t *testing.T) { @@ -599,62 +660,77 @@ cc_library_static { name: "android_dep_for_shared" } }, blueprint: soongCcLibraryPreamble, expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "a", attrNameToString{ - "copts": `["bothflag"]`, - "implementation_deps": `[":static_dep_for_both"]`, - "local_includes": `["."]`, - "shared": `{ - "copts": ["sharedflag"] + select({ - "//build/bazel/platforms/arch:arm": ["-DARM_SHARED"], - "//conditions:default": [], - }) + select({ - "//build/bazel/platforms/os:android": ["-DANDROID_SHARED"], - "//conditions:default": [], - }) + select({ - "//build/bazel/platforms/os_arch:android_arm": ["-DANDROID_ARM_SHARED"], - "//conditions:default": [], - }), - "implementation_deps": [":static_dep_for_shared"] + select({ - "//build/bazel/platforms/arch:arm": [":arm_static_dep_for_shared"], - "//conditions:default": [], - }) + select({ - "//build/bazel/platforms/os:android": [":android_dep_for_shared"], - "//conditions:default": [], - }), - "implementation_dynamic_deps": select({ - "//build/bazel/platforms/arch:arm": [":arm_shared_dep_for_shared"], - "//conditions:default": [], - }), - "srcs": ["sharedonly.cpp"] + select({ - "//build/bazel/platforms/arch:arm": ["arm_shared.cpp"], - "//conditions:default": [], - }) + select({ - "//build/bazel/platforms/os:android": ["android_shared.cpp"], - "//conditions:default": [], - }), - "whole_archive_deps": select({ - "//build/bazel/platforms/arch:arm": [":arm_whole_static_dep_for_shared"], - "//conditions:default": [], - }), - }`, - "srcs": `["both.cpp"]`, - "static": `{ - "copts": ["staticflag"] + select({ - "//build/bazel/platforms/arch:x86": ["-DX86_STATIC"], - "//conditions:default": [], - }), - "implementation_deps": [":static_dep_for_static"] + select({ - "//build/bazel/platforms/arch:x86": [":x86_dep_for_static"], - "//conditions:default": [], - }), - "srcs": ["staticonly.cpp"] + select({ - "//build/bazel/platforms/arch:x86": ["x86_static.cpp"], - "//conditions:default": [], - }), - }`, + makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", attrNameToString{ + "copts": `[ + "bothflag", + "staticflag", + ] + select({ + "//build/bazel/platforms/arch:x86": ["-DX86_STATIC"], + "//conditions:default": [], + })`, + "implementation_deps": `[ + ":static_dep_for_both", + ":static_dep_for_static", + ] + select({ + "//build/bazel/platforms/arch:x86": [":x86_dep_for_static"], + "//conditions:default": [], + })`, + "local_includes": `["."]`, + "srcs": `[ + "both.cpp", + "staticonly.cpp", + ] + select({ + "//build/bazel/platforms/arch:x86": ["x86_static.cpp"], + "//conditions:default": [], + })`, + }), + makeBazelTarget("cc_library_shared", "a", attrNameToString{ + "copts": `[ + "bothflag", + "sharedflag", + ] + select({ + "//build/bazel/platforms/arch:arm": ["-DARM_SHARED"], + "//conditions:default": [], + }) + select({ + "//build/bazel/platforms/os:android": ["-DANDROID_SHARED"], + "//conditions:default": [], + }) + select({ + "//build/bazel/platforms/os_arch:android_arm": ["-DANDROID_ARM_SHARED"], + "//conditions:default": [], + })`, + "implementation_deps": `[ + ":static_dep_for_both", + ":static_dep_for_shared", + ] + select({ + "//build/bazel/platforms/arch:arm": [":arm_static_dep_for_shared"], + "//conditions:default": [], + }) + select({ + "//build/bazel/platforms/os:android": [":android_dep_for_shared"], + "//conditions:default": [], + })`, + "implementation_dynamic_deps": `select({ + "//build/bazel/platforms/arch:arm": [":arm_shared_dep_for_shared"], + "//conditions:default": [], + })`, + "local_includes": `["."]`, + "srcs": `[ + "both.cpp", + "sharedonly.cpp", + ] + select({ + "//build/bazel/platforms/arch:arm": ["arm_shared.cpp"], + "//conditions:default": [], + }) + select({ + "//build/bazel/platforms/os:android": ["android_shared.cpp"], + "//conditions:default": [], + })`, + "whole_archive_deps": `select({ + "//build/bazel/platforms/arch:arm": [":arm_whole_static_dep_for_shared"], + "//conditions:default": [], + })`, }), }, - }) + }, + ) } func TestCcLibrarySharedStaticPropsWithMixedSources(t *testing.T) { @@ -738,57 +814,56 @@ filegroup { }, blueprint: soongCcLibraryPreamble, expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "a", attrNameToString{ + makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", attrNameToString{ "local_includes": `["."]`, - "shared": `{ - "srcs": [ - "shared_source.cpp", - "shared_source.cc", - ":shared_filegroup_cpp_srcs", - ], - "srcs_as": [ - "shared_source.s", - "shared_source.S", - ":shared_filegroup_as_srcs", - ], - "srcs_c": [ - "shared_source.c", - ":shared_filegroup_c_srcs", - ], - }`, "srcs": `[ "both_source.cpp", "both_source.cc", ":both_filegroup_cpp_srcs", + "static_source.cpp", + "static_source.cc", + ":static_filegroup_cpp_srcs", ]`, "srcs_as": `[ "both_source.s", "both_source.S", ":both_filegroup_as_srcs", + "static_source.s", + "static_source.S", + ":static_filegroup_as_srcs", ]`, "srcs_c": `[ "both_source.c", ":both_filegroup_c_srcs", + "static_source.c", + ":static_filegroup_c_srcs", ]`, - "static": `{ - "srcs": [ - "static_source.cpp", - "static_source.cc", - ":static_filegroup_cpp_srcs", - ], - "srcs_as": [ - "static_source.s", - "static_source.S", - ":static_filegroup_as_srcs", - ], - "srcs_c": [ - "static_source.c", - ":static_filegroup_c_srcs", - ], - }`, }), - }, - }) + makeBazelTarget("cc_library_shared", "a", attrNameToString{ + "local_includes": `["."]`, + "srcs": `[ + "both_source.cpp", + "both_source.cc", + ":both_filegroup_cpp_srcs", + "shared_source.cpp", + "shared_source.cc", + ":shared_filegroup_cpp_srcs", + ]`, + "srcs_as": `[ + "both_source.s", + "both_source.S", + ":both_filegroup_as_srcs", + "shared_source.s", + "shared_source.S", + ":shared_filegroup_as_srcs", + ]`, + "srcs_c": `[ + "both_source.c", + ":both_filegroup_c_srcs", + "shared_source.c", + ":shared_filegroup_c_srcs", + ]`, + })}}) } func TestCcLibraryNonConfiguredVersionScript(t *testing.T) { @@ -810,14 +885,13 @@ cc_library { `, }, blueprint: soongCcLibraryPreamble, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "a", attrNameToString{ - "additional_linker_inputs": `["v.map"]`, - "linkopts": `["-Wl,--version-script,$(location v.map)"]`, - "srcs": `["a.cpp"]`, - }), - }, - }) + expectedBazelTargets: makeCcLibraryTargets("a", attrNameToString{ + "additional_linker_inputs": `["v.map"]`, + "linkopts": `["-Wl,--version-script,$(location v.map)"]`, + "srcs": `["a.cpp"]`, + }), + }, + ) } func TestCcLibraryConfiguredVersionScript(t *testing.T) { @@ -847,22 +921,21 @@ cc_library { `, }, blueprint: soongCcLibraryPreamble, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "a", attrNameToString{ - "additional_linker_inputs": `select({ + expectedBazelTargets: makeCcLibraryTargets("a", attrNameToString{ + "additional_linker_inputs": `select({ "//build/bazel/platforms/arch:arm": ["arm.map"], "//build/bazel/platforms/arch:arm64": ["arm64.map"], "//conditions:default": [], })`, - "linkopts": `select({ + "linkopts": `select({ "//build/bazel/platforms/arch:arm": ["-Wl,--version-script,$(location arm.map)"], "//build/bazel/platforms/arch:arm64": ["-Wl,--version-script,$(location arm64.map)"], "//conditions:default": [], })`, - "srcs": `["a.cpp"]`, - }), - }, - }) + "srcs": `["a.cpp"]`, + }), + }, + ) } func TestCcLibrarySharedLibs(t *testing.T) { @@ -883,15 +956,43 @@ cc_library { include_build_directory: false, } `, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "a", attrNameToString{ - "implementation_dynamic_deps": `[":mylib"]`, - }), - }, - }) + expectedBazelTargets: makeCcLibraryTargets("a", attrNameToString{ + "implementation_dynamic_deps": `[":mylib"]`, + }), + }, + ) } func TestCcLibraryFeatures(t *testing.T) { + expected_targets := []string{} + expected_targets = append(expected_targets, makeCcLibraryTargets("a", attrNameToString{ + "features": `[ + "disable_pack_relocations", + "-no_undefined_symbols", + ]`, + "srcs": `["a.cpp"]`, + })...) + expected_targets = append(expected_targets, makeCcLibraryTargets("b", attrNameToString{ + "features": `select({ + "//build/bazel/platforms/arch:x86_64": [ + "disable_pack_relocations", + "-no_undefined_symbols", + ], + "//conditions:default": [], + })`, + "srcs": `["b.cpp"]`, + })...) + expected_targets = append(expected_targets, makeCcLibraryTargets("c", attrNameToString{ + "features": `select({ + "//build/bazel/platforms/os:darwin": [ + "disable_pack_relocations", + "-no_undefined_symbols", + ], + "//conditions:default": [], + })`, + "srcs": `["c.cpp"]`, + })...) + runCcLibraryTestCase(t, bp2buildTestCase{ description: "cc_library pack_relocations test", moduleTypeUnderTest: "cc_library", @@ -929,33 +1030,7 @@ cc_library { }, include_build_directory: false, }`, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "a", attrNameToString{ - "features": `[ - "disable_pack_relocations", - "-no_undefined_symbols", - ]`, - "srcs": `["a.cpp"]`, - }), makeBazelTarget("cc_library", "b", attrNameToString{ - "features": `select({ - "//build/bazel/platforms/arch:x86_64": [ - "disable_pack_relocations", - "-no_undefined_symbols", - ], - "//conditions:default": [], - })`, - "srcs": `["b.cpp"]`, - }), makeBazelTarget("cc_library", "c", attrNameToString{ - "features": `select({ - "//build/bazel/platforms/os:darwin": [ - "disable_pack_relocations", - "-no_undefined_symbols", - ], - "//conditions:default": [], - })`, - "srcs": `["c.cpp"]`, - }), - }, + expectedBazelTargets: expected_targets, }) } @@ -972,15 +1047,14 @@ cc_library { include_build_directory: false, } `, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "a", attrNameToString{ - "copts": `[ + expectedBazelTargets: makeCcLibraryTargets("a", attrNameToString{ + "copts": `[ "-include", "header.h", ]`, - }), - }, - }) + }), + }, + ) } func TestCcLibraryCppFlagsGoesIntoCopts(t *testing.T) { @@ -1010,10 +1084,9 @@ func TestCcLibraryCppFlagsGoesIntoCopts(t *testing.T) { include_build_directory: false, } `, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "a", attrNameToString{ - "copts": `["-Wall"]`, - "cppflags": `[ + expectedBazelTargets: makeCcLibraryTargets("a", attrNameToString{ + "copts": `["-Wall"]`, + "cppflags": `[ "-fsigned-char", "-pedantic", ] + select({ @@ -1023,10 +1096,10 @@ func TestCcLibraryCppFlagsGoesIntoCopts(t *testing.T) { "//build/bazel/platforms/os:android": ["-DANDROID=1"], "//conditions:default": [], })`, - "srcs": `["a.cpp"]`, - }), - }, - }) + "srcs": `["a.cpp"]`, + }), + }, + ) } func TestCcLibraryExcludeLibs(t *testing.T) { @@ -1109,33 +1182,32 @@ cc_library { bazel_module: { bp2build_available: false }, } `, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "foo_static", attrNameToString{ - "implementation_deps": `select({ + expectedBazelTargets: makeCcLibraryTargets("foo_static", attrNameToString{ + "implementation_deps": `select({ "//build/bazel/platforms/arch:arm": [], "//conditions:default": [":arm_static_lib_excludes_bp2build_cc_library_static"], }) + select({ "//build/bazel/product_variables:malloc_not_svelte": [], "//conditions:default": [":malloc_not_svelte_static_lib_excludes_bp2build_cc_library_static"], })`, - "implementation_dynamic_deps": `select({ + "implementation_dynamic_deps": `select({ "//build/bazel/platforms/arch:arm": [], "//conditions:default": [":arm_shared_lib_excludes"], }) + select({ "//build/bazel/product_variables:malloc_not_svelte": [":malloc_not_svelte_shared_lib"], "//conditions:default": [], })`, - "srcs_c": `["common.c"]`, - "whole_archive_deps": `select({ + "srcs_c": `["common.c"]`, + "whole_archive_deps": `select({ "//build/bazel/platforms/arch:arm": [], "//conditions:default": [":arm_whole_static_lib_excludes_bp2build_cc_library_static"], }) + select({ "//build/bazel/product_variables:malloc_not_svelte": [":malloc_not_svelte_whole_static_lib_bp2build_cc_library_static"], "//conditions:default": [":malloc_not_svelte_whole_static_lib_excludes_bp2build_cc_library_static"], })`, - }), - }, - }) + }), + }, + ) } func TestCCLibraryNoCrtTrue(t *testing.T) { @@ -1155,13 +1227,12 @@ cc_library { include_build_directory: false, } `, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "foo-lib", attrNameToString{ - "link_crt": `False`, - "srcs": `["impl.cpp"]`, - }), - }, - }) + expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{ + "link_crt": `False`, + "srcs": `["impl.cpp"]`, + }), + }, + ) } func TestCCLibraryNoCrtFalse(t *testing.T) { @@ -1181,11 +1252,9 @@ cc_library { include_build_directory: false, } `, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "foo-lib", attrNameToString{ - "srcs": `["impl.cpp"]`, - }), - }, + expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{ + "srcs": `["impl.cpp"]`, + }), }) } @@ -1235,12 +1304,35 @@ cc_library { include_build_directory: false, } `, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "foo-lib", attrNameToString{ - "srcs": `["impl.cpp"]`, - "use_libcrt": `False`, - }), - }}) + expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{ + "srcs": `["impl.cpp"]`, + "use_libcrt": `False`, + }), + }) +} + +func makeCcLibraryTargets(name string, attrs attrNameToString) []string { + STATIC_ONLY_ATTRS := map[string]bool{} + SHARED_ONLY_ATTRS := map[string]bool{ + "link_crt": true, + "additional_linker_inputs": true, + "linkopts": true, + "strip": true, + } + sharedAttrs := attrNameToString{} + staticAttrs := attrNameToString{} + for key, val := range attrs { + if _, staticOnly := STATIC_ONLY_ATTRS[key]; !staticOnly { + sharedAttrs[key] = val + } + if _, sharedOnly := SHARED_ONLY_ATTRS[key]; !sharedOnly { + staticAttrs[key] = val + } + } + sharedTarget := makeBazelTarget("cc_library_shared", name, sharedAttrs) + staticTarget := makeBazelTarget("cc_library_static", name+"_bp2build_cc_library_static", staticAttrs) + + return []string{staticTarget, sharedTarget} } func TestCCLibraryNoLibCrtFalse(t *testing.T) { @@ -1260,12 +1352,11 @@ cc_library { include_build_directory: false, } `, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "foo-lib", attrNameToString{ - "srcs": `["impl.cpp"]`, - "use_libcrt": `True`, - }), - }}) + expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{ + "srcs": `["impl.cpp"]`, + "use_libcrt": `True`, + }), + }) } func TestCCLibraryNoLibCrtArchVariant(t *testing.T) { @@ -1291,19 +1382,46 @@ cc_library { include_build_directory: false, } `, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "foo-lib", attrNameToString{ - "srcs": `["impl.cpp"]`, - "use_libcrt": `select({ + expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{ + "srcs": `["impl.cpp"]`, + "use_libcrt": `select({ "//build/bazel/platforms/arch:arm": False, "//build/bazel/platforms/arch:x86": False, "//conditions:default": None, })`, - }), - }}) + }), + }) } func TestCcLibraryStrip(t *testing.T) { + expectedTargets := []string{} + expectedTargets = append(expectedTargets, makeCcLibraryTargets("all", attrNameToString{ + "strip": `{ + "all": True, + }`, + })...) + expectedTargets = append(expectedTargets, makeCcLibraryTargets("keep_symbols", attrNameToString{ + "strip": `{ + "keep_symbols": True, + }`, + })...) + expectedTargets = append(expectedTargets, makeCcLibraryTargets("keep_symbols_and_debug_frame", attrNameToString{ + "strip": `{ + "keep_symbols_and_debug_frame": True, + }`, + })...) + expectedTargets = append(expectedTargets, makeCcLibraryTargets("keep_symbols_list", attrNameToString{ + "strip": `{ + "keep_symbols_list": ["symbol"], + }`, + })...) + expectedTargets = append(expectedTargets, makeCcLibraryTargets("none", attrNameToString{ + "strip": `{ + "none": True, + }`, + })...) + expectedTargets = append(expectedTargets, makeCcLibraryTargets("nothing", attrNameToString{})...) + runCcLibraryTestCase(t, bp2buildTestCase{ description: "cc_library strip args", moduleTypeUnderTest: "cc_library", @@ -1350,29 +1468,7 @@ cc_library { include_build_directory: false, } `, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "all", attrNameToString{ - "strip": `{ - "all": True, - }`, - }), makeBazelTarget("cc_library", "keep_symbols", attrNameToString{ - "strip": `{ - "keep_symbols": True, - }`, - }), makeBazelTarget("cc_library", "keep_symbols_and_debug_frame", attrNameToString{ - "strip": `{ - "keep_symbols_and_debug_frame": True, - }`, - }), makeBazelTarget("cc_library", "keep_symbols_list", attrNameToString{ - "strip": `{ - "keep_symbols_list": ["symbol"], - }`, - }), makeBazelTarget("cc_library", "none", attrNameToString{ - "strip": `{ - "none": True, - }`, - }), makeBazelTarget("cc_library", "nothing", attrNameToString{}), - }, + expectedBazelTargets: expectedTargets, }) } @@ -1407,9 +1503,8 @@ cc_library { include_build_directory: false, } `, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "multi-arch", attrNameToString{ - "strip": `{ + expectedBazelTargets: makeCcLibraryTargets("multi-arch", attrNameToString{ + "strip": `{ "keep_symbols": select({ "//build/bazel/platforms/arch:arm64": True, "//conditions:default": None, @@ -1426,9 +1521,9 @@ cc_library { "//conditions:default": [], }), }`, - }), - }, - }) + }), + }, + ) } func TestCcLibrary_SystemSharedLibsRootEmpty(t *testing.T) { @@ -1444,12 +1539,11 @@ cc_library { include_build_directory: false, } `, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "root_empty", attrNameToString{ - "system_dynamic_deps": `[]`, - }), - }, - }) + expectedBazelTargets: makeCcLibraryTargets("root_empty", attrNameToString{ + "system_dynamic_deps": `[]`, + }), + }, + ) } func TestCcLibrary_SystemSharedLibsStaticEmpty(t *testing.T) { @@ -1468,11 +1562,10 @@ cc_library { } `, expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "static_empty", attrNameToString{ - "static": `{ - "system_dynamic_deps": [], - }`, + makeBazelTarget("cc_library_static", "static_empty_bp2build_cc_library_static", attrNameToString{ + "system_dynamic_deps": "[]", }), + makeBazelTarget("cc_library_shared", "static_empty", attrNameToString{}), }, }) } @@ -1493,10 +1586,9 @@ cc_library { } `, expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "shared_empty", attrNameToString{ - "shared": `{ - "system_dynamic_deps": [], - }`, + makeBazelTarget("cc_library_static", "shared_empty_bp2build_cc_library_static", attrNameToString{}), + makeBazelTarget("cc_library_shared", "shared_empty", attrNameToString{ + "system_dynamic_deps": "[]", }), }, }) @@ -1522,10 +1614,9 @@ cc_library { } `, expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "shared_empty", attrNameToString{ - "shared": `{ - "system_dynamic_deps": [], - }`, + makeBazelTarget("cc_library_static", "shared_empty_bp2build_cc_library_static", attrNameToString{}), + makeBazelTarget("cc_library_shared", "shared_empty", attrNameToString{ + "system_dynamic_deps": "[]", }), }, }) @@ -1552,12 +1643,11 @@ cc_library { include_build_directory: false, } `, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "target_linux_bionic_empty", attrNameToString{ - "system_dynamic_deps": `[]`, - }), - }, - }) + expectedBazelTargets: makeCcLibraryTargets("target_linux_bionic_empty", attrNameToString{ + "system_dynamic_deps": `[]`, + }), + }, + ) } func TestCcLibrary_SystemSharedLibsBionicEmpty(t *testing.T) { @@ -1577,12 +1667,11 @@ cc_library { include_build_directory: false, } `, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "target_bionic_empty", attrNameToString{ - "system_dynamic_deps": `[]`, - }), - }, - }) + expectedBazelTargets: makeCcLibraryTargets("target_bionic_empty", attrNameToString{ + "system_dynamic_deps": `[]`, + }), + }, + ) } func TestCcLibrary_SystemSharedLibsSharedAndRoot(t *testing.T) { @@ -1611,12 +1700,15 @@ cc_library { } `, expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "foo", attrNameToString{ - "shared": `{ - "system_dynamic_deps": [":libm"], - }`, + makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{ "system_dynamic_deps": `[":libc"]`, }), + makeBazelTarget("cc_library_shared", "foo", attrNameToString{ + "system_dynamic_deps": `[ + ":libc", + ":libm", + ]`, + }), }, }) } @@ -1659,9 +1751,8 @@ cc_library { include_build_directory: false, } `, - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", "foo-lib", attrNameToString{ - "srcs": `["base.cpp"] + select({ + expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{ + "srcs": `["base.cpp"] + select({ "//build/bazel/platforms/os:android": [ "linux.cpp", "bionic.cpp", @@ -1683,9 +1774,9 @@ cc_library { "//build/bazel/platforms/os:windows": ["windows.cpp"], "//conditions:default": [], })`, - }), - }, - }) + }), + }, + ) } func TestCcLibraryCppStdWithGnuExtensions_ConvertsToFeatureAttr(t *testing.T) { @@ -1783,9 +1874,7 @@ cc_library { include_build_directory: false, } `, name_prefix, cppStdProp, cStdProp, gnuExtensionsProp), - expectedBazelTargets: []string{ - makeBazelTarget("cc_library", name_prefix+"_full", attrs), - }, + expectedBazelTargets: makeCcLibraryTargets(name_prefix+"_full", attrs), }) runCcLibraryStaticTestCase(t, bp2buildTestCase{ @@ -1829,3 +1918,170 @@ cc_library_shared { }) } } + +func TestCcLibraryProtoSimple(t *testing.T) { + runCcLibraryTestCase(t, bp2buildTestCase{ + moduleTypeUnderTest: "cc_library", + moduleTypeUnderTestFactory: cc.LibraryFactory, + moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build, + blueprint: soongCcProtoPreamble + `cc_library { + name: "foo", + srcs: ["foo.proto"], + include_build_directory: false, +}`, + expectedBazelTargets: []string{ + makeBazelTarget("proto_library", "foo_proto", attrNameToString{ + "srcs": `["foo.proto"]`, + "strip_import_prefix": `""`, + }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{ + "deps": `[":foo_proto"]`, + }), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{ + "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`, + "deps": `[":libprotobuf-cpp-lite"]`, + }), makeBazelTarget("cc_library_shared", "foo", attrNameToString{ + "dynamic_deps": `[":libprotobuf-cpp-lite"]`, + }), + }, + }) +} + +func TestCcLibraryProtoNoCanonicalPathFromRoot(t *testing.T) { + runCcLibraryTestCase(t, bp2buildTestCase{ + moduleTypeUnderTest: "cc_library", + moduleTypeUnderTestFactory: cc.LibraryFactory, + moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build, + blueprint: soongCcProtoPreamble + `cc_library { + name: "foo", + srcs: ["foo.proto"], + proto: { canonical_path_from_root: false}, + include_build_directory: false, +}`, + expectedBazelTargets: []string{ + makeBazelTarget("proto_library", "foo_proto", attrNameToString{ + "srcs": `["foo.proto"]`, + }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{ + "deps": `[":foo_proto"]`, + }), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{ + "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`, + "deps": `[":libprotobuf-cpp-lite"]`, + }), makeBazelTarget("cc_library_shared", "foo", attrNameToString{ + "dynamic_deps": `[":libprotobuf-cpp-lite"]`, + }), + }, + }) +} + +func TestCcLibraryProtoExplicitCanonicalPathFromRoot(t *testing.T) { + runCcLibraryTestCase(t, bp2buildTestCase{ + moduleTypeUnderTest: "cc_library", + moduleTypeUnderTestFactory: cc.LibraryFactory, + moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build, + blueprint: soongCcProtoPreamble + `cc_library { + name: "foo", + srcs: ["foo.proto"], + proto: { canonical_path_from_root: true}, + include_build_directory: false, +}`, + expectedBazelTargets: []string{ + makeBazelTarget("proto_library", "foo_proto", attrNameToString{ + "srcs": `["foo.proto"]`, + "strip_import_prefix": `""`, + }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{ + "deps": `[":foo_proto"]`, + }), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{ + "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`, + "deps": `[":libprotobuf-cpp-lite"]`, + }), makeBazelTarget("cc_library_shared", "foo", attrNameToString{ + "dynamic_deps": `[":libprotobuf-cpp-lite"]`, + }), + }, + }) +} + +func TestCcLibraryProtoFull(t *testing.T) { + runCcLibraryTestCase(t, bp2buildTestCase{ + moduleTypeUnderTest: "cc_library", + moduleTypeUnderTestFactory: cc.LibraryFactory, + moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build, + blueprint: soongCcProtoPreamble + `cc_library { + name: "foo", + srcs: ["foo.proto"], + proto: { + canonical_path_from_root: false, + type: "full", + }, + include_build_directory: false, +}`, + expectedBazelTargets: []string{ + makeBazelTarget("proto_library", "foo_proto", attrNameToString{ + "srcs": `["foo.proto"]`, + }), makeBazelTarget("cc_proto_library", "foo_cc_proto", attrNameToString{ + "deps": `[":foo_proto"]`, + }), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{ + "implementation_whole_archive_deps": `[":foo_cc_proto"]`, + "deps": `[":libprotobuf-cpp-full"]`, + }), makeBazelTarget("cc_library_shared", "foo", attrNameToString{ + "dynamic_deps": `[":libprotobuf-cpp-full"]`, + }), + }, + }) +} + +func TestCcLibraryProtoLite(t *testing.T) { + runCcLibraryTestCase(t, bp2buildTestCase{ + moduleTypeUnderTest: "cc_library", + moduleTypeUnderTestFactory: cc.LibraryFactory, + moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build, + blueprint: soongCcProtoPreamble + `cc_library { + name: "foo", + srcs: ["foo.proto"], + proto: { + canonical_path_from_root: false, + type: "lite", + }, + include_build_directory: false, +}`, + expectedBazelTargets: []string{ + makeBazelTarget("proto_library", "foo_proto", attrNameToString{ + "srcs": `["foo.proto"]`, + }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{ + "deps": `[":foo_proto"]`, + }), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{ + "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`, + "deps": `[":libprotobuf-cpp-lite"]`, + }), makeBazelTarget("cc_library_shared", "foo", attrNameToString{ + "dynamic_deps": `[":libprotobuf-cpp-lite"]`, + }), + }, + }) +} + +func TestCcLibraryProtoExportHeaders(t *testing.T) { + runCcLibraryTestCase(t, bp2buildTestCase{ + moduleTypeUnderTest: "cc_library", + moduleTypeUnderTestFactory: cc.LibraryFactory, + moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build, + blueprint: soongCcProtoPreamble + `cc_library { + name: "foo", + srcs: ["foo.proto"], + proto: { + canonical_path_from_root: false, + export_proto_headers: true, + }, + include_build_directory: false, +}`, + expectedBazelTargets: []string{ + makeBazelTarget("proto_library", "foo_proto", attrNameToString{ + "srcs": `["foo.proto"]`, + }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{ + "deps": `[":foo_proto"]`, + }), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{ + "deps": `[":libprotobuf-cpp-lite"]`, + "whole_archive_deps": `[":foo_cc_proto_lite"]`, + }), makeBazelTarget("cc_library_shared", "foo", attrNameToString{ + "dynamic_deps": `[":libprotobuf-cpp-lite"]`, + "whole_archive_deps": `[":foo_cc_proto_lite"]`, + }), + }, + }) +} diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go index 4ec95c3a3..e0331bee5 100644 --- a/bp2build/cc_library_shared_conversion_test.go +++ b/bp2build/cc_library_shared_conversion_test.go @@ -33,6 +33,7 @@ func registerCcLibrarySharedModuleTypes(ctx android.RegistrationContext) { ctx.RegisterModuleType("toolchain_library", cc.ToolchainLibraryFactory) ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory) ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory) + ctx.RegisterModuleType("cc_library", cc.LibraryFactory) } func runCcLibrarySharedTestCase(t *testing.T, tc bp2buildTestCase) { @@ -425,3 +426,27 @@ cc_library_shared { expectedErr: fmt.Errorf("Android.bp:16:1: module \"foo_shared\": nocrt is not supported for arch variants"), }) } + +func TestCcLibrarySharedProto(t *testing.T) { + runCcLibrarySharedTestCase(t, bp2buildTestCase{ + blueprint: soongCcProtoPreamble + `cc_library_shared { + name: "foo", + srcs: ["foo.proto"], + proto: { + canonical_path_from_root: false, + export_proto_headers: true, + }, + include_build_directory: false, +}`, + expectedBazelTargets: []string{ + makeBazelTarget("proto_library", "foo_proto", attrNameToString{ + "srcs": `["foo.proto"]`, + }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{ + "deps": `[":foo_proto"]`, + }), makeBazelTarget("cc_library_shared", "foo", attrNameToString{ + "dynamic_deps": `[":libprotobuf-cpp-lite"]`, + "whole_archive_deps": `[":foo_cc_proto_lite"]`, + }), + }, + }) +} diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go index 2f760d236..02229e51e 100644 --- a/bp2build/cc_library_static_conversion_test.go +++ b/bp2build/cc_library_static_conversion_test.go @@ -1419,3 +1419,27 @@ cc_library_static { }, }) } + +func TestCcLibraryStaticProto(t *testing.T) { + runCcLibraryStaticTestCase(t, bp2buildTestCase{ + blueprint: soongCcProtoPreamble + `cc_library_static { + name: "foo", + srcs: ["foo.proto"], + proto: { + canonical_path_from_root: false, + export_proto_headers: true, + }, + include_build_directory: false, +}`, + expectedBazelTargets: []string{ + makeBazelTarget("proto_library", "foo_proto", attrNameToString{ + "srcs": `["foo.proto"]`, + }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{ + "deps": `[":foo_proto"]`, + }), makeBazelTarget("cc_library_static", "foo", attrNameToString{ + "deps": `[":libprotobuf-cpp-lite"]`, + "whole_archive_deps": `[":foo_cc_proto_lite"]`, + }), + }, + }) +} diff --git a/cc/binary.go b/cc/binary.go index a5afb0725..3f951eca5 100644 --- a/cc/binary.go +++ b/cc/binary.go @@ -18,6 +18,7 @@ import ( "path/filepath" "github.com/google/blueprint" + "github.com/google/blueprint/proptools" "android/soong/android" "android/soong/bazel" @@ -388,7 +389,7 @@ func (binary *binaryDecorator) link(ctx ModuleContext, } } - var validations android.WritablePaths + var validations android.Paths // Handle host bionic linker symbols. if ctx.Os() == android.LinuxBionic && !binary.static() { @@ -411,6 +412,7 @@ func (binary *binaryDecorator) link(ctx ModuleContext, linkerDeps = append(linkerDeps, deps.EarlySharedLibsDeps...) linkerDeps = append(linkerDeps, deps.SharedLibsDeps...) linkerDeps = append(linkerDeps, deps.LateSharedLibsDeps...) + linkerDeps = append(linkerDeps, ndkSharedLibDeps(ctx)...) } validations = append(validations, objs.tidyFiles...) @@ -578,9 +580,16 @@ func binaryBp2build(ctx android.TopDownMutatorContext, typ string) { } baseAttrs := bp2BuildParseBaseProps(ctx, m) + binaryLinkerAttrs := bp2buildBinaryLinkerProps(ctx, m) + + if proptools.BoolDefault(binaryLinkerAttrs.Linkshared, true) { + baseAttrs.implementationDynamicDeps.Add(baseAttrs.protoDependency) + } else { + baseAttrs.implementationDeps.Add(baseAttrs.protoDependency) + } attrs := &binaryAttributes{ - binaryLinkerAttrs: bp2buildBinaryLinkerProps(ctx, m), + binaryLinkerAttrs: binaryLinkerAttrs, Srcs: baseAttrs.srcs, Srcs_c: baseAttrs.cSrcs, diff --git a/cc/bp2build.go b/cc/bp2build.go index 888c3bacb..f9bbe8752 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -27,9 +27,10 @@ import ( ) const ( - cSrcPartition = "c" - asSrcPartition = "as" - cppSrcPartition = "cpp" + cSrcPartition = "c" + asSrcPartition = "as" + cppSrcPartition = "cpp" + protoSrcPartition = "proto" ) // staticOrSharedAttributes are the Bazel-ified versions of StaticOrSharedProperties -- @@ -41,52 +42,53 @@ type staticOrSharedAttributes struct { Hdrs bazel.LabelListAttribute Copts bazel.StringListAttribute - Deps bazel.LabelListAttribute - Implementation_deps bazel.LabelListAttribute - Dynamic_deps bazel.LabelListAttribute - Implementation_dynamic_deps bazel.LabelListAttribute - Whole_archive_deps bazel.LabelListAttribute + Deps bazel.LabelListAttribute + Implementation_deps bazel.LabelListAttribute + Dynamic_deps bazel.LabelListAttribute + Implementation_dynamic_deps bazel.LabelListAttribute + Whole_archive_deps bazel.LabelListAttribute + Implementation_whole_archive_deps bazel.LabelListAttribute System_dynamic_deps bazel.LabelListAttribute } func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.LabelListAttribute) bazel.PartitionToLabelListAttribute { - // Check that a module is a filegroup type named <label>. - isFilegroupNamed := func(m android.Module, fullLabel string) bool { - if ctx.OtherModuleType(m) != "filegroup" { - return false - } - labelParts := strings.Split(fullLabel, ":") - if len(labelParts) > 2 { - // There should not be more than one colon in a label. - ctx.ModuleErrorf("%s is not a valid Bazel label for a filegroup", fullLabel) - } - return m.Name() == labelParts[len(labelParts)-1] + // Check that a module is a filegroup type + isFilegroup := func(m blueprint.Module) bool { + return ctx.OtherModuleType(m) == "filegroup" } // Convert filegroup dependencies into extension-specific filegroups filtered in the filegroup.bzl // macro. addSuffixForFilegroup := func(suffix string) bazel.LabelMapper { - return func(ctx bazel.OtherModuleContext, label string) (string, bool) { - m, exists := ctx.ModuleFromName(label) - if !exists { - return label, false + return func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) { + m, exists := ctx.ModuleFromName(label.OriginalModuleName) + labelStr := label.Label + if !exists || !isFilegroup(m) { + return labelStr, false } - aModule, _ := m.(android.Module) - if !isFilegroupNamed(aModule, label) { - return label, false - } - return label + suffix, true + return labelStr + suffix, true } } + isProtoFilegroup := func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) { + m, exists := ctx.ModuleFromName(label.OriginalModuleName) + labelStr := label.Label + if !exists || !isFilegroup(m) { + return labelStr, false + } + likelyProtos := strings.HasSuffix(labelStr, "proto") || strings.HasSuffix(labelStr, "protos") + return labelStr, likelyProtos + } + // TODO(b/190006308): Handle language detection of sources in a Bazel rule. partitioned := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{ cSrcPartition: bazel.LabelPartition{Extensions: []string{".c"}, LabelMapper: addSuffixForFilegroup("_c_srcs")}, asSrcPartition: bazel.LabelPartition{Extensions: []string{".s", ".S"}, LabelMapper: addSuffixForFilegroup("_as_srcs")}, // C++ is the "catch-all" group, and comprises generated sources because we don't // know the language of these sources until the genrule is executed. - cppSrcPartition: bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true}, + cppSrcPartition: bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true}, + protoSrcPartition: bazel.LabelPartition{Extensions: []string{".proto"}, LabelMapper: isProtoFilegroup}, }) return partitioned @@ -195,6 +197,11 @@ func bp2buildParseStaticOrSharedProps(ctx android.BazelConversionPathContext, mo attrs.Srcs_c = partitionedSrcs[cSrcPartition] attrs.Srcs_as = partitionedSrcs[asSrcPartition] + if !partitionedSrcs[protoSrcPartition].IsEmpty() { + // TODO(b/208815215): determine whether this is used and add support if necessary + ctx.ModuleErrorf("Migrating static/shared only proto srcs is not currently supported") + } + return attrs } @@ -230,6 +237,8 @@ func Bp2BuildParsePrebuiltLibraryProps(ctx android.BazelConversionPathContext, m type baseAttributes struct { compilerAttributes linkerAttributes + + protoDependency *bazel.LabelAttribute } // Convenience struct to hold all attributes parsed from compiler properties. @@ -257,6 +266,8 @@ type compilerAttributes struct { localIncludes bazel.StringListAttribute absoluteIncludes bazel.StringListAttribute + + protoSrcs bazel.LabelListAttribute } func parseCommandLineFlags(soongFlags []string) []string { @@ -337,6 +348,8 @@ func (ca *compilerAttributes) finalize(ctx android.BazelConversionPathContext, i ca.srcs.ResolveExcludes() partitionedSrcs := groupSrcsByExtension(ctx, ca.srcs) + ca.protoSrcs = partitionedSrcs[protoSrcPartition] + for p, lla := range partitionedSrcs { // if there are no sources, there is no need for headers if lla.IsEmpty() { @@ -400,7 +413,7 @@ func bp2buildResolveCppStdValue(c_std *string, cpp_std *string, gnu_extensions * } // bp2BuildParseCompilerProps returns copts, srcs and hdrs and other attributes. -func bp2BuildParseBaseProps(ctx android.BazelConversionPathContext, module *Module) baseAttributes { +func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) baseAttributes { archVariantCompilerProps := module.GetArchVariantProperties(ctx, &BaseCompilerProperties{}) archVariantLinkerProps := module.GetArchVariantProperties(ctx, &BaseLinkerProperties{}) @@ -456,20 +469,30 @@ func bp2BuildParseBaseProps(ctx android.BazelConversionPathContext, module *Modu (&compilerAttrs).finalize(ctx, implementationHdrs) (&linkerAttrs).finalize() + protoDep := bp2buildProto(ctx, module, compilerAttrs.protoSrcs) + + // bp2buildProto will only set wholeStaticLib or implementationWholeStaticLib, but we don't know + // which. This will add the newly generated proto library to the appropriate attribute and nothing + // to the other + (&linkerAttrs).wholeArchiveDeps.Add(protoDep.wholeStaticLib) + (&linkerAttrs).implementationWholeArchiveDeps.Add(protoDep.implementationWholeStaticLib) + return baseAttributes{ compilerAttrs, linkerAttrs, + protoDep.protoDep, } } // Convenience struct to hold all attributes parsed from linker properties. type linkerAttributes struct { - deps bazel.LabelListAttribute - implementationDeps bazel.LabelListAttribute - dynamicDeps bazel.LabelListAttribute - implementationDynamicDeps bazel.LabelListAttribute - wholeArchiveDeps bazel.LabelListAttribute - systemDynamicDeps bazel.LabelListAttribute + deps bazel.LabelListAttribute + implementationDeps bazel.LabelListAttribute + dynamicDeps bazel.LabelListAttribute + implementationDynamicDeps bazel.LabelListAttribute + wholeArchiveDeps bazel.LabelListAttribute + implementationWholeArchiveDeps bazel.LabelListAttribute + systemDynamicDeps bazel.LabelListAttribute linkCrt bazel.BoolAttribute useLibcrt bazel.BoolAttribute diff --git a/cc/builder.go b/cc/builder.go index fea65d581..7161ccf83 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -413,7 +413,7 @@ type StripFlags struct { // Objects is a collection of file paths corresponding to outputs for C++ related build statements. type Objects struct { objFiles android.Paths - tidyFiles android.WritablePaths + tidyFiles android.Paths coverageFiles android.Paths sAbiDumpFiles android.Paths kytheFiles android.Paths @@ -422,7 +422,7 @@ type Objects struct { func (a Objects) Copy() Objects { return Objects{ objFiles: append(android.Paths{}, a.objFiles...), - tidyFiles: append(android.WritablePaths{}, a.tidyFiles...), + tidyFiles: append(android.Paths{}, a.tidyFiles...), coverageFiles: append(android.Paths{}, a.coverageFiles...), sAbiDumpFiles: append(android.Paths{}, a.sAbiDumpFiles...), kytheFiles: append(android.Paths{}, a.kytheFiles...), @@ -451,11 +451,11 @@ func transformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles, no // Source files are one-to-one with tidy, coverage, or kythe files, if enabled. objFiles := make(android.Paths, len(srcFiles)) - var tidyFiles android.WritablePaths + var tidyFiles android.Paths noTidySrcsMap := make(map[android.Path]bool) var tidyVars string if flags.tidy { - tidyFiles = make(android.WritablePaths, 0, len(srcFiles)) + tidyFiles = make(android.Paths, 0, len(srcFiles)) for _, path := range noTidySrcs { noTidySrcsMap[path] = true } @@ -549,10 +549,6 @@ func transformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles, no return "$" + kind + n } - // clang-tidy checks source files and does not need to link with libraries. - // tidyPathDeps should contain pathDeps but not libraries. - tidyPathDeps := skipNdkLibraryDeps(ctx, pathDeps) - for i, srcFile := range srcFiles { objFile := android.ObjPathWithExt(ctx, subdir, srcFile, "o") @@ -669,14 +665,13 @@ func transformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles, no rule = clangTidyRE } - ctx.TidyFile(tidyFile) ctx.Build(pctx, android.BuildParams{ Rule: rule, Description: "clang-tidy " + srcFile.Rel(), Output: tidyFile, Input: srcFile, Implicits: cFlagsDeps, - OrderOnly: tidyPathDeps, + OrderOnly: pathDeps, Args: map[string]string{ "ccCmd": ccCmd, "cFlags": shareFlags("cFlags", escapeSingleQuotes(moduleToolingFlags)), @@ -723,7 +718,7 @@ func transformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles, no // Generate a rule for compiling multiple .o files to a static library (.a) func transformObjToStaticLib(ctx android.ModuleContext, objFiles android.Paths, wholeStaticLibs android.Paths, - flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths, validations android.WritablePaths) { + flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths, validations android.Paths) { arCmd := "${config.ClangBin}/llvm-ar" arFlags := "" @@ -738,7 +733,7 @@ func transformObjToStaticLib(ctx android.ModuleContext, Output: outputFile, Inputs: objFiles, Implicits: deps, - Validations: validations.Paths(), + Validations: validations, Args: map[string]string{ "arFlags": "crsPD" + arFlags, "arCmd": arCmd, @@ -768,7 +763,7 @@ func transformObjToStaticLib(ctx android.ModuleContext, func transformObjToDynamicBinary(ctx android.ModuleContext, objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps, crtBegin, crtEnd android.Paths, groupLate bool, flags builderFlags, outputFile android.WritablePath, - implicitOutputs android.WritablePaths, validations android.WritablePaths) { + implicitOutputs android.WritablePaths, validations android.Paths) { ldCmd := "${config.ClangBin}/clang++" @@ -835,7 +830,7 @@ func transformObjToDynamicBinary(ctx android.ModuleContext, Inputs: objFiles, Implicits: deps, OrderOnly: sharedLibs, - Validations: validations.Paths(), + Validations: validations, Args: args, }) } @@ -815,6 +815,10 @@ type Module struct { makeLinkType string // Kythe (source file indexer) paths for this compilation module kytheFiles android.Paths + // Object .o file output paths for this compilation module + objFiles android.Paths + // Tidy .tidy file output paths for this compilation module + tidyFiles android.Paths // For apex variants, this is set as apex.min_sdk_version apexSdkVersion android.ApiLevel @@ -1713,7 +1717,15 @@ func (c *Module) setSubnameProperty(actx android.ModuleContext) { // Returns true if Bazel was successfully used for the analysis of this module. func (c *Module) maybeGenerateBazelActions(actx android.ModuleContext) bool { - bazelModuleLabel := c.GetBazelLabel(actx, c) + var bazelModuleLabel string + if actx.ModuleType() == "cc_library" && c.static() { + // cc_library is a special case in bp2build; two targets are generated -- one for each + // of the shared and static variants. The shared variant keeps the module name, but the + // static variant uses a different suffixed name. + bazelModuleLabel = bazelLabelForStaticModule(actx, c) + } else { + bazelModuleLabel = c.GetBazelLabel(actx, c) + } bazelActionsUsed := false // Mixed builds mode is disabled for modules outside of device OS. // TODO(b/200841190): Support non-device OS in mixed builds. @@ -1827,6 +1839,8 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { return } c.kytheFiles = objs.kytheFiles + c.objFiles = objs.objFiles + c.tidyFiles = objs.tidyFiles } if c.linker != nil { diff --git a/cc/compiler.go b/cc/compiler.go index 2e62b0002..8adc3ab16 100644 --- a/cc/compiler.go +++ b/cc/compiler.go @@ -637,9 +637,9 @@ var gnuToCReplacer = strings.NewReplacer("gnu", "c") func ndkPathDeps(ctx ModuleContext) android.Paths { if ctx.Module().(*Module).IsSdkVariant() { - // The NDK sysroot timestamp file depends on all the NDK sysroot files - // (headers and libraries). - return android.Paths{getNdkBaseTimestampFile(ctx)} + // The NDK sysroot timestamp file depends on all the NDK sysroot header files + // for compiling src to obj files. + return android.Paths{getNdkHeadersTimestampFile(ctx)} } return nil } diff --git a/cc/config/global.go b/cc/config/global.go index 0b229be76..a340e465e 100644 --- a/cc/config/global.go +++ b/cc/config/global.go @@ -46,7 +46,6 @@ var ( "-O2", "-g", - "-fdebug-info-for-profiling", "-fno-strict-aliasing", @@ -125,6 +124,9 @@ var ( "-Werror=sequence-point", "-Werror=format-security", "-nostdlibinc", + + // Emit additional debug info for AutoFDO + "-fdebug-info-for-profiling", } deviceGlobalCppflags = []string{ diff --git a/cc/libbuildversion/Android.bp b/cc/libbuildversion/Android.bp index 2cff99435..b105a3029 100644 --- a/cc/libbuildversion/Android.bp +++ b/cc/libbuildversion/Android.bp @@ -19,4 +19,5 @@ cc_library_static { "//apex_available:platform", "//apex_available:anyapex", ], + vendor_available: true, } diff --git a/cc/libbuildversion/libbuildversion.cpp b/cc/libbuildversion/libbuildversion.cpp index 5242025eb..1e01c1145 100644 --- a/cc/libbuildversion/libbuildversion.cpp +++ b/cc/libbuildversion/libbuildversion.cpp @@ -36,7 +36,11 @@ std::string GetBuildNumber() { return soong_build_number; } +#ifdef __ANDROID_VENDOR__ + const prop_info* pi = __system_property_find("ro.vendor.build.version.incremental"); +#else const prop_info* pi = __system_property_find("ro.build.version.incremental"); +#endif if (pi == nullptr) return ""; std::string property_value; diff --git a/cc/library.go b/cc/library.go index 3dceda0a3..e53aac0c6 100644 --- a/cc/library.go +++ b/cc/library.go @@ -236,12 +236,13 @@ type bazelCcLibraryAttributes struct { Hdrs bazel.LabelListAttribute - Deps bazel.LabelListAttribute - Implementation_deps bazel.LabelListAttribute - Dynamic_deps bazel.LabelListAttribute - Implementation_dynamic_deps bazel.LabelListAttribute - Whole_archive_deps bazel.LabelListAttribute - System_dynamic_deps bazel.LabelListAttribute + Deps bazel.LabelListAttribute + Implementation_deps bazel.LabelListAttribute + Dynamic_deps bazel.LabelListAttribute + Implementation_dynamic_deps bazel.LabelListAttribute + Whole_archive_deps bazel.LabelListAttribute + Implementation_whole_archive_deps bazel.LabelListAttribute + System_dynamic_deps bazel.LabelListAttribute Export_includes bazel.StringListAttribute Export_system_includes bazel.StringListAttribute @@ -303,40 +304,83 @@ func CcLibraryBp2Build(ctx android.TopDownMutatorContext) { srcs := compilerAttrs.srcs + sharedAttrs.Dynamic_deps.Add(baseAttributes.protoDependency) + staticAttrs.Deps.Add(baseAttributes.protoDependency) + asFlags := compilerAttrs.asFlags if compilerAttrs.asSrcs.IsEmpty() && sharedAttrs.Srcs_as.IsEmpty() && staticAttrs.Srcs_as.IsEmpty() { // Skip asflags for BUILD file simplicity if there are no assembly sources. asFlags = bazel.MakeStringListAttribute(nil) } - attrs := &bazelCcLibraryAttributes{ - Srcs: srcs, - Srcs_c: compilerAttrs.cSrcs, - Srcs_as: compilerAttrs.asSrcs, - Hdrs: compilerAttrs.hdrs, + staticCommonAttrs := staticOrSharedAttributes{ + Srcs: *srcs.Clone().Append(staticAttrs.Srcs), + Srcs_c: *compilerAttrs.cSrcs.Clone().Append(staticAttrs.Srcs_c), + Srcs_as: *compilerAttrs.asSrcs.Clone().Append(staticAttrs.Srcs_as), + Copts: *compilerAttrs.copts.Clone().Append(staticAttrs.Copts), + Hdrs: *compilerAttrs.hdrs.Clone().Append(staticAttrs.Hdrs), + + Deps: *linkerAttrs.deps.Clone().Append(staticAttrs.Deps), + Implementation_deps: *linkerAttrs.implementationDeps.Clone().Append(staticAttrs.Implementation_deps), + Dynamic_deps: *linkerAttrs.dynamicDeps.Clone().Append(staticAttrs.Dynamic_deps), + Implementation_dynamic_deps: *linkerAttrs.implementationDynamicDeps.Clone().Append(staticAttrs.Implementation_dynamic_deps), + Implementation_whole_archive_deps: linkerAttrs.implementationWholeArchiveDeps, + Whole_archive_deps: *linkerAttrs.wholeArchiveDeps.Clone().Append(staticAttrs.Whole_archive_deps), + System_dynamic_deps: *linkerAttrs.systemDynamicDeps.Clone().Append(staticAttrs.System_dynamic_deps), + } + + sharedCommonAttrs := staticOrSharedAttributes{ + Srcs: *srcs.Clone().Append(sharedAttrs.Srcs), + Srcs_c: *compilerAttrs.cSrcs.Clone().Append(sharedAttrs.Srcs_c), + Srcs_as: *compilerAttrs.asSrcs.Clone().Append(sharedAttrs.Srcs_as), + Copts: *compilerAttrs.copts.Clone().Append(sharedAttrs.Copts), + Hdrs: *compilerAttrs.hdrs.Clone().Append(sharedAttrs.Hdrs), + + Deps: *linkerAttrs.deps.Clone().Append(sharedAttrs.Deps), + Implementation_deps: *linkerAttrs.implementationDeps.Clone().Append(sharedAttrs.Implementation_deps), + Dynamic_deps: *linkerAttrs.dynamicDeps.Clone().Append(sharedAttrs.Dynamic_deps), + Implementation_dynamic_deps: *linkerAttrs.implementationDynamicDeps.Clone().Append(sharedAttrs.Implementation_dynamic_deps), + Whole_archive_deps: *linkerAttrs.wholeArchiveDeps.Clone().Append(sharedAttrs.Whole_archive_deps), + System_dynamic_deps: *linkerAttrs.systemDynamicDeps.Clone().Append(sharedAttrs.System_dynamic_deps), + } + + staticTargetAttrs := &bazelCcLibraryStaticAttributes{ + staticOrSharedAttributes: staticCommonAttrs, - Copts: compilerAttrs.copts, Cppflags: compilerAttrs.cppFlags, Conlyflags: compilerAttrs.conlyFlags, Asflags: asFlags, - Implementation_deps: linkerAttrs.implementationDeps, - Deps: linkerAttrs.deps, - Implementation_dynamic_deps: linkerAttrs.implementationDynamicDeps, - Dynamic_deps: linkerAttrs.dynamicDeps, - Whole_archive_deps: linkerAttrs.wholeArchiveDeps, - System_dynamic_deps: linkerAttrs.systemDynamicDeps, - Export_includes: exportedIncludes.Includes, - Export_system_includes: exportedIncludes.SystemIncludes, - Local_includes: compilerAttrs.localIncludes, - Absolute_includes: compilerAttrs.absoluteIncludes, - Linkopts: linkerAttrs.linkopts, - Link_crt: linkerAttrs.linkCrt, - Use_libcrt: linkerAttrs.useLibcrt, - Rtti: compilerAttrs.rtti, - Stl: compilerAttrs.stl, - Cpp_std: compilerAttrs.cppStd, - C_std: compilerAttrs.cStd, + Export_includes: exportedIncludes.Includes, + Export_system_includes: exportedIncludes.SystemIncludes, + Local_includes: compilerAttrs.localIncludes, + Absolute_includes: compilerAttrs.absoluteIncludes, + Use_libcrt: linkerAttrs.useLibcrt, + Rtti: compilerAttrs.rtti, + Stl: compilerAttrs.stl, + Cpp_std: compilerAttrs.cppStd, + C_std: compilerAttrs.cStd, + + Features: linkerAttrs.features, + } + + sharedTargetAttrs := &bazelCcLibrarySharedAttributes{ + staticOrSharedAttributes: sharedCommonAttrs, + Cppflags: compilerAttrs.cppFlags, + Conlyflags: compilerAttrs.conlyFlags, + Asflags: asFlags, + + Export_includes: exportedIncludes.Includes, + Export_system_includes: exportedIncludes.SystemIncludes, + Local_includes: compilerAttrs.localIncludes, + Absolute_includes: compilerAttrs.absoluteIncludes, + Linkopts: linkerAttrs.linkopts, + Link_crt: linkerAttrs.linkCrt, + Use_libcrt: linkerAttrs.useLibcrt, + Rtti: compilerAttrs.rtti, + Stl: compilerAttrs.stl, + Cpp_std: compilerAttrs.cppStd, + C_std: compilerAttrs.cStd, Additional_linker_inputs: linkerAttrs.additionalLinkerInputs, @@ -347,20 +391,20 @@ func CcLibraryBp2Build(ctx android.TopDownMutatorContext) { All: linkerAttrs.stripAll, None: linkerAttrs.stripNone, }, - - Shared: sharedAttrs, - - Static: staticAttrs, - Features: linkerAttrs.features, } - props := bazel.BazelTargetModuleProperties{ - Rule_class: "cc_library", - Bzl_load_location: "//build/bazel/rules:full_cc_library.bzl", + staticProps := bazel.BazelTargetModuleProperties{ + Rule_class: "cc_library_static", + Bzl_load_location: "//build/bazel/rules:cc_library_static.bzl", + } + sharedProps := bazel.BazelTargetModuleProperties{ + Rule_class: "cc_library_shared", + Bzl_load_location: "//build/bazel/rules:cc_library_shared.bzl", } - ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs) + ctx.CreateBazelTargetModule(staticProps, android.CommonAttributes{Name: m.Name() + "_bp2build_cc_library_static"}, staticTargetAttrs) + ctx.CreateBazelTargetModule(sharedProps, android.CommonAttributes{Name: m.Name()}, sharedTargetAttrs) } // cc_library creates both static and/or shared libraries for a device and/or @@ -1322,11 +1366,21 @@ func (library *libraryDecorator) linkStatic(ctx ModuleContext, return outputFile } +func ndkSharedLibDeps(ctx ModuleContext) android.Paths { + if ctx.Module().(*Module).IsSdkVariant() { + // The NDK sysroot timestamp file depends on all the NDK + // sysroot header and shared library files. + return android.Paths{getNdkBaseTimestampFile(ctx)} + } + return nil +} + func (library *libraryDecorator) linkShared(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path { var linkerDeps android.Paths linkerDeps = append(linkerDeps, flags.LdFlagsDeps...) + linkerDeps = append(linkerDeps, ndkSharedLibDeps(ctx)...) unexportedSymbols := ctx.ExpandOptionalSource(library.Properties.Unexported_symbols_list, "unexported_symbols_list") forceNotWeakSymbols := ctx.ExpandOptionalSource(library.Properties.Force_symbols_not_weak_list, "force_symbols_not_weak_list") @@ -2405,16 +2459,18 @@ func ccSharedOrStaticBp2BuildMutatorInternal(ctx android.TopDownMutatorContext, Copts: compilerAttrs.copts, Hdrs: compilerAttrs.hdrs, - Deps: linkerAttrs.deps, - Implementation_deps: linkerAttrs.implementationDeps, - Dynamic_deps: linkerAttrs.dynamicDeps, - Implementation_dynamic_deps: linkerAttrs.implementationDynamicDeps, - Whole_archive_deps: linkerAttrs.wholeArchiveDeps, - System_dynamic_deps: linkerAttrs.systemDynamicDeps, + Deps: linkerAttrs.deps, + Implementation_deps: linkerAttrs.implementationDeps, + Dynamic_deps: linkerAttrs.dynamicDeps, + Implementation_dynamic_deps: linkerAttrs.implementationDynamicDeps, + Whole_archive_deps: linkerAttrs.wholeArchiveDeps, + Implementation_whole_archive_deps: linkerAttrs.implementationWholeArchiveDeps, + System_dynamic_deps: linkerAttrs.systemDynamicDeps, } var attrs interface{} if isStatic { + commonAttrs.Deps.Add(baseAttributes.protoDependency) attrs = &bazelCcLibraryStaticAttributes{ staticOrSharedAttributes: commonAttrs, @@ -2435,6 +2491,8 @@ func ccSharedOrStaticBp2BuildMutatorInternal(ctx android.TopDownMutatorContext, Features: linkerAttrs.features, } } else { + commonAttrs.Dynamic_deps.Add(baseAttributes.protoDependency) + attrs = &bazelCcLibrarySharedAttributes{ staticOrSharedAttributes: commonAttrs, diff --git a/cc/library_test.go b/cc/library_test.go index 7ddfaa7fd..d220e19f8 100644 --- a/cc/library_test.go +++ b/cc/library_test.go @@ -257,9 +257,16 @@ cc_library { CcObjectFiles: []string{"foo.o"}, Includes: []string{"include"}, SystemIncludes: []string{"system_include"}, - RootStaticArchives: []string{"foo.a"}, + Headers: []string{"foo.h"}, RootDynamicLibraries: []string{"foo.so"}, }, + "//foo/bar:bar_bp2build_cc_library_static": cquery.CcInfo{ + CcObjectFiles: []string{"foo.o"}, + Includes: []string{"include"}, + SystemIncludes: []string{"system_include"}, + Headers: []string{"foo.h"}, + RootStaticArchives: []string{"foo.a"}, + }, }, } ctx := testCcWithConfig(t, config) @@ -273,18 +280,25 @@ cc_library { expectedOutputFiles := []string{"outputbase/execroot/__main__/foo.a"} android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings()) + flagExporter := ctx.ModuleProvider(staticFoo, FlagExporterInfoProvider).(FlagExporterInfo) + android.AssertPathsRelativeToTopEquals(t, "exported include dirs", []string{"outputbase/execroot/__main__/include"}, flagExporter.IncludeDirs) + android.AssertPathsRelativeToTopEquals(t, "exported system include dirs", []string{"outputbase/execroot/__main__/system_include"}, flagExporter.SystemIncludeDirs) + android.AssertPathsRelativeToTopEquals(t, "exported headers", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.GeneratedHeaders) + android.AssertPathsRelativeToTopEquals(t, "deps", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.Deps) + sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module() outputFiles, err = sharedFoo.(android.OutputFileProducer).OutputFiles("") if err != nil { - t.Errorf("Unexpected error getting cc_object outputfiles %s", err) + t.Errorf("Unexpected error getting cc_library outputfiles %s", err) } expectedOutputFiles = []string{"outputbase/execroot/__main__/foo.so"} android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings()) - entries := android.AndroidMkEntriesForTest(t, ctx, sharedFoo)[0] - expectedFlags := []string{"-Ioutputbase/execroot/__main__/include", "-isystem outputbase/execroot/__main__/system_include"} - gotFlags := entries.EntryMap["LOCAL_EXPORT_CFLAGS"] - android.AssertDeepEquals(t, "androidmk exported cflags", expectedFlags, gotFlags) + flagExporter = ctx.ModuleProvider(sharedFoo, FlagExporterInfoProvider).(FlagExporterInfo) + android.AssertPathsRelativeToTopEquals(t, "exported include dirs", []string{"outputbase/execroot/__main__/include"}, flagExporter.IncludeDirs) + android.AssertPathsRelativeToTopEquals(t, "exported system include dirs", []string{"outputbase/execroot/__main__/system_include"}, flagExporter.SystemIncludeDirs) + android.AssertPathsRelativeToTopEquals(t, "exported headers", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.GeneratedHeaders) + android.AssertPathsRelativeToTopEquals(t, "deps", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.Deps) } func TestLibraryVersionScript(t *testing.T) { diff --git a/cc/linkable.go b/cc/linkable.go index 560c9debe..02d7047bf 100644 --- a/cc/linkable.go +++ b/cc/linkable.go @@ -384,9 +384,13 @@ func flagExporterInfoFromCcInfo(ctx android.ModuleContext, ccInfo cquery.CcInfo) includes := android.PathsForBazelOut(ctx, ccInfo.Includes) systemIncludes := android.PathsForBazelOut(ctx, ccInfo.SystemIncludes) + headers := android.PathsForBazelOut(ctx, ccInfo.Headers) return FlagExporterInfo{ IncludeDirs: android.FirstUniquePaths(includes), SystemIncludeDirs: android.FirstUniquePaths(systemIncludes), + GeneratedHeaders: headers, + // necessary to ensure generated headers are considered implicit deps of dependent actions + Deps: headers, } } diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go index ee11db101..6c200f5dd 100644 --- a/cc/ndk_sysroot.go +++ b/cc/ndk_sysroot.go @@ -94,21 +94,6 @@ func getNdkFullTimestampFile(ctx android.PathContext) android.WritablePath { return android.PathForOutput(ctx, "ndk.timestamp") } -// Replace ndk_base.timestamp and ndk.timestamp with ndk_headers.timestamp. -func skipNdkLibraryDeps(ctx android.ModuleContext, paths android.Paths) android.Paths { - var newPaths android.Paths - baseTimestamp := getNdkBaseTimestampFile(ctx) - fullTimestamp := getNdkFullTimestampFile(ctx) - headersTimestamp := getNdkHeadersTimestampFile(ctx) - for _, path := range paths { - if path == baseTimestamp || path == fullTimestamp { - path = headersTimestamp - } - newPaths = append(newPaths, path) - } - return newPaths -} - func NdkSingleton() android.Singleton { return &ndkSingleton{} } @@ -96,10 +96,6 @@ func (props *PgoProperties) addInstrumentationProfileGatherFlags(ctx ModuleConte flags.Local.LdFlags = append(flags.Local.LdFlags, profileInstrumentFlag) return flags } -func (props *PgoProperties) addSamplingProfileGatherFlags(ctx ModuleContext, flags Flags) Flags { - flags.Local.CFlags = append(flags.Local.CFlags, props.Pgo.Cflags...) - return flags -} func (props *PgoProperties) getPgoProfileFile(ctx BaseModuleContext) android.OptionalPath { profileFile := *props.Pgo.Profile_file @@ -313,10 +309,6 @@ func (pgo *pgo) flags(ctx ModuleContext, flags Flags) Flags { if (props.ShouldProfileModule && props.isInstrumentation()) || props.PgoInstrLink { // Instrumentation PGO use and gather flags cannot coexist. return props.addInstrumentationProfileGatherFlags(ctx, flags) - } else if props.ShouldProfileModule && props.isSampling() { - flags = props.addSamplingProfileGatherFlags(ctx, flags) - } else if ctx.DeviceConfig().SamplingPGO() { - flags = props.addSamplingProfileGatherFlags(ctx, flags) } if !ctx.Config().IsEnvTrue("ANDROID_PGO_NO_PROFILE_USE") { diff --git a/cc/proto.go b/cc/proto.go index 44661447c..f3410bc2b 100644 --- a/cc/proto.go +++ b/cc/proto.go @@ -16,8 +16,14 @@ package cc import ( "github.com/google/blueprint/pathtools" + "github.com/google/blueprint/proptools" "android/soong/android" + "android/soong/bazel" +) + +const ( + protoTypeDefault = "lite" ) // genProto creates a rule to convert a .proto file to generated .pb.cc and .pb.h files and returns @@ -63,7 +69,7 @@ func protoDeps(ctx DepsContext, deps Deps, p *android.ProtoProperties, static bo var lib string if String(p.Proto.Plugin) == "" { - switch String(p.Proto.Type) { + switch proptools.StringDefault(p.Proto.Type, protoTypeDefault) { case "full": if ctx.useSdk() { lib = "libprotobuf-cpp-full-ndk" @@ -71,7 +77,7 @@ func protoDeps(ctx DepsContext, deps Deps, p *android.ProtoProperties, static bo } else { lib = "libprotobuf-cpp-full" } - case "lite", "": + case "lite": if ctx.useSdk() { lib = "libprotobuf-cpp-lite-ndk" static = true @@ -157,3 +163,69 @@ func protoFlags(ctx ModuleContext, flags Flags, p *android.ProtoProperties) Flag return flags } + +type protoAttributes struct { + Deps bazel.LabelListAttribute +} + +type bp2buildProtoDeps struct { + wholeStaticLib *bazel.LabelAttribute + implementationWholeStaticLib *bazel.LabelAttribute + protoDep *bazel.LabelAttribute +} + +func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs bazel.LabelListAttribute) bp2buildProtoDeps { + var ret bp2buildProtoDeps + + protoInfo, ok := android.Bp2buildProtoProperties(ctx, m, protoSrcs) + if !ok { + return ret + } + + var depName string + typ := proptools.StringDefault(protoInfo.Type, protoTypeDefault) + var rule_class string + suffix := "_cc_proto" + switch typ { + case "lite": + suffix += "_lite" + rule_class = "cc_lite_proto_library" + depName = "libprotobuf-cpp-lite" + case "full": + rule_class = "cc_proto_library" + depName = "libprotobuf-cpp-full" + default: + ctx.PropertyErrorf("proto.type", "cannot handle conversion at this time: %q", typ) + } + + dep := android.BazelLabelForModuleDepSingle(ctx, depName) + ret.protoDep = &bazel.LabelAttribute{Value: &dep} + + protoLabel := bazel.Label{Label: ":" + protoInfo.Name} + var protoAttrs protoAttributes + protoAttrs.Deps.SetValue(bazel.LabelList{Includes: []bazel.Label{protoLabel}}) + + name := m.Name() + suffix + + ctx.CreateBazelTargetModule( + bazel.BazelTargetModuleProperties{ + Rule_class: rule_class, + Bzl_load_location: "//build/bazel/rules:cc_proto.bzl", + }, + android.CommonAttributes{Name: name}, + &protoAttrs) + + var privateHdrs bool + if lib, ok := m.linker.(*libraryDecorator); ok { + privateHdrs = !proptools.Bool(lib.Properties.Proto.Export_proto_headers) + } + + labelAttr := &bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + name}} + if privateHdrs { + ret.implementationWholeStaticLib = labelAttr + } else { + ret.wholeStaticLib = labelAttr + } + + return ret +} diff --git a/cc/sanitize.go b/cc/sanitize.go index 93d4b4c54..d7b1adee5 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -35,7 +35,6 @@ var ( asanCflags = []string{ "-fno-omit-frame-pointer", - "-fno-experimental-new-pass-manager", } asanLdflags = []string{"-Wl,-u,__asan_preinit"} @@ -666,9 +665,6 @@ func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags { flags.Local.LdFlags = append(flags.Local.LdFlags, "-fno-sanitize-coverage=stack-depth") flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-coverage=stack-depth") - // TODO(b/133876586): Experimental PM breaks sanitizer coverage. - flags.Local.CFlags = append(flags.Local.CFlags, "-fno-experimental-new-pass-manager") - // Disable fortify for fuzzing builds. Generally, we'll be building with // UBSan or ASan here and the fortify checks pollute the stack traces. flags.Local.CFlags = append(flags.Local.CFlags, "-U_FORTIFY_SOURCE") diff --git a/cc/tidy.go b/cc/tidy.go index 53ff1564b..78a791faf 100644 --- a/cc/tidy.go +++ b/cc/tidy.go @@ -15,6 +15,7 @@ package cc import ( + "path/filepath" "regexp" "strings" @@ -183,3 +184,154 @@ func (tidy *tidyFeature) flags(ctx ModuleContext, flags Flags) Flags { } return flags } + +func init() { + android.RegisterSingletonType("tidy_phony_targets", TidyPhonySingleton) +} + +// This TidyPhonySingleton generates both tidy-* and obj-* phony targets for C/C++ files. +func TidyPhonySingleton() android.Singleton { + return &tidyPhonySingleton{} +} + +type tidyPhonySingleton struct{} + +// Given a final module, add its tidy/obj phony targets to tidy/objModulesInDirGroup. +func collectTidyObjModuleTargets(ctx android.SingletonContext, module android.Module, + tidyModulesInDirGroup, objModulesInDirGroup map[string]map[string]android.Paths) { + allObjFileGroups := make(map[string]android.Paths) // variant group name => obj file Paths + allTidyFileGroups := make(map[string]android.Paths) // variant group name => tidy file Paths + subsetObjFileGroups := make(map[string]android.Paths) // subset group name => obj file Paths + subsetTidyFileGroups := make(map[string]android.Paths) // subset group name => tidy file Paths + + // (1) Collect all obj/tidy files into OS-specific groups. + ctx.VisitAllModuleVariants(module, func(variant android.Module) { + if ctx.Config().KatiEnabled() && android.ShouldSkipAndroidMkProcessing(variant) { + return + } + if m, ok := variant.(*Module); ok { + osName := variant.Target().Os.Name + addToOSGroup(osName, m.objFiles, allObjFileGroups, subsetObjFileGroups) + addToOSGroup(osName, m.tidyFiles, allTidyFileGroups, subsetTidyFileGroups) + } + }) + + // (2) Add an all-OS group, with "" or "subset" name, to include all os-specific phony targets. + addAllOSGroup(ctx, module, allObjFileGroups, "", "obj") + addAllOSGroup(ctx, module, allTidyFileGroups, "", "tidy") + addAllOSGroup(ctx, module, subsetObjFileGroups, "subset", "obj") + addAllOSGroup(ctx, module, subsetTidyFileGroups, "subset", "tidy") + + tidyTargetGroups := make(map[string]android.Path) + objTargetGroups := make(map[string]android.Path) + genObjTidyPhonyTargets(ctx, module, "obj", allObjFileGroups, objTargetGroups) + genObjTidyPhonyTargets(ctx, module, "obj", subsetObjFileGroups, objTargetGroups) + genObjTidyPhonyTargets(ctx, module, "tidy", allTidyFileGroups, tidyTargetGroups) + genObjTidyPhonyTargets(ctx, module, "tidy", subsetTidyFileGroups, tidyTargetGroups) + + moduleDir := ctx.ModuleDir(module) + appendToModulesInDirGroup(tidyTargetGroups, moduleDir, tidyModulesInDirGroup) + appendToModulesInDirGroup(objTargetGroups, moduleDir, objModulesInDirGroup) +} + +func (m *tidyPhonySingleton) GenerateBuildActions(ctx android.SingletonContext) { + // For tidy-* directory phony targets, there are different variant groups. + // tidyModulesInDirGroup[G][D] is for group G, directory D, with Paths + // of all phony targets to be included into direct dependents of tidy-D_G. + tidyModulesInDirGroup := make(map[string]map[string]android.Paths) + // Also for obj-* directory phony targets. + objModulesInDirGroup := make(map[string]map[string]android.Paths) + + // Collect tidy/obj targets from the 'final' modules. + ctx.VisitAllModules(func(module android.Module) { + if module == ctx.FinalModule(module) { + collectTidyObjModuleTargets(ctx, module, tidyModulesInDirGroup, objModulesInDirGroup) + } + }) + + suffix := "" + if ctx.Config().KatiEnabled() { + suffix = "-soong" + } + generateObjTidyPhonyTargets(ctx, suffix, "obj", objModulesInDirGroup) + generateObjTidyPhonyTargets(ctx, suffix, "tidy", tidyModulesInDirGroup) +} + +// The name for an obj/tidy module variant group phony target is Name_group-obj/tidy, +func objTidyModuleGroupName(module android.Module, group string, suffix string) string { + if group == "" { + return module.Name() + "-" + suffix + } + return module.Name() + "_" + group + "-" + suffix +} + +// Generate obj-* or tidy-* phony targets. +func generateObjTidyPhonyTargets(ctx android.SingletonContext, suffix string, prefix string, objTidyModulesInDirGroup map[string]map[string]android.Paths) { + // For each variant group, create a <prefix>-<directory>_group target that + // depends on all subdirectories and modules in the directory. + for group, modulesInDir := range objTidyModulesInDirGroup { + groupSuffix := "" + if group != "" { + groupSuffix = "_" + group + } + mmTarget := func(dir string) string { + return prefix + "-" + strings.Replace(filepath.Clean(dir), "/", "-", -1) + groupSuffix + } + dirs, topDirs := android.AddAncestors(ctx, modulesInDir, mmTarget) + // Create a <prefix>-soong_group target that depends on all <prefix>-dir_group of top level dirs. + var topDirPaths android.Paths + for _, dir := range topDirs { + topDirPaths = append(topDirPaths, android.PathForPhony(ctx, mmTarget(dir))) + } + ctx.Phony(prefix+suffix+groupSuffix, topDirPaths...) + // Create a <prefix>-dir_group target that depends on all targets in modulesInDir[dir] + for _, dir := range dirs { + if dir != "." && dir != "" { + ctx.Phony(mmTarget(dir), modulesInDir[dir]...) + } + } + } +} + +// Append (obj|tidy)TargetGroups[group] into (obj|tidy)ModulesInDirGroups[group][moduleDir]. +func appendToModulesInDirGroup(targetGroups map[string]android.Path, moduleDir string, modulesInDirGroup map[string]map[string]android.Paths) { + for group, phonyPath := range targetGroups { + if _, found := modulesInDirGroup[group]; !found { + modulesInDirGroup[group] = make(map[string]android.Paths) + } + modulesInDirGroup[group][moduleDir] = append(modulesInDirGroup[group][moduleDir], phonyPath) + } +} + +// Add given files to the OS group and subset group. +func addToOSGroup(osName string, files android.Paths, allGroups, subsetGroups map[string]android.Paths) { + if len(files) > 0 { + subsetName := osName + "_subset" + allGroups[osName] = append(allGroups[osName], files...) + // Now include only the first variant in the subsetGroups. + // If clang and clang-tidy get faster, we might include more variants. + if _, found := subsetGroups[subsetName]; !found { + subsetGroups[subsetName] = files + } + } +} + +// Add an all-OS group, with groupName, to include all os-specific phony targets. +func addAllOSGroup(ctx android.SingletonContext, module android.Module, phonyTargetGroups map[string]android.Paths, groupName string, objTidyName string) { + if len(phonyTargetGroups) > 0 { + var targets android.Paths + for group, _ := range phonyTargetGroups { + targets = append(targets, android.PathForPhony(ctx, objTidyModuleGroupName(module, group, objTidyName))) + } + phonyTargetGroups[groupName] = targets + } +} + +// Create one phony targets for each group and add them to the targetGroups. +func genObjTidyPhonyTargets(ctx android.SingletonContext, module android.Module, objTidyName string, fileGroups map[string]android.Paths, targetGroups map[string]android.Path) { + for group, files := range fileGroups { + groupName := objTidyModuleGroupName(module, group, objTidyName) + ctx.Phony(groupName, files...) + targetGroups[group] = android.PathForPhony(ctx, groupName) + } +} diff --git a/dexpreopt/testing.go b/dexpreopt/testing.go index 2fba01aa7..5131cd3f4 100644 --- a/dexpreopt/testing.go +++ b/dexpreopt/testing.go @@ -85,12 +85,12 @@ var PrepareForTestWithFakeDex2oatd = android.GroupFixturePreparers( // Prepares a test fixture by enabling dexpreopt, registering the fake_tool_binary module type and // using that to define the `dex2oatd` module. var PrepareForTestByEnablingDexpreopt = android.GroupFixturePreparers( - FixtureModifyGlobalConfig(func(*GlobalConfig) {}), + FixtureModifyGlobalConfig(func(android.PathContext, *GlobalConfig) {}), ) // FixtureModifyGlobalConfig enables dexpreopt (unless modified by the mutator) and modifies the // configuration. -func FixtureModifyGlobalConfig(configModifier func(dexpreoptConfig *GlobalConfig)) android.FixturePreparer { +func FixtureModifyGlobalConfig(configModifier func(ctx android.PathContext, dexpreoptConfig *GlobalConfig)) android.FixturePreparer { return android.FixtureModifyConfig(func(config android.Config) { // Initialize the dexpreopt GlobalConfig to an empty structure. This has no effect if it has // already been set. @@ -100,48 +100,48 @@ func FixtureModifyGlobalConfig(configModifier func(dexpreoptConfig *GlobalConfig // Retrieve the existing configuration and modify it. dexpreoptConfig = GetGlobalConfig(pathCtx) - configModifier(dexpreoptConfig) + configModifier(pathCtx, dexpreoptConfig) }) } // FixtureSetArtBootJars enables dexpreopt and sets the ArtApexJars property. func FixtureSetArtBootJars(bootJars ...string) android.FixturePreparer { - return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) { + return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) { dexpreoptConfig.ArtApexJars = android.CreateTestConfiguredJarList(bootJars) }) } // FixtureSetBootJars enables dexpreopt and sets the BootJars property. func FixtureSetBootJars(bootJars ...string) android.FixturePreparer { - return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) { + return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) { dexpreoptConfig.BootJars = android.CreateTestConfiguredJarList(bootJars) }) } // FixtureSetApexBootJars sets the ApexBootJars property in the global config. func FixtureSetApexBootJars(bootJars ...string) android.FixturePreparer { - return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) { + return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) { dexpreoptConfig.ApexBootJars = android.CreateTestConfiguredJarList(bootJars) }) } // FixtureSetStandaloneSystemServerJars sets the StandaloneSystemServerJars property. func FixtureSetStandaloneSystemServerJars(jars ...string) android.FixturePreparer { - return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) { + return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) { dexpreoptConfig.StandaloneSystemServerJars = android.CreateTestConfiguredJarList(jars) }) } // FixtureSetSystemServerJars sets the SystemServerJars property. func FixtureSetSystemServerJars(jars ...string) android.FixturePreparer { - return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) { + return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) { dexpreoptConfig.SystemServerJars = android.CreateTestConfiguredJarList(jars) }) } // FixtureSetApexSystemServerJars sets the ApexSystemServerJars property in the global config. func FixtureSetApexSystemServerJars(jars ...string) android.FixturePreparer { - return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) { + return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) { dexpreoptConfig.ApexSystemServerJars = android.CreateTestConfiguredJarList(jars) }) } @@ -149,14 +149,21 @@ func FixtureSetApexSystemServerJars(jars ...string) android.FixturePreparer { // FixtureSetApexStandaloneSystemServerJars sets the ApexStandaloneSystemServerJars property in the // global config. func FixtureSetApexStandaloneSystemServerJars(jars ...string) android.FixturePreparer { - return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) { + return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) { dexpreoptConfig.ApexStandaloneSystemServerJars = android.CreateTestConfiguredJarList(jars) }) } // FixtureSetPreoptWithUpdatableBcp sets the PreoptWithUpdatableBcp property in the global config. func FixtureSetPreoptWithUpdatableBcp(value bool) android.FixturePreparer { - return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) { + return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) { dexpreoptConfig.PreoptWithUpdatableBcp = value }) } + +// FixtureSetBootImageProfiles sets the BootImageProfiles property in the global config. +func FixtureSetBootImageProfiles(profiles ...string) android.FixturePreparer { + return FixtureModifyGlobalConfig(func(ctx android.PathContext, dexpreoptConfig *GlobalConfig) { + dexpreoptConfig.BootImageProfiles = android.PathsForSource(ctx, profiles) + }) +} diff --git a/java/android_manifest.go b/java/android_manifest.go index 3a1f5fcb1..38065f153 100644 --- a/java/android_manifest.go +++ b/java/android_manifest.go @@ -16,7 +16,6 @@ package java import ( "fmt" - "strconv" "strings" "github.com/google/blueprint" @@ -43,20 +42,6 @@ var manifestMergerRule = pctx.AndroidStaticRule("manifestMerger", }, "args", "libs") -// targetSdkVersion for manifest_fixer -// When TARGET_BUILD_APPS is not empty, this method returns the unreleased(future) API level -// This enables release builds (that run with TARGET_BUILD_APPS=[val...]) to target APIs that have not yet been finalized as part of an SDK -func targetSdkVersionForManifestFixer(ctx android.ModuleContext, sdkContext android.SdkContext) string { - if ctx.Config().UnbundledBuildApps() { - return strconv.Itoa(android.FutureApiLevel.FinalOrFutureInt()) - } - targetSdkVersion, err := sdkContext.TargetSdkVersion(ctx).EffectiveVersionString(ctx) - if err != nil { - ctx.ModuleErrorf("invalid targetSdkVersion: %s", err) - } - return targetSdkVersion -} - // Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext android.SdkContext, classLoaderContexts dexpreopt.ClassLoaderContextMap, isLibrary, useEmbeddedNativeLibs, usesNonSdkApis, @@ -104,7 +89,10 @@ func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext args = append(args, "--logging-parent", loggingParent) } var deps android.Paths - targetSdkVersion := targetSdkVersionForManifestFixer(ctx, sdkContext) + targetSdkVersion, err := sdkContext.TargetSdkVersion(ctx).EffectiveVersionString(ctx) + if err != nil { + ctx.ModuleErrorf("invalid targetSdkVersion: %s", err) + } if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" { targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String()) deps = append(deps, ApiFingerprintPath(ctx)) diff --git a/java/android_resources.go b/java/android_resources.go index 6864ebb90..8c5908f69 100644 --- a/java/android_resources.go +++ b/java/android_resources.go @@ -43,7 +43,7 @@ var androidResourceIgnoreFilenames = []string{ // androidResourceGlob returns the list of files in the given directory, using the standard // exclusion patterns for Android resources. -func androidResourceGlob(ctx android.ModuleContext, dir android.Path) android.Paths { +func androidResourceGlob(ctx android.EarlyModuleContext, dir android.Path) android.Paths { return ctx.GlobFiles(filepath.Join(dir.String(), "**/*"), androidResourceIgnoreFilenames) } diff --git a/java/app.go b/java/app.go index c08ec0697..b43e53226 100755 --- a/java/app.go +++ b/java/app.go @@ -45,6 +45,7 @@ func RegisterAppBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("override_android_test", OverrideAndroidTestModuleFactory) android.RegisterBp2BuildMutator("android_app_certificate", AndroidAppCertificateBp2Build) + android.RegisterBp2BuildMutator("android_app", AppBp2Build) } // AndroidManifest.xml merging @@ -139,6 +140,7 @@ type overridableAppProperties struct { } type AndroidApp struct { + android.BazelModuleBase Library aapt android.OverridableModuleBase @@ -291,7 +293,7 @@ func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) { if minSdkVersion, err := a.MinSdkVersion(ctx).EffectiveVersion(ctx); err == nil { a.checkJniLibsSdkVersion(ctx, minSdkVersion) - android.CheckMinSdkVersion(a, ctx, minSdkVersion) + android.CheckMinSdkVersion(ctx, minSdkVersion, a.WalkPayloadDeps) } else { ctx.PropertyErrorf("min_sdk_version", "%s", err.Error()) } @@ -1438,3 +1440,47 @@ func androidAppCertificateBp2BuildInternal(ctx android.TopDownMutatorContext, mo ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs) } + +type bazelAndroidAppAttributes struct { + Srcs bazel.LabelListAttribute + Manifest bazel.Label + Custom_package *string + Resource_files bazel.LabelListAttribute +} + +// AppBp2Build is used for android_app. +func AppBp2Build(ctx android.TopDownMutatorContext) { + a, ok := ctx.Module().(*AndroidApp) + if !ok || !a.ConvertWithBp2build(ctx) { + return + } + if ctx.ModuleType() != "android_app" { + return + } + + //TODO(b/209577426): Support multiple arch variants + srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, a.properties.Srcs, a.properties.Exclude_srcs)) + + manifest := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml") + + resourceFiles := bazel.LabelList{ + Includes: []bazel.Label{}, + } + for _, dir := range android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs, "res") { + files := android.RootToModuleRelativePaths(ctx, androidResourceGlob(ctx, dir)) + resourceFiles.Includes = append(resourceFiles.Includes, files...) + } + + attrs := &bazelAndroidAppAttributes{ + Srcs: srcs, + Manifest: android.BazelLabelForModuleSrcSingle(ctx, manifest), + // TODO(b/209576404): handle package name override by product variable PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES + Custom_package: a.overridableAppProperties.Package_name, + Resource_files: bazel.MakeLabelListAttribute(resourceFiles), + } + props := bazel.BazelTargetModuleProperties{Rule_class: "android_binary", + Bzl_load_location: "@rules_android//rules:rules.bzl"} + + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: a.Name()}, attrs) + +} diff --git a/java/base.go b/java/base.go index 2f90db2b8..c0da21523 100644 --- a/java/base.go +++ b/java/base.go @@ -1643,8 +1643,7 @@ func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu } // Implements android.ApexModule -func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, - sdkVersion android.ApiLevel) error { +func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error { sdkSpec := j.MinSdkVersion(ctx) if !sdkSpec.Specified() { return fmt.Errorf("min_sdk_version is not specified") diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index bfa683824..bfe895c17 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -390,6 +390,13 @@ type BootclasspathFragmentApexContentInfo struct { // Map from the base module name (without prebuilt_ prefix) of a fragment's contents module to the // hidden API encoded dex jar path. contentModuleDexJarPaths bootDexJarByModule + + // Path to the image profile file on host (or empty, if profile is not generated). + profilePathOnHost android.Path + + // Install path of the boot image profile if it needs to be installed in the APEX, or empty if not + // needed. + profileInstallPathInApex string } func (i BootclasspathFragmentApexContentInfo) Modules() android.ConfiguredJarList { @@ -418,6 +425,14 @@ func (i BootclasspathFragmentApexContentInfo) DexBootJarPathForContentModule(mod } } +func (i BootclasspathFragmentApexContentInfo) ProfilePathOnHost() android.Path { + return i.profilePathOnHost +} + +func (i BootclasspathFragmentApexContentInfo) ProfileInstallPathInApex() string { + return i.profileInstallPathInApex +} + func (b *BootclasspathFragmentModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { tag := ctx.OtherModuleDependencyTag(dep) if IsBootclasspathFragmentContentDepTag(tag) { @@ -579,6 +594,11 @@ func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleC if imageConfig != nil { info.modules = imageConfig.modules + global := dexpreopt.GetGlobalConfig(ctx) + if !global.DisableGenerateProfile { + info.profilePathOnHost = imageConfig.profilePathOnHost + info.profileInstallPathInApex = imageConfig.profileInstallPathInApex + } } info.bootImageFilesByArch = bootImageFilesByArch diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index a72294626..75083e8c2 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -256,6 +256,10 @@ type bootImageConfig struct { // Subdirectory where the image files on device are installed. installDirOnDevice string + // Install path of the boot image profile if it needs to be installed in the APEX, or empty if not + // needed. + profileInstallPathInApex string + // A list of (location, jar) pairs for the Java modules in this image. modules android.ConfiguredJarList @@ -272,6 +276,9 @@ type bootImageConfig struct { // Rules which should be used in make to install the outputs. profileInstalls android.RuleBuilderInstalls + // Path to the image profile file on host (or empty, if profile is not generated). + profilePathOnHost android.Path + // Target-dependent fields. variants []*bootImageVariant } @@ -769,11 +776,14 @@ func bootImageProfileRule(ctx android.ModuleContext, image *bootImageConfig) and FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps). FlagWithOutput("--reference-profile-file=", profile) - rule.Install(profile, "/system/etc/boot-image.prof") + if image == defaultBootImageConfig(ctx) { + rule.Install(profile, "/system/etc/boot-image.prof") + image.profileInstalls = append(image.profileInstalls, rule.Installs()...) + } rule.Build("bootJarsProfile", "profile boot jars") - image.profileInstalls = append(image.profileInstalls, rule.Installs()...) + image.profilePathOnHost = profile return profile } diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go index 415a1d4e7..26c110544 100644 --- a/java/dexpreopt_config.go +++ b/java/dexpreopt_config.go @@ -56,22 +56,20 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { artModules := global.ArtApexJars frameworkModules := global.BootJars.RemoveList(artModules) - artDirOnHost := "apex/art_boot_images/javalib" - artDirOnDevice := "apex/com.android.art/javalib" - frameworkSubdir := "system/framework" - // ART config for the primary boot image in the ART apex. // It includes the Core Libraries. artCfg := bootImageConfig{ - name: artBootImageName, - stem: "boot", - installDirOnHost: artDirOnHost, - installDirOnDevice: artDirOnDevice, - modules: artModules, + name: artBootImageName, + stem: "boot", + installDirOnHost: "apex/art_boot_images/javalib", + installDirOnDevice: "apex/com.android.art/javalib", + profileInstallPathInApex: "etc/boot-image.prof", + modules: artModules, } // Framework config for the boot image extension. // It includes framework libraries and depends on the ART config. + frameworkSubdir := "system/framework" frameworkCfg := bootImageConfig{ extends: &artCfg, name: frameworkBootImageName, diff --git a/java/sdk_library.go b/java/sdk_library.go index 3065d57eb..52ab06ec5 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -1129,6 +1129,22 @@ func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext) return generatedScopes } +var _ android.ModuleWithMinSdkVersionCheck = (*SdkLibrary)(nil) + +func (module *SdkLibrary) CheckMinSdkVersion(ctx android.ModuleContext) { + android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx).ApiLevel, func(c android.ModuleContext, do android.PayloadDepsCallback) { + ctx.WalkDeps(func(child android.Module, parent android.Module) bool { + isExternal := !module.depIsInSameApex(ctx, child) + if am, ok := child.(android.ApexModule); ok { + if !do(ctx, parent, am, isExternal) { + return false + } + } + return !isExternal + }) + }) +} + type sdkLibraryComponentTag struct { blueprint.BaseDependencyTag name string @@ -1214,6 +1230,10 @@ func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) { } func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { + if proptools.String(module.deviceProperties.Min_sdk_version) != "" { + module.CheckMinSdkVersion(ctx) + } + module.generateCommonBuildActions(ctx) // Only build an implementation library if required. @@ -2605,12 +2625,12 @@ func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleConte func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries { if module.hideApexVariantFromMake { - return []android.AndroidMkEntries{android.AndroidMkEntries{ + return []android.AndroidMkEntries{{ Disabled: true, }} } - return []android.AndroidMkEntries{android.AndroidMkEntries{ + return []android.AndroidMkEntries{{ Class: "ETC", OutputFile: android.OptionalPathForPath(module.outputFilePath), ExtraEntries: []android.AndroidMkExtraEntriesFunc{ diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go index 2271573b6..f3a19e956 100644 --- a/java/sdk_library_test.go +++ b/java/sdk_library_test.go @@ -1140,3 +1140,87 @@ func TestJavaSdkLibraryDist(t *testing.T) { }) } } + +func TestSdkLibrary_CheckMinSdkVersion(t *testing.T) { + preparer := android.GroupFixturePreparers( + PrepareForTestWithJavaBuildComponents, + PrepareForTestWithJavaDefaultModules, + PrepareForTestWithJavaSdkLibraryFiles, + ) + + preparer.RunTestWithBp(t, ` + java_sdk_library { + name: "sdklib", + srcs: ["a.java"], + static_libs: ["util"], + min_sdk_version: "30", + unsafe_ignore_missing_latest_api: true, + } + + java_library { + name: "util", + srcs: ["a.java"], + min_sdk_version: "30", + } + `) + + preparer. + RunTestWithBp(t, ` + java_sdk_library { + name: "sdklib", + srcs: ["a.java"], + libs: ["util"], + impl_only_libs: ["util"], + stub_only_libs: ["util"], + stub_only_static_libs: ["util"], + min_sdk_version: "30", + unsafe_ignore_missing_latest_api: true, + } + + java_library { + name: "util", + srcs: ["a.java"], + } + `) + + preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "util".*should support min_sdk_version\(30\)`)). + RunTestWithBp(t, ` + java_sdk_library { + name: "sdklib", + srcs: ["a.java"], + static_libs: ["util"], + min_sdk_version: "30", + unsafe_ignore_missing_latest_api: true, + } + + java_library { + name: "util", + srcs: ["a.java"], + min_sdk_version: "31", + } + `) + + preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "another_util".*should support min_sdk_version\(30\)`)). + RunTestWithBp(t, ` + java_sdk_library { + name: "sdklib", + srcs: ["a.java"], + static_libs: ["util"], + min_sdk_version: "30", + unsafe_ignore_missing_latest_api: true, + } + + java_library { + name: "util", + srcs: ["a.java"], + static_libs: ["another_util"], + min_sdk_version: "30", + } + + java_library { + name: "another_util", + srcs: ["a.java"], + min_sdk_version: "31", + } + `) +} diff --git a/mk2rbc/Android.bp b/mk2rbc/Android.bp index b18bfc72c..4fa3eb678 100644 --- a/mk2rbc/Android.bp +++ b/mk2rbc/Android.bp @@ -38,7 +38,6 @@ bootstrap_go_package { "soong_variables.go", "types.go", "variable.go", - "version_defaults.go", ], deps: ["androidmk-parser"], } diff --git a/mk2rbc/cmd/mk2rbc.go b/mk2rbc/cmd/mk2rbc.go index bb5a68033..d9b4e86b7 100644 --- a/mk2rbc/cmd/mk2rbc.go +++ b/mk2rbc/cmd/mk2rbc.go @@ -80,7 +80,6 @@ var backupSuffix string var tracedVariables []string var errorLogger = errorSink{data: make(map[string]datum)} var makefileFinder = &LinuxMakefileFinder{} -var versionDefaultsMk = filepath.Join("build", "make", "core", "version_defaults.mk") func main() { flag.Usage = func() { @@ -168,18 +167,14 @@ func main() { if len(files) != 1 { quit(fmt.Errorf("a launcher can be generated only for a single product")) } - versionDefaults, err := generateVersionDefaults() - if err != nil { - quit(err) + if *inputVariables == "" { + quit(fmt.Errorf("the product launcher requires an input variables file")) } - versionDefaultsPath := outputFilePath(versionDefaultsMk) - err = writeGenerated(versionDefaultsPath, versionDefaults) - if err != nil { - fmt.Fprintf(os.Stderr, "%s: %s", files[0], err) - ok = false + if !convertOne(*inputVariables) { + quit(fmt.Errorf("the product launcher input variables file failed to convert")) } - err = writeGenerated(*launcher, mk2rbc.Launcher(outputFilePath(files[0]), versionDefaultsPath, + err := writeGenerated(*launcher, mk2rbc.Launcher(outputFilePath(files[0]), outputFilePath(*inputVariables), mk2rbc.MakePath2ModuleName(files[0]))) if err != nil { fmt.Fprintf(os.Stderr, "%s: %s", files[0], err) @@ -213,15 +208,6 @@ func main() { } } -func generateVersionDefaults() (string, error) { - versionSettings, err := mk2rbc.ParseVersionDefaults(filepath.Join(*rootDir, versionDefaultsMk)) - if err != nil { - return "", err - } - return mk2rbc.VersionDefaults(versionSettings), nil - -} - func quit(s interface{}) { fmt.Fprintln(os.Stderr, s) os.Exit(2) diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go index 4b9779c68..cade4d20f 100644 --- a/mk2rbc/mk2rbc.go +++ b/mk2rbc/mk2rbc.go @@ -1111,10 +1111,8 @@ func (ctx *parseContext) parseCompareSpecialCases(directive *mkparser.Directive, } switch call.name { - case "filter": + case "filter", "filter-out": return ctx.parseCompareFilterFuncResult(directive, call, value, isEq), true - case "filter-out": - return ctx.parseCompareFilterFuncResult(directive, call, value, !isEq), true case "wildcard": return ctx.parseCompareWildcardFuncResult(directive, call, value, !isEq), true case "findstring": @@ -1695,12 +1693,12 @@ func Convert(req Request) (*StarlarkScript, error) { return starScript, nil } -func Launcher(mainModuleUri, versionDefaultsUri, mainModuleName string) string { +func Launcher(mainModuleUri, inputVariablesUri, mainModuleName string) string { var buf bytes.Buffer fmt.Fprintf(&buf, "load(%q, %q)\n", baseUri, baseName) - fmt.Fprintf(&buf, "load(%q, \"version_defaults\")\n", versionDefaultsUri) + fmt.Fprintf(&buf, "load(%q, input_variables_init = \"init\")\n", inputVariablesUri) fmt.Fprintf(&buf, "load(%q, \"init\")\n", mainModuleUri) - fmt.Fprintf(&buf, "%s(%s(%q, init, version_defaults))\n", cfnPrintVars, cfnMain, mainModuleName) + fmt.Fprintf(&buf, "%s(%s(%q, init, input_variables_init))\n", cfnPrintVars, cfnMain, mainModuleName) return buf.String() } diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go index dfdf274ef..fa33e75d5 100644 --- a/mk2rbc/mk2rbc_test.go +++ b/mk2rbc/mk2rbc_test.go @@ -390,6 +390,8 @@ endif ifeq (,$(filter barbet coral%,$(TARGET_PRODUCT))) else ifneq (,$(filter barbet%,$(TARGET_PRODUCT))) endif +ifeq (,$(filter-out sunfish_kasan, $(TARGET_PRODUCT))) +endif `, expected: `load("//build/make/core:product_config.rbc", "rblf") @@ -409,6 +411,8 @@ def init(g, handle): pass elif rblf.filter("barbet%", g["TARGET_PRODUCT"]): pass + if not rblf.filter_out("sunfish_kasan", g["TARGET_PRODUCT"]): + pass `, }, { diff --git a/mk2rbc/version_defaults.go b/mk2rbc/version_defaults.go deleted file mode 100644 index 64645d761..000000000 --- a/mk2rbc/version_defaults.go +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2021 Google LLC -// -// 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 mk2rbc - -import ( - "bytes" - "fmt" - "io/ioutil" - "os" - "sort" - "strconv" - "strings" - - mkparser "android/soong/androidmk/parser" -) - -const codenamePrefix = "PLATFORM_VERSION_CODENAME." - -// ParseVersionDefaults extracts version settings from the given file -// and returns the map. -func ParseVersionDefaults(path string) (map[string]string, error) { - contents, err := ioutil.ReadFile(path) - if err != nil { - return nil, err - } - parser := mkparser.NewParser(path, bytes.NewBuffer(contents)) - nodes, errs := parser.Parse() - if len(errs) > 0 { - for _, e := range errs { - fmt.Fprintln(os.Stderr, "ERROR:", e) - } - return nil, fmt.Errorf("cannot parse %s", path) - } - - result := map[string]string{ - "DEFAULT_PLATFORM_VERSION": "", - "MAX_PLATFORM_VERSION": "", - "MIN_PLATFORM_VERSION": "A", - "PLATFORM_BASE_SDK_EXTENSION_VERSION": "", - "PLATFORM_SDK_EXTENSION_VERSION": "", - "PLATFORM_SDK_VERSION": "", - "PLATFORM_SECURITY_PATCH": "", - "PLATFORM_VERSION_LAST_STABLE": "", - } - for _, node := range nodes { - asgn, ok := node.(*mkparser.Assignment) - if !(ok && asgn.Name.Const()) { - continue - } - s := asgn.Name.Strings[0] - _, ok = result[s] - if !ok { - ok = strings.HasPrefix(s, codenamePrefix) - } - if !ok { - continue - } - v := asgn.Value - if !v.Const() { - return nil, fmt.Errorf("the value of %s should be constant", s) - } - result[s] = strings.TrimSpace(v.Strings[0]) - } - return result, nil -} - -func genericValue(s string) interface{} { - if ival, err := strconv.ParseInt(s, 0, 0); err == nil { - return ival - } - return s -} - -// VersionDefaults generates the contents of the version_defaults.rbc file -func VersionDefaults(values map[string]string) string { - var sink bytes.Buffer - var lines []string - var codenames []string - for name, value := range values { - if strings.HasPrefix(name, codenamePrefix) { - codenames = append(codenames, - fmt.Sprintf("%q: %q", strings.TrimPrefix(name, codenamePrefix), value)) - } else { - // Print numbers as such - lines = append(lines, fmt.Sprintf(" %s = %#v,\n", - strings.ToLower(name), genericValue(value))) - } - } - - sort.Strings(lines) - sort.Strings(codenames) - - sink.WriteString("version_defaults = struct(\n") - for _, l := range lines { - sink.WriteString(l) - } - sink.WriteString(" codenames = { ") - sink.WriteString(strings.Join(codenames, ", ")) - sink.WriteString(" }\n)\n") - return sink.String() -} diff --git a/mk2rbc/version_defaults_test.go b/mk2rbc/version_defaults_test.go deleted file mode 100644 index c78fa3238..000000000 --- a/mk2rbc/version_defaults_test.go +++ /dev/null @@ -1,60 +0,0 @@ -package mk2rbc - -import ( - "path/filepath" - "reflect" - "strings" - "testing" -) - -func TestParseVersionDefaults(t *testing.T) { - testDir := getTestDirectory() - abspath := func(relPath string) string { return filepath.Join(testDir, relPath) } - actualProducts, err := ParseVersionDefaults(abspath("version_defaults.mk.test")) - if err != nil { - t.Fatal(err) - } - expectedProducts := map[string]string{ - "DEFAULT_PLATFORM_VERSION": "TP1A", - "MAX_PLATFORM_VERSION": "TP1A", - "MIN_PLATFORM_VERSION": "TP1A", - "PLATFORM_BASE_SDK_EXTENSION_VERSION": "0", - "PLATFORM_SDK_EXTENSION_VERSION": "1", - "PLATFORM_SDK_VERSION": "31", - "PLATFORM_SECURITY_PATCH": "2021-10-05", - "PLATFORM_VERSION_LAST_STABLE": "12", - "PLATFORM_VERSION_CODENAME.SP2A": "Sv2", - "PLATFORM_VERSION_CODENAME.TP1A": "Tiramisu", - } - if !reflect.DeepEqual(actualProducts, expectedProducts) { - t.Errorf("\nExpected: %v\n Actual: %v", expectedProducts, actualProducts) - } -} - -func TestVersionDefaults(t *testing.T) { - testDir := getTestDirectory() - abspath := func(relPath string) string { return filepath.Join(testDir, relPath) } - actualProducts, err := ParseVersionDefaults(abspath("version_defaults.mk.test")) - if err != nil { - t.Fatal(err) - } - expectedString := `version_defaults = struct( - default_platform_version = "TP1A", - max_platform_version = "TP1A", - min_platform_version = "TP1A", - platform_base_sdk_extension_version = 0, - platform_sdk_extension_version = 1, - platform_sdk_version = 31, - platform_security_patch = "2021-10-05", - platform_version_last_stable = 12, - codenames = { "SP2A": "Sv2", "TP1A": "Tiramisu" } -) -` - actualString := VersionDefaults(actualProducts) - if !reflect.DeepEqual(actualString, expectedString) { - t.Errorf("\nExpected: %v\nActual:\n%v", - strings.ReplaceAll(expectedString, "\n", "\n"), - strings.ReplaceAll(actualString, "\n", "\n")) - } - -} diff --git a/python/library.go b/python/library.go index b9201177d..9c92ebd5c 100644 --- a/python/library.go +++ b/python/library.go @@ -96,8 +96,8 @@ func pythonLibBp2Build(ctx android.TopDownMutatorContext, modType string) { } props := bazel.BazelTargetModuleProperties{ - // Use the native py_library rule. - Rule_class: "py_library", + Rule_class: "py_library", + Bzl_load_location: "//build/bazel/rules/python:library.bzl", } ctx.CreateBazelTargetModule(props, android.CommonAttributes{ diff --git a/rust/bindgen.go b/rust/bindgen.go index 32d02e4f6..5e1b4b74a 100644 --- a/rust/bindgen.go +++ b/rust/bindgen.go @@ -30,7 +30,7 @@ var ( defaultBindgenFlags = []string{""} // bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures. - bindgenClangVersion = "clang-r433403" + bindgenClangVersion = "clang-r437112" _ = pctx.VariableFunc("bindgenClangVersion", func(ctx android.PackageVarContext) string { if override := ctx.Config().Getenv("LLVM_BINDGEN_PREBUILTS_VERSION"); override != "" { diff --git a/rust/builder.go b/rust/builder.go index 60b5926e8..a7efc282a 100644 --- a/rust/builder.go +++ b/rust/builder.go @@ -216,6 +216,13 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl // Suppress an implicit sysroot rustcFlags = append(rustcFlags, "--sysroot=/dev/null") + // Enable incremental compilation if requested by user + if ctx.Config().IsEnvTrue("SOONG_RUSTC_INCREMENTAL") { + incrementalPath := android.PathForOutput(ctx, "rustc").String() + + rustcFlags = append(rustcFlags, "-C incremental="+incrementalPath) + } + // Collect linker flags linkFlags = append(linkFlags, flags.GlobalLinkFlags...) linkFlags = append(linkFlags, flags.LinkFlags...) diff --git a/rust/config/global.go b/rust/config/global.go index 78c8dae11..23384e551 100644 --- a/rust/config/global.go +++ b/rust/config/global.go @@ -55,6 +55,8 @@ var ( deviceGlobalRustFlags = []string{ "-C panic=abort", "-Z link-native-libraries=no", + // Generate additional debug info for AutoFDO + "-Z debug-info-for-profiling", } deviceGlobalLinkFlags = []string{ diff --git a/rust/project_json.go b/rust/project_json.go index ae48312b5..fe259d6c2 100644 --- a/rust/project_json.go +++ b/rust/project_json.go @@ -211,6 +211,8 @@ func isModuleSupported(ctx android.SingletonContext, module android.Module) (*Mo comp = c.binaryDecorator.baseCompiler case *procMacroDecorator: comp = c.baseCompiler + case *toolchainLibraryDecorator: + comp = c.baseCompiler default: return nil, nil, false } diff --git a/scripts/check_boot_jars/package_allowed_list.txt b/scripts/check_boot_jars/package_allowed_list.txt index ed63651ef..a02c19560 100644 --- a/scripts/check_boot_jars/package_allowed_list.txt +++ b/scripts/check_boot_jars/package_allowed_list.txt @@ -72,6 +72,7 @@ javax\.xml\.xpath jdk\.internal jdk\.internal\.math jdk\.internal\.misc +jdk\.internal\.ref jdk\.internal\.reflect jdk\.internal\.util jdk\.internal\.vm\.annotation diff --git a/scripts/rbc-run b/scripts/rbc-run index 235da7517..7243421ff 100755 --- a/scripts/rbc-run +++ b/scripts/rbc-run @@ -2,7 +2,7 @@ # Convert and run one configuration # Args: a product/board makefile optionally followed by additional arguments # that will be passed to rbcrun. -[[ $# -gt 0 && -f "$1" ]] || { echo "Usage: ${0##*/} product.mk [Additional rbcrun arguments]" >&2; exit 1; } +[[ $# -gt 1 && -f "$1" && -f "$2" ]] || { echo "Usage: ${0##*/} product.mk input_variables.mk [Additional rbcrun arguments]" >&2; exit 1; } set -eu declare -r output_root="${OUT_DIR:-out}" @@ -10,7 +10,8 @@ declare -r runner="${output_root}/soong/rbcrun" declare -r converter="${output_root}/soong/mk2rbc" declare -r launcher="${output_root}/rbc/launcher.rbc" declare -r makefile="$1" -shift -"${converter}" -mode=write -r --outdir "${output_root}/rbc" --launcher="${launcher}" "${makefile}" +declare -r input_variables="$2" +shift 2 +"${converter}" -mode=write -r --outdir "${output_root}/rbc" --input_variables "${input_variables}" --launcher="${launcher}" "${makefile}" "${runner}" RBC_OUT="make,global" RBC_DEBUG="${RBC_DEBUG:-}" $@ "${launcher}" diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go index ff2af439f..2dacdb55c 100644 --- a/sdk/bootclasspath_fragment_sdk_test.go +++ b/sdk/bootclasspath_fragment_sdk_test.go @@ -40,6 +40,7 @@ func fixtureAddPlatformBootclasspathForBootclasspathFragment(apex, fragment stri } `, apex, fragment)), android.FixtureAddFile("frameworks/base/config/boot-profile.txt", nil), + android.FixtureAddFile("frameworks/base/config/boot-image-profile.txt", nil), android.FixtureAddFile("build/soong/scripts/check_boot_jars/package_allowed_list.txt", nil), ) } diff --git a/ui/build/soong.go b/ui/build/soong.go index 4ced722d6..ae9a2ce25 100644 --- a/ui/build/soong.go +++ b/ui/build/soong.go @@ -153,7 +153,12 @@ func fileExists(path string) (bool, error) { return true, nil } -func primaryBuilderInvocation(config Config, name string, output string, specificArgs []string) bootstrap.PrimaryBuilderInvocation { +func primaryBuilderInvocation( + config Config, + name string, + output string, + specificArgs []string, + description string) bootstrap.PrimaryBuilderInvocation { commonArgs := make([]string, 0, 0) if !config.skipSoongTests { @@ -178,9 +183,10 @@ func primaryBuilderInvocation(config Config, name string, output string, specifi allArgs = append(allArgs, "Android.bp") return bootstrap.PrimaryBuilderInvocation{ - Inputs: []string{"Android.bp"}, - Outputs: []string{output}, - Args: allArgs, + Inputs: []string{"Android.bp"}, + Outputs: []string{output}, + Args: allArgs, + Description: description, } } @@ -232,7 +238,9 @@ func bootstrapBlueprint(ctx Context, config Config) { config, soongBuildTag, config.SoongNinjaFile(), - mainSoongBuildExtraArgs) + mainSoongBuildExtraArgs, + fmt.Sprintf("analyzing Android.bp files and generating ninja file at %s", config.SoongNinjaFile()), + ) if config.bazelBuildMode() == mixedBuild { // Mixed builds call Bazel from soong_build and they therefore need the @@ -248,7 +256,9 @@ func bootstrapBlueprint(ctx Context, config Config) { config.Bp2BuildMarkerFile(), []string{ "--bp2build_marker", config.Bp2BuildMarkerFile(), - }) + }, + fmt.Sprintf("converting Android.bp files to BUILD files at %s/bp2build", config.SoongOutDir()), + ) jsonModuleGraphInvocation := primaryBuilderInvocation( config, @@ -256,15 +266,20 @@ func bootstrapBlueprint(ctx Context, config Config) { config.ModuleGraphFile(), []string{ "--module_graph_file", config.ModuleGraphFile(), - }) + }, + fmt.Sprintf("generating the Soong module graph at %s", config.ModuleGraphFile()), + ) + queryviewDir := filepath.Join(config.SoongOutDir(), "queryview") queryviewInvocation := primaryBuilderInvocation( config, queryviewTag, config.QueryviewMarkerFile(), []string{ - "--bazel_queryview_dir", filepath.Join(config.SoongOutDir(), "queryview"), - }) + "--bazel_queryview_dir", queryviewDir, + }, + fmt.Sprintf("generating the Soong module graph as a Bazel workspace at %s", queryviewDir), + ) soongDocsInvocation := primaryBuilderInvocation( config, @@ -272,7 +287,9 @@ func bootstrapBlueprint(ctx Context, config Config) { config.SoongDocsHtml(), []string{ "--soong_docs", config.SoongDocsHtml(), - }) + }, + fmt.Sprintf("generating Soong docs at %s", config.SoongDocsHtml()), + ) globFiles := []string{ config.NamedGlobFile(soongBuildTag), |