diff options
114 files changed, 4452 insertions, 1396 deletions
diff --git a/android/androidmk.go b/android/androidmk.go index fafbfd61e..ddd51ffd5 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -304,15 +304,16 @@ func (a *AndroidMkEntries) fillInEntries(config Config, bpPath string, mod bluep host := false switch amod.Os().Class { case Host: - // Make cannot identify LOCAL_MODULE_HOST_ARCH:= common. - if amod.Arch().ArchType != Common { - a.SetString("LOCAL_MODULE_HOST_ARCH", archStr) - } - host = true - case HostCross: - // Make cannot identify LOCAL_MODULE_HOST_CROSS_ARCH:= common. - if amod.Arch().ArchType != Common { - a.SetString("LOCAL_MODULE_HOST_CROSS_ARCH", archStr) + if amod.Target().HostCross { + // Make cannot identify LOCAL_MODULE_HOST_CROSS_ARCH:= common. + if amod.Arch().ArchType != Common { + a.SetString("LOCAL_MODULE_HOST_CROSS_ARCH", archStr) + } + } else { + // Make cannot identify LOCAL_MODULE_HOST_ARCH:= common. + if amod.Arch().ArchType != Common { + a.SetString("LOCAL_MODULE_HOST_ARCH", archStr) + } } host = true case Device: @@ -359,9 +360,11 @@ func (a *AndroidMkEntries) fillInEntries(config Config, bpPath string, mod bluep if amod.ArchSpecific() { switch amod.Os().Class { case Host: - prefix = "HOST_" - case HostCross: - prefix = "HOST_CROSS_" + if amod.Target().HostCross { + prefix = "HOST_CROSS_" + } else { + prefix = "HOST_" + } case Device: prefix = "TARGET_" @@ -563,9 +566,11 @@ func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Mod if amod.ArchSpecific() { switch amod.Os().Class { case Host: - prefix = "HOST_" - case HostCross: - prefix = "HOST_CROSS_" + if amod.Target().HostCross { + prefix = "HOST_CROSS_" + } else { + prefix = "HOST_" + } case Device: prefix = "TARGET_" @@ -634,3 +639,21 @@ func shouldSkipAndroidMkProcessing(module *ModuleBase) bool { // Make does not understand LinuxBionic module.Os() == LinuxBionic } + +func AndroidMkDataPaths(data []DataPath) []string { + var testFiles []string + for _, d := range data { + rel := d.SrcPath.Rel() + path := d.SrcPath.String() + if !strings.HasSuffix(path, rel) { + panic(fmt.Errorf("path %q does not end with %q", path, rel)) + } + path = strings.TrimSuffix(path, rel) + testFileString := path + ":" + rel + if len(d.RelativeInstallPath) > 0 { + testFileString += ":" + d.RelativeInstallPath + } + testFiles = append(testFiles, testFileString) + } + return testFiles +} diff --git a/android/apex.go b/android/apex.go index f857ec692..c88696284 100644 --- a/android/apex.go +++ b/android/apex.go @@ -24,29 +24,36 @@ import ( "github.com/google/blueprint" ) -const ( - SdkVersion_Android10 = 29 +var ( + SdkVersion_Android10 = uncheckedFinalApiLevel(29) ) type ApexInfo struct { // Name of the apex variation that this module is mutated into ApexVariationName string - MinSdkVersion int - Updatable bool - RequiredSdks SdkRefs + // Serialized ApiLevel. Use via MinSdkVersion() method. Cannot be stored in + // its struct form because this is cloned into properties structs, and + // ApiLevel has private members. + MinSdkVersionStr string + Updatable bool + RequiredSdks SdkRefs InApexes []string } -func (i ApexInfo) mergedName() string { - name := "apex" + strconv.Itoa(i.MinSdkVersion) +func (i ApexInfo) mergedName(ctx EarlyModuleContext) string { + name := "apex" + strconv.Itoa(i.MinSdkVersion(ctx).FinalOrFutureInt()) for _, sdk := range i.RequiredSdks { name += "_" + sdk.Name + "_" + sdk.Version } return name } +func (this *ApexInfo) MinSdkVersion(ctx EarlyModuleContext) ApiLevel { + return ApiLevelOrPanic(ctx, this.MinSdkVersionStr) +} + // Extracted from ApexModule to make it easier to define custom subsets of the // ApexModule interface and improve code navigation within the IDE. type DepIsInSameApex interface { @@ -129,7 +136,7 @@ type ApexModule interface { // Returns the highest version which is <= maxSdkVersion. // For example, with maxSdkVersion is 10 and versionList is [9,11] // it returns 9 as string - ChooseSdkVersion(versionList []string, maxSdkVersion int) (string, error) + ChooseSdkVersion(ctx BaseModuleContext, versionList []string, maxSdkVersion ApiLevel) (string, error) // Tests if the module comes from an updatable APEX. Updatable() bool @@ -141,7 +148,7 @@ type ApexModule interface { // Returns nil if this module supports sdkVersion // Otherwise, returns error with reason - ShouldSupportSdkVersion(ctx BaseModuleContext, sdkVersion int) error + ShouldSupportSdkVersion(ctx BaseModuleContext, sdkVersion ApiLevel) error // Returns true if this module needs a unique variation per apex, for example if // use_apex_name_macro is set. @@ -313,14 +320,18 @@ func (m *ApexModuleBase) DepIsInSameApex(ctx BaseModuleContext, dep Module) bool return true } -func (m *ApexModuleBase) ChooseSdkVersion(versionList []string, maxSdkVersion int) (string, error) { +func (m *ApexModuleBase) ChooseSdkVersion(ctx BaseModuleContext, versionList []string, maxSdkVersion ApiLevel) (string, error) { for i := range versionList { - ver, _ := strconv.Atoi(versionList[len(versionList)-i-1]) - if ver <= maxSdkVersion { - return versionList[len(versionList)-i-1], nil + version := versionList[len(versionList)-i-1] + ver, err := ApiLevelFromUser(ctx, version) + if err != nil { + return "", err + } + if ver.LessThanOrEqualTo(maxSdkVersion) { + return version, nil } } - return "", fmt.Errorf("not found a version(<=%d) in versionList: %v", maxSdkVersion, versionList) + return "", fmt.Errorf("not found a version(<=%s) in versionList: %v", maxSdkVersion, versionList) } func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) { @@ -347,18 +358,18 @@ func (a byApexName) Less(i, j int) bool { return a[i].ApexVariationName < a[j].A // mergeApexVariations deduplicates APEX variations that would build identically into a common // variation. It returns the reduced list of variations and a list of aliases from the original // variation names to the new variation names. -func mergeApexVariations(apexVariations []ApexInfo) (merged []ApexInfo, aliases [][2]string) { +func mergeApexVariations(ctx EarlyModuleContext, apexVariations []ApexInfo) (merged []ApexInfo, aliases [][2]string) { sort.Sort(byApexName(apexVariations)) seen := make(map[string]int) for _, apexInfo := range apexVariations { apexName := apexInfo.ApexVariationName - mergedName := apexInfo.mergedName() + mergedName := apexInfo.mergedName(ctx) if index, exists := seen[mergedName]; exists { merged[index].InApexes = append(merged[index].InApexes, apexName) merged[index].Updatable = merged[index].Updatable || apexInfo.Updatable } else { seen[mergedName] = len(merged) - apexInfo.ApexVariationName = apexInfo.mergedName() + apexInfo.ApexVariationName = apexInfo.mergedName(ctx) apexInfo.InApexes = CopyOf(apexInfo.InApexes) merged = append(merged, apexInfo) } @@ -374,7 +385,7 @@ func (m *ApexModuleBase) CreateApexVariations(mctx BottomUpMutatorContext) []Mod var apexVariations []ApexInfo var aliases [][2]string if !mctx.Module().(ApexModule).UniqueApexVariations() && !m.ApexProperties.UniqueApexVariationsForDeps { - apexVariations, aliases = mergeApexVariations(m.apexVariations) + apexVariations, aliases = mergeApexVariations(mctx, m.apexVariations) } else { apexVariations = m.apexVariations } @@ -570,15 +581,15 @@ func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, minSdkVersion var fullContent strings.Builder var flatContent strings.Builder - fmt.Fprintf(&flatContent, "%s(minSdkVersion:%s):\\n", ctx.ModuleName(), minSdkVersion) + fmt.Fprintf(&fullContent, "%s(minSdkVersion:%s):\\n", ctx.ModuleName(), minSdkVersion) for _, key := range FirstUniqueStrings(SortedStringKeys(depInfos)) { info := depInfos[key] toName := fmt.Sprintf("%s(minSdkVersion:%s)", info.To, info.MinSdkVersion) if info.IsExternal { toName = toName + " (external)" } - fmt.Fprintf(&fullContent, "%s <- %s\\n", toName, strings.Join(SortedUniqueStrings(info.From), ", ")) - fmt.Fprintf(&flatContent, " %s\\n", toName) + fmt.Fprintf(&fullContent, " %s <- %s\\n", toName, strings.Join(SortedUniqueStrings(info.From), ", ")) + fmt.Fprintf(&flatContent, "%s\\n", toName) } d.fullListPath = PathForModuleOut(ctx, "depsinfo", "fulllist.txt").OutputPath @@ -603,7 +614,13 @@ func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, minSdkVersion } // TODO(b/158059172): remove minSdkVersion allowlist -var minSdkVersionAllowlist = map[string]int{ +var minSdkVersionAllowlist = func(apiMap map[string]int) map[string]ApiLevel { + list := make(map[string]ApiLevel, len(apiMap)) + for name, finalApiInt := range apiMap { + list[name] = uncheckedFinalApiLevel(finalApiInt) + } + return list +}(map[string]int{ "adbd": 30, "android.net.ipsec.ike": 30, "androidx-constraintlayout_constraintlayout-solver": 30, @@ -672,7 +689,7 @@ var minSdkVersionAllowlist = map[string]int{ "statsd": 30, "tensorflow_headers": 30, "xz-java": 29, -} +}) // Function called while walking an APEX's payload dependencies. // @@ -686,7 +703,7 @@ type UpdatableModule interface { } // CheckMinSdkVersion checks if every dependency of an updatable module sets min_sdk_version accordingly -func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion int) { +func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion ApiLevel) { // do not enforce min_sdk_version for host if ctx.Host() { return @@ -699,7 +716,7 @@ func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion int) // do not enforce deps.min_sdk_version if APEX/APK doesn't set min_sdk_version or // min_sdk_version is not finalized (e.g. current or codenames) - if minSdkVersion == FutureApiLevel { + if minSdkVersion.IsCurrent() { return } @@ -714,7 +731,7 @@ func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion int) } if err := to.ShouldSupportSdkVersion(ctx, minSdkVersion); err != nil { toName := ctx.OtherModuleName(to) - if ver, ok := minSdkVersionAllowlist[toName]; !ok || ver > minSdkVersion { + if ver, ok := minSdkVersionAllowlist[toName]; !ok || ver.GreaterThan(minSdkVersion) { ctx.OtherModuleErrorf(to, "should support min_sdk_version(%v) for %q: %v. Dependency path: %s", minSdkVersion, ctx.ModuleName(), err.Error(), ctx.GetPathString(false)) return false diff --git a/android/api_levels.go b/android/api_levels.go index 087206633..97683404e 100644 --- a/android/api_levels.go +++ b/android/api_levels.go @@ -24,6 +24,193 @@ func init() { RegisterSingletonType("api_levels", ApiLevelsSingleton) } +// An API level, which may be a finalized (numbered) API, a preview (codenamed) +// API, or the future API level (10000). Can be parsed from a string with +// ApiLevelFromUser or ApiLevelOrPanic. +// +// The different *types* of API levels are handled separately. Currently only +// Java has these, and they're managed with the sdkKind enum of the sdkSpec. A +// future cleanup should be to migrate sdkSpec to using ApiLevel instead of its +// sdkVersion int, and to move sdkSpec into this package. +type ApiLevel struct { + // The string representation of the API level. + value string + + // A number associated with the API level. The exact value depends on + // whether this API level is a preview or final API. + // + // For final API levels, this is the assigned version number. + // + // For preview API levels, this value has no meaning except to index known + // previews to determine ordering. + number int + + // Identifies this API level as either a preview or final API level. + isPreview bool +} + +func (this ApiLevel) FinalOrFutureInt() int { + if this.IsPreview() { + return FutureApiLevelInt + } else { + return this.number + } +} + +// Returns the canonical name for this API level. For a finalized API level +// this will be the API number as a string. For a preview API level this +// will be the codename, or "current". +func (this ApiLevel) String() string { + return this.value +} + +// Returns true if this is a non-final API level. +func (this ApiLevel) IsPreview() bool { + return this.isPreview +} + +// Returns true if this is the unfinalized "current" API level. This means +// different things across Java and native. Java APIs do not use explicit +// codenames, so all non-final codenames are grouped into "current". For native +// explicit codenames are typically used, and current is the union of all +// non-final APIs, including those that may not yet be in any codename. +// +// Note that in a build where the platform is final, "current" will not be a +// preview API level but will instead be canonicalized to the final API level. +func (this ApiLevel) IsCurrent() bool { + return this.value == "current" +} + +// Returns -1 if the current API level is less than the argument, 0 if they +// are equal, and 1 if it is greater than the argument. +func (this ApiLevel) CompareTo(other ApiLevel) int { + if this.IsPreview() && !other.IsPreview() { + return 1 + } else if !this.IsPreview() && other.IsPreview() { + return -1 + } + + if this.number < other.number { + return -1 + } else if this.number == other.number { + return 0 + } else { + return 1 + } +} + +func (this ApiLevel) EqualTo(other ApiLevel) bool { + return this.CompareTo(other) == 0 +} + +func (this ApiLevel) GreaterThan(other ApiLevel) bool { + return this.CompareTo(other) > 0 +} + +func (this ApiLevel) GreaterThanOrEqualTo(other ApiLevel) bool { + return this.CompareTo(other) >= 0 +} + +func (this ApiLevel) LessThan(other ApiLevel) bool { + return this.CompareTo(other) < 0 +} + +func (this ApiLevel) LessThanOrEqualTo(other ApiLevel) bool { + return this.CompareTo(other) <= 0 +} + +func uncheckedFinalApiLevel(num int) ApiLevel { + return ApiLevel{ + value: strconv.Itoa(num), + number: num, + isPreview: false, + } +} + +var NoneApiLevel = ApiLevel{ + value: "(no version)", + // Not 0 because we don't want this to compare equal with the first preview. + number: -1, + isPreview: true, +} + +// The first version that introduced 64-bit ABIs. +var FirstLp64Version = uncheckedFinalApiLevel(21) + +// The first API level that does not require NDK code to link +// libandroid_support. +var FirstNonLibAndroidSupportVersion = uncheckedFinalApiLevel(21) + +// If the `raw` input is the codename of an API level has been finalized, this +// function returns the API level number associated with that API level. If the +// input is *not* a finalized codename, the input is returned unmodified. +// +// For example, at the time of writing, R has been finalized as API level 30, +// but S is in development so it has no number assigned. For the following +// inputs: +// +// * "30" -> "30" +// * "R" -> "30" +// * "S" -> "S" +func ReplaceFinalizedCodenames(ctx EarlyModuleContext, raw string) string { + num, ok := getFinalCodenamesMap(ctx.Config())[raw] + if !ok { + return raw + } + + return strconv.Itoa(num) +} + +// Converts the given string `raw` to an ApiLevel, possibly returning an error. +// +// `raw` must be non-empty. Passing an empty string results in a panic. +// +// "current" will return CurrentApiLevel, which is the ApiLevel associated with +// an arbitrary future release (often referred to as API level 10000). +// +// Finalized codenames will be interpreted as their final API levels, not the +// preview of the associated releases. R is now API 30, not the R preview. +// +// Future codenames return a preview API level that has no associated integer. +// +// Inputs that are not "current", known previews, or convertible to an integer +// will return an error. +func ApiLevelFromUser(ctx EarlyModuleContext, raw string) (ApiLevel, error) { + if raw == "" { + panic("API level string must be non-empty") + } + + if raw == "current" { + return FutureApiLevel, nil + } + + for _, preview := range ctx.Config().PreviewApiLevels() { + if raw == preview.String() { + return preview, nil + } + } + + canonical := ReplaceFinalizedCodenames(ctx, raw) + asInt, err := strconv.Atoi(canonical) + if err != nil { + return NoneApiLevel, fmt.Errorf("%q could not be parsed as an integer and is not a recognized codename", canonical) + } + + apiLevel := uncheckedFinalApiLevel(asInt) + return apiLevel, nil +} + +// Converts an API level string `raw` into an ApiLevel in the same method as +// `ApiLevelFromUser`, but the input is assumed to have no errors and any errors +// will panic instead of returning an error. +func ApiLevelOrPanic(ctx EarlyModuleContext, raw string) ApiLevel { + value, err := ApiLevelFromUser(ctx, raw) + if err != nil { + panic(err.Error()) + } + return value +} + func ApiLevelsSingleton() Singleton { return &apiLevelsSingleton{} } @@ -52,6 +239,48 @@ func GetApiLevelsJson(ctx PathContext) WritablePath { return PathForOutput(ctx, "api_levels.json") } +var finalCodenamesMapKey = NewOnceKey("FinalCodenamesMap") + +func getFinalCodenamesMap(config Config) map[string]int { + return config.Once(finalCodenamesMapKey, func() interface{} { + apiLevelsMap := map[string]int{ + "G": 9, + "I": 14, + "J": 16, + "J-MR1": 17, + "J-MR2": 18, + "K": 19, + "L": 21, + "L-MR1": 22, + "M": 23, + "N": 24, + "N-MR1": 25, + "O": 26, + "O-MR1": 27, + "P": 28, + "Q": 29, + "R": 30, + } + + // TODO: Differentiate "current" and "future". + // The code base calls it FutureApiLevel, but the spelling is "current", + // and these are really two different things. When defining APIs it + // means the API has not yet been added to a specific release. When + // choosing an API level to build for it means that the future API level + // should be used, except in the case where the build is finalized in + // which case the platform version should be used. This is *weird*, + // because in the circumstance where API foo was added in R and bar was + // added in S, both of these are usable when building for "current" when + // neither R nor S are final, but the S APIs stop being available in a + // final R build. + if Bool(config.productVariables.Platform_sdk_final) { + apiLevelsMap["current"] = config.PlatformSdkVersion().FinalOrFutureInt() + } + + return apiLevelsMap + }).(map[string]int) +} + var apiLevelsMapKey = NewOnceKey("ApiLevelsMap") func getApiLevelsMap(config Config) map[string]int { @@ -83,24 +312,6 @@ func getApiLevelsMap(config Config) map[string]int { }).(map[string]int) } -// Converts an API level string into its numeric form. -// * Codenames are decoded. -// * Numeric API levels are simply converted. -// * "current" is mapped to FutureApiLevel(10000) -// * "minimum" is NDK specific and not handled with this. (refer normalizeNdkApiLevel in cc.go) -func ApiStrToNum(ctx BaseModuleContext, apiLevel string) (int, error) { - if apiLevel == "current" { - return FutureApiLevel, nil - } - if num, ok := getApiLevelsMap(ctx.Config())[apiLevel]; ok { - return num, nil - } - if num, err := strconv.Atoi(apiLevel); err == nil { - return num, nil - } - return 0, fmt.Errorf("SDK version should be one of \"current\", <number> or <codename>: %q", apiLevel) -} - func (a *apiLevelsSingleton) GenerateBuildActions(ctx SingletonContext) { apiLevelsMap := getApiLevelsMap(ctx.Config()) apiLevelsJson := GetApiLevelsJson(ctx) diff --git a/android/arch.go b/android/arch.go index d055a6fe0..f4b0d66d9 100644 --- a/android/arch.go +++ b/android/arch.go @@ -78,13 +78,22 @@ module { }, target: { android: { - // Device variants + // Device variants (implies Bionic) }, host: { // Host variants }, + bionic: { + // Bionic (device and host) variants + }, + linux_bionic: { + // Bionic host variants + }, + linux: { + // Bionic (device and host) and Linux glibc variants + }, linux_glibc: { - // Linux host variants + // Linux host variants (using non-Bionic libc) }, darwin: { // Darwin host variants @@ -95,6 +104,9 @@ module { not_windows: { // Non-windows host variants }, + android_arm: { + // Any <os>_<arch> combination restricts to that os and arch + }, }, } */ @@ -125,6 +137,7 @@ var archVariants = map[ArchType][]string{ Arm64: { "armv8_a", "armv8_2a", + "armv8-2a-dotprod", "cortex-a53", "cortex-a55", "cortex-a72", @@ -172,6 +185,9 @@ var archFeatures = map[ArchType][]string{ Arm: { "neon", }, + Arm64: { + "dotprod", + }, X86: { "ssse3", "sse4", @@ -209,6 +225,11 @@ var archFeatureMap = map[ArchType]map[string][]string{ "neon", }, }, + Arm64: { + "armv8-2a-dotprod": { + "dotprod", + }, + }, X86: { "amberlake": { "ssse3", @@ -569,7 +590,7 @@ var ( Linux = NewOsType("linux_glibc", Host, false) Darwin = NewOsType("darwin", Host, false) LinuxBionic = NewOsType("linux_bionic", Host, false) - Windows = NewOsType("windows", HostCross, true) + Windows = NewOsType("windows", Host, true) Android = NewOsType("android", Device, false) Fuchsia = NewOsType("fuchsia", Device, false) @@ -600,7 +621,6 @@ const ( Generic OsClass = iota Device Host - HostCross ) func (class OsClass) String() string { @@ -611,8 +631,6 @@ func (class OsClass) String() string { return "device" case Host: return "host" - case HostCross: - return "host cross" default: panic(fmt.Errorf("unknown class %d", class)) } @@ -672,6 +690,11 @@ type Target struct { NativeBridge NativeBridgeSupport NativeBridgeHostArchName string NativeBridgeRelativePath string + + // HostCross is true when the target cannot run natively on the current build host. + // For example, linux_glibc_x86 returns true on a regular x86/i686/Linux machines, but returns false + // on Mac (different OS), or on 64-bit only i686/Linux machines (unsupported arch). + HostCross bool } func (target Target) String() string { @@ -730,26 +753,15 @@ func osMutator(bpctx blueprint.BottomUpMutatorContext) { return } - osClasses := base.OsClassSupported() - var moduleOSList []OsType for _, os := range OsTypeList { - supportedClass := false - for _, osClass := range osClasses { - if os.Class == osClass { - supportedClass = true + for _, t := range mctx.Config().Targets[os] { + if base.supportsTarget(t, mctx.Config()) { + moduleOSList = append(moduleOSList, os) + break } } - if !supportedClass { - continue - } - - if len(mctx.Config().Targets[os]) == 0 { - continue - } - - moduleOSList = append(moduleOSList, os) } if len(moduleOSList) == 0 { @@ -904,7 +916,7 @@ func archMutator(bpctx blueprint.BottomUpMutatorContext) { prefer32 := false if base.prefer32 != nil { - prefer32 = base.prefer32(mctx, base, os.Class) + prefer32 = base.prefer32(mctx, base, os) } multilib, extraMultilib := decodeMultilib(base, os.Class) @@ -955,7 +967,7 @@ func decodeMultilib(base *ModuleBase, class OsClass) (multilib, extraMultilib st switch class { case Device: multilib = String(base.commonProperties.Target.Android.Compile_multilib) - case Host, HostCross: + case Host: multilib = String(base.commonProperties.Target.Host.Compile_multilib) } if multilib == "" { @@ -1231,7 +1243,7 @@ func (m *ModuleBase) setOSProperties(ctx BottomUpMutatorContext) { // key: value, // }, // }, - if os.Class == Host || os.Class == HostCross { + if os.Class == Host { field := "Host" prefix := "target.host" m.appendProperties(ctx, genProps, targetProp, field, prefix) @@ -1271,7 +1283,7 @@ func (m *ModuleBase) setOSProperties(ctx BottomUpMutatorContext) { prefix := "target." + os.Name m.appendProperties(ctx, genProps, targetProp, field, prefix) - if (os.Class == Host || os.Class == HostCross) && os != Windows { + if os.Class == Host && os != Windows { field := "Not_windows" prefix := "target.not_windows" m.appendProperties(ctx, genProps, targetProp, field, prefix) @@ -1434,20 +1446,15 @@ func (m *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) { // key: value, // }, // }, - // TODO(ccross): is this still necessary with native bridge? if os.Class == Device { - if (arch.ArchType == X86 && (hasArmAbi(arch) || - hasArmAndroidArch(ctx.Config().Targets[Android]))) || - (arch.ArchType == Arm && - hasX86AndroidArch(ctx.Config().Targets[Android])) { + if arch.ArchType == X86 && (hasArmAbi(arch) || + hasArmAndroidArch(ctx.Config().Targets[Android])) { field := "Arm_on_x86" prefix := "target.arm_on_x86" m.appendProperties(ctx, genProps, targetProp, field, prefix) } - if (arch.ArchType == X86_64 && (hasArmAbi(arch) || - hasArmAndroidArch(ctx.Config().Targets[Android]))) || - (arch.ArchType == Arm && - hasX8664AndroidArch(ctx.Config().Targets[Android])) { + if arch.ArchType == X86_64 && (hasArmAbi(arch) || + hasArmAndroidArch(ctx.Config().Targets[Android])) { field := "Arm_on_x86_64" prefix := "target.arm_on_x86_64" m.appendProperties(ctx, genProps, targetProp, field, prefix) @@ -1504,6 +1511,36 @@ func decodeTargetProductVariables(config *config) (map[OsType][]Target, error) { nativeBridgeRelativePathStr = arch.ArchType.String() } + // A target is considered as HostCross if it's a host target which can't run natively on + // the currently configured build machine (either because the OS is different or because of + // the unsupported arch) + hostCross := false + if os.Class == Host { + var osSupported bool + if os == BuildOs { + osSupported = true + } else if BuildOs.Linux() && os.Linux() { + // LinuxBionic and Linux are compatible + osSupported = true + } else { + osSupported = false + } + + var archSupported bool + if arch.ArchType == Common { + archSupported = true + } else if arch.ArchType.Name == *variables.HostArch { + archSupported = true + } else if variables.HostSecondaryArch != nil && arch.ArchType.Name == *variables.HostSecondaryArch { + archSupported = true + } else { + archSupported = false + } + if !osSupported || !archSupported { + hostCross = true + } + } + targets[os] = append(targets[os], Target{ Os: os, @@ -1511,6 +1548,7 @@ func decodeTargetProductVariables(config *config) (map[OsType][]Target, error) { NativeBridge: nativeBridgeEnabled, NativeBridgeHostArchName: nativeBridgeHostArchNameStr, NativeBridgeRelativePath: nativeBridgeRelativePathStr, + HostCross: hostCross, }) } @@ -1527,6 +1565,9 @@ func decodeTargetProductVariables(config *config) (map[OsType][]Target, error) { if Bool(config.Host_bionic) { addTarget(LinuxBionic, "x86_64", nil, nil, nil, NativeBridgeDisabled, nil, nil) } + if Bool(config.Host_bionic_arm64) { + addTarget(LinuxBionic, "arm64", nil, nil, nil, NativeBridgeDisabled, nil, nil) + } if String(variables.CrossHost) != "" { crossHostOs := osByName(*variables.CrossHost) @@ -1594,27 +1635,7 @@ func hasArmAbi(arch Arch) bool { // hasArmArch returns true if targets has at least non-native_bridge arm Android arch func hasArmAndroidArch(targets []Target) bool { for _, target := range targets { - if target.Os == Android && target.Arch.ArchType == Arm && target.NativeBridge == NativeBridgeDisabled { - return true - } - } - return false -} - -// hasX86Arch returns true if targets has at least x86 Android arch -func hasX86AndroidArch(targets []Target) bool { - for _, target := range targets { - if target.Os == Android && target.Arch.ArchType == X86 { - return true - } - } - return false -} - -// hasX8664Arch returns true if targets has at least x86_64 Android arch -func hasX8664AndroidArch(targets []Target) bool { - for _, target := range targets { - if target.Os == Android && target.Arch.ArchType == X86_64 { + if target.Os == Android && target.Arch.ArchType == Arm { return true } } @@ -1653,9 +1674,10 @@ func getMegaDeviceConfig() []archConfig { {"arm64", "armv8-a", "kryo", []string{"arm64-v8a"}}, {"arm64", "armv8-a", "exynos-m1", []string{"arm64-v8a"}}, {"arm64", "armv8-a", "exynos-m2", []string{"arm64-v8a"}}, - {"arm64", "armv8-2a", "cortex-a75", []string{"arm64-v8a"}}, - {"arm64", "armv8-2a", "cortex-a76", []string{"arm64-v8a"}}, {"arm64", "armv8-2a", "kryo385", []string{"arm64-v8a"}}, + {"arm64", "armv8-2a-dotprod", "cortex-a55", []string{"arm64-v8a"}}, + {"arm64", "armv8-2a-dotprod", "cortex-a75", []string{"arm64-v8a"}}, + {"arm64", "armv8-2a-dotprod", "cortex-a76", []string{"arm64-v8a"}}, {"x86", "", "", []string{"x86"}}, {"x86", "atom", "", []string{"x86"}}, {"x86", "haswell", "", []string{"x86"}}, @@ -1786,13 +1808,22 @@ func getCommonTargets(targets []Target) []Target { } func firstTarget(targets []Target, filters ...string) []Target { + // find the first target from each OS + var ret []Target + hasHost := false + set := make(map[OsType]bool) + for _, filter := range filters { buildTargets := filterMultilibTargets(targets, filter) - if len(buildTargets) > 0 { - return buildTargets[:1] + for _, t := range buildTargets { + if _, found := set[t.Os]; !found { + hasHost = hasHost || (t.Os.Class == Host) + set[t.Os] = true + ret = append(ret, t) + } } } - return nil + return ret } // Use the module multilib setting to select one or more targets from a target list diff --git a/android/config.go b/android/config.go index dd622e5b2..8df65f720 100644 --- a/android/config.go +++ b/android/config.go @@ -21,7 +21,6 @@ import ( "os" "path/filepath" "runtime" - "strconv" "strings" "sync" @@ -37,7 +36,13 @@ var Bool = proptools.Bool var String = proptools.String var StringDefault = proptools.StringDefault -const FutureApiLevel = 10000 +const FutureApiLevelInt = 10000 + +var FutureApiLevel = ApiLevel{ + value: "current", + number: FutureApiLevelInt, + isPreview: true, +} // The configuration file name const configFileName = "soong.config" @@ -46,8 +51,9 @@ const productVariablesFileName = "soong.variables" // A FileConfigurableOptions contains options which can be configured by the // config file. These will be included in the config struct. type FileConfigurableOptions struct { - Mega_device *bool `json:",omitempty"` - Host_bionic *bool `json:",omitempty"` + Mega_device *bool `json:",omitempty"` + Host_bionic *bool `json:",omitempty"` + Host_bionic_arm64 *bool `json:",omitempty"` } func (f *FileConfigurableOptions) SetDefaultConfig() { @@ -222,15 +228,17 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string config := &config{ productVariables: productVariables{ - DeviceName: stringPtr("test_device"), - Platform_sdk_version: intPtr(30), - DeviceSystemSdkVersions: []string{"14", "15"}, - Platform_systemsdk_versions: []string{"29", "30"}, - AAPTConfig: []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"}, - AAPTPreferredConfig: stringPtr("xhdpi"), - AAPTCharacteristics: stringPtr("nosdcard"), - AAPTPrebuiltDPI: []string{"xhdpi", "xxhdpi"}, - UncompressPrivAppDex: boolPtr(true), + DeviceName: stringPtr("test_device"), + Platform_sdk_version: intPtr(30), + Platform_sdk_codename: stringPtr("S"), + Platform_version_active_codenames: []string{"S"}, + DeviceSystemSdkVersions: []string{"14", "15"}, + Platform_systemsdk_versions: []string{"29", "30"}, + AAPTConfig: []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"}, + AAPTPreferredConfig: stringPtr("xhdpi"), + AAPTCharacteristics: stringPtr("nosdcard"), + AAPTPrebuiltDPI: []string{"xhdpi", "xxhdpi"}, + UncompressPrivAppDex: boolPtr(true), }, buildDir: buildDir, @@ -260,10 +268,10 @@ func TestArchConfigNativeBridge(buildDir string, env map[string]string, bp strin config := testConfig.config config.Targets[Android] = []Target{ - {Android, Arch{ArchType: X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", ""}, - {Android, Arch{ArchType: X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", ""}, - {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeEnabled, "x86_64", "arm64"}, - {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeEnabled, "x86", "arm"}, + {Android, Arch{ArchType: X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", "", false}, + {Android, Arch{ArchType: X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", "", false}, + {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeEnabled, "x86_64", "arm64", false}, + {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeEnabled, "x86", "arm", false}, } return testConfig @@ -275,10 +283,10 @@ func TestArchConfigFuchsia(buildDir string, env map[string]string, bp string, fs config.Targets = map[OsType][]Target{ Fuchsia: []Target{ - {Fuchsia, Arch{ArchType: Arm64, ArchVariant: "", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", ""}, + {Fuchsia, Arch{ArchType: Arm64, ArchVariant: "", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", "", false}, }, BuildOs: []Target{ - {BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", ""}, + {BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", false}, }, } @@ -292,12 +300,12 @@ func TestArchConfig(buildDir string, env map[string]string, bp string, fs map[st config.Targets = map[OsType][]Target{ Android: []Target{ - {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", ""}, - {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", ""}, + {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", "", false}, + {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", "", false}, }, BuildOs: []Target{ - {BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", ""}, - {BuildOs, Arch{ArchType: X86}, NativeBridgeDisabled, "", ""}, + {BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", false}, + {BuildOs, Arch{ArchType: X86}, NativeBridgeDisabled, "", "", false}, }, } @@ -614,12 +622,8 @@ func (c *config) PlatformVersionName() string { return String(c.productVariables.Platform_version_name) } -func (c *config) PlatformSdkVersionInt() int { - return *c.productVariables.Platform_sdk_version -} - -func (c *config) PlatformSdkVersion() string { - return strconv.Itoa(c.PlatformSdkVersionInt()) +func (c *config) PlatformSdkVersion() ApiLevel { + return uncheckedFinalApiLevel(*c.productVariables.Platform_sdk_version) } func (c *config) PlatformSdkCodename() string { @@ -642,23 +646,48 @@ func (c *config) PlatformBaseOS() string { return String(c.productVariables.Platform_base_os) } -func (c *config) MinSupportedSdkVersion() int { - return 16 +func (c *config) MinSupportedSdkVersion() ApiLevel { + return uncheckedFinalApiLevel(16) } -func (c *config) DefaultAppTargetSdkInt() int { - if Bool(c.productVariables.Platform_sdk_final) { - return c.PlatformSdkVersionInt() - } else { - return FutureApiLevel +func (c *config) FinalApiLevels() []ApiLevel { + var levels []ApiLevel + for i := 1; i <= c.PlatformSdkVersion().FinalOrFutureInt(); i++ { + levels = append(levels, uncheckedFinalApiLevel(i)) } + return levels } -func (c *config) DefaultAppTargetSdk() string { +func (c *config) PreviewApiLevels() []ApiLevel { + var levels []ApiLevel + for i, codename := range c.PlatformVersionActiveCodenames() { + levels = append(levels, ApiLevel{ + value: codename, + number: i, + isPreview: true, + }) + } + return levels +} + +func (c *config) AllSupportedApiLevels() []ApiLevel { + var levels []ApiLevel + levels = append(levels, c.FinalApiLevels()...) + return append(levels, c.PreviewApiLevels()...) +} + +func (c *config) DefaultAppTargetSdk(ctx EarlyModuleContext) ApiLevel { if Bool(c.productVariables.Platform_sdk_final) { return c.PlatformSdkVersion() } else { - return c.PlatformSdkCodename() + codename := c.PlatformSdkCodename() + if codename == "" { + return NoneApiLevel + } + if codename == "REL" { + panic("Platform_sdk_codename should not be REL when Platform_sdk_final is true") + } + return ApiLevelOrPanic(ctx, codename) } } diff --git a/android/makevars.go b/android/makevars.go index 003a9df32..374986e84 100644 --- a/android/makevars.go +++ b/android/makevars.go @@ -18,7 +18,6 @@ import ( "bytes" "fmt" "sort" - "strconv" "strings" "github.com/google/blueprint" @@ -31,7 +30,7 @@ func init() { } func androidMakeVarsProvider(ctx MakeVarsContext) { - ctx.Strict("MIN_SUPPORTED_SDK_VERSION", strconv.Itoa(ctx.Config().MinSupportedSdkVersion())) + ctx.Strict("MIN_SUPPORTED_SDK_VERSION", ctx.Config().MinSupportedSdkVersion().String()) } /////////////////////////////////////////////////////////////////////////////// diff --git a/android/module.go b/android/module.go index 337ae4076..c4e43c219 100644 --- a/android/module.go +++ b/android/module.go @@ -61,18 +61,44 @@ type ModuleBuildParams BuildParams // EarlyModuleContext provides methods that can be called early, as soon as the properties have // been parsed into the module and before any mutators have run. type EarlyModuleContext interface { + // Module returns the current module as a Module. It should rarely be necessary, as the module already has a + // reference to itself. Module() Module + + // ModuleName returns the name of the module. This is generally the value that was returned by Module.Name() when + // the module was created, but may have been modified by calls to BaseMutatorContext.Rename. ModuleName() string + + // ModuleDir returns the path to the directory that contains the definition of the module. ModuleDir() string + + // ModuleType returns the name of the module type that was used to create the module, as specified in + // RegisterModuleType. ModuleType() string + + // BlueprintFile returns the name of the blueprint file that contains the definition of this + // module. BlueprintsFile() string + // ContainsProperty returns true if the specified property name was set in the module definition. ContainsProperty(name string) bool + + // Errorf reports an error at the specified position of the module definition file. Errorf(pos scanner.Position, fmt string, args ...interface{}) + + // ModuleErrorf reports an error at the line number of the module type in the module definition. ModuleErrorf(fmt string, args ...interface{}) + + // PropertyErrorf reports an error at the line number of a property in the module definition. PropertyErrorf(property, fmt string, args ...interface{}) + + // Failed returns true if any errors have been reported. In most cases the module can continue with generating + // build rules after an error, allowing it to report additional errors in a single run, but in cases where the error + // has prevented the module from creating necessary data it can return early when Failed returns true. Failed() bool + // AddNinjaFileDeps adds dependencies on the specified files to the rule that creates the ninja manifest. The + // primary builder will be rerun whenever the specified files are modified. AddNinjaFileDeps(deps ...string) DeviceSpecific() bool @@ -98,6 +124,8 @@ type EarlyModuleContext interface { IsSymlink(path Path) bool Readlink(path Path) string + // Namespace returns the Namespace object provided by the NameInterface set by Context.SetNameInterface, or the + // default SimpleNameInterface if Context.SetNameInterface was not called. Namespace() *Namespace } @@ -110,33 +138,156 @@ type BaseModuleContext interface { blueprintBaseModuleContext() blueprint.BaseModuleContext + // OtherModuleName returns the name of another Module. See BaseModuleContext.ModuleName for more information. + // It is intended for use inside the visit functions of Visit* and WalkDeps. OtherModuleName(m blueprint.Module) string + + // OtherModuleDir returns the directory of another Module. See BaseModuleContext.ModuleDir for more information. + // It is intended for use inside the visit functions of Visit* and WalkDeps. OtherModuleDir(m blueprint.Module) string + + // OtherModuleErrorf reports an error on another Module. See BaseModuleContext.ModuleErrorf for more information. + // It is intended for use inside the visit functions of Visit* and WalkDeps. OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) + + // OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency + // on the module. When called inside a Visit* method with current module being visited, and there are multiple + // dependencies on the module being visited, it returns the dependency tag used for the current dependency. OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag + + // OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface + // passed to Context.SetNameInterface, or SimpleNameInterface if it was not called. OtherModuleExists(name string) bool + + // OtherModuleDependencyVariantExists returns true if a module with the + // specified name and variant exists. The variant must match the given + // variations. It must also match all the non-local variations of the current + // module. In other words, it checks for the module AddVariationDependencies + // would add a dependency on with the same arguments. OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool + + // OtherModuleReverseDependencyVariantExists returns true if a module with the + // specified name exists with the same variations as the current module. In + // other words, it checks for the module AddReverseDependency would add a + // dependency on with the same argument. OtherModuleReverseDependencyVariantExists(name string) bool + + // OtherModuleType returns the type of another Module. See BaseModuleContext.ModuleType for more information. + // It is intended for use inside the visit functions of Visit* and WalkDeps. OtherModuleType(m blueprint.Module) string + // OtherModuleProvider returns the value for a provider for the given module. If the value is + // not set it returns the zero value of the type of the provider, so the return value can always + // be type asserted to the type of the provider. The value returned may be a deep copy of the + // value originally passed to SetProvider. + OtherModuleProvider(m blueprint.Module, provider blueprint.ProviderKey) interface{} + + // OtherModuleHasProvider returns true if the provider for the given module has been set. + OtherModuleHasProvider(m blueprint.Module, provider blueprint.ProviderKey) bool + + // Provider returns the value for a provider for the current module. If the value is + // not set it returns the zero value of the type of the provider, so the return value can always + // be type asserted to the type of the provider. It panics if called before the appropriate + // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep + // copy of the value originally passed to SetProvider. + Provider(provider blueprint.ProviderKey) interface{} + + // HasProvider returns true if the provider for the current module has been set. + HasProvider(provider blueprint.ProviderKey) bool + + // SetProvider sets the value for a provider for the current module. It panics if not called + // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value + // is not of the appropriate type, or if the value has already been set. The value should not + // be modified after being passed to SetProvider. + SetProvider(provider blueprint.ProviderKey, value interface{}) + GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module + + // GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if + // none exists. It panics if the dependency does not have the specified tag. It skips any + // dependencies that are not an android.Module. GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module + + // GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified + // name, or nil if none exists. If there are multiple dependencies on the same module it returns + // the first DependencyTag. It skips any dependencies that are not an android.Module. GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) + // VisitDirectDepsBlueprint calls visit for each direct dependency. If there are multiple + // direct dependencies on the same module visit will be called multiple times on that module + // and OtherModuleDependencyTag will return a different tag for each. + // + // The Module passed to the visit function should not be retained outside of the visit + // function, it may be invalidated by future mutators. VisitDirectDepsBlueprint(visit func(blueprint.Module)) + + // VisitDirectDeps calls visit for each direct dependency. If there are multiple + // direct dependencies on the same module visit will be called multiple times on that module + // and OtherModuleDependencyTag will return a different tag for each. It skips any + // dependencies that are not an android.Module. + // + // The Module passed to the visit function should not be retained outside of the visit + // function, it may be invalidated by future mutators. VisitDirectDeps(visit func(Module)) + VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) + + // VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit. If there are + // multiple direct dependencies on the same module pred and visit will be called multiple times on that module and + // OtherModuleDependencyTag will return a different tag for each. It skips any + // dependencies that are not an android.Module. + // + // The Module passed to the visit function should not be retained outside of the visit function, it may be + // invalidated by future mutators. VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module VisitDepsDepthFirst(visit func(Module)) // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) + + // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may + // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the + // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited + // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips + // any dependencies that are not an android.Module. + // + // The Modules passed to the visit function should not be retained outside of the visit function, they may be + // invalidated by future mutators. WalkDeps(visit func(Module, Module) bool) + + // WalkDepsBlueprint calls visit for each transitive dependency, traversing the dependency + // tree in top down order. visit may be called multiple times for the same (child, parent) + // pair if there are multiple direct dependencies between the child and parent with different + // tags. OtherModuleDependencyTag will return the tag for the currently visited + // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down + // to child. + // + // The Modules passed to the visit function should not be retained outside of the visit function, they may be + // invalidated by future mutators. WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) + // GetWalkPath is supposed to be called in visit function passed in WalkDeps() // and returns a top-down dependency path from a start module to current child module. GetWalkPath() []Module + // PrimaryModule returns the first variant of the current module. Variants of a module are always visited in + // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the + // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are + // only done once for all variants of a module. + PrimaryModule() Module + + // FinalModule returns the last variant of the current module. Variants of a module are always visited in + // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all + // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform + // singleton actions that are only done once for all variants of a module. + FinalModule() Module + + // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always + // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read + // from all variants if the current module == FinalModule(). Otherwise, care must be taken to not access any + // data modified by the current mutator. + VisitAllModuleVariants(visit func(Module)) + // GetTagPath is supposed to be called in visit function passed in WalkDeps() // and returns a top-down dependency tags path from a start module to current child module. // It has one less entry than GetWalkPath() as it contains the dependency tags that @@ -216,10 +367,8 @@ type ModuleContext interface { // additional dependencies. Phony(phony string, deps ...Path) - PrimaryModule() Module - FinalModule() Module - VisitAllModuleVariants(visit func(Module)) - + // GetMissingDependencies returns the list of dependencies that were passed to AddDependencies or related methods, + // but do not exist. GetMissingDependencies() []string } @@ -417,7 +566,7 @@ type commonProperties struct { // control whether this module compiles for 32-bit, 64-bit, or both. Possible values // are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both // architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit - // platform + // platform). Compile_multilib *string `android:"arch_variant"` Target struct { @@ -476,7 +625,7 @@ type commonProperties struct { Native_bridge_supported *bool `android:"arch_variant"` // init.rc files to be installed if this module is installed - Init_rc []string `android:"path"` + Init_rc []string `android:"arch_variant,path"` // VINTF manifest fragments to be installed if this module is installed Vintf_fragments []string `android:"path"` @@ -799,7 +948,7 @@ type ModuleBase struct { initRcPaths Paths vintfFragmentsPaths Paths - prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool + prefer32 func(ctx BaseModuleContext, base *ModuleBase, os OsType) bool } func (m *ModuleBase) ComponentDepsMutator(BottomUpMutatorContext) {} @@ -826,7 +975,7 @@ func (m *ModuleBase) VariablesForTests() map[string]string { return m.variables } -func (m *ModuleBase) Prefer32(prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool) { +func (m *ModuleBase) Prefer32(prefer32 func(ctx BaseModuleContext, base *ModuleBase, os OsType) bool) { m.prefer32 = prefer32 } @@ -922,7 +1071,7 @@ func (m *ModuleBase) Os() OsType { } func (m *ModuleBase) Host() bool { - return m.Os().Class == Host || m.Os().Class == HostCross + return m.Os().Class == Host } func (m *ModuleBase) Device() bool { @@ -942,28 +1091,28 @@ func (m *ModuleBase) IsCommonOSVariant() bool { return m.commonProperties.CommonOSVariant } -func (m *ModuleBase) OsClassSupported() []OsClass { +func (m *ModuleBase) supportsTarget(target Target, config Config) bool { switch m.commonProperties.HostOrDeviceSupported { case HostSupported: - return []OsClass{Host, HostCross} + return target.Os.Class == Host case HostSupportedNoCross: - return []OsClass{Host} + return target.Os.Class == Host && !target.HostCross case DeviceSupported: - return []OsClass{Device} + return target.Os.Class == Device case HostAndDeviceSupported, HostAndDeviceDefault: - var supported []OsClass + supported := false if Bool(m.hostAndDeviceProperties.Host_supported) || (m.commonProperties.HostOrDeviceSupported == HostAndDeviceDefault && m.hostAndDeviceProperties.Host_supported == nil) { - supported = append(supported, Host, HostCross) + supported = supported || target.Os.Class == Host } if m.hostAndDeviceProperties.Device_supported == nil || *m.hostAndDeviceProperties.Device_supported { - supported = append(supported, Device) + supported = supported || target.Os.Class == Device } return supported default: - return nil + return false } } @@ -1557,6 +1706,21 @@ func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name strin func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string { return b.bp.OtherModuleType(m) } +func (b *baseModuleContext) OtherModuleProvider(m blueprint.Module, provider blueprint.ProviderKey) interface{} { + return b.bp.OtherModuleProvider(m, provider) +} +func (b *baseModuleContext) OtherModuleHasProvider(m blueprint.Module, provider blueprint.ProviderKey) bool { + return b.bp.OtherModuleHasProvider(m, provider) +} +func (b *baseModuleContext) Provider(provider blueprint.ProviderKey) interface{} { + return b.bp.Provider(provider) +} +func (b *baseModuleContext) HasProvider(provider blueprint.ProviderKey) bool { + return b.bp.HasProvider(provider) +} +func (b *baseModuleContext) SetProvider(provider blueprint.ProviderKey, value interface{}) { + b.bp.SetProvider(provider, value) +} func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module { return b.bp.GetDirectDepWithTag(name, tag) @@ -1877,6 +2041,20 @@ func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag { return b.tagPath } +func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) { + b.bp.VisitAllModuleVariants(func(module blueprint.Module) { + visit(module.(Module)) + }) +} + +func (b *baseModuleContext) PrimaryModule() Module { + return b.bp.PrimaryModule().(Module) +} + +func (b *baseModuleContext) FinalModule() Module { + return b.bp.FinalModule().(Module) +} + // A regexp for removing boilerplate from BaseDependencyTag from the string representation of // a dependency tag. var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`) @@ -1912,20 +2090,6 @@ func (b *baseModuleContext) GetPathString(skipFirst bool) string { return sb.String() } -func (m *moduleContext) VisitAllModuleVariants(visit func(Module)) { - m.bp.VisitAllModuleVariants(func(module blueprint.Module) { - visit(module.(Module)) - }) -} - -func (m *moduleContext) PrimaryModule() Module { - return m.bp.PrimaryModule().(Module) -} - -func (m *moduleContext) FinalModule() Module { - return m.bp.FinalModule().(Module) -} - func (m *moduleContext) ModuleSubDir() string { return m.bp.ModuleSubDir() } @@ -1951,7 +2115,7 @@ func (b *baseModuleContext) Os() OsType { } func (b *baseModuleContext) Host() bool { - return b.os.Class == Host || b.os.Class == HostCross + return b.os.Class == Host } func (b *baseModuleContext) Device() bool { @@ -2411,30 +2575,36 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) { } // Create (host|host-cross|target)-<OS> phony rules to build a reduced checkbuild. - osDeps := map[OsType]Paths{} + type osAndCross struct { + os OsType + hostCross bool + } + osDeps := map[osAndCross]Paths{} ctx.VisitAllModules(func(module Module) { if module.Enabled() { - os := module.Target().Os - osDeps[os] = append(osDeps[os], module.base().checkbuildFiles...) + key := osAndCross{os: module.Target().Os, hostCross: module.Target().HostCross} + osDeps[key] = append(osDeps[key], module.base().checkbuildFiles...) } }) osClass := make(map[string]Paths) - for os, deps := range osDeps { + for key, deps := range osDeps { var className string - switch os.Class { + switch key.os.Class { case Host: - className = "host" - case HostCross: - className = "host-cross" + if key.hostCross { + className = "host-cross" + } else { + className = "host" + } case Device: className = "target" default: continue } - name := className + "-" + os.Name + name := className + "-" + key.os.Name osClass[className] = append(osClass[className], PathForPhony(ctx, name)) ctx.Phony(name, deps...) diff --git a/android/mutator.go b/android/mutator.go index 521255328..7a104772f 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -179,15 +179,24 @@ func FinalDepsMutators(f RegisterMutatorFunc) { finalDeps = append(finalDeps, f) } -type TopDownMutator func(TopDownMutatorContext) - -type TopDownMutatorContext interface { +type BaseMutatorContext interface { BaseModuleContext + // MutatorName returns the name that this mutator was registered with. MutatorName() string + // Rename all variants of a module. The new name is not visible to calls to ModuleName, + // AddDependency or OtherModuleName until after this mutator pass is complete. Rename(name string) +} +type TopDownMutator func(TopDownMutatorContext) + +type TopDownMutatorContext interface { + BaseMutatorContext + + // CreateModule creates a new module by calling the factory method for the specified moduleType, and applies + // the specified property structs to it as if the properties were set in a blueprint file. CreateModule(ModuleFactory, ...interface{}) Module } @@ -199,25 +208,121 @@ type topDownMutatorContext struct { type BottomUpMutator func(BottomUpMutatorContext) type BottomUpMutatorContext interface { - BaseModuleContext + BaseMutatorContext - MutatorName() string - - Rename(name string) - - AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) + // AddDependency adds a dependency to the given module. It returns a slice of modules for each + // dependency (some entries may be nil). + // + // If the mutator is parallel (see MutatorHandle.Parallel), this method will pause until the + // new dependencies have had the current mutator called on them. If the mutator is not + // parallel this method does not affect the ordering of the current mutator pass, but will + // be ordered correctly for all future mutator passes. + AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) []blueprint.Module + + // AddReverseDependency adds a dependency from the destination to the given module. + // Does not affect the ordering of the current mutator pass, but will be ordered + // correctly for all future mutator passes. All reverse dependencies for a destination module are + // collected until the end of the mutator pass, sorted by name, and then appended to the destination + // module's dependency list. AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string) + + // CreateVariations splits a module into multiple variants, one for each name in the variationNames + // parameter. It returns a list of new modules in the same order as the variationNames + // list. + // + // If any of the dependencies of the module being operated on were already split + // by calling CreateVariations with the same name, the dependency will automatically + // be updated to point the matching variant. + // + // If a module is split, and then a module depending on the first module is not split + // when the Mutator is later called on it, the dependency of the depending module will + // automatically be updated to point to the first variant. CreateVariations(...string) []Module + + // CreateLocationVariations splits a module into multiple variants, one for each name in the variantNames + // parameter. It returns a list of new modules in the same order as the variantNames + // list. + // + // Local variations do not affect automatic dependency resolution - dependencies added + // to the split module via deps or DynamicDependerModule must exactly match a variant + // that contains all the non-local variations. CreateLocalVariations(...string) []Module + + // SetDependencyVariation sets all dangling dependencies on the current module to point to the variation + // with given name. This function ignores the default variation set by SetDefaultDependencyVariation. SetDependencyVariation(string) + + // SetDefaultDependencyVariation sets the default variation when a dangling reference is detected + // during the subsequent calls on Create*Variations* functions. To reset, set it to nil. SetDefaultDependencyVariation(*string) - AddVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string) - AddFarVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string) + + // AddVariationDependencies adds deps as dependencies of the current module, but uses the variations + // argument to select which variant of the dependency to use. It returns a slice of modules for + // each dependency (some entries may be nil). A variant of the dependency must exist that matches + // the all of the non-local variations of the current module, plus the variations argument. + // + // If the mutator is parallel (see MutatorHandle.Parallel), this method will pause until the + // new dependencies have had the current mutator called on them. If the mutator is not + // parallel this method does not affect the ordering of the current mutator pass, but will + // be ordered correctly for all future mutator passes. + AddVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string) []blueprint.Module + + // AddFarVariationDependencies adds deps as dependencies of the current module, but uses the + // variations argument to select which variant of the dependency to use. It returns a slice of + // modules for each dependency (some entries may be nil). A variant of the dependency must + // exist that matches the variations argument, but may also have other variations. + // For any unspecified variation the first variant will be used. + // + // Unlike AddVariationDependencies, the variations of the current module are ignored - the + // dependency only needs to match the supplied variations. + // + // If the mutator is parallel (see MutatorHandle.Parallel), this method will pause until the + // new dependencies have had the current mutator called on them. If the mutator is not + // parallel this method does not affect the ordering of the current mutator pass, but will + // be ordered correctly for all future mutator passes. + AddFarVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string) []blueprint.Module + + // AddInterVariantDependency adds a dependency between two variants of the same module. Variants are always + // ordered in the same orderas they were listed in CreateVariations, and AddInterVariantDependency does not change + // that ordering, but it associates a DependencyTag with the dependency and makes it visible to VisitDirectDeps, + // WalkDeps, etc. AddInterVariantDependency(tag blueprint.DependencyTag, from, to blueprint.Module) + + // ReplaceDependencies replaces all dependencies on the identical variant of the module with the + // specified name with the current variant of this module. Replacements don't take effect until + // after the mutator pass is finished. ReplaceDependencies(string) + + // ReplaceDependencies replaces all dependencies on the identical variant of the module with the + // specified name with the current variant of this module as long as the supplied predicate returns + // true. + // + // Replacements don't take effect until after the mutator pass is finished. ReplaceDependenciesIf(string, blueprint.ReplaceDependencyPredicate) + + // AliasVariation takes a variationName that was passed to CreateVariations for this module, + // and creates an alias from the current variant (before the mutator has run) to the new + // variant. The alias will be valid until the next time a mutator calls CreateVariations or + // CreateLocalVariations on this module without also calling AliasVariation. The alias can + // be used to add dependencies on the newly created variant using the variant map from + // before CreateVariations was run. AliasVariation(variationName string) + + // CreateAliasVariation takes a toVariationName that was passed to CreateVariations for this + // module, and creates an alias from a new fromVariationName variant the toVariationName + // variant. The alias will be valid until the next time a mutator calls CreateVariations or + // CreateLocalVariations on this module without also calling AliasVariation. The alias can + // be used to add dependencies on the toVariationName variant using the fromVariationName + // variant. CreateAliasVariation(fromVariationName, toVariationName string) + + // SetVariationProvider sets the value for a provider for the given newly created variant of + // the current module, i.e. one of the Modules returned by CreateVariations.. It panics if + // not called during the appropriate mutator or GenerateBuildActions pass for the provider, + // if the value is not of the appropriate type, or if the module is not a newly created + // variant of the current module. The value should not be modified after being passed to + // SetVariationProvider. + SetVariationProvider(module blueprint.Module, provider blueprint.ProviderKey, value interface{}) } type bottomUpMutatorContext struct { @@ -370,8 +475,8 @@ func (b *bottomUpMutatorContext) Rename(name string) { b.Module().base().commonProperties.DebugName = name } -func (b *bottomUpMutatorContext) AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) { - b.bp.AddDependency(module, tag, name...) +func (b *bottomUpMutatorContext) AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) []blueprint.Module { + return b.bp.AddDependency(module, tag, name...) } func (b *bottomUpMutatorContext) AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string) { @@ -423,15 +528,15 @@ func (b *bottomUpMutatorContext) SetDefaultDependencyVariation(variation *string } func (b *bottomUpMutatorContext) AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag, - names ...string) { + names ...string) []blueprint.Module { - b.bp.AddVariationDependencies(variations, tag, names...) + return b.bp.AddVariationDependencies(variations, tag, names...) } func (b *bottomUpMutatorContext) AddFarVariationDependencies(variations []blueprint.Variation, - tag blueprint.DependencyTag, names ...string) { + tag blueprint.DependencyTag, names ...string) []blueprint.Module { - b.bp.AddFarVariationDependencies(variations, tag, names...) + return b.bp.AddFarVariationDependencies(variations, tag, names...) } func (b *bottomUpMutatorContext) AddInterVariantDependency(tag blueprint.DependencyTag, from, to blueprint.Module) { @@ -453,3 +558,7 @@ func (b *bottomUpMutatorContext) AliasVariation(variationName string) { func (b *bottomUpMutatorContext) CreateAliasVariation(fromVariationName, toVariationName string) { b.bp.CreateAliasVariation(fromVariationName, toVariationName) } + +func (b *bottomUpMutatorContext) SetVariationProvider(module blueprint.Module, provider blueprint.ProviderKey, value interface{}) { + b.bp.SetVariationProvider(module, provider, value) +} diff --git a/android/prebuilt_build_tool.go b/android/prebuilt_build_tool.go index 1dcf1996b..e2555e4c3 100644 --- a/android/prebuilt_build_tool.go +++ b/android/prebuilt_build_tool.go @@ -14,6 +14,8 @@ package android +import "path/filepath" + func init() { RegisterModuleType("prebuilt_build_tool", prebuiltBuildToolFactory) } @@ -58,13 +60,18 @@ func (t *prebuiltBuildTool) GenerateAndroidBuildActions(ctx ModuleContext) { installedPath := PathForModuleOut(ctx, t.ModuleBase.Name()) deps := PathsForModuleSrc(ctx, t.properties.Deps) + var fromPath = sourcePath.String() + if !filepath.IsAbs(fromPath) { + fromPath = "$$PWD/" + fromPath + } + ctx.Build(pctx, BuildParams{ Rule: Symlink, Output: installedPath, Input: sourcePath, Implicits: deps, Args: map[string]string{ - "fromPath": "$$PWD/" + sourcePath.String(), + "fromPath": fromPath, }, }) diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go index 6c3cd9eef..854395e64 100644 --- a/android/prebuilt_test.go +++ b/android/prebuilt_test.go @@ -285,7 +285,7 @@ func TestPrebuilts(t *testing.T) { t.Errorf("windows is assumed to be disabled by default") } config.config.Targets[Windows] = []Target{ - {Windows, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", ""}, + {Windows, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", true}, } ctx := NewTestArchContext() diff --git a/android/sdk.go b/android/sdk.go index 9ea7ff49c..f2cdc880b 100644 --- a/android/sdk.go +++ b/android/sdk.go @@ -237,9 +237,25 @@ type BpPropertySet interface { // * string // * array of the above // * bool + // For these types it is an error if multiple properties with the same name + // are added. + // + // * pointer to a struct // * BpPropertySet // - // It is an error if multiple properties with the same name are added. + // A pointer to a Blueprint-style property struct is first converted into a + // BpPropertySet by traversing the fields and adding their values as + // properties in a BpPropertySet. A field with a struct value is itself + // converted into a BpPropertySet before adding. + // + // Adding a BpPropertySet is done as follows: + // * If no property with the name exists then the BpPropertySet is added + // directly to this property. Care must be taken to ensure that it does not + // introduce a cycle. + // * If a property exists with the name and the current value is a + // BpPropertySet then every property of the new BpPropertySet is added to + // the existing BpPropertySet. + // * Otherwise, if a property exists with the name then it is an error. AddProperty(name string, value interface{}) // Add a property with an associated tag diff --git a/android/singleton.go b/android/singleton.go index 2c51c6c48..9832378d5 100644 --- a/android/singleton.go +++ b/android/singleton.go @@ -29,6 +29,16 @@ type SingletonContext interface { ModuleType(module blueprint.Module) string BlueprintFile(module blueprint.Module) string + // ModuleProvider returns the value, if any, for the provider for a module. If the value for the + // provider was not set it returns the zero value of the type of the provider, which means the + // return value can always be type-asserted to the type of the provider. The return value should + // always be considered read-only. It panics if called before the appropriate mutator or + // GenerateBuildActions pass for the provider on the module. + ModuleProvider(module blueprint.Module, provider blueprint.ProviderKey) interface{} + + // ModuleHasProvider returns true if the provider for the given module has been set. + ModuleHasProvider(module blueprint.Module, provider blueprint.ProviderKey) bool + ModuleErrorf(module blueprint.Module, format string, args ...interface{}) Errorf(format string, args ...interface{}) Failed() bool diff --git a/android/variable.go b/android/variable.go index 53f081e8c..ce523ed90 100644 --- a/android/variable.go +++ b/android/variable.go @@ -365,12 +365,12 @@ func (v *productVariables) SetDefaultConfig() { *v = productVariables{ BuildNumberFile: stringPtr("build_number.txt"), - Platform_version_name: stringPtr("Q"), - Platform_sdk_version: intPtr(28), - Platform_sdk_codename: stringPtr("Q"), + Platform_version_name: stringPtr("S"), + Platform_sdk_version: intPtr(30), + Platform_sdk_codename: stringPtr("S"), Platform_sdk_final: boolPtr(false), - Platform_version_active_codenames: []string{"Q"}, - Platform_vndk_version: stringPtr("Q"), + Platform_version_active_codenames: []string{"S"}, + Platform_vndk_version: stringPtr("S"), HostArch: stringPtr("x86_64"), HostSecondaryArch: stringPtr("x86"), diff --git a/android/visibility.go b/android/visibility.go index 68da1c475..51d561120 100644 --- a/android/visibility.go +++ b/android/visibility.go @@ -17,6 +17,7 @@ package android import ( "fmt" "regexp" + "sort" "strings" "sync" @@ -441,12 +442,19 @@ func visibilityRuleEnforcer(ctx TopDownMutatorContext) { } rule := effectiveVisibilityRules(ctx.Config(), depQualified) - if rule != nil && !rule.matches(qualified) { + if !rule.matches(qualified) { ctx.ModuleErrorf("depends on %s which is not visible to this module", depQualified) } }) } +// Default visibility is public. +var defaultVisibility = compositeRule{publicRule{}} + +// Return the effective visibility rules. +// +// If no rules have been specified this will return the default visibility rule +// which is currently //visibility:public. func effectiveVisibilityRules(config Config, qualified qualifiedModuleName) compositeRule { moduleToVisibilityRule := moduleToVisibilityRuleMap(config) value, ok := moduleToVisibilityRule.Load(qualified) @@ -456,6 +464,12 @@ func effectiveVisibilityRules(config Config, qualified qualifiedModuleName) comp } else { rule = packageDefaultVisibility(config, qualified) } + + // If no rule is specified then return the default visibility rule to avoid + // every caller having to treat nil as public. + if rule == nil { + rule = defaultVisibility + } return rule } @@ -483,13 +497,63 @@ func packageDefaultVisibility(config Config, moduleId qualifiedModuleName) compo } } +type VisibilityRuleSet interface { + // Widen the visibility with some extra rules. + Widen(extra []string) error + + Strings() []string +} + +type visibilityRuleSet struct { + rules []string +} + +var _ VisibilityRuleSet = (*visibilityRuleSet)(nil) + +func (v *visibilityRuleSet) Widen(extra []string) error { + // Check the extra rules first just in case they are invalid. Otherwise, if + // the current visibility is public then the extra rules will just be ignored. + if len(extra) == 1 { + singularRule := extra[0] + switch singularRule { + case "//visibility:public": + // Public overrides everything so just discard any existing rules. + v.rules = extra + return nil + case "//visibility:private": + // Extending rule with private is an error. + return fmt.Errorf("%q does not widen the visibility", singularRule) + } + } + + if len(v.rules) == 1 { + switch v.rules[0] { + case "//visibility:public": + // No point in adding rules to something which is already public. + return nil + case "//visibility:private": + // Adding any rules to private means it is no longer private so the + // private can be discarded. + v.rules = nil + } + } + + v.rules = FirstUniqueStrings(append(v.rules, extra...)) + sort.Strings(v.rules) + return nil +} + +func (v *visibilityRuleSet) Strings() []string { + return v.rules +} + // Get the effective visibility rules, i.e. the actual rules that affect the visibility of the // property irrespective of where they are defined. // // Includes visibility rules specified by package default_visibility and/or on defaults. // Short hand forms, e.g. //:__subpackages__ are replaced with their full form, e.g. // //package/containing/rule:__subpackages__. -func EffectiveVisibilityRules(ctx BaseModuleContext, module Module) []string { +func EffectiveVisibilityRules(ctx BaseModuleContext, module Module) VisibilityRuleSet { moduleName := ctx.OtherModuleName(module) dir := ctx.OtherModuleDir(module) qualified := qualifiedModuleName{dir, moduleName} @@ -499,7 +563,7 @@ func EffectiveVisibilityRules(ctx BaseModuleContext, module Module) []string { // Modules are implicitly visible to other modules in the same package, // without checking the visibility rules. Here we need to add that visibility // explicitly. - if rule != nil && !rule.matches(qualified) { + if !rule.matches(qualified) { if len(rule) == 1 { if _, ok := rule[0].(privateRule); ok { // If the rule is //visibility:private we can't append another @@ -508,13 +572,13 @@ func EffectiveVisibilityRules(ctx BaseModuleContext, module Module) []string { // modules are implicitly visible within the package we get the same // result without any rule at all, so just make it an empty list to be // appended below. - rule = compositeRule{} + rule = nil } } rule = append(rule, packageRule{dir}) } - return rule.Strings() + return &visibilityRuleSet{rule.Strings()} } // Clear the default visibility properties so they can be replaced. diff --git a/android/visibility_test.go b/android/visibility_test.go index ca0934557..9d9e57438 100644 --- a/android/visibility_test.go +++ b/android/visibility_test.go @@ -1270,3 +1270,49 @@ func newMockParentFactory() Module { }) return m } + +func testVisibilityRuleSet(t *testing.T, rules, extra, expected []string) { + t.Helper() + set := &visibilityRuleSet{rules} + err := set.Widen(extra) + if err != nil { + t.Error(err) + return + } + actual := set.Strings() + if !reflect.DeepEqual(actual, expected) { + t.Errorf("mismatching rules after extend: expected %#v, actual %#v", expected, actual) + } +} + +func TestVisibilityRuleSet(t *testing.T) { + t.Run("extend empty", func(t *testing.T) { + testVisibilityRuleSet(t, nil, []string{"//foo"}, []string{"//foo"}) + }) + t.Run("extend", func(t *testing.T) { + testVisibilityRuleSet(t, []string{"//foo"}, []string{"//bar"}, []string{"//bar", "//foo"}) + }) + t.Run("extend duplicate", func(t *testing.T) { + testVisibilityRuleSet(t, []string{"//foo"}, []string{"//bar", "//foo"}, []string{"//bar", "//foo"}) + }) + t.Run("extend public", func(t *testing.T) { + testVisibilityRuleSet(t, []string{"//visibility:public"}, []string{"//foo"}, []string{"//visibility:public"}) + }) + t.Run("extend private", func(t *testing.T) { + testVisibilityRuleSet(t, []string{"//visibility:private"}, []string{"//foo"}, []string{"//foo"}) + }) + t.Run("extend with public", func(t *testing.T) { + testVisibilityRuleSet(t, []string{"//foo"}, []string{"//visibility:public"}, []string{"//visibility:public"}) + }) + t.Run("extend with private", func(t *testing.T) { + t.Helper() + set := &visibilityRuleSet{[]string{"//foo"}} + err := set.Widen([]string{"//visibility:private"}) + expectedError := `"//visibility:private" does not widen the visibility` + if err == nil { + t.Errorf("missing error") + } else if err.Error() != expectedError { + t.Errorf("expected error %q found error %q", expectedError, err) + } + }) +} diff --git a/apex/OWNERS b/apex/OWNERS index a382ae810..793f3ed19 100644 --- a/apex/OWNERS +++ b/apex/OWNERS @@ -1 +1,4 @@ -per-file * = jiyong@google.com
\ No newline at end of file +per-file * = jiyong@google.com + +per-file allowed_deps.txt = set noparent +per-file allowed_deps.txt = dariofreni@google.com,hansson@google.com,harpin@google.com,jiyong@google.com,narayan@google.com,omakoto@google.com,jham@google.com diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt new file mode 100644 index 000000000..87e96eaa7 --- /dev/null +++ b/apex/allowed_deps.txt @@ -0,0 +1,521 @@ +# A list of allowed dependencies for all updatable modules. +# +# The list tracks all direct and transitive dependencies that end up within any +# of the updatable binaries; specifically excluding external dependencies +# required to compile those binaries. This prevents potential regressions in +# case a new dependency is not aware of the different functional and +# non-functional requirements being part of an updatable module, for example +# setting correct min_sdk_version. +# +# To update the list, run: +# repo-root$ build/soong/scripts/update-apex-allowed-deps.sh +# +# See go/apex-allowed-deps-error for more details. +# TODO(b/157465465): introduce automated quality signals and remove this list. + +adbd(minSdkVersion:(no version)) +android.hardware.cas.native@1.0(minSdkVersion:29) +android.hardware.cas@1.0(minSdkVersion:29) +android.hardware.common-ndk_platform(minSdkVersion:29) +android.hardware.graphics.allocator@2.0(minSdkVersion:29) +android.hardware.graphics.allocator@3.0(minSdkVersion:29) +android.hardware.graphics.allocator@4.0(minSdkVersion:29) +android.hardware.graphics.bufferqueue@1.0(minSdkVersion:29) +android.hardware.graphics.bufferqueue@2.0(minSdkVersion:29) +android.hardware.graphics.common-ndk_platform(minSdkVersion:29) +android.hardware.graphics.common@1.0(minSdkVersion:29) +android.hardware.graphics.common@1.1(minSdkVersion:29) +android.hardware.graphics.common@1.2(minSdkVersion:29) +android.hardware.graphics.mapper@2.0(minSdkVersion:29) +android.hardware.graphics.mapper@2.1(minSdkVersion:29) +android.hardware.graphics.mapper@3.0(minSdkVersion:29) +android.hardware.graphics.mapper@4.0(minSdkVersion:29) +android.hardware.media.bufferpool@2.0(minSdkVersion:29) +android.hardware.media.c2@1.0(minSdkVersion:29) +android.hardware.media.c2@1.1(minSdkVersion:29) +android.hardware.media.omx@1.0(minSdkVersion:29) +android.hardware.media@1.0(minSdkVersion:29) +android.hardware.neuralnetworks@1.0(minSdkVersion:30) +android.hardware.neuralnetworks@1.1(minSdkVersion:30) +android.hardware.neuralnetworks@1.2(minSdkVersion:30) +android.hardware.neuralnetworks@1.3(minSdkVersion:30) +android.hardware.tetheroffload.config-V1.0-java(minSdkVersion:current) +android.hardware.tetheroffload.control-V1.0-java(minSdkVersion:current) +android.hidl.allocator@1.0(minSdkVersion:29) +android.hidl.base-V1.0-java(minSdkVersion:current) +android.hidl.memory.token@1.0(minSdkVersion:29) +android.hidl.memory@1.0(minSdkVersion:29) +android.hidl.safe_union@1.0(minSdkVersion:29) +android.hidl.token@1.0(minSdkVersion:29) +android.hidl.token@1.0-utils(minSdkVersion:29) +android.net.ipsec.ike(minSdkVersion:current) +android.net.ipsec.ike.xml(minSdkVersion:(no version)) +androidx-constraintlayout_constraintlayout(minSdkVersion:14) +androidx-constraintlayout_constraintlayout-solver(minSdkVersion:24) +androidx.activity_activity(minSdkVersion:14) +androidx.activity_activity-ktx(minSdkVersion:14) +androidx.annotation_annotation(minSdkVersion:24) +androidx.annotation_annotation(minSdkVersion:current) +androidx.appcompat_appcompat(minSdkVersion:14) +androidx.appcompat_appcompat-resources(minSdkVersion:14) +androidx.arch.core_core-common(minSdkVersion:24) +androidx.arch.core_core-common(minSdkVersion:current) +androidx.arch.core_core-runtime(minSdkVersion:14) +androidx.asynclayoutinflater_asynclayoutinflater(minSdkVersion:14) +androidx.autofill_autofill(minSdkVersion:14) +androidx.cardview_cardview(minSdkVersion:14) +androidx.collection_collection(minSdkVersion:24) +androidx.collection_collection(minSdkVersion:current) +androidx.collection_collection-ktx(minSdkVersion:24) +androidx.coordinatorlayout_coordinatorlayout(minSdkVersion:14) +androidx.core_core(minSdkVersion:14) +androidx.core_core-ktx(minSdkVersion:14) +androidx.cursoradapter_cursoradapter(minSdkVersion:14) +androidx.customview_customview(minSdkVersion:14) +androidx.documentfile_documentfile(minSdkVersion:14) +androidx.drawerlayout_drawerlayout(minSdkVersion:14) +androidx.fragment_fragment(minSdkVersion:14) +androidx.fragment_fragment-ktx(minSdkVersion:14) +androidx.interpolator_interpolator(minSdkVersion:14) +androidx.leanback_leanback(minSdkVersion:17) +androidx.leanback_leanback-preference(minSdkVersion:21) +androidx.legacy_legacy-preference-v14(minSdkVersion:14) +androidx.legacy_legacy-support-core-ui(minSdkVersion:14) +androidx.legacy_legacy-support-core-utils(minSdkVersion:14) +androidx.legacy_legacy-support-v13(minSdkVersion:14) +androidx.legacy_legacy-support-v4(minSdkVersion:14) +androidx.lifecycle_lifecycle-common(minSdkVersion:24) +androidx.lifecycle_lifecycle-common(minSdkVersion:current) +androidx.lifecycle_lifecycle-common-java8(minSdkVersion:24) +androidx.lifecycle_lifecycle-extensions(minSdkVersion:14) +androidx.lifecycle_lifecycle-livedata(minSdkVersion:14) +androidx.lifecycle_lifecycle-livedata-core(minSdkVersion:14) +androidx.lifecycle_lifecycle-livedata-core-ktx(minSdkVersion:14) +androidx.lifecycle_lifecycle-process(minSdkVersion:14) +androidx.lifecycle_lifecycle-runtime(minSdkVersion:14) +androidx.lifecycle_lifecycle-runtime-ktx(minSdkVersion:14) +androidx.lifecycle_lifecycle-service(minSdkVersion:14) +androidx.lifecycle_lifecycle-viewmodel(minSdkVersion:14) +androidx.lifecycle_lifecycle-viewmodel-ktx(minSdkVersion:14) +androidx.lifecycle_lifecycle-viewmodel-savedstate(minSdkVersion:14) +androidx.loader_loader(minSdkVersion:14) +androidx.localbroadcastmanager_localbroadcastmanager(minSdkVersion:14) +androidx.media_media(minSdkVersion:14) +androidx.navigation_navigation-common(minSdkVersion:14) +androidx.navigation_navigation-common-ktx(minSdkVersion:14) +androidx.navigation_navigation-fragment(minSdkVersion:14) +androidx.navigation_navigation-fragment-ktx(minSdkVersion:14) +androidx.navigation_navigation-runtime(minSdkVersion:14) +androidx.navigation_navigation-runtime-ktx(minSdkVersion:14) +androidx.navigation_navigation-ui(minSdkVersion:14) +androidx.navigation_navigation-ui-ktx(minSdkVersion:14) +androidx.preference_preference(minSdkVersion:14) +androidx.print_print(minSdkVersion:14) +androidx.recyclerview_recyclerview(minSdkVersion:14) +androidx.recyclerview_recyclerview-selection(minSdkVersion:14) +androidx.savedstate_savedstate(minSdkVersion:14) +androidx.slidingpanelayout_slidingpanelayout(minSdkVersion:14) +androidx.swiperefreshlayout_swiperefreshlayout(minSdkVersion:14) +androidx.transition_transition(minSdkVersion:14) +androidx.vectordrawable_vectordrawable(minSdkVersion:14) +androidx.vectordrawable_vectordrawable-animated(minSdkVersion:14) +androidx.versionedparcelable_versionedparcelable(minSdkVersion:14) +androidx.viewpager_viewpager(minSdkVersion:14) +apache-commons-compress(minSdkVersion:current) +art.module.public.api.stubs(minSdkVersion:(no version)) +bcm_object(minSdkVersion:29) +boringssl_self_test(minSdkVersion:29) +bouncycastle_ike_digests(minSdkVersion:current) +brotli-java(minSdkVersion:current) +captiveportal-lib(minSdkVersion:29) +car-ui-lib(minSdkVersion:28) +CellBroadcastApp(minSdkVersion:29) +CellBroadcastServiceModule(minSdkVersion:29) +codecs_g711dec(minSdkVersion:29) +com.google.android.material_material(minSdkVersion:14) +conscrypt(minSdkVersion:29) +conscrypt.module.platform.api.stubs(minSdkVersion:(no version)) +conscrypt.module.public.api.stubs(minSdkVersion:(no version)) +core-lambda-stubs(minSdkVersion:(no version)) +core.current.stubs(minSdkVersion:(no version)) +crtbegin_dynamic(minSdkVersion:apex_inherit) +crtbegin_dynamic1(minSdkVersion:apex_inherit) +crtbegin_so(minSdkVersion:apex_inherit) +crtbegin_so1(minSdkVersion:apex_inherit) +crtbrand(minSdkVersion:apex_inherit) +crtend_android(minSdkVersion:apex_inherit) +crtend_so(minSdkVersion:apex_inherit) +datastallprotosnano(minSdkVersion:29) +derive_sdk(minSdkVersion:current) +derive_sdk_prefer32(minSdkVersion:current) +dnsresolver_aidl_interface-unstable-ndk_platform(minSdkVersion:29) +DocumentsUI-res-lib(minSdkVersion:29) +exoplayer2-extractor(minSdkVersion:16) +exoplayer2-extractor-annotation-stubs(minSdkVersion:16) +ExtServices(minSdkVersion:current) +ExtServices-core(minSdkVersion:current) +flatbuffer_headers(minSdkVersion:(no version)) +fmtlib(minSdkVersion:29) +framework-permission(minSdkVersion:current) +framework-sdkextensions(minSdkVersion:current) +framework-statsd(minSdkVersion:current) +framework-tethering(minSdkVersion:current) +gemmlowp_headers(minSdkVersion:(no version)) +GoogleCellBroadcastApp(minSdkVersion:29) +GoogleCellBroadcastServiceModule(minSdkVersion:29) +GoogleExtServices(minSdkVersion:current) +GooglePermissionController(minSdkVersion:28) +guava(minSdkVersion:current) +gwp_asan_headers(minSdkVersion:(no version)) +i18n.module.public.api.stubs(minSdkVersion:(no version)) +iconloader(minSdkVersion:21) +ike-internals(minSdkVersion:current) +InProcessTethering(minSdkVersion:current) +ipmemorystore-aidl-interfaces-java(minSdkVersion:29) +ipmemorystore-aidl-interfaces-unstable-java(minSdkVersion:29) +jni_headers(minSdkVersion:29) +jsr305(minSdkVersion:14) +kotlinx-coroutines-android(minSdkVersion:current) +kotlinx-coroutines-core(minSdkVersion:current) +legacy.art.module.platform.api.stubs(minSdkVersion:(no version)) +legacy.core.platform.api.stubs(minSdkVersion:(no version)) +legacy.i18n.module.platform.api.stubs(minSdkVersion:(no version)) +libaacextractor(minSdkVersion:29) +libadb_crypto(minSdkVersion:(no version)) +libadb_pairing_auth(minSdkVersion:(no version)) +libadb_pairing_connection(minSdkVersion:(no version)) +libadb_pairing_server(minSdkVersion:(no version)) +libadb_protos(minSdkVersion:(no version)) +libadb_tls_connection(minSdkVersion:(no version)) +libadbconnection_client(minSdkVersion:(no version)) +libadbconnection_server(minSdkVersion:(no version)) +libadbd(minSdkVersion:(no version)) +libadbd_core(minSdkVersion:(no version)) +libadbd_services(minSdkVersion:(no version)) +libamrextractor(minSdkVersion:29) +libapp_processes_protos_lite(minSdkVersion:(no version)) +libarect(minSdkVersion:29) +libasyncio(minSdkVersion:(no version)) +libatomic(minSdkVersion:(no version)) +libaudio_system_headers(minSdkVersion:29) +libaudioclient_headers(minSdkVersion:29) +libaudiofoundation_headers(minSdkVersion:29) +libaudioutils(minSdkVersion:29) +libaudioutils_fixedfft(minSdkVersion:29) +libavcdec(minSdkVersion:29) +libavcenc(minSdkVersion:29) +libavservices_minijail(minSdkVersion:29) +libbacktrace_headers(minSdkVersion:apex_inherit) +libbase(minSdkVersion:29) +libbase_headers(minSdkVersion:29) +libbinder_headers(minSdkVersion:29) +libbinderthreadstateutils(minSdkVersion:29) +libbluetooth-types-header(minSdkVersion:29) +libbrotli(minSdkVersion:(no version)) +libbuildversion(minSdkVersion:(no version)) +libc(minSdkVersion:(no version)) +libc++(minSdkVersion:apex_inherit) +libc++_static(minSdkVersion:apex_inherit) +libc++abi(minSdkVersion:apex_inherit) +libc++demangle(minSdkVersion:apex_inherit) +libc_headers(minSdkVersion:apex_inherit) +libc_headers_arch(minSdkVersion:apex_inherit) +libcap(minSdkVersion:29) +libcodec2(minSdkVersion:29) +libcodec2_headers(minSdkVersion:29) +libcodec2_hidl@1.0(minSdkVersion:29) +libcodec2_hidl@1.1(minSdkVersion:29) +libcodec2_internal(minSdkVersion:29) +libcodec2_soft_aacdec(minSdkVersion:29) +libcodec2_soft_aacenc(minSdkVersion:29) +libcodec2_soft_amrnbdec(minSdkVersion:29) +libcodec2_soft_amrnbenc(minSdkVersion:29) +libcodec2_soft_amrwbdec(minSdkVersion:29) +libcodec2_soft_amrwbenc(minSdkVersion:29) +libcodec2_soft_av1dec_gav1(minSdkVersion:29) +libcodec2_soft_avcdec(minSdkVersion:29) +libcodec2_soft_avcenc(minSdkVersion:29) +libcodec2_soft_common(minSdkVersion:29) +libcodec2_soft_flacdec(minSdkVersion:29) +libcodec2_soft_flacenc(minSdkVersion:29) +libcodec2_soft_g711alawdec(minSdkVersion:29) +libcodec2_soft_g711mlawdec(minSdkVersion:29) +libcodec2_soft_gsmdec(minSdkVersion:29) +libcodec2_soft_h263dec(minSdkVersion:29) +libcodec2_soft_h263enc(minSdkVersion:29) +libcodec2_soft_hevcdec(minSdkVersion:29) +libcodec2_soft_hevcenc(minSdkVersion:29) +libcodec2_soft_mp3dec(minSdkVersion:29) +libcodec2_soft_mpeg2dec(minSdkVersion:29) +libcodec2_soft_mpeg4dec(minSdkVersion:29) +libcodec2_soft_mpeg4enc(minSdkVersion:29) +libcodec2_soft_opusdec(minSdkVersion:29) +libcodec2_soft_opusenc(minSdkVersion:29) +libcodec2_soft_rawdec(minSdkVersion:29) +libcodec2_soft_vorbisdec(minSdkVersion:29) +libcodec2_soft_vp8dec(minSdkVersion:29) +libcodec2_soft_vp8enc(minSdkVersion:29) +libcodec2_soft_vp9dec(minSdkVersion:29) +libcodec2_soft_vp9enc(minSdkVersion:29) +libcodec2_vndk(minSdkVersion:29) +libcrypto(minSdkVersion:29) +libcrypto_static(minSdkVersion:(no version)) +libcrypto_utils(minSdkVersion:(no version)) +libcutils(minSdkVersion:29) +libcutils_headers(minSdkVersion:29) +libcutils_sockets(minSdkVersion:29) +libdiagnose_usb(minSdkVersion:(no version)) +libdl(minSdkVersion:(no version)) +libeigen(minSdkVersion:(no version)) +libfifo(minSdkVersion:29) +libFLAC(minSdkVersion:29) +libFLAC-config(minSdkVersion:29) +libFLAC-headers(minSdkVersion:29) +libflacextractor(minSdkVersion:29) +libfmq(minSdkVersion:29) +libFraunhoferAAC(minSdkVersion:29) +libgav1(minSdkVersion:29) +libgcc_stripped(minSdkVersion:(no version)) +libgralloctypes(minSdkVersion:29) +libgrallocusage(minSdkVersion:29) +libgsm(minSdkVersion:apex_inherit) +libgtest_prod(minSdkVersion:apex_inherit) +libgui_bufferqueue_static(minSdkVersion:29) +libgui_headers(minSdkVersion:29) +libhardware(minSdkVersion:29) +libhardware_headers(minSdkVersion:29) +libhevcdec(minSdkVersion:29) +libhevcenc(minSdkVersion:29) +libhidlbase(minSdkVersion:29) +libhidlmemory(minSdkVersion:29) +libhwbinder-impl-internal(minSdkVersion:29) +libion(minSdkVersion:29) +libjavacrypto(minSdkVersion:29) +libjsoncpp(minSdkVersion:29) +libLibGuiProperties(minSdkVersion:29) +liblog(minSdkVersion:(no version)) +liblog_headers(minSdkVersion:29) +liblua(minSdkVersion:(no version)) +liblz4(minSdkVersion:(no version)) +libm(minSdkVersion:(no version)) +libmath(minSdkVersion:29) +libmdnssd(minSdkVersion:(no version)) +libmedia_codecserviceregistrant(minSdkVersion:29) +libmedia_datasource_headers(minSdkVersion:29) +libmedia_headers(minSdkVersion:29) +libmedia_helper_headers(minSdkVersion:29) +libmedia_midiiowrapper(minSdkVersion:29) +libmidiextractor(minSdkVersion:29) +libminijail(minSdkVersion:29) +libminijail_gen_constants(minSdkVersion:(no version)) +libminijail_gen_constants_obj(minSdkVersion:29) +libminijail_gen_syscall(minSdkVersion:(no version)) +libminijail_gen_syscall_obj(minSdkVersion:29) +libminijail_generated(minSdkVersion:29) +libmkvextractor(minSdkVersion:29) +libmp3extractor(minSdkVersion:29) +libmp4extractor(minSdkVersion:29) +libmpeg2dec(minSdkVersion:29) +libmpeg2extractor(minSdkVersion:29) +libnativebase_headers(minSdkVersion:29) +libnativehelper_compat_libc++(minSdkVersion:(no version)) +libnativehelper_header_only(minSdkVersion:29) +libnativewindow_headers(minSdkVersion:29) +libnetd_resolv(minSdkVersion:29) +libnetdbinder_utils_headers(minSdkVersion:29) +libnetdutils(minSdkVersion:29) +libnetworkstackutilsjni(minSdkVersion:29) +libneuralnetworks(minSdkVersion:(no version)) +libneuralnetworks_common(minSdkVersion:(no version)) +libneuralnetworks_headers(minSdkVersion:(no version)) +liboggextractor(minSdkVersion:29) +libopus(minSdkVersion:29) +libprocessgroup(minSdkVersion:29) +libprocessgroup_headers(minSdkVersion:29) +libprocpartition(minSdkVersion:(no version)) +libprotobuf-cpp-lite(minSdkVersion:29) +libprotobuf-java-lite(minSdkVersion:current) +libprotobuf-java-nano(minSdkVersion:9) +libprotoutil(minSdkVersion:(no version)) +libqemu_pipe(minSdkVersion:(no version)) +libsfplugin_ccodec_utils(minSdkVersion:29) +libsonivoxwithoutjet(minSdkVersion:29) +libspeexresampler(minSdkVersion:29) +libssl(minSdkVersion:29) +libstagefright_amrnb_common(minSdkVersion:29) +libstagefright_amrnbdec(minSdkVersion:29) +libstagefright_amrnbenc(minSdkVersion:29) +libstagefright_amrwbdec(minSdkVersion:29) +libstagefright_amrwbenc(minSdkVersion:29) +libstagefright_bufferpool@2.0.1(minSdkVersion:29) +libstagefright_bufferqueue_helper(minSdkVersion:29) +libstagefright_enc_common(minSdkVersion:29) +libstagefright_esds(minSdkVersion:29) +libstagefright_flacdec(minSdkVersion:29) +libstagefright_foundation(minSdkVersion:29) +libstagefright_foundation_headers(minSdkVersion:29) +libstagefright_foundation_without_imemory(minSdkVersion:29) +libstagefright_headers(minSdkVersion:29) +libstagefright_id3(minSdkVersion:29) +libstagefright_m4vh263dec(minSdkVersion:29) +libstagefright_m4vh263enc(minSdkVersion:29) +libstagefright_metadatautils(minSdkVersion:29) +libstagefright_mp3dec(minSdkVersion:29) +libstagefright_mpeg2extractor(minSdkVersion:29) +libstagefright_mpeg2support_nocrypto(minSdkVersion:29) +libstats_jni(minSdkVersion:(no version)) +libstatslog_resolv(minSdkVersion:29) +libstatslog_statsd(minSdkVersion:(no version)) +libstatspull(minSdkVersion:(no version)) +libstatspush_compat(minSdkVersion:29) +libstatssocket(minSdkVersion:(no version)) +libstatssocket_headers(minSdkVersion:29) +libsystem_headers(minSdkVersion:apex_inherit) +libsysutils(minSdkVersion:apex_inherit) +libtetherutilsjni(minSdkVersion:current) +libtextclassifier(minSdkVersion:(no version)) +libtextclassifier-java(minSdkVersion:current) +libtextclassifier_hash_headers(minSdkVersion:(no version)) +libtextclassifier_hash_static(minSdkVersion:(no version)) +libtflite_kernel_utils(minSdkVersion:(no version)) +libtflite_static(minSdkVersion:(no version)) +libui(minSdkVersion:29) +libui_headers(minSdkVersion:29) +libunwind_llvm(minSdkVersion:apex_inherit) +libutf(minSdkVersion:(no version)) +libutils(minSdkVersion:apex_inherit) +libutils_headers(minSdkVersion:apex_inherit) +libvorbisidec(minSdkVersion:29) +libvpx(minSdkVersion:29) +libwatchdog(minSdkVersion:29) +libwavextractor(minSdkVersion:29) +libwebm(minSdkVersion:29) +libyuv(minSdkVersion:29) +libyuv_static(minSdkVersion:29) +libzstd(minSdkVersion:(no version)) +media_ndk_headers(minSdkVersion:29) +media_plugin_headers(minSdkVersion:29) +mediaswcodec(minSdkVersion:29) +metrics-constants-protos(minSdkVersion:29) +ndk_crtbegin_so.19(minSdkVersion:(no version)) +ndk_crtbegin_so.21(minSdkVersion:(no version)) +ndk_crtbegin_so.27(minSdkVersion:(no version)) +ndk_crtend_so.19(minSdkVersion:(no version)) +ndk_crtend_so.21(minSdkVersion:(no version)) +ndk_crtend_so.27(minSdkVersion:(no version)) +ndk_libc++_static(minSdkVersion:(no version)) +ndk_libc++abi(minSdkVersion:(no version)) +net-utils-framework-common(minSdkVersion:current) +netd_aidl_interface-unstable-java(minSdkVersion:29) +netd_event_listener_interface-ndk_platform(minSdkVersion:29) +netlink-client(minSdkVersion:29) +networkstack-aidl-interfaces-unstable-java(minSdkVersion:29) +networkstack-client(minSdkVersion:29) +NetworkStackApiStableDependencies(minSdkVersion:29) +NetworkStackApiStableLib(minSdkVersion:29) +networkstackprotos(minSdkVersion:29) +PermissionController(minSdkVersion:28) +permissioncontroller-statsd(minSdkVersion:current) +philox_random(minSdkVersion:(no version)) +philox_random_headers(minSdkVersion:(no version)) +prebuilt_androidx-constraintlayout_constraintlayout-nodeps(minSdkVersion:(no version)) +prebuilt_androidx-constraintlayout_constraintlayout-solver-nodeps(minSdkVersion:current) +prebuilt_androidx.activity_activity-ktx-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.activity_activity-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.annotation_annotation-nodeps(minSdkVersion:current) +prebuilt_androidx.appcompat_appcompat-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.appcompat_appcompat-resources-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.arch.core_core-common-nodeps(minSdkVersion:current) +prebuilt_androidx.arch.core_core-runtime-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.asynclayoutinflater_asynclayoutinflater-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.autofill_autofill-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.cardview_cardview-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.collection_collection-ktx-nodeps(minSdkVersion:current) +prebuilt_androidx.collection_collection-nodeps(minSdkVersion:current) +prebuilt_androidx.coordinatorlayout_coordinatorlayout-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.core_core-ktx-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.core_core-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.cursoradapter_cursoradapter-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.customview_customview-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.documentfile_documentfile-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.drawerlayout_drawerlayout-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.fragment_fragment-ktx-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.fragment_fragment-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.interpolator_interpolator-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.leanback_leanback-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.leanback_leanback-preference-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.legacy_legacy-support-core-ui-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.legacy_legacy-support-core-utils-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.legacy_legacy-support-v13-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.lifecycle_lifecycle-common-java8-nodeps(minSdkVersion:current) +prebuilt_androidx.lifecycle_lifecycle-common-nodeps(minSdkVersion:current) +prebuilt_androidx.lifecycle_lifecycle-extensions-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.lifecycle_lifecycle-livedata-core-ktx-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.lifecycle_lifecycle-livedata-core-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.lifecycle_lifecycle-livedata-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.lifecycle_lifecycle-process-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.lifecycle_lifecycle-runtime-ktx-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.lifecycle_lifecycle-runtime-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.lifecycle_lifecycle-service-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.lifecycle_lifecycle-viewmodel-ktx-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.lifecycle_lifecycle-viewmodel-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.lifecycle_lifecycle-viewmodel-savedstate-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.loader_loader-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.localbroadcastmanager_localbroadcastmanager-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.media_media-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.navigation_navigation-common-ktx-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.navigation_navigation-common-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.navigation_navigation-fragment-ktx-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.navigation_navigation-fragment-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.navigation_navigation-runtime-ktx-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.navigation_navigation-runtime-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.navigation_navigation-ui-ktx-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.navigation_navigation-ui-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.preference_preference-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.print_print-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.recyclerview_recyclerview-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.recyclerview_recyclerview-selection-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.savedstate_savedstate-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.slidingpanelayout_slidingpanelayout-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.swiperefreshlayout_swiperefreshlayout-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.transition_transition-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.vectordrawable_vectordrawable-animated-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.vectordrawable_vectordrawable-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.versionedparcelable_versionedparcelable-nodeps(minSdkVersion:(no version)) +prebuilt_androidx.viewpager_viewpager-nodeps(minSdkVersion:(no version)) +prebuilt_com.google.android.material_material-nodeps(minSdkVersion:(no version)) +prebuilt_error_prone_annotations(minSdkVersion:(no version)) +prebuilt_kotlin-stdlib(minSdkVersion:current) +prebuilt_kotlinx-coroutines-android-nodeps(minSdkVersion:(no version)) +prebuilt_kotlinx-coroutines-core-nodeps(minSdkVersion:(no version)) +prebuilt_libclang_rt.builtins-aarch64-android(minSdkVersion:(no version)) +prebuilt_libclang_rt.builtins-arm-android(minSdkVersion:(no version)) +prebuilt_libclang_rt.builtins-i686-android(minSdkVersion:(no version)) +prebuilt_libclang_rt.builtins-x86_64-android(minSdkVersion:(no version)) +prebuilt_test_framework-sdkextensions(minSdkVersion:(no version)) +server_configurable_flags(minSdkVersion:29) +service-permission(minSdkVersion:current) +service-statsd(minSdkVersion:current) +SettingsLibActionBarShadow(minSdkVersion:21) +SettingsLibAppPreference(minSdkVersion:21) +SettingsLibBarChartPreference(minSdkVersion:21) +SettingsLibHelpUtils(minSdkVersion:21) +SettingsLibLayoutPreference(minSdkVersion:21) +SettingsLibProgressBar(minSdkVersion:21) +SettingsLibRestrictedLockUtils(minSdkVersion:21) +SettingsLibSearchWidget(minSdkVersion:21) +SettingsLibSettingsTheme(minSdkVersion:21) +SettingsLibUtils(minSdkVersion:21) +stats_proto(minSdkVersion:29) +statsd(minSdkVersion:(no version)) +statsd-aidl-ndk_platform(minSdkVersion:(no version)) +statsprotos(minSdkVersion:29) +tensorflow_headers(minSdkVersion:(no version)) +Tethering(minSdkVersion:current) +TetheringApiCurrentLib(minSdkVersion:current) +TetheringGoogle(minSdkVersion:current) +textclassifier-statsd(minSdkVersion:current) +TextClassifierNotificationLibNoManifest(minSdkVersion:29) +TextClassifierServiceLibNoManifest(minSdkVersion:28) +updatable-media(minSdkVersion:29) +xz-java(minSdkVersion:current) diff --git a/apex/androidmk.go b/apex/androidmk.go index 1b53a672b..f76181d2d 100644 --- a/apex/androidmk.go +++ b/apex/androidmk.go @@ -135,7 +135,7 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo } } if len(newDataPaths) > 0 { - fmt.Fprintln(w, "LOCAL_TEST_DATA :=", strings.Join(cc.AndroidMkDataPaths(newDataPaths), " ")) + fmt.Fprintln(w, "LOCAL_TEST_DATA :=", strings.Join(android.AndroidMkDataPaths(newDataPaths), " ")) } if fi.module != nil && len(fi.module.NoticeFiles()) > 0 { @@ -157,13 +157,14 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo host := false switch fi.module.Target().Os.Class { case android.Host: - if fi.module.Target().Arch.ArchType != android.Common { - fmt.Fprintln(w, "LOCAL_MODULE_HOST_ARCH :=", archStr) - } - host = true - case android.HostCross: - if fi.module.Target().Arch.ArchType != android.Common { - fmt.Fprintln(w, "LOCAL_MODULE_HOST_CROSS_ARCH :=", archStr) + if fi.module.Target().HostCross { + if fi.module.Target().Arch.ArchType != android.Common { + fmt.Fprintln(w, "LOCAL_MODULE_HOST_CROSS_ARCH :=", archStr) + } + } else { + if fi.module.Target().Arch.ArchType != android.Common { + fmt.Fprintln(w, "LOCAL_MODULE_HOST_ARCH :=", archStr) + } } host = true case android.Device: diff --git a/apex/apex.go b/apex/apex.go index 8e35e07c0..0108c0f0d 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -565,7 +565,6 @@ func makeApexAvailableBaseline() map[string][]string { "libdebuggerd_handler_fallback", "libdexfile_external_headers", "libdexfile_support", - "libdexfile_support_static", "libdl_static", "libjemalloc5", "liblinker_main", @@ -795,7 +794,7 @@ func apexDepsMutator(mctx android.TopDownMutatorContext) { } apexInfo := android.ApexInfo{ ApexVariationName: mctx.ModuleName(), - MinSdkVersion: a.minSdkVersion(mctx), + MinSdkVersionStr: a.minSdkVersion(mctx).String(), RequiredSdks: a.RequiredSdks(), Updatable: a.Updatable(), InApexes: []string{mctx.ModuleName()}, @@ -1499,6 +1498,12 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) { } } for i, target := range targets { + if target.HostCross { + // Don't include artifats for the host cross targets because there is no way + // for us to run those artifacts natively on host + continue + } + // When multilib.* is omitted for native_shared_libs/jni_libs/tests, it implies // multilib.both addDependenciesForNativeModules(ctx, @@ -1952,27 +1957,21 @@ func (a *apexBundle) WalkPayloadDeps(ctx android.ModuleContext, do android.Paylo }) } -func (a *apexBundle) minSdkVersion(ctx android.BaseModuleContext) int { +func (a *apexBundle) minSdkVersion(ctx android.BaseModuleContext) android.ApiLevel { ver := proptools.String(a.properties.Min_sdk_version) if ver == "" { return android.FutureApiLevel } - // Treat the current codenames as "current", which means future API version (10000) - // Otherwise, ApiStrToNum converts codename(non-finalized) to a value from [9000...] - // and would fail to build against "current". - if android.InList(ver, ctx.Config().PlatformVersionActiveCodenames()) { - return android.FutureApiLevel - } - // In "REL" branch, "current" is mapped to finalized sdk version - if ctx.Config().PlatformSdkCodename() == "REL" && ver == "current" { - return ctx.Config().PlatformSdkVersionInt() - } - // Finalized codenames are OKAY and will be converted to int - intVer, err := android.ApiStrToNum(ctx, ver) + apiLevel, err := android.ApiLevelFromUser(ctx, ver) if err != nil { ctx.PropertyErrorf("min_sdk_version", "%s", err.Error()) + return android.NoneApiLevel + } + if apiLevel.IsPreview() { + // All codenames should build against "current". + return android.FutureApiLevel } - return intVer + return apiLevel } func (a *apexBundle) Updatable() bool { @@ -2046,7 +2045,9 @@ func (a *apexBundle) checkMinSdkVersion(ctx android.ModuleContext) { if proptools.Bool(a.properties.Use_vendor) && ctx.DeviceConfig().VndkVersion() == "" { return } - android.CheckMinSdkVersion(a, ctx, a.minSdkVersion(ctx)) + // apexBundle::minSdkVersion reports its own errors. + minSdkVersion := a.minSdkVersion(ctx) + android.CheckMinSdkVersion(a, ctx, minSdkVersion) } // Ensures that a lib providing stub isn't statically linked diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go index 83a56a2b5..afb739cef 100644 --- a/apex/apex_singleton.go +++ b/apex/apex_singleton.go @@ -17,9 +17,9 @@ package apex import ( - "github.com/google/blueprint" - "android/soong/android" + + "github.com/google/blueprint" ) func init() { @@ -27,39 +27,79 @@ func init() { } type apexDepsInfoSingleton struct { - // Output file with all flatlists from updatable modules' deps-info combined - updatableFlatListsPath android.OutputPath + allowedApexDepsInfoCheckResult android.OutputPath } func apexDepsInfoSingletonFactory() android.Singleton { return &apexDepsInfoSingleton{} } -var combineFilesRule = pctx.AndroidStaticRule("combineFilesRule", - blueprint.RuleParams{ - Command: "cat $out.rsp | xargs cat > $out", +var ( + // Generate new apex allowed_deps.txt by merging all internal dependencies. + generateApexDepsInfoFilesRule = pctx.AndroidStaticRule("generateApexDepsInfoFilesRule", blueprint.RuleParams{ + Command: "cat $out.rsp | xargs cat" + + // Only track non-external dependencies, i.e. those that end up in the binary + " | grep -v '(external)'" + + // Ignore comments in any of the files + " | grep -v '^#'" + + " | sort -u -f >$out", Rspfile: "$out.rsp", RspfileContent: "$in", - }, + }) + + // Diff two given lists while ignoring comments in the allowed deps file. + diffAllowedApexDepsInfoRule = pctx.AndroidStaticRule("diffAllowedApexDepsInfoRule", blueprint.RuleParams{ + Description: "Diff ${allowed_deps} and ${new_allowed_deps}", + Command: ` + if grep -v '^#' ${allowed_deps} | diff -B - ${new_allowed_deps}; then + touch ${out}; + else + echo -e "\n******************************"; + echo "ERROR: go/apex-allowed-deps-error"; + echo "******************************"; + echo "Detected changes to allowed dependencies in updatable modules."; + echo "To fix and update build/soong/apex/allowed_deps.txt, please run:"; + echo "$$ (croot && build/soong/scripts/update-apex-allowed-deps.sh)"; + echo "Members of mainline-modularization@google.com will review the changes."; + echo -e "******************************\n"; + exit 1; + fi; + `, + }, "allowed_deps", "new_allowed_deps") ) func (s *apexDepsInfoSingleton) GenerateBuildActions(ctx android.SingletonContext) { updatableFlatLists := android.Paths{} ctx.VisitAllModules(func(module android.Module) { if binaryInfo, ok := module.(android.ApexBundleDepsInfoIntf); ok { - if path := binaryInfo.FlatListPath(); path != nil { - if binaryInfo.Updatable() { - updatableFlatLists = append(updatableFlatLists, path) - } + if path := binaryInfo.FlatListPath(); path != nil && binaryInfo.Updatable() { + updatableFlatLists = append(updatableFlatLists, path) } } }) - s.updatableFlatListsPath = android.PathForOutput(ctx, "apex", "depsinfo", "updatable-flatlists.txt") + allowedDeps := android.ExistentPathForSource(ctx, "build/soong/apex/allowed_deps.txt").Path() + + newAllowedDeps := android.PathForOutput(ctx, "apex", "depsinfo", "new-allowed-deps.txt") + ctx.Build(pctx, android.BuildParams{ + Rule: generateApexDepsInfoFilesRule, + Inputs: append(updatableFlatLists, allowedDeps), + Output: newAllowedDeps, + }) + + s.allowedApexDepsInfoCheckResult = android.PathForOutput(ctx, newAllowedDeps.Rel()+".check") ctx.Build(pctx, android.BuildParams{ - Rule: combineFilesRule, - Description: "Generate " + s.updatableFlatListsPath.String(), - Inputs: updatableFlatLists, - Output: s.updatableFlatListsPath, + Rule: diffAllowedApexDepsInfoRule, + Input: newAllowedDeps, + Output: s.allowedApexDepsInfoCheckResult, + Args: map[string]string{ + "allowed_deps": allowedDeps.String(), + "new_allowed_deps": newAllowedDeps.String(), + }, }) } + +func (s *apexDepsInfoSingleton) MakeVars(ctx android.MakeVarsContext) { + // Export check result to Make. The path is added to droidcore. + ctx.Strict("APEX_ALLOWED_DEPS_CHECK", s.allowedApexDepsInfoCheckResult.String()) +} diff --git a/apex/apex_test.go b/apex/apex_test.go index 610f66750..71c4aa268 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -207,7 +207,7 @@ func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*andr config.TestProductVariables.CertificateOverrides = []string{"myapex_keytest:myapex.certificate.override"} config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("Q") config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(false) - config.TestProductVariables.Platform_version_active_codenames = []string{"R"} + config.TestProductVariables.Platform_version_active_codenames = []string{"Q"} config.TestProductVariables.Platform_vndk_version = proptools.StringPtr("VER") for _, handler := range handlers { @@ -584,18 +584,18 @@ func TestBasicApex(t *testing.T) { ensureListContains(t, noticeInputs, "custom_notice_for_static_lib") fullDepsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("depsinfo/fulllist.txt").Args["content"], "\\n") - ensureListContains(t, fullDepsInfo, "myjar(minSdkVersion:(no version)) <- myapex") - ensureListContains(t, fullDepsInfo, "mylib(minSdkVersion:(no version)) <- myapex") - ensureListContains(t, fullDepsInfo, "mylib2(minSdkVersion:(no version)) <- mylib") - ensureListContains(t, fullDepsInfo, "myotherjar(minSdkVersion:(no version)) <- myjar") - ensureListContains(t, fullDepsInfo, "mysharedjar(minSdkVersion:(no version)) (external) <- myjar") + ensureListContains(t, fullDepsInfo, " myjar(minSdkVersion:(no version)) <- myapex") + ensureListContains(t, fullDepsInfo, " mylib(minSdkVersion:(no version)) <- myapex") + ensureListContains(t, fullDepsInfo, " mylib2(minSdkVersion:(no version)) <- mylib") + ensureListContains(t, fullDepsInfo, " myotherjar(minSdkVersion:(no version)) <- myjar") + ensureListContains(t, fullDepsInfo, " mysharedjar(minSdkVersion:(no version)) (external) <- myjar") flatDepsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("depsinfo/flatlist.txt").Args["content"], "\\n") - ensureListContains(t, flatDepsInfo, " myjar(minSdkVersion:(no version))") - ensureListContains(t, flatDepsInfo, " mylib(minSdkVersion:(no version))") - ensureListContains(t, flatDepsInfo, " mylib2(minSdkVersion:(no version))") - ensureListContains(t, flatDepsInfo, " myotherjar(minSdkVersion:(no version))") - ensureListContains(t, flatDepsInfo, " mysharedjar(minSdkVersion:(no version)) (external)") + ensureListContains(t, flatDepsInfo, "myjar(minSdkVersion:(no version))") + ensureListContains(t, flatDepsInfo, "mylib(minSdkVersion:(no version))") + ensureListContains(t, flatDepsInfo, "mylib2(minSdkVersion:(no version))") + ensureListContains(t, flatDepsInfo, "myotherjar(minSdkVersion:(no version))") + ensureListContains(t, flatDepsInfo, "mysharedjar(minSdkVersion:(no version)) (external)") } func TestDefaults(t *testing.T) { @@ -836,6 +836,105 @@ func TestApexWithStubs(t *testing.T) { }) } +func TestApexWithStubsWithMinSdkVersion(t *testing.T) { + t.Parallel() + ctx, _ := testApex(t, ` + apex { + name: "myapex", + key: "myapex.key", + native_shared_libs: ["mylib", "mylib3"], + min_sdk_version: "29", + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + cc_library { + name: "mylib", + srcs: ["mylib.cpp"], + shared_libs: ["mylib2", "mylib3"], + system_shared_libs: [], + stl: "none", + apex_available: [ "myapex" ], + min_sdk_version: "28", + } + + cc_library { + name: "mylib2", + srcs: ["mylib.cpp"], + cflags: ["-include mylib.h"], + system_shared_libs: [], + stl: "none", + stubs: { + versions: ["28", "29", "30", "current"], + }, + min_sdk_version: "28", + } + + cc_library { + name: "mylib3", + srcs: ["mylib.cpp"], + shared_libs: ["mylib4"], + system_shared_libs: [], + stl: "none", + stubs: { + versions: ["28", "29", "30", "current"], + }, + apex_available: [ "myapex" ], + min_sdk_version: "28", + } + + cc_library { + name: "mylib4", + srcs: ["mylib.cpp"], + system_shared_libs: [], + stl: "none", + apex_available: [ "myapex" ], + min_sdk_version: "28", + } + `) + + apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule") + copyCmds := apexRule.Args["copy_commands"] + + // Ensure that direct non-stubs dep is always included + ensureContains(t, copyCmds, "image.apex/lib64/mylib.so") + + // Ensure that indirect stubs dep is not included + ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so") + + // Ensure that direct stubs dep is included + ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so") + + mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex29").Rule("ld").Args["libFlags"] + + // Ensure that mylib is linking with the version 29 stubs for mylib2 + ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_29/mylib2.so") + // ... and not linking to the non-stub (impl) variant of mylib2 + ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so") + + // Ensure that mylib is linking with the non-stub (impl) of mylib3 (because mylib3 is in the same apex) + ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_apex29/mylib3.so") + // .. and not linking to the stubs variant of mylib3 + ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_29/mylib3.so") + + // Ensure that stubs libs are built without -include flags + mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"] + ensureNotContains(t, mylib2Cflags, "-include ") + + // Ensure that genstub is invoked with --apex + ensureContains(t, "--apex", ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_29").Rule("genStubSrc").Args["flags"]) + + ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{ + "lib64/mylib.so", + "lib64/mylib3.so", + "lib64/mylib4.so", + }) +} + func TestApexWithExplicitStubsDependency(t *testing.T) { ctx, _ := testApex(t, ` apex { @@ -913,14 +1012,14 @@ func TestApexWithExplicitStubsDependency(t *testing.T) { ensureNotContains(t, libFooStubsLdFlags, "libbar.so") fullDepsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("depsinfo/fulllist.txt").Args["content"], "\\n") - ensureListContains(t, fullDepsInfo, "mylib(minSdkVersion:(no version)) <- myapex2") - ensureListContains(t, fullDepsInfo, "libbaz(minSdkVersion:(no version)) <- mylib") - ensureListContains(t, fullDepsInfo, "libfoo(minSdkVersion:(no version)) (external) <- mylib") + ensureListContains(t, fullDepsInfo, " mylib(minSdkVersion:(no version)) <- myapex2") + ensureListContains(t, fullDepsInfo, " libbaz(minSdkVersion:(no version)) <- mylib") + ensureListContains(t, fullDepsInfo, " libfoo(minSdkVersion:(no version)) (external) <- mylib") flatDepsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("depsinfo/flatlist.txt").Args["content"], "\\n") - ensureListContains(t, flatDepsInfo, " mylib(minSdkVersion:(no version))") - ensureListContains(t, flatDepsInfo, " libbaz(minSdkVersion:(no version))") - ensureListContains(t, flatDepsInfo, " libfoo(minSdkVersion:(no version)) (external)") + ensureListContains(t, flatDepsInfo, "mylib(minSdkVersion:(no version))") + ensureListContains(t, flatDepsInfo, "libbaz(minSdkVersion:(no version))") + ensureListContains(t, flatDepsInfo, "libfoo(minSdkVersion:(no version)) (external)") } func TestApexWithRuntimeLibsDependency(t *testing.T) { @@ -1425,13 +1524,7 @@ func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) { ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"] ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so") } - // 9000 is quite a magic number. - // Finalized SDK codenames are mapped as P(28), Q(29), ... - // And, codenames which are not finalized yet(active_codenames + future_codenames) are numbered from 9000, 9001, ... - // to distinguish them from finalized and future_api(10000) - // In this test, "R" is assumed not finalized yet( listed in Platform_version_active_codenames) and translated into 9000 - // (refer android/api_levels.go) - expectLink("libx", "shared_apex10000", "libz", "shared_9000") + expectLink("libx", "shared_apex10000", "libz", "shared_R") expectNoLink("libx", "shared_apex10000", "libz", "shared_29") expectNoLink("libx", "shared_apex10000", "libz", "shared") } @@ -2282,30 +2375,40 @@ func TestVendorApex_use_vndk_as_stable(t *testing.T) { ensureListContains(t, requireNativeLibs, ":vndk") } -func TestVendorApex_withPrebuiltFirmware(t *testing.T) { - ctx, _ := testApex(t, ` - apex { - name: "myapex", - key: "myapex.key", - prebuilts: ["myfirmware"], - vendor: true, - } - apex_key { - name: "myapex.key", - public_key: "testkey.avbpubkey", - private_key: "testkey.pem", - } - prebuilt_firmware { - name: "myfirmware", - src: "myfirmware.bin", - filename_from_src: true, - vendor: true, - } - `) - - ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{ - "firmware/myfirmware.bin", - }) +func TestApex_withPrebuiltFirmware(t *testing.T) { + testCases := []struct { + name string + additionalProp string + }{ + {"system apex with prebuilt_firmware", ""}, + {"vendor apex with prebuilt_firmware", "vendor: true,"}, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + ctx, _ := testApex(t, ` + apex { + name: "myapex", + key: "myapex.key", + prebuilts: ["myfirmware"], + `+tc.additionalProp+` + } + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + prebuilt_firmware { + name: "myfirmware", + src: "myfirmware.bin", + filename_from_src: true, + `+tc.additionalProp+` + } + `) + ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{ + "etc/firmware/myfirmware.bin", + }) + }) + } } func TestAndroidMk_UseVendorRequired(t *testing.T) { @@ -6120,7 +6223,7 @@ func TestNonPreferredPrebuiltDependency(t *testing.T) { name: "mylib", srcs: ["mylib.cpp"], stubs: { - versions: ["10000"], + versions: ["current"], }, apex_available: ["myapex"], } @@ -6130,7 +6233,7 @@ func TestNonPreferredPrebuiltDependency(t *testing.T) { prefer: false, srcs: ["prebuilt.so"], stubs: { - versions: ["10000"], + versions: ["current"], }, apex_available: ["myapex"], } diff --git a/apex/builder.go b/apex/builder.go index c5680ad2d..b0f0c8212 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -21,7 +21,6 @@ import ( "path/filepath" "runtime" "sort" - "strconv" "strings" "android/soong/android" @@ -214,7 +213,8 @@ func (a *apexBundle) buildManifest(ctx android.ModuleContext, provideNativeLibs, }, }) - if a.minSdkVersion(ctx) == android.SdkVersion_Android10 { + minSdkVersion := a.minSdkVersion(ctx) + if minSdkVersion.EqualTo(android.SdkVersion_Android10) { // b/143654022 Q apexd can't understand newly added keys in apex_manifest.json // prepare stripped-down version so that APEX modules built from R+ can be installed to Q a.manifestJsonOut = android.PathForModuleOut(ctx, "apex_manifest.json") @@ -426,7 +426,8 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { var emitCommands []string imageContentFile := android.PathForModuleOut(ctx, "content.txt") emitCommands = append(emitCommands, "echo ./apex_manifest.pb >> "+imageContentFile.String()) - if a.minSdkVersion(ctx) == android.SdkVersion_Android10 { + minSdkVersion := a.minSdkVersion(ctx) + if minSdkVersion.EqualTo(android.SdkVersion_Android10) { emitCommands = append(emitCommands, "echo ./apex_manifest.json >> "+imageContentFile.String()) } for _, fi := range a.filesInfo { @@ -532,12 +533,13 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { optFlags = append(optFlags, "--android_manifest "+androidManifestFile.String()) } - targetSdkVersion := ctx.Config().DefaultAppTargetSdk() + targetSdkVersion := ctx.Config().DefaultAppTargetSdk(ctx).String() // TODO(b/157078772): propagate min_sdk_version to apexer. - minSdkVersion := ctx.Config().DefaultAppTargetSdk() + minSdkVersion := ctx.Config().DefaultAppTargetSdk(ctx).String() - if a.minSdkVersion(ctx) == android.SdkVersion_Android10 { - minSdkVersion = strconv.Itoa(a.minSdkVersion(ctx)) + moduleMinSdkVersion := a.minSdkVersion(ctx) + if moduleMinSdkVersion.EqualTo(android.SdkVersion_Android10) { + minSdkVersion = moduleMinSdkVersion.String() } if java.UseApiFingerprint(ctx) { @@ -566,7 +568,7 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { ctx.PropertyErrorf("test_only_no_hashtree", "not available") return } - if a.minSdkVersion(ctx) > android.SdkVersion_Android10 || a.testOnlyShouldSkipHashtreeGeneration() { + if moduleMinSdkVersion.GreaterThan(android.SdkVersion_Android10) || a.testOnlyShouldSkipHashtreeGeneration() { // Apexes which are supposed to be installed in builtin dirs(/system, etc) // don't need hashtree for activation. Therefore, by removing hashtree from // apex bundle (filesystem image in it, to be specific), we can save storage. @@ -583,7 +585,7 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { optFlags = append(optFlags, "--do_not_check_keyname") } - if a.minSdkVersion(ctx) == android.SdkVersion_Android10 { + if moduleMinSdkVersion == android.SdkVersion_Android10 { implicitInputs = append(implicitInputs, a.manifestJsonOut) optFlags = append(optFlags, "--manifest_json "+a.manifestJsonOut.String()) } diff --git a/apex/prebuilt.go b/apex/prebuilt.go index 37457e921..9f6c8ada9 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -326,7 +326,7 @@ func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { Args: map[string]string{ "abis": strings.Join(java.SupportedAbis(ctx), ","), "allow-prereleased": strconv.FormatBool(proptools.Bool(a.properties.Prerelease)), - "sdk-version": ctx.Config().PlatformSdkVersion(), + "sdk-version": ctx.Config().PlatformSdkVersion().String(), }, }) diff --git a/apex/vndk.go b/apex/vndk.go index 5cc0e2a43..93265c4ac 100644 --- a/apex/vndk.go +++ b/apex/vndk.go @@ -16,7 +16,6 @@ package apex import ( "path/filepath" - "strconv" "strings" "sync" @@ -124,10 +123,10 @@ func makeCompatSymlinks(name string, ctx android.ModuleContext) (symlinks []stri // Since prebuilt vndk libs still depend on system/lib/vndk path if strings.HasPrefix(name, vndkApexNamePrefix) { vndkVersion := strings.TrimPrefix(name, vndkApexNamePrefix) - if numVer, err := strconv.Atoi(vndkVersion); err != nil { + if ver, err := android.ApiLevelFromUser(ctx, vndkVersion); err != nil { ctx.ModuleErrorf("apex_vndk should be named as %v<ver:number>: %s", vndkApexNamePrefix, name) return - } else if numVer > android.SdkVersion_Android10 { + } else if ver.GreaterThan(android.SdkVersion_Android10) { return } // the name of vndk apex is formatted "com.android.vndk.v" + version diff --git a/cc/Android.bp b/cc/Android.bp index 831911e45..ff2cdf374 100644 --- a/cc/Android.bp +++ b/cc/Android.bp @@ -13,6 +13,7 @@ bootstrap_go_package { ], srcs: [ "androidmk.go", + "api_level.go", "builder.go", "cc.go", "ccdeps.go", diff --git a/cc/androidmk.go b/cc/androidmk.go index 380b4e92f..d92fabc0d 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -33,7 +33,7 @@ var ( ) type AndroidMkContext interface { - Name() string + BaseModuleName() string Target() android.Target subAndroidMk(*android.AndroidMkEntries, interface{}) Arch() android.Arch @@ -83,6 +83,13 @@ func (c *Module) AndroidMkEntries() []android.AndroidMkEntries { if len(c.Properties.Logtags) > 0 { entries.AddStrings("LOCAL_LOGTAGS_FILES", c.Properties.Logtags...) } + // Note: Pass the exact value of AndroidMkSystemSharedLibs to the Make + // world, even if it is an empty list. In the Make world, + // LOCAL_SYSTEM_SHARED_LIBRARIES defaults to "none", which is expanded + // to the default list of system shared libs by the build system. + // Soong computes the exact list of system shared libs, so we have to + // override the default value when the list of libs is actually empty. + entries.SetString("LOCAL_SYSTEM_SHARED_LIBRARIES", strings.Join(c.Properties.AndroidMkSystemSharedLibs, " ")) if len(c.Properties.AndroidMkSharedLibs) > 0 { entries.AddStrings("LOCAL_SHARED_LIBRARIES", c.Properties.AndroidMkSharedLibs...) } @@ -149,24 +156,6 @@ func (c *Module) AndroidMkEntries() []android.AndroidMkEntries { return []android.AndroidMkEntries{entries} } -func AndroidMkDataPaths(data []android.DataPath) []string { - var testFiles []string - for _, d := range data { - rel := d.SrcPath.Rel() - path := d.SrcPath.String() - if !strings.HasSuffix(path, rel) { - panic(fmt.Errorf("path %q does not end with %q", path, rel)) - } - path = strings.TrimSuffix(path, rel) - testFileString := path + ":" + rel - if len(d.RelativeInstallPath) > 0 { - testFileString += ":" + d.RelativeInstallPath - } - testFiles = append(testFiles, testFileString) - } - return testFiles -} - func androidMkWriteExtraTestConfigs(extraTestConfigs android.Paths, entries *android.AndroidMkEntries) { if len(extraTestConfigs) > 0 { entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) { @@ -176,7 +165,7 @@ func androidMkWriteExtraTestConfigs(extraTestConfigs android.Paths, entries *and } func androidMkWriteTestData(data []android.DataPath, ctx AndroidMkContext, entries *android.AndroidMkEntries) { - testFiles := AndroidMkDataPaths(data) + testFiles := android.AndroidMkDataPaths(data) if len(testFiles) > 0 { entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) { entries.AddStrings("LOCAL_TEST_DATA", testFiles...) @@ -289,7 +278,7 @@ func (library *libraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries }) } if len(library.Properties.Stubs.Versions) > 0 && - android.DirectlyInAnyApex(ctx, ctx.Name()) && !ctx.InRamdisk() && !ctx.InRecovery() && !ctx.UseVndk() && + android.DirectlyInAnyApex(ctx, ctx.BaseModuleName()) && !ctx.InRamdisk() && !ctx.InRecovery() && !ctx.UseVndk() && !ctx.static() { if library.buildStubs() && library.isLatestStubVersion() { // reference the latest version via its name without suffix when it is provided by apex @@ -451,7 +440,7 @@ func (installer *baseInstaller) AndroidMkEntries(ctx AndroidMkContext, entries * } func (c *stubDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) { - entries.SubName = ndkLibrarySuffix + "." + c.properties.ApiLevel + entries.SubName = ndkLibrarySuffix + "." + c.apiLevel.String() entries.Class = "SHARED_LIBRARIES" entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) { diff --git a/cc/api_level.go b/cc/api_level.go new file mode 100644 index 000000000..c93d6eda3 --- /dev/null +++ b/cc/api_level.go @@ -0,0 +1,71 @@ +// Copyright 2020 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 cc + +import ( + "fmt" + + "android/soong/android" +) + +func minApiForArch(ctx android.BaseModuleContext, + arch android.ArchType) android.ApiLevel { + + switch arch { + case android.Arm, android.X86: + return ctx.Config().MinSupportedSdkVersion() + case android.Arm64, android.X86_64: + return android.FirstLp64Version + default: + panic(fmt.Errorf("Unknown arch %q", arch)) + } +} + +func nativeApiLevelFromUser(ctx android.BaseModuleContext, + raw string) (android.ApiLevel, error) { + + min := minApiForArch(ctx, ctx.Arch().ArchType) + if raw == "minimum" { + return min, nil + } + + value, err := android.ApiLevelFromUser(ctx, raw) + if err != nil { + return android.NoneApiLevel, err + } + + if value.LessThan(min) { + return min, nil + } + + return value, nil +} + +func nativeApiLevelFromUserWithDefault(ctx android.BaseModuleContext, + raw string, defaultValue string) (android.ApiLevel, error) { + if raw == "" { + raw = defaultValue + } + return nativeApiLevelFromUser(ctx, raw) +} + +func nativeApiLevelOrPanic(ctx android.BaseModuleContext, + raw string) android.ApiLevel { + value, err := nativeApiLevelFromUser(ctx, raw) + if err != nil { + panic(err.Error()) + } + return value +} diff --git a/cc/binary_sdk_member.go b/cc/binary_sdk_member.go index a1abc728a..55e400e8e 100644 --- a/cc/binary_sdk_member.go +++ b/cc/binary_sdk_member.go @@ -44,7 +44,7 @@ func (mt *binarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorConte for _, target := range targets { name, version := StubsLibNameAndVersion(lib) if version == "" { - version = LatestStubsVersionFor(mctx.Config(), name) + version = "latest" } variations := target.Variations() if mctx.Device() { diff --git a/cc/builder.go b/cc/builder.go index ef653481d..81c09b1a1 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -221,7 +221,6 @@ var ( ExecStrategy: "${config.REAbiDumperExecStrategy}", Platform: map[string]string{ remoteexec.PoolKey: "${config.RECXXPool}", - "InputRootAbsolutePath": android.AbsSrcDirForExistingUseCases(), }, }, []string{"cFlags", "exportDirs"}, nil) @@ -47,7 +47,8 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) { ctx.BottomUp("link", LinkageMutator).Parallel() ctx.BottomUp("ndk_api", NdkApiMutator).Parallel() ctx.BottomUp("test_per_src", TestPerSrcMutator).Parallel() - ctx.BottomUp("version", VersionMutator).Parallel() + ctx.BottomUp("version_selector", versionSelectorMutator).Parallel() + ctx.BottomUp("version", versionMutator).Parallel() ctx.BottomUp("begin", BeginMutator).Parallel() ctx.BottomUp("sysprop_cc", SyspropMutator).Parallel() ctx.BottomUp("vendor_snapshot", VendorSnapshotMutator).Parallel() @@ -99,6 +100,9 @@ type Deps struct { // Used for data dependencies adjacent to tests DataLibs []string + // Used by DepsMutator to pass system_shared_libs information to check_elf_file.py. + SystemSharedLibs []string + StaticUnwinderIfLegacy bool ReexportSharedLibHeaders, ReexportStaticLibHeaders, ReexportHeaderLibHeaders []string @@ -237,6 +241,9 @@ type BaseProperties struct { PreventInstall bool `blueprint:"mutated"` ApexesProvidingSharedLibs []string `blueprint:"mutated"` + // Set by DepsMutator. + AndroidMkSystemSharedLibs []string `blueprint:"mutated"` + ImageVariationPrefix string `blueprint:"mutated"` VndkVersion string `blueprint:"mutated"` SubName string `blueprint:"mutated"` @@ -353,7 +360,7 @@ type ModuleContextIntf interface { useClangLld(actx ModuleContext) bool isForPlatform() bool apexVariationName() string - apexSdkVersion() int + apexSdkVersion() android.ApiLevel hasStubsVariants() bool isStubs() bool bootstrap() bool @@ -614,7 +621,7 @@ type Module struct { kytheFiles android.Paths // For apex variants, this is set as apex.min_sdk_version - apexSdkVersion int + apexSdkVersion android.ApiLevel } func (c *Module) Toc() android.OptionalPath { @@ -629,7 +636,7 @@ func (c *Module) Toc() android.OptionalPath { func (c *Module) ApiLevel() string { if c.linker != nil { if stub, ok := c.linker.(*stubDecorator); ok { - return stub.properties.ApiLevel + return stub.apiLevel.String() } } panic(fmt.Errorf("ApiLevel() called on non-stub library module: %q", c.BaseModuleName())) @@ -733,6 +740,9 @@ func (c *Module) StubsVersions() []string { if library, ok := c.linker.(*libraryDecorator); ok { return library.Properties.Stubs.Versions } + if library, ok := c.linker.(*prebuiltLibraryLinker); ok { + return library.Properties.Stubs.Versions + } } panic(fmt.Errorf("StubsVersions called on non-library module: %q", c.BaseModuleName())) } @@ -742,6 +752,9 @@ func (c *Module) CcLibrary() bool { if _, ok := c.linker.(*libraryDecorator); ok { return true } + if _, ok := c.linker.(*prebuiltLibraryLinker); ok { + return true + } } return false } @@ -767,6 +780,14 @@ func (c *Module) SetBuildStubs() { c.Properties.PreventInstall = true return } + if library, ok := c.linker.(*prebuiltLibraryLinker); ok { + library.MutatedProperties.BuildStubs = true + c.Properties.HideFromMake = true + c.sanitize = nil + c.stl = nil + c.Properties.PreventInstall = true + return + } if _, ok := c.linker.(*llndkStubDecorator); ok { c.Properties.HideFromMake = true return @@ -780,22 +801,57 @@ func (c *Module) BuildStubs() bool { if library, ok := c.linker.(*libraryDecorator); ok { return library.buildStubs() } + if library, ok := c.linker.(*prebuiltLibraryLinker); ok { + return library.buildStubs() + } } panic(fmt.Errorf("BuildStubs called on non-library module: %q", c.BaseModuleName())) } -func (c *Module) SetStubsVersions(version string) { +func (c *Module) SetAllStubsVersions(versions []string) { + if library, ok := c.linker.(*libraryDecorator); ok { + library.MutatedProperties.AllStubsVersions = versions + return + } + if library, ok := c.linker.(*prebuiltLibraryLinker); ok { + library.MutatedProperties.AllStubsVersions = versions + return + } + if llndk, ok := c.linker.(*llndkStubDecorator); ok { + llndk.libraryDecorator.MutatedProperties.AllStubsVersions = versions + return + } +} + +func (c *Module) AllStubsVersions() []string { + if library, ok := c.linker.(*libraryDecorator); ok { + return library.MutatedProperties.AllStubsVersions + } + if library, ok := c.linker.(*prebuiltLibraryLinker); ok { + return library.MutatedProperties.AllStubsVersions + } + if llndk, ok := c.linker.(*llndkStubDecorator); ok { + return llndk.libraryDecorator.MutatedProperties.AllStubsVersions + } + return nil +} + +func (c *Module) SetStubsVersion(version string) { if c.linker != nil { if library, ok := c.linker.(*libraryDecorator); ok { library.MutatedProperties.StubsVersion = version return } + if library, ok := c.linker.(*prebuiltLibraryLinker); ok { + library.MutatedProperties.StubsVersion = version + return + } if llndk, ok := c.linker.(*llndkStubDecorator); ok { llndk.libraryDecorator.MutatedProperties.StubsVersion = version return } } - panic(fmt.Errorf("SetStubsVersions called on non-library module: %q", c.BaseModuleName())) + panic(fmt.Errorf("SetStubsVersion called on non-library module: %q", c.BaseModuleName())) } func (c *Module) StubsVersion() string { @@ -803,6 +859,9 @@ func (c *Module) StubsVersion() string { if library, ok := c.linker.(*libraryDecorator); ok { return library.MutatedProperties.StubsVersion } + if library, ok := c.linker.(*prebuiltLibraryLinker); ok { + return library.MutatedProperties.StubsVersion + } if llndk, ok := c.linker.(*llndkStubDecorator); ok { return llndk.libraryDecorator.MutatedProperties.StubsVersion } @@ -928,9 +987,9 @@ func (c *Module) Init() android.Module { c.AddProperties(feature.props()...) } - c.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool { + c.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, os android.OsType) bool { // Windows builds always prefer 32-bit - return class == android.HostCross + return os == android.Windows }) android.InitAndroidArchModule(c, c.hod, c.multilib) android.InitApexModule(c) @@ -1045,6 +1104,8 @@ func (c *Module) getVndkExtendsModuleName() string { func (c *Module) IsStubs() bool { if library, ok := c.linker.(*libraryDecorator); ok { return library.buildStubs() + } else if library, ok := c.linker.(*prebuiltLibraryLinker); ok { + return library.buildStubs() } else if _, ok := c.linker.(*llndkStubDecorator); ok { return true } @@ -1306,7 +1367,7 @@ func (ctx *moduleContextImpl) apexVariationName() string { return ctx.mod.ApexVariationName() } -func (ctx *moduleContextImpl) apexSdkVersion() int { +func (ctx *moduleContextImpl) apexSdkVersion() android.ApiLevel { return ctx.mod.apexSdkVersion } @@ -1682,11 +1743,13 @@ func (c *Module) begin(ctx BaseModuleContext) { feature.begin(ctx) } if ctx.useSdk() && c.IsSdkVariant() { - version, err := normalizeNdkApiLevel(ctx, ctx.sdkVersion(), ctx.Arch()) + version, err := nativeApiLevelFromUser(ctx, ctx.sdkVersion()) if err != nil { ctx.PropertyErrorf("sdk_version", err.Error()) + c.Properties.Sdk_version = nil + } else { + c.Properties.Sdk_version = StringPtr(version.String()) } - c.Properties.Sdk_version = StringPtr(version) } } @@ -1800,6 +1863,42 @@ func GetCrtVariations(ctx android.BottomUpMutatorContext, } } +func (c *Module) addSharedLibDependenciesWithVersions(ctx android.BottomUpMutatorContext, + variations []blueprint.Variation, depTag libraryDependencyTag, name, version string, far bool) { + + variations = append([]blueprint.Variation(nil), variations...) + + if version != "" && VersionVariantAvailable(c) { + // Version is explicitly specified. i.e. libFoo#30 + variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version}) + depTag.explicitlyVersioned = true + } + var deps []blueprint.Module + if far { + deps = ctx.AddFarVariationDependencies(variations, depTag, name) + } else { + deps = ctx.AddVariationDependencies(variations, depTag, name) + } + + // If the version is not specified, add dependency to all stubs libraries. + // The stubs library will be used when the depending module is built for APEX and + // the dependent module is not in the same APEX. + if version == "" && VersionVariantAvailable(c) { + if dep, ok := deps[0].(*Module); ok { + for _, ver := range dep.AllStubsVersions() { + // Note that depTag.ExplicitlyVersioned is false in this case. + versionVariations := append(variations, + blueprint.Variation{Mutator: "version", Variation: ver}) + if far { + ctx.AddFarVariationDependencies(versionVariations, depTag, name) + } else { + ctx.AddVariationDependencies(versionVariations, depTag, name) + } + } + } + } +} + func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { if !c.Enabled() { return @@ -1815,6 +1914,8 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { deps := c.deps(ctx) + c.Properties.AndroidMkSystemSharedLibs = deps.SystemSharedLibs + variantNdkLibs := []string{} variantLateNdkLibs := []string{} if ctx.Os() == android.Android { @@ -1898,6 +1999,11 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { buildStubs = true } } + if library, ok := c.linker.(*prebuiltLibraryLinker); ok { + if library.buildStubs() { + buildStubs = true + } + } } rewriteSnapshotLibs := func(lib string, snapshotMap *snapshotMap) string { @@ -1986,30 +2092,6 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { }, depTag, rewriteSnapshotLibs(lib, vendorSnapshotStaticLibs)) } - addSharedLibDependencies := func(depTag libraryDependencyTag, name string, version string) { - var variations []blueprint.Variation - variations = append(variations, blueprint.Variation{Mutator: "link", Variation: "shared"}) - if version != "" && VersionVariantAvailable(c) { - // Version is explicitly specified. i.e. libFoo#30 - variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version}) - depTag.explicitlyVersioned = true - } - actx.AddVariationDependencies(variations, depTag, name) - - // If the version is not specified, add dependency to all stubs libraries. - // The stubs library will be used when the depending module is built for APEX and - // the dependent module is not in the same APEX. - if version == "" && VersionVariantAvailable(c) { - for _, ver := range stubsVersionsFor(actx.Config())[name] { - // Note that depTag.ExplicitlyVersioned is false in this case. - actx.AddVariationDependencies([]blueprint.Variation{ - {Mutator: "link", Variation: "shared"}, - {Mutator: "version", Variation: ver}, - }, depTag, name) - } - } - } - // shared lib names without the #version suffix var sharedLibNames []string @@ -2026,7 +2108,10 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { name, version := StubsLibNameAndVersion(lib) sharedLibNames = append(sharedLibNames, name) - addSharedLibDependencies(depTag, name, version) + variations := []blueprint.Variation{ + {Mutator: "link", Variation: "shared"}, + } + c.addSharedLibDependenciesWithVersions(ctx, variations, depTag, name, version, false) } for _, lib := range deps.LateSharedLibs { @@ -2037,7 +2122,10 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { continue } depTag := libraryDependencyTag{Kind: sharedLibraryDependency, Order: lateLibraryDependency} - addSharedLibDependencies(depTag, lib, "") + variations := []blueprint.Variation{ + {Mutator: "link", Variation: "shared"}, + } + c.addSharedLibDependenciesWithVersions(ctx, variations, depTag, lib, "", false) } actx.AddVariationDependencies([]blueprint.Variation{ @@ -2291,7 +2379,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // For the dependency from platform to apex, use the latest stubs c.apexSdkVersion = android.FutureApiLevel if !c.IsForPlatform() { - c.apexSdkVersion = c.ApexProperties.Info.MinSdkVersion + c.apexSdkVersion = c.ApexProperties.Info.MinSdkVersion(ctx) } if android.InList("hwaddress", ctx.Config().SanitizeDevice()) { @@ -2395,7 +2483,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { if libDepTag, ok := depTag.(libraryDependencyTag); ok { // Only use static unwinder for legacy (min_sdk_version = 29) apexes (b/144430859) - if libDepTag.staticUnwinder && c.apexSdkVersion > android.SdkVersion_Android10 { + if libDepTag.staticUnwinder && c.apexSdkVersion.GreaterThan(android.SdkVersion_Android10) { return } @@ -2439,7 +2527,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // when to use (unspecified) stubs, check min_sdk_version and choose the right one if useThisDep && depIsStubs && !libDepTag.explicitlyVersioned { - versionToUse, err := c.ChooseSdkVersion(ccDep.StubsVersions(), c.apexSdkVersion) + versionToUse, err := c.ChooseSdkVersion(ctx, ccDep.StubsVersions(), c.apexSdkVersion) if err != nil { ctx.OtherModuleErrorf(dep, err.Error()) return @@ -2457,12 +2545,12 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { if m, ok := ccDep.(*Module); ok && m.IsStubs() { // LLNDK // by default, use current version of LLNDK versionToUse := "" - versions := stubsVersionsFor(ctx.Config())[depName] + versions := m.AllStubsVersions() if c.ApexVariationName() != "" && len(versions) > 0 { // if this is for use_vendor apex && dep has stubsVersions // apply the same rule of apex sdk enforcement to choose right version var err error - versionToUse, err = c.ChooseSdkVersion(versions, c.apexSdkVersion) + versionToUse, err = c.ChooseSdkVersion(ctx, versions, c.apexSdkVersion) if err != nil { ctx.OtherModuleErrorf(dep, err.Error()) return @@ -2533,17 +2621,20 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // in the context of proper cc.Modules. if ccWholeStaticLib, ok := ccDep.(*Module); ok { staticLib := ccWholeStaticLib.linker.(libraryInterface) - if missingDeps := staticLib.getWholeStaticMissingDeps(); missingDeps != nil { - postfix := " (required by " + ctx.OtherModuleName(dep) + ")" - for i := range missingDeps { - missingDeps[i] += postfix - } - ctx.AddMissingDependencies(missingDeps) - } - if _, ok := ccWholeStaticLib.linker.(prebuiltLinkerInterface); ok { - depPaths.WholeStaticLibsFromPrebuilts = append(depPaths.WholeStaticLibsFromPrebuilts, linkFile.Path()) + if objs := staticLib.objs(); len(objs.objFiles) > 0 { + depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(objs) } else { - depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(staticLib.objs()) + // This case normally catches prebuilt static + // libraries, but it can also occur when + // AllowMissingDependencies is on and the + // dependencies has no sources of its own + // but has a whole_static_libs dependency + // on a missing library. We want to depend + // on the .a file so that there is something + // in the dependency tree that contains the + // error rule for the missing transitive + // dependency. + depPaths.WholeStaticLibsFromPrebuilts = append(depPaths.WholeStaticLibsFromPrebuilts, linkFile.Path()) } } else { ctx.ModuleErrorf( @@ -2986,21 +3077,8 @@ func (c *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu return true } -// b/154667674: refactor this to handle "current" in a consistent way -func decodeSdkVersionString(ctx android.BaseModuleContext, versionString string) (int, error) { - if versionString == "" { - return 0, fmt.Errorf("not specified") - } - if versionString == "current" { - if ctx.Config().PlatformSdkCodename() == "REL" { - return ctx.Config().PlatformSdkVersionInt(), nil - } - return android.FutureApiLevel, nil - } - return android.ApiStrToNum(ctx, versionString) -} - -func (c *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +func (c *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, + sdkVersion android.ApiLevel) error { // We ignore libclang_rt.* prebuilt libs since they declare sdk_version: 14(b/121358700) if strings.HasPrefix(ctx.OtherModuleName(c), "libclang_rt") { return nil @@ -3024,11 +3102,17 @@ func (c *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersi // non-SDK variant resets sdk_version, which works too. minSdkVersion = c.SdkVersion() } - ver, err := decodeSdkVersionString(ctx, minSdkVersion) + if minSdkVersion == "" { + return fmt.Errorf("neither min_sdk_version nor sdk_version specificed") + } + // Not using nativeApiLevelFromUser because the context here is not + // necessarily a native context. + ver, err := android.ApiLevelFromUser(ctx, minSdkVersion) if err != nil { return err } - if ver > sdkVersion { + + if ver.GreaterThan(sdkVersion) { return fmt.Errorf("newer SDK(%v)", ver) } return nil @@ -3082,6 +3166,8 @@ func DefaultsFactory(props ...interface{}) android.Module { <OProperties{}, &PgoProperties{}, &android.ProtoProperties{}, + // RustBindgenProperties is included here so that cc_defaults can be used for rust_bindgen modules. + &RustBindgenClangProperties{}, ) android.InitDefaultsModule(module) @@ -3119,13 +3205,6 @@ func (c *Module) IsSdkVariant() bool { return c.Properties.IsSdkVariant || c.AlwaysSdk() } -func getCurrentNdkPrebuiltVersion(ctx DepsContext) string { - if ctx.Config().PlatformSdkVersionInt() > config.NdkMaxPrebuiltVersionInt { - return strconv.Itoa(config.NdkMaxPrebuiltVersionInt) - } - return ctx.Config().PlatformSdkVersion() -} - func kytheExtractAllFactory() android.Singleton { return &kytheExtractAllSingleton{} } diff --git a/cc/cc_test.go b/cc/cc_test.go index a4c067772..e0d464093 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -3025,6 +3025,7 @@ func TestStaticLibDepReorderingWithShared(t *testing.T) { } func checkEquals(t *testing.T, message string, expected, actual interface{}) { + t.Helper() if !reflect.DeepEqual(actual, expected) { t.Errorf(message+ "\nactual: %v"+ @@ -3779,3 +3780,46 @@ func TestProductVariableDefaults(t *testing.T) { t.Errorf("expected -DBAR in cppflags, got %q", libfoo.flags.Local.CppFlags) } } + +func TestEmptyWholeStaticLibsAllowMissingDependencies(t *testing.T) { + t.Parallel() + bp := ` + cc_library_static { + name: "libfoo", + srcs: ["foo.c"], + whole_static_libs: ["libbar"], + } + + cc_library_static { + name: "libbar", + whole_static_libs: ["libmissing"], + } + ` + + config := TestConfig(buildDir, android.Android, nil, bp, nil) + config.TestProductVariables.Allow_missing_dependencies = BoolPtr(true) + + ctx := CreateTestContext() + ctx.SetAllowMissingDependencies(true) + ctx.Register(config) + + _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) + android.FailIfErrored(t, errs) + _, errs = ctx.PrepareBuildActions(config) + android.FailIfErrored(t, errs) + + libbar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_static").Output("libbar.a") + if g, w := libbar.Rule, android.ErrorRule; g != w { + t.Fatalf("Expected libbar rule to be %q, got %q", w, g) + } + + if g, w := libbar.Args["error"], "missing dependencies: libmissing"; !strings.Contains(g, w) { + t.Errorf("Expected libbar error to contain %q, was %q", w, g) + } + + libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Output("libfoo.a") + if g, w := libfoo.Inputs.Strings(), libbar.Output.String(); !android.InList(w, g) { + t.Errorf("Expected libfoo.a to depend on %q, got %q", w, g) + } + +} diff --git a/cc/check.go b/cc/check.go index 46328e915..0058b8c06 100644 --- a/cc/check.go +++ b/cc/check.go @@ -38,6 +38,8 @@ func CheckBadCompilerFlags(ctx BaseModuleContext, prop string, flags []string) { ctx.PropertyErrorf(prop, "Illegal flag `%s`", flag) } else if flag == "--coverage" { ctx.PropertyErrorf(prop, "Bad flag: `%s`, use native_coverage instead", flag) + } else if flag == "-fwhole-program-vtables" { + ctx.PropertyErrorf(prop, "Bad flag: `%s`, use whole_program_vtables instead", flag) } else if flag == "-Weverything" { if !ctx.Config().IsEnvTrue("ANDROID_TEMPORARILY_ALLOW_WEVERYTHING") { ctx.PropertyErrorf(prop, "-Weverything is not allowed in Android.bp files. "+ diff --git a/cc/compiler.go b/cc/compiler.go index c268dec2b..21da2fc60 100644 --- a/cc/compiler.go +++ b/cc/compiler.go @@ -354,10 +354,16 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_APEX_NAME__='\""+ctx.apexVariationName()+"\"'") } if ctx.Device() { - flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_SDK_VERSION__="+strconv.Itoa(ctx.apexSdkVersion())) + flags.Global.CommonFlags = append(flags.Global.CommonFlags, + fmt.Sprintf("-D__ANDROID_SDK_VERSION__=%d", + ctx.apexSdkVersion().FinalOrFutureInt())) } } + if ctx.Target().NativeBridge == android.NativeBridgeEnabled { + flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_NATIVE_BRIDGE__") + } + instructionSet := String(compiler.Properties.Instruction_set) if flags.RequiredInstructionSet != "" { instructionSet = flags.RequiredInstructionSet @@ -386,7 +392,7 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps if ctx.Os().Class == android.Device { version := ctx.sdkVersion() if version == "" || version == "current" { - target += strconv.Itoa(android.FutureApiLevel) + target += strconv.Itoa(android.FutureApiLevelInt) } else { target += version } @@ -646,3 +652,43 @@ func isThirdParty(path string) bool { } return true } + +// Properties for rust_bindgen related to generating rust bindings. +// This exists here so these properties can be included in a cc_default +// which can be used in both cc and rust modules. +type RustBindgenClangProperties struct { + // list of directories relative to the Blueprints file that will + // be added to the include path using -I + Local_include_dirs []string `android:"arch_variant,variant_prepend"` + + // list of static libraries that provide headers for this binding. + Static_libs []string `android:"arch_variant,variant_prepend"` + + // list of shared libraries that provide headers for this binding. + Shared_libs []string `android:"arch_variant"` + + // list of clang flags required to correctly interpret the headers. + Cflags []string `android:"arch_variant"` + + // list of c++ specific clang flags required to correctly interpret the headers. + // This is provided primarily to make sure cppflags defined in cc_defaults are pulled in. + Cppflags []string `android:"arch_variant"` + + // C standard version to use. Can be a specific version (such as "gnu11"), + // "experimental" (which will use draft versions like C1x when available), + // or the empty string (which will use the default). + // + // If this is set, the file extension will be ignored and this will be used as the std version value. Setting this + // to "default" will use the build system default version. This cannot be set at the same time as cpp_std. + C_std *string + + // C++ standard version to use. Can be a specific version (such as + // "gnu++11"), "experimental" (which will use draft versions like C++1z when + // available), or the empty string (which will use the default). + // + // If this is set, the file extension will be ignored and this will be used as the std version value. Setting this + // to "default" will use the build system default version. This cannot be set at the same time as c_std. + Cpp_std *string + + //TODO(b/161141999) Add support for headers from cc_library_header modules. +} diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go index 62d8cc8fb..e6024aa45 100644 --- a/cc/config/arm64_device.go +++ b/cc/config/arm64_device.go @@ -34,6 +34,9 @@ var ( "armv8-2a": []string{ "-march=armv8.2-a", }, + "armv8-2a-dotprod": []string{ + "-march=armv8.2-a+dotprod", + }, } arm64Ldflags = []string{ @@ -100,6 +103,7 @@ func init() { pctx.StaticVariable("Arm64ClangArmv8ACflags", strings.Join(arm64ArchVariantCflags["armv8-a"], " ")) pctx.StaticVariable("Arm64ClangArmv82ACflags", strings.Join(arm64ArchVariantCflags["armv8-2a"], " ")) + pctx.StaticVariable("Arm64ClangArmv82ADotprodCflags", strings.Join(arm64ArchVariantCflags["armv8-2a-dotprod"], " ")) pctx.StaticVariable("Arm64ClangCortexA53Cflags", strings.Join(arm64ClangCpuVariantCflags["cortex-a53"], " ")) @@ -121,6 +125,7 @@ var ( arm64ClangArchVariantCflagsVar = map[string]string{ "armv8-a": "${config.Arm64ClangArmv8ACflags}", "armv8-2a": "${config.Arm64ClangArmv82ACflags}", + "armv8-2a-dotprod": "${config.Arm64ClangArmv82ADotprodCflags}", } arm64ClangCpuVariantCflagsVar = map[string]string{ @@ -198,6 +203,7 @@ func arm64ToolchainFactory(arch android.Arch) Toolchain { switch arch.ArchVariant { case "armv8-a": case "armv8-2a": + case "armv8-2a-dotprod": // Nothing extra for armv8-a/armv8-2a default: panic(fmt.Sprintf("Unknown ARM architecture version: %q", arch.ArchVariant)) diff --git a/cc/config/clang.go b/cc/config/clang.go index 7db405c2e..441bff2a5 100644 --- a/cc/config/clang.go +++ b/cc/config/clang.go @@ -42,7 +42,6 @@ var ClangUnknownCflags = sorted([]string{ "-Wno-literal-suffix", "-Wno-maybe-uninitialized", "-Wno-old-style-declaration", - "-Wno-psabi", "-Wno-unused-but-set-parameter", "-Wno-unused-but-set-variable", "-Wno-unused-local-typedefs", @@ -93,7 +92,9 @@ var ClangLibToolingUnknownCflags = sorted([]string{}) // updated, some checks enabled by this module may be disabled if they have // become more strict, or if they are a new match for a wildcard group like // `modernize-*`. -var ClangTidyDisableChecks = []string{} +var ClangTidyDisableChecks = []string{ + "misc-no-recursion", +} func init() { pctx.StaticVariable("ClangExtraCflags", strings.Join([]string{ @@ -103,6 +104,10 @@ func init() { // not emit the table by default on Android since NDK still uses GNU binutils. "-faddrsig", + // Turn on -fcommon explicitly, since Clang now defaults to -fno-common. The cleanup bug + // tracking this is http://b/151457797. + "-fcommon", + // Help catch common 32/64-bit errors. "-Werror=int-conversion", @@ -183,6 +188,8 @@ func init() { "-Wno-enum-enum-conversion", // http://b/154138986 "-Wno-enum-float-conversion", // http://b/154255917 "-Wno-pessimizing-move", // http://b/154270751 + // New warnings to be fixed after clang-r399163 + "-Wno-non-c-typedef-for-linkage", // http://b/161304145 }, " ")) // Extra cflags for external third-party projects to disable warnings that @@ -205,6 +212,9 @@ func init() { "-Wno-xor-used-as-pow", // http://b/145211022 "-Wno-final-dtor-non-final-class", + + // http://b/165945989 + "-Wno-psabi", }, " ")) } diff --git a/cc/config/global.go b/cc/config/global.go index 32f163d88..d4c626699 100644 --- a/cc/config/global.go +++ b/cc/config/global.go @@ -114,6 +114,12 @@ var ( noOverrideGlobalCflags = []string{ "-Werror=int-to-pointer-cast", "-Werror=pointer-to-int-cast", + // http://b/161386391 for -Wno-void-pointer-to-enum-cast + "-Wno-void-pointer-to-enum-cast", + // http://b/161386391 for -Wno-void-pointer-to-int-cast + "-Wno-void-pointer-to-int-cast", + // http://b/161386391 for -Wno-pointer-to-int-cast + "-Wno-pointer-to-int-cast", "-Werror=fortify-source", } @@ -126,12 +132,10 @@ var ( ExperimentalCStdVersion = "gnu11" ExperimentalCppStdVersion = "gnu++2a" - NdkMaxPrebuiltVersionInt = 27 - // prebuilts/clang default settings. ClangDefaultBase = "prebuilts/clang/host" - ClangDefaultVersion = "clang-r383902b" - ClangDefaultShortVersion = "11.0.2" + ClangDefaultVersion = "clang-r399163b" + ClangDefaultShortVersion = "11.0.5" // Directories with warnings from Android.bp files. WarningAllowedProjects = []string{ diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go index b5b555322..b77df7906 100644 --- a/cc/config/x86_windows_host.go +++ b/cc/config/x86_windows_host.go @@ -39,6 +39,9 @@ var ( // Get 64-bit off_t and related functions. "-D_FILE_OFFSET_BITS=64", + // Don't adjust the layout of bitfields like msvc does. + "-mno-ms-bitfields", + "--sysroot ${WindowsGccRoot}/${WindowsGccTriple}", } windowsClangCflags = append(ClangFilterUnknownCflags(windowsCflags), []string{}...) diff --git a/cc/fuzz.go b/cc/fuzz.go index 529541859..045384718 100644 --- a/cc/fuzz.go +++ b/cc/fuzz.go @@ -38,6 +38,9 @@ type FuzzConfig struct { // Specify whether this fuzz target was submitted by a researcher. Defaults // to false. Researcher_submitted *bool `json:"researcher_submitted,omitempty"` + // Specify who should be acknowledged for CVEs in the Android Security + // Bulletin. + Acknowledgement []string `json:"acknowledgement,omitempty"` } func (f *FuzzConfig) String() string { diff --git a/cc/library.go b/cc/library.go index 92853b5d3..bf7868ff7 100644 --- a/cc/library.go +++ b/cc/library.go @@ -19,8 +19,6 @@ import ( "io" "path/filepath" "regexp" - "sort" - "strconv" "strings" "sync" @@ -152,6 +150,8 @@ type LibraryMutatedProperties struct { BuildStubs bool `blueprint:"mutated"` // Version of the stubs lib StubsVersion string `blueprint:"mutated"` + // List of all stubs versions associated with an implementation lib + AllStubsVersions []string `blueprint:"mutated"` } type FlagExporterProperties struct { @@ -338,10 +338,6 @@ type libraryDecorator struct { flagExporter stripper Stripper - // If we're used as a whole_static_lib, our missing dependencies need - // to be given - wholeStaticMissingDeps []string - // For whole_static_libs objects Objects @@ -682,7 +678,6 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa } type libraryInterface interface { - getWholeStaticMissingDeps() []string static() bool shared() bool objs() Objects @@ -889,8 +884,6 @@ func (library *libraryDecorator) linkStatic(ctx ModuleContext, library.coverageOutputFile = TransformCoverageFilesToZip(ctx, library.objects, ctx.ModuleName()) - library.wholeStaticMissingDeps = ctx.GetMissingDependencies() - ctx.CheckbuildFile(outputFile) return outputFile @@ -1182,10 +1175,6 @@ func (library *libraryDecorator) buildShared() bool { BoolDefault(library.SharedProperties.Shared.Enabled, true) } -func (library *libraryDecorator) getWholeStaticMissingDeps() []string { - return append([]string(nil), library.wholeStaticMissingDeps...) -} - func (library *libraryDecorator) objs() Objects { return library.objects } @@ -1517,56 +1506,39 @@ func LinkageMutator(mctx android.BottomUpMutatorContext) { } } -var stubVersionsKey = android.NewOnceKey("stubVersions") - -// maps a module name to the list of stubs versions available for the module -func stubsVersionsFor(config android.Config) map[string][]string { - return config.Once(stubVersionsKey, func() interface{} { - return make(map[string][]string) - }).(map[string][]string) -} - -var stubsVersionsLock sync.Mutex - -func LatestStubsVersionFor(config android.Config, name string) string { - versions, ok := stubsVersionsFor(config)[name] - if ok && len(versions) > 0 { - // the versions are alreay sorted in ascending order - return versions[len(versions)-1] - } - return "" -} - func normalizeVersions(ctx android.BaseModuleContext, versions []string) { - numVersions := make([]int, len(versions)) + var previous android.ApiLevel for i, v := range versions { - numVer, err := android.ApiStrToNum(ctx, v) + ver, err := android.ApiLevelFromUser(ctx, v) if err != nil { ctx.PropertyErrorf("versions", "%s", err.Error()) return } - numVersions[i] = numVer - } - if !sort.IsSorted(sort.IntSlice(numVersions)) { - ctx.PropertyErrorf("versions", "not sorted: %v", versions) - } - for i, v := range numVersions { - versions[i] = strconv.Itoa(v) + if i > 0 && ver.LessThanOrEqualTo(previous) { + ctx.PropertyErrorf("versions", "not sorted: %v", versions) + } + versions[i] = ver.String() + previous = ver } } func createVersionVariations(mctx android.BottomUpMutatorContext, versions []string) { - // "" is for the non-stubs variant - versions = append([]string{""}, versions...) + // "" is for the non-stubs (implementation) variant. + variants := append([]string{""}, versions...) - modules := mctx.CreateLocalVariations(versions...) + modules := mctx.CreateLocalVariations(variants...) for i, m := range modules { - if versions[i] != "" { + if variants[i] != "" { m.(LinkableInterface).SetBuildStubs() - m.(LinkableInterface).SetStubsVersions(versions[i]) + m.(LinkableInterface).SetStubsVersion(variants[i]) } } mctx.AliasVariation("") + latestVersion := "" + if len(versions) > 0 { + latestVersion = versions[len(versions)-1] + } + mctx.CreateAliasVariation("latest", latestVersion) } func VersionVariantAvailable(module interface { @@ -1577,44 +1549,41 @@ func VersionVariantAvailable(module interface { return !module.Host() && !module.InRamdisk() && !module.InRecovery() } -// VersionMutator splits a module into the mandatory non-stubs variant -// (which is unnamed) and zero or more stubs variants. -func VersionMutator(mctx android.BottomUpMutatorContext) { +// versionSelector normalizes the versions in the Stubs.Versions property into MutatedProperties.AllStubsVersions, +// and propagates the value from implementation libraries to llndk libraries with the same name. +func versionSelectorMutator(mctx android.BottomUpMutatorContext) { if library, ok := mctx.Module().(LinkableInterface); ok && VersionVariantAvailable(library) { if library.CcLibrary() && library.BuildSharedVariant() && len(library.StubsVersions()) > 0 && !library.IsSdkVariant() { + versions := library.StubsVersions() normalizeVersions(mctx, versions) if mctx.Failed() { return } - - stubsVersionsLock.Lock() - defer stubsVersionsLock.Unlock() - // save the list of versions for later use - stubsVersionsFor(mctx.Config())[mctx.ModuleName()] = versions - - createVersionVariations(mctx, versions) + // Set the versions on the pre-mutated module so they can be read by any llndk modules that + // depend on the implementation library and haven't been mutated yet. + library.SetAllStubsVersions(versions) return } if c, ok := library.(*Module); ok && c.IsStubs() { - stubsVersionsLock.Lock() - defer stubsVersionsLock.Unlock() - // For LLNDK llndk_library, we borrow stubs.versions from its implementation library. - // Since llndk_library has dependency to its implementation library, - // we can safely access stubsVersionsFor() with its baseModuleName. - versions := stubsVersionsFor(mctx.Config())[c.BaseModuleName()] - // save the list of versions for later use - stubsVersionsFor(mctx.Config())[mctx.ModuleName()] = versions - - createVersionVariations(mctx, versions) - return + // Get the versions from the implementation module. + impls := mctx.GetDirectDepsWithTag(llndkImplDep) + if len(impls) > 1 { + panic(fmt.Errorf("Expected single implmenetation library, got %d", len(impls))) + } else if len(impls) == 1 { + c.SetAllStubsVersions(impls[0].(*Module).AllStubsVersions()) + } } + } +} - mctx.CreateLocalVariations("") - mctx.AliasVariation("") - return +// versionMutator splits a module into the mandatory non-stubs variant +// (which is unnamed) and zero or more stubs variants. +func versionMutator(mctx android.BottomUpMutatorContext) { + if library, ok := mctx.Module().(LinkableInterface); ok && VersionVariantAvailable(library) { + createVersionVariations(mctx, library.AllStubsVersions()) } } diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go index ecfdc9977..41ce29422 100644 --- a/cc/library_sdk_member.go +++ b/cc/library_sdk_member.go @@ -80,7 +80,7 @@ func (mt *librarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorCont for _, target := range targets { name, version := StubsLibNameAndVersion(lib) if version == "" { - version = LatestStubsVersionFor(mctx.Config(), name) + version = "latest" } variations := target.Variations() if mctx.Device() { @@ -221,10 +221,7 @@ var includeDirProperties = []includeDirsProperty{ // Add properties that may, or may not, be arch specific. func addPossiblyArchSpecificProperties(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, libInfo *nativeLibInfoProperties, outputProperties android.BpPropertySet) { - if libInfo.SanitizeNever { - sanitizeSet := outputProperties.AddPropertySet("sanitize") - sanitizeSet.AddProperty("never", true) - } + outputProperties.AddProperty("sanitize", &libInfo.Sanitize) // Copy the generated library to the snapshot and add a reference to it in the .bp module. if libInfo.outputFile != nil { @@ -295,9 +292,9 @@ func addPossiblyArchSpecificProperties(sdkModuleContext android.ModuleContext, b outputProperties.AddProperty(property, includeDirs[property]) } - if len(libInfo.StubsVersion) > 0 { + if len(libInfo.StubsVersions) > 0 { stubsSet := outputProperties.AddPropertySet("stubs") - stubsSet.AddProperty("versions", []string{libInfo.StubsVersion}) + stubsSet.AddProperty("versions", libInfo.StubsVersions) } } @@ -368,13 +365,15 @@ type nativeLibInfoProperties struct { // The specific stubs version for the lib variant, or empty string if stubs // are not in use. // - // Marked 'ignored-on-host' as the StubsVersion() from which this is initialized is - // not set on host and the stubs.versions property which this is written to is does - // not vary by arch so cannot be android specific. - StubsVersion string `sdk:"ignored-on-host"` + // Marked 'ignored-on-host' as the AllStubsVersions() from which this is + // initialized is not set on host and the stubs.versions property which this + // is written to does not vary by arch so cannot be android specific. + StubsVersions []string `sdk:"ignored-on-host"` - // Value of SanitizeProperties.Sanitize.Never. Needs to be propagated for CRT objects. - SanitizeNever bool `android:"arch_variant"` + // Value of SanitizeProperties.Sanitize. Several - but not all - of these + // affect the expanded variants. All are propagated to avoid entangling the + // sanitizer logic with the snapshot generation. + Sanitize SanitizeUserProps `android:"arch_variant"` // outputFile is not exported as it is always arch specific. outputFile android.Path @@ -420,11 +419,15 @@ func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberConte p.exportedGeneratedHeaders = ccModule.ExportedGeneratedHeaders() if ccModule.HasStubsVariants() { - p.StubsVersion = ccModule.StubsVersion() + // TODO(b/169373910): 1. Only output the specific version (from + // ccModule.StubsVersion()) if the module is versioned. 2. Ensure that all + // the versioned stub libs are retained in the prebuilt tree; currently only + // the stub corresponding to ccModule.StubsVersion() is. + p.StubsVersions = ccModule.AllStubsVersions() } - if ccModule.sanitize != nil && proptools.Bool(ccModule.sanitize.Properties.Sanitize.Never) { - p.SanitizeNever = true + if ccModule.sanitize != nil { + p.Sanitize = ccModule.sanitize.Properties.Sanitize } } diff --git a/cc/library_test.go b/cc/library_test.go index cb167252d..49838b48e 100644 --- a/cc/library_test.go +++ b/cc/library_test.go @@ -195,7 +195,7 @@ func TestStubsVersions(t *testing.T) { name: "libfoo", srcs: ["foo.c"], stubs: { - versions: ["29", "R", "10000"], + versions: ["29", "R", "current"], }, } ` @@ -204,7 +204,7 @@ func TestStubsVersions(t *testing.T) { ctx := testCcWithConfig(t, config) variants := ctx.ModuleVariantsForTests("libfoo") - for _, expectedVer := range []string{"29", "9000", "10000"} { + for _, expectedVer := range []string{"29", "R", "current"} { expectedVariant := "android_arm_armv7-a-neon_shared_" + expectedVer if !inList(expectedVariant, variants) { t.Errorf("missing expected variant: %q", expectedVariant) @@ -218,7 +218,7 @@ func TestStubsVersions_NotSorted(t *testing.T) { name: "libfoo", srcs: ["foo.c"], stubs: { - versions: ["29", "10000", "R"], + versions: ["29", "current", "R"], }, } ` @@ -233,10 +233,10 @@ func TestStubsVersions_ParseError(t *testing.T) { name: "libfoo", srcs: ["foo.c"], stubs: { - versions: ["29", "10000", "X"], + versions: ["29", "current", "X"], }, } ` - testCcError(t, `"libfoo" .*: versions: SDK version should be`, bp) + testCcError(t, `"libfoo" .*: versions: "X" could not be parsed as an integer and is not a recognized codename`, bp) } diff --git a/cc/linkable.go b/cc/linkable.go index 4c8416347..6d8a4b71e 100644 --- a/cc/linkable.go +++ b/cc/linkable.go @@ -26,8 +26,10 @@ type LinkableInterface interface { StubsVersions() []string BuildStubs() bool SetBuildStubs() - SetStubsVersions(string) + SetStubsVersion(string) StubsVersion() string + SetAllStubsVersions([]string) + AllStubsVersions() []string HasStubsVariants() bool SelectedStl() string ApiLevel() string diff --git a/cc/linker.go b/cc/linker.go index 58f8a294e..12c8b2c59 100644 --- a/cc/linker.go +++ b/cc/linker.go @@ -278,19 +278,19 @@ func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps { deps.LateStaticLibs = append(deps.LateStaticLibs, "libatomic") } - systemSharedLibs := linker.Properties.System_shared_libs - if systemSharedLibs == nil { + deps.SystemSharedLibs = linker.Properties.System_shared_libs + if deps.SystemSharedLibs == nil { // Provide a default system_shared_libs if it is unspecified. Note: If an // empty list [] is specified, it implies that the module declines the // default system_shared_libs. - systemSharedLibs = []string{"libc", "libm", "libdl"} + deps.SystemSharedLibs = []string{"libc", "libm", "libdl"} } if inList("libdl", deps.SharedLibs) { // If system_shared_libs has libc but not libdl, make sure shared_libs does not // have libdl to avoid loading libdl before libc. - if inList("libc", systemSharedLibs) { - if !inList("libdl", systemSharedLibs) { + if inList("libc", deps.SystemSharedLibs) { + if !inList("libdl", deps.SystemSharedLibs) { ctx.PropertyErrorf("shared_libs", "libdl must be in system_shared_libs, not shared_libs") } @@ -300,12 +300,12 @@ func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps { // If libc and libdl are both in system_shared_libs make sure libdl comes after libc // to avoid loading libdl before libc. - if inList("libdl", systemSharedLibs) && inList("libc", systemSharedLibs) && - indexList("libdl", systemSharedLibs) < indexList("libc", systemSharedLibs) { + if inList("libdl", deps.SystemSharedLibs) && inList("libc", deps.SystemSharedLibs) && + indexList("libdl", deps.SystemSharedLibs) < indexList("libc", deps.SystemSharedLibs) { ctx.PropertyErrorf("system_shared_libs", "libdl must be after libc") } - deps.LateSharedLibs = append(deps.LateSharedLibs, systemSharedLibs...) + deps.LateSharedLibs = append(deps.LateSharedLibs, deps.SystemSharedLibs...) } if ctx.Fuchsia() { @@ -52,6 +52,9 @@ type LTOProperties struct { // Use clang lld instead of gnu ld. Use_clang_lld *bool + + // Use -fwhole-program-vtables cflag. + Whole_program_vtables *bool } type lto struct { @@ -65,6 +68,14 @@ func (lto *lto) props() []interface{} { func (lto *lto) begin(ctx BaseModuleContext) { if ctx.Config().IsEnvTrue("DISABLE_LTO") { lto.Properties.Lto.Never = boolPtr(true) + } else if ctx.Config().IsEnvTrue("GLOBAL_THINLTO") { + staticLib := ctx.static() && !ctx.staticBinary() + hostBin := ctx.Host() + if !staticLib && !hostBin { + if !lto.Never() && !lto.FullLTO() { + lto.Properties.Lto.Thin = boolPtr(true) + } + } } } @@ -88,7 +99,7 @@ func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags { if lto.LTO() { var ltoFlag string - if Bool(lto.Properties.Lto.Thin) { + if lto.ThinLTO() { ltoFlag = "-flto=thin -fsplit-lto-unit" } else { ltoFlag = "-flto" @@ -97,7 +108,11 @@ func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags { flags.Local.CFlags = append(flags.Local.CFlags, ltoFlag) flags.Local.LdFlags = append(flags.Local.LdFlags, ltoFlag) - if ctx.Config().IsEnvTrue("USE_THINLTO_CACHE") && Bool(lto.Properties.Lto.Thin) && lto.useClangLld(ctx) { + if Bool(lto.Properties.Whole_program_vtables) { + flags.Local.CFlags = append(flags.Local.CFlags, "-fwhole-program-vtables") + } + + if lto.ThinLTO() && ctx.Config().IsEnvTrue("USE_THINLTO_CACHE") && lto.useClangLld(ctx) { // Set appropriate ThinLTO cache policy cacheDirFormat := "-Wl,--thinlto-cache-dir=" cacheDir := android.PathForOutput(ctx, "thinlto-cache").String() @@ -110,12 +125,11 @@ func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags { flags.Local.LdFlags = append(flags.Local.LdFlags, cachePolicyFormat+policy) } - // If the module does not have a profile, be conservative and do not inline - // or unroll loops during LTO, in order to prevent significant size bloat. + // If the module does not have a profile, be conservative and limit cross TU inline + // limit to 5 LLVM IR instructions, to balance binary size increase and performance. if !ctx.isPgoCompile() { flags.Local.LdFlags = append(flags.Local.LdFlags, - "-Wl,-plugin-opt,-inline-threshold=0", - "-Wl,-plugin-opt,-unroll-threshold=0") + "-Wl,-plugin-opt,-import-instr-limit=5") } } return flags @@ -123,25 +137,31 @@ func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags { // Can be called with a null receiver func (lto *lto) LTO() bool { - if lto == nil || lto.Disabled() { + if lto == nil || lto.Never() { return false } - full := Bool(lto.Properties.Lto.Full) - thin := Bool(lto.Properties.Lto.Thin) - return full || thin + return lto.FullLTO() || lto.ThinLTO() +} + +func (lto *lto) FullLTO() bool { + return Bool(lto.Properties.Lto.Full) +} + +func (lto *lto) ThinLTO() bool { + return Bool(lto.Properties.Lto.Thin) } // Is lto.never explicitly set to true? -func (lto *lto) Disabled() bool { - return lto.Properties.Lto.Never != nil && *lto.Properties.Lto.Never +func (lto *lto) Never() bool { + return Bool(lto.Properties.Lto.Never) } // Propagate lto requirements down from binaries func ltoDepsMutator(mctx android.TopDownMutatorContext) { if m, ok := mctx.Module().(*Module); ok && m.lto.LTO() { - full := Bool(m.lto.Properties.Lto.Full) - thin := Bool(m.lto.Properties.Lto.Thin) + full := m.lto.FullLTO() + thin := m.lto.ThinLTO() if full && thin { mctx.PropertyErrorf("LTO", "FullLTO and ThinLTO are mutually exclusive") } @@ -162,11 +182,11 @@ func ltoDepsMutator(mctx android.TopDownMutatorContext) { } if dep, ok := dep.(*Module); ok && dep.lto != nil && - !dep.lto.Disabled() { - if full && !Bool(dep.lto.Properties.Lto.Full) { + !dep.lto.Never() { + if full && !dep.lto.FullLTO() { dep.lto.Properties.FullDep = true } - if thin && !Bool(dep.lto.Properties.Lto.Thin) { + if thin && !dep.lto.ThinLTO() { dep.lto.Properties.ThinDep = true } } @@ -183,19 +203,19 @@ func ltoMutator(mctx android.BottomUpMutatorContext) { // Create variations for LTO types required as static // dependencies variationNames := []string{""} - if m.lto.Properties.FullDep && !Bool(m.lto.Properties.Lto.Full) { + if m.lto.Properties.FullDep && !m.lto.FullLTO() { variationNames = append(variationNames, "lto-full") } - if m.lto.Properties.ThinDep && !Bool(m.lto.Properties.Lto.Thin) { + if m.lto.Properties.ThinDep && !m.lto.ThinLTO() { variationNames = append(variationNames, "lto-thin") } // Use correct dependencies if LTO property is explicitly set // (mutually exclusive) - if Bool(m.lto.Properties.Lto.Full) { + if m.lto.FullLTO() { mctx.SetDependencyVariation("lto-full") } - if Bool(m.lto.Properties.Lto.Thin) { + if m.lto.ThinLTO() { mctx.SetDependencyVariation("lto-thin") } diff --git a/cc/ndk_library.go b/cc/ndk_library.go index fe3efc01e..5682d1c6b 100644 --- a/cc/ndk_library.go +++ b/cc/ndk_library.go @@ -16,7 +16,6 @@ package cc import ( "fmt" - "strconv" "strings" "sync" @@ -52,6 +51,10 @@ var ( ndkKnownLibsLock sync.Mutex ) +// The First_version and Unversioned_until properties of this struct should not +// be used directly, but rather through the ApiLevel returning methods +// firstVersion() and unversionedUntil(). + // Creates a stub shared library based on the provided version file. // // Example: @@ -77,9 +80,7 @@ type libraryProperties struct { // https://github.com/android-ndk/ndk/issues/265. Unversioned_until *string - // Private property for use by the mutator that splits per-API level. Can be - // one of <number:sdk_version> or <codename> or "current" passed to - // "ndkstubgen.py" as it is + // Use via apiLevel on the stubDecorator. ApiLevel string `blueprint:"mutated"` // True if this API is not yet ready to be shipped in the NDK. It will be @@ -96,125 +97,33 @@ type stubDecorator struct { versionScriptPath android.ModuleGenPath parsedCoverageXmlPath android.ModuleOutPath installPath android.Path -} - -// OMG GO -func intMax(a int, b int) int { - if a > b { - return a - } else { - return b - } -} - -func normalizeNdkApiLevel(ctx android.BaseModuleContext, apiLevel string, - arch android.Arch) (string, error) { - - if apiLevel == "" { - panic("empty apiLevel not allowed") - } - - if apiLevel == "current" { - return apiLevel, nil - } - - minVersion := ctx.Config().MinSupportedSdkVersion() - firstArchVersions := map[android.ArchType]int{ - android.Arm: minVersion, - android.Arm64: 21, - android.X86: minVersion, - android.X86_64: 21, - } - - firstArchVersion, ok := firstArchVersions[arch.ArchType] - if !ok { - panic(fmt.Errorf("Arch %q not found in firstArchVersions", arch.ArchType)) - } - - if apiLevel == "minimum" { - return strconv.Itoa(firstArchVersion), nil - } - // If the NDK drops support for a platform version, we don't want to have to - // fix up every module that was using it as its SDK version. Clip to the - // supported version here instead. - version, err := strconv.Atoi(apiLevel) - if err != nil { - // Non-integer API levels are codenames. - return apiLevel, nil - } - version = intMax(version, minVersion) - - return strconv.Itoa(intMax(version, firstArchVersion)), nil + apiLevel android.ApiLevel + firstVersion android.ApiLevel + unversionedUntil android.ApiLevel } -func getFirstGeneratedVersion(firstSupportedVersion string, platformVersion int) (int, error) { - if firstSupportedVersion == "current" { - return platformVersion + 1, nil - } - - return strconv.Atoi(firstSupportedVersion) -} - -func shouldUseVersionScript(ctx android.BaseModuleContext, stub *stubDecorator) (bool, error) { - // unversioned_until is normally empty, in which case we should use the version script. - if String(stub.properties.Unversioned_until) == "" { - return true, nil - } - - if String(stub.properties.Unversioned_until) == "current" { - if stub.properties.ApiLevel == "current" { - return true, nil - } else { - return false, nil - } - } - - if stub.properties.ApiLevel == "current" { - return true, nil - } - - unversionedUntil, err := android.ApiStrToNum(ctx, String(stub.properties.Unversioned_until)) - if err != nil { - return true, err - } - - version, err := android.ApiStrToNum(ctx, stub.properties.ApiLevel) - if err != nil { - return true, err - } - - return version >= unversionedUntil, nil +func shouldUseVersionScript(ctx BaseModuleContext, stub *stubDecorator) bool { + return stub.apiLevel.GreaterThanOrEqualTo(stub.unversionedUntil) } func generatePerApiVariants(ctx android.BottomUpMutatorContext, m *Module, - propName string, propValue string, perSplit func(*Module, string)) { - platformVersion := ctx.Config().PlatformSdkVersionInt() - - firstSupportedVersion, err := normalizeNdkApiLevel(ctx, propValue, - ctx.Arch()) - if err != nil { - ctx.PropertyErrorf(propName, err.Error()) - } - - firstGenVersion, err := getFirstGeneratedVersion(firstSupportedVersion, - platformVersion) - if err != nil { - // In theory this is impossible because we've already run this through - // normalizeNdkApiLevel above. - ctx.PropertyErrorf(propName, err.Error()) - } - - var versionStrs []string - for version := firstGenVersion; version <= platformVersion; version++ { - versionStrs = append(versionStrs, strconv.Itoa(version)) + from android.ApiLevel, perSplit func(*Module, android.ApiLevel)) { + + var versions []android.ApiLevel + versionStrs := []string{} + for _, version := range ctx.Config().AllSupportedApiLevels() { + if version.GreaterThanOrEqualTo(from) { + versions = append(versions, version) + versionStrs = append(versionStrs, version.String()) + } } - versionStrs = append(versionStrs, ctx.Config().PlatformVersionActiveCodenames()...) - versionStrs = append(versionStrs, "current") + versions = append(versions, android.FutureApiLevel) + versionStrs = append(versionStrs, android.FutureApiLevel.String()) modules := ctx.CreateVariations(versionStrs...) for i, module := range modules { - perSplit(module.(*Module), versionStrs[i]) + perSplit(module.(*Module), versions[i]) } } @@ -228,25 +137,56 @@ func NdkApiMutator(ctx android.BottomUpMutatorContext) { ctx.Module().Disable() return } - generatePerApiVariants(ctx, m, "first_version", - String(compiler.properties.First_version), - func(m *Module, version string) { + firstVersion, err := nativeApiLevelFromUser(ctx, + String(compiler.properties.First_version)) + if err != nil { + ctx.PropertyErrorf("first_version", err.Error()) + return + } + generatePerApiVariants(ctx, m, firstVersion, + func(m *Module, version android.ApiLevel) { m.compiler.(*stubDecorator).properties.ApiLevel = - version + version.String() }) } else if m.SplitPerApiLevel() && m.IsSdkVariant() { if ctx.Os() != android.Android { return } - generatePerApiVariants(ctx, m, "min_sdk_version", - m.MinSdkVersion(), func(m *Module, version string) { - m.Properties.Sdk_version = &version + from, err := nativeApiLevelFromUser(ctx, m.MinSdkVersion()) + if err != nil { + ctx.PropertyErrorf("min_sdk_version", err.Error()) + return + } + generatePerApiVariants(ctx, m, from, + func(m *Module, version android.ApiLevel) { + m.Properties.Sdk_version = StringPtr(version.String()) }) } } } } +func (this *stubDecorator) initializeProperties(ctx BaseModuleContext) bool { + this.apiLevel = nativeApiLevelOrPanic(ctx, this.properties.ApiLevel) + + var err error + this.firstVersion, err = nativeApiLevelFromUser(ctx, + String(this.properties.First_version)) + if err != nil { + ctx.PropertyErrorf("first_version", err.Error()) + return false + } + + this.unversionedUntil, err = nativeApiLevelFromUserWithDefault(ctx, + String(this.properties.Unversioned_until), "minimum") + if err != nil { + ctx.PropertyErrorf("unversioned_until", err.Error()) + return false + } + + return true +} + func (c *stubDecorator) compilerInit(ctx BaseModuleContext) { c.baseCompiler.compilerInit(ctx) @@ -340,11 +280,16 @@ func (c *stubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) O ctx.PropertyErrorf("symbol_file", "must end with .map.txt") } + if !c.initializeProperties(ctx) { + // Emits its own errors, so we don't need to. + return Objects{} + } + symbolFile := String(c.properties.Symbol_file) objs, versionScript := compileStubLibrary(ctx, flags, symbolFile, - c.properties.ApiLevel, "") + c.apiLevel.String(), "") c.versionScriptPath = versionScript - if c.properties.ApiLevel == "current" && ctx.PrimaryArch() { + if c.apiLevel.IsCurrent() && ctx.PrimaryArch() { c.parsedCoverageXmlPath = parseSymbolFileForCoverage(ctx, symbolFile) } return objs @@ -366,12 +311,7 @@ func (stub *stubDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags { func (stub *stubDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path { - useVersionScript, err := shouldUseVersionScript(ctx, stub) - if err != nil { - ctx.ModuleErrorf(err.Error()) - } - - if useVersionScript { + if shouldUseVersionScript(ctx, stub) { linkerScriptFlag := "-Wl,--version-script," + stub.versionScriptPath.String() flags.Local.LdFlags = append(flags.Local.LdFlags, linkerScriptFlag) flags.LdFlagsDeps = append(flags.LdFlagsDeps, stub.versionScriptPath) @@ -386,8 +326,6 @@ func (stub *stubDecorator) nativeCoverage() bool { func (stub *stubDecorator) install(ctx ModuleContext, path android.Path) { arch := ctx.Target().Arch.ArchType.Name - apiLevel := stub.properties.ApiLevel - // arm64 isn't actually a multilib toolchain, so unlike the other LP64 // architectures it's just installed to lib. libDir := "lib" @@ -396,7 +334,7 @@ func (stub *stubDecorator) install(ctx ModuleContext, path android.Path) { } installDir := getNdkInstallBase(ctx).Join(ctx, fmt.Sprintf( - "platforms/android-%s/arch-%s/usr/%s", apiLevel, arch, libDir)) + "platforms/android-%s/arch-%s/usr/%s", stub.apiLevel, arch, libDir)) stub.installPath = ctx.InstallFile(installDir, path.Base(), path) } diff --git a/cc/ndkstubgen/__init__.py b/cc/ndkstubgen/__init__.py index 2f4326a9c..86bf6ff85 100755 --- a/cc/ndkstubgen/__init__.py +++ b/cc/ndkstubgen/__init__.py @@ -20,13 +20,16 @@ import json import logging import os import sys +from typing import Iterable, TextIO import symbolfile +from symbolfile import Arch, Version class Generator: """Output generator that writes stub source files and version scripts.""" - def __init__(self, src_file, version_script, arch, api, llndk, apex): + def __init__(self, src_file: TextIO, version_script: TextIO, arch: Arch, + api: int, llndk: bool, apex: bool) -> None: self.src_file = src_file self.version_script = version_script self.arch = arch @@ -34,12 +37,12 @@ class Generator: self.llndk = llndk self.apex = apex - def write(self, versions): + def write(self, versions: Iterable[Version]) -> None: """Writes all symbol data to the output files.""" for version in versions: self.write_version(version) - def write_version(self, version): + def write_version(self, version: Version) -> None: """Writes a single version block's data to the output files.""" if symbolfile.should_omit_version(version, self.arch, self.api, self.llndk, self.apex): @@ -84,7 +87,7 @@ class Generator: self.version_script.write('}' + base + ';\n') -def parse_args(): +def parse_args() -> argparse.Namespace: """Parses and returns command line arguments.""" parser = argparse.ArgumentParser() @@ -100,23 +103,31 @@ def parse_args(): parser.add_argument( '--apex', action='store_true', help='Use the APEX variant.') + # https://github.com/python/mypy/issues/1317 + # mypy has issues with using os.path.realpath as an argument here. parser.add_argument( - '--api-map', type=os.path.realpath, required=True, + '--api-map', + type=os.path.realpath, # type: ignore + required=True, help='Path to the API level map JSON file.') parser.add_argument( - 'symbol_file', type=os.path.realpath, help='Path to symbol file.') + 'symbol_file', + type=os.path.realpath, # type: ignore + help='Path to symbol file.') parser.add_argument( - 'stub_src', type=os.path.realpath, + 'stub_src', + type=os.path.realpath, # type: ignore help='Path to output stub source file.') parser.add_argument( - 'version_script', type=os.path.realpath, + 'version_script', + type=os.path.realpath, # type: ignore help='Path to output version script.') return parser.parse_args() -def main(): +def main() -> None: """Program entry point.""" args = parse_args() diff --git a/cc/ndkstubgen/mypy.ini b/cc/ndkstubgen/mypy.ini new file mode 100644 index 000000000..82aa7eb9d --- /dev/null +++ b/cc/ndkstubgen/mypy.ini @@ -0,0 +1,2 @@ +[mypy] +disallow_untyped_defs = True diff --git a/cc/ndkstubgen/test_ndkstubgen.py b/cc/ndkstubgen/test_ndkstubgen.py index 70bcf781c..6d2c9d673 100755 --- a/cc/ndkstubgen/test_ndkstubgen.py +++ b/cc/ndkstubgen/test_ndkstubgen.py @@ -21,19 +21,20 @@ import unittest import ndkstubgen import symbolfile +from symbolfile import Arch, Tag # pylint: disable=missing-docstring class GeneratorTest(unittest.TestCase): - def test_omit_version(self): + def test_omit_version(self) -> None: # Thorough testing of the cases involved here is handled by # OmitVersionTest, PrivateVersionTest, and SymbolPresenceTest. src_file = io.StringIO() version_file = io.StringIO() - generator = ndkstubgen.Generator(src_file, version_file, 'arm', 9, - False, False) + generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'), + 9, False, False) version = symbolfile.Version('VERSION_PRIVATE', None, [], [ symbolfile.Symbol('foo', []), @@ -42,74 +43,75 @@ class GeneratorTest(unittest.TestCase): self.assertEqual('', src_file.getvalue()) self.assertEqual('', version_file.getvalue()) - version = symbolfile.Version('VERSION', None, ['x86'], [ + version = symbolfile.Version('VERSION', None, [Tag('x86')], [ symbolfile.Symbol('foo', []), ]) generator.write_version(version) self.assertEqual('', src_file.getvalue()) self.assertEqual('', version_file.getvalue()) - version = symbolfile.Version('VERSION', None, ['introduced=14'], [ + version = symbolfile.Version('VERSION', None, [Tag('introduced=14')], [ symbolfile.Symbol('foo', []), ]) generator.write_version(version) self.assertEqual('', src_file.getvalue()) self.assertEqual('', version_file.getvalue()) - def test_omit_symbol(self): + def test_omit_symbol(self) -> None: # Thorough testing of the cases involved here is handled by # SymbolPresenceTest. src_file = io.StringIO() version_file = io.StringIO() - generator = ndkstubgen.Generator(src_file, version_file, 'arm', 9, - False, False) + generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'), + 9, False, False) version = symbolfile.Version('VERSION_1', None, [], [ - symbolfile.Symbol('foo', ['x86']), + symbolfile.Symbol('foo', [Tag('x86')]), ]) generator.write_version(version) self.assertEqual('', src_file.getvalue()) self.assertEqual('', version_file.getvalue()) version = symbolfile.Version('VERSION_1', None, [], [ - symbolfile.Symbol('foo', ['introduced=14']), + symbolfile.Symbol('foo', [Tag('introduced=14')]), ]) generator.write_version(version) self.assertEqual('', src_file.getvalue()) self.assertEqual('', version_file.getvalue()) version = symbolfile.Version('VERSION_1', None, [], [ - symbolfile.Symbol('foo', ['llndk']), + symbolfile.Symbol('foo', [Tag('llndk')]), ]) generator.write_version(version) self.assertEqual('', src_file.getvalue()) self.assertEqual('', version_file.getvalue()) version = symbolfile.Version('VERSION_1', None, [], [ - symbolfile.Symbol('foo', ['apex']), + symbolfile.Symbol('foo', [Tag('apex')]), ]) generator.write_version(version) self.assertEqual('', src_file.getvalue()) self.assertEqual('', version_file.getvalue()) - def test_write(self): + def test_write(self) -> None: src_file = io.StringIO() version_file = io.StringIO() - generator = ndkstubgen.Generator(src_file, version_file, 'arm', 9, - False, False) + generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'), + 9, False, False) versions = [ symbolfile.Version('VERSION_1', None, [], [ symbolfile.Symbol('foo', []), - symbolfile.Symbol('bar', ['var']), - symbolfile.Symbol('woodly', ['weak']), - symbolfile.Symbol('doodly', ['weak', 'var']), + symbolfile.Symbol('bar', [Tag('var')]), + symbolfile.Symbol('woodly', [Tag('weak')]), + symbolfile.Symbol('doodly', + [Tag('weak'), Tag('var')]), ]), symbolfile.Version('VERSION_2', 'VERSION_1', [], [ symbolfile.Symbol('baz', []), ]), symbolfile.Version('VERSION_3', 'VERSION_1', [], [ - symbolfile.Symbol('qux', ['versioned=14']), + symbolfile.Symbol('qux', [Tag('versioned=14')]), ]), ] @@ -141,7 +143,7 @@ class GeneratorTest(unittest.TestCase): class IntegrationTest(unittest.TestCase): - def test_integration(self): + def test_integration(self) -> None: api_map = { 'O': 9000, 'P': 9001, @@ -178,14 +180,14 @@ class IntegrationTest(unittest.TestCase): wobble; } VERSION_4; """)) - parser = symbolfile.SymbolFileParser(input_file, api_map, 'arm', 9, - False, False) + parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'), + 9, False, False) versions = parser.parse() src_file = io.StringIO() version_file = io.StringIO() - generator = ndkstubgen.Generator(src_file, version_file, 'arm', 9, - False, False) + generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'), + 9, False, False) generator.write(versions) expected_src = textwrap.dedent("""\ @@ -213,7 +215,7 @@ class IntegrationTest(unittest.TestCase): """) self.assertEqual(expected_version, version_file.getvalue()) - def test_integration_future_api(self): + def test_integration_future_api(self) -> None: api_map = { 'O': 9000, 'P': 9001, @@ -230,14 +232,14 @@ class IntegrationTest(unittest.TestCase): *; }; """)) - parser = symbolfile.SymbolFileParser(input_file, api_map, 'arm', 9001, - False, False) + parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'), + 9001, False, False) versions = parser.parse() src_file = io.StringIO() version_file = io.StringIO() - generator = ndkstubgen.Generator(src_file, version_file, 'arm', 9001, - False, False) + generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'), + 9001, False, False) generator.write(versions) expected_src = textwrap.dedent("""\ @@ -255,7 +257,7 @@ class IntegrationTest(unittest.TestCase): """) self.assertEqual(expected_version, version_file.getvalue()) - def test_multiple_definition(self): + def test_multiple_definition(self) -> None: input_file = io.StringIO(textwrap.dedent("""\ VERSION_1 { global: @@ -280,8 +282,8 @@ class IntegrationTest(unittest.TestCase): } VERSION_2; """)) - parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, - False) + parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, + False, False) with self.assertRaises( symbolfile.MultiplyDefinedSymbolError) as ex_context: @@ -289,7 +291,7 @@ class IntegrationTest(unittest.TestCase): self.assertEqual(['bar', 'foo'], ex_context.exception.multiply_defined_symbols) - def test_integration_with_apex(self): + def test_integration_with_apex(self) -> None: api_map = { 'O': 9000, 'P': 9001, @@ -328,14 +330,14 @@ class IntegrationTest(unittest.TestCase): wobble; } VERSION_4; """)) - parser = symbolfile.SymbolFileParser(input_file, api_map, 'arm', 9, - False, True) + parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'), + 9, False, True) versions = parser.parse() src_file = io.StringIO() version_file = io.StringIO() - generator = ndkstubgen.Generator(src_file, version_file, 'arm', 9, - False, True) + generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'), + 9, False, True) generator.write(versions) expected_src = textwrap.dedent("""\ @@ -369,7 +371,8 @@ class IntegrationTest(unittest.TestCase): """) self.assertEqual(expected_version, version_file.getvalue()) -def main(): + +def main() -> None: suite = unittest.TestLoader().loadTestsFromName(__name__) unittest.TextTestRunner(verbosity=3).run(suite) @@ -70,6 +70,7 @@ type PgoProperties struct { PgoPresent bool `blueprint:"mutated"` ShouldProfileModule bool `blueprint:"mutated"` PgoCompile bool `blueprint:"mutated"` + PgoInstrLink bool `blueprint:"mutated"` } type pgo struct { @@ -89,13 +90,12 @@ func (pgo *pgo) props() []interface{} { } func (props *PgoProperties) addInstrumentationProfileGatherFlags(ctx ModuleContext, flags Flags) Flags { - flags.Local.CFlags = append(flags.Local.CFlags, props.Pgo.Cflags...) - - flags.Local.CFlags = append(flags.Local.CFlags, profileInstrumentFlag) - // The profile runtime is added below in deps(). Add the below - // flag, which is the only other link-time action performed by - // the Clang driver during link. - flags.Local.LdFlags = append(flags.Local.LdFlags, "-u__llvm_profile_runtime") + // Add to C flags iff PGO is explicitly enabled for this module. + if props.ShouldProfileModule { + flags.Local.CFlags = append(flags.Local.CFlags, props.Pgo.Cflags...) + flags.Local.CFlags = append(flags.Local.CFlags, profileInstrumentFlag) + } + flags.Local.LdFlags = append(flags.Local.LdFlags, profileInstrumentFlag) return flags } func (props *PgoProperties) addSamplingProfileGatherFlags(ctx ModuleContext, flags Flags) Flags { @@ -250,10 +250,12 @@ func (pgo *pgo) begin(ctx BaseModuleContext) { if pgoBenchmarksMap["all"] == true || pgoBenchmarksMap["ALL"] == true { pgo.Properties.ShouldProfileModule = true + pgo.Properties.PgoInstrLink = pgo.Properties.isInstrumentation() } else { for _, b := range pgo.Properties.Pgo.Benchmarks { if pgoBenchmarksMap[b] == true { pgo.Properties.ShouldProfileModule = true + pgo.Properties.PgoInstrLink = pgo.Properties.isInstrumentation() break } } @@ -286,10 +288,42 @@ func (pgo *pgo) flags(ctx ModuleContext, flags Flags) Flags { return flags } - props := pgo.Properties + // Deduce PgoInstrLink property i.e. whether this module needs to be + // linked with profile-generation flags. Here, we're setting it if any + // dependency needs PGO instrumentation. It is initially set in + // begin() if PGO is directly enabled for this module. + if ctx.static() && !ctx.staticBinary() { + // For static libraries, check if any whole_static_libs are + // linked with profile generation + ctx.VisitDirectDeps(func(m android.Module) { + if depTag, ok := ctx.OtherModuleDependencyTag(m).(libraryDependencyTag); ok { + if depTag.static() && depTag.wholeStatic { + if cc, ok := m.(*Module); ok { + if cc.pgo.Properties.PgoInstrLink { + pgo.Properties.PgoInstrLink = true + } + } + } + } + }) + } else { + // For executables and shared libraries, check all static dependencies. + ctx.VisitDirectDeps(func(m android.Module) { + if depTag, ok := ctx.OtherModuleDependencyTag(m).(libraryDependencyTag); ok { + if depTag.static() { + if cc, ok := m.(*Module); ok { + if cc.pgo.Properties.PgoInstrLink { + pgo.Properties.PgoInstrLink = true + } + } + } + } + }) + } + props := pgo.Properties // Add flags to profile this module based on its profile_kind - if props.ShouldProfileModule && props.isInstrumentation() { + 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() { diff --git a/cc/prebuilt.go b/cc/prebuilt.go index 1ee096e18..9d1b01608 100644 --- a/cc/prebuilt.go +++ b/cc/prebuilt.go @@ -16,6 +16,7 @@ package cc import ( "android/soong/android" + "path/filepath" ) func init() { @@ -360,13 +361,18 @@ func (p *prebuiltBinaryLinker) link(ctx ModuleContext, sharedLibPaths = append(sharedLibPaths, deps.SharedLibs...) sharedLibPaths = append(sharedLibPaths, deps.LateSharedLibs...) + var fromPath = in.String() + if !filepath.IsAbs(fromPath) { + fromPath = "$$PWD/" + fromPath + } + ctx.Build(pctx, android.BuildParams{ Rule: android.Symlink, Output: outputFile, Input: in, Implicits: sharedLibPaths, Args: map[string]string{ - "fromPath": "$$PWD/" + in.String(), + "fromPath": fromPath, }, }) diff --git a/cc/sanitize.go b/cc/sanitize.go index 174dcfea5..43198c16e 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -139,56 +139,59 @@ func (t sanitizerType) incompatibleWithCfi() bool { return t == asan || t == fuzzer || t == hwasan } -type SanitizeProperties struct { - // enable AddressSanitizer, ThreadSanitizer, or UndefinedBehaviorSanitizer - Sanitize struct { - Never *bool `android:"arch_variant"` - - // main sanitizers - Address *bool `android:"arch_variant"` - Thread *bool `android:"arch_variant"` - Hwaddress *bool `android:"arch_variant"` - - // local sanitizers +type SanitizeUserProps struct { + Never *bool `android:"arch_variant"` + + // main sanitizers + Address *bool `android:"arch_variant"` + Thread *bool `android:"arch_variant"` + Hwaddress *bool `android:"arch_variant"` + + // local sanitizers + Undefined *bool `android:"arch_variant"` + All_undefined *bool `android:"arch_variant"` + Misc_undefined []string `android:"arch_variant"` + Fuzzer *bool `android:"arch_variant"` + Safestack *bool `android:"arch_variant"` + Cfi *bool `android:"arch_variant"` + Integer_overflow *bool `android:"arch_variant"` + Scudo *bool `android:"arch_variant"` + Scs *bool `android:"arch_variant"` + + // A modifier for ASAN and HWASAN for write only instrumentation + Writeonly *bool `android:"arch_variant"` + + // Sanitizers to run in the diagnostic mode (as opposed to the release mode). + // Replaces abort() on error with a human-readable error message. + // Address and Thread sanitizers always run in diagnostic mode. + Diag struct { Undefined *bool `android:"arch_variant"` - All_undefined *bool `android:"arch_variant"` - Misc_undefined []string `android:"arch_variant"` - Fuzzer *bool `android:"arch_variant"` - Safestack *bool `android:"arch_variant"` Cfi *bool `android:"arch_variant"` Integer_overflow *bool `android:"arch_variant"` - Scudo *bool `android:"arch_variant"` - Scs *bool `android:"arch_variant"` - - // A modifier for ASAN and HWASAN for write only instrumentation - Writeonly *bool `android:"arch_variant"` - - // Sanitizers to run in the diagnostic mode (as opposed to the release mode). - // Replaces abort() on error with a human-readable error message. - // Address and Thread sanitizers always run in diagnostic mode. - Diag struct { - Undefined *bool `android:"arch_variant"` - Cfi *bool `android:"arch_variant"` - Integer_overflow *bool `android:"arch_variant"` - Misc_undefined []string `android:"arch_variant"` - No_recover []string - } + Misc_undefined []string `android:"arch_variant"` + No_recover []string + } + + // value to pass to -fsanitize-recover= + Recover []string - // value to pass to -fsanitize-recover= - Recover []string - - // value to pass to -fsanitize-blacklist - Blocklist *string - } `android:"arch_variant"` - - SanitizerEnabled bool `blueprint:"mutated"` - SanitizeDep bool `blueprint:"mutated"` - MinimalRuntimeDep bool `blueprint:"mutated"` - BuiltinsDep bool `blueprint:"mutated"` - UbsanRuntimeDep bool `blueprint:"mutated"` - InSanitizerDir bool `blueprint:"mutated"` - Sanitizers []string `blueprint:"mutated"` - DiagSanitizers []string `blueprint:"mutated"` + // value to pass to -fsanitize-blacklist + Blocklist *string +} + +type SanitizeProperties struct { + // Enable AddressSanitizer, ThreadSanitizer, UndefinedBehaviorSanitizer, and + // others. Please see SanitizerUserProps in build/soong/cc/sanitize.go for + // details. + Sanitize SanitizeUserProps `android:"arch_variant"` + SanitizerEnabled bool `blueprint:"mutated"` + SanitizeDep bool `blueprint:"mutated"` + MinimalRuntimeDep bool `blueprint:"mutated"` + BuiltinsDep bool `blueprint:"mutated"` + UbsanRuntimeDep bool `blueprint:"mutated"` + InSanitizerDir bool `blueprint:"mutated"` + Sanitizers []string `blueprint:"mutated"` + DiagSanitizers []string `blueprint:"mutated"` } type sanitize struct { @@ -1037,7 +1040,7 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { if c.Device() { variations = append(variations, c.ImageVariation()) } - mctx.AddFarVariationDependencies(variations, depTag, runtimeLibrary) + c.addSharedLibDependenciesWithVersions(mctx, variations, depTag, runtimeLibrary, "", true) } // static lib does not have dependency to the runtime library. The // dependency will be added to the executables or shared libs using @@ -17,7 +17,6 @@ package cc import ( "android/soong/android" "fmt" - "strconv" ) func getNdkStlFamily(m LinkableInterface) string { @@ -136,23 +135,8 @@ func (stl *stl) begin(ctx BaseModuleContext) { } func needsLibAndroidSupport(ctx BaseModuleContext) bool { - versionStr, err := normalizeNdkApiLevel(ctx, ctx.sdkVersion(), ctx.Arch()) - if err != nil { - ctx.PropertyErrorf("sdk_version", err.Error()) - } - - if versionStr == "current" { - return false - } - - version, err := strconv.Atoi(versionStr) - if err != nil { - panic(fmt.Sprintf( - "invalid API level returned from normalizeNdkApiLevel: %q", - versionStr)) - } - - return version < 21 + version := nativeApiLevelOrPanic(ctx, ctx.sdkVersion()) + return version.LessThan(android.FirstNonLibAndroidSupportVersion) } func staticUnwinder(ctx android.BaseModuleContext) string { diff --git a/cc/symbolfile/__init__.py b/cc/symbolfile/__init__.py index faa3823f3..5678e7d83 100644 --- a/cc/symbolfile/__init__.py +++ b/cc/symbolfile/__init__.py @@ -14,15 +14,31 @@ # limitations under the License. # """Parser for Android's version script information.""" +from dataclasses import dataclass import logging import re +from typing import ( + Dict, + Iterable, + List, + Mapping, + NewType, + Optional, + TextIO, + Tuple, +) + + +ApiMap = Mapping[str, int] +Arch = NewType('Arch', str) +Tag = NewType('Tag', str) ALL_ARCHITECTURES = ( - 'arm', - 'arm64', - 'x86', - 'x86_64', + Arch('arm'), + Arch('arm64'), + Arch('x86'), + Arch('x86_64'), ) @@ -30,18 +46,36 @@ ALL_ARCHITECTURES = ( FUTURE_API_LEVEL = 10000 -def logger(): +def logger() -> logging.Logger: """Return the main logger for this module.""" return logging.getLogger(__name__) -def get_tags(line): +@dataclass +class Symbol: + """A symbol definition from a symbol file.""" + + name: str + tags: List[Tag] + + +@dataclass +class Version: + """A version block of a symbol file.""" + + name: str + base: Optional[str] + tags: List[Tag] + symbols: List[Symbol] + + +def get_tags(line: str) -> List[Tag]: """Returns a list of all tags on this line.""" _, _, all_tags = line.strip().partition('#') - return [e for e in re.split(r'\s+', all_tags) if e.strip()] + return [Tag(e) for e in re.split(r'\s+', all_tags) if e.strip()] -def is_api_level_tag(tag): +def is_api_level_tag(tag: Tag) -> bool: """Returns true if this tag has an API level that may need decoding.""" if tag.startswith('introduced='): return True @@ -52,7 +86,7 @@ def is_api_level_tag(tag): return False -def decode_api_level(api, api_map): +def decode_api_level(api: str, api_map: ApiMap) -> int: """Decodes the API level argument into the API level number. For the average case, this just decodes the integer value from the string, @@ -70,12 +104,13 @@ def decode_api_level(api, api_map): return api_map[api] -def decode_api_level_tags(tags, api_map): +def decode_api_level_tags(tags: Iterable[Tag], api_map: ApiMap) -> List[Tag]: """Decodes API level code names in a list of tags. Raises: ParseError: An unknown version name was found in a tag. """ + decoded_tags = list(tags) for idx, tag in enumerate(tags): if not is_api_level_tag(tag): continue @@ -83,13 +118,13 @@ def decode_api_level_tags(tags, api_map): try: decoded = str(decode_api_level(value, api_map)) - tags[idx] = '='.join([name, decoded]) + decoded_tags[idx] = Tag('='.join([name, decoded])) except KeyError: - raise ParseError('Unknown version name in tag: {}'.format(tag)) - return tags + raise ParseError(f'Unknown version name in tag: {tag}') + return decoded_tags -def split_tag(tag): +def split_tag(tag: Tag) -> Tuple[str, str]: """Returns a key/value tuple of the tag. Raises: @@ -103,7 +138,7 @@ def split_tag(tag): return key, value -def get_tag_value(tag): +def get_tag_value(tag: Tag) -> str: """Returns the value of a key/value tag. Raises: @@ -114,12 +149,13 @@ def get_tag_value(tag): return split_tag(tag)[1] -def version_is_private(version): +def version_is_private(version: str) -> bool: """Returns True if the version name should be treated as private.""" return version.endswith('_PRIVATE') or version.endswith('_PLATFORM') -def should_omit_version(version, arch, api, llndk, apex): +def should_omit_version(version: Version, arch: Arch, api: int, llndk: bool, + apex: bool) -> bool: """Returns True if the version section should be ommitted. We want to omit any sections that do not have any symbols we'll have in the @@ -145,7 +181,8 @@ def should_omit_version(version, arch, api, llndk, apex): return False -def should_omit_symbol(symbol, arch, api, llndk, apex): +def should_omit_symbol(symbol: Symbol, arch: Arch, api: int, llndk: bool, + apex: bool) -> bool: """Returns True if the symbol should be omitted.""" no_llndk_no_apex = 'llndk' not in symbol.tags and 'apex' not in symbol.tags keep = no_llndk_no_apex or \ @@ -160,7 +197,7 @@ def should_omit_symbol(symbol, arch, api, llndk, apex): return False -def symbol_in_arch(tags, arch): +def symbol_in_arch(tags: Iterable[Tag], arch: Arch) -> bool: """Returns true if the symbol is present for the given architecture.""" has_arch_tags = False for tag in tags: @@ -175,7 +212,7 @@ def symbol_in_arch(tags, arch): return not has_arch_tags -def symbol_in_api(tags, arch, api): +def symbol_in_api(tags: Iterable[Tag], arch: Arch, api: int) -> bool: """Returns true if the symbol is present for the given API level.""" introduced_tag = None arch_specific = False @@ -197,7 +234,7 @@ def symbol_in_api(tags, arch, api): return api >= int(get_tag_value(introduced_tag)) -def symbol_versioned_in_api(tags, api): +def symbol_versioned_in_api(tags: Iterable[Tag], api: int) -> bool: """Returns true if the symbol should be versioned for the given API. This models the `versioned=API` tag. This should be a very uncommonly @@ -223,68 +260,40 @@ class ParseError(RuntimeError): class MultiplyDefinedSymbolError(RuntimeError): """A symbol name was multiply defined.""" - def __init__(self, multiply_defined_symbols): - super(MultiplyDefinedSymbolError, self).__init__( + def __init__(self, multiply_defined_symbols: Iterable[str]) -> None: + super().__init__( 'Version script contains multiple definitions for: {}'.format( ', '.join(multiply_defined_symbols))) self.multiply_defined_symbols = multiply_defined_symbols -class Version: - """A version block of a symbol file.""" - def __init__(self, name, base, tags, symbols): - self.name = name - self.base = base - self.tags = tags - self.symbols = symbols - - def __eq__(self, other): - if self.name != other.name: - return False - if self.base != other.base: - return False - if self.tags != other.tags: - return False - if self.symbols != other.symbols: - return False - return True - - -class Symbol: - """A symbol definition from a symbol file.""" - def __init__(self, name, tags): - self.name = name - self.tags = tags - - def __eq__(self, other): - return self.name == other.name and set(self.tags) == set(other.tags) - - class SymbolFileParser: """Parses NDK symbol files.""" - def __init__(self, input_file, api_map, arch, api, llndk, apex): + def __init__(self, input_file: TextIO, api_map: ApiMap, arch: Arch, + api: int, llndk: bool, apex: bool) -> None: self.input_file = input_file self.api_map = api_map self.arch = arch self.api = api self.llndk = llndk self.apex = apex - self.current_line = None + self.current_line: Optional[str] = None - def parse(self): + def parse(self) -> List[Version]: """Parses the symbol file and returns a list of Version objects.""" versions = [] while self.next_line() != '': + assert self.current_line is not None if '{' in self.current_line: versions.append(self.parse_version()) else: raise ParseError( - 'Unexpected contents at top level: ' + self.current_line) + f'Unexpected contents at top level: {self.current_line}') self.check_no_duplicate_symbols(versions) return versions - def check_no_duplicate_symbols(self, versions): + def check_no_duplicate_symbols(self, versions: Iterable[Version]) -> None: """Raises errors for multiply defined symbols. This situation is the normal case when symbol versioning is actually @@ -312,12 +321,13 @@ class SymbolFileParser: raise MultiplyDefinedSymbolError( sorted(list(multiply_defined_symbols))) - def parse_version(self): + def parse_version(self) -> Version: """Parses a single version section and returns a Version object.""" + assert self.current_line is not None name = self.current_line.split('{')[0].strip() tags = get_tags(self.current_line) tags = decode_api_level_tags(tags, self.api_map) - symbols = [] + symbols: List[Symbol] = [] global_scope = True cpp_symbols = False while self.next_line() != '': @@ -333,9 +343,7 @@ class SymbolFileParser: cpp_symbols = False else: base = base.rstrip(';').rstrip() - if base == '': - base = None - return Version(name, base, tags, symbols) + return Version(name, base or None, tags, symbols) elif 'extern "C++" {' in self.current_line: cpp_symbols = True elif not cpp_symbols and ':' in self.current_line: @@ -354,8 +362,9 @@ class SymbolFileParser: pass raise ParseError('Unexpected EOF in version block.') - def parse_symbol(self): + def parse_symbol(self) -> Symbol: """Parses a single symbol line and returns a Symbol object.""" + assert self.current_line is not None if ';' not in self.current_line: raise ParseError( 'Expected ; to terminate symbol: ' + self.current_line) @@ -368,7 +377,7 @@ class SymbolFileParser: tags = decode_api_level_tags(tags, self.api_map) return Symbol(name, tags) - def next_line(self): + def next_line(self) -> str: """Returns the next non-empty non-comment line. A return value of '' indicates EOF. diff --git a/cc/symbolfile/mypy.ini b/cc/symbolfile/mypy.ini new file mode 100644 index 000000000..82aa7eb9d --- /dev/null +++ b/cc/symbolfile/mypy.ini @@ -0,0 +1,2 @@ +[mypy] +disallow_untyped_defs = True diff --git a/cc/symbolfile/test_symbolfile.py b/cc/symbolfile/test_symbolfile.py index c91131fee..92b13999e 100644 --- a/cc/symbolfile/test_symbolfile.py +++ b/cc/symbolfile/test_symbolfile.py @@ -19,12 +19,13 @@ import textwrap import unittest import symbolfile +from symbolfile import Arch, Tag # pylint: disable=missing-docstring class DecodeApiLevelTest(unittest.TestCase): - def test_decode_api_level(self): + def test_decode_api_level(self) -> None: self.assertEqual(9, symbolfile.decode_api_level('9', {})) self.assertEqual(9000, symbolfile.decode_api_level('O', {'O': 9000})) @@ -33,70 +34,73 @@ class DecodeApiLevelTest(unittest.TestCase): class TagsTest(unittest.TestCase): - def test_get_tags_no_tags(self): + def test_get_tags_no_tags(self) -> None: self.assertEqual([], symbolfile.get_tags('')) self.assertEqual([], symbolfile.get_tags('foo bar baz')) - def test_get_tags(self): + def test_get_tags(self) -> None: self.assertEqual(['foo', 'bar'], symbolfile.get_tags('# foo bar')) self.assertEqual(['bar', 'baz'], symbolfile.get_tags('foo # bar baz')) - def test_split_tag(self): - self.assertTupleEqual(('foo', 'bar'), symbolfile.split_tag('foo=bar')) - self.assertTupleEqual(('foo', 'bar=baz'), symbolfile.split_tag('foo=bar=baz')) + def test_split_tag(self) -> None: + self.assertTupleEqual(('foo', 'bar'), + symbolfile.split_tag(Tag('foo=bar'))) + self.assertTupleEqual(('foo', 'bar=baz'), + symbolfile.split_tag(Tag('foo=bar=baz'))) with self.assertRaises(ValueError): - symbolfile.split_tag('foo') + symbolfile.split_tag(Tag('foo')) - def test_get_tag_value(self): - self.assertEqual('bar', symbolfile.get_tag_value('foo=bar')) - self.assertEqual('bar=baz', symbolfile.get_tag_value('foo=bar=baz')) + def test_get_tag_value(self) -> None: + self.assertEqual('bar', symbolfile.get_tag_value(Tag('foo=bar'))) + self.assertEqual('bar=baz', + symbolfile.get_tag_value(Tag('foo=bar=baz'))) with self.assertRaises(ValueError): - symbolfile.get_tag_value('foo') + symbolfile.get_tag_value(Tag('foo')) - def test_is_api_level_tag(self): - self.assertTrue(symbolfile.is_api_level_tag('introduced=24')) - self.assertTrue(symbolfile.is_api_level_tag('introduced-arm=24')) - self.assertTrue(symbolfile.is_api_level_tag('versioned=24')) + def test_is_api_level_tag(self) -> None: + self.assertTrue(symbolfile.is_api_level_tag(Tag('introduced=24'))) + self.assertTrue(symbolfile.is_api_level_tag(Tag('introduced-arm=24'))) + self.assertTrue(symbolfile.is_api_level_tag(Tag('versioned=24'))) # Shouldn't try to process things that aren't a key/value tag. - self.assertFalse(symbolfile.is_api_level_tag('arm')) - self.assertFalse(symbolfile.is_api_level_tag('introduced')) - self.assertFalse(symbolfile.is_api_level_tag('versioned')) + self.assertFalse(symbolfile.is_api_level_tag(Tag('arm'))) + self.assertFalse(symbolfile.is_api_level_tag(Tag('introduced'))) + self.assertFalse(symbolfile.is_api_level_tag(Tag('versioned'))) # We don't support arch specific `versioned` tags. - self.assertFalse(symbolfile.is_api_level_tag('versioned-arm=24')) + self.assertFalse(symbolfile.is_api_level_tag(Tag('versioned-arm=24'))) - def test_decode_api_level_tags(self): + def test_decode_api_level_tags(self) -> None: api_map = { 'O': 9000, 'P': 9001, } tags = [ - 'introduced=9', - 'introduced-arm=14', - 'versioned=16', - 'arm', - 'introduced=O', - 'introduced=P', + Tag('introduced=9'), + Tag('introduced-arm=14'), + Tag('versioned=16'), + Tag('arm'), + Tag('introduced=O'), + Tag('introduced=P'), ] expected_tags = [ - 'introduced=9', - 'introduced-arm=14', - 'versioned=16', - 'arm', - 'introduced=9000', - 'introduced=9001', + Tag('introduced=9'), + Tag('introduced-arm=14'), + Tag('versioned=16'), + Tag('arm'), + Tag('introduced=9000'), + Tag('introduced=9001'), ] self.assertListEqual( expected_tags, symbolfile.decode_api_level_tags(tags, api_map)) with self.assertRaises(symbolfile.ParseError): - symbolfile.decode_api_level_tags(['introduced=O'], {}) + symbolfile.decode_api_level_tags([Tag('introduced=O')], {}) class PrivateVersionTest(unittest.TestCase): - def test_version_is_private(self): + def test_version_is_private(self) -> None: self.assertFalse(symbolfile.version_is_private('foo')) self.assertFalse(symbolfile.version_is_private('PRIVATE')) self.assertFalse(symbolfile.version_is_private('PLATFORM')) @@ -110,191 +114,227 @@ class PrivateVersionTest(unittest.TestCase): class SymbolPresenceTest(unittest.TestCase): - def test_symbol_in_arch(self): - self.assertTrue(symbolfile.symbol_in_arch([], 'arm')) - self.assertTrue(symbolfile.symbol_in_arch(['arm'], 'arm')) - - self.assertFalse(symbolfile.symbol_in_arch(['x86'], 'arm')) - - def test_symbol_in_api(self): - self.assertTrue(symbolfile.symbol_in_api([], 'arm', 9)) - self.assertTrue(symbolfile.symbol_in_api(['introduced=9'], 'arm', 9)) - self.assertTrue(symbolfile.symbol_in_api(['introduced=9'], 'arm', 14)) - self.assertTrue(symbolfile.symbol_in_api(['introduced-arm=9'], 'arm', 14)) - self.assertTrue(symbolfile.symbol_in_api(['introduced-arm=9'], 'arm', 14)) - self.assertTrue(symbolfile.symbol_in_api(['introduced-x86=14'], 'arm', 9)) - self.assertTrue(symbolfile.symbol_in_api( - ['introduced-arm=9', 'introduced-x86=21'], 'arm', 14)) - self.assertTrue(symbolfile.symbol_in_api( - ['introduced=9', 'introduced-x86=21'], 'arm', 14)) - self.assertTrue(symbolfile.symbol_in_api( - ['introduced=21', 'introduced-arm=9'], 'arm', 14)) - self.assertTrue(symbolfile.symbol_in_api( - ['future'], 'arm', symbolfile.FUTURE_API_LEVEL)) - - self.assertFalse(symbolfile.symbol_in_api(['introduced=14'], 'arm', 9)) - self.assertFalse(symbolfile.symbol_in_api(['introduced-arm=14'], 'arm', 9)) - self.assertFalse(symbolfile.symbol_in_api(['future'], 'arm', 9)) - self.assertFalse(symbolfile.symbol_in_api( - ['introduced=9', 'future'], 'arm', 14)) - self.assertFalse(symbolfile.symbol_in_api( - ['introduced-arm=9', 'future'], 'arm', 14)) - self.assertFalse(symbolfile.symbol_in_api( - ['introduced-arm=21', 'introduced-x86=9'], 'arm', 14)) - self.assertFalse(symbolfile.symbol_in_api( - ['introduced=9', 'introduced-arm=21'], 'arm', 14)) - self.assertFalse(symbolfile.symbol_in_api( - ['introduced=21', 'introduced-x86=9'], 'arm', 14)) + def test_symbol_in_arch(self) -> None: + self.assertTrue(symbolfile.symbol_in_arch([], Arch('arm'))) + self.assertTrue(symbolfile.symbol_in_arch([Tag('arm')], Arch('arm'))) + + self.assertFalse(symbolfile.symbol_in_arch([Tag('x86')], Arch('arm'))) + + def test_symbol_in_api(self) -> None: + self.assertTrue(symbolfile.symbol_in_api([], Arch('arm'), 9)) + self.assertTrue( + symbolfile.symbol_in_api([Tag('introduced=9')], Arch('arm'), 9)) + self.assertTrue( + symbolfile.symbol_in_api([Tag('introduced=9')], Arch('arm'), 14)) + self.assertTrue( + symbolfile.symbol_in_api([Tag('introduced-arm=9')], Arch('arm'), + 14)) + self.assertTrue( + symbolfile.symbol_in_api([Tag('introduced-arm=9')], Arch('arm'), + 14)) + self.assertTrue( + symbolfile.symbol_in_api([Tag('introduced-x86=14')], Arch('arm'), + 9)) + self.assertTrue( + symbolfile.symbol_in_api( + [Tag('introduced-arm=9'), + Tag('introduced-x86=21')], Arch('arm'), 14)) + self.assertTrue( + symbolfile.symbol_in_api( + [Tag('introduced=9'), + Tag('introduced-x86=21')], Arch('arm'), 14)) + self.assertTrue( + symbolfile.symbol_in_api( + [Tag('introduced=21'), + Tag('introduced-arm=9')], Arch('arm'), 14)) + self.assertTrue( + symbolfile.symbol_in_api([Tag('future')], Arch('arm'), + symbolfile.FUTURE_API_LEVEL)) + + self.assertFalse( + symbolfile.symbol_in_api([Tag('introduced=14')], Arch('arm'), 9)) + self.assertFalse( + symbolfile.symbol_in_api([Tag('introduced-arm=14')], Arch('arm'), + 9)) + self.assertFalse( + symbolfile.symbol_in_api([Tag('future')], Arch('arm'), 9)) + self.assertFalse( + symbolfile.symbol_in_api( + [Tag('introduced=9'), Tag('future')], Arch('arm'), 14)) + self.assertFalse( + symbolfile.symbol_in_api([Tag('introduced-arm=9'), + Tag('future')], Arch('arm'), 14)) + self.assertFalse( + symbolfile.symbol_in_api( + [Tag('introduced-arm=21'), + Tag('introduced-x86=9')], Arch('arm'), 14)) + self.assertFalse( + symbolfile.symbol_in_api( + [Tag('introduced=9'), + Tag('introduced-arm=21')], Arch('arm'), 14)) + self.assertFalse( + symbolfile.symbol_in_api( + [Tag('introduced=21'), + Tag('introduced-x86=9')], Arch('arm'), 14)) # Interesting edge case: this symbol should be omitted from the # library, but this call should still return true because none of the # tags indiciate that it's not present in this API level. - self.assertTrue(symbolfile.symbol_in_api(['x86'], 'arm', 9)) + self.assertTrue(symbolfile.symbol_in_api([Tag('x86')], Arch('arm'), 9)) - def test_verioned_in_api(self): + def test_verioned_in_api(self) -> None: self.assertTrue(symbolfile.symbol_versioned_in_api([], 9)) - self.assertTrue(symbolfile.symbol_versioned_in_api(['versioned=9'], 9)) - self.assertTrue(symbolfile.symbol_versioned_in_api(['versioned=9'], 14)) + self.assertTrue( + symbolfile.symbol_versioned_in_api([Tag('versioned=9')], 9)) + self.assertTrue( + symbolfile.symbol_versioned_in_api([Tag('versioned=9')], 14)) - self.assertFalse(symbolfile.symbol_versioned_in_api(['versioned=14'], 9)) + self.assertFalse( + symbolfile.symbol_versioned_in_api([Tag('versioned=14')], 9)) class OmitVersionTest(unittest.TestCase): - def test_omit_private(self): + def test_omit_private(self) -> None: self.assertFalse( symbolfile.should_omit_version( - symbolfile.Version('foo', None, [], []), 'arm', 9, False, + symbolfile.Version('foo', None, [], []), Arch('arm'), 9, False, False)) self.assertTrue( symbolfile.should_omit_version( - symbolfile.Version('foo_PRIVATE', None, [], []), 'arm', 9, - False, False)) + symbolfile.Version('foo_PRIVATE', None, [], []), Arch('arm'), + 9, False, False)) self.assertTrue( symbolfile.should_omit_version( - symbolfile.Version('foo_PLATFORM', None, [], []), 'arm', 9, - False, False)) + symbolfile.Version('foo_PLATFORM', None, [], []), Arch('arm'), + 9, False, False)) self.assertTrue( symbolfile.should_omit_version( - symbolfile.Version('foo', None, ['platform-only'], []), 'arm', - 9, False, False)) + symbolfile.Version('foo', None, [Tag('platform-only')], []), + Arch('arm'), 9, False, False)) - def test_omit_llndk(self): + def test_omit_llndk(self) -> None: self.assertTrue( symbolfile.should_omit_version( - symbolfile.Version('foo', None, ['llndk'], []), 'arm', 9, - False, False)) + symbolfile.Version('foo', None, [Tag('llndk')], []), + Arch('arm'), 9, False, False)) self.assertFalse( symbolfile.should_omit_version( - symbolfile.Version('foo', None, [], []), 'arm', 9, True, + symbolfile.Version('foo', None, [], []), Arch('arm'), 9, True, False)) self.assertFalse( symbolfile.should_omit_version( - symbolfile.Version('foo', None, ['llndk'], []), 'arm', 9, True, - False)) + symbolfile.Version('foo', None, [Tag('llndk')], []), + Arch('arm'), 9, True, False)) - def test_omit_apex(self): + def test_omit_apex(self) -> None: self.assertTrue( symbolfile.should_omit_version( - symbolfile.Version('foo', None, ['apex'], []), 'arm', 9, False, - False)) + symbolfile.Version('foo', None, [Tag('apex')], []), + Arch('arm'), 9, False, False)) self.assertFalse( symbolfile.should_omit_version( - symbolfile.Version('foo', None, [], []), 'arm', 9, False, + symbolfile.Version('foo', None, [], []), Arch('arm'), 9, False, True)) self.assertFalse( symbolfile.should_omit_version( - symbolfile.Version('foo', None, ['apex'], []), 'arm', 9, False, - True)) + symbolfile.Version('foo', None, [Tag('apex')], []), + Arch('arm'), 9, False, True)) - def test_omit_arch(self): + def test_omit_arch(self) -> None: self.assertFalse( symbolfile.should_omit_version( - symbolfile.Version('foo', None, [], []), 'arm', 9, False, + symbolfile.Version('foo', None, [], []), Arch('arm'), 9, False, False)) self.assertFalse( symbolfile.should_omit_version( - symbolfile.Version('foo', None, ['arm'], []), 'arm', 9, False, - False)) + symbolfile.Version('foo', None, [Tag('arm')], []), Arch('arm'), + 9, False, False)) self.assertTrue( symbolfile.should_omit_version( - symbolfile.Version('foo', None, ['x86'], []), 'arm', 9, False, - False)) + symbolfile.Version('foo', None, [Tag('x86')], []), Arch('arm'), + 9, False, False)) - def test_omit_api(self): + def test_omit_api(self) -> None: self.assertFalse( symbolfile.should_omit_version( - symbolfile.Version('foo', None, [], []), 'arm', 9, False, + symbolfile.Version('foo', None, [], []), Arch('arm'), 9, False, False)) self.assertFalse( symbolfile.should_omit_version( - symbolfile.Version('foo', None, ['introduced=9'], []), 'arm', - 9, False, False)) + symbolfile.Version('foo', None, [Tag('introduced=9')], []), + Arch('arm'), 9, False, False)) self.assertTrue( symbolfile.should_omit_version( - symbolfile.Version('foo', None, ['introduced=14'], []), 'arm', - 9, False, False)) + symbolfile.Version('foo', None, [Tag('introduced=14')], []), + Arch('arm'), 9, False, False)) class OmitSymbolTest(unittest.TestCase): - def test_omit_llndk(self): + def test_omit_llndk(self) -> None: self.assertTrue( - symbolfile.should_omit_symbol(symbolfile.Symbol('foo', ['llndk']), - 'arm', 9, False, False)) + symbolfile.should_omit_symbol( + symbolfile.Symbol('foo', [Tag('llndk')]), Arch('arm'), 9, + False, False)) self.assertFalse( - symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []), 'arm', - 9, True, False)) + symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []), + Arch('arm'), 9, True, False)) self.assertFalse( - symbolfile.should_omit_symbol(symbolfile.Symbol('foo', ['llndk']), - 'arm', 9, True, False)) + symbolfile.should_omit_symbol( + symbolfile.Symbol('foo', [Tag('llndk')]), Arch('arm'), 9, True, + False)) - def test_omit_apex(self): + def test_omit_apex(self) -> None: self.assertTrue( - symbolfile.should_omit_symbol(symbolfile.Symbol('foo', ['apex']), - 'arm', 9, False, False)) + symbolfile.should_omit_symbol( + symbolfile.Symbol('foo', [Tag('apex')]), Arch('arm'), 9, False, + False)) self.assertFalse( - symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []), 'arm', - 9, False, True)) + symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []), + Arch('arm'), 9, False, True)) self.assertFalse( - symbolfile.should_omit_symbol(symbolfile.Symbol('foo', ['apex']), - 'arm', 9, False, True)) + symbolfile.should_omit_symbol( + symbolfile.Symbol('foo', [Tag('apex')]), Arch('arm'), 9, False, + True)) - def test_omit_arch(self): + def test_omit_arch(self) -> None: self.assertFalse( - symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []), 'arm', - 9, False, False)) + symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []), + Arch('arm'), 9, False, False)) self.assertFalse( - symbolfile.should_omit_symbol(symbolfile.Symbol('foo', ['arm']), - 'arm', 9, False, False)) + symbolfile.should_omit_symbol( + symbolfile.Symbol('foo', [Tag('arm')]), Arch('arm'), 9, False, + False)) self.assertTrue( - symbolfile.should_omit_symbol(symbolfile.Symbol('foo', ['x86']), - 'arm', 9, False, False)) + symbolfile.should_omit_symbol( + symbolfile.Symbol('foo', [Tag('x86')]), Arch('arm'), 9, False, + False)) - def test_omit_api(self): + def test_omit_api(self) -> None: self.assertFalse( - symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []), 'arm', - 9, False, False)) + symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []), + Arch('arm'), 9, False, False)) self.assertFalse( symbolfile.should_omit_symbol( - symbolfile.Symbol('foo', ['introduced=9']), 'arm', 9, False, - False)) + symbolfile.Symbol('foo', [Tag('introduced=9')]), Arch('arm'), + 9, False, False)) self.assertTrue( symbolfile.should_omit_symbol( - symbolfile.Symbol('foo', ['introduced=14']), 'arm', 9, False, - False)) + symbolfile.Symbol('foo', [Tag('introduced=14')]), Arch('arm'), + 9, False, False)) class SymbolFileParseTest(unittest.TestCase): - def test_next_line(self): + def test_next_line(self) -> None: input_file = io.StringIO(textwrap.dedent("""\ foo @@ -302,10 +342,12 @@ class SymbolFileParseTest(unittest.TestCase): # baz qux """)) - parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, False) + parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, + False, False) self.assertIsNone(parser.current_line) self.assertEqual('foo', parser.next_line().strip()) + assert parser.current_line is not None self.assertEqual('foo', parser.current_line.strip()) self.assertEqual('bar', parser.next_line().strip()) @@ -317,7 +359,7 @@ class SymbolFileParseTest(unittest.TestCase): self.assertEqual('', parser.next_line()) self.assertEqual('', parser.current_line) - def test_parse_version(self): + def test_parse_version(self) -> None: input_file = io.StringIO(textwrap.dedent("""\ VERSION_1 { # foo bar baz; @@ -327,7 +369,8 @@ class SymbolFileParseTest(unittest.TestCase): VERSION_2 { } VERSION_1; # asdf """)) - parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, False) + parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, + False, False) parser.next_line() version = parser.parse_version() @@ -337,7 +380,7 @@ class SymbolFileParseTest(unittest.TestCase): expected_symbols = [ symbolfile.Symbol('baz', []), - symbolfile.Symbol('qux', ['woodly', 'doodly']), + symbolfile.Symbol('qux', [Tag('woodly'), Tag('doodly')]), ] self.assertEqual(expected_symbols, version.symbols) @@ -347,32 +390,35 @@ class SymbolFileParseTest(unittest.TestCase): self.assertEqual('VERSION_1', version.base) self.assertEqual([], version.tags) - def test_parse_version_eof(self): + def test_parse_version_eof(self) -> None: input_file = io.StringIO(textwrap.dedent("""\ VERSION_1 { """)) - parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, False) + parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, + False, False) parser.next_line() with self.assertRaises(symbolfile.ParseError): parser.parse_version() - def test_unknown_scope_label(self): + def test_unknown_scope_label(self) -> None: input_file = io.StringIO(textwrap.dedent("""\ VERSION_1 { foo: } """)) - parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, False) + parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, + False, False) parser.next_line() with self.assertRaises(symbolfile.ParseError): parser.parse_version() - def test_parse_symbol(self): + def test_parse_symbol(self) -> None: input_file = io.StringIO(textwrap.dedent("""\ foo; bar; # baz qux """)) - parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, False) + parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, + False, False) parser.next_line() symbol = parser.parse_symbol() @@ -384,48 +430,51 @@ class SymbolFileParseTest(unittest.TestCase): self.assertEqual('bar', symbol.name) self.assertEqual(['baz', 'qux'], symbol.tags) - def test_wildcard_symbol_global(self): + def test_wildcard_symbol_global(self) -> None: input_file = io.StringIO(textwrap.dedent("""\ VERSION_1 { *; }; """)) - parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, False) + parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, + False, False) parser.next_line() with self.assertRaises(symbolfile.ParseError): parser.parse_version() - def test_wildcard_symbol_local(self): + def test_wildcard_symbol_local(self) -> None: input_file = io.StringIO(textwrap.dedent("""\ VERSION_1 { local: *; }; """)) - parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, False) + parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, + False, False) parser.next_line() version = parser.parse_version() self.assertEqual([], version.symbols) - def test_missing_semicolon(self): + def test_missing_semicolon(self) -> None: input_file = io.StringIO(textwrap.dedent("""\ VERSION_1 { foo }; """)) - parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, False) + parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, + False, False) parser.next_line() with self.assertRaises(symbolfile.ParseError): parser.parse_version() - def test_parse_fails_invalid_input(self): + def test_parse_fails_invalid_input(self) -> None: with self.assertRaises(symbolfile.ParseError): input_file = io.StringIO('foo') - parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, - False, False) + parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), + 16, False, False) parser.parse() - def test_parse(self): + def test_parse(self) -> None: input_file = io.StringIO(textwrap.dedent("""\ VERSION_1 { local: @@ -443,23 +492,24 @@ class SymbolFileParseTest(unittest.TestCase): qwerty; } VERSION_1; """)) - parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, False) + parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, + False, False) versions = parser.parse() expected = [ symbolfile.Version('VERSION_1', None, [], [ symbolfile.Symbol('foo', []), - symbolfile.Symbol('bar', ['baz']), + symbolfile.Symbol('bar', [Tag('baz')]), ]), - symbolfile.Version('VERSION_2', 'VERSION_1', ['wasd'], [ + symbolfile.Version('VERSION_2', 'VERSION_1', [Tag('wasd')], [ symbolfile.Symbol('woodly', []), - symbolfile.Symbol('doodly', ['asdf']), + symbolfile.Symbol('doodly', [Tag('asdf')]), ]), ] self.assertEqual(expected, versions) - def test_parse_llndk_apex_symbol(self): + def test_parse_llndk_apex_symbol(self) -> None: input_file = io.StringIO(textwrap.dedent("""\ VERSION_1 { foo; @@ -468,7 +518,8 @@ class SymbolFileParseTest(unittest.TestCase): qux; # apex }; """)) - parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, True) + parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, + False, True) parser.next_line() version = parser.parse_version() @@ -477,14 +528,14 @@ class SymbolFileParseTest(unittest.TestCase): expected_symbols = [ symbolfile.Symbol('foo', []), - symbolfile.Symbol('bar', ['llndk']), - symbolfile.Symbol('baz', ['llndk', 'apex']), - symbolfile.Symbol('qux', ['apex']), + symbolfile.Symbol('bar', [Tag('llndk')]), + symbolfile.Symbol('baz', [Tag('llndk'), Tag('apex')]), + symbolfile.Symbol('qux', [Tag('apex')]), ] self.assertEqual(expected_symbols, version.symbols) -def main(): +def main() -> None: suite = unittest.TestLoader().loadTestsFromName(__name__) unittest.TextTestRunner(verbosity=3).run(suite) diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go index 4aa62be3c..69e4f696c 100644 --- a/cmd/soong_ui/main.go +++ b/cmd/soong_ui/main.go @@ -173,7 +173,6 @@ func main() { rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb") soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics") defer build.UploadMetrics(buildCtx, config, c.simpleOutput, buildStarted, buildErrorFile, rbeMetricsFile, soongMetricsFile) - defer build.PrintGomaDeprecation(buildCtx, config) os.MkdirAll(logsDir, 0777) log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log")) diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go index 5dd2a8696..8e356793f 100644 --- a/etc/prebuilt_etc.go +++ b/etc/prebuilt_etc.go @@ -172,13 +172,7 @@ func (p *PrebuiltEtc) SubDir() string { } func (p *PrebuiltEtc) BaseDir() string { - // If soc install dir was specified and SOC specific is set, set the installDirPath to the specified - // socInstallDirBase. - installBaseDir := p.installDirBase - if p.SocSpecific() && p.socInstallDirBase != "" { - installBaseDir = p.socInstallDirBase - } - return installBaseDir + return p.installDirBase } func (p *PrebuiltEtc) Installable() bool { @@ -205,7 +199,13 @@ func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.PropertyErrorf("sub_dir", "relative_install_path is set. Cannot set sub_dir") } - p.installDirPath = android.PathForModuleInstall(ctx, p.BaseDir(), p.SubDir()) + // If soc install dir was specified and SOC specific is set, set the installDirPath to the specified + // socInstallDirBase. + installBaseDir := p.installDirBase + if p.SocSpecific() && p.socInstallDirBase != "" { + installBaseDir = p.socInstallDirBase + } + p.installDirPath = android.PathForModuleInstall(ctx, installBaseDir, p.SubDir()) // This ensures that outputFilePath has the correct name for others to // use, as the source file may have a different name. diff --git a/genrule/genrule.go b/genrule/genrule.go index 1cec2893a..4a2f81073 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -555,7 +555,8 @@ func (g *Module) AndroidMk() android.AndroidMkData { } } -func (g *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +func (g *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, + sdkVersion android.ApiLevel) error { // Because generated outputs are checked by client modules(e.g. cc_library, ...) // we can safely ignore the check here. return nil diff --git a/java/aar.go b/java/aar.go index 667dd9de4..9cab0bdca 100644 --- a/java/aar.go +++ b/java/aar.go @@ -189,7 +189,7 @@ func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext, // Version code if !hasVersionCode { - linkFlags = append(linkFlags, "--version-code", ctx.Config().PlatformSdkVersion()) + linkFlags = append(linkFlags, "--version-code", ctx.Config().PlatformSdkVersion().String()) } if !hasVersionName { @@ -774,7 +774,8 @@ func (a *AARImport) DepIsInSameApex(ctx android.BaseModuleContext, dep android.M return a.depIsInSameApex(ctx, dep) } -func (g *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +func (g *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, + sdkVersion android.ApiLevel) error { return nil } diff --git a/java/app.go b/java/app.go index ae7373fc7..13d08b94a 100755 --- a/java/app.go +++ b/java/app.go @@ -157,7 +157,7 @@ func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) "abis": strings.Join(SupportedAbis(ctx), ","), "allow-prereleased": strconv.FormatBool(proptools.Bool(as.properties.Prerelease)), "screen-densities": screenDensities, - "sdk-version": ctx.Config().PlatformSdkVersion(), + "sdk-version": ctx.Config().PlatformSdkVersion().String(), "stem": as.BaseModuleName(), "apkcerts": as.apkcertsFile.String(), "partition": as.PartitionTag(ctx.DeviceConfig()), @@ -436,7 +436,7 @@ func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) { if minSdkVersion, err := a.minSdkVersion().effectiveVersion(ctx); err == nil { a.checkJniLibsSdkVersion(ctx, minSdkVersion) - android.CheckMinSdkVersion(a, ctx, int(minSdkVersion)) + android.CheckMinSdkVersion(a, ctx, minSdkVersion.ApiLevel(ctx)) } else { ctx.PropertyErrorf("min_sdk_version", "%s", err.Error()) } @@ -678,7 +678,7 @@ func (a *AndroidApp) noticeBuildActions(ctx android.ModuleContext) { seenModules[child] = true // Skip host modules. - if child.Target().Os.Class == android.Host || child.Target().Os.Class == android.HostCross { + if child.Target().Os.Class == android.Host { return false } @@ -1637,7 +1637,8 @@ func (a *AndroidAppImport) minSdkVersion() sdkSpec { return sdkSpecFrom("") } -func (j *AndroidAppImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +func (j *AndroidAppImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, + sdkVersion android.ApiLevel) error { // Do not check for prebuilts against the min_sdk_version of enclosing APEX return nil } diff --git a/java/app_test.go b/java/app_test.go index 536797119..4347db8b1 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -1078,6 +1078,7 @@ func TestAppSdkVersion(t *testing.T) { platformSdkFinal bool expectedMinSdkVersion string platformApis bool + activeCodenames []string }{ { name: "current final SDK", @@ -1094,6 +1095,7 @@ func TestAppSdkVersion(t *testing.T) { platformSdkCodename: "OMR1", platformSdkFinal: false, expectedMinSdkVersion: "OMR1", + activeCodenames: []string{"OMR1"}, }, { name: "default final SDK", @@ -1112,11 +1114,14 @@ func TestAppSdkVersion(t *testing.T) { platformSdkCodename: "OMR1", platformSdkFinal: false, expectedMinSdkVersion: "OMR1", + activeCodenames: []string{"OMR1"}, }, { name: "14", sdkVersion: "14", expectedMinSdkVersion: "14", + platformSdkCodename: "S", + activeCodenames: []string{"S"}, }, } @@ -1137,6 +1142,7 @@ func TestAppSdkVersion(t *testing.T) { config := testAppConfig(nil, bp, nil) config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename + config.TestProductVariables.Platform_version_active_codenames = test.activeCodenames config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal checkSdkVersion(t, config, test.expectedMinSdkVersion) @@ -1179,15 +1185,6 @@ func TestVendorAppSdkVersion(t *testing.T) { platformSdkInt: 29, platformSdkCodename: "Q", platformSdkFinal: false, - deviceCurrentApiLevelForVendorModules: "current", - expectedMinSdkVersion: "Q", - }, - { - name: "current final SDK", - sdkVersion: "current", - platformSdkInt: 29, - platformSdkCodename: "Q", - platformSdkFinal: false, deviceCurrentApiLevelForVendorModules: "28", expectedMinSdkVersion: "28", }, diff --git a/java/dex.go b/java/dex.go index 21a59266e..055d47983 100644 --- a/java/dex.go +++ b/java/dex.go @@ -135,6 +135,7 @@ var r8, r8RE = remoteexec.MultiCommandStaticRules(pctx, "r8", "$r8Template": &remoteexec.REParams{ Labels: map[string]string{"type": "compile", "compiler": "r8"}, Inputs: []string{"$implicits", "${config.R8Jar}"}, + OutputFiles: []string{"${outUsage}"}, ExecStrategy: "${config.RER8ExecStrategy}", ToolchainInputs: []string{"${config.JavaCmd}"}, Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, diff --git a/java/droiddoc.go b/java/droiddoc.go index e39a556e7..33f422d4e 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -253,6 +253,10 @@ type DroidstubsProperties struct { // if set to true, allow Metalava to generate doc_stubs source files. Defaults to false. Create_doc_stubs *bool + // if set to true, cause Metalava to output Javadoc comments in the stubs source files. Defaults to false. + // Has no effect if create_doc_stubs: true. + Output_javadoc_comments *bool + // if set to false then do not write out stubs. Defaults to true. // // TODO(b/146727827): Remove capability when we do not need to generate stubs and API separately. @@ -1150,7 +1154,9 @@ func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuil cmd.FlagWithArg("--doc-stubs ", stubsDir.String()) } else { cmd.FlagWithArg("--stubs ", stubsDir.String()) - cmd.Flag("--exclude-documentation-from-stubs") + if !Bool(d.properties.Output_javadoc_comments) { + cmd.Flag("--exclude-documentation-from-stubs") + } } } } @@ -1228,7 +1234,7 @@ func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *a cmd.FlagWithOutput("--generate-api-levels ", d.apiVersionsXml) cmd.FlagWithInput("--apply-api-levels ", d.apiVersionsXml) - cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion()) + cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String()) cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename()) filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar") @@ -1298,6 +1304,7 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersi cmd.BuiltTool(ctx, "metalava"). Flag(config.JavacVmFlags). + Flag("-J--add-opens=java.base/java.util=ALL-UNNAMED"). FlagWithArg("-encoding ", "UTF-8"). FlagWithArg("-source ", javaVersion.String()). FlagWithRspFileInputList("@", srcs). @@ -1411,9 +1418,7 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { // TODO(b/154317059): Clean up this whitelist by baselining and/or checking in last-released. if d.Name() != "android.car-system-stubs-docs" && - d.Name() != "android.car-stubs-docs" && - d.Name() != "system-api-stubs-docs" && - d.Name() != "test-api-stubs-docs" { + d.Name() != "android.car-stubs-docs" { cmd.Flag("--lints-as-errors") cmd.Flag("--warnings-as-errors") // Most lints are actually warnings. } diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go index b6af3bf28..61a9b97e4 100644 --- a/java/hiddenapi_singleton.go +++ b/java/hiddenapi_singleton.go @@ -92,31 +92,34 @@ func (h *hiddenAPISingleton) MakeVars(ctx android.MakeVarsContext) { // stubFlagsRule creates the rule to build hiddenapi-stub-flags.txt out of dex jars from stub modules and boot image // modules. func stubFlagsRule(ctx android.SingletonContext) { - // Public API stubs - publicStubModules := []string{ - "android_stubs_current", + var publicStubModules []string + var systemStubModules []string + var testStubModules []string + var corePlatformStubModules []string + + if ctx.Config().AlwaysUsePrebuiltSdks() { + // Build configuration mandates using prebuilt stub modules + publicStubModules = append(publicStubModules, "sdk_public_current_android") + systemStubModules = append(systemStubModules, "sdk_system_current_android") + testStubModules = append(testStubModules, "sdk_test_current_android") + } else { + // Use stub modules built from source + publicStubModules = append(publicStubModules, "android_stubs_current") + systemStubModules = append(systemStubModules, "android_system_stubs_current") + testStubModules = append(testStubModules, "android_test_stubs_current") } + // We do not have prebuilts of the core platform api yet + corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs") // Add the android.test.base to the set of stubs only if the android.test.base module is on // the boot jars list as the runtime will only enforce hiddenapi access against modules on // that list. - if inList("android.test.base", ctx.Config().BootJars()) && !ctx.Config().AlwaysUsePrebuiltSdks() { - publicStubModules = append(publicStubModules, "android.test.base.stubs") - } - - // System API stubs - systemStubModules := []string{ - "android_system_stubs_current", - } - - // Test API stubs - testStubModules := []string{ - "android_test_stubs_current", - } - - // Core Platform API stubs - corePlatformStubModules := []string{ - "legacy.core.platform.api.stubs", + if inList("android.test.base", ctx.Config().BootJars()) { + if ctx.Config().AlwaysUsePrebuiltSdks() { + publicStubModules = append(publicStubModules, "sdk_public_current_android.test.base") + } else { + publicStubModules = append(publicStubModules, "android.test.base.stubs") + } } // Allow products to define their own stubs for custom product jars that apps can use. diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go index bcca93a00..dbdab7ade 100644 --- a/java/hiddenapi_singleton_test.go +++ b/java/hiddenapi_singleton_test.go @@ -16,8 +16,11 @@ package java import ( "android/soong/android" + "fmt" "strings" "testing" + + "github.com/google/blueprint/proptools" ) func testConfigWithBootJars(bp string, bootJars []string) android.Config { @@ -32,19 +35,30 @@ func testContextWithHiddenAPI() *android.TestContext { return ctx } -func testHiddenAPI(t *testing.T, bp string, bootJars []string) (*android.TestContext, android.Config) { +func testHiddenAPIWithConfig(t *testing.T, config android.Config) *android.TestContext { t.Helper() - config := testConfigWithBootJars(bp, bootJars) ctx := testContextWithHiddenAPI() run(t, ctx, config) + return ctx +} + +func testHiddenAPIBootJars(t *testing.T, bp string, bootJars []string) (*android.TestContext, android.Config) { + config := testConfigWithBootJars(bp, bootJars) - return ctx, config + return testHiddenAPIWithConfig(t, config), config +} + +func testHiddenAPIUnbundled(t *testing.T, unbundled bool) (*android.TestContext, android.Config) { + config := testConfig(nil, ``, nil) + config.TestProductVariables.Always_use_prebuilt_sdks = proptools.BoolPtr(unbundled) + + return testHiddenAPIWithConfig(t, config), config } func TestHiddenAPISingleton(t *testing.T) { - ctx, _ := testHiddenAPI(t, ` + ctx, _ := testHiddenAPIBootJars(t, ` java_library { name: "foo", srcs: ["a.java"], @@ -61,7 +75,7 @@ func TestHiddenAPISingleton(t *testing.T) { } func TestHiddenAPISingletonWithPrebuilt(t *testing.T) { - ctx, _ := testHiddenAPI(t, ` + ctx, _ := testHiddenAPIBootJars(t, ` java_import { name: "foo", jars: ["a.jar"], @@ -78,7 +92,7 @@ func TestHiddenAPISingletonWithPrebuilt(t *testing.T) { } func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) { - ctx, _ := testHiddenAPI(t, ` + ctx, _ := testHiddenAPIBootJars(t, ` java_library { name: "foo", srcs: ["a.java"], @@ -107,7 +121,7 @@ func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) { } func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) { - ctx, _ := testHiddenAPI(t, ` + ctx, _ := testHiddenAPIBootJars(t, ` java_library { name: "foo", srcs: ["a.java"], @@ -134,3 +148,72 @@ func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) { t.Errorf("Did not expect %s in hiddenapi command, but it was present: %s", fromSourceJarArg, hiddenapiRule.RuleParams.Command) } } + +func TestHiddenAPISingletonSdks(t *testing.T) { + testCases := []struct { + name string + unbundledBuild bool + publicStub string + systemStub string + testStub string + corePlatformStub string + }{ + { + name: "testBundled", + unbundledBuild: false, + publicStub: "android_stubs_current", + systemStub: "android_system_stubs_current", + testStub: "android_test_stubs_current", + corePlatformStub: "legacy.core.platform.api.stubs", + }, { + name: "testUnbundled", + unbundledBuild: true, + publicStub: "sdk_public_current_android", + systemStub: "sdk_system_current_android", + testStub: "sdk_test_current_android", + corePlatformStub: "legacy.core.platform.api.stubs", + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + ctx, _ := testHiddenAPIUnbundled(t, tc.unbundledBuild) + + hiddenAPI := ctx.SingletonForTests("hiddenapi") + hiddenapiRule := hiddenAPI.Rule("hiddenapi") + wantPublicStubs := "--public-stub-classpath=" + generateSdkDexPath(tc.publicStub, tc.unbundledBuild) + if !strings.Contains(hiddenapiRule.RuleParams.Command, wantPublicStubs) { + t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", wantPublicStubs, hiddenapiRule.RuleParams.Command) + } + + wantSystemStubs := "--system-stub-classpath=" + generateSdkDexPath(tc.systemStub, tc.unbundledBuild) + if !strings.Contains(hiddenapiRule.RuleParams.Command, wantSystemStubs) { + t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", wantSystemStubs, hiddenapiRule.RuleParams.Command) + } + + wantTestStubs := "--test-stub-classpath=" + generateSdkDexPath(tc.testStub, tc.unbundledBuild) + if !strings.Contains(hiddenapiRule.RuleParams.Command, wantTestStubs) { + t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", wantTestStubs, hiddenapiRule.RuleParams.Command) + } + + wantCorePlatformStubs := "--core-platform-stub-classpath=" + generateDexPath(tc.corePlatformStub) + if !strings.Contains(hiddenapiRule.RuleParams.Command, wantCorePlatformStubs) { + t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", wantCorePlatformStubs, hiddenapiRule.RuleParams.Command) + } + }) + } +} + +func generateDexedPath(subDir, dex, module string) string { + return fmt.Sprintf("%s/.intermediates/%s/android_common/%s/%s.jar", buildDir, subDir, dex, module) +} + +func generateDexPath(module string) string { + return generateDexedPath(module, "dex", module) +} + +func generateSdkDexPath(module string, unbundled bool) string { + if unbundled { + return generateDexedPath("prebuilts/sdk/"+module, "dex", module) + } + return generateDexPath(module) +} diff --git a/java/java.go b/java/java.go index d67e9e098..1d7eaa771 100644 --- a/java/java.go +++ b/java/java.go @@ -1658,7 +1658,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { if v := sdkSpec.version; v.isNumbered() { return v.String() } else { - return ctx.Config().DefaultAppTargetSdk() + return ctx.Config().DefaultAppTargetSdk(ctx).String() } } @@ -1876,7 +1876,8 @@ func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu return j.depIsInSameApex(ctx, dep) } -func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, + sdkVersion android.ApiLevel) error { sdkSpec := j.minSdkVersion() if !sdkSpec.specified() { return fmt.Errorf("min_sdk_version is not specified") @@ -1888,7 +1889,7 @@ func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersi if err != nil { return err } - if int(ver) > sdkVersion { + if ver.ApiLevel(ctx).GreaterThan(sdkVersion) { return fmt.Errorf("newer SDK(%v)", ver) } return nil @@ -2753,7 +2754,8 @@ func (j *Import) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu return j.depIsInSameApex(ctx, dep) } -func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext, + sdkVersion android.ApiLevel) error { // Do not check for prebuilts against the min_sdk_version of enclosing APEX return nil } @@ -2936,7 +2938,8 @@ func (j *DexImport) DexJarBuildPath() android.Path { return j.dexJarFile } -func (j *DexImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +func (j *DexImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, + sdkVersion android.ApiLevel) error { // we don't check prebuilt modules for sdk_version return nil } diff --git a/java/java_test.go b/java/java_test.go index 9e6357792..f16639aa8 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -1487,6 +1487,12 @@ func TestJavaSdkLibrary(t *testing.T) { libs: ["foo"], sdk_version: "system_29", } + java_library { + name: "baz-module-30", + srcs: ["c.java"], + libs: ["foo"], + sdk_version: "module_30", + } `) // check the existence of the internal modules @@ -1533,6 +1539,13 @@ func TestJavaSdkLibrary(t *testing.T) { "prebuilts/sdk/29/system/foo.jar") } + bazModule30Javac := ctx.ModuleForTests("baz-module-30", "android_common").Rule("javac") + // tests if "baz-module-30" is actually linked to the module 30 stubs lib + if !strings.Contains(bazModule30Javac.Args["classpath"], "prebuilts/sdk/30/module-lib/foo.jar") { + t.Errorf("baz-module-30 javac classpath %v does not contain %q", bazModule30Javac.Args["classpath"], + "prebuilts/sdk/30/module-lib/foo.jar") + } + // test if baz has exported SDK lib names foo and bar to qux qux := ctx.ModuleForTests("qux", "android_common") if quxLib, ok := qux.Module().(*Library); ok { diff --git a/java/robolectric.go b/java/robolectric.go index ec112bc99..04fc11722 100644 --- a/java/robolectric.go +++ b/java/robolectric.go @@ -31,7 +31,6 @@ func init() { } var robolectricDefaultLibs = []string{ - "robolectric_android-all-stub", "Robolectric_all-target", "mockito-robolectric-prebuilt", "truth-prebuilt", @@ -99,7 +98,8 @@ func (r *robolectricTest) DepsMutator(ctx android.BottomUpMutatorContext) { ctx.AddVariationDependencies(nil, roboCoverageLibsTag, r.robolectricProperties.Coverage_libs...) - ctx.AddVariationDependencies(nil, roboRuntimesTag, "robolectric-android-all-prebuilts") + ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), + roboRuntimesTag, "robolectric-android-all-prebuilts") } func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -335,7 +335,7 @@ func (r *robolectricTest) InstallForceOS() (*android.OsType, *android.ArchType) func robolectricRuntimesFactory() android.Module { module := &robolectricRuntimes{} module.AddProperties(&module.props) - android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) + android.InitAndroidArchModule(module, android.HostSupportedNoCross, android.MultilibCommon) return module } @@ -365,6 +365,10 @@ func (r *robolectricRuntimes) DepsMutator(ctx android.BottomUpMutatorContext) { } func (r *robolectricRuntimes) GenerateAndroidBuildActions(ctx android.ModuleContext) { + if ctx.Target().Os != ctx.Config().BuildOSCommonTarget.Os { + return + } + files := android.PathsForModuleSrc(ctx, r.props.Jars) androidAllDir := android.PathForModuleInstall(ctx, "android-all") diff --git a/java/sdk.go b/java/sdk.go index 56fa12b3e..971791f4a 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -107,7 +107,7 @@ type sdkVersion int const ( // special version number for a not-yet-frozen SDK - sdkVersionCurrent sdkVersion = sdkVersion(android.FutureApiLevel) + sdkVersionCurrent sdkVersion = sdkVersion(android.FutureApiLevelInt) // special version number to be used for SDK specs where version number doesn't // make sense, e.g. "none", "", etc. sdkVersionNone sdkVersion = sdkVersion(0) @@ -133,6 +133,10 @@ func (v sdkVersion) String() string { return "(no version)" } +func (v sdkVersion) ApiLevel(ctx android.EarlyModuleContext) android.ApiLevel { + return android.ApiLevelOrPanic(ctx, v.String()) +} + // asNumberString directly converts the numeric value of this sdk version as a string. // When isNumbered() is true, this method is the same as String(). However, for sdkVersionCurrent // and sdkVersionNone, this returns 10000 and 0 while String() returns "current" and "(no version"), @@ -218,7 +222,7 @@ func (s sdkSpec) usePrebuilt(ctx android.EarlyModuleContext) bool { return ctx.Config().AlwaysUsePrebuiltSdks() } else if s.version.isNumbered() { // validation check - if s.kind != sdkPublic && s.kind != sdkSystem && s.kind != sdkTest { + if s.kind != sdkPublic && s.kind != sdkSystem && s.kind != sdkTest && s.kind != sdkModule { panic(fmt.Errorf("prebuilt SDK is not not available for sdkKind=%q", s.kind)) return false } @@ -243,7 +247,7 @@ func (s sdkSpec) effectiveVersion(ctx android.EarlyModuleContext) (sdkVersion, e if s.version.isNumbered() { return s.version, nil } - return sdkVersion(ctx.Config().DefaultAppTargetSdkInt()), nil + return sdkVersion(ctx.Config().DefaultAppTargetSdk(ctx).FinalOrFutureInt()), nil } // effectiveVersionString converts an sdkSpec into the concrete version string that the module @@ -251,8 +255,8 @@ func (s sdkSpec) effectiveVersion(ctx android.EarlyModuleContext) (sdkVersion, e // it returns the codename (P, Q, R, etc.) func (s sdkSpec) effectiveVersionString(ctx android.EarlyModuleContext) (string, error) { ver, err := s.effectiveVersion(ctx) - if err == nil && int(ver) == ctx.Config().DefaultAppTargetSdkInt() { - return ctx.Config().DefaultAppTargetSdk(), nil + if err == nil && int(ver) == ctx.Config().DefaultAppTargetSdk(ctx).FinalOrFutureInt() { + return ctx.Config().DefaultAppTargetSdk(ctx).String(), nil } return ver.String(), err } diff --git a/java/sdk_library.go b/java/sdk_library.go index 1a5ef544c..60924a662 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -589,6 +589,9 @@ type commonToSdkLibraryAndImportProperties struct { // An Android shared library is one that can be referenced in a <uses-library> element // in an AndroidManifest.xml. Shared_library *bool + + // Files containing information about supported java doc tags. + Doctag_files []string `android:"path"` } // Common code between sdk library and sdk library import @@ -601,6 +604,9 @@ type commonToSdkLibraryAndImport struct { commonSdkLibraryProperties commonToSdkLibraryAndImportProperties + // Paths to commonSdkLibraryProperties.Doctag_files + doctagPaths android.Paths + // Functionality related to this being used as a component of a java_sdk_library. EmbeddableSdkLibraryComponent } @@ -633,6 +639,10 @@ func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android return true } +func (c *commonToSdkLibraryAndImport) generateCommonBuildActions(ctx android.ModuleContext) { + c.doctagPaths = android.PathsForModuleSrc(ctx, c.commonSdkLibraryProperties.Doctag_files) +} + // Module name of the runtime implementation library func (c *commonToSdkLibraryAndImport) implLibraryModuleName() string { return c.moduleBase.BaseModuleName() + ".impl" @@ -732,6 +742,14 @@ func (c *commonToSdkLibraryAndImport) commonOutputFiles(tag string) (android.Pat } } else { + switch tag { + case ".doctags": + if c.doctagPaths != nil { + return c.doctagPaths, nil + } else { + return nil, fmt.Errorf("no doctag_files specified on %s", c.moduleBase.BaseModuleName()) + } + } return nil, nil } } @@ -1014,6 +1032,8 @@ func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) { } func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { + module.generateCommonBuildActions(ctx) + // Only build an implementation library if required. if module.requiresRuntimeImplementationLibrary() { module.Library.GenerateAndroidBuildActions(ctx) @@ -1203,6 +1223,7 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC Sdk_version *string System_modules *string Libs []string + Output_javadoc_comments *bool Arg_files []string Args *string Java_version *string @@ -1278,6 +1299,11 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC } droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide ")) + // Output Javadoc comments for public scope. + if apiScope == apiScopePublic { + props.Output_javadoc_comments = proptools.BoolPtr(true) + } + // Add in scope specific arguments. droidstubsArgs = append(droidstubsArgs, scopeSpecificDroidstubsArgs...) props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files @@ -1878,7 +1904,8 @@ func (module *SdkLibraryImport) DepIsInSameApex(mctx android.BaseModuleContext, return false } -func (module *SdkLibraryImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +func (module *SdkLibraryImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, + sdkVersion android.ApiLevel) error { // we don't check prebuilt modules for sdk_version return nil } @@ -1888,6 +1915,8 @@ func (module *SdkLibraryImport) OutputFiles(tag string) (android.Paths, error) { } func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { + module.generateCommonBuildActions(ctx) + // Record the paths to the prebuilt stubs library and stubs source. ctx.VisitDirectDeps(func(to android.Module) { tag := ctx.OtherModuleDependencyTag(to) @@ -2078,7 +2107,8 @@ func (module *sdkLibraryXml) DepsMutator(ctx android.BottomUpMutatorContext) { // do nothing } -func (module *sdkLibraryXml) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +func (module *sdkLibraryXml) ShouldSupportSdkVersion(ctx android.BaseModuleContext, + sdkVersion android.ApiLevel) error { // sdkLibraryXml doesn't need to be checked separately because java_sdk_library is checked return nil } @@ -2179,6 +2209,9 @@ type sdkLibrarySdkMemberProperties struct { // True if the java_sdk_library_import is for a shared library, false // otherwise. Shared_library *bool + + // The paths to the doctag files to add to the prebuilt. + Doctag_paths android.Paths } type scopeProperties struct { @@ -2218,6 +2251,7 @@ func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMembe s.Libs = sdk.properties.Libs s.Naming_scheme = sdk.commonSdkLibraryProperties.Naming_scheme s.Shared_library = proptools.BoolPtr(sdk.sharedLibrary()) + s.Doctag_paths = sdk.doctagPaths } func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) { @@ -2266,6 +2300,16 @@ func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberCo } } + if len(s.Doctag_paths) > 0 { + dests := []string{} + for _, p := range s.Doctag_paths { + dest := filepath.Join("doctags", p.Rel()) + ctx.SnapshotBuilder().CopyToSnapshot(p, dest) + dests = append(dests, dest) + } + propertySet.AddProperty("doctag_files", dests) + } + if len(s.Libs) > 0 { propertySet.AddPropertyWithTag("libs", s.Libs, ctx.SnapshotBuilder().SdkMemberReferencePropertyTag(false)) } diff --git a/java/testing.go b/java/testing.go index 322dc9ec6..461fd3f9f 100644 --- a/java/testing.go +++ b/java/testing.go @@ -55,6 +55,8 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string "prebuilts/sdk/30/public/framework.aidl": nil, "prebuilts/sdk/30/system/android.jar": nil, "prebuilts/sdk/30/system/foo.jar": nil, + "prebuilts/sdk/30/module-lib/android.jar": nil, + "prebuilts/sdk/30/module-lib/foo.jar": nil, "prebuilts/sdk/30/public/core-for-system-modules.jar": nil, "prebuilts/sdk/current/core/android.jar": nil, "prebuilts/sdk/current/public/android.jar": nil, @@ -88,7 +90,7 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string "prebuilts/sdk/30/system/api/bar-removed.txt": nil, "prebuilts/sdk/30/test/api/bar-removed.txt": nil, "prebuilts/sdk/tools/core-lambda-stubs.jar": nil, - "prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "30", "current"],}`), + "prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "30", "current"], imports_sdk_version: "none", imports_compile_dex:true,}`), "bin.py": nil, python.StubTemplateHost: []byte(`PYTHON_BINARY = '%interpreter%' diff --git a/python/androidmk.go b/python/androidmk.go index 247b80dc0..8ad5889b5 100644 --- a/python/androidmk.go +++ b/python/androidmk.go @@ -15,11 +15,12 @@ package python import ( - "android/soong/android" "fmt" "io" "path/filepath" "strings" + + "android/soong/android" ) type subAndroidMkProvider interface { @@ -74,6 +75,11 @@ func (p *testDecorator) AndroidMk(base *Module, ret *android.AndroidMkData) { if !BoolDefault(p.binaryProperties.Auto_gen_config, true) { fmt.Fprintln(w, "LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG := true") } + + if len(p.data) > 0 { + fmt.Fprintln(w, "LOCAL_TEST_DATA :=", + strings.Join(android.AndroidMkDataPaths(p.data), " ")) + } }) base.subAndroidMk(ret, p.binaryDecorator.pythonInstaller) } diff --git a/python/binary.go b/python/binary.go index 5a7492648..1d2400efd 100644 --- a/python/binary.go +++ b/python/binary.go @@ -79,7 +79,7 @@ func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) { } func PythonBinaryHostFactory() android.Module { - module, _ := NewBinary(android.HostSupportedNoCross) + module, _ := NewBinary(android.HostSupported) return module.Init() } diff --git a/python/library.go b/python/library.go index 65c1352e7..0c8d61313 100644 --- a/python/library.go +++ b/python/library.go @@ -26,7 +26,7 @@ func init() { } func PythonLibraryHostFactory() android.Module { - module := newModule(android.HostSupportedNoCross, android.MultilibFirst) + module := newModule(android.HostSupported, android.MultilibFirst) return module.Init() } diff --git a/python/test.go b/python/test.go index a669c73a6..434e71abf 100644 --- a/python/test.go +++ b/python/test.go @@ -34,6 +34,10 @@ type TestProperties struct { // the name of the test configuration template (for example "AndroidTestTemplate.xml") that // should be installed with the module. Test_config_template *string `android:"path,arch_variant"` + + // list of files or filegroup modules that provide data that should be installed alongside + // the test + Data []string `android:"path,arch_variant"` } type testDecorator struct { @@ -42,6 +46,8 @@ type testDecorator struct { testProperties TestProperties testConfig android.Path + + data []android.DataPath } func (test *testDecorator) bootstrapperProps() []interface{} { @@ -59,6 +65,12 @@ func (test *testDecorator) install(ctx android.ModuleContext, file android.Path) test.binaryDecorator.pythonInstaller.relative = ctx.ModuleName() test.binaryDecorator.pythonInstaller.install(ctx, file) + + dataSrcPaths := android.PathsForModuleSrc(ctx, test.testProperties.Data) + + for _, dataSrcPath := range dataSrcPaths { + test.data = append(test.data, android.DataPath{SrcPath: dataSrcPath}) + } } func NewTest(hod android.HostOrDeviceSupported) *Module { diff --git a/rust/androidmk.go b/rust/androidmk.go index edae0e63d..5a33f77fa 100644 --- a/rust/androidmk.go +++ b/rust/androidmk.go @@ -178,6 +178,10 @@ func (proto *protobufDecorator) AndroidMk(ctx AndroidMkContext, ret *android.And } func (compiler *baseCompiler) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) { + if compiler.path == (android.InstallPath{}) { + return + } + var unstrippedOutputFile android.OptionalPath // Soong installation is only supported for host modules. Have Make // installation trigger Soong installation. diff --git a/rust/binary.go b/rust/binary.go index 1d02453db..af39d383d 100644 --- a/rust/binary.go +++ b/rust/binary.go @@ -24,6 +24,16 @@ func init() { } type BinaryCompilerProperties struct { + // Change the rustlibs linkage to select rlib linkage by default for device targets. + // Also link libstd as an rlib as well on device targets. + // Note: This is the default behavior for host targets. + Prefer_rlib *bool `android:"arch_variant"` + + // Builds this binary as a static binary. Implies prefer_rlib true. + // + // Static executables currently only support for bionic targets. Non-bionic targets will not produce a fully static + // binary, but will still implicitly imply prefer_rlib true. + Static_executable *bool `android:"arch_variant"` } type binaryDecorator struct { @@ -68,6 +78,11 @@ func (binary *binaryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Fla "-Wl,--gc-sections", "-Wl,-z,nocopyreloc", "-Wl,--no-undefined-version") + + if Bool(binary.Properties.Static_executable) { + flags.LinkFlags = append(flags.LinkFlags, "-static") + flags.RustFlags = append(flags.RustFlags, "-C relocation-model=static") + } } return flags @@ -77,8 +92,12 @@ func (binary *binaryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps { deps = binary.baseCompiler.compilerDeps(ctx, deps) if ctx.toolchain().Bionic() { - deps = bionicDeps(deps) - deps.CrtBegin = "crtbegin_dynamic" + deps = bionicDeps(deps, Bool(binary.Properties.Static_executable)) + if Bool(binary.Properties.Static_executable) { + deps.CrtBegin = "crtbegin_static" + } else { + deps.CrtBegin = "crtbegin_dynamic" + } deps.CrtEnd = "crtend_android" } @@ -95,6 +114,10 @@ func (binary *binaryDecorator) nativeCoverage() bool { return true } +func (binary *binaryDecorator) preferRlib() bool { + return Bool(binary.Properties.Prefer_rlib) || Bool(binary.Properties.Static_executable) +} + func (binary *binaryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path { fileName := binary.getStem(ctx) + ctx.toolchain().ExecutableSuffix() srcPath, _ := srcPathFromModuleSrcs(ctx, binary.baseCompiler.Properties.Srcs) @@ -131,9 +154,19 @@ func (binary *binaryDecorator) coverageOutputZipPath() android.OptionalPath { func (binary *binaryDecorator) autoDep(ctx BaseModuleContext) autoDep { // Binaries default to dylib dependencies for device, rlib for host. + if binary.preferRlib() { + return rlibAutoDep + } if ctx.Device() { return dylibAutoDep } else { return rlibAutoDep } } + +func (binary *binaryDecorator) stdLinkage(ctx *depsContext) RustLinkage { + if binary.preferRlib() { + return RlibLinkage + } + return binary.baseCompiler.stdLinkage(ctx) +} diff --git a/rust/binary_test.go b/rust/binary_test.go index cfef57a77..b44a5bc71 100644 --- a/rust/binary_test.go +++ b/rust/binary_test.go @@ -30,6 +30,13 @@ func TestBinaryLinkage(t *testing.T) { rustlibs: ["libfoo"], host_supported: true, } + rust_binary { + name: "rlib_linked", + srcs: ["foo.rs"], + rustlibs: ["libfoo"], + host_supported: true, + prefer_rlib: true, + } rust_library { name: "libfoo", srcs: ["foo.rs"], @@ -40,7 +47,7 @@ func TestBinaryLinkage(t *testing.T) { fizzBuzzHost := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module) fizzBuzzDevice := ctx.ModuleForTests("fizz-buzz", "android_arm64_armv8-a").Module().(*Module) - if !android.InList("libfoo", fizzBuzzHost.Properties.AndroidMkRlibs) { + if !android.InList("libfoo.rlib-std", fizzBuzzHost.Properties.AndroidMkRlibs) { t.Errorf("rustlibs dependency libfoo should be an rlib dep for host modules") } @@ -49,6 +56,34 @@ func TestBinaryLinkage(t *testing.T) { } } +// Test that prefer_rlib links in libstd statically as well as rustlibs. +func TestBinaryPreferRlib(t *testing.T) { + ctx := testRust(t, ` + rust_binary { + name: "rlib_linked", + srcs: ["foo.rs"], + rustlibs: ["libfoo"], + host_supported: true, + prefer_rlib: true, + } + rust_library { + name: "libfoo", + srcs: ["foo.rs"], + crate_name: "foo", + host_supported: true, + }`) + + mod := ctx.ModuleForTests("rlib_linked", "android_arm64_armv8-a").Module().(*Module) + + if !android.InList("libfoo.rlib-std", mod.Properties.AndroidMkRlibs) { + t.Errorf("rustlibs dependency libfoo should be an rlib dep when prefer_rlib is defined") + } + + if !android.InList("libstd", mod.Properties.AndroidMkRlibs) { + t.Errorf("libstd dependency should be an rlib dep when prefer_rlib is defined") + } +} + // Test that the path returned by HostToolPath is correct func TestHostToolPath(t *testing.T) { ctx := testRust(t, ` @@ -79,6 +114,34 @@ func TestBinaryFlags(t *testing.T) { } } +func TestStaticBinaryFlags(t *testing.T) { + ctx := testRust(t, ` + rust_binary { + name: "fizz", + srcs: ["foo.rs"], + static_executable: true, + }`) + + fizzOut := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Output("fizz") + fizzMod := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Module().(*Module) + + flags := fizzOut.Args["rustcFlags"] + linkFlags := fizzOut.Args["linkFlags"] + if !strings.Contains(flags, "-C relocation-model=static") { + t.Errorf("static binary missing '-C relocation-model=static' in rustcFlags, found: %#v", flags) + } + if !strings.Contains(linkFlags, "-static") { + t.Errorf("static binary missing '-static' in linkFlags, found: %#v", flags) + } + + if !android.InList("libc", fizzMod.Properties.AndroidMkStaticLibs) { + t.Errorf("static binary not linking against libc as a static library") + } + if len(fizzMod.Properties.AndroidMkSharedLibs) > 0 { + t.Errorf("static binary incorrectly linking against shared libraries") + } +} + func TestLinkObjects(t *testing.T) { ctx := testRust(t, ` rust_binary { diff --git a/rust/bindgen.go b/rust/bindgen.go index cafdb8bfa..ac33ff7ef 100644 --- a/rust/bindgen.go +++ b/rust/bindgen.go @@ -21,6 +21,8 @@ import ( "github.com/google/blueprint/proptools" "android/soong/android" + "android/soong/cc" + cc_config "android/soong/cc/config" ) var ( @@ -56,38 +58,67 @@ func init() { var _ SourceProvider = (*bindgenDecorator)(nil) type BindgenProperties struct { - // The wrapper header file + // The wrapper header file. By default this is assumed to be a C header unless the extension is ".hh" or ".hpp". + // This is used to specify how to interpret the header and determines which '-std' flag to use by default. + // + // If your C++ header must have some other extension, then the default behavior can be overridden by setting the + // cpp_std property. Wrapper_src *string `android:"path,arch_variant"` // list of bindgen-specific flags and options Bindgen_flags []string `android:"arch_variant"` - // list of clang flags required to correctly interpret the headers. - Cflags []string `android:"arch_variant"` - - // list of directories relative to the Blueprints file that will - // be added to the include path using -I - Local_include_dirs []string `android:"arch_variant,variant_prepend"` - - // list of static libraries that provide headers for this binding. - Static_libs []string `android:"arch_variant,variant_prepend"` - - // list of shared libraries that provide headers for this binding. - Shared_libs []string `android:"arch_variant"` - // module name of a custom binary/script which should be used instead of the 'bindgen' binary. This custom // binary must expect arguments in a similar fashion to bindgen, e.g. // // "my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]" Custom_bindgen string `android:"path"` - - //TODO(b/161141999) Add support for headers from cc_library_header modules. } type bindgenDecorator struct { *BaseSourceProvider - Properties BindgenProperties + Properties BindgenProperties + ClangProperties cc.RustBindgenClangProperties +} + +func (b *bindgenDecorator) getStdVersion(ctx ModuleContext, src android.Path) (string, bool) { + // Assume headers are C headers + isCpp := false + stdVersion := "" + + switch src.Ext() { + case ".hpp", ".hh": + isCpp = true + } + + if String(b.ClangProperties.Cpp_std) != "" && String(b.ClangProperties.C_std) != "" { + ctx.PropertyErrorf("c_std", "c_std and cpp_std cannot both be defined at the same time.") + } + + if String(b.ClangProperties.Cpp_std) != "" { + if String(b.ClangProperties.Cpp_std) == "experimental" { + stdVersion = cc_config.ExperimentalCppStdVersion + } else if String(b.ClangProperties.Cpp_std) == "default" { + stdVersion = cc_config.CppStdVersion + } else { + stdVersion = String(b.ClangProperties.Cpp_std) + } + } else if b.ClangProperties.C_std != nil { + if String(b.ClangProperties.C_std) == "experimental" { + stdVersion = cc_config.ExperimentalCStdVersion + } else if String(b.ClangProperties.C_std) == "default" { + stdVersion = cc_config.CStdVersion + } else { + stdVersion = String(b.ClangProperties.C_std) + } + } else if isCpp { + stdVersion = cc_config.CppStdVersion + } else { + stdVersion = cc_config.CStdVersion + } + + return stdVersion, isCpp } func (b *bindgenDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) android.Path { @@ -120,8 +151,8 @@ func (b *bindgenDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) andr esc := proptools.NinjaAndShellEscapeList // Module defined clang flags and include paths - cflags = append(cflags, esc(b.Properties.Cflags)...) - for _, include := range b.Properties.Local_include_dirs { + cflags = append(cflags, esc(b.ClangProperties.Cflags)...) + for _, include := range b.ClangProperties.Local_include_dirs { cflags = append(cflags, "-I"+android.PathForModuleSrc(ctx, include).String()) implicits = append(implicits, android.PathForModuleSrc(ctx, include)) } @@ -134,6 +165,19 @@ func (b *bindgenDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) andr ctx.PropertyErrorf("wrapper_src", "invalid path to wrapper source") } + // Add C std version flag + stdVersion, isCpp := b.getStdVersion(ctx, wrapperFile.Path()) + cflags = append(cflags, "-std="+stdVersion) + + // Specify the header source language to avoid ambiguity. + if isCpp { + cflags = append(cflags, "-x c++") + // Add any C++ only flags. + cflags = append(cflags, esc(b.ClangProperties.Cppflags)...) + } else { + cflags = append(cflags, "-x c") + } + outputFile := android.PathForModuleOut(ctx, b.BaseSourceProvider.getStem(ctx)+".rs") var cmd, cmdDesc string @@ -164,12 +208,14 @@ func (b *bindgenDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) andr func (b *bindgenDecorator) SourceProviderProps() []interface{} { return append(b.BaseSourceProvider.SourceProviderProps(), - &b.Properties) + &b.Properties, &b.ClangProperties) } // rust_bindgen generates Rust FFI bindings to C libraries using bindgen given a wrapper header as the primary input. // Bindgen has a number of flags to control the generated source, and additional flags can be passed to clang to ensure -// the header and generated source is appropriately handled. +// the header and generated source is appropriately handled. It is recommended to add it as a dependency in the +// rlibs, dylibs or rustlibs property. It may also be added in the srcs property for external crates, using the ":" +// prefix. func RustBindgenFactory() android.Module { module, _ := NewRustBindgen(android.HostAndDeviceSupported) return module.Init() @@ -184,6 +230,7 @@ func NewRustBindgen(hod android.HostOrDeviceSupported) (*Module, *bindgenDecorat bindgen := &bindgenDecorator{ BaseSourceProvider: NewSourceProvider(), Properties: BindgenProperties{}, + ClangProperties: cc.RustBindgenClangProperties{}, } module := NewSourceProviderModule(hod, bindgen, false) @@ -194,10 +241,10 @@ func NewRustBindgen(hod android.HostOrDeviceSupported) (*Module, *bindgenDecorat func (b *bindgenDecorator) SourceProviderDeps(ctx DepsContext, deps Deps) Deps { deps = b.BaseSourceProvider.SourceProviderDeps(ctx, deps) if ctx.toolchain().Bionic() { - deps = bionicDeps(deps) + deps = bionicDeps(deps, false) } - deps.SharedLibs = append(deps.SharedLibs, b.Properties.Shared_libs...) - deps.StaticLibs = append(deps.StaticLibs, b.Properties.Static_libs...) + deps.SharedLibs = append(deps.SharedLibs, b.ClangProperties.Shared_libs...) + deps.StaticLibs = append(deps.StaticLibs, b.ClangProperties.Static_libs...) return deps } diff --git a/rust/bindgen_test.go b/rust/bindgen_test.go index 191da9b11..9cccf13be 100644 --- a/rust/bindgen_test.go +++ b/rust/bindgen_test.go @@ -23,6 +23,7 @@ func TestRustBindgen(t *testing.T) { ctx := testRust(t, ` rust_bindgen { name: "libbindgen", + defaults: ["cc_defaults_flags"], wrapper_src: "src/any.h", crate_name: "bindgen", stem: "libbindgen", @@ -40,8 +41,12 @@ func TestRustBindgen(t *testing.T) { name: "libfoo_static", export_include_dirs: ["static_include"], } + cc_defaults { + name: "cc_defaults_flags", + cflags: ["--default-flag"], + } `) - libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a").Output("bindings.rs") + libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a_source").Output("bindings.rs") // Ensure that the flags are present and escaped if !strings.Contains(libbindgen.Args["flags"], "'--bindgen-flag.*'") { t.Errorf("missing bindgen flags in rust_bindgen rule: flags %#v", libbindgen.Args["flags"]) @@ -55,6 +60,9 @@ func TestRustBindgen(t *testing.T) { if !strings.Contains(libbindgen.Args["cflags"], "-Istatic_include") { t.Errorf("missing static_libs exported includes in rust_bindgen rule: cflags %#v", libbindgen.Args["cflags"]) } + if !strings.Contains(libbindgen.Args["cflags"], "--default-flag") { + t.Errorf("rust_bindgen missing cflags defined in cc_defaults: cflags %#v", libbindgen.Args["cflags"]) + } } func TestRustBindgenCustomBindgen(t *testing.T) { @@ -73,7 +81,7 @@ func TestRustBindgenCustomBindgen(t *testing.T) { } `) - libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a").Output("bindings.rs") + libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a_source").Output("bindings.rs") // The rule description should contain the custom binary name rather than bindgen, so checking the description // should be sufficient. @@ -82,3 +90,47 @@ func TestRustBindgenCustomBindgen(t *testing.T) { libbindgen.Description) } } + +func TestRustBindgenStdVersions(t *testing.T) { + testRustError(t, "c_std and cpp_std cannot both be defined at the same time.", ` + rust_bindgen { + name: "libbindgen", + wrapper_src: "src/any.h", + crate_name: "bindgen", + stem: "libbindgen", + source_stem: "bindings", + c_std: "somevalue", + cpp_std: "somevalue", + } + `) + + ctx := testRust(t, ` + rust_bindgen { + name: "libbindgen_cstd", + wrapper_src: "src/any.h", + crate_name: "bindgen", + stem: "libbindgen", + source_stem: "bindings", + c_std: "foo" + } + rust_bindgen { + name: "libbindgen_cppstd", + wrapper_src: "src/any.h", + crate_name: "bindgen", + stem: "libbindgen", + source_stem: "bindings", + cpp_std: "foo" + } + `) + + libbindgen_cstd := ctx.ModuleForTests("libbindgen_cstd", "android_arm64_armv8-a_source").Output("bindings.rs") + libbindgen_cppstd := ctx.ModuleForTests("libbindgen_cppstd", "android_arm64_armv8-a_source").Output("bindings.rs") + + if !strings.Contains(libbindgen_cstd.Args["cflags"], "-std=foo") { + t.Errorf("c_std value not passed in to rust_bindgen as a clang flag") + } + + if !strings.Contains(libbindgen_cppstd.Args["cflags"], "-std=foo") { + t.Errorf("cpp_std value not passed in to rust_bindgen as a clang flag") + } +} diff --git a/rust/compiler.go b/rust/compiler.go index 664578d82..8d2f09c2b 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -24,6 +24,14 @@ import ( "android/soong/rust/config" ) +type RustLinkage int + +const ( + DefaultLinkage RustLinkage = iota + RlibLinkage + DylibLinkage +) + func (compiler *baseCompiler) edition() string { return proptools.StringDefault(compiler.Properties.Edition, config.DefaultEdition) } @@ -146,8 +154,13 @@ func (compiler *baseCompiler) coverageOutputZipPath() android.OptionalPath { panic("baseCompiler does not implement coverageOutputZipPath()") } -func (compiler *baseCompiler) static() bool { - return false +func (compiler *baseCompiler) stdLinkage(ctx *depsContext) RustLinkage { + // For devices, we always link stdlibs in as dylibs by default. + if ctx.Device() { + return DylibLinkage + } else { + return RlibLinkage + } } var _ compiler = (*baseCompiler)(nil) @@ -221,25 +234,24 @@ func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps { stdlib = stdlib + "_" + ctx.toolchain().RustTriple() } - // For devices, we always link stdlibs in as dylibs except for ffi static libraries. - // (rustc does not support linking libstd as a dylib for ffi static libraries) - if ctx.Host() { - deps.Rustlibs = append(deps.Rustlibs, stdlib) - } else if ctx.RustModule().compiler.static() { - deps.Rlibs = append(deps.Rlibs, stdlib) - } else { - deps.Dylibs = append(deps.Dylibs, stdlib) - } + deps.Stdlibs = append(deps.Stdlibs, stdlib) } } return deps } -func bionicDeps(deps Deps) Deps { - deps.SharedLibs = append(deps.SharedLibs, "liblog") - deps.SharedLibs = append(deps.SharedLibs, "libc") - deps.SharedLibs = append(deps.SharedLibs, "libm") - deps.SharedLibs = append(deps.SharedLibs, "libdl") +func bionicDeps(deps Deps, static bool) Deps { + bionicLibs := []string{} + bionicLibs = append(bionicLibs, "liblog") + bionicLibs = append(bionicLibs, "libc") + bionicLibs = append(bionicLibs, "libm") + bionicLibs = append(bionicLibs, "libdl") + + if static { + deps.StaticLibs = append(deps.StaticLibs, bionicLibs...) + } else { + deps.SharedLibs = append(deps.SharedLibs, bionicLibs...) + } //TODO(b/141331117) libstd requires libgcc on Android deps.StaticLibs = append(deps.StaticLibs, "libgcc") diff --git a/rust/compiler_test.go b/rust/compiler_test.go index 56a8ef8ac..a25523c05 100644 --- a/rust/compiler_test.go +++ b/rust/compiler_test.go @@ -191,7 +191,7 @@ func TestStdDeviceLinkage(t *testing.T) { crate_name: "foo", }`) fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Module().(*Module) - fooRlib := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib").Module().(*Module) + fooRlib := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_dylib-std").Module().(*Module) fooDylib := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").Module().(*Module) if !android.InList("libstd", fizz.Properties.AndroidMkDylibs) { diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go index 62d469e4f..483dddb3f 100644 --- a/rust/config/allowed_list.go +++ b/rust/config/allowed_list.go @@ -1,6 +1,10 @@ package config var ( + // When adding a new path below, add a rustfmt.toml file at the root of + // the repository and enable the rustfmt repo hook. See aosp/1347562 + // for an example. + // TODO(b/160223496): enable rustfmt globally. RustAllowedPaths = []string{ "external/minijail", "external/rust", diff --git a/rust/config/arm64_device.go b/rust/config/arm64_device.go index 7d13c42aa..21b22a4d5 100644 --- a/rust/config/arm64_device.go +++ b/rust/config/arm64_device.go @@ -28,6 +28,7 @@ var ( Arm64ArchVariantRustFlags = map[string][]string{ "armv8-a": []string{}, "armv8-2a": []string{}, + "armv8-2a-dotprod": []string{}, } ) diff --git a/rust/config/arm_device.go b/rust/config/arm_device.go index ac4f1c659..adfe917a1 100644 --- a/rust/config/arm_device.go +++ b/rust/config/arm_device.go @@ -52,7 +52,7 @@ type toolchainArm struct { } func (t *toolchainArm) RustTriple() string { - return "arm-linux-androideabi" + return "armv7-linux-androideabi" } func (t *toolchainArm) ToolchainLinkFlags() string { diff --git a/rust/config/global.go b/rust/config/global.go index 6a5251bb5..71c424091 100644 --- a/rust/config/global.go +++ b/rust/config/global.go @@ -24,7 +24,7 @@ import ( var pctx = android.NewPackageContext("android/soong/rust/config") var ( - RustDefaultVersion = "1.45.2" + RustDefaultVersion = "1.46.0" RustDefaultBase = "prebuilts/rust/" DefaultEdition = "2018" Stdlibs = []string{ diff --git a/rust/coverage_test.go b/rust/coverage_test.go index 73673d035..90155ca6e 100644 --- a/rust/coverage_test.go +++ b/rust/coverage_test.go @@ -154,12 +154,12 @@ func TestCoverageZip(t *testing.T) { } // Make sure the expected inputs are provided to the zip rule. - if !android.SuffixInList(fizzZipInputs, "android_arm64_armv8-a_rlib_cov/librlib.gcno") || + if !android.SuffixInList(fizzZipInputs, "android_arm64_armv8-a_rlib_dylib-std_cov/librlib.gcno") || !android.SuffixInList(fizzZipInputs, "android_arm64_armv8-a_static_cov/libbaz.gcno") || !android.SuffixInList(fizzZipInputs, "android_arm64_armv8-a_cov/fizz.gcno") { t.Fatalf("missing expected coverage files for rust 'fizz' binary: %#v", fizzZipInputs) } - if !android.SuffixInList(libfooZipInputs, "android_arm64_armv8-a_rlib_cov/librlib.gcno") || + if !android.SuffixInList(libfooZipInputs, "android_arm64_armv8-a_rlib_dylib-std_cov/librlib.gcno") || !android.SuffixInList(libfooZipInputs, "android_arm64_armv8-a_dylib_cov/libfoo.dylib.gcno") { t.Fatalf("missing expected coverage files for rust 'fizz' binary: %#v", libfooZipInputs) } diff --git a/rust/library.go b/rust/library.go index a44293307..3bba089e6 100644 --- a/rust/library.go +++ b/rust/library.go @@ -15,12 +15,18 @@ package rust import ( + "fmt" "regexp" "strings" "android/soong/android" ) +var ( + DylibStdlibSuffix = ".dylib-std" + RlibStdlibSuffix = ".rlib-std" +) + func init() { android.RegisterModuleType("rust_library", RustLibraryFactory) android.RegisterModuleType("rust_library_dylib", RustLibraryDylibFactory) @@ -49,6 +55,9 @@ type LibraryCompilerProperties struct { // path to include directories to pass to cc_* modules, only relevant for static/shared variants. Include_dirs []string `android:"path,arch_variant"` + + // Whether this library is part of the Rust toolchain sysroot. + Sysroot *bool } type LibraryMutatedProperties struct { @@ -69,10 +78,15 @@ type LibraryMutatedProperties struct { VariantIsShared bool `blueprint:"mutated"` // This variant is a static library VariantIsStatic bool `blueprint:"mutated"` + // This variant is a source provider + VariantIsSource bool `blueprint:"mutated"` // This variant is disabled and should not be compiled // (used for SourceProvider variants that produce only source) VariantIsDisabled bool `blueprint:"mutated"` + + // Whether this library variant should be link libstd via rlibs + VariantIsStaticStd bool `blueprint:"mutated"` } type libraryDecorator struct { @@ -91,6 +105,8 @@ type libraryInterface interface { dylib() bool static() bool shared() bool + sysroot() bool + source() bool // Returns true if the build options for the module have selected a particular build type buildRlib() bool @@ -103,6 +119,11 @@ type libraryInterface interface { setDylib() setShared() setStatic() + setSource() + + // Set libstd linkage + setRlibStd() + setDylibStd() // Build a specific library variant BuildOnlyFFI() @@ -121,6 +142,10 @@ func (library *libraryDecorator) rlib() bool { return library.MutatedProperties.VariantIsRlib } +func (library *libraryDecorator) sysroot() bool { + return Bool(library.Properties.Sysroot) +} + func (library *libraryDecorator) dylib() bool { return library.MutatedProperties.VariantIsDylib } @@ -133,6 +158,18 @@ func (library *libraryDecorator) static() bool { return library.MutatedProperties.VariantIsStatic } +func (library *libraryDecorator) stdLinkage(ctx *depsContext) RustLinkage { + // libraries should only request the RlibLinkage when building a static FFI or when variant is StaticStd + if library.static() || library.MutatedProperties.VariantIsStaticStd { + return RlibLinkage + } + return DefaultLinkage +} + +func (library *libraryDecorator) source() bool { + return library.MutatedProperties.VariantIsSource +} + func (library *libraryDecorator) buildRlib() bool { return library.MutatedProperties.BuildRlib && BoolDefault(library.Properties.Rlib.Enabled, true) } @@ -163,6 +200,14 @@ func (library *libraryDecorator) setDylib() { library.MutatedProperties.VariantIsShared = false } +func (library *libraryDecorator) setRlibStd() { + library.MutatedProperties.VariantIsStaticStd = true +} + +func (library *libraryDecorator) setDylibStd() { + library.MutatedProperties.VariantIsStaticStd = false +} + func (library *libraryDecorator) setShared() { library.MutatedProperties.VariantIsStatic = false library.MutatedProperties.VariantIsShared = true @@ -177,13 +222,17 @@ func (library *libraryDecorator) setStatic() { library.MutatedProperties.VariantIsDylib = false } +func (library *libraryDecorator) setSource() { + library.MutatedProperties.VariantIsSource = true +} + func (library *libraryDecorator) autoDep(ctx BaseModuleContext) autoDep { if library.rlib() || library.static() { return rlibAutoDep } else if library.dylib() || library.shared() { return dylibAutoDep } else { - panic("autoDep called on library" + ctx.ModuleName() + "that has no enabled variants.") + panic(fmt.Errorf("autoDep called on library %q that has no enabled variants.", ctx.ModuleName())) } } @@ -347,7 +396,7 @@ func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps { deps = library.baseCompiler.compilerDeps(ctx, deps) if ctx.toolchain().Bionic() && (library.dylib() || library.shared()) { - deps = bionicDeps(deps) + deps = bionicDeps(deps, false) deps.CrtBegin = "crtbegin_so" deps.CrtEnd = "crtend_so" } @@ -450,6 +499,13 @@ func (library *libraryDecorator) getStem(ctx ModuleContext) string { return stem + String(library.baseCompiler.Properties.Suffix) } +func (library *libraryDecorator) install(ctx ModuleContext) { + // Only shared and dylib variants make sense to install. + if library.shared() || library.dylib() { + library.baseCompiler.install(ctx) + } +} + func (library *libraryDecorator) Disabled() bool { return library.MutatedProperties.VariantIsDisabled } @@ -478,39 +534,85 @@ func validateLibraryStem(ctx BaseModuleContext, filename string, crate_name stri } } +// LibraryMutator mutates the libraries into variants according to the +// build{Rlib,Dylib} attributes. func LibraryMutator(mctx android.BottomUpMutatorContext) { - if m, ok := mctx.Module().(*Module); ok && m.compiler != nil { + // Only mutate on Rust libraries. + m, ok := mctx.Module().(*Module) + if !ok || m.compiler == nil { + return + } + library, ok := m.compiler.(libraryInterface) + if !ok { + return + } + + var variants []string + // The source variant is used for SourceProvider modules. The other variants (i.e. rlib and dylib) + // depend on this variant. It must be the first variant to be declared. + sourceVariant := false + if m.sourceProvider != nil { + variants = append(variants, "source") + sourceVariant = true + } + if library.buildRlib() { + variants = append(variants, rlibVariation) + } + if library.buildDylib() { + variants = append(variants, dylibVariation) + } + + if len(variants) == 0 { + return + } + modules := mctx.CreateLocalVariations(variants...) + + // The order of the variations (modules) matches the variant names provided. Iterate + // through the new variation modules and set their mutated properties. + for i, v := range modules { + switch variants[i] { + case rlibVariation: + v.(*Module).compiler.(libraryInterface).setRlib() + case dylibVariation: + v.(*Module).compiler.(libraryInterface).setDylib() + case "source": + v.(*Module).compiler.(libraryInterface).setSource() + // The source variant does not produce any library. + // Disable the compilation steps. + v.(*Module).compiler.SetDisabled() + } + } + + // If a source variant is created, add an inter-variant dependency + // between the other variants and the source variant. + if sourceVariant { + sv := modules[0] + for _, v := range modules[1:] { + if !v.Enabled() { + continue + } + mctx.AddInterVariantDependency(sourceDepTag, v, sv) + } + // Alias the source variation so it can be named directly in "srcs" properties. + mctx.AliasVariation("source") + } +} + +func LibstdMutator(mctx android.BottomUpMutatorContext) { + if m, ok := mctx.Module().(*Module); ok && m.compiler != nil && !m.compiler.Disabled() { switch library := m.compiler.(type) { case libraryInterface: - if library.buildRlib() && library.buildDylib() { - variants := []string{"rlib", "dylib"} - if m.sourceProvider != nil { - variants = append(variants, "") - } + // Only create a variant if a library is actually being built. + if library.rlib() && !library.sysroot() { + variants := []string{"rlib-std", "dylib-std"} modules := mctx.CreateLocalVariations(variants...) rlib := modules[0].(*Module) dylib := modules[1].(*Module) - rlib.compiler.(libraryInterface).setRlib() - dylib.compiler.(libraryInterface).setDylib() - - if m.sourceProvider != nil { - // This library is SourceProvider generated, so the non-library-producing - // variant needs to disable it's compiler and skip installation. - sourceProvider := modules[2].(*Module) - sourceProvider.compiler.SetDisabled() - } - } else if library.buildRlib() { - modules := mctx.CreateLocalVariations("rlib") - modules[0].(*Module).compiler.(libraryInterface).setRlib() - } else if library.buildDylib() { - modules := mctx.CreateLocalVariations("dylib") - modules[0].(*Module).compiler.(libraryInterface).setDylib() - } - - if m.sourceProvider != nil { - // Alias the non-library variant to the empty-string variant. - mctx.AliasVariation("") + rlib.compiler.(libraryInterface).setRlibStd() + dylib.compiler.(libraryInterface).setDylibStd() + rlib.Properties.SubName += RlibStdlibSuffix + dylib.Properties.SubName += DylibStdlibSuffix } } } diff --git a/rust/library_test.go b/rust/library_test.go index f1bc0507b..fec3992aa 100644 --- a/rust/library_test.go +++ b/rust/library_test.go @@ -37,7 +37,7 @@ func TestLibraryVariants(t *testing.T) { }`) // Test all variants are being built. - libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib").Output("libfoo.rlib") + libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib_rlib-std").Output("libfoo.rlib") libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Output("libfoo.dylib.so") libfooStatic := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_static").Output("libfoo.ffi.a") libfooShared := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_shared").Output("libfoo.ffi.so") @@ -182,14 +182,14 @@ func TestAutoDeps(t *testing.T) { rustlibs: ["libbar"], }`) - libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib") + libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib_rlib-std") libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib") libfooStatic := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_static") libfooShared := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_shared") for _, static := range []android.TestingModule{libfooRlib, libfooStatic} { - if !android.InList("libbar", static.Module().(*Module).Properties.AndroidMkRlibs) { - t.Errorf("libbar not present as static dependency in static lib") + if !android.InList("libbar.rlib-std", static.Module().(*Module).Properties.AndroidMkRlibs) { + t.Errorf("libbar not present as rlib dependency in static lib") } if android.InList("libbar", static.Module().(*Module).Properties.AndroidMkDylibs) { t.Errorf("libbar present as dynamic dependency in static lib") @@ -200,8 +200,8 @@ func TestAutoDeps(t *testing.T) { if !android.InList("libbar", dyn.Module().(*Module).Properties.AndroidMkDylibs) { t.Errorf("libbar not present as dynamic dependency in dynamic lib") } - if android.InList("libbar", dyn.Module().(*Module).Properties.AndroidMkRlibs) { - t.Errorf("libbar present as static dependency in dynamic lib") + if android.InList("libbar.dylib-std", dyn.Module().(*Module).Properties.AndroidMkRlibs) { + t.Errorf("libbar present as rlib dependency in dynamic lib") } } @@ -238,3 +238,45 @@ func TestStrippedLibrary(t *testing.T) { t.Errorf("stripped version of bar has been generated") } } + +func TestLibstdLinkage(t *testing.T) { + ctx := testRust(t, ` + rust_library { + name: "libfoo", + srcs: ["foo.rs"], + crate_name: "foo", + } + rust_ffi { + name: "libbar", + srcs: ["foo.rs"], + crate_name: "bar", + rustlibs: ["libfoo"], + }`) + + libfooDylib := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").Module().(*Module) + libfooRlibStatic := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_rlib-std").Module().(*Module) + libfooRlibDynamic := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_dylib-std").Module().(*Module) + + libbarShared := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module().(*Module) + libbarStatic := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_static").Module().(*Module) + + if !android.InList("libstd", libfooRlibStatic.Properties.AndroidMkRlibs) { + t.Errorf("rlib-std variant for device rust_library_rlib does not link libstd as an rlib") + } + if !android.InList("libstd", libfooRlibDynamic.Properties.AndroidMkDylibs) { + t.Errorf("dylib-std variant for device rust_library_rlib does not link libstd as an dylib") + } + if !android.InList("libstd", libfooDylib.Properties.AndroidMkDylibs) { + t.Errorf("Device rust_library_dylib does not link libstd as an dylib") + } + + if !android.InList("libstd", libbarShared.Properties.AndroidMkDylibs) { + t.Errorf("Device rust_ffi_shared does not link libstd as an dylib") + } + if !android.InList("libstd", libbarStatic.Properties.AndroidMkRlibs) { + t.Errorf("Device rust_ffi_static does not link libstd as an rlib") + } + if !android.InList("libfoo.rlib-std", libbarStatic.Properties.AndroidMkRlibs) { + t.Errorf("Device rust_ffi_static does not link dependent rustlib rlib-std variant") + } +} diff --git a/rust/project_json.go b/rust/project_json.go index 831047938..8d161b2d7 100644 --- a/rust/project_json.go +++ b/rust/project_json.go @@ -30,16 +30,6 @@ import ( // // $ SOONG_GEN_RUST_PROJECT=1 m nothing -func init() { - android.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton) -} - -func rustProjectGeneratorSingleton() android.Singleton { - return &projectGeneratorSingleton{} -} - -type projectGeneratorSingleton struct{} - const ( // Environment variables used to control the behavior of this singleton. envVariableCollectRustDeps = "SOONG_GEN_RUST_PROJECT" @@ -49,6 +39,7 @@ const ( // The format of rust-project.json is not yet finalized. A current description is available at: // https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/manual.adoc#non-cargo-based-projects type rustProjectDep struct { + // The Crate attribute is the index of the dependency in the Crates array in rustProjectJson. Crate int `json:"crate"` Name string `json:"name"` } @@ -71,12 +62,50 @@ type crateInfo struct { Deps map[string]int } -func mergeDependencies(ctx android.SingletonContext, project *rustProjectJson, - knownCrates map[string]crateInfo, module android.Module, - crate *rustProjectCrate, deps map[string]int) { +type projectGeneratorSingleton struct { + project rustProjectJson + knownCrates map[string]crateInfo +} + +func rustProjectGeneratorSingleton() android.Singleton { + return &projectGeneratorSingleton{} +} + +func init() { + android.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton) +} + +// librarySource finds the main source file (.rs) for a crate. +func librarySource(ctx android.SingletonContext, rModule *Module, rustLib *libraryDecorator) (string, bool) { + srcs := rustLib.baseCompiler.Properties.Srcs + if len(srcs) != 0 { + return path.Join(ctx.ModuleDir(rModule), srcs[0]), true + } + if !rustLib.source() { + return "", false + } + // It is a SourceProvider module. If this module is host only, uses the variation for the host. + // Otherwise, use the variation for the primary target. + switch rModule.hod { + case android.HostSupported: + case android.HostSupportedNoCross: + if rModule.Target().String() != ctx.Config().BuildOSTarget.String() { + return "", false + } + default: + if rModule.Target().String() != ctx.Config().Targets[android.Android][0].String() { + return "", false + } + } + src := rustLib.sourceProvider.Srcs()[0] + return src.String(), true +} + +func (singleton *projectGeneratorSingleton) mergeDependencies(ctx android.SingletonContext, + module android.Module, crate *rustProjectCrate, deps map[string]int) { ctx.VisitDirectDeps(module, func(child android.Module) { - childId, childCrateName, ok := appendLibraryAndDeps(ctx, project, knownCrates, child) + childId, childCrateName, ok := singleton.appendLibraryAndDeps(ctx, child) if !ok { return } @@ -88,12 +117,10 @@ func mergeDependencies(ctx android.SingletonContext, project *rustProjectJson, }) } -// appendLibraryAndDeps creates a rustProjectCrate for the module argument and -// appends it to the rustProjectJson struct. It visits the dependencies of the -// module depth-first. If the current module is already in knownCrates, its -// dependencies are merged. Returns a tuple (id, crate_name, ok). -func appendLibraryAndDeps(ctx android.SingletonContext, project *rustProjectJson, - knownCrates map[string]crateInfo, module android.Module) (int, string, bool) { +// appendLibraryAndDeps creates a rustProjectCrate for the module argument and appends it to singleton.project. +// It visits the dependencies of the module depth-first so the dependency ID can be added to the current module. If the +// current module is already in singleton.knownCrates, its dependencies are merged. Returns a tuple (id, crate_name, ok). +func (singleton *projectGeneratorSingleton) appendLibraryAndDeps(ctx android.SingletonContext, module android.Module) (int, string, bool) { rModule, ok := module.(*Module) if !ok { return 0, "", false @@ -107,46 +134,45 @@ func appendLibraryAndDeps(ctx android.SingletonContext, project *rustProjectJson } moduleName := ctx.ModuleName(module) crateName := rModule.CrateName() - if cInfo, ok := knownCrates[moduleName]; ok { + if cInfo, ok := singleton.knownCrates[moduleName]; ok { // We have seen this crate already; merge any new dependencies. - crate := project.Crates[cInfo.ID] - mergeDependencies(ctx, project, knownCrates, module, &crate, cInfo.Deps) - project.Crates[cInfo.ID] = crate + crate := singleton.project.Crates[cInfo.ID] + singleton.mergeDependencies(ctx, module, &crate, cInfo.Deps) + singleton.project.Crates[cInfo.ID] = crate return cInfo.ID, crateName, true } crate := rustProjectCrate{Deps: make([]rustProjectDep, 0), Cfgs: make([]string, 0)} - srcs := rustLib.baseCompiler.Properties.Srcs - if len(srcs) == 0 { + rootModule, ok := librarySource(ctx, rModule, rustLib) + if !ok { return 0, "", false } - crate.RootModule = path.Join(ctx.ModuleDir(rModule), srcs[0]) + crate.RootModule = rootModule crate.Edition = rustLib.baseCompiler.edition() deps := make(map[string]int) - mergeDependencies(ctx, project, knownCrates, module, &crate, deps) + singleton.mergeDependencies(ctx, module, &crate, deps) - id := len(project.Crates) - knownCrates[moduleName] = crateInfo{ID: id, Deps: deps} - project.Crates = append(project.Crates, crate) + id := len(singleton.project.Crates) + singleton.knownCrates[moduleName] = crateInfo{ID: id, Deps: deps} + singleton.project.Crates = append(singleton.project.Crates, crate) // rust-analyzer requires that all crates belong to at least one root: // https://github.com/rust-analyzer/rust-analyzer/issues/4735. - project.Roots = append(project.Roots, path.Dir(crate.RootModule)) + singleton.project.Roots = append(singleton.project.Roots, path.Dir(crate.RootModule)) return id, crateName, true } -func (r *projectGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) { +func (singleton *projectGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) { if !ctx.Config().IsEnvTrue(envVariableCollectRustDeps) { return } - project := rustProjectJson{} - knownCrates := make(map[string]crateInfo) + singleton.knownCrates = make(map[string]crateInfo) ctx.VisitAllModules(func(module android.Module) { - appendLibraryAndDeps(ctx, &project, knownCrates, module) + singleton.appendLibraryAndDeps(ctx, module) }) path := android.PathForOutput(ctx, rustProjectJsonFileName) - err := createJsonFile(project, path) + err := createJsonFile(singleton.project, path) if err != nil { ctx.Errorf(err.Error()) } diff --git a/rust/project_json_test.go b/rust/project_json_test.go index 85219404a..11964f345 100644 --- a/rust/project_json_test.go +++ b/rust/project_json_test.go @@ -18,6 +18,7 @@ import ( "encoding/json" "io/ioutil" "path/filepath" + "strings" "testing" "android/soong/android" @@ -100,22 +101,51 @@ func TestProjectJsonBindGen(t *testing.T) { rust_library { name: "liba", srcs: ["src/lib.rs"], - rlibs: ["libbindings"], + rlibs: ["libbindings1"], crate_name: "a" } rust_bindgen { - name: "libbindings", - crate_name: "bindings", - source_stem: "bindings", + name: "libbindings1", + crate_name: "bindings1", + source_stem: "bindings1", host_supported: true, wrapper_src: "src/any.h", } + rust_library_host { + name: "libb", + srcs: ["src/lib.rs"], + rustlibs: ["libbindings2"], + crate_name: "b" + } + rust_bindgen_host { + name: "libbindings2", + crate_name: "bindings2", + source_stem: "bindings2", + wrapper_src: "src/any.h", + } ` + GatherRequiredDepsForTest() fs := map[string][]byte{ "src/lib.rs": nil, } jsonContent := testProjectJson(t, bp, fs) - validateJsonCrates(t, jsonContent) + crates := validateJsonCrates(t, jsonContent) + for _, c := range crates { + crate, ok := c.(map[string]interface{}) + if !ok { + t.Fatalf("Unexpected type for crate: %v", c) + } + rootModule, ok := crate["root_module"].(string) + if !ok { + t.Fatalf("Unexpected type for root_module: %v", crate["root_module"]) + } + if strings.Contains(rootModule, "libbindings1") && !strings.Contains(rootModule, "android_arm64") { + t.Errorf("The source path for libbindings1 does not contain android_arm64, got %v", rootModule) + } + if strings.Contains(rootModule, "libbindings2") && !strings.Contains(rootModule, android.BuildOs.String()) { + t.Errorf("The source path for libbindings2 does not contain the BuildOs, got %v; want %v", + rootModule, android.BuildOs.String()) + } + } } func TestProjectJsonMultiVersion(t *testing.T) { diff --git a/rust/protobuf_test.go b/rust/protobuf_test.go index a9dbf397d..bd11a5ae3 100644 --- a/rust/protobuf_test.go +++ b/rust/protobuf_test.go @@ -29,7 +29,7 @@ func TestRustProtobuf(t *testing.T) { } `) // Check that there's a rule to generate the expected output - _ = ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_dylib").Output("buf.rs") + _ = ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_source").Output("buf.rs") // Check that libprotobuf is added as a dependency. librust_proto := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_dylib").Module().(*Module) diff --git a/rust/rust.go b/rust/rust.go index b98992c9b..f7207aa7d 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -40,6 +40,7 @@ func init() { android.RegisterModuleType("rust_defaults", defaultsFactory) android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) { ctx.BottomUp("rust_libraries", LibraryMutator).Parallel() + ctx.BottomUp("rust_stdlinkage", LibstdMutator).Parallel() ctx.BottomUp("rust_begin", BeginMutator).Parallel() }) pctx.Import("android/soong/rust/config") @@ -86,8 +87,7 @@ type Module struct { sourceProvider SourceProvider subAndroidMkOnce map[SubAndroidMkProvider]bool - outputFile android.OptionalPath - generatedFile android.OptionalPath + outputFile android.OptionalPath } func (mod *Module) OutputFiles(tag string) (android.Paths, error) { @@ -237,6 +237,7 @@ type Deps struct { Dylibs []string Rlibs []string Rustlibs []string + Stdlibs []string ProcMacros []string SharedLibs []string StaticLibs []string @@ -293,7 +294,7 @@ type compiler interface { Disabled() bool SetDisabled() - static() bool + stdLinkage(ctx *depsContext) RustLinkage } type exportedFlagsProducer interface { @@ -386,6 +387,7 @@ func DefaultsFactory(props ...interface{}) android.Module { module.AddProperties(props...) module.AddProperties( &BaseProperties{}, + &BindgenProperties{}, &BaseCompilerProperties{}, &BinaryCompilerProperties{}, &LibraryCompilerProperties{}, @@ -394,6 +396,7 @@ func DefaultsFactory(props ...interface{}) android.Module { &SourceProviderProperties{}, &TestProperties{}, &cc.CoverageProperties{}, + &cc.RustBindgenClangProperties{}, &ClippyProperties{}, ) @@ -458,12 +461,20 @@ func (mod *Module) SetBuildStubs() { panic("SetBuildStubs not yet implemented for rust modules") } -func (mod *Module) SetStubsVersions(string) { - panic("SetStubsVersions not yet implemented for rust modules") +func (mod *Module) SetStubsVersion(string) { + panic("SetStubsVersion not yet implemented for rust modules") } func (mod *Module) StubsVersion() string { - panic("SetStubsVersions not yet implemented for rust modules") + panic("StubsVersion not yet implemented for rust modules") +} + +func (mod *Module) SetAllStubsVersions([]string) { + panic("SetAllStubsVersions not yet implemented for rust modules") +} + +func (mod *Module) AllStubsVersions() []string { + return nil } func (mod *Module) BuildStaticVariant() bool { @@ -677,12 +688,25 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { flags, deps = mod.clippy.flags(ctx, flags, deps) } - // SourceProvider needs to call GenerateSource() before compiler calls compile() so it can provide the source. - // TODO(b/162588681) This shouldn't have to run for every variant. + // SourceProvider needs to call GenerateSource() before compiler calls + // compile() so it can provide the source. A SourceProvider has + // multiple variants (e.g. source, rlib, dylib). Only the "source" + // variant is responsible for effectively generating the source. The + // remaining variants relies on the "source" variant output. if mod.sourceProvider != nil { - generatedFile := mod.sourceProvider.GenerateSource(ctx, deps) - mod.generatedFile = android.OptionalPathForPath(generatedFile) - mod.sourceProvider.setSubName(ctx.ModuleSubDir()) + if mod.compiler.(libraryInterface).source() { + mod.sourceProvider.GenerateSource(ctx, deps) + mod.sourceProvider.setSubName(ctx.ModuleSubDir()) + if lib, ok := mod.compiler.(*libraryDecorator); ok { + lib.flagExporter.linkDirs = nil + lib.flagExporter.linkObjects = nil + lib.flagExporter.depFlags = nil + } + } else { + sourceMod := actx.GetDirectDepWithTag(mod.Name(), sourceDepTag) + sourceLib := sourceMod.(*Module).compiler.(*libraryDecorator) + mod.sourceProvider.setOutputFile(sourceLib.sourceProvider.Srcs()[0]) + } } if mod.compiler != nil && !mod.compiler.Disabled() { @@ -733,6 +757,7 @@ var ( dylibDepTag = dependencyTag{name: "dylib", library: true} procMacroDepTag = dependencyTag{name: "procMacro", proc_macro: true} testPerSrcDepTag = dependencyTag{name: "rust_unit_tests"} + sourceDepTag = dependencyTag{name: "source"} ) type autoDep struct { @@ -741,8 +766,10 @@ type autoDep struct { } var ( - rlibAutoDep = autoDep{variation: "rlib", depTag: rlibDepTag} - dylibAutoDep = autoDep{variation: "dylib", depTag: dylibDepTag} + rlibVariation = "rlib" + dylibVariation = "dylib" + rlibAutoDep = autoDep{variation: rlibVariation, depTag: rlibDepTag} + dylibAutoDep = autoDep{variation: dylibVariation, depTag: dylibDepTag} ) type autoDeppable interface { @@ -782,14 +809,15 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { directDylibDeps = append(directDylibDeps, rustDep) mod.Properties.AndroidMkDylibs = append(mod.Properties.AndroidMkDylibs, depName) case rlibDepTag: + rlib, ok := rustDep.compiler.(libraryInterface) if !ok || !rlib.rlib() { - ctx.ModuleErrorf("mod %q not an rlib library", depName) + ctx.ModuleErrorf("mod %q not an rlib library", depName+rustDep.Properties.SubName) return } depPaths.coverageFiles = append(depPaths.coverageFiles, rustDep.CoverageFiles()...) directRlibDeps = append(directRlibDeps, rustDep) - mod.Properties.AndroidMkRlibs = append(mod.Properties.AndroidMkRlibs, depName) + mod.Properties.AndroidMkRlibs = append(mod.Properties.AndroidMkRlibs, depName+rustDep.Properties.SubName) case procMacroDepTag: directProcMacroDeps = append(directProcMacroDeps, rustDep) mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, depName) @@ -976,23 +1004,50 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { commonDepVariations = append(commonDepVariations, blueprint.Variation{Mutator: "image", Variation: android.CoreVariation}) } + + stdLinkage := "dylib-std" + if mod.compiler.stdLinkage(ctx) == RlibLinkage { + stdLinkage = "rlib-std" + } + + rlibDepVariations := commonDepVariations + if lib, ok := mod.compiler.(libraryInterface); !ok || !lib.sysroot() { + rlibDepVariations = append(rlibDepVariations, + blueprint.Variation{Mutator: "rust_stdlinkage", Variation: stdLinkage}) + } + actx.AddVariationDependencies( - append(commonDepVariations, []blueprint.Variation{ - {Mutator: "rust_libraries", Variation: "rlib"}}...), + append(rlibDepVariations, []blueprint.Variation{ + {Mutator: "rust_libraries", Variation: rlibVariation}}...), rlibDepTag, deps.Rlibs...) actx.AddVariationDependencies( append(commonDepVariations, []blueprint.Variation{ - {Mutator: "rust_libraries", Variation: "dylib"}}...), + {Mutator: "rust_libraries", Variation: dylibVariation}}...), dylibDepTag, deps.Dylibs...) if deps.Rustlibs != nil && !mod.compiler.Disabled() { autoDep := mod.compiler.(autoDeppable).autoDep(ctx) - actx.AddVariationDependencies( - append(commonDepVariations, []blueprint.Variation{ - {Mutator: "rust_libraries", Variation: autoDep.variation}}...), - autoDep.depTag, deps.Rustlibs...) + if autoDep.depTag == rlibDepTag { + actx.AddVariationDependencies( + append(rlibDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation}), + autoDep.depTag, deps.Rustlibs...) + } else { + actx.AddVariationDependencies( + append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation}), + autoDep.depTag, deps.Rustlibs...) + } + } + if deps.Stdlibs != nil { + if mod.compiler.stdLinkage(ctx) == RlibLinkage { + actx.AddVariationDependencies( + append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: "rlib"}), + rlibDepTag, deps.Stdlibs...) + } else { + actx.AddVariationDependencies( + append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: "dylib"}), + dylibDepTag, deps.Stdlibs...) + } } - actx.AddVariationDependencies(append(commonDepVariations, blueprint.Variation{Mutator: "link", Variation: "shared"}), cc.SharedDepTag(), deps.SharedLibs...) diff --git a/rust/rust_test.go b/rust/rust_test.go index 89ce35919..4842a4ca8 100644 --- a/rust/rust_test.go +++ b/rust/rust_test.go @@ -189,7 +189,7 @@ func TestDepsTracking(t *testing.T) { t.Errorf("Dylib dependency not detected (dependency missing from AndroidMkDylibs)") } - if !android.InList("librlib", module.Properties.AndroidMkRlibs) { + if !android.InList("librlib.rlib-std", module.Properties.AndroidMkRlibs) { t.Errorf("Rlib dependency not detected (dependency missing from AndroidMkRlibs)") } @@ -253,7 +253,7 @@ func TestSourceProviderDeps(t *testing.T) { } `) - libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib").Rule("rustc") + libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_dylib-std").Rule("rustc") if !android.SuffixInList(libfoo.Implicits.Strings(), "/out/bindings.rs") { t.Errorf("rust_bindgen generated source not included as implicit input for libfoo; Implicits %#v", libfoo.Implicits.Strings()) } @@ -279,15 +279,15 @@ func TestSourceProviderDeps(t *testing.T) { // Check that our bindings are picked up as crate dependencies as well libfooMod := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").Module().(*Module) - if !android.InList("libbindings", libfooMod.Properties.AndroidMkRlibs) { + if !android.InList("libbindings.dylib-std", libfooMod.Properties.AndroidMkRlibs) { t.Errorf("bindgen dependency not detected as a rlib dependency (dependency missing from AndroidMkRlibs)") } fizzBuzzMod := ctx.ModuleForTests("fizz-buzz-dep", "android_arm64_armv8-a").Module().(*Module) - if !android.InList("libbindings", fizzBuzzMod.Properties.AndroidMkRlibs) { + if !android.InList("libbindings.dylib-std", fizzBuzzMod.Properties.AndroidMkRlibs) { t.Errorf("bindgen dependency not detected as a rlib dependency (dependency missing from AndroidMkRlibs)") } libprocmacroMod := ctx.ModuleForTests("libprocmacro", "linux_glibc_x86_64").Module().(*Module) - if !android.InList("libbindings", libprocmacroMod.Properties.AndroidMkRlibs) { + if !android.InList("libbindings.rlib-std", libprocmacroMod.Properties.AndroidMkRlibs) { t.Errorf("bindgen dependency not detected as a rlib dependency (dependency missing from AndroidMkRlibs)") } @@ -365,6 +365,6 @@ func TestMultilib(t *testing.T) { crate_name: "foo", }`) - _ = ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib") - _ = ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_rlib") + _ = ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_dylib-std") + _ = ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_rlib_dylib-std") } diff --git a/rust/source_provider.go b/rust/source_provider.go index 755a369a7..03adf9e6f 100644 --- a/rust/source_provider.go +++ b/rust/source_provider.go @@ -43,6 +43,7 @@ type SourceProvider interface { SourceProviderProps() []interface{} SourceProviderDeps(ctx DepsContext, deps Deps) Deps setSubName(subName string) + setOutputFile(outputFile android.Path) } func (sp *BaseSourceProvider) Srcs() android.Paths { @@ -95,3 +96,7 @@ func (sp *BaseSourceProvider) SourceProviderDeps(ctx DepsContext, deps Deps) Dep func (sp *BaseSourceProvider) setSubName(subName string) { sp.subName = subName } + +func (sp *BaseSourceProvider) setOutputFile(outputFile android.Path) { + sp.OutputFile = outputFile +} diff --git a/rust/test.go b/rust/test.go index d93fc313f..bc7f53c7c 100644 --- a/rust/test.go +++ b/rust/test.go @@ -133,3 +133,7 @@ func RustTestHostFactory() android.Module { module, _ := NewRustTest(android.HostSupported) return module.Init() } + +func (test *testDecorator) stdLinkage(ctx *depsContext) RustLinkage { + return RlibLinkage +} diff --git a/rust/test_test.go b/rust/test_test.go index 2382b1848..fea2ad059 100644 --- a/rust/test_test.go +++ b/rust/test_test.go @@ -17,6 +17,8 @@ package rust import ( "strings" "testing" + + "android/soong/android" ) func TestRustTest(t *testing.T) { @@ -33,3 +35,35 @@ func TestRustTest(t *testing.T) { t.Errorf("wrong output path: %v; expected: %v", outPath, expectedOut) } } + +func TestRustTestLinkage(t *testing.T) { + ctx := testRust(t, ` + rust_test { + name: "my_test", + srcs: ["foo.rs"], + rustlibs: ["libfoo"], + rlibs: ["libbar"], + } + rust_library { + name: "libfoo", + srcs: ["foo.rs"], + crate_name: "foo", + } + rust_library { + name: "libbar", + srcs: ["foo.rs"], + crate_name: "bar", + }`) + + testingModule := ctx.ModuleForTests("my_test", "android_arm64_armv8-a").Module().(*Module) + + if !android.InList("libfoo.rlib-std", testingModule.Properties.AndroidMkRlibs) { + t.Errorf("rlib-std variant for libfoo not detected as a rustlib-defined rlib dependency for device rust_test module") + } + if !android.InList("libbar.rlib-std", testingModule.Properties.AndroidMkRlibs) { + t.Errorf("rlib-std variant for libbar not detected as an rlib dependency for device rust_test module") + } + if !android.InList("libstd", testingModule.Properties.AndroidMkRlibs) { + t.Errorf("Device rust_test module 'my_test' does not link libstd as an rlib") + } +} diff --git a/rust/testing.go b/rust/testing.go index 0144c8218..42b0da171 100644 --- a/rust/testing.go +++ b/rust/testing.go @@ -32,6 +32,7 @@ func GatherRequiredDepsForTest() string { srcs: ["libstd.so"], }, host_supported: true, + sysroot: true, } rust_prebuilt_library { name: "libtest_x86_64-unknown-linux-gnu", @@ -43,6 +44,7 @@ func GatherRequiredDepsForTest() string { srcs: ["libtest.so"], }, host_supported: true, + sysroot: true, } rust_prebuilt_library { name: "libstd_x86_64-apple-darwin", @@ -54,6 +56,7 @@ func GatherRequiredDepsForTest() string { srcs: ["libstd.so"], }, host_supported: true, + sysroot: true, } rust_prebuilt_library { name: "libtest_x86_64-apple-darwin", @@ -65,6 +68,7 @@ func GatherRequiredDepsForTest() string { srcs: ["libtest.so"], }, host_supported: true, + sysroot: true, } ////////////////////////////// // Device module requirements @@ -82,6 +86,7 @@ func GatherRequiredDepsForTest() string { no_stdlibs: true, host_supported: true, native_coverage: false, + sysroot: true, } rust_library { name: "libtest", @@ -90,6 +95,7 @@ func GatherRequiredDepsForTest() string { no_stdlibs: true, host_supported: true, native_coverage: false, + sysroot: true, } rust_library { name: "libprotobuf", @@ -111,6 +117,7 @@ func CreateTestContext() *android.TestContext { ctx.RegisterModuleType("rust_binary", RustBinaryFactory) ctx.RegisterModuleType("rust_binary_host", RustBinaryHostFactory) ctx.RegisterModuleType("rust_bindgen", RustBindgenFactory) + ctx.RegisterModuleType("rust_bindgen_host", RustBindgenHostFactory) ctx.RegisterModuleType("rust_test", RustTestFactory) ctx.RegisterModuleType("rust_test_host", RustTestHostFactory) ctx.RegisterModuleType("rust_library", RustLibraryFactory) @@ -134,6 +141,7 @@ func CreateTestContext() *android.TestContext { ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) { // rust mutators ctx.BottomUp("rust_libraries", LibraryMutator).Parallel() + ctx.BottomUp("rust_stdlinkage", LibstdMutator).Parallel() ctx.BottomUp("rust_begin", BeginMutator).Parallel() }) ctx.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton) diff --git a/scripts/update-apex-allowed-deps.sh b/scripts/update-apex-allowed-deps.sh new file mode 100755 index 000000000..872d74670 --- /dev/null +++ b/scripts/update-apex-allowed-deps.sh @@ -0,0 +1,39 @@ +#!/bin/bash -e +# +# The script to run locally to re-generate global allowed list of dependencies +# for updatable modules. + +if [ ! -e "build/envsetup.sh" ]; then + echo "ERROR: $0 must be run from the top of the tree" + exit 1 +fi + +source build/envsetup.sh > /dev/null || exit 1 + +readonly OUT_DIR=$(get_build_var OUT_DIR) + +readonly ALLOWED_DEPS_FILE="build/soong/apex/allowed_deps.txt" +readonly NEW_ALLOWED_DEPS_FILE="${OUT_DIR}/soong/apex/depsinfo/new-allowed-deps.txt" + +# If the script is run after droidcore failure, ${NEW_ALLOWED_DEPS_FILE} +# should already be built. If running the script manually, make sure it exists. +m "${NEW_ALLOWED_DEPS_FILE}" -j + +cat > "${ALLOWED_DEPS_FILE}" << EndOfFileComment +# A list of allowed dependencies for all updatable modules. +# +# The list tracks all direct and transitive dependencies that end up within any +# of the updatable binaries; specifically excluding external dependencies +# required to compile those binaries. This prevents potential regressions in +# case a new dependency is not aware of the different functional and +# non-functional requirements being part of an updatable module, for example +# setting correct min_sdk_version. +# +# To update the list, run: +# repo-root$ build/soong/scripts/update-apex-allowed-deps.sh +# +# See go/apex-allowed-deps-error for more details. +# TODO(b/157465465): introduce automated quality signals and remove this list. +EndOfFileComment + +cat "${NEW_ALLOWED_DEPS_FILE}" >> "${ALLOWED_DEPS_FILE}" @@ -16,6 +16,8 @@ package sdk import ( "fmt" + "reflect" + "strings" "android/soong/android" ) @@ -33,7 +35,82 @@ func (s *bpPropertySet) init() { s.tags = make(map[string]android.BpPropertyTag) } +// Converts the given value, which is assumed to be a struct, to a +// bpPropertySet. +func convertToPropertySet(value reflect.Value) *bpPropertySet { + res := newPropertySet() + structType := value.Type() + + for i := 0; i < structType.NumField(); i++ { + field := structType.Field(i) + fieldVal := value.Field(i) + + switch fieldVal.Type().Kind() { + case reflect.Ptr: + if fieldVal.IsNil() { + continue // nil pointer means the property isn't set. + } + fieldVal = fieldVal.Elem() + case reflect.Slice: + if fieldVal.IsNil() { + continue // Ignore a nil slice (but not one with length zero). + } + } + + if fieldVal.Type().Kind() == reflect.Struct { + fieldVal = fieldVal.Addr() // Avoid struct copy below. + } + res.AddProperty(strings.ToLower(field.Name), fieldVal.Interface()) + } + + return res +} + +// Converts the given value to something that can be set in a property. +func coercePropertyValue(value interface{}) interface{} { + val := reflect.ValueOf(value) + switch val.Kind() { + case reflect.Struct: + // convertToPropertySet requires an addressable struct, and this is probably + // a mistake. + panic(fmt.Sprintf("Value is a struct, not a pointer to one: %v", value)) + case reflect.Ptr: + if _, ok := value.(*bpPropertySet); !ok { + derefValue := reflect.Indirect(val) + if derefValue.Kind() != reflect.Struct { + panic(fmt.Sprintf("A pointer must be to a struct, got: %v", value)) + } + return convertToPropertySet(derefValue) + } + } + return value +} + +// Merges the fields of the given property set into s. +func (s *bpPropertySet) mergePropertySet(propSet *bpPropertySet) { + for _, name := range propSet.order { + if tag, ok := propSet.tags[name]; ok { + s.AddPropertyWithTag(name, propSet.properties[name], tag) + } else { + s.AddProperty(name, propSet.properties[name]) + } + } +} + func (s *bpPropertySet) AddProperty(name string, value interface{}) { + value = coercePropertyValue(value) + + if propSetValue, ok := value.(*bpPropertySet); ok { + if curValue, ok := s.properties[name]; ok { + if curSet, ok := curValue.(*bpPropertySet); ok { + curSet.mergePropertySet(propSetValue) + return + } + // If the current value isn't a property set we got conflicting types. + // Continue down to the check below to complain about it. + } + } + if s.properties[name] != nil { panic(fmt.Sprintf("Property %q already exists in property set", name)) } @@ -48,9 +125,8 @@ func (s *bpPropertySet) AddPropertyWithTag(name string, value interface{}, tag a } func (s *bpPropertySet) AddPropertySet(name string) android.BpPropertySet { - set := newPropertySet() - s.AddProperty(name, set) - return set + s.AddProperty(name, newPropertySet()) + return s.properties[name].(android.BpPropertySet) } func (s *bpPropertySet) getValue(name string) interface{} { diff --git a/sdk/bp_test.go b/sdk/bp_test.go index c630c2524..e1edc5131 100644 --- a/sdk/bp_test.go +++ b/sdk/bp_test.go @@ -18,8 +18,142 @@ import ( "testing" "android/soong/android" + + "github.com/google/blueprint/proptools" ) +func propertySetFixture() interface{} { + set := newPropertySet() + set.AddProperty("x", "taxi") + set.AddPropertyWithTag("y", 1729, "tag_y") + subset := set.AddPropertySet("sub") + subset.AddPropertyWithTag("x", "taxi", "tag_x") + subset.AddProperty("y", 1729) + return set +} + +func intPtr(i int) *int { return &i } + +type propertyStruct struct { + X *string + Y *int + Unset *bool + Sub struct { + X *string + Y *int + Unset *bool + } +} + +func propertyStructFixture() interface{} { + str := &propertyStruct{} + str.X = proptools.StringPtr("taxi") + str.Y = intPtr(1729) + str.Sub.X = proptools.StringPtr("taxi") + str.Sub.Y = intPtr(1729) + return str +} + +func checkPropertySetFixture(h *TestHelper, val interface{}, hasTags bool) { + set := val.(*bpPropertySet) + h.AssertDeepEquals("wrong x value", "taxi", set.getValue("x")) + h.AssertDeepEquals("wrong y value", 1729, set.getValue("y")) + + subset := set.getValue("sub").(*bpPropertySet) + h.AssertDeepEquals("wrong sub.x value", "taxi", subset.getValue("x")) + h.AssertDeepEquals("wrong sub.y value", 1729, subset.getValue("y")) + + if hasTags { + h.AssertDeepEquals("wrong y tag", "tag_y", set.getTag("y")) + h.AssertDeepEquals("wrong sub.x tag", "tag_x", subset.getTag("x")) + } else { + h.AssertDeepEquals("wrong y tag", nil, set.getTag("y")) + h.AssertDeepEquals("wrong sub.x tag", nil, subset.getTag("x")) + } +} + +func TestAddPropertySimple(t *testing.T) { + h := &TestHelper{t} + set := newPropertySet() + for name, val := range map[string]interface{}{ + "x": "taxi", + "y": 1729, + "t": true, + "f": false, + "arr": []string{"a", "b", "c"}, + } { + set.AddProperty(name, val) + h.AssertDeepEquals("wrong value", val, set.getValue(name)) + } + h.AssertPanic("adding x again should panic", + func() { set.AddProperty("x", "taxi") }) + h.AssertPanic("adding arr again should panic", + func() { set.AddProperty("arr", []string{"d"}) }) +} + +func TestAddPropertySubset(t *testing.T) { + h := &TestHelper{t} + getFixtureMap := map[string]func() interface{}{ + "property set": propertySetFixture, + "property struct": propertyStructFixture, + } + + t.Run("add new subset", func(t *testing.T) { + for name, getFixture := range getFixtureMap { + t.Run(name, func(t *testing.T) { + set := propertySetFixture().(*bpPropertySet) + set.AddProperty("new", getFixture()) + checkPropertySetFixture(h, set, true) + checkPropertySetFixture(h, set.getValue("new"), name == "property set") + }) + } + }) + + t.Run("merge existing subset", func(t *testing.T) { + for name, getFixture := range getFixtureMap { + t.Run(name, func(t *testing.T) { + set := newPropertySet() + subset := set.AddPropertySet("sub") + subset.AddProperty("flag", false) + subset.AddPropertySet("sub") + set.AddProperty("sub", getFixture()) + merged := set.getValue("sub").(*bpPropertySet) + h.AssertDeepEquals("wrong flag value", false, merged.getValue("flag")) + checkPropertySetFixture(h, merged, name == "property set") + }) + } + }) + + t.Run("add conflicting subset", func(t *testing.T) { + set := propertySetFixture().(*bpPropertySet) + h.AssertPanic("adding x again should panic", + func() { set.AddProperty("x", propertySetFixture()) }) + }) + + t.Run("add non-pointer struct", func(t *testing.T) { + set := propertySetFixture().(*bpPropertySet) + str := propertyStructFixture().(*propertyStruct) + h.AssertPanic("adding a non-pointer struct should panic", + func() { set.AddProperty("new", *str) }) + }) +} + +func TestAddPropertySetNew(t *testing.T) { + h := &TestHelper{t} + set := newPropertySet() + subset := set.AddPropertySet("sub") + subset.AddProperty("new", "d^^b") + h.AssertDeepEquals("wrong sub.new value", "d^^b", set.getValue("sub").(*bpPropertySet).getValue("new")) +} + +func TestAddPropertySetExisting(t *testing.T) { + h := &TestHelper{t} + set := propertySetFixture().(*bpPropertySet) + subset := set.AddPropertySet("sub") + subset.AddProperty("new", "d^^b") + h.AssertDeepEquals("wrong sub.new value", "d^^b", set.getValue("sub").(*bpPropertySet).getValue("new")) +} + type removeFredTransformation struct { identityTransformation } diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go index 8c9e2285d..c214e75c4 100644 --- a/sdk/cc_sdk_test.go +++ b/sdk/cc_sdk_test.go @@ -108,6 +108,7 @@ func TestSdkCompileMultilibOverride(t *testing.T) { cc_prebuilt_library_shared { name: "mysdk_sdkmember@current", sdk_member_name: "sdkmember", + visibility: ["//visibility:public"], host_supported: true, installable: false, stl: "none", @@ -131,6 +132,7 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "sdkmember", prefer: false, + visibility: ["//visibility:public"], host_supported: true, stl: "none", compile_multilib: "64", @@ -152,6 +154,7 @@ cc_prebuilt_library_shared { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], host_supported: true, native_shared_libs: ["mysdk_sdkmember@current"], compile_multilib: "64", @@ -353,6 +356,7 @@ func TestSnapshotWithObject(t *testing.T) { cc_prebuilt_object { name: "mysdk_crtobj@current", sdk_member_name: "crtobj", + visibility: ["//visibility:public"], stl: "none", compile_multilib: "both", sanitize: { @@ -371,6 +375,7 @@ cc_prebuilt_object { cc_prebuilt_object { name: "crtobj", prefer: false, + visibility: ["//visibility:public"], stl: "none", compile_multilib: "both", sanitize: { @@ -388,6 +393,7 @@ cc_prebuilt_object { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], native_objects: ["mysdk_crtobj@current"], } `), @@ -435,8 +441,10 @@ include/Test.h -> include/include/Test.h ) } -// Verify that when the shared library has some common and some arch specific properties that the generated -// snapshot is optimized properly. +// Verify that when the shared library has some common and some arch specific +// properties that the generated snapshot is optimized properly. Substruct +// handling is tested with the sanitize clauses (but note there's a lot of +// built-in logic in sanitize.go that can affect those flags). func TestSnapshotWithCcSharedLibraryCommonProperties(t *testing.T) { result := testSdkWithCc(t, ` sdk { @@ -451,9 +459,18 @@ func TestSnapshotWithCcSharedLibraryCommonProperties(t *testing.T) { "aidl/foo/bar/Test.aidl", ], export_include_dirs: ["include"], + sanitize: { + fuzzer: false, + integer_overflow: true, + diag: { undefined: false }, + }, arch: { arm64: { export_system_include_dirs: ["arm64/include"], + sanitize: { + hwaddress: true, + integer_overflow: false, + }, }, }, stl: "none", @@ -467,17 +484,31 @@ func TestSnapshotWithCcSharedLibraryCommonProperties(t *testing.T) { cc_prebuilt_library_shared { name: "mysdk_mynativelib@current", sdk_member_name: "mynativelib", + visibility: ["//visibility:public"], installable: false, stl: "none", compile_multilib: "both", export_include_dirs: ["include/include"], + sanitize: { + fuzzer: false, + diag: { + undefined: false, + }, + }, arch: { arm64: { srcs: ["arm64/lib/mynativelib.so"], export_system_include_dirs: ["arm64/include/arm64/include"], + sanitize: { + hwaddress: true, + integer_overflow: false, + }, }, arm: { srcs: ["arm/lib/mynativelib.so"], + sanitize: { + integer_overflow: true, + }, }, }, } @@ -485,28 +516,43 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "mynativelib", prefer: false, + visibility: ["//visibility:public"], stl: "none", compile_multilib: "both", export_include_dirs: ["include/include"], + sanitize: { + fuzzer: false, + diag: { + undefined: false, + }, + }, arch: { arm64: { srcs: ["arm64/lib/mynativelib.so"], export_system_include_dirs: ["arm64/include/arm64/include"], + sanitize: { + hwaddress: true, + integer_overflow: false, + }, }, arm: { srcs: ["arm/lib/mynativelib.so"], + sanitize: { + integer_overflow: true, + }, }, }, } sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], native_shared_libs: ["mysdk_mynativelib@current"], } `), checkAllCopyRules(` include/Test.h -> include/include/Test.h -.intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so +.intermediates/mynativelib/android_arm64_armv8-a_shared_hwasan/mynativelib.so -> arm64/lib/mynativelib.so arm64/include/Arm64Test.h -> arm64/include/arm64/include/Arm64Test.h .intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so`), ) @@ -535,6 +581,7 @@ func TestSnapshotWithCcBinary(t *testing.T) { cc_prebuilt_binary { name: "mymodule_exports_mynativebinary@current", sdk_member_name: "mynativebinary", + visibility: ["//visibility:public"], installable: false, compile_multilib: "both", arch: { @@ -550,6 +597,7 @@ cc_prebuilt_binary { cc_prebuilt_binary { name: "mynativebinary", prefer: false, + visibility: ["//visibility:public"], compile_multilib: "both", arch: { arm64: { @@ -563,6 +611,7 @@ cc_prebuilt_binary { module_exports_snapshot { name: "mymodule_exports@current", + visibility: ["//visibility:public"], native_binaries: ["mymodule_exports_mynativebinary@current"], } `), @@ -611,6 +660,7 @@ func TestMultipleHostOsTypesSnapshotWithCcBinary(t *testing.T) { cc_prebuilt_binary { name: "myexports_mynativebinary@current", sdk_member_name: "mynativebinary", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, installable: false, @@ -642,6 +692,7 @@ cc_prebuilt_binary { cc_prebuilt_binary { name: "mynativebinary", prefer: false, + visibility: ["//visibility:public"], device_supported: false, host_supported: true, stl: "none", @@ -671,6 +722,7 @@ cc_prebuilt_binary { module_exports_snapshot { name: "myexports@current", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, native_binaries: ["myexports_mynativebinary@current"], @@ -749,6 +801,7 @@ func TestSnapshotWithSingleHostOsType(t *testing.T) { cc_prebuilt_binary { name: "myexports_mynativebinary@current", sdk_member_name: "mynativebinary", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, installable: false, @@ -770,6 +823,7 @@ cc_prebuilt_binary { cc_prebuilt_binary { name: "mynativebinary", prefer: false, + visibility: ["//visibility:public"], device_supported: false, host_supported: true, stl: "none", @@ -790,6 +844,7 @@ cc_prebuilt_binary { cc_prebuilt_library_shared { name: "myexports_mynativelib@current", sdk_member_name: "mynativelib", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, installable: false, @@ -811,6 +866,7 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "mynativelib", prefer: false, + visibility: ["//visibility:public"], device_supported: false, host_supported: true, stl: "none", @@ -830,6 +886,7 @@ cc_prebuilt_library_shared { module_exports_snapshot { name: "myexports@current", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, native_binaries: ["myexports_mynativebinary@current"], @@ -883,6 +940,7 @@ func TestSnapshotWithCcStaticNocrtBinary(t *testing.T) { cc_prebuilt_binary { name: "mymodule_exports_linker@current", sdk_member_name: "linker", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, installable: false, @@ -909,6 +967,7 @@ cc_prebuilt_binary { cc_prebuilt_binary { name: "linker", prefer: false, + visibility: ["//visibility:public"], device_supported: false, host_supported: true, stl: "none", @@ -933,6 +992,7 @@ cc_prebuilt_binary { module_exports_snapshot { name: "mymodule_exports@current", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, native_binaries: ["mymodule_exports_linker@current"], @@ -982,6 +1042,7 @@ func TestSnapshotWithCcSharedLibrary(t *testing.T) { cc_prebuilt_library_shared { name: "mysdk_mynativelib@current", sdk_member_name: "mynativelib", + visibility: ["//visibility:public"], apex_available: [ "apex1", "apex2", @@ -1005,6 +1066,7 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "mynativelib", prefer: false, + visibility: ["//visibility:public"], apex_available: [ "apex1", "apex2", @@ -1026,6 +1088,7 @@ cc_prebuilt_library_shared { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], native_shared_libs: ["mysdk_mynativelib@current"], } `), @@ -1110,6 +1173,7 @@ func TestSnapshotWithCcSharedLibrarySharedLibs(t *testing.T) { cc_prebuilt_library_shared { name: "mysdk_mynativelib@current", sdk_member_name: "mynativelib", + visibility: ["//visibility:public"], installable: false, stl: "none", compile_multilib: "both", @@ -1130,6 +1194,7 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "mynativelib", prefer: false, + visibility: ["//visibility:public"], stl: "none", compile_multilib: "both", shared_libs: [ @@ -1149,6 +1214,7 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "mysdk_myothernativelib@current", sdk_member_name: "myothernativelib", + visibility: ["//visibility:public"], installable: false, stl: "none", compile_multilib: "both", @@ -1166,6 +1232,7 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "myothernativelib", prefer: false, + visibility: ["//visibility:public"], stl: "none", compile_multilib: "both", system_shared_libs: ["libm"], @@ -1182,6 +1249,7 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "mysdk_mysystemnativelib@current", sdk_member_name: "mysystemnativelib", + visibility: ["//visibility:public"], installable: false, stl: "none", compile_multilib: "both", @@ -1198,6 +1266,7 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "mysystemnativelib", prefer: false, + visibility: ["//visibility:public"], stl: "none", compile_multilib: "both", arch: { @@ -1212,6 +1281,7 @@ cc_prebuilt_library_shared { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], native_shared_libs: [ "mysdk_mynativelib@current", "mysdk_myothernativelib@current", @@ -1263,6 +1333,7 @@ func TestHostSnapshotWithCcSharedLibrary(t *testing.T) { cc_prebuilt_library_shared { name: "mysdk_mynativelib@current", sdk_member_name: "mynativelib", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, installable: false, @@ -1291,6 +1362,7 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "mynativelib", prefer: false, + visibility: ["//visibility:public"], device_supported: false, host_supported: true, sdk_version: "minimum", @@ -1317,6 +1389,7 @@ cc_prebuilt_library_shared { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, native_shared_libs: ["mysdk_mynativelib@current"], @@ -1381,6 +1454,7 @@ func TestMultipleHostOsTypesSnapshotWithCcSharedLibrary(t *testing.T) { cc_prebuilt_library_shared { name: "mysdk_mynativelib@current", sdk_member_name: "mynativelib", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, installable: false, @@ -1412,6 +1486,7 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "mynativelib", prefer: false, + visibility: ["//visibility:public"], device_supported: false, host_supported: true, stl: "none", @@ -1441,6 +1516,7 @@ cc_prebuilt_library_shared { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, native_shared_libs: ["mysdk_mynativelib@current"], @@ -1494,6 +1570,7 @@ func TestSnapshotWithCcStaticLibrary(t *testing.T) { cc_prebuilt_library_static { name: "myexports_mynativelib@current", sdk_member_name: "mynativelib", + visibility: ["//visibility:public"], installable: false, stl: "none", compile_multilib: "both", @@ -1513,6 +1590,7 @@ cc_prebuilt_library_static { cc_prebuilt_library_static { name: "mynativelib", prefer: false, + visibility: ["//visibility:public"], stl: "none", compile_multilib: "both", export_include_dirs: ["include/include"], @@ -1530,6 +1608,7 @@ cc_prebuilt_library_static { module_exports_snapshot { name: "myexports@current", + visibility: ["//visibility:public"], native_static_libs: ["myexports_mynativelib@current"], } `), @@ -1579,6 +1658,7 @@ func TestHostSnapshotWithCcStaticLibrary(t *testing.T) { cc_prebuilt_library_static { name: "myexports_mynativelib@current", sdk_member_name: "mynativelib", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, installable: false, @@ -1606,6 +1686,7 @@ cc_prebuilt_library_static { cc_prebuilt_library_static { name: "mynativelib", prefer: false, + visibility: ["//visibility:public"], device_supported: false, host_supported: true, stl: "none", @@ -1631,6 +1712,7 @@ cc_prebuilt_library_static { module_exports_snapshot { name: "myexports@current", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, native_static_libs: ["myexports_mynativelib@current"], @@ -1684,6 +1766,7 @@ func TestSnapshotWithCcLibrary(t *testing.T) { cc_prebuilt_library { name: "myexports_mynativelib@current", sdk_member_name: "mynativelib", + visibility: ["//visibility:public"], installable: false, recovery_available: true, vendor_available: true, @@ -1713,6 +1796,7 @@ cc_prebuilt_library { cc_prebuilt_library { name: "mynativelib", prefer: false, + visibility: ["//visibility:public"], recovery_available: true, vendor_available: true, stl: "none", @@ -1740,6 +1824,7 @@ cc_prebuilt_library { module_exports_snapshot { name: "myexports@current", + visibility: ["//visibility:public"], native_libs: ["myexports_mynativelib@current"], } `), @@ -1789,6 +1874,7 @@ func TestHostSnapshotWithMultiLib64(t *testing.T) { cc_prebuilt_library_static { name: "myexports_mynativelib@current", sdk_member_name: "mynativelib", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, installable: false, @@ -1812,6 +1898,7 @@ cc_prebuilt_library_static { cc_prebuilt_library_static { name: "mynativelib", prefer: false, + visibility: ["//visibility:public"], device_supported: false, host_supported: true, stl: "none", @@ -1833,6 +1920,7 @@ cc_prebuilt_library_static { module_exports_snapshot { name: "myexports@current", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, native_static_libs: ["myexports_mynativelib@current"], @@ -1877,6 +1965,7 @@ func TestSnapshotWithCcHeadersLibrary(t *testing.T) { cc_prebuilt_library_headers { name: "mysdk_mynativeheaders@current", sdk_member_name: "mynativeheaders", + visibility: ["//visibility:public"], stl: "none", compile_multilib: "both", export_include_dirs: ["include/include"], @@ -1885,6 +1974,7 @@ cc_prebuilt_library_headers { cc_prebuilt_library_headers { name: "mynativeheaders", prefer: false, + visibility: ["//visibility:public"], stl: "none", compile_multilib: "both", export_include_dirs: ["include/include"], @@ -1892,6 +1982,7 @@ cc_prebuilt_library_headers { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], native_header_libs: ["mysdk_mynativeheaders@current"], } `), @@ -1926,6 +2017,7 @@ func TestHostSnapshotWithCcHeadersLibrary(t *testing.T) { cc_prebuilt_library_headers { name: "mysdk_mynativeheaders@current", sdk_member_name: "mynativeheaders", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, stl: "none", @@ -1944,6 +2036,7 @@ cc_prebuilt_library_headers { cc_prebuilt_library_headers { name: "mynativeheaders", prefer: false, + visibility: ["//visibility:public"], device_supported: false, host_supported: true, stl: "none", @@ -1961,6 +2054,7 @@ cc_prebuilt_library_headers { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, native_header_libs: ["mysdk_mynativeheaders@current"], @@ -2011,6 +2105,7 @@ func TestDeviceAndHostSnapshotWithCcHeadersLibrary(t *testing.T) { cc_prebuilt_library_headers { name: "mysdk_mynativeheaders@current", sdk_member_name: "mynativeheaders", + visibility: ["//visibility:public"], host_supported: true, stl: "none", compile_multilib: "both", @@ -2032,6 +2127,7 @@ cc_prebuilt_library_headers { cc_prebuilt_library_headers { name: "mynativeheaders", prefer: false, + visibility: ["//visibility:public"], host_supported: true, stl: "none", compile_multilib: "both", @@ -2052,6 +2148,7 @@ cc_prebuilt_library_headers { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], host_supported: true, native_header_libs: ["mysdk_mynativeheaders@current"], target: { @@ -2102,6 +2199,7 @@ func TestSystemSharedLibPropagation(t *testing.T) { cc_prebuilt_library_shared { name: "mysdk_sslnil@current", sdk_member_name: "sslnil", + visibility: ["//visibility:public"], installable: false, compile_multilib: "both", arch: { @@ -2117,6 +2215,7 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "sslnil", prefer: false, + visibility: ["//visibility:public"], compile_multilib: "both", arch: { arm64: { @@ -2131,6 +2230,7 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "mysdk_sslempty@current", sdk_member_name: "sslempty", + visibility: ["//visibility:public"], installable: false, compile_multilib: "both", system_shared_libs: [], @@ -2147,6 +2247,7 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "sslempty", prefer: false, + visibility: ["//visibility:public"], compile_multilib: "both", system_shared_libs: [], arch: { @@ -2162,6 +2263,7 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "mysdk_sslnonempty@current", sdk_member_name: "sslnonempty", + visibility: ["//visibility:public"], installable: false, compile_multilib: "both", system_shared_libs: ["mysdk_sslnil@current"], @@ -2178,6 +2280,7 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "sslnonempty", prefer: false, + visibility: ["//visibility:public"], compile_multilib: "both", system_shared_libs: ["sslnil"], arch: { @@ -2192,6 +2295,7 @@ cc_prebuilt_library_shared { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], native_shared_libs: [ "mysdk_sslnil@current", "mysdk_sslempty@current", @@ -2225,6 +2329,7 @@ sdk_snapshot { cc_prebuilt_library_shared { name: "mysdk_sslvariants@current", sdk_member_name: "sslvariants", + visibility: ["//visibility:public"], host_supported: true, installable: false, compile_multilib: "both", @@ -2256,6 +2361,7 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "sslvariants", prefer: false, + visibility: ["//visibility:public"], host_supported: true, compile_multilib: "both", target: { @@ -2285,6 +2391,7 @@ cc_prebuilt_library_shared { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], host_supported: true, native_shared_libs: ["mysdk_sslvariants@current"], target: { @@ -2327,10 +2434,15 @@ func TestStubsLibrary(t *testing.T) { cc_prebuilt_library_shared { name: "mysdk_stubslib@current", sdk_member_name: "stubslib", + visibility: ["//visibility:public"], installable: false, compile_multilib: "both", stubs: { - versions: ["3"], + versions: [ + "1", + "2", + "3", + ], }, arch: { arm64: { @@ -2345,9 +2457,14 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "stubslib", prefer: false, + visibility: ["//visibility:public"], compile_multilib: "both", stubs: { - versions: ["3"], + versions: [ + "1", + "2", + "3", + ], }, arch: { arm64: { @@ -2361,6 +2478,7 @@ cc_prebuilt_library_shared { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], native_shared_libs: ["mysdk_stubslib@current"], } `)) @@ -2397,11 +2515,16 @@ func TestDeviceAndHostSnapshotWithStubsLibrary(t *testing.T) { cc_prebuilt_library_shared { name: "mysdk_stubslib@current", sdk_member_name: "stubslib", + visibility: ["//visibility:public"], host_supported: true, installable: false, compile_multilib: "both", stubs: { - versions: ["3"], + versions: [ + "1", + "2", + "3", + ], }, target: { host: { @@ -2428,10 +2551,15 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "stubslib", prefer: false, + visibility: ["//visibility:public"], host_supported: true, compile_multilib: "both", stubs: { - versions: ["3"], + versions: [ + "1", + "2", + "3", + ], }, target: { host: { @@ -2457,6 +2585,7 @@ cc_prebuilt_library_shared { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], host_supported: true, native_shared_libs: ["mysdk_stubslib@current"], target: { @@ -2493,6 +2622,7 @@ func TestUniqueHostSoname(t *testing.T) { cc_prebuilt_library_shared { name: "mysdk_mylib@current", sdk_member_name: "mylib", + visibility: ["//visibility:public"], host_supported: true, installable: false, unique_host_soname: true, @@ -2522,6 +2652,7 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "mylib", prefer: false, + visibility: ["//visibility:public"], host_supported: true, unique_host_soname: true, compile_multilib: "both", @@ -2549,6 +2680,7 @@ cc_prebuilt_library_shared { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], host_supported: true, native_shared_libs: ["mysdk_mylib@current"], target: { diff --git a/sdk/exports_test.go b/sdk/exports_test.go index 20e25212c..aa1200fed 100644 --- a/sdk/exports_test.go +++ b/sdk/exports_test.go @@ -49,17 +49,20 @@ func TestModuleExportsSnapshot(t *testing.T) { java_import { name: "myexports_myjavalib@current", sdk_member_name: "myjavalib", + visibility: ["//visibility:public"], jars: ["java/myjavalib.jar"], } java_import { name: "myjavalib", prefer: false, + visibility: ["//visibility:public"], jars: ["java/myjavalib.jar"], } module_exports_snapshot { name: "myexports@current", + visibility: ["//visibility:public"], java_libs: ["myexports_myjavalib@current"], } `)) diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go index a7ee8d12f..d6828c95b 100644 --- a/sdk/java_sdk_test.go +++ b/sdk/java_sdk_test.go @@ -43,6 +43,7 @@ func testSdkWithJava(t *testing.T, bp string) *testSdkResult { "api/system-server-current.txt": nil, "api/system-server-removed.txt": nil, "build/soong/scripts/gen-java-current-api-files.sh": nil, + "docs/known_doctags": nil, } // for java_sdk_library tests @@ -120,17 +121,20 @@ func TestSdkDependsOnSourceEvenWhenPrebuiltPreferred(t *testing.T) { java_import { name: "mysdk_sdkmember@current", sdk_member_name: "sdkmember", + visibility: ["//visibility:public"], jars: ["java/sdkmember.jar"], } java_import { name: "sdkmember", prefer: false, + visibility: ["//visibility:public"], jars: ["java/sdkmember.jar"], } sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], java_header_libs: ["mysdk_sdkmember@current"], } `)) @@ -242,17 +246,20 @@ func TestSnapshotWithJavaHeaderLibrary(t *testing.T) { java_import { name: "mysdk_myjavalib@current", sdk_member_name: "myjavalib", + visibility: ["//visibility:public"], jars: ["java/myjavalib.jar"], } java_import { name: "myjavalib", prefer: false, + visibility: ["//visibility:public"], jars: ["java/myjavalib.jar"], } sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], java_header_libs: ["mysdk_myjavalib@current"], } @@ -294,6 +301,7 @@ func TestHostSnapshotWithJavaHeaderLibrary(t *testing.T) { java_import { name: "mysdk_myjavalib@current", sdk_member_name: "myjavalib", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, jars: ["java/myjavalib.jar"], @@ -302,6 +310,7 @@ java_import { java_import { name: "myjavalib", prefer: false, + visibility: ["//visibility:public"], device_supported: false, host_supported: true, jars: ["java/myjavalib.jar"], @@ -309,6 +318,7 @@ java_import { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, java_header_libs: ["mysdk_myjavalib@current"], @@ -346,6 +356,7 @@ func TestDeviceAndHostSnapshotWithJavaHeaderLibrary(t *testing.T) { java_import { name: "mysdk_myjavalib@current", sdk_member_name: "myjavalib", + visibility: ["//visibility:public"], host_supported: true, target: { android: { @@ -360,6 +371,7 @@ java_import { java_import { name: "myjavalib", prefer: false, + visibility: ["//visibility:public"], host_supported: true, target: { android: { @@ -373,6 +385,7 @@ java_import { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], host_supported: true, java_header_libs: ["mysdk_myjavalib@current"], } @@ -412,17 +425,20 @@ func TestSnapshotWithJavaImplLibrary(t *testing.T) { java_import { name: "myexports_myjavalib@current", sdk_member_name: "myjavalib", + visibility: ["//visibility:public"], jars: ["java/myjavalib.jar"], } java_import { name: "myjavalib", prefer: false, + visibility: ["//visibility:public"], jars: ["java/myjavalib.jar"], } module_exports_snapshot { name: "myexports@current", + visibility: ["//visibility:public"], java_libs: ["myexports_myjavalib@current"], } @@ -464,6 +480,7 @@ func TestHostSnapshotWithJavaImplLibrary(t *testing.T) { java_import { name: "myexports_myjavalib@current", sdk_member_name: "myjavalib", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, jars: ["java/myjavalib.jar"], @@ -472,6 +489,7 @@ java_import { java_import { name: "myjavalib", prefer: false, + visibility: ["//visibility:public"], device_supported: false, host_supported: true, jars: ["java/myjavalib.jar"], @@ -479,6 +497,7 @@ java_import { module_exports_snapshot { name: "myexports@current", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, java_libs: ["myexports_myjavalib@current"], @@ -515,6 +534,7 @@ func TestSnapshotWithJavaTest(t *testing.T) { java_test_import { name: "myexports_myjavatests@current", sdk_member_name: "myjavatests", + visibility: ["//visibility:public"], jars: ["java/myjavatests.jar"], test_config: "java/myjavatests-AndroidTest.xml", } @@ -522,12 +542,14 @@ java_test_import { java_test_import { name: "myjavatests", prefer: false, + visibility: ["//visibility:public"], jars: ["java/myjavatests.jar"], test_config: "java/myjavatests-AndroidTest.xml", } module_exports_snapshot { name: "myexports@current", + visibility: ["//visibility:public"], java_tests: ["myexports_myjavatests@current"], } `), @@ -565,6 +587,7 @@ func TestHostSnapshotWithJavaTest(t *testing.T) { java_test_import { name: "myexports_myjavatests@current", sdk_member_name: "myjavatests", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, jars: ["java/myjavatests.jar"], @@ -574,6 +597,7 @@ java_test_import { java_test_import { name: "myjavatests", prefer: false, + visibility: ["//visibility:public"], device_supported: false, host_supported: true, jars: ["java/myjavatests.jar"], @@ -582,6 +606,7 @@ java_test_import { module_exports_snapshot { name: "myexports@current", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, java_tests: ["myexports_myjavatests@current"], @@ -659,17 +684,20 @@ func TestSnapshotWithDroidstubs(t *testing.T) { prebuilt_stubs_sources { name: "myexports_myjavaapistubs@current", sdk_member_name: "myjavaapistubs", + visibility: ["//visibility:public"], srcs: ["java/myjavaapistubs_stubs_sources"], } prebuilt_stubs_sources { name: "myjavaapistubs", prefer: false, + visibility: ["//visibility:public"], srcs: ["java/myjavaapistubs_stubs_sources"], } module_exports_snapshot { name: "myexports@current", + visibility: ["//visibility:public"], stubs_sources: ["myexports_myjavaapistubs@current"], } @@ -705,6 +733,7 @@ func TestHostSnapshotWithDroidstubs(t *testing.T) { prebuilt_stubs_sources { name: "myexports_myjavaapistubs@current", sdk_member_name: "myjavaapistubs", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, srcs: ["java/myjavaapistubs_stubs_sources"], @@ -713,6 +742,7 @@ prebuilt_stubs_sources { prebuilt_stubs_sources { name: "myjavaapistubs", prefer: false, + visibility: ["//visibility:public"], device_supported: false, host_supported: true, srcs: ["java/myjavaapistubs_stubs_sources"], @@ -720,6 +750,7 @@ prebuilt_stubs_sources { module_exports_snapshot { name: "myexports@current", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, stubs_sources: ["myexports_myjavaapistubs@current"], @@ -765,12 +796,14 @@ func TestSnapshotWithJavaSystemModules(t *testing.T) { java_import { name: "mysdk_exported-system-module@current", sdk_member_name: "exported-system-module", + visibility: ["//visibility:public"], jars: ["java/exported-system-module.jar"], } java_import { name: "exported-system-module", prefer: false, + visibility: ["//visibility:public"], jars: ["java/exported-system-module.jar"], } @@ -791,6 +824,7 @@ java_import { java_system_modules_import { name: "mysdk_my-system-modules@current", sdk_member_name: "my-system-modules", + visibility: ["//visibility:public"], libs: [ "mysdk_system-module@current", "mysdk_exported-system-module@current", @@ -800,6 +834,7 @@ java_system_modules_import { java_system_modules_import { name: "my-system-modules", prefer: false, + visibility: ["//visibility:public"], libs: [ "mysdk_system-module", "exported-system-module", @@ -808,6 +843,7 @@ java_system_modules_import { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], java_header_libs: ["mysdk_exported-system-module@current"], java_system_modules: ["mysdk_my-system-modules@current"], } @@ -870,6 +906,7 @@ java_import { java_system_modules_import { name: "mysdk_my-system-modules@current", sdk_member_name: "my-system-modules", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, libs: ["mysdk_system-module@current"], @@ -878,6 +915,7 @@ java_system_modules_import { java_system_modules_import { name: "my-system-modules", prefer: false, + visibility: ["//visibility:public"], device_supported: false, host_supported: true, libs: ["mysdk_system-module"], @@ -885,6 +923,7 @@ java_system_modules_import { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, java_system_modules: ["mysdk_my-system-modules@current"], @@ -938,6 +977,7 @@ func TestDeviceAndHostSnapshotWithOsSpecificMembers(t *testing.T) { java_import { name: "myexports_hostjavalib@current", sdk_member_name: "hostjavalib", + visibility: ["//visibility:public"], device_supported: false, host_supported: true, jars: ["java/hostjavalib.jar"], @@ -946,6 +986,7 @@ java_import { java_import { name: "hostjavalib", prefer: false, + visibility: ["//visibility:public"], device_supported: false, host_supported: true, jars: ["java/hostjavalib.jar"], @@ -954,18 +995,21 @@ java_import { java_import { name: "myexports_androidjavalib@current", sdk_member_name: "androidjavalib", + visibility: ["//visibility:public"], jars: ["java/androidjavalib.jar"], } java_import { name: "androidjavalib", prefer: false, + visibility: ["//visibility:public"], jars: ["java/androidjavalib.jar"], } java_import { name: "myexports_myjavalib@current", sdk_member_name: "myjavalib", + visibility: ["//visibility:public"], host_supported: true, target: { android: { @@ -980,6 +1024,7 @@ java_import { java_import { name: "myjavalib", prefer: false, + visibility: ["//visibility:public"], host_supported: true, target: { android: { @@ -993,6 +1038,7 @@ java_import { module_exports_snapshot { name: "myexports@current", + visibility: ["//visibility:public"], host_supported: true, java_libs: ["myexports_myjavalib@current"], target: { @@ -1039,6 +1085,7 @@ func TestSnapshotWithJavaSdkLibrary(t *testing.T) { java_sdk_library_import { name: "mysdk_myjavalib@current", sdk_member_name: "myjavalib", + visibility: ["//visibility:public"], apex_available: ["//apex_available:anyapex"], shared_library: false, public: { @@ -1067,6 +1114,7 @@ java_sdk_library_import { java_sdk_library_import { name: "myjavalib", prefer: false, + visibility: ["//visibility:public"], apex_available: ["//apex_available:anyapex"], shared_library: false, public: { @@ -1094,6 +1142,7 @@ java_sdk_library_import { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], java_sdk_libs: ["mysdk_myjavalib@current"], } `), @@ -1137,6 +1186,7 @@ func TestSnapshotWithJavaSdkLibrary_SdkVersion_None(t *testing.T) { java_sdk_library_import { name: "mysdk_myjavalib@current", sdk_member_name: "myjavalib", + visibility: ["//visibility:public"], shared_library: true, public: { jars: ["sdk_library/public/myjavalib-stubs.jar"], @@ -1150,6 +1200,7 @@ java_sdk_library_import { java_sdk_library_import { name: "myjavalib", prefer: false, + visibility: ["//visibility:public"], shared_library: true, public: { jars: ["sdk_library/public/myjavalib-stubs.jar"], @@ -1162,6 +1213,7 @@ java_sdk_library_import { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], java_sdk_libs: ["mysdk_myjavalib@current"], } `), @@ -1201,6 +1253,7 @@ func TestSnapshotWithJavaSdkLibrary_SdkVersion_ForScope(t *testing.T) { java_sdk_library_import { name: "mysdk_myjavalib@current", sdk_member_name: "myjavalib", + visibility: ["//visibility:public"], shared_library: true, public: { jars: ["sdk_library/public/myjavalib-stubs.jar"], @@ -1214,6 +1267,7 @@ java_sdk_library_import { java_sdk_library_import { name: "myjavalib", prefer: false, + visibility: ["//visibility:public"], shared_library: true, public: { jars: ["sdk_library/public/myjavalib-stubs.jar"], @@ -1226,6 +1280,7 @@ java_sdk_library_import { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], java_sdk_libs: ["mysdk_myjavalib@current"], } `), @@ -1268,6 +1323,7 @@ func TestSnapshotWithJavaSdkLibrary_ApiScopes(t *testing.T) { java_sdk_library_import { name: "mysdk_myjavalib@current", sdk_member_name: "myjavalib", + visibility: ["//visibility:public"], apex_available: ["//apex_available:anyapex"], shared_library: true, public: { @@ -1289,6 +1345,7 @@ java_sdk_library_import { java_sdk_library_import { name: "myjavalib", prefer: false, + visibility: ["//visibility:public"], apex_available: ["//apex_available:anyapex"], shared_library: true, public: { @@ -1309,6 +1366,7 @@ java_sdk_library_import { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], java_sdk_libs: ["mysdk_myjavalib@current"], } `), @@ -1358,6 +1416,7 @@ func TestSnapshotWithJavaSdkLibrary_ModuleLib(t *testing.T) { java_sdk_library_import { name: "mysdk_myjavalib@current", sdk_member_name: "myjavalib", + visibility: ["//visibility:public"], apex_available: ["//apex_available:anyapex"], shared_library: true, public: { @@ -1386,6 +1445,7 @@ java_sdk_library_import { java_sdk_library_import { name: "myjavalib", prefer: false, + visibility: ["//visibility:public"], apex_available: ["//apex_available:anyapex"], shared_library: true, public: { @@ -1413,6 +1473,7 @@ java_sdk_library_import { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], java_sdk_libs: ["mysdk_myjavalib@current"], } `), @@ -1463,6 +1524,7 @@ func TestSnapshotWithJavaSdkLibrary_SystemServer(t *testing.T) { java_sdk_library_import { name: "mysdk_myjavalib@current", sdk_member_name: "myjavalib", + visibility: ["//visibility:public"], apex_available: ["//apex_available:anyapex"], shared_library: true, public: { @@ -1484,6 +1546,7 @@ java_sdk_library_import { java_sdk_library_import { name: "myjavalib", prefer: false, + visibility: ["//visibility:public"], apex_available: ["//apex_available:anyapex"], shared_library: true, public: { @@ -1504,6 +1567,7 @@ java_sdk_library_import { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], java_sdk_libs: ["mysdk_myjavalib@current"], } `), @@ -1548,6 +1612,7 @@ func TestSnapshotWithJavaSdkLibrary_NamingScheme(t *testing.T) { java_sdk_library_import { name: "mysdk_myjavalib@current", sdk_member_name: "myjavalib", + visibility: ["//visibility:public"], apex_available: ["//apex_available:anyapex"], naming_scheme: "default", shared_library: true, @@ -1563,6 +1628,7 @@ java_sdk_library_import { java_sdk_library_import { name: "myjavalib", prefer: false, + visibility: ["//visibility:public"], apex_available: ["//apex_available:anyapex"], naming_scheme: "default", shared_library: true, @@ -1577,6 +1643,7 @@ java_sdk_library_import { sdk_snapshot { name: "mysdk@current", + visibility: ["//visibility:public"], java_sdk_libs: ["mysdk_myjavalib@current"], } `), @@ -1590,3 +1657,75 @@ sdk_snapshot { ), ) } + +func TestSnapshotWithJavaSdkLibrary_DoctagFiles(t *testing.T) { + result := testSdkWithJava(t, ` + sdk { + name: "mysdk", + java_sdk_libs: ["myjavalib"], + } + + java_sdk_library { + name: "myjavalib", + srcs: ["Test.java"], + sdk_version: "current", + public: { + enabled: true, + }, + doctag_files: ["docs/known_doctags"], + } + + filegroup { + name: "mygroup", + srcs: [":myjavalib{.doctags}"], + } + `) + + result.CheckSnapshot("mysdk", "", + checkAndroidBpContents(` +// This is auto-generated. DO NOT EDIT. + +java_sdk_library_import { + name: "mysdk_myjavalib@current", + sdk_member_name: "myjavalib", + visibility: ["//visibility:public"], + shared_library: true, + doctag_files: ["doctags/docs/known_doctags"], + public: { + jars: ["sdk_library/public/myjavalib-stubs.jar"], + stub_srcs: ["sdk_library/public/myjavalib_stub_sources"], + current_api: "sdk_library/public/myjavalib.txt", + removed_api: "sdk_library/public/myjavalib-removed.txt", + sdk_version: "current", + }, +} + +java_sdk_library_import { + name: "myjavalib", + prefer: false, + visibility: ["//visibility:public"], + shared_library: true, + doctag_files: ["doctags/docs/known_doctags"], + public: { + jars: ["sdk_library/public/myjavalib-stubs.jar"], + stub_srcs: ["sdk_library/public/myjavalib_stub_sources"], + current_api: "sdk_library/public/myjavalib.txt", + removed_api: "sdk_library/public/myjavalib-removed.txt", + sdk_version: "current", + }, +} + +sdk_snapshot { + name: "mysdk@current", + visibility: ["//visibility:public"], + java_sdk_libs: ["mysdk_myjavalib@current"], +} +`), + checkAllCopyRules(` +.intermediates/myjavalib.stubs/android_common/javac/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar +.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt +.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt +docs/known_doctags -> doctags/docs/known_doctags +`), + ) +} diff --git a/sdk/sdk.go b/sdk/sdk.go index 759102028..50b0886d4 100644 --- a/sdk/sdk.go +++ b/sdk/sdk.go @@ -75,6 +75,20 @@ type sdkProperties struct { // True if this is a module_exports (or module_exports_snapshot) module type. Module_exports bool `blueprint:"mutated"` + + // The additional visibility to add to the prebuilt modules to allow them to + // reference each other. + // + // This can only be used to widen the visibility of the members: + // + // * Specifying //visibility:public here will make all members visible and + // essentially ignore their own visibility. + // * Specifying //visibility:private here is an error. + // * Specifying any other rule here will add it to the members visibility and + // be output to the member prebuilt in the snapshot. Duplicates will be + // dropped. Adding a rule to members that have //visibility:private will + // cause the //visibility:private to be discarded. + Prebuilt_visibility []string } // Contains information about the sdk properties that list sdk members, e.g. @@ -211,6 +225,9 @@ func newSdkModule(moduleExports bool) *sdk { // properties for the member type specific list properties. s.dynamicMemberTypeListProperties = s.dynamicSdkMemberTypes.createMemberListProperties() s.AddProperties(&s.properties, s.dynamicMemberTypeListProperties) + + // Make sure that the prebuilt visibility property is verified for errors. + android.AddVisibilityProperty(s, "prebuilt_visibility", &s.properties.Prebuilt_visibility) android.InitCommonOSAndroidMultiTargetsArchModule(s, android.HostAndDeviceSupported, android.MultilibCommon) android.InitDefaultableModule(s) android.AddLoadHook(s, func(ctx android.LoadHookContext) { diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go index ef62b79ba..2e6c62a9b 100644 --- a/sdk/sdk_test.go +++ b/sdk/sdk_test.go @@ -108,6 +108,9 @@ func TestSnapshotVisibility(t *testing.T) { // generated sdk_snapshot. ":__subpackages__", ], + prebuilt_visibility: [ + "//prebuilts/mysdk", + ], java_header_libs: [ "myjavalib", "mypublicjavalib", @@ -176,6 +179,7 @@ java_import { visibility: [ "//other/foo", "//package", + "//prebuilts/mysdk", ], jars: ["java/myjavalib.jar"], } @@ -186,6 +190,7 @@ java_import { visibility: [ "//other/foo", "//package", + "//prebuilts/mysdk", ], jars: ["java/myjavalib.jar"], } @@ -210,6 +215,7 @@ java_import { visibility: [ "//other/bar", "//package", + "//prebuilts/mysdk", ], jars: ["java/mydefaultedjavalib.jar"], } @@ -220,6 +226,7 @@ java_import { visibility: [ "//other/bar", "//package", + "//prebuilts/mysdk", ], jars: ["java/mydefaultedjavalib.jar"], } @@ -227,14 +234,20 @@ java_import { java_import { name: "mysdk_myprivatejavalib@current", sdk_member_name: "myprivatejavalib", - visibility: ["//package"], + visibility: [ + "//package", + "//prebuilts/mysdk", + ], jars: ["java/myprivatejavalib.jar"], } java_import { name: "myprivatejavalib", prefer: false, - visibility: ["//package"], + visibility: [ + "//package", + "//prebuilts/mysdk", + ], jars: ["java/myprivatejavalib.jar"], } @@ -254,6 +267,40 @@ sdk_snapshot { `)) } +func TestPrebuiltVisibilityProperty_IsValidated(t *testing.T) { + testSdkError(t, `prebuilt_visibility: cannot mix "//visibility:private" with any other visibility rules`, ` + sdk { + name: "mysdk", + prebuilt_visibility: [ + "//foo", + "//visibility:private", + ], + } +`) +} + +func TestPrebuiltVisibilityProperty_AddPrivate(t *testing.T) { + testSdkError(t, `prebuilt_visibility: "//visibility:private" does not widen the visibility`, ` + sdk { + name: "mysdk", + prebuilt_visibility: [ + "//visibility:private", + ], + java_header_libs: [ + "myjavalib", + ], + } + + java_library { + name: "myjavalib", + // Uses package default visibility + srcs: ["Test.java"], + system_modules: "none", + sdk_version: "none", + } +`) +} + func TestSDkInstall(t *testing.T) { sdk := ` sdk { diff --git a/sdk/testing.go b/sdk/testing.go index b53558d9f..0b280efa3 100644 --- a/sdk/testing.go +++ b/sdk/testing.go @@ -68,14 +68,14 @@ func testSdkContext(bp string, fs map[string][]byte, extraOsTypes []android.OsTy // Add windows as a default disable OS to test behavior when some OS variants // are disabled. config.Targets[android.Windows] = []android.Target{ - {android.Windows, android.Arch{ArchType: android.X86_64}, android.NativeBridgeDisabled, "", ""}, + {android.Windows, android.Arch{ArchType: android.X86_64}, android.NativeBridgeDisabled, "", "", true}, } for _, extraOsType := range extraOsTypes { switch extraOsType { case android.LinuxBionic: config.Targets[android.LinuxBionic] = []android.Target{ - {android.LinuxBionic, android.Arch{ArchType: android.X86_64}, android.NativeBridgeDisabled, "", ""}, + {android.LinuxBionic, android.Arch{ArchType: android.X86_64}, android.NativeBridgeDisabled, "", "", false}, } } } @@ -89,11 +89,12 @@ func testSdkContext(bp string, fs map[string][]byte, extraOsTypes []android.OsTy android.RegisterAndroidMkBuildComponents(ctx) android.SetInMakeForTests(config) config.Targets[android.CommonOS] = []android.Target{ - {android.CommonOS, android.Arch{ArchType: android.Common}, android.NativeBridgeDisabled, "", ""}, + {android.CommonOS, android.Arch{ArchType: android.Common}, android.NativeBridgeDisabled, "", "", true}, } // from android package android.RegisterPackageBuildComponents(ctx) + ctx.RegisterModuleType("filegroup", android.FileGroupFactory) ctx.PreArchMutators(android.RegisterVisibilityRuleChecker) ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators) ctx.PreArchMutators(android.RegisterComponentsMutator) @@ -217,6 +218,22 @@ func (h *TestHelper) AssertDeepEquals(message string, expected interface{}, actu } } +func (h *TestHelper) AssertPanic(message string, funcThatShouldPanic func()) { + h.t.Helper() + panicked := false + func() { + defer func() { + if x := recover(); x != nil { + panicked = true + } + }() + funcThatShouldPanic() + }() + if !panicked { + h.t.Error(message) + } +} + // Encapsulates result of processing an SDK definition. Provides support for // checking the state of the build structures. type testSdkResult struct { diff --git a/sdk/update.go b/sdk/update.go index 537ab13cb..f29b5a00c 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -300,7 +300,7 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) andro snapshotModule.AddProperty("name", snapshotName) // Make sure that the snapshot has the same visibility as the sdk. - visibility := android.EffectiveVisibilityRules(ctx, s) + visibility := android.EffectiveVisibilityRules(ctx, s).Strings() if len(visibility) != 0 { snapshotModule.AddProperty("visibility", visibility) } @@ -371,8 +371,7 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) andro osPropertySet := targetPropertySet.AddPropertySet(sdkVariant.Target().Os.Name) // Enable the variant explicitly when we've disabled it by default on host. - if hasHostOsDependentMember && - (osType.Class == android.Host || osType.Class == android.HostCross) { + if hasHostOsDependentMember && osType.Class == android.Host { osPropertySet.AddProperty("enabled", true) } @@ -720,7 +719,15 @@ func (s *snapshotBuilder) AddPrebuiltModule(member android.SdkMember, moduleType } else { // Extract visibility information from a member variant. All variants have the same // visibility so it doesn't matter which one is used. - visibility := android.EffectiveVisibilityRules(s.ctx, variant) + visibilityRules := android.EffectiveVisibilityRules(s.ctx, variant) + + // Add any additional visibility rules needed for the prebuilts to reference each other. + err := visibilityRules.Widen(s.sdk.properties.Prebuilt_visibility) + if err != nil { + s.ctx.PropertyErrorf("prebuilt_visibility", "%s", err) + } + + visibility := visibilityRules.Strings() if len(visibility) != 0 { m.AddProperty("visibility", visibility) } @@ -731,7 +738,7 @@ func (s *snapshotBuilder) AddPrebuiltModule(member android.SdkMember, moduleType for _, variant := range member.Variants() { osClass := variant.Target().Os.Class - if osClass == android.Host || osClass == android.HostCross { + if osClass == android.Host { hostSupported = true } else if osClass == android.Device { deviceSupported = true @@ -1061,8 +1068,7 @@ func (osInfo *osTypeSpecificInfo) addToPropertySet(ctx *memberContext, bpModule archPropertySet = targetPropertySet // Enable the variant explicitly when we've disabled it by default on host. - if ctx.memberType.IsHostOsDependent() && - (osType.Class == android.Host || osType.Class == android.HostCross) { + if ctx.memberType.IsHostOsDependent() && osType.Class == android.Host { osPropertySet.AddProperty("enabled", true) } @@ -1086,7 +1092,7 @@ func (osInfo *osTypeSpecificInfo) addToPropertySet(ctx *memberContext, bpModule func (osInfo *osTypeSpecificInfo) isHostVariant() bool { osClass := osInfo.osType.Class - return osClass == android.Host || osClass == android.HostCross + return osClass == android.Host } var _ isHostVariant = (*osTypeSpecificInfo)(nil) @@ -1323,7 +1329,7 @@ func (s *sdk) getPossibleOsTypes() []android.OsType { } } if s.HostSupported() { - if osType.Class == android.Host || osType.Class == android.HostCross { + if osType.Class == android.Host { osTypes = append(osTypes, osType) } } @@ -1348,7 +1354,8 @@ type isHostVariant interface { // A property that can be optimized by the commonValueExtractor. type extractorProperty struct { - // The name of the field for this property. + // The name of the field for this property. It is a "."-separated path for + // fields in non-anonymous substructs. name string // Filter that can use metadata associated with the properties being optimized @@ -1385,18 +1392,18 @@ type commonValueExtractor struct { func newCommonValueExtractor(propertiesStruct interface{}) *commonValueExtractor { structType := getStructValue(reflect.ValueOf(propertiesStruct)).Type() extractor := &commonValueExtractor{} - extractor.gatherFields(structType, nil) + extractor.gatherFields(structType, nil, "") return extractor } // Gather the fields from the supplied structure type from which common values will // be extracted. // -// This is recursive function. If it encounters an embedded field (no field name) -// that is a struct then it will recurse into that struct passing in the accessor -// for the field. That will then be used in the accessors for the fields in the -// embedded struct. -func (e *commonValueExtractor) gatherFields(structType reflect.Type, containingStructAccessor fieldAccessorFunc) { +// This is recursive function. If it encounters a struct then it will recurse +// into it, passing in the accessor for the field and the struct name as prefix +// for the nested fields. That will then be used in the accessors for the fields +// in the embedded struct. +func (e *commonValueExtractor) gatherFields(structType reflect.Type, containingStructAccessor fieldAccessorFunc, namePrefix string) { for f := 0; f < structType.NumField(); f++ { field := structType.Field(f) if field.PkgPath != "" { @@ -1426,7 +1433,7 @@ func (e *commonValueExtractor) gatherFields(structType reflect.Type, containingS // Save a copy of the field index for use in the function. fieldIndex := f - name := field.Name + name := namePrefix + field.Name fieldGetter := func(value reflect.Value) reflect.Value { if containingStructAccessor != nil { @@ -1448,9 +1455,15 @@ func (e *commonValueExtractor) gatherFields(structType reflect.Type, containingS return value.Field(fieldIndex) } - if field.Type.Kind() == reflect.Struct && field.Anonymous { - // Gather fields from the embedded structure. - e.gatherFields(field.Type, fieldGetter) + if field.Type.Kind() == reflect.Struct { + // Gather fields from the nested or embedded structure. + var subNamePrefix string + if field.Anonymous { + subNamePrefix = namePrefix + } else { + subNamePrefix = name + "." + } + e.gatherFields(field.Type, fieldGetter, subNamePrefix) } else { property := extractorProperty{ name, @@ -1514,7 +1527,8 @@ func (c dynamicMemberPropertiesContainer) String() string { // Iterates over each exported field (capitalized name) and checks to see whether they // have the same value (using DeepEquals) across all the input properties. If it does not then no // change is made. Otherwise, the common value is stored in the field in the commonProperties -// and the field in each of the input properties structure is set to its default value. +// and the field in each of the input properties structure is set to its default value. Nested +// structs are visited recursively and their non-struct fields are compared. func (e *commonValueExtractor) extractCommonProperties(commonProperties interface{}, inputPropertiesSlice interface{}) error { commonPropertiesValue := reflect.ValueOf(commonProperties) commonStructValue := commonPropertiesValue.Elem() diff --git a/sh/sh_binary.go b/sh/sh_binary.go index f3f4a4aa7..7c3cdbdbb 100644 --- a/sh/sh_binary.go +++ b/sh/sh_binary.go @@ -313,6 +313,15 @@ func (s *ShTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { options := []tradefed.Option{{Name: "force-root", Value: "false"}} configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options}) } + if len(s.testProperties.Data_device_bins) > 0 { + moduleName := s.Name() + remoteDir := "/data/local/tests/unrestricted/" + moduleName + "/" + options := []tradefed.Option{{Name: "cleanup", Value: "true"}} + for _, bin := range s.testProperties.Data_device_bins { + options = append(options, tradefed.Option{Name: "push-file", Key: bin, Value: remoteDir + bin}) + } + configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.PushFilePreparer", options}) + } s.testConfig = tradefed.AutoGenShellTestConfig(ctx, s.testProperties.Test_config, s.testProperties.Test_config_template, s.testProperties.Test_suites, configs, s.testProperties.Auto_gen_config, s.outputFilePath.Base()) diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go index 768c8e5b0..480f9b797 100644 --- a/sysprop/sysprop_library.go +++ b/sysprop/sysprop_library.go @@ -310,7 +310,8 @@ func (m *syspropLibrary) AndroidMk() android.AndroidMkData { }} } -func (m *syspropLibrary) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +func (m *syspropLibrary) ShouldSupportSdkVersion(ctx android.BaseModuleContext, + sdkVersion android.ApiLevel) error { return fmt.Errorf("sysprop_library is not supposed to be part of apex modules") } diff --git a/ui/build/config.go b/ui/build/config.go index e9a8fc910..fe74ace39 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -24,6 +24,7 @@ import ( "time" "android/soong/shared" + "github.com/golang/protobuf/proto" smpb "android/soong/ui/metrics/metrics_proto" @@ -183,6 +184,17 @@ func NewConfig(ctx Context, args ...string) Config { "EMPTY_NINJA_FILE", ) + if ret.UseGoma() { + ctx.Println("Goma for Android is being deprecated and replaced with RBE. See go/rbe_for_android for instructions on how to use RBE.") + ctx.Println() + ctx.Println("See go/goma_android_exceptions for exceptions.") + ctx.Fatalln("USE_GOMA flag is no longer supported.") + } + + if ret.ForceUseGoma() { + ret.environ.Set("USE_GOMA", "true") + } + // Tell python not to spam the source tree with .pyc files. ret.environ.Set("PYTHONDONTWRITEBYTECODE", "1") @@ -286,8 +298,9 @@ func storeConfigMetrics(ctx Context, config Config) { } b := &smpb.BuildConfig{ - UseGoma: proto.Bool(config.UseGoma()), - UseRbe: proto.Bool(config.UseRBE()), + ForceUseGoma: proto.Bool(config.ForceUseGoma()), + UseGoma: proto.Bool(config.UseGoma()), + UseRbe: proto.Bool(config.UseRBE()), } ctx.Metrics.BuildConfig(b) } @@ -778,6 +791,18 @@ func (c *configImpl) TotalRAM() uint64 { return c.totalRAM } +// ForceUseGoma determines whether we should override Goma deprecation +// and use Goma for the current build or not. +func (c *configImpl) ForceUseGoma() bool { + if v, ok := c.environ.Get("FORCE_USE_GOMA"); ok { + v = strings.TrimSpace(v) + if v != "" && v != "false" { + return true + } + } + return false +} + func (c *configImpl) UseGoma() bool { if v, ok := c.environ.Get("USE_GOMA"); ok { v = strings.TrimSpace(v) @@ -827,6 +852,11 @@ func (c *configImpl) StartRBE() bool { } func (c *configImpl) logDir() string { + for _, f := range []string{"RBE_log_dir", "FLAG_log_dir"} { + if v, ok := c.environ.Get(f); ok { + return v + } + } if c.Dist() { return filepath.Join(c.DistDir(), "logs") } diff --git a/ui/build/rbe.go b/ui/build/rbe.go index c4b829d2e..182c544d7 100644 --- a/ui/build/rbe.go +++ b/ui/build/rbe.go @@ -151,13 +151,3 @@ func DumpRBEMetrics(ctx Context, config Config, filename string) { ctx.Fatalf("failed to copy %q to %q: %v\n", metricsFile, filename, err) } } - -// PrintGomaDeprecation prints a PSA on the deprecation of Goma if it is set for the build. -func PrintGomaDeprecation(ctx Context, config Config) { - if config.UseGoma() { - fmt.Fprintln(ctx.Writer, "") - fmt.Fprintln(ctx.Writer, "Goma for Android is being deprecated and replaced with RBE.") - fmt.Fprintln(ctx.Writer, "See go/goma_android_deprecation for more details.") - fmt.Fprintln(ctx.Writer, "") - } -} diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go index d7c53ec2b..05efe132d 100644 --- a/ui/metrics/metrics_proto/metrics.pb.go +++ b/ui/metrics/metrics_proto/metrics.pb.go @@ -399,6 +399,7 @@ func (m *MetricsBase) GetBuildConfig() *BuildConfig { type BuildConfig struct { UseGoma *bool `protobuf:"varint,1,opt,name=use_goma,json=useGoma" json:"use_goma,omitempty"` UseRbe *bool `protobuf:"varint,2,opt,name=use_rbe,json=useRbe" json:"use_rbe,omitempty"` + ForceUseGoma *bool `protobuf:"varint,3,opt,name=force_use_goma,json=forceUseGoma" json:"force_use_goma,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -443,6 +444,13 @@ func (m *BuildConfig) GetUseRbe() bool { return false } +func (m *BuildConfig) GetForceUseGoma() bool { + if m != nil && m.ForceUseGoma != nil { + return *m.ForceUseGoma + } + return false +} + type PerfInfo struct { // The description for the phase/action/part while the tool running. Desc *string `protobuf:"bytes,1,opt,name=desc" json:"desc,omitempty"` @@ -764,69 +772,70 @@ func init() { } var fileDescriptor_6039342a2ba47b72 = []byte{ - // 1021 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xef, 0x6e, 0xdb, 0x36, - 0x10, 0xaf, 0x12, 0x27, 0xb6, 0x4e, 0xb1, 0xab, 0x30, 0xed, 0xa2, 0xb6, 0x08, 0x66, 0x18, 0x6b, - 0x11, 0x0c, 0x6b, 0x5a, 0x64, 0x45, 0x50, 0x04, 0xc5, 0x00, 0xc7, 0x09, 0xb2, 0x2e, 0x48, 0x5c, - 0x30, 0x7f, 0x56, 0x6c, 0x1f, 0x04, 0x5a, 0xa2, 0x13, 0x75, 0x96, 0x28, 0x90, 0x54, 0x91, 0xf4, - 0x1d, 0xf6, 0x54, 0x7b, 0x96, 0xbd, 0xc6, 0x30, 0xf0, 0x28, 0xd9, 0xca, 0xe6, 0xad, 0x41, 0xbf, - 0x89, 0xf7, 0xfb, 0xc3, 0x3b, 0xf2, 0x78, 0x36, 0xb4, 0x53, 0xae, 0x65, 0x12, 0xa9, 0xad, 0x5c, - 0x0a, 0x2d, 0xc8, 0x9a, 0x12, 0x22, 0xbb, 0x0c, 0x47, 0x45, 0x32, 0x89, 0xc3, 0x12, 0xea, 0xfd, - 0x05, 0xe0, 0x1d, 0xdb, 0xef, 0x3d, 0xa6, 0x38, 0x79, 0x09, 0x0f, 0x2c, 0x21, 0x66, 0x9a, 0x87, - 0x3a, 0x49, 0xb9, 0xd2, 0x2c, 0xcd, 0x03, 0xa7, 0xeb, 0x6c, 0x2e, 0x52, 0x82, 0xd8, 0x3e, 0xd3, - 0xfc, 0xac, 0x42, 0xc8, 0x23, 0x68, 0x59, 0x45, 0x12, 0x07, 0x0b, 0x5d, 0x67, 0xd3, 0xa5, 0x4d, - 0x5c, 0xbf, 0x8d, 0xc9, 0x2e, 0x3c, 0xca, 0x27, 0x4c, 0x8f, 0x85, 0x4c, 0xc3, 0x8f, 0x5c, 0xaa, - 0x44, 0x64, 0x61, 0x24, 0x62, 0x9e, 0xb1, 0x94, 0x07, 0x8b, 0xc8, 0x5d, 0xaf, 0x08, 0x17, 0x16, - 0x1f, 0x94, 0x30, 0x79, 0x0a, 0x1d, 0xcd, 0xe4, 0x25, 0xd7, 0x61, 0x2e, 0x45, 0x5c, 0x44, 0x3a, - 0x68, 0xa0, 0xa0, 0x6d, 0xa3, 0xef, 0x6c, 0x90, 0xc4, 0xf0, 0xa0, 0xa4, 0xd9, 0x24, 0x3e, 0x32, - 0x99, 0xb0, 0x4c, 0x07, 0x4b, 0x5d, 0x67, 0xb3, 0xb3, 0xfd, 0x7c, 0x6b, 0x4e, 0xcd, 0x5b, 0xb5, - 0x7a, 0xb7, 0xf6, 0x0c, 0x72, 0x61, 0x45, 0xbb, 0x8b, 0x07, 0x27, 0x87, 0x94, 0x58, 0xbf, 0x3a, - 0x40, 0x86, 0xe0, 0x95, 0xbb, 0x30, 0x19, 0x5d, 0x05, 0xcb, 0x68, 0xfe, 0xf4, 0xb3, 0xe6, 0x7d, - 0x19, 0x5d, 0xed, 0x36, 0xcf, 0x4f, 0x8e, 0x4e, 0x86, 0x3f, 0x9f, 0x50, 0xb0, 0x16, 0x26, 0x48, - 0xb6, 0x60, 0xad, 0x66, 0x38, 0xcd, 0xba, 0x89, 0x25, 0xae, 0xce, 0x88, 0x55, 0x02, 0xdf, 0x41, - 0x99, 0x56, 0x18, 0xe5, 0xc5, 0x94, 0xde, 0x42, 0xba, 0x6f, 0x91, 0x41, 0x5e, 0x54, 0xec, 0x23, - 0x70, 0xaf, 0x84, 0x2a, 0x93, 0x75, 0xbf, 0x28, 0xd9, 0x96, 0x31, 0xc0, 0x54, 0x29, 0xb4, 0xd1, - 0x6c, 0x3b, 0x8b, 0xad, 0x21, 0x7c, 0x91, 0xa1, 0x67, 0x4c, 0xb6, 0xb3, 0x18, 0x3d, 0xd7, 0xa1, - 0x89, 0x9e, 0x42, 0x05, 0x1e, 0xd6, 0xb0, 0x6c, 0x96, 0x43, 0x45, 0x7a, 0xe5, 0x66, 0x42, 0x85, - 0xfc, 0x5a, 0x4b, 0x16, 0xac, 0x20, 0xec, 0x59, 0xf8, 0xc0, 0x84, 0xa6, 0x9c, 0x48, 0x0a, 0xa5, - 0x8c, 0x45, 0x7b, 0xc6, 0x19, 0x98, 0xd8, 0x50, 0x91, 0x67, 0x70, 0xbf, 0xc6, 0xc1, 0xb4, 0x3b, - 0xb6, 0x7d, 0xa6, 0x2c, 0x4c, 0xe4, 0x39, 0xac, 0xd5, 0x78, 0xd3, 0x12, 0xef, 0xdb, 0x83, 0x9d, - 0x72, 0x6b, 0x79, 0x8b, 0x42, 0x87, 0x71, 0x22, 0x03, 0xdf, 0xe6, 0x2d, 0x0a, 0xbd, 0x9f, 0x48, - 0xf2, 0x03, 0x78, 0x8a, 0xeb, 0x22, 0x0f, 0xb5, 0x10, 0x13, 0x15, 0xac, 0x76, 0x17, 0x37, 0xbd, - 0xed, 0x8d, 0xb9, 0x47, 0xf4, 0x8e, 0xcb, 0xf1, 0xdb, 0x6c, 0x2c, 0x28, 0xa0, 0xe2, 0xcc, 0x08, - 0xc8, 0x2e, 0xb8, 0xbf, 0x31, 0x9d, 0x84, 0xb2, 0xc8, 0x54, 0x40, 0xee, 0xa2, 0x6e, 0x19, 0x3e, - 0x2d, 0x32, 0x45, 0xde, 0x00, 0x58, 0x26, 0x8a, 0xd7, 0xee, 0x22, 0x76, 0x11, 0xad, 0xd4, 0x59, - 0x92, 0x7d, 0x60, 0x56, 0xfd, 0xe0, 0x4e, 0x6a, 0x14, 0xa0, 0xfa, 0x7b, 0x58, 0xd2, 0x42, 0xb3, - 0x49, 0xf0, 0xb0, 0xeb, 0x7c, 0x5e, 0x68, 0xb9, 0xe4, 0x02, 0xe6, 0x8d, 0xa2, 0xe0, 0x2b, 0xb4, - 0x78, 0x36, 0xd7, 0xe2, 0xd4, 0xc4, 0xf0, 0x49, 0x96, 0x1d, 0x46, 0x57, 0xd5, 0x3f, 0x43, 0x64, - 0x00, 0x2b, 0x56, 0x15, 0x89, 0x6c, 0x9c, 0x5c, 0x06, 0xeb, 0x68, 0xd8, 0x9d, 0x6b, 0x88, 0xc2, - 0x01, 0xf2, 0xa8, 0x37, 0x9a, 0x2d, 0x7a, 0x2f, 0x61, 0xe5, 0xd6, 0xd3, 0x6f, 0x41, 0xe3, 0xfc, - 0xf4, 0x80, 0xfa, 0xf7, 0x48, 0x1b, 0x5c, 0xf3, 0xb5, 0x7f, 0xb0, 0x77, 0x7e, 0xe8, 0x3b, 0xa4, - 0x09, 0x66, 0x5c, 0xf8, 0x0b, 0xbd, 0x37, 0xd0, 0xc0, 0xe6, 0xf0, 0xa0, 0x6a, 0x76, 0xff, 0x9e, - 0x41, 0xfb, 0xf4, 0xd8, 0x77, 0x88, 0x0b, 0x4b, 0x7d, 0x7a, 0xbc, 0xf3, 0xca, 0x5f, 0x30, 0xb1, - 0xf7, 0xaf, 0x77, 0xfc, 0x45, 0x02, 0xb0, 0xfc, 0xfe, 0xf5, 0x4e, 0xb8, 0xf3, 0xca, 0x6f, 0xf4, - 0xfa, 0xe0, 0xd5, 0x72, 0x31, 0xd3, 0xb4, 0x50, 0x3c, 0xbc, 0x14, 0x29, 0xc3, 0x99, 0xdb, 0xa2, - 0xcd, 0x42, 0xf1, 0x43, 0x91, 0x32, 0xd3, 0x7c, 0x06, 0x92, 0x23, 0x8e, 0x73, 0xb6, 0x45, 0x97, - 0x0b, 0xc5, 0xe9, 0x88, 0xf7, 0x7e, 0x77, 0xa0, 0x55, 0x9d, 0x31, 0x21, 0xd0, 0x88, 0xb9, 0x8a, - 0x50, 0xec, 0x52, 0xfc, 0x36, 0x31, 0x1c, 0xb9, 0x76, 0x3c, 0xe3, 0x37, 0xd9, 0x00, 0x50, 0x9a, - 0x49, 0x8d, 0x33, 0x1e, 0x87, 0x71, 0x83, 0xba, 0x18, 0x31, 0xa3, 0x9d, 0x3c, 0x01, 0x57, 0x72, - 0x36, 0xb1, 0x68, 0x03, 0xd1, 0x96, 0x09, 0x20, 0xb8, 0x01, 0x90, 0xf2, 0x54, 0xc8, 0x9b, 0xb0, - 0x50, 0x1c, 0x47, 0x6d, 0x83, 0xba, 0x36, 0x72, 0xae, 0x78, 0xef, 0x4f, 0x07, 0x3a, 0xc7, 0x22, - 0x2e, 0x26, 0xfc, 0xec, 0x26, 0xe7, 0x98, 0xd5, 0xaf, 0xd5, 0xd5, 0xa8, 0x1b, 0xa5, 0x79, 0x8a, - 0xd9, 0x75, 0xb6, 0x5f, 0xcc, 0x9f, 0x21, 0xb7, 0xa4, 0xf6, 0xa6, 0x4e, 0x51, 0x56, 0x9b, 0x26, - 0xa3, 0x59, 0x94, 0x7c, 0x0d, 0x5e, 0x8a, 0x9a, 0x50, 0xdf, 0xe4, 0x55, 0x95, 0x90, 0x4e, 0x6d, - 0xc8, 0x37, 0xd0, 0xc9, 0x8a, 0x34, 0x14, 0xe3, 0xd0, 0x06, 0x15, 0xd6, 0xdb, 0xa6, 0x2b, 0x59, - 0x91, 0x0e, 0xc7, 0x76, 0x3f, 0xd5, 0x7b, 0x51, 0xde, 0x44, 0xe9, 0x7a, 0xeb, 0x3a, 0x5d, 0x58, - 0x3a, 0x1d, 0x0e, 0x4f, 0xcc, 0xbd, 0xb7, 0xa0, 0x71, 0xdc, 0x3f, 0x3a, 0xf0, 0x17, 0x7a, 0x13, - 0x78, 0x3c, 0x90, 0x89, 0x4e, 0x22, 0x36, 0x39, 0x57, 0x5c, 0xfe, 0x24, 0x0a, 0x99, 0xf1, 0x9b, - 0xaa, 0x1b, 0xab, 0x43, 0x77, 0x6a, 0x87, 0xbe, 0x0b, 0xcd, 0xaa, 0xdb, 0x17, 0xfe, 0xa7, 0x39, - 0x6b, 0x53, 0x94, 0x56, 0x82, 0xde, 0x08, 0x9e, 0xcc, 0xd9, 0x4d, 0xcd, 0x9a, 0xbf, 0x11, 0x15, - 0x1f, 0x54, 0xe0, 0xe0, 0x0b, 0x9e, 0x7f, 0xb2, 0xff, 0x9d, 0x2d, 0x45, 0x71, 0xef, 0x0f, 0x07, - 0x56, 0xff, 0xf5, 0xd4, 0x48, 0x00, 0xcd, 0xea, 0xdc, 0x1c, 0x3c, 0xb7, 0x6a, 0x49, 0x1e, 0x43, - 0xab, 0xfc, 0x2d, 0xb2, 0x05, 0xb5, 0xe9, 0x74, 0x4d, 0xbe, 0x85, 0x55, 0x7c, 0xee, 0x21, 0x9b, - 0x4c, 0x44, 0x14, 0x46, 0xa2, 0xc8, 0x74, 0xd9, 0x67, 0xf7, 0x11, 0xe8, 0x9b, 0xf8, 0xc0, 0x84, - 0xc9, 0x26, 0xf8, 0x75, 0xae, 0x4a, 0x3e, 0x55, 0x4d, 0xd7, 0x99, 0x51, 0x4f, 0x93, 0x4f, 0xdc, - 0x0c, 0xff, 0x94, 0x5d, 0x87, 0x57, 0x9c, 0xe5, 0x96, 0x66, 0xbb, 0xcf, 0x4b, 0xd9, 0xf5, 0x8f, - 0x9c, 0xe5, 0x86, 0xb3, 0xf7, 0xf0, 0x97, 0x72, 0xbe, 0x94, 0x75, 0x87, 0xf8, 0xff, 0xe7, 0xef, - 0x00, 0x00, 0x00, 0xff, 0xff, 0x0a, 0x03, 0x26, 0x59, 0x0f, 0x09, 0x00, 0x00, + // 1036 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xef, 0x4e, 0x1b, 0x47, + 0x10, 0xcf, 0x61, 0x83, 0x7d, 0x73, 0xd8, 0x1c, 0x0b, 0x29, 0x97, 0x44, 0xa8, 0x96, 0xd5, 0x44, + 0xa8, 0x6a, 0x48, 0x44, 0x23, 0x14, 0xa1, 0xa8, 0x12, 0x18, 0x44, 0x53, 0x04, 0x8e, 0x16, 0x4c, + 0xa3, 0xf6, 0xc3, 0x69, 0x7d, 0xb7, 0x86, 0x4b, 0x7d, 0xb7, 0xd6, 0xee, 0x5e, 0x04, 0x79, 0x87, + 0x3e, 0x55, 0x9f, 0xa5, 0xaf, 0x51, 0x55, 0x3b, 0x7b, 0x67, 0x1f, 0xad, 0xdb, 0xa0, 0x7c, 0xf3, + 0xce, 0xef, 0xcf, 0xce, 0xec, 0xce, 0xce, 0x19, 0x5a, 0x29, 0xd7, 0x32, 0x89, 0xd4, 0xf6, 0x44, + 0x0a, 0x2d, 0xc8, 0x9a, 0x12, 0x22, 0xbb, 0x0a, 0x87, 0x79, 0x32, 0x8e, 0xc3, 0x02, 0xea, 0xfe, + 0x05, 0xe0, 0x9d, 0xda, 0xdf, 0x07, 0x4c, 0x71, 0xf2, 0x12, 0xd6, 0x2d, 0x21, 0x66, 0x9a, 0x87, + 0x3a, 0x49, 0xb9, 0xd2, 0x2c, 0x9d, 0x04, 0x4e, 0xc7, 0xd9, 0xaa, 0x51, 0x82, 0xd8, 0x21, 0xd3, + 0xfc, 0xa2, 0x44, 0xc8, 0x23, 0x68, 0x5a, 0x45, 0x12, 0x07, 0x0b, 0x1d, 0x67, 0xcb, 0xa5, 0x0d, + 0x5c, 0xbf, 0x8d, 0xc9, 0x1e, 0x3c, 0x9a, 0x8c, 0x99, 0x1e, 0x09, 0x99, 0x86, 0x1f, 0xb9, 0x54, + 0x89, 0xc8, 0xc2, 0x48, 0xc4, 0x3c, 0x63, 0x29, 0x0f, 0x6a, 0xc8, 0xdd, 0x28, 0x09, 0x97, 0x16, + 0xef, 0x15, 0x30, 0x79, 0x0a, 0x6d, 0xcd, 0xe4, 0x15, 0xd7, 0xe1, 0x44, 0x8a, 0x38, 0x8f, 0x74, + 0x50, 0x47, 0x41, 0xcb, 0x46, 0xdf, 0xd9, 0x20, 0x89, 0x61, 0xbd, 0xa0, 0xd9, 0x24, 0x3e, 0x32, + 0x99, 0xb0, 0x4c, 0x07, 0x8b, 0x1d, 0x67, 0xab, 0xbd, 0xf3, 0x7c, 0x7b, 0x4e, 0xcd, 0xdb, 0x95, + 0x7a, 0xb7, 0x0f, 0x0c, 0x72, 0x69, 0x45, 0x7b, 0xb5, 0xa3, 0xb3, 0x63, 0x4a, 0xac, 0x5f, 0x15, + 0x20, 0x7d, 0xf0, 0x8a, 0x5d, 0x98, 0x8c, 0xae, 0x83, 0x25, 0x34, 0x7f, 0xfa, 0x59, 0xf3, 0x7d, + 0x19, 0x5d, 0xef, 0x35, 0x06, 0x67, 0x27, 0x67, 0xfd, 0x9f, 0xcf, 0x28, 0x58, 0x0b, 0x13, 0x24, + 0xdb, 0xb0, 0x56, 0x31, 0x9c, 0x66, 0xdd, 0xc0, 0x12, 0x57, 0x67, 0xc4, 0x32, 0x81, 0xef, 0xa0, + 0x48, 0x2b, 0x8c, 0x26, 0xf9, 0x94, 0xde, 0x44, 0xba, 0x6f, 0x91, 0xde, 0x24, 0x2f, 0xd9, 0x27, + 0xe0, 0x5e, 0x0b, 0x55, 0x24, 0xeb, 0x7e, 0x51, 0xb2, 0x4d, 0x63, 0x80, 0xa9, 0x52, 0x68, 0xa1, + 0xd9, 0x4e, 0x16, 0x5b, 0x43, 0xf8, 0x22, 0x43, 0xcf, 0x98, 0xec, 0x64, 0x31, 0x7a, 0x6e, 0x40, + 0x03, 0x3d, 0x85, 0x0a, 0x3c, 0xac, 0x61, 0xc9, 0x2c, 0xfb, 0x8a, 0x74, 0x8b, 0xcd, 0x84, 0x0a, + 0xf9, 0x8d, 0x96, 0x2c, 0x58, 0x46, 0xd8, 0xb3, 0xf0, 0x91, 0x09, 0x4d, 0x39, 0x91, 0x14, 0x4a, + 0x19, 0x8b, 0xd6, 0x8c, 0xd3, 0x33, 0xb1, 0xbe, 0x22, 0xcf, 0x60, 0xa5, 0xc2, 0xc1, 0xb4, 0xdb, + 0xb6, 0x7d, 0xa6, 0x2c, 0x4c, 0xe4, 0x39, 0xac, 0x55, 0x78, 0xd3, 0x12, 0x57, 0xec, 0xc1, 0x4e, + 0xb9, 0x95, 0xbc, 0x45, 0xae, 0xc3, 0x38, 0x91, 0x81, 0x6f, 0xf3, 0x16, 0xb9, 0x3e, 0x4c, 0x24, + 0xf9, 0x01, 0x3c, 0xc5, 0x75, 0x3e, 0x09, 0xb5, 0x10, 0x63, 0x15, 0xac, 0x76, 0x6a, 0x5b, 0xde, + 0xce, 0xe6, 0xdc, 0x23, 0x7a, 0xc7, 0xe5, 0xe8, 0x6d, 0x36, 0x12, 0x14, 0x50, 0x71, 0x61, 0x04, + 0x64, 0x0f, 0xdc, 0xdf, 0x98, 0x4e, 0x42, 0x99, 0x67, 0x2a, 0x20, 0xf7, 0x51, 0x37, 0x0d, 0x9f, + 0xe6, 0x99, 0x22, 0x6f, 0x00, 0x2c, 0x13, 0xc5, 0x6b, 0xf7, 0x11, 0xbb, 0x88, 0x96, 0xea, 0x2c, + 0xc9, 0x3e, 0x30, 0xab, 0x5e, 0xbf, 0x97, 0x1a, 0x05, 0xa8, 0xfe, 0x1e, 0x16, 0xb5, 0xd0, 0x6c, + 0x1c, 0x3c, 0xec, 0x38, 0x9f, 0x17, 0x5a, 0x2e, 0xb9, 0x84, 0x79, 0xa3, 0x28, 0xf8, 0x0a, 0x2d, + 0x9e, 0xcd, 0xb5, 0x38, 0x37, 0x31, 0x7c, 0x92, 0x45, 0x87, 0xd1, 0x55, 0xf5, 0xcf, 0x10, 0xe9, + 0xc1, 0xb2, 0x55, 0x45, 0x22, 0x1b, 0x25, 0x57, 0xc1, 0x06, 0x1a, 0x76, 0xe6, 0x1a, 0xa2, 0xb0, + 0x87, 0x3c, 0xea, 0x0d, 0x67, 0x8b, 0xee, 0x4b, 0x58, 0xbe, 0xf3, 0xf4, 0x9b, 0x50, 0x1f, 0x9c, + 0x1f, 0x51, 0xff, 0x01, 0x69, 0x81, 0x6b, 0x7e, 0x1d, 0x1e, 0x1d, 0x0c, 0x8e, 0x7d, 0x87, 0x34, + 0xc0, 0x8c, 0x0b, 0x7f, 0xa1, 0xfb, 0x06, 0xea, 0xd8, 0x1c, 0x1e, 0x94, 0xcd, 0xee, 0x3f, 0x30, + 0xe8, 0x3e, 0x3d, 0xf5, 0x1d, 0xe2, 0xc2, 0xe2, 0x3e, 0x3d, 0xdd, 0x7d, 0xe5, 0x2f, 0x98, 0xd8, + 0xfb, 0xd7, 0xbb, 0x7e, 0x8d, 0x00, 0x2c, 0xbd, 0x7f, 0xbd, 0x1b, 0xee, 0xbe, 0xf2, 0xeb, 0xdd, + 0x2b, 0xf0, 0x2a, 0xb9, 0x98, 0x69, 0x9a, 0x2b, 0x1e, 0x5e, 0x89, 0x94, 0xe1, 0xcc, 0x6d, 0xd2, + 0x46, 0xae, 0xf8, 0xb1, 0x48, 0x99, 0x69, 0x3e, 0x03, 0xc9, 0x21, 0xc7, 0x39, 0xdb, 0xa4, 0x4b, + 0xb9, 0xe2, 0x74, 0xc8, 0xc9, 0x37, 0xd0, 0x1e, 0x09, 0x19, 0xf1, 0x70, 0xaa, 0xac, 0x21, 0xbe, + 0x8c, 0xd1, 0x81, 0x95, 0x77, 0x7f, 0x77, 0xa0, 0x59, 0xde, 0x04, 0x21, 0x50, 0x8f, 0xb9, 0x8a, + 0x70, 0x0b, 0x97, 0xe2, 0x6f, 0x13, 0xc3, 0xc1, 0x6c, 0x87, 0x38, 0xfe, 0x26, 0x9b, 0x00, 0x4a, + 0x33, 0xa9, 0xf1, 0x4b, 0x80, 0xb6, 0x75, 0xea, 0x62, 0xc4, 0x7c, 0x00, 0xc8, 0x13, 0x70, 0x25, + 0x67, 0x63, 0x8b, 0xd6, 0x11, 0x6d, 0x9a, 0x00, 0x82, 0x9b, 0x00, 0x29, 0x4f, 0x85, 0xbc, 0x35, + 0x79, 0xe1, 0x40, 0xae, 0x53, 0xd7, 0x46, 0x06, 0x8a, 0x77, 0xff, 0x74, 0xa0, 0x7d, 0x2a, 0xe2, + 0x7c, 0xcc, 0x2f, 0x6e, 0x27, 0x1c, 0xb3, 0xfa, 0xb5, 0xbc, 0x40, 0x75, 0xab, 0x34, 0x4f, 0x31, + 0xbb, 0xf6, 0xce, 0x8b, 0xf9, 0x93, 0xe6, 0x8e, 0xd4, 0xde, 0xe7, 0x39, 0xca, 0x2a, 0x33, 0x67, + 0x38, 0x8b, 0x92, 0xaf, 0xc1, 0x4b, 0x51, 0x13, 0xea, 0xdb, 0x49, 0x59, 0x25, 0xa4, 0x53, 0x1b, + 0x73, 0x8c, 0x59, 0x9e, 0x86, 0x62, 0x14, 0xda, 0xa0, 0xc2, 0x7a, 0x5b, 0x74, 0x39, 0xcb, 0xd3, + 0xfe, 0xc8, 0xee, 0xa7, 0xba, 0x2f, 0x8a, 0xfb, 0x2a, 0x5c, 0xef, 0x5c, 0xba, 0x0b, 0x8b, 0xe7, + 0xfd, 0xfe, 0x99, 0xe9, 0x8e, 0x26, 0xd4, 0x4f, 0xf7, 0x4f, 0x8e, 0xfc, 0x85, 0xee, 0x18, 0x1e, + 0xf7, 0x64, 0xa2, 0x93, 0x88, 0x8d, 0x07, 0x8a, 0xcb, 0x9f, 0x44, 0x2e, 0x33, 0x7e, 0x5b, 0xf6, + 0x6c, 0x79, 0xe8, 0x4e, 0xe5, 0xd0, 0xf7, 0xa0, 0x51, 0xbe, 0x89, 0x85, 0xff, 0x69, 0xe1, 0xca, + 0xac, 0xa5, 0xa5, 0xa0, 0x3b, 0x84, 0x27, 0x73, 0x76, 0x53, 0xb3, 0x27, 0x52, 0x8f, 0xf2, 0x0f, + 0x2a, 0x70, 0xf0, 0x9d, 0xcf, 0x3f, 0xd9, 0xff, 0xce, 0x96, 0xa2, 0xb8, 0xfb, 0x87, 0x03, 0xab, + 0xff, 0x7a, 0x90, 0x24, 0x80, 0x46, 0x79, 0x6e, 0x0e, 0x9e, 0x5b, 0xb9, 0x24, 0x8f, 0xa1, 0x59, + 0x7c, 0xb1, 0x6c, 0x41, 0x2d, 0x3a, 0x5d, 0x93, 0x6f, 0x61, 0x15, 0x87, 0x42, 0xc8, 0xc6, 0x63, + 0x11, 0x85, 0x91, 0xc8, 0x33, 0x5d, 0xf4, 0xd9, 0x0a, 0x02, 0xfb, 0x26, 0xde, 0x33, 0x61, 0xb2, + 0x05, 0x7e, 0x95, 0xab, 0x92, 0x4f, 0x65, 0xd3, 0xb5, 0x67, 0xd4, 0xf3, 0xe4, 0x13, 0x37, 0x9f, + 0x88, 0x94, 0xdd, 0x84, 0xd7, 0x9c, 0x4d, 0x2c, 0xcd, 0x76, 0x9f, 0x97, 0xb2, 0x9b, 0x1f, 0x39, + 0x9b, 0x18, 0xce, 0xc1, 0xc3, 0x5f, 0x8a, 0x29, 0x54, 0xd4, 0x1d, 0xe2, 0xbf, 0xa4, 0xbf, 0x03, + 0x00, 0x00, 0xff, 0xff, 0x85, 0xc5, 0xe0, 0x4b, 0x35, 0x09, 0x00, 0x00, } diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto index 6559ba334..4d6118b1d 100644 --- a/ui/metrics/metrics_proto/metrics.proto +++ b/ui/metrics/metrics_proto/metrics.proto @@ -102,6 +102,8 @@ message BuildConfig { optional bool use_goma = 1; optional bool use_rbe = 2; + + optional bool force_use_goma = 3; } message PerfInfo { |