Merge "Add bugprone to global clang-tidy default checks"
diff --git a/android/arch.go b/android/arch.go
index 73a490d..922548e 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -607,6 +607,10 @@
Android = NewOsType("android", Device, false)
Fuchsia = NewOsType("fuchsia", Device, false)
+ // A pseudo OSType for a common os variant, which is OSType agnostic and which
+ // has dependencies on all the OS variants.
+ CommonOS = NewOsType("common_os", Generic, false)
+
osArchTypeMap = map[OsType][]ArchType{
Linux: []ArchType{X86, X86_64},
LinuxBionic: []ArchType{X86_64},
@@ -775,12 +779,64 @@
osNames[i] = os.String()
}
- modules := mctx.CreateVariations(osNames...)
- for i, m := range modules {
- m.(Module).base().commonProperties.CompileOS = moduleOSList[i]
- m.(Module).base().setOSProperties(mctx)
+ createCommonOSVariant := base.commonProperties.CreateCommonOSVariant
+ if createCommonOSVariant {
+ // A CommonOS variant was requested so add it to the list of OS's variants to
+ // create. It needs to be added to the end because it needs to depend on the
+ // the other variants in the list returned by CreateVariations(...) and inter
+ // variant dependencies can only be created from a later variant in that list to
+ // an earlier one. That is because variants are always processed in the order in
+ // which they are returned from CreateVariations(...).
+ osNames = append(osNames, CommonOS.Name)
+ moduleOSList = append(moduleOSList, CommonOS)
}
+ modules := mctx.CreateVariations(osNames...)
+ for i, m := range modules {
+ m.base().commonProperties.CompileOS = moduleOSList[i]
+ m.base().setOSProperties(mctx)
+ }
+
+ if createCommonOSVariant {
+ // A CommonOS variant was requested so add dependencies from it (the last one in
+ // the list) to the OS type specific variants.
+ last := len(modules) - 1
+ commonOSVariant := modules[last]
+ commonOSVariant.base().commonProperties.CommonOSVariant = true
+ for _, module := range modules[0:last] {
+ // Ignore modules that are enabled. Note, this will only avoid adding
+ // dependencies on OsType variants that are explicitly disabled in their
+ // properties. The CommonOS variant will still depend on disabled variants
+ // if they are disabled afterwards, e.g. in archMutator if
+ if module.Enabled() {
+ mctx.AddInterVariantDependency(commonOsToOsSpecificVariantTag, commonOSVariant, module)
+ }
+ }
+ }
+}
+
+// Identifies the dependency from CommonOS variant to the os specific variants.
+type commonOSTag struct{ blueprint.BaseDependencyTag }
+
+var commonOsToOsSpecificVariantTag = commonOSTag{}
+
+// Get the OsType specific variants for the current CommonOS variant.
+//
+// The returned list will only contain enabled OsType specific variants of the
+// module referenced in the supplied context. An empty list is returned if there
+// are no enabled variants or the supplied context is not for an CommonOS
+// variant.
+func GetOsSpecificVariantsOfCommonOSVariant(mctx BaseModuleContext) []Module {
+ var variants []Module
+ mctx.VisitDirectDeps(func(m Module) {
+ if mctx.OtherModuleDependencyTag(m) == commonOsToOsSpecificVariantTag {
+ if m.Enabled() {
+ variants = append(variants, m)
+ }
+ }
+ })
+
+ return variants
}
// archMutator splits a module into a variant for each Target requested by the module. Target selection
@@ -821,6 +877,15 @@
}
os := base.commonProperties.CompileOS
+ if os == CommonOS {
+ // Make sure that the target related properties are initialized for the
+ // CommonOS variant.
+ addTargetProperties(module, commonTargetMap[os.Name], nil, true)
+
+ // Do not create arch specific variants for the CommonOS variant.
+ return
+ }
+
osTargets := mctx.Config().Targets[os]
image := base.commonProperties.ImageVariation
// Filter NativeBridge targets unless they are explicitly supported
@@ -881,15 +946,17 @@
modules := mctx.CreateVariations(targetNames...)
for i, m := range modules {
- m.(Module).base().commonProperties.CompileTarget = targets[i]
- m.(Module).base().commonProperties.CompileMultiTargets = multiTargets
- if i == 0 {
- m.(Module).base().commonProperties.CompilePrimary = true
- }
+ addTargetProperties(m, targets[i], multiTargets, i == 0)
m.(Module).base().setArchProperties(mctx)
}
}
+func addTargetProperties(m Module, target Target, multiTargets []Target, primaryTarget bool) {
+ m.base().commonProperties.CompileTarget = target
+ m.base().commonProperties.CompileMultiTargets = multiTargets
+ m.base().commonProperties.CompilePrimary = primaryTarget
+}
+
func decodeMultilib(base *ModuleBase, class OsClass) (multilib, extraMultilib string) {
switch class {
case Device:
@@ -1711,6 +1778,8 @@
return ret
}
+// Return the set of Os specific common architecture targets for each Os in a list of
+// targets.
func getCommonTargets(targets []Target) []Target {
var ret []Target
set := make(map[string]bool)
diff --git a/android/config.go b/android/config.go
index b2bda2a..9b1297c 100644
--- a/android/config.go
+++ b/android/config.go
@@ -359,6 +359,9 @@
return Config{}, err
}
+ // Make the CommonOS OsType available for all products.
+ targets[CommonOS] = []Target{commonTargetMap[CommonOS.Name]}
+
var archConfig []archConfig
if Bool(config.Mega_device) {
archConfig = getMegaDeviceConfig()
diff --git a/android/module.go b/android/module.go
index 1026bdf..2e33056 100644
--- a/android/module.go
+++ b/android/module.go
@@ -132,6 +132,9 @@
Target() Target
TargetPrimary() bool
+
+ // The additional arch specific targets (e.g. 32/64 bit) that this module variant is
+ // responsible for creating.
MultiTargets() []Target
Arch() Arch
Os() OsType
@@ -364,6 +367,10 @@
}
}
+ // If set to true then the archMutator will create variants for each arch specific target
+ // (e.g. 32/64) that the module is required to produce. If set to false then it will only
+ // create a variant for the architecture and will list the additional arch specific targets
+ // that the variant needs to produce in the CompileMultiTargets property.
UseTargetVariants bool `blueprint:"mutated"`
Default_multilib string `blueprint:"mutated"`
@@ -442,16 +449,56 @@
Suffix *string `android:"arch_variant"`
} `android:"arch_variant"`
- // Set by TargetMutator
- CompileOS OsType `blueprint:"mutated"`
- CompileTarget Target `blueprint:"mutated"`
+ // The OsType of artifacts that this module variant is responsible for creating.
+ //
+ // Set by osMutator
+ CompileOS OsType `blueprint:"mutated"`
+
+ // The Target of artifacts that this module variant is responsible for creating.
+ //
+ // Set by archMutator
+ CompileTarget Target `blueprint:"mutated"`
+
+ // The additional arch specific targets (e.g. 32/64 bit) that this module variant is
+ // responsible for creating.
+ //
+ // By default this is nil as, where necessary, separate variants are created for the
+ // different multilib types supported and that information is encapsulated in the
+ // CompileTarget so the module variant simply needs to create artifacts for that.
+ //
+ // However, if UseTargetVariants is set to false (e.g. by
+ // InitAndroidMultiTargetsArchModule) then no separate variants are created for the
+ // multilib targets. Instead a single variant is created for the architecture and
+ // this contains the multilib specific targets that this variant should create.
+ //
+ // Set by archMutator
CompileMultiTargets []Target `blueprint:"mutated"`
- CompilePrimary bool `blueprint:"mutated"`
+
+ // True if the module variant's CompileTarget is the primary target
+ //
+ // Set by archMutator
+ CompilePrimary bool `blueprint:"mutated"`
// Set by InitAndroidModule
HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"`
ArchSpecific bool `blueprint:"mutated"`
+ // If set to true then a CommonOS variant will be created which will have dependencies
+ // on all its OsType specific variants. Used by sdk/module_exports to create a snapshot
+ // that covers all os and architecture variants.
+ //
+ // The OsType specific variants can be retrieved by calling
+ // GetOsSpecificVariantsOfCommonOSVariant
+ //
+ // Set at module initialization time by calling InitCommonOSAndroidMultiTargetsArchModule
+ CreateCommonOSVariant bool `blueprint:"mutated"`
+
+ // If set to true then this variant is the CommonOS variant that has dependencies on its
+ // OsType specific variants.
+ //
+ // Set by osMutator.
+ CommonOSVariant bool `blueprint:"mutated"`
+
SkipInstall bool `blueprint:"mutated"`
NamespaceExportedToMake bool `blueprint:"mutated"`
@@ -584,6 +631,14 @@
m.base().commonProperties.UseTargetVariants = false
}
+// As InitAndroidMultiTargetsArchModule except it creates an additional CommonOS variant that
+// has dependencies on all the OsType specific variants.
+func InitCommonOSAndroidMultiTargetsArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) {
+ InitAndroidArchModule(m, hod, defaultMultilib)
+ m.base().commonProperties.UseTargetVariants = false
+ m.base().commonProperties.CreateCommonOSVariant = true
+}
+
// A ModuleBase object contains the properties that are common to all Android
// modules. It should be included as an anonymous field in every module
// struct definition. InitAndroidModule should then be called from the module's
@@ -775,6 +830,11 @@
return m.commonProperties.ArchSpecific
}
+// True if the current variant is a CommonOS variant, false otherwise.
+func (m *ModuleBase) IsCommonOSVariant() bool {
+ return m.commonProperties.CommonOSVariant
+}
+
func (m *ModuleBase) OsClassSupported() []OsClass {
switch m.commonProperties.HostOrDeviceSupported {
case HostSupported:
@@ -1103,8 +1163,11 @@
blueprintCtx.GetMissingDependencies()
// For the final GenerateAndroidBuildActions pass, require that all visited dependencies Soong modules and
- // are enabled.
- ctx.baseModuleContext.strictVisitDeps = true
+ // are enabled. Unless the module is a CommonOS variant which may have dependencies on disabled variants
+ // (because the dependencies are added before the modules are disabled). The
+ // GetOsSpecificVariantsOfCommonOSVariant(...) method will ensure that the disabled variants are
+ // ignored.
+ ctx.baseModuleContext.strictVisitDeps = !m.IsCommonOSVariant()
if ctx.config.captureBuild {
ctx.ruleParams = make(map[blueprint.Rule]blueprint.RuleParams)
@@ -1297,16 +1360,20 @@
strictVisitDeps bool // If true, enforce that all dependencies are enabled
}
-func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string { return b.bp.OtherModuleName(m) }
-func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string { return b.bp.OtherModuleDir(m) }
+func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string {
+ return b.bp.OtherModuleName(m)
+}
+func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string { return b.bp.OtherModuleDir(m) }
func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) {
b.bp.OtherModuleErrorf(m, fmt, args...)
}
func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
return b.bp.OtherModuleDependencyTag(m)
}
-func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
-func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string { return b.bp.OtherModuleType(m) }
+func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
+func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
+ return b.bp.OtherModuleType(m)
+}
func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
return b.bp.GetDirectDepWithTag(name, tag)
diff --git a/android/neverallow.go b/android/neverallow.go
index 0cb2029..8fcfb8a 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -102,6 +102,7 @@
In("vendor", "device").
With("vndk.enabled", "true").
Without("vendor", "true").
+ Without("product_specific", "true").
Because("the VNDK can never contain a library that is device dependent."),
NeverAllow().
With("vndk.enabled", "true").
diff --git a/android/notices.go b/android/notices.go
index bf273b5..07cf3e4 100644
--- a/android/notices.go
+++ b/android/notices.go
@@ -22,7 +22,7 @@
func init() {
pctx.SourcePathVariable("merge_notices", "build/soong/scripts/mergenotice.py")
- pctx.SourcePathVariable("generate_notice", "build/make/tools/generate-notice-files.py")
+ pctx.SourcePathVariable("generate_notice", "build/soong/scripts/generate-notice-files.py")
pctx.HostBinToolVariable("minigzip", "minigzip")
}
diff --git a/android/paths.go b/android/paths.go
index 8b373da..c4b1073 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -470,6 +470,14 @@
// FirstUniquePaths returns all unique elements of a Paths, keeping the first copy of each. It
// modifies the Paths slice contents in place, and returns a subslice of the original slice.
func FirstUniquePaths(list Paths) Paths {
+ // 128 was chosen based on BenchmarkFirstUniquePaths results.
+ if len(list) > 128 {
+ return firstUniquePathsMap(list)
+ }
+ return firstUniquePathsList(list)
+}
+
+func firstUniquePathsList(list Paths) Paths {
k := 0
outer:
for i := 0; i < len(list); i++ {
@@ -484,6 +492,20 @@
return list[:k]
}
+func firstUniquePathsMap(list Paths) Paths {
+ k := 0
+ seen := make(map[Path]bool, len(list))
+ for i := 0; i < len(list); i++ {
+ if seen[list[i]] {
+ continue
+ }
+ seen[list[i]] = true
+ list[k] = list[i]
+ k++
+ }
+ return list[:k]
+}
+
// LastUniquePaths returns all unique elements of a Paths, keeping the last copy of each. It
// modifies the Paths slice contents in place, and returns a subslice of the original slice.
func LastUniquePaths(list Paths) Paths {
diff --git a/android/paths_test.go b/android/paths_test.go
index f1908ac..9b45d3f 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -18,6 +18,7 @@
"errors"
"fmt"
"reflect"
+ "strconv"
"strings"
"testing"
@@ -1255,3 +1256,51 @@
// out/system/framework/boot.art out/system/framework/oat/arm/boot.vdex
// boot.art oat/arm/boot.vdex
}
+
+func BenchmarkFirstUniquePaths(b *testing.B) {
+ implementations := []struct {
+ name string
+ f func(Paths) Paths
+ }{
+ {
+ name: "list",
+ f: firstUniquePathsList,
+ },
+ {
+ name: "map",
+ f: firstUniquePathsMap,
+ },
+ }
+ const maxSize = 1024
+ uniquePaths := make(Paths, maxSize)
+ for i := range uniquePaths {
+ uniquePaths[i] = PathForTesting(strconv.Itoa(i))
+ }
+ samePath := make(Paths, maxSize)
+ for i := range samePath {
+ samePath[i] = uniquePaths[0]
+ }
+
+ f := func(b *testing.B, imp func(Paths) Paths, paths Paths) {
+ for i := 0; i < b.N; i++ {
+ b.ReportAllocs()
+ paths = append(Paths(nil), paths...)
+ imp(paths)
+ }
+ }
+
+ for n := 1; n <= maxSize; n <<= 1 {
+ b.Run(strconv.Itoa(n), func(b *testing.B) {
+ for _, implementation := range implementations {
+ b.Run(implementation.name, func(b *testing.B) {
+ b.Run("same", func(b *testing.B) {
+ f(b, implementation.f, samePath[:n])
+ })
+ b.Run("unique", func(b *testing.B) {
+ f(b, implementation.f, uniquePaths[:n])
+ })
+ })
+ }
+ })
+ }
+}
diff --git a/android/util.go b/android/util.go
index ade851e..e74b64e 100644
--- a/android/util.go
+++ b/android/util.go
@@ -193,6 +193,14 @@
// FirstUniqueStrings returns all unique elements of a slice of strings, keeping the first copy of
// each. It modifies the slice contents in place, and returns a subslice of the original slice.
func FirstUniqueStrings(list []string) []string {
+ // 128 was chosen based on BenchmarkFirstUniqueStrings results.
+ if len(list) > 128 {
+ return firstUniqueStringsMap(list)
+ }
+ return firstUniqueStringsList(list)
+}
+
+func firstUniqueStringsList(list []string) []string {
k := 0
outer:
for i := 0; i < len(list); i++ {
@@ -207,6 +215,20 @@
return list[:k]
}
+func firstUniqueStringsMap(list []string) []string {
+ k := 0
+ seen := make(map[string]bool, len(list))
+ for i := 0; i < len(list); i++ {
+ if seen[list[i]] {
+ continue
+ }
+ seen[list[i]] = true
+ list[k] = list[i]
+ k++
+ }
+ return list[:k]
+}
+
// LastUniqueStrings returns all unique elements of a slice of strings, keeping the last copy of
// each. It modifies the slice contents in place, and returns a subslice of the original slice.
func LastUniqueStrings(list []string) []string {
diff --git a/android/util_test.go b/android/util_test.go
index 1f9ca36..25b52ca 100644
--- a/android/util_test.go
+++ b/android/util_test.go
@@ -17,6 +17,7 @@
import (
"fmt"
"reflect"
+ "strconv"
"testing"
)
@@ -59,15 +60,25 @@
}
func TestFirstUniqueStrings(t *testing.T) {
- for _, testCase := range firstUniqueStringsTestCases {
- out := FirstUniqueStrings(testCase.in)
- if !reflect.DeepEqual(out, testCase.out) {
+ f := func(t *testing.T, imp func([]string) []string, in, want []string) {
+ t.Helper()
+ out := imp(in)
+ if !reflect.DeepEqual(out, want) {
t.Errorf("incorrect output:")
- t.Errorf(" input: %#v", testCase.in)
- t.Errorf(" expected: %#v", testCase.out)
+ t.Errorf(" input: %#v", in)
+ t.Errorf(" expected: %#v", want)
t.Errorf(" got: %#v", out)
}
}
+
+ for _, testCase := range firstUniqueStringsTestCases {
+ t.Run("list", func(t *testing.T) {
+ f(t, firstUniqueStringsList, testCase.in, testCase.out)
+ })
+ t.Run("map", func(t *testing.T) {
+ f(t, firstUniqueStringsMap, testCase.in, testCase.out)
+ })
+ }
}
var lastUniqueStringsTestCases = []struct {
@@ -568,3 +579,51 @@
})
}
}
+
+func BenchmarkFirstUniqueStrings(b *testing.B) {
+ implementations := []struct {
+ name string
+ f func([]string) []string
+ }{
+ {
+ name: "list",
+ f: firstUniqueStringsList,
+ },
+ {
+ name: "map",
+ f: firstUniqueStringsMap,
+ },
+ }
+ const maxSize = 1024
+ uniqueStrings := make([]string, maxSize)
+ for i := range uniqueStrings {
+ uniqueStrings[i] = strconv.Itoa(i)
+ }
+ sameString := make([]string, maxSize)
+ for i := range sameString {
+ sameString[i] = uniqueStrings[0]
+ }
+
+ f := func(b *testing.B, imp func([]string) []string, s []string) {
+ for i := 0; i < b.N; i++ {
+ b.ReportAllocs()
+ s = append([]string(nil), s...)
+ imp(s)
+ }
+ }
+
+ for n := 1; n <= maxSize; n <<= 1 {
+ b.Run(strconv.Itoa(n), func(b *testing.B) {
+ for _, implementation := range implementations {
+ b.Run(implementation.name, func(b *testing.B) {
+ b.Run("same", func(b *testing.B) {
+ f(b, implementation.f, sameString[:n])
+ })
+ b.Run("unique", func(b *testing.B) {
+ f(b, implementation.f, uniqueStrings[:n])
+ })
+ })
+ }
+ })
+ }
+}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 6d9ad26..674446a 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -1389,13 +1389,13 @@
apex {
name: "myapex",
key: "myapex.key",
- native_shared_libs: ["mylib"],
+ native_shared_libs: ["mylib", "mylib2"],
}
apex {
name: "otherapex",
key: "myapex.key",
- native_shared_libs: ["mylib"],
+ native_shared_libs: ["mylib", "mylib2"],
}
apex_key {
@@ -1409,29 +1409,53 @@
srcs: ["mylib.cpp"],
system_shared_libs: [],
stl: "none",
- // TODO: remove //apex_available:platform
apex_available: [
- "//apex_available:platform",
"myapex",
"otherapex",
],
}
+ cc_library {
+ name: "mylib2",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [
+ "myapex",
+ "otherapex",
+ ],
+ use_apex_name_macro: true,
+ }
`)
- // non-APEX variant does not have __ANDROID_APEX(_NAME)__ defined
+ // non-APEX variant does not have __ANDROID_APEX__ defined
mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
+
+ // APEX variant has __ANDROID_APEX__ defined
+ mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
+ ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
+
+ // APEX variant has __ANDROID_APEX__ defined
+ mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_otherapex").Rule("cc").Args["cFlags"]
+ ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
- // APEX variant has __ANDROID_APEX(_NAME)__ defined
- mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
+ // When cc_library sets use_apex_name_macro: true
+ // apex variants define additional macro to distinguish which apex variant it is built for
+
+ // non-APEX variant does not have __ANDROID_APEX__ defined
+ mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
+ ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
+
+ // APEX variant has __ANDROID_APEX__ defined
+ mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
- // APEX variant has __ANDROID_APEX(_NAME)__ defined
- mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_otherapex").Rule("cc").Args["cFlags"]
+ // APEX variant has __ANDROID_APEX__ defined
+ mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_otherapex").Rule("cc").Args["cFlags"]
ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
@@ -3301,7 +3325,7 @@
base: "app",
package_name: "bar",
}
- `)
+ `, withManifestPackageNameOverrides([]string{"myapex:com.android.myapex"}))
originalVariant := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(android.OverridableModule)
overriddenVariant := ctx.ModuleForTests("myapex", "android_common_override_myapex_myapex_image").Module().(android.OverridableModule)
@@ -3329,6 +3353,9 @@
t.Errorf("override_myapex should have logging parent (com.foo.bar), but was %q.", apexBundle.overridableProperties.Logging_parent)
}
+ optFlags := apexRule.Args["opt_flags"]
+ ensureContains(t, optFlags, "--override_apk_package_name com.android.myapex")
+
data := android.AndroidMkDataForTest(t, config, "", apexBundle)
var builder strings.Builder
data.Custom(&builder, name, "TARGET_", "", data)
diff --git a/apex/builder.go b/apex/builder.go
index 38a2a53..279445b 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -660,7 +660,7 @@
}
return ""
}
- manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(a.Name())
+ manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(ctx.ModuleName())
if overridden {
return manifestPackageName
}
diff --git a/cc/cc.go b/cc/cc.go
index 76f1f96..cc54f7a 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -2740,19 +2740,18 @@
if vndkdep := m.vndkdep; vndkdep != nil {
if vndkdep.isVndk() {
- if productSpecific {
- mctx.PropertyErrorf("product_specific",
- "product_specific must not be true when `vndk: {enabled: true}`")
- }
- if vendorSpecific {
+ if vendorSpecific || productSpecific {
if !vndkdep.isVndkExt() {
mctx.PropertyErrorf("vndk",
"must set `extends: \"...\"` to vndk extension")
+ } else if m.VendorProperties.Vendor_available != nil {
+ mctx.PropertyErrorf("vendor_available",
+ "must not set at the same time as `vndk: {extends: \"...\"}`")
}
} else {
if vndkdep.isVndkExt() {
mctx.PropertyErrorf("vndk",
- "must set `vendor: true` to set `extends: %q`",
+ "must set `vendor: true` or `product_specific: true` to set `extends: %q`",
m.getVndkExtendsModuleName())
}
if m.VendorProperties.Vendor_available == nil {
@@ -2825,7 +2824,7 @@
} else {
mctx.ModuleErrorf("version is unknown for snapshot prebuilt")
}
- } else if m.HasVendorVariant() && !vendorSpecific {
+ } else if m.HasVendorVariant() && !m.isVndkExt() {
// This will be available in /system, /vendor and /product
// or a /system directory that is available to vendor and product.
coreVariantNeeded = true
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 30ba733..8acc817 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -218,13 +218,13 @@
}
func checkVndkModule(t *testing.T, ctx *android.TestContext, name, subDir string,
- isVndkSp bool, extends string) {
+ isVndkSp bool, extends string, variant string) {
t.Helper()
- mod := ctx.ModuleForTests(name, vendorVariant).Module().(*Module)
+ mod := ctx.ModuleForTests(name, variant).Module().(*Module)
if !mod.HasVendorVariant() {
- t.Errorf("%q must have vendor variant", name)
+ t.Errorf("%q must have variant %q", name, variant)
}
// Check library properties.
@@ -375,10 +375,10 @@
ctx := testCcWithConfig(t, config)
- checkVndkModule(t, ctx, "libvndk", "vndk-VER", false, "")
- checkVndkModule(t, ctx, "libvndk_private", "vndk-VER", false, "")
- checkVndkModule(t, ctx, "libvndk_sp", "vndk-sp-VER", true, "")
- checkVndkModule(t, ctx, "libvndk_sp_private", "vndk-sp-VER", true, "")
+ checkVndkModule(t, ctx, "libvndk", "vndk-VER", false, "", vendorVariant)
+ checkVndkModule(t, ctx, "libvndk_private", "vndk-VER", false, "", vendorVariant)
+ checkVndkModule(t, ctx, "libvndk_sp", "vndk-sp-VER", true, "", vendorVariant)
+ checkVndkModule(t, ctx, "libvndk_sp_private", "vndk-sp-VER", true, "", vendorVariant)
// Check VNDK snapshot output.
@@ -1001,24 +1001,9 @@
`)
}
-func TestVndkMustNotBeProductSpecific(t *testing.T) {
- // Check whether an error is emitted when a vndk lib has 'product_specific: true'.
- testCcError(t, "product_specific must not be true when `vndk: {enabled: true}`", `
- cc_library {
- name: "libvndk",
- product_specific: true, // Cause error
- vendor_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
- `)
-}
-
func TestVndkExt(t *testing.T) {
// This test checks the VNDK-Ext properties.
- ctx := testCc(t, `
+ bp := `
cc_library {
name: "libvndk",
vendor_available: true,
@@ -1060,12 +1045,42 @@
},
nocrt: true,
}
- `)
- checkVndkModule(t, ctx, "libvndk_ext", "vndk", false, "libvndk")
+ cc_library {
+ name: "libvndk_ext_product",
+ product_specific: true,
+ vndk: {
+ enabled: true,
+ extends: "libvndk",
+ },
+ nocrt: true,
+ }
- mod := ctx.ModuleForTests("libvndk2_ext", vendorVariant).Module().(*Module)
- assertString(t, mod.outputFile.Path().Base(), "libvndk2-suffix.so")
+ cc_library {
+ name: "libvndk2_ext_product",
+ product_specific: true,
+ vndk: {
+ enabled: true,
+ extends: "libvndk2",
+ },
+ nocrt: true,
+ }
+ `
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+ config.TestProductVariables.ProductVndkVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+
+ ctx := testCcWithConfig(t, config)
+
+ checkVndkModule(t, ctx, "libvndk_ext", "vndk", false, "libvndk", vendorVariant)
+ checkVndkModule(t, ctx, "libvndk_ext_product", "vndk", false, "libvndk", productVariant)
+
+ mod_vendor := ctx.ModuleForTests("libvndk2_ext", vendorVariant).Module().(*Module)
+ assertString(t, mod_vendor.outputFile.Path().Base(), "libvndk2-suffix.so")
+
+ mod_product := ctx.ModuleForTests("libvndk2_ext_product", productVariant).Module().(*Module)
+ assertString(t, mod_product.outputFile.Path().Base(), "libvndk2-suffix.so")
}
func TestVndkExtWithoutBoardVndkVersion(t *testing.T) {
@@ -1098,9 +1113,39 @@
}
}
+func TestVndkExtWithoutProductVndkVersion(t *testing.T) {
+ // This test checks the VNDK-Ext properties when PRODUCT_PRODUCT_VNDK_VERSION is not set.
+ ctx := testCc(t, `
+ cc_library {
+ name: "libvndk",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libvndk_ext_product",
+ product_specific: true,
+ vndk: {
+ enabled: true,
+ extends: "libvndk",
+ },
+ nocrt: true,
+ }
+ `)
+
+ // Ensures that the core variant of "libvndk_ext_product" can be found.
+ mod := ctx.ModuleForTests("libvndk_ext_product", coreVariant).Module().(*Module)
+ if extends := mod.getVndkExtendsModuleName(); extends != "libvndk" {
+ t.Errorf("\"libvndk_ext_product\" must extend from \"libvndk\" but get %q", extends)
+ }
+}
+
func TestVndkExtError(t *testing.T) {
// This test ensures an error is emitted in ill-formed vndk-ext definition.
- testCcError(t, "must set `vendor: true` to set `extends: \".*\"`", `
+ testCcError(t, "must set `vendor: true` or `product_specific: true` to set `extends: \".*\"`", `
cc_library {
name: "libvndk",
vendor_available: true,
@@ -1139,6 +1184,48 @@
nocrt: true,
}
`)
+
+ testCcErrorProductVndk(t, "must set `extends: \"\\.\\.\\.\"` to vndk extension", `
+ cc_library {
+ name: "libvndk",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libvndk_ext_product",
+ product_specific: true,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ }
+ `)
+
+ testCcErrorProductVndk(t, "must not set at the same time as `vndk: {extends: \"\\.\\.\\.\"}`", `
+ cc_library {
+ name: "libvndk",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libvndk_ext_product",
+ product_specific: true,
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ extends: "libvndk",
+ },
+ nocrt: true,
+ }
+ `)
}
func TestVndkExtInconsistentSupportSystemProcessError(t *testing.T) {
@@ -1211,6 +1298,27 @@
nocrt: true,
}
`)
+
+ testCcErrorProductVndk(t, "`extends` refers module \".*\" which does not have `vendor_available: true`", `
+ cc_library {
+ name: "libvndk",
+ vendor_available: false,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libvndk_ext_product",
+ product_specific: true,
+ vndk: {
+ enabled: true,
+ extends: "libvndk",
+ },
+ nocrt: true,
+ }
+ `)
}
func TestVendorModuleUseVndkExt(t *testing.T) {
@@ -1236,7 +1344,6 @@
}
cc_library {
-
name: "libvndk_sp",
vendor_available: true,
vndk: {
@@ -1328,6 +1435,71 @@
`)
}
+func TestProductVndkExtDependency(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "libvndk",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libvndk_ext_product",
+ product_specific: true,
+ vndk: {
+ enabled: true,
+ extends: "libvndk",
+ },
+ shared_libs: ["libproduct_for_vndklibs"],
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libvndk_sp",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libvndk_sp_ext_product",
+ product_specific: true,
+ vndk: {
+ enabled: true,
+ extends: "libvndk_sp",
+ support_system_process: true,
+ },
+ shared_libs: ["libproduct_for_vndklibs"],
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libproduct",
+ product_specific: true,
+ shared_libs: ["libvndk_ext_product", "libvndk_sp_ext_product"],
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libproduct_for_vndklibs",
+ product_specific: true,
+ nocrt: true,
+ }
+ `
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+ config.TestProductVariables.ProductVndkVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+
+ testCcWithConfig(t, config)
+}
+
func TestVndkSpExtUseVndkError(t *testing.T) {
// This test ensures an error is emitted if a VNDK-SP-Ext library depends on a VNDK
// library.
@@ -1619,8 +1791,8 @@
ctx := testCcWithConfig(t, config)
- checkVndkModule(t, ctx, "libvndk", "vndk-VER", false, "")
- checkVndkModule(t, ctx, "libvndk_sp", "vndk-sp-VER", true, "")
+ checkVndkModule(t, ctx, "libvndk", "vndk-VER", false, "", productVariant)
+ checkVndkModule(t, ctx, "libvndk_sp", "vndk-sp-VER", true, "", productVariant)
}
func TestEnforceProductVndkVersionErrors(t *testing.T) {
diff --git a/cc/compiler.go b/cc/compiler.go
index c1a8d96..3a87b69 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -176,6 +176,9 @@
// Build and link with OpenMP
Openmp *bool `android:"arch_variant"`
+
+ // Adds __ANDROID_APEX_<APEX_MODULE_NAME>__ macro defined for apex variants in addition to __ANDROID_APEX__
+ Use_apex_name_macro *bool
}
func NewBaseCompiler() *baseCompiler {
@@ -321,9 +324,10 @@
}
if ctx.apexName() != "" {
- flags.Global.CommonFlags = append(flags.Global.CommonFlags,
- "-D__ANDROID_APEX__",
- "-D__ANDROID_APEX_"+makeDefineString(ctx.apexName())+"__")
+ flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_APEX__")
+ if Bool(compiler.Properties.Use_apex_name_macro) {
+ flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_APEX_"+makeDefineString(ctx.apexName())+"__")
+ }
}
instructionSet := String(compiler.Properties.Instruction_set)
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 1ca1656..19aedd9 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -39,6 +39,7 @@
arm64Ldflags = []string{
"-Wl,-m,aarch64_elf64_le_vec",
"-Wl,--hash-style=gnu",
+ "-Wl,-z,separate-code",
"-fuse-ld=gold",
"-Wl,--icf=safe",
}
diff --git a/java/java.go b/java/java.go
index 8d58a90..135ae51 100644
--- a/java/java.go
+++ b/java/java.go
@@ -41,11 +41,17 @@
// Register sdk member types.
android.RegisterSdkMemberType(javaHeaderLibsSdkMemberType)
- android.RegisterSdkMemberType(&implLibrarySdkMemberType{
- librarySdkMemberType{
- android.SdkMemberTypeBase{
- PropertyName: "java_libs",
- },
+ android.RegisterSdkMemberType(&librarySdkMemberType{
+ android.SdkMemberTypeBase{
+ PropertyName: "java_libs",
+ },
+ func(j *Library) android.Path {
+ implementationJars := j.ImplementationJars()
+ if len(implementationJars) != 1 {
+ panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name()))
+ }
+
+ return implementationJars[0]
},
})
@@ -1883,6 +1889,10 @@
type librarySdkMemberType struct {
android.SdkMemberTypeBase
+
+ // Function to retrieve the appropriate output jar (implementation or header) from
+ // the library.
+ jarToExportGetter func(j *Library) android.Path
}
func (mt *librarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
@@ -1894,11 +1904,7 @@
return ok
}
-func (mt *librarySdkMemberType) buildSnapshot(
- sdkModuleContext android.ModuleContext,
- builder android.SnapshotBuilder,
- member android.SdkMember,
- jarToExportGetter func(j *Library) android.Path) {
+func (mt *librarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
variants := member.Variants()
if len(variants) != 1 {
@@ -1910,7 +1916,7 @@
variant := variants[0]
j := variant.(*Library)
- exportedJar := jarToExportGetter(j)
+ exportedJar := mt.jarToExportGetter(j)
snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(member)
builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath)
@@ -1926,43 +1932,19 @@
module.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
}
-var javaHeaderLibsSdkMemberType android.SdkMemberType = &headerLibrarySdkMemberType{
- librarySdkMemberType{
- android.SdkMemberTypeBase{
- PropertyName: "java_header_libs",
- SupportsSdk: true,
- },
+var javaHeaderLibsSdkMemberType android.SdkMemberType = &librarySdkMemberType{
+ android.SdkMemberTypeBase{
+ PropertyName: "java_header_libs",
+ SupportsSdk: true,
},
-}
-
-type headerLibrarySdkMemberType struct {
- librarySdkMemberType
-}
-
-func (mt *headerLibrarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
- mt.librarySdkMemberType.buildSnapshot(sdkModuleContext, builder, member, func(j *Library) android.Path {
+ func(j *Library) android.Path {
headerJars := j.HeaderJars()
if len(headerJars) != 1 {
panic(fmt.Errorf("there must be only one header jar from %q", j.Name()))
}
return headerJars[0]
- })
-}
-
-type implLibrarySdkMemberType struct {
- librarySdkMemberType
-}
-
-func (mt *implLibrarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
- mt.librarySdkMemberType.buildSnapshot(sdkModuleContext, builder, member, func(j *Library) android.Path {
- implementationJars := j.ImplementationJars()
- if len(implementationJars) != 1 {
- panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name()))
- }
-
- return implementationJars[0]
- })
+ },
}
// java_library builds and links sources into a `.jar` file for the device, and possibly for the host as well.
diff --git a/scripts/build_broken_logs.go b/scripts/build_broken_logs.go
index 8021e55..82ba749 100644
--- a/scripts/build_broken_logs.go
+++ b/scripts/build_broken_logs.go
@@ -54,11 +54,13 @@
DefaultDeprecated
)
-var buildBrokenSettings = []struct {
+type Setting struct {
name string
behavior BuildBrokenBehavior
warnings []string
-}{
+}
+
+var buildBrokenSettings = []Setting{
{
name: "BUILD_BROKEN_DUP_RULES",
behavior: DefaultFalse,
@@ -68,6 +70,19 @@
name: "BUILD_BROKEN_USES_NETWORK",
behavior: DefaultDeprecated,
},
+ {
+ name: "BUILD_BROKEN_USES_BUILD_COPY_HEADERS",
+ behavior: DefaultTrue,
+ warnings: []string{
+ "COPY_HEADERS has been deprecated",
+ "COPY_HEADERS is deprecated",
+ },
+ },
+}
+
+type Branch struct {
+ Settings []Setting
+ Logs []ProductLog
}
type ProductBranch struct {
@@ -82,35 +97,48 @@
}
type Log struct {
- BuildBroken []*bool
- HasBroken []bool
+ WarningModuleTypes []string
+ ErrorModuleTypes []string
+
+ BuildBroken map[string]*bool
+ HasBroken map[string]int
}
func Merge(l, l2 Log) Log {
- if len(l.BuildBroken) == 0 {
- l.BuildBroken = make([]*bool, len(buildBrokenSettings))
+ if l.BuildBroken == nil {
+ l.BuildBroken = map[string]*bool{}
}
- if len(l.HasBroken) == 0 {
- l.HasBroken = make([]bool, len(buildBrokenSettings))
+ if l.HasBroken == nil {
+ l.HasBroken = map[string]int{}
}
- if len(l.BuildBroken) != len(l2.BuildBroken) || len(l.HasBroken) != len(l2.HasBroken) {
- panic("mis-matched logs")
- }
-
- for i, v := range l.BuildBroken {
+ for n, v := range l.BuildBroken {
if v == nil {
- l.BuildBroken[i] = l2.BuildBroken[i]
+ l.BuildBroken[n] = l2.BuildBroken[n]
}
}
- for i := range l.HasBroken {
- l.HasBroken[i] = l.HasBroken[i] || l2.HasBroken[i]
+ for n, v := range l2.BuildBroken {
+ if _, ok := l.BuildBroken[n]; !ok {
+ l.BuildBroken[n] = v
+ }
+ }
+
+ for n := range l.HasBroken {
+ if l.HasBroken[n] < l2.HasBroken[n] {
+ l.HasBroken[n] = l2.HasBroken[n]
+ }
+ }
+ for n := range l2.HasBroken {
+ if _, ok := l.HasBroken[n]; !ok {
+ l.HasBroken[n] = l2.HasBroken[n]
+ }
}
return l
}
-func PrintResults(products []ProductLog) {
+func PrintResults(branch Branch) {
+ products := branch.Logs
devices := map[string]Log{}
deviceNames := []string{}
@@ -124,39 +152,48 @@
sort.Strings(deviceNames)
- for i, setting := range buildBrokenSettings {
+ for _, setting := range branch.Settings {
printed := false
+ n := setting.name
for _, device := range deviceNames {
log := devices[device]
if setting.behavior == DefaultTrue {
- if log.BuildBroken[i] == nil || *log.BuildBroken[i] == false {
- if log.HasBroken[i] {
+ if log.BuildBroken[n] == nil || *log.BuildBroken[n] == false {
+ if log.HasBroken[n] > 0 {
printed = true
- fmt.Printf(" %s needs to set %s := true\n", device, setting.name)
+ plural := ""
+ if log.HasBroken[n] > 1 {
+ plural = "s"
+ }
+ fmt.Printf(" %s needs to set %s := true (%d instance%s)\n", device, setting.name, log.HasBroken[n], plural)
}
- } else if !log.HasBroken[i] {
+ } else if log.HasBroken[n] == 0 {
printed = true
fmt.Printf(" %s sets %s := true, but does not need it\n", device, setting.name)
}
} else if setting.behavior == DefaultFalse {
- if log.BuildBroken[i] == nil {
+ if log.BuildBroken[n] == nil {
// Nothing to be done
- } else if *log.BuildBroken[i] == false {
+ } else if *log.BuildBroken[n] == false {
printed = true
fmt.Printf(" %s sets %s := false, which is the default and can be removed\n", device, setting.name)
- } else if !log.HasBroken[i] {
+ } else if log.HasBroken[n] == 0 {
printed = true
fmt.Printf(" %s sets %s := true, but does not need it\n", device, setting.name)
}
} else if setting.behavior == DefaultDeprecated {
- if log.BuildBroken[i] != nil {
+ if log.BuildBroken[n] != nil {
printed = true
- if log.HasBroken[i] {
- fmt.Printf(" %s sets %s := %v, which is deprecated, but has failures\n", device, setting.name, *log.BuildBroken[i])
+ if log.HasBroken[n] > 0 {
+ plural := ""
+ if log.HasBroken[n] > 1 {
+ plural = "s"
+ }
+ fmt.Printf(" %s sets %s := %v, which is deprecated, but has %d failure%s\n", device, setting.name, *log.BuildBroken[n], log.HasBroken[n], plural)
} else {
- fmt.Printf(" %s sets %s := %v, which is deprecated and can be removed\n", device, setting.name, *log.BuildBroken[i])
+ fmt.Printf(" %s sets %s := %v, which is deprecated and can be removed\n", device, setting.name, *log.BuildBroken[n])
}
}
}
@@ -168,17 +205,45 @@
}
}
-func ParseBranch(name string) []ProductLog {
+func ParseBranch(name string) Branch {
products, err := filepath.Glob(filepath.Join(name, "*"))
if err != nil {
log.Fatal(err)
}
- ret := []ProductLog{}
+ ret := Branch{Logs: []ProductLog{}}
for _, product := range products {
product = filepath.Base(product)
- ret = append(ret, ParseProduct(ProductBranch{Branch: name, Name: product}))
+ ret.Logs = append(ret.Logs, ParseProduct(ProductBranch{Branch: name, Name: product}))
+ }
+
+ ret.Settings = append(ret.Settings, buildBrokenSettings...)
+ if len(ret.Logs) > 0 {
+ for _, mtype := range ret.Logs[0].WarningModuleTypes {
+ if mtype == "BUILD_COPY_HEADERS" || mtype == "" {
+ continue
+ }
+ ret.Settings = append(ret.Settings, Setting{
+ name: "BUILD_BROKEN_USES_" + mtype,
+ behavior: DefaultTrue,
+ warnings: []string{mtype + " has been deprecated"},
+ })
+ }
+ for _, mtype := range ret.Logs[0].ErrorModuleTypes {
+ if mtype == "BUILD_COPY_HEADERS" || mtype == "" {
+ continue
+ }
+ ret.Settings = append(ret.Settings, Setting{
+ name: "BUILD_BROKEN_USES_" + mtype,
+ behavior: DefaultFalse,
+ warnings: []string{mtype + " has been deprecated"},
+ })
+ }
+ }
+
+ for _, productLog := range ret.Logs {
+ ScanProduct(ret.Settings, productLog)
}
return ret
}
@@ -192,15 +257,15 @@
ret := ProductLog{
ProductBranch: p,
Log: Log{
- BuildBroken: make([]*bool, len(buildBrokenSettings)),
- HasBroken: make([]bool, len(buildBrokenSettings)),
+ BuildBroken: map[string]*bool{},
+ HasBroken: map[string]int{},
},
}
lines := strings.Split(string(soongLog), "\n")
for _, line := range lines {
fields := strings.Split(line, " ")
- if len(fields) != 5 {
+ if len(fields) < 5 {
continue
}
@@ -208,30 +273,35 @@
ret.Device = fields[4]
}
+ if fields[3] == "DEFAULT_WARNING_BUILD_MODULE_TYPES" {
+ ret.WarningModuleTypes = fields[4:]
+ }
+ if fields[3] == "DEFAULT_ERROR_BUILD_MODULE_TYPES" {
+ ret.ErrorModuleTypes = fields[4:]
+ }
+
if strings.HasPrefix(fields[3], "BUILD_BROKEN_") {
- for i, setting := range buildBrokenSettings {
- if setting.name == fields[3] {
- ret.BuildBroken[i] = ParseBoolPtr(fields[4])
- }
- }
+ ret.BuildBroken[fields[3]] = ParseBoolPtr(fields[4])
}
}
- stdLog, err := ioutil.ReadFile(filepath.Join(p.Branch, p.Name, "std_full.log"))
+ return ret
+}
+
+func ScanProduct(settings []Setting, l ProductLog) {
+ stdLog, err := ioutil.ReadFile(filepath.Join(l.Branch, l.Name, "std_full.log"))
if err != nil {
log.Fatal(err)
}
stdStr := string(stdLog)
- for i, setting := range buildBrokenSettings {
+ for _, setting := range settings {
for _, warning := range setting.warnings {
if strings.Contains(stdStr, warning) {
- ret.HasBroken[i] = true
+ l.HasBroken[setting.name] += strings.Count(stdStr, warning)
}
}
}
-
- return ret
}
func ParseBoolPtr(str string) *bool {
diff --git a/scripts/generate-notice-files.py b/scripts/generate-notice-files.py
new file mode 100755
index 0000000..49011b2
--- /dev/null
+++ b/scripts/generate-notice-files.py
@@ -0,0 +1,267 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+Usage: generate-notice-files --text-output [plain text output file] \
+ --html-output [html output file] \
+ --xml-output [xml output file] \
+ -t [file title] -s [directory of notices]
+
+Generate the Android notice files, including both text and html files.
+
+-h to display this usage message and exit.
+"""
+from collections import defaultdict
+import argparse
+import hashlib
+import itertools
+import os
+import os.path
+import re
+import sys
+
+MD5_BLOCKSIZE = 1024 * 1024
+HTML_ESCAPE_TABLE = {
+ "&": "&",
+ '"': """,
+ "'": "'",
+ ">": ">",
+ "<": "<",
+ }
+
+def hexify(s):
+ return ("%02x"*len(s)) % tuple(map(ord, s))
+
+def md5sum(filename):
+ """Calculate an MD5 of the file given by FILENAME,
+ and return hex digest as a string.
+ Output should be compatible with md5sum command"""
+
+ f = open(filename, "rb")
+ sum = hashlib.md5()
+ while 1:
+ block = f.read(MD5_BLOCKSIZE)
+ if not block:
+ break
+ sum.update(block)
+ f.close()
+ return hexify(sum.digest())
+
+
+def html_escape(text):
+ """Produce entities within text."""
+ return "".join(HTML_ESCAPE_TABLE.get(c,c) for c in text)
+
+HTML_OUTPUT_CSS="""
+<style type="text/css">
+body { padding: 0; font-family: sans-serif; }
+.same-license { background-color: #eeeeee; border-top: 20px solid white; padding: 10px; }
+.label { font-weight: bold; }
+.file-list { margin-left: 1em; color: blue; }
+</style>
+"""
+
+def combine_notice_files_html(file_hash, input_dir, output_filename):
+ """Combine notice files in FILE_HASH and output a HTML version to OUTPUT_FILENAME."""
+
+ SRC_DIR_STRIP_RE = re.compile(input_dir + "(/.*).txt")
+
+ # Set up a filename to row id table (anchors inside tables don't work in
+ # most browsers, but href's to table row ids do)
+ id_table = {}
+ id_count = 0
+ for value in file_hash:
+ for filename in value:
+ id_table[filename] = id_count
+ id_count += 1
+
+ # Open the output file, and output the header pieces
+ output_file = open(output_filename, "wb")
+
+ print >> output_file, "<html><head>"
+ print >> output_file, HTML_OUTPUT_CSS
+ print >> output_file, '</head><body topmargin="0" leftmargin="0" rightmargin="0" bottommargin="0">'
+
+ # Output our table of contents
+ print >> output_file, '<div class="toc">'
+ print >> output_file, "<ul>"
+
+ # Flatten the list of lists into a single list of filenames
+ sorted_filenames = sorted(itertools.chain.from_iterable(file_hash))
+
+ # Print out a nice table of contents
+ for filename in sorted_filenames:
+ stripped_filename = SRC_DIR_STRIP_RE.sub(r"\1", filename)
+ print >> output_file, '<li><a href="#id%d">%s</a></li>' % (id_table.get(filename), stripped_filename)
+
+ print >> output_file, "</ul>"
+ print >> output_file, "</div><!-- table of contents -->"
+ # Output the individual notice file lists
+ print >>output_file, '<table cellpadding="0" cellspacing="0" border="0">'
+ for value in file_hash:
+ print >> output_file, '<tr id="id%d"><td class="same-license">' % id_table.get(value[0])
+ print >> output_file, '<div class="label">Notices for file(s):</div>'
+ print >> output_file, '<div class="file-list">'
+ for filename in value:
+ print >> output_file, "%s <br/>" % (SRC_DIR_STRIP_RE.sub(r"\1", filename))
+ print >> output_file, "</div><!-- file-list -->"
+ print >> output_file
+ print >> output_file, '<pre class="license-text">'
+ print >> output_file, html_escape(open(value[0]).read())
+ print >> output_file, "</pre><!-- license-text -->"
+ print >> output_file, "</td></tr><!-- same-license -->"
+ print >> output_file
+ print >> output_file
+ print >> output_file
+
+ # Finish off the file output
+ print >> output_file, "</table>"
+ print >> output_file, "</body></html>"
+ output_file.close()
+
+def combine_notice_files_text(file_hash, input_dir, output_filename, file_title):
+ """Combine notice files in FILE_HASH and output a text version to OUTPUT_FILENAME."""
+
+ SRC_DIR_STRIP_RE = re.compile(input_dir + "(/.*).txt")
+ output_file = open(output_filename, "wb")
+ print >> output_file, file_title
+ for value in file_hash:
+ print >> output_file, "============================================================"
+ print >> output_file, "Notices for file(s):"
+ for filename in value:
+ print >> output_file, SRC_DIR_STRIP_RE.sub(r"\1", filename)
+ print >> output_file, "------------------------------------------------------------"
+ print >> output_file, open(value[0]).read()
+ output_file.close()
+
+def combine_notice_files_xml(files_with_same_hash, input_dir, output_filename):
+ """Combine notice files in FILE_HASH and output a XML version to OUTPUT_FILENAME."""
+
+ SRC_DIR_STRIP_RE = re.compile(input_dir + "(/.*).txt")
+
+ # Set up a filename to row id table (anchors inside tables don't work in
+ # most browsers, but href's to table row ids do)
+ id_table = {}
+ for file_key in files_with_same_hash.keys():
+ for filename in files_with_same_hash[file_key]:
+ id_table[filename] = file_key
+
+ # Open the output file, and output the header pieces
+ output_file = open(output_filename, "wb")
+
+ print >> output_file, '<?xml version="1.0" encoding="utf-8"?>'
+ print >> output_file, "<licenses>"
+
+ # Flatten the list of lists into a single list of filenames
+ sorted_filenames = sorted(id_table.keys())
+
+ # Print out a nice table of contents
+ for filename in sorted_filenames:
+ stripped_filename = SRC_DIR_STRIP_RE.sub(r"\1", filename)
+ print >> output_file, '<file-name contentId="%s">%s</file-name>' % (id_table.get(filename), stripped_filename)
+
+ print >> output_file
+ print >> output_file
+
+ processed_file_keys = []
+ # Output the individual notice file lists
+ for filename in sorted_filenames:
+ file_key = id_table.get(filename)
+ if file_key in processed_file_keys:
+ continue
+ processed_file_keys.append(file_key)
+
+ print >> output_file, '<file-content contentId="%s"><![CDATA[%s]]></file-content>' % (file_key, html_escape(open(filename).read()))
+ print >> output_file
+
+ # Finish off the file output
+ print >> output_file, "</licenses>"
+ output_file.close()
+
+def get_args():
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '--text-output', required=True,
+ help='The text output file path.')
+ parser.add_argument(
+ '--html-output',
+ help='The html output file path.')
+ parser.add_argument(
+ '--xml-output',
+ help='The xml output file path.')
+ parser.add_argument(
+ '-t', '--title', required=True,
+ help='The file title.')
+ parser.add_argument(
+ '-s', '--source-dir', required=True,
+ help='The directory containing notices.')
+ parser.add_argument(
+ '-i', '--included-subdirs', action='append',
+ help='The sub directories which should be included.')
+ parser.add_argument(
+ '-e', '--excluded-subdirs', action='append',
+ help='The sub directories which should be excluded.')
+ return parser.parse_args()
+
+def main(argv):
+ args = get_args()
+
+ txt_output_file = args.text_output
+ html_output_file = args.html_output
+ xml_output_file = args.xml_output
+ file_title = args.title
+ included_subdirs = []
+ excluded_subdirs = []
+ if args.included_subdirs is not None:
+ included_subdirs = args.included_subdirs
+ if args.excluded_subdirs is not None:
+ excluded_subdirs = args.excluded_subdirs
+
+ # Find all the notice files and md5 them
+ input_dir = os.path.normpath(args.source_dir)
+ files_with_same_hash = defaultdict(list)
+ for root, dir, files in os.walk(input_dir):
+ for file in files:
+ matched = True
+ if len(included_subdirs) > 0:
+ matched = False
+ for subdir in included_subdirs:
+ if (root == (input_dir + '/' + subdir) or
+ root.startswith(input_dir + '/' + subdir + '/')):
+ matched = True
+ break
+ elif len(excluded_subdirs) > 0:
+ for subdir in excluded_subdirs:
+ if (root == (input_dir + '/' + subdir) or
+ root.startswith(input_dir + '/' + subdir + '/')):
+ matched = False
+ break
+ if matched and file.endswith(".txt"):
+ filename = os.path.join(root, file)
+ file_md5sum = md5sum(filename)
+ files_with_same_hash[file_md5sum].append(filename)
+
+ filesets = [sorted(files_with_same_hash[md5]) for md5 in sorted(files_with_same_hash.keys())]
+
+ combine_notice_files_text(filesets, input_dir, txt_output_file, file_title)
+
+ if html_output_file is not None:
+ combine_notice_files_html(filesets, input_dir, html_output_file)
+
+ if xml_output_file is not None:
+ combine_notice_files_xml(files_with_same_hash, input_dir, xml_output_file)
+
+if __name__ == "__main__":
+ main(sys.argv)
diff --git a/scripts/mergenotice.py b/scripts/mergenotice.py
index 407ae8c..fe99073 100755
--- a/scripts/mergenotice.py
+++ b/scripts/mergenotice.py
@@ -16,7 +16,7 @@
#
"""
Merges input notice files to the output file while ignoring duplicated files
-This script shouldn't be confused with build/make/tools/generate-notice-files.py
+This script shouldn't be confused with build/soong/scripts/generate-notice-files.py
which is responsible for creating the final notice file for all artifacts
installed. This script has rather limited scope; it is meant to create a merged
notice file for a set of modules that are packaged together, e.g. in an APEX.
diff --git a/sdk/bp.go b/sdk/bp.go
index c2a75e4..68fe7ab 100644
--- a/sdk/bp.go
+++ b/sdk/bp.go
@@ -35,7 +35,7 @@
func (s *bpPropertySet) AddProperty(name string, value interface{}) {
if s.properties[name] != nil {
- panic("Property %q already exists in property set")
+ panic(fmt.Sprintf("Property %q already exists in property set", name))
}
s.properties[name] = value
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index ecb1da0..45b548c 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -17,6 +17,7 @@
import (
"testing"
+ "android/soong/android"
"android/soong/cc"
)
@@ -54,7 +55,7 @@
arm64Output := result.Module("sdkmember", "android_arm64_armv8-a_shared").(*cc.Module).OutputFile()
var inputs []string
- buildParams := result.Module("mysdk", "android_common").BuildParamsForTests()
+ buildParams := result.Module("mysdk", android.CommonOS.Name).BuildParamsForTests()
for _, bp := range buildParams {
if bp.Input != nil {
inputs = append(inputs, bp.Input.String())
@@ -250,7 +251,7 @@
}
`)
- result.CheckSnapshot("mysdk", "android_common", "",
+ result.CheckSnapshot("mysdk", "",
checkAllCopyRules(`
include/Test.h -> include/include/Test.h
.intermediates/mynativelib1/android_arm64_armv8-a_shared/mynativelib1.so -> arm64/lib/mynativelib1.so
@@ -287,7 +288,7 @@
}
`)
- result.CheckSnapshot("mysdk", "android_common", "",
+ result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -356,7 +357,7 @@
}
`)
- result.CheckSnapshot("mymodule_exports", "android_common", "",
+ result.CheckSnapshot("mymodule_exports", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -422,7 +423,7 @@
}
`)
- result.CheckSnapshot("mysdk", "android_common", "",
+ result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -510,7 +511,7 @@
}
`)
- result.CheckSnapshot("mysdk", "linux_glibc_common", "",
+ result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -597,7 +598,7 @@
}
`)
- result.CheckSnapshot("myexports", "android_common", "",
+ result.CheckSnapshot("myexports", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -685,7 +686,7 @@
}
`)
- result.CheckSnapshot("myexports", "linux_glibc_common", "",
+ result.CheckSnapshot("myexports", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -784,7 +785,7 @@
}
`)
- result.CheckSnapshot("myexports", "linux_glibc_common", "",
+ result.CheckSnapshot("myexports", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -856,7 +857,7 @@
}
`)
- result.CheckSnapshot("mysdk", "android_common", "",
+ result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -909,7 +910,7 @@
}
`)
- result.CheckSnapshot("mysdk", "linux_glibc_common", "",
+ result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
diff --git a/sdk/exports_test.go b/sdk/exports_test.go
index b905d71..20e2521 100644
--- a/sdk/exports_test.go
+++ b/sdk/exports_test.go
@@ -42,7 +42,7 @@
"package/Android.bp": []byte(packageBp),
})
- result.CheckSnapshot("myexports", "android_common", "package",
+ result.CheckSnapshot("myexports", "package",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 0737e5e..9046eec 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -141,7 +141,7 @@
}
`)
- result.CheckSnapshot("mysdk", "android_common", "",
+ result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -196,7 +196,7 @@
}
`)
- result.CheckSnapshot("mysdk", "linux_glibc_common", "",
+ result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -250,7 +250,7 @@
}
`)
- result.CheckSnapshot("myexports", "android_common", "",
+ result.CheckSnapshot("myexports", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -305,7 +305,7 @@
}
`)
- result.CheckSnapshot("myexports", "linux_glibc_common", "",
+ result.CheckSnapshot("myexports", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -356,7 +356,7 @@
}
`)
- result.CheckSnapshot("myexports", "android_common", "",
+ result.CheckSnapshot("myexports", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -409,7 +409,7 @@
}
`)
- result.CheckSnapshot("myexports", "linux_glibc_common", "",
+ result.CheckSnapshot("myexports", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -503,7 +503,7 @@
}
`)
- result.CheckSnapshot("myexports", "android_common", "",
+ result.CheckSnapshot("myexports", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -526,7 +526,7 @@
`),
checkAllCopyRules(""),
- checkMergeZip(".intermediates/myexports/android_common/tmp/java/myjavaapistubs_stubs_sources.zip"),
+ checkMergeZip(".intermediates/myexports/common_os/tmp/java/myjavaapistubs_stubs_sources.zip"),
)
}
@@ -552,7 +552,7 @@
}
`)
- result.CheckSnapshot("myexports", "linux_glibc_common", "",
+ result.CheckSnapshot("myexports", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -580,7 +580,7 @@
}
`),
checkAllCopyRules(""),
- checkMergeZip(".intermediates/myexports/linux_glibc_common/tmp/java/myjavaapistubs_stubs_sources.zip"),
+ checkMergeZip(".intermediates/myexports/common_os/tmp/java/myjavaapistubs_stubs_sources.zip"),
)
}
@@ -612,7 +612,7 @@
}
`)
- result.CheckSnapshot("mysdk", "android_common", "",
+ result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -702,7 +702,7 @@
}
`)
- result.CheckSnapshot("mysdk", "linux_glibc_common", "",
+ result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
diff --git a/sdk/sdk.go b/sdk/sdk.go
index c194ac1..14e44bf 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -53,6 +53,13 @@
// The set of exported members.
exportedMembers map[string]struct{}
+ // Information about the OsType specific member variants associated with this variant.
+ //
+ // Set by OsType specific variants when their GenerateAndroidBuildActions is invoked
+ // and used by the CommonOS variant when its GenerateAndroidBuildActions is invoked, which
+ // is guaranteed to occur afterwards.
+ memberRefs []sdkMemberRef
+
properties sdkProperties
snapshotFile android.OptionalPath
@@ -201,7 +208,7 @@
// properties for the member type specific list properties.
s.dynamicMemberTypeListProperties = s.dynamicSdkMemberTypes.createMemberListProperties()
s.AddProperties(&s.properties, s.dynamicMemberTypeListProperties)
- android.InitAndroidMultiTargetsArchModule(s, android.HostAndDeviceSupported, android.MultilibCommon)
+ android.InitCommonOSAndroidMultiTargetsArchModule(s, android.HostAndDeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(s)
android.AddLoadHook(s, func(ctx android.LoadHookContext) {
type props struct {
@@ -252,10 +259,29 @@
}
func (s *sdk) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- if !s.snapshot() {
+ if s.snapshot() {
// We don't need to create a snapshot out of sdk_snapshot.
// That doesn't make sense. We need a snapshot to create sdk_snapshot.
- s.snapshotFile = android.OptionalPathForPath(s.buildSnapshot(ctx))
+ return
+ }
+
+ // This method is guaranteed to be called on OsType specific variants before it is called
+ // on their corresponding CommonOS variant.
+ if !s.IsCommonOSVariant() {
+ // Collect the OsType specific members are add them to the OsType specific variant.
+ s.memberRefs = s.collectMembers(ctx)
+ } else {
+ // Get the OsType specific variants on which the CommonOS depends.
+ osSpecificVariants := android.GetOsSpecificVariantsOfCommonOSVariant(ctx)
+ var sdkVariants []*sdk
+ for _, m := range osSpecificVariants {
+ if sdkVariant, ok := m.(*sdk); ok {
+ sdkVariants = append(sdkVariants, sdkVariant)
+ }
+ }
+
+ // Generate the snapshot from the member info.
+ s.snapshotFile = android.OptionalPathForPath(s.buildSnapshot(ctx, sdkVariants))
}
}
@@ -320,7 +346,8 @@
// Step 1: create dependencies from an SDK module to its members.
func memberMutator(mctx android.BottomUpMutatorContext) {
if s, ok := mctx.Module().(*sdk); ok {
- if s.Enabled() {
+ // Add dependencies from enabled and non CommonOS variants to the sdk member variants.
+ if s.Enabled() && !s.IsCommonOSVariant() {
for _, memberListProperty := range s.memberListProperties() {
names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
if len(names) > 0 {
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index 934bdae..d06401a 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -145,7 +145,7 @@
"package/Android.bp": []byte(packageBp),
})
- result.CheckSnapshot("mysdk", "android_common", "package",
+ result.CheckSnapshot("mysdk", "package",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
diff --git a/sdk/testing.go b/sdk/testing.go
index 7352c74..3ae8b5d 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -188,15 +188,20 @@
buildParams := sdk.BuildParamsForTests()
copyRules := &strings.Builder{}
+ snapshotDirPrefix := sdk.builderForTests.snapshotDir.String() + "/"
for _, bp := range buildParams {
switch bp.Rule.String() {
case android.Cp.String():
- // Get source relative to build directory.
- src := android.NormalizePathForTesting(bp.Input)
- // Get destination relative to the snapshot root
- dest := bp.Output.Rel()
- _, _ = fmt.Fprintf(copyRules, "%s -> %s\n", src, dest)
- info.snapshotContents = append(info.snapshotContents, dest)
+ output := bp.Output
+ // Only check copies into the snapshot directory.
+ if strings.HasPrefix(output.String(), snapshotDirPrefix) {
+ // Get source relative to build directory.
+ src := android.NormalizePathForTesting(bp.Input)
+ // Get destination relative to the snapshot root
+ dest := output.Rel()
+ _, _ = fmt.Fprintf(copyRules, "%s -> %s\n", src, dest)
+ info.snapshotContents = append(info.snapshotContents, dest)
+ }
case repackageZip.String():
// Add the destdir to the snapshot contents as that is effectively where
@@ -246,9 +251,12 @@
// Takes a list of functions which check different facets of the snapshot build rules.
// Allows each test to customize what is checked without duplicating lots of code
// or proliferating check methods of different flavors.
-func (r *testSdkResult) CheckSnapshot(name string, variant string, dir string, checkers ...snapshotBuildInfoChecker) {
+func (r *testSdkResult) CheckSnapshot(name string, dir string, checkers ...snapshotBuildInfoChecker) {
r.t.Helper()
+ // The sdk CommonOS variant is always responsible for generating the snapshot.
+ variant := android.CommonOS.Name
+
sdk := r.Module(name, variant).(*sdk)
snapshotBuildInfo := r.getSdkSnapshotBuildInfo(sdk)
diff --git a/sdk/update.go b/sdk/update.go
index d211e80..087b8bc 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -104,18 +104,9 @@
// Collect all the members.
//
-// The members are first grouped by type and then grouped by name. The order of
-// the types is the order they are referenced in android.SdkMemberTypesRegistry.
-// The names are in the order in which the dependencies were added.
-//
-// Returns the members as well as the multilib setting to use.
-func (s *sdk) collectMembers(ctx android.ModuleContext) ([]*sdkMember, string) {
- byType := make(map[android.SdkMemberType][]*sdkMember)
- byName := make(map[string]*sdkMember)
-
- lib32 := false // True if any of the members have 32 bit version.
- lib64 := false // True if any of the members have 64 bit version.
-
+// Returns a list containing type (extracted from the dependency tag) and the variant.
+func (s *sdk) collectMembers(ctx android.ModuleContext) []sdkMemberRef {
+ var memberRefs []sdkMemberRef
ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
tag := ctx.OtherModuleDependencyTag(child)
if memberTag, ok := tag.(android.SdkMemberTypeDependencyTag); ok {
@@ -126,24 +117,7 @@
ctx.ModuleErrorf("module %q is not valid in property %s", ctx.OtherModuleName(child), memberType.SdkPropertyName())
}
- name := ctx.OtherModuleName(child)
- member := byName[name]
- if member == nil {
- member = &sdkMember{memberType: memberType, name: name}
- byName[name] = member
- byType[memberType] = append(byType[memberType], member)
- }
-
- multilib := child.Target().Arch.ArchType.Multilib
- if multilib == "lib32" {
- lib32 = true
- } else if multilib == "lib64" {
- lib64 = true
- }
-
- // Only append new variants to the list. This is needed because a member can be both
- // exported by the sdk and also be a transitive sdk member.
- member.variants = appendUniqueVariants(member.variants, child.(android.SdkAware))
+ memberRefs = append(memberRefs, sdkMemberRef{memberType, child.(android.SdkAware)})
// If the member type supports transitive sdk members then recurse down into
// its dependencies, otherwise exit traversal.
@@ -153,6 +127,47 @@
return false
})
+ return memberRefs
+}
+
+// Organize the members.
+//
+// The members are first grouped by type and then grouped by name. The order of
+// the types is the order they are referenced in android.SdkMemberTypesRegistry.
+// The names are in the order in which the dependencies were added.
+//
+// Returns the members as well as the multilib setting to use.
+func (s *sdk) organizeMembers(ctx android.ModuleContext, memberRefs []sdkMemberRef) ([]*sdkMember, string) {
+ byType := make(map[android.SdkMemberType][]*sdkMember)
+ byName := make(map[string]*sdkMember)
+
+ lib32 := false // True if any of the members have 32 bit version.
+ lib64 := false // True if any of the members have 64 bit version.
+
+ for _, memberRef := range memberRefs {
+ memberType := memberRef.memberType
+ variant := memberRef.variant
+
+ name := ctx.OtherModuleName(variant)
+ member := byName[name]
+ if member == nil {
+ member = &sdkMember{memberType: memberType, name: name}
+ byName[name] = member
+ byType[memberType] = append(byType[memberType], member)
+ }
+
+ multilib := variant.Target().Arch.ArchType.Multilib
+ if multilib == "lib32" {
+ lib32 = true
+ } else if multilib == "lib64" {
+ lib64 = true
+ }
+
+ // Only append new variants to the list. This is needed because a member can be both
+ // exported by the sdk and also be a transitive sdk member.
+ member.variants = appendUniqueVariants(member.variants, variant)
+ }
+
var members []*sdkMember
for _, memberListProperty := range s.memberListProperties() {
membersOfType := byType[memberListProperty.memberType]
@@ -207,7 +222,13 @@
// buildSnapshot is the main function in this source file. It creates rules to copy
// the contents (header files, stub libraries, etc) into the zip file.
-func (s *sdk) buildSnapshot(ctx android.ModuleContext) android.OutputPath {
+func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) android.OutputPath {
+
+ var memberRefs []sdkMemberRef
+ for _, sdkVariant := range sdkVariants {
+ memberRefs = append(memberRefs, sdkVariant.memberRefs...)
+ }
+
snapshotDir := android.PathForModuleOut(ctx, "snapshot")
bp := newGeneratedFile(ctx, "snapshot", "Android.bp")
@@ -228,7 +249,7 @@
}
s.builderForTests = builder
- members, multilib := s.collectMembers(ctx)
+ members, multilib := s.organizeMembers(ctx, memberRefs)
for _, member := range members {
member.memberType.BuildSnapshot(ctx, builder, member)
}
@@ -592,6 +613,11 @@
return references
}
+type sdkMemberRef struct {
+ memberType android.SdkMemberType
+ variant android.SdkAware
+}
+
var _ android.SdkMember = (*sdkMember)(nil)
type sdkMember struct {
diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go
index 11ff667..2de772b 100644
--- a/ui/build/sandbox_linux.go
+++ b/ui/build/sandbox_linux.go
@@ -90,10 +90,7 @@
return
}
- c.ctx.Println("Build sandboxing disabled due to nsjail error. This may become fatal in the future.")
- c.ctx.Println("Please let us know why nsjail doesn't work in your environment at:")
- c.ctx.Println(" https://groups.google.com/forum/#!forum/android-building")
- c.ctx.Println(" https://issuetracker.google.com/issues/new?component=381517")
+ c.ctx.Println("Build sandboxing disabled due to nsjail error.")
for _, line := range strings.Split(strings.TrimSpace(string(data)), "\n") {
c.ctx.Verboseln(line)