Merge "Add keymint to vndk."
diff --git a/Android.bp b/Android.bp
index 3075d67..e7a5de2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -46,7 +46,9 @@
name: "libatomic",
defaults: ["linux_bionic_supported"],
vendor_available: true,
+ product_available: true,
ramdisk_available: true,
+ vendor_ramdisk_available: true,
recovery_available: true,
native_bridge_supported: true,
@@ -70,6 +72,7 @@
name: "libgcc",
defaults: ["linux_bionic_supported"],
vendor_available: true,
+ product_available: true,
recovery_available: true,
native_bridge_supported: true,
@@ -93,7 +96,9 @@
name: "libgcc_stripped",
defaults: ["linux_bionic_supported"],
vendor_available: true,
+ product_available: true,
ramdisk_available: true,
+ vendor_ramdisk_available: true,
recovery_available: true,
native_bridge_supported: true,
sdk_version: "current",
diff --git a/OWNERS b/OWNERS
index 8355d10..3a5a8a7 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,13 +1,20 @@
-per-file * = asmundak@google.com
-per-file * = ccross@android.com
-per-file * = dwillemsen@google.com
-per-file * = eakammer@google.com
-per-file * = jungjw@google.com
-per-file * = patricearruda@google.com
-per-file * = paulduffin@google.com
+# This file is included by several other projects as the list of people
+# approving build related projects.
-per-file ndk_*.go = danalbert@google.com
-per-file clang.go,global.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
-per-file tidy.go = srhines@google.com, chh@google.com
-per-file lto.go,pgo.go = srhines@google.com, pirama@google.com, yikong@google.com
-per-file docs/map_files.md = danalbert@google.com, enh@google.com, jiyong@google.com
+ahumesky@google.com
+asmundak@google.com
+ccross@android.com
+cparsons@google.com
+dwillemsen@google.com
+eakammer@google.com
+jingwen@google.com
+joeo@google.com
+jungjw@google.com
+lberki@google.com
+patricearruda@google.com
+ruperts@google.com
+
+# To expedite LON reviews
+hansson@google.com
+paulduffin@google.com
+
diff --git a/android/Android.bp b/android/Android.bp
index a1b5159..7bd1450 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -15,7 +15,7 @@
"apex.go",
"api_levels.go",
"arch.go",
- "bazel_overlay.go",
+ "bazel_handler.go",
"config.go",
"csuite_config.go",
"defaults.go",
@@ -43,6 +43,7 @@
"prebuilt.go",
"prebuilt_build_tool.go",
"proto.go",
+ "queryview.go",
"register.go",
"rule_builder.go",
"sandbox.go",
@@ -54,7 +55,6 @@
"util.go",
"variable.go",
"visibility.go",
- "vts_config.go",
"writedocs.go",
// Lock down environment access last
@@ -63,6 +63,7 @@
testSrcs: [
"android_test.go",
"androidmk_test.go",
+ "apex_test.go",
"arch_test.go",
"config_test.go",
"csuite_config_test.go",
@@ -82,6 +83,5 @@
"util_test.go",
"variable_test.go",
"visibility_test.go",
- "vts_config_test.go",
],
}
diff --git a/android/androidmk.go b/android/androidmk.go
index fafbfd6..cfd7c91 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -72,6 +72,7 @@
type AndroidMkEntries struct {
Class string
SubName string
+ OverrideName string
DistFiles TaggedDistFiles
OutputFile OptionalPath
Disabled bool
@@ -273,6 +274,9 @@
a.EntryMap = make(map[string][]string)
amod := mod.(Module).base()
name := amod.BaseModuleName()
+ if a.OverrideName != "" {
+ name = a.OverrideName
+ }
if a.Include == "" {
a.Include = "$(BUILD_PREBUILT)"
@@ -304,15 +308,16 @@
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 +364,11 @@
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 +570,11 @@
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 +643,21 @@
// 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/androidmk_test.go b/android/androidmk_test.go
index a558f45..10527b9 100644
--- a/android/androidmk_test.go
+++ b/android/androidmk_test.go
@@ -80,10 +80,10 @@
config := TestConfig(buildDir, nil, bp, nil)
config.inMake = true // Enable androidmk Singleton
- ctx := NewTestContext()
+ ctx := NewTestContext(config)
ctx.RegisterSingletonType("androidmk", AndroidMkSingleton)
ctx.RegisterModuleType("custom", customModuleFactory)
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
FailIfErrored(t, errs)
@@ -252,10 +252,10 @@
config := TestConfig(buildDir, nil, testCase.bp, nil)
config.inMake = true // Enable androidmk Singleton
- ctx := NewTestContext()
+ ctx := NewTestContext(config)
ctx.RegisterSingletonType("androidmk", AndroidMkSingleton)
ctx.RegisterModuleType("custom", customModuleFactory)
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
FailIfErrored(t, errs)
diff --git a/android/apex.go b/android/apex.go
index f857ec6..276f7a4 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -24,29 +24,66 @@
"github.com/google/blueprint"
)
-const (
- SdkVersion_Android10 = 29
+var (
+ SdkVersion_Android10 = uncheckedFinalApiLevel(29)
)
+// ApexInfo describes the metadata common to all modules in an apexBundle.
type ApexInfo struct {
- // Name of the apex variation that this module is mutated into
+ // Name of the apex variation that this module is mutated into, or "" for
+ // a platform variant. Note that a module can be included in multiple APEXes,
+ // in which case, the module is mutated into one or more variants, each of
+ // which is for one or more APEXes.
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
- InApexes []string
+ // True if the module comes from an updatable APEX.
+ Updatable bool
+ RequiredSdks SdkRefs
+
+ InApexes []string
+ ApexContents []*ApexContents
}
-func (i ApexInfo) mergedName() string {
- name := "apex" + strconv.Itoa(i.MinSdkVersion)
+var ApexInfoProvider = blueprint.NewMutatorProvider(ApexInfo{}, "apex")
+
+func (i ApexInfo) mergedName(ctx PathContext) 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 PathContext) ApiLevel {
+ return ApiLevelOrPanic(ctx, this.MinSdkVersionStr)
+}
+
+func (i ApexInfo) IsForPlatform() bool {
+ return i.ApexVariationName == ""
+}
+
+func (i ApexInfo) InApex(apex string) bool {
+ for _, a := range i.InApexes {
+ if a == apex {
+ return true
+ }
+ }
+ return false
+}
+
+// ApexTestForInfo stores the contents of APEXes for which this module is a test and thus has
+// access to APEX internals.
+type ApexTestForInfo struct {
+ ApexContents []*ApexContents
+}
+
+var ApexTestForInfoProvider = blueprint.NewMutatorProvider(ApexTestForInfo{}, "apex_test_for")
+
// 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 {
@@ -80,23 +117,18 @@
// Call this before apex.apexMutator is run.
BuildForApex(apex ApexInfo)
- // Returns the name of APEX variation that this module will be built for.
- // Empty string is returned when 'IsForPlatform() == true'. Note that a
- // module can beincluded in multiple APEXes, in which case, the module
- // is mutated into one or more variants, each of which is for one or
- // more APEXes. This method returns the name of the APEX variation of
- // the module.
+ // Returns true if this module is present in any APEXes
+ // directly or indirectly.
// Call this after apex.apexMutator is run.
- ApexVariationName() string
+ InAnyApex() bool
- // Returns the name of the APEX modules that this variant of this module
- // is present in.
+ // Returns true if this module is directly in any APEXes.
// Call this after apex.apexMutator is run.
- InApexes() []string
+ DirectlyInAnyApex() bool
- // Tests whether this module will be built for the platform or not.
- // This is a shortcut for ApexVariationName() == ""
- IsForPlatform() bool
+ // Returns true if any variant of this module is directly in any APEXes.
+ // Call this after apex.apexMutator is run.
+ AnyVariantDirectlyInAnyApex() bool
// Tests if this module could have APEX variants. APEX variants are
// created only for the modules that returns true here. This is useful
@@ -109,10 +141,6 @@
// libs.
IsInstallableToApex() bool
- // Mutate this module into one or more variants each of which is built
- // for an APEX marked via BuildForApex().
- CreateApexVariations(mctx BottomUpMutatorContext) []Module
-
// Tests if this module is available for the specified APEX or ":platform"
AvailableFor(what string) bool
@@ -126,14 +154,6 @@
// check-platform-availability mutator in the apex package.
SetNotAvailableForPlatform()
- // 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)
-
- // Tests if the module comes from an updatable APEX.
- Updatable() bool
-
// List of APEXes that this module tests. The module has access to
// the private part of the listed APEXes even when it is not included in the
// APEXes.
@@ -141,16 +161,11 @@
// 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.
UniqueApexVariations() bool
-
- // UpdateUniqueApexVariationsForDeps sets UniqueApexVariationsForDeps if any dependencies
- // that are in the same APEX have unique APEX variations so that the module can link against
- // the right variant.
- UpdateUniqueApexVariationsForDeps(mctx BottomUpMutatorContext)
}
type ApexProperties struct {
@@ -164,7 +179,21 @@
// Default is ["//apex_available:platform"].
Apex_available []string
- Info ApexInfo `blueprint:"mutated"`
+ // AnyVariantDirectlyInAnyApex is true in the primary variant of a module if _any_ variant
+ // of the module is directly in any apex. This includes host, arch, asan, etc. variants.
+ // It is unused in any variant that is not the primary variant.
+ // Ideally this wouldn't be used, as it incorrectly mixes arch variants if only one arch
+ // is in an apex, but a few places depend on it, for example when an ASAN variant is
+ // created before the apexMutator.
+ AnyVariantDirectlyInAnyApex bool `blueprint:"mutated"`
+
+ // DirectlyInAnyApex is true if any APEX variant (including the "" variant used for the
+ // platform) of this module is directly in any APEX.
+ DirectlyInAnyApex bool `blueprint:"mutated"`
+
+ // DirectlyInAnyApex is true if any APEX variant (including the "" variant used for the
+ // platform) of this module is directly or indirectly in any APEX.
+ InAnyApex bool `blueprint:"mutated"`
NotAvailableForPlatform bool `blueprint:"mutated"`
@@ -180,6 +209,15 @@
ExcludeFromApexContents()
}
+// Marker interface that identifies dependencies that should inherit the DirectlyInAnyApex
+// state from the parent to the child. For example, stubs libraries are marked as
+// DirectlyInAnyApex if their implementation is in an apex.
+type CopyDirectlyInAnyApexTag interface {
+ blueprint.DependencyTag
+
+ CopyDirectlyInAnyApex()
+}
+
// Provides default implementation for the ApexModule interface. APEX-aware
// modules are expected to include this struct and call InitApexModule().
type ApexModuleBase struct {
@@ -208,43 +246,6 @@
return false
}
-func (m *ApexModuleBase) UpdateUniqueApexVariationsForDeps(mctx BottomUpMutatorContext) {
- // anyInSameApex returns true if the two ApexInfo lists contain any values in an InApexes list
- // in common. It is used instead of DepIsInSameApex because it needs to determine if the dep
- // is in the same APEX due to being directly included, not only if it is included _because_ it
- // is a dependency.
- anyInSameApex := func(a, b []ApexInfo) bool {
- collectApexes := func(infos []ApexInfo) []string {
- var ret []string
- for _, info := range infos {
- ret = append(ret, info.InApexes...)
- }
- return ret
- }
-
- aApexes := collectApexes(a)
- bApexes := collectApexes(b)
- sort.Strings(bApexes)
- for _, aApex := range aApexes {
- index := sort.SearchStrings(bApexes, aApex)
- if index < len(bApexes) && bApexes[index] == aApex {
- return true
- }
- }
- return false
- }
-
- mctx.VisitDirectDeps(func(dep Module) {
- if depApexModule, ok := dep.(ApexModule); ok {
- if anyInSameApex(depApexModule.apexModuleBase().apexVariations, m.apexVariations) &&
- (depApexModule.UniqueApexVariations() ||
- depApexModule.apexModuleBase().ApexProperties.UniqueApexVariationsForDeps) {
- m.ApexProperties.UniqueApexVariationsForDeps = true
- }
- }
- })
-}
-
func (m *ApexModuleBase) BuildForApex(apex ApexInfo) {
m.apexVariationsLock.Lock()
defer m.apexVariationsLock.Unlock()
@@ -256,16 +257,16 @@
m.apexVariations = append(m.apexVariations, apex)
}
-func (m *ApexModuleBase) ApexVariationName() string {
- return m.ApexProperties.Info.ApexVariationName
+func (m *ApexModuleBase) DirectlyInAnyApex() bool {
+ return m.ApexProperties.DirectlyInAnyApex
}
-func (m *ApexModuleBase) InApexes() []string {
- return m.ApexProperties.Info.InApexes
+func (m *ApexModuleBase) AnyVariantDirectlyInAnyApex() bool {
+ return m.ApexProperties.AnyVariantDirectlyInAnyApex
}
-func (m *ApexModuleBase) IsForPlatform() bool {
- return m.ApexProperties.Info.ApexVariationName == ""
+func (m *ApexModuleBase) InAnyApex() bool {
+ return m.ApexProperties.InAnyApex
}
func (m *ApexModuleBase) CanHaveApexVariants() bool {
@@ -313,16 +314,6 @@
return true
}
-func (m *ApexModuleBase) ChooseSdkVersion(versionList []string, maxSdkVersion int) (string, error) {
- for i := range versionList {
- ver, _ := strconv.Atoi(versionList[len(versionList)-i-1])
- if ver <= maxSdkVersion {
- return versionList[len(versionList)-i-1], nil
- }
- }
- return "", fmt.Errorf("not found a version(<=%d) in versionList: %v", maxSdkVersion, versionList)
-}
-
func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
for _, n := range m.ApexProperties.Apex_available {
if n == AvailableToPlatform || n == AvailableToAnyApex || n == AvailableToGkiApex {
@@ -334,10 +325,6 @@
}
}
-func (m *ApexModuleBase) Updatable() bool {
- return m.ApexProperties.Info.Updatable
-}
-
type byApexName []ApexInfo
func (a byApexName) Len() int { return len(a) }
@@ -347,19 +334,21 @@
// 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 PathContext, 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].ApexContents = append(merged[index].ApexContents, apexInfo.ApexContents...)
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)
+ apexInfo.ApexContents = append([]*ApexContents(nil), apexInfo.ApexContents...)
merged = append(merged, apexInfo)
}
aliases = append(aliases, [2]string{apexName, mergedName})
@@ -367,17 +356,23 @@
return merged, aliases
}
-func (m *ApexModuleBase) CreateApexVariations(mctx BottomUpMutatorContext) []Module {
- if len(m.apexVariations) > 0 {
- m.checkApexAvailableProperty(mctx)
+func CreateApexVariations(mctx BottomUpMutatorContext, module ApexModule) []Module {
+ base := module.apexModuleBase()
+ if len(base.apexVariations) > 0 {
+ base.checkApexAvailableProperty(mctx)
var apexVariations []ApexInfo
var aliases [][2]string
- if !mctx.Module().(ApexModule).UniqueApexVariations() && !m.ApexProperties.UniqueApexVariationsForDeps {
- apexVariations, aliases = mergeApexVariations(m.apexVariations)
+ if !mctx.Module().(ApexModule).UniqueApexVariations() && !base.ApexProperties.UniqueApexVariationsForDeps {
+ apexVariations, aliases = mergeApexVariations(mctx, base.apexVariations)
} else {
- apexVariations = m.apexVariations
+ apexVariations = base.apexVariations
}
+ // base.apexVariations is only needed to propagate the list of apexes from
+ // apexDepsMutator to apexMutator. It is no longer accurate after
+ // mergeApexVariations, and won't be copied to all but the first created
+ // variant. Clear it so it doesn't accidentally get used later.
+ base.apexVariations = nil
sort.Sort(byApexName(apexVariations))
variations := []string{}
@@ -389,6 +384,16 @@
defaultVariation := ""
mctx.SetDefaultDependencyVariation(&defaultVariation)
+ var inApex ApexMembership
+ for _, a := range apexVariations {
+ for _, apexContents := range a.ApexContents {
+ inApex = inApex.merge(apexContents.contents[mctx.ModuleName()])
+ }
+ }
+
+ base.ApexProperties.InAnyApex = true
+ base.ApexProperties.DirectlyInAnyApex = inApex == directlyInApex
+
modules := mctx.CreateVariations(variations...)
for i, mod := range modules {
platformVariation := i == 0
@@ -399,7 +404,7 @@
mod.MakeUninstallable()
}
if !platformVariation {
- mod.(ApexModule).apexModuleBase().ApexProperties.Info = apexVariations[i-1]
+ mctx.SetVariationProvider(mod, ApexInfoProvider, apexVariations[i-1])
}
}
@@ -412,116 +417,139 @@
return nil
}
-var apexData OncePer
-var apexNamesMapMutex sync.Mutex
-var apexNamesKey = NewOnceKey("apexNames")
+// UpdateUniqueApexVariationsForDeps sets UniqueApexVariationsForDeps if any dependencies
+// that are in the same APEX have unique APEX variations so that the module can link against
+// the right variant.
+func UpdateUniqueApexVariationsForDeps(mctx BottomUpMutatorContext, am ApexModule) {
+ // anyInSameApex returns true if the two ApexInfo lists contain any values in an InApexes list
+ // in common. It is used instead of DepIsInSameApex because it needs to determine if the dep
+ // is in the same APEX due to being directly included, not only if it is included _because_ it
+ // is a dependency.
+ anyInSameApex := func(a, b []ApexInfo) bool {
+ collectApexes := func(infos []ApexInfo) []string {
+ var ret []string
+ for _, info := range infos {
+ ret = append(ret, info.InApexes...)
+ }
+ return ret
+ }
-// This structure maintains the global mapping in between modules and APEXes.
-// Examples:
-//
-// apexNamesMap()["foo"]["bar"] == true: module foo is directly depended on by APEX bar
-// apexNamesMap()["foo"]["bar"] == false: module foo is indirectly depended on by APEX bar
-// apexNamesMap()["foo"]["bar"] doesn't exist: foo is not built for APEX bar
-func apexNamesMap() map[string]map[string]bool {
- return apexData.Once(apexNamesKey, func() interface{} {
- return make(map[string]map[string]bool)
- }).(map[string]map[string]bool)
+ aApexes := collectApexes(a)
+ bApexes := collectApexes(b)
+ sort.Strings(bApexes)
+ for _, aApex := range aApexes {
+ index := sort.SearchStrings(bApexes, aApex)
+ if index < len(bApexes) && bApexes[index] == aApex {
+ return true
+ }
+ }
+ return false
+ }
+
+ mctx.VisitDirectDeps(func(dep Module) {
+ if depApexModule, ok := dep.(ApexModule); ok {
+ if anyInSameApex(depApexModule.apexModuleBase().apexVariations, am.apexModuleBase().apexVariations) &&
+ (depApexModule.UniqueApexVariations() ||
+ depApexModule.apexModuleBase().ApexProperties.UniqueApexVariationsForDeps) {
+ am.apexModuleBase().ApexProperties.UniqueApexVariationsForDeps = true
+ }
+ }
+ })
}
-// Update the map to mark that a module named moduleName is directly or indirectly
-// depended on by the specified APEXes. Directly depending means that a module
-// is explicitly listed in the build definition of the APEX via properties like
-// native_shared_libs, java_libs, etc.
-func UpdateApexDependency(apex ApexInfo, moduleName string, directDep bool) {
- apexNamesMapMutex.Lock()
- defer apexNamesMapMutex.Unlock()
- apexesForModule, ok := apexNamesMap()[moduleName]
- if !ok {
- apexesForModule = make(map[string]bool)
- apexNamesMap()[moduleName] = apexesForModule
+// UpdateDirectlyInAnyApex uses the final module to store if any variant of this
+// module is directly in any APEX, and then copies the final value to all the modules.
+// It also copies the DirectlyInAnyApex value to any direct dependencies with a
+// CopyDirectlyInAnyApexTag dependency tag.
+func UpdateDirectlyInAnyApex(mctx BottomUpMutatorContext, am ApexModule) {
+ base := am.apexModuleBase()
+ // Copy DirectlyInAnyApex and InAnyApex from any direct dependencies with a
+ // CopyDirectlyInAnyApexTag dependency tag.
+ mctx.VisitDirectDeps(func(dep Module) {
+ if _, ok := mctx.OtherModuleDependencyTag(dep).(CopyDirectlyInAnyApexTag); ok {
+ depBase := dep.(ApexModule).apexModuleBase()
+ base.ApexProperties.DirectlyInAnyApex = depBase.ApexProperties.DirectlyInAnyApex
+ base.ApexProperties.InAnyApex = depBase.ApexProperties.InAnyApex
+ }
+ })
+
+ if base.ApexProperties.DirectlyInAnyApex {
+ // Variants of a module are always visited sequentially in order, so it is safe to
+ // write to another variant of this module.
+ // For a BottomUpMutator the PrimaryModule() is visited first and FinalModule() is
+ // visited last.
+ mctx.FinalModule().(ApexModule).apexModuleBase().ApexProperties.AnyVariantDirectlyInAnyApex = true
}
- apexesForModule[apex.ApexVariationName] = apexesForModule[apex.ApexVariationName] || directDep
- for _, apexName := range apex.InApexes {
- apexesForModule[apexName] = apexesForModule[apex.ApexVariationName] || directDep
+
+ // If this is the FinalModule (last visited module) copy AnyVariantDirectlyInAnyApex to
+ // all the other variants
+ if am == mctx.FinalModule().(ApexModule) {
+ mctx.VisitAllModuleVariants(func(variant Module) {
+ variant.(ApexModule).apexModuleBase().ApexProperties.AnyVariantDirectlyInAnyApex =
+ base.ApexProperties.AnyVariantDirectlyInAnyApex
+ })
}
}
-// TODO(b/146393795): remove this when b/146393795 is fixed
-func ClearApexDependency() {
- m := apexNamesMap()
- for k := range m {
- delete(m, k)
+type ApexMembership int
+
+const (
+ notInApex ApexMembership = 0
+ indirectlyInApex = iota
+ directlyInApex
+)
+
+// Each apexBundle has an apexContents, and modules in that apex have a provider containing the
+// apexContents of each apexBundle they are part of.
+type ApexContents struct {
+ ApexName string
+ contents map[string]ApexMembership
+}
+
+func NewApexContents(name string, contents map[string]ApexMembership) *ApexContents {
+ return &ApexContents{
+ ApexName: name,
+ contents: contents,
}
}
-// Tests whether a module named moduleName is directly depended on by an APEX
-// named apexName.
-func DirectlyInApex(apexName string, moduleName string) bool {
- apexNamesMapMutex.Lock()
- defer apexNamesMapMutex.Unlock()
- if apexNamesForModule, ok := apexNamesMap()[moduleName]; ok {
- return apexNamesForModule[apexName]
+func (i ApexMembership) Add(direct bool) ApexMembership {
+ if direct || i == directlyInApex {
+ return directlyInApex
}
- return false
+ return indirectlyInApex
+}
+
+func (i ApexMembership) merge(other ApexMembership) ApexMembership {
+ if other == directlyInApex || i == directlyInApex {
+ return directlyInApex
+ }
+
+ if other == indirectlyInApex || i == indirectlyInApex {
+ return indirectlyInApex
+ }
+ return notInApex
+}
+
+func (ac *ApexContents) DirectlyInApex(name string) bool {
+ return ac.contents[name] == directlyInApex
+}
+
+func (ac *ApexContents) InApex(name string) bool {
+ return ac.contents[name] != notInApex
}
// Tests whether a module named moduleName is directly depended on by all APEXes
-// in a list of apexNames.
-func DirectlyInAllApexes(apexNames []string, moduleName string) bool {
- apexNamesMapMutex.Lock()
- defer apexNamesMapMutex.Unlock()
- for _, apexName := range apexNames {
- apexNamesForModule := apexNamesMap()[moduleName]
- if !apexNamesForModule[apexName] {
+// in an ApexInfo.
+func DirectlyInAllApexes(apexInfo ApexInfo, moduleName string) bool {
+ for _, contents := range apexInfo.ApexContents {
+ if !contents.DirectlyInApex(moduleName) {
return false
}
}
return true
}
-type hostContext interface {
- Host() bool
-}
-
-// Tests whether a module named moduleName is directly depended on by any APEX.
-func DirectlyInAnyApex(ctx hostContext, moduleName string) bool {
- if ctx.Host() {
- // Host has no APEX.
- return false
- }
- apexNamesMapMutex.Lock()
- defer apexNamesMapMutex.Unlock()
- if apexNames, ok := apexNamesMap()[moduleName]; ok {
- for an := range apexNames {
- if apexNames[an] {
- return true
- }
- }
- }
- return false
-}
-
-// Tests whether a module named module is depended on (including both
-// direct and indirect dependencies) by any APEX.
-func InAnyApex(moduleName string) bool {
- apexNamesMapMutex.Lock()
- defer apexNamesMapMutex.Unlock()
- apexNames, ok := apexNamesMap()[moduleName]
- return ok && len(apexNames) > 0
-}
-
-func GetApexesForModule(moduleName string) []string {
- ret := []string{}
- apexNamesMapMutex.Lock()
- defer apexNamesMapMutex.Unlock()
- if apexNames, ok := apexNamesMap()[moduleName]; ok {
- for an := range apexNames {
- ret = append(ret, an)
- }
- }
- return ret
-}
-
func InitApexModule(m ApexModule) {
base := m.apexModuleBase()
base.canHaveApexVariants = true
@@ -570,40 +598,32 @@
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
- ctx.Build(pctx, BuildParams{
- Rule: WriteFile,
- Description: "Full Dependency Info",
- Output: d.fullListPath,
- Args: map[string]string{
- "content": fullContent.String(),
- },
- })
+ WriteFileRule(ctx, d.fullListPath, fullContent.String())
d.flatListPath = PathForModuleOut(ctx, "depsinfo", "flatlist.txt").OutputPath
- ctx.Build(pctx, BuildParams{
- Rule: WriteFile,
- Description: "Flat Dependency Info",
- Output: d.flatListPath,
- Args: map[string]string{
- "content": flatContent.String(),
- },
- })
+ WriteFileRule(ctx, d.flatListPath, flatContent.String())
}
// 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 +692,7 @@
"statsd": 30,
"tensorflow_headers": 30,
"xz-java": 29,
-}
+})
// Function called while walking an APEX's payload dependencies.
//
@@ -686,7 +706,7 @@
}
// 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 +719,7 @@
// 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 +734,7 @@
}
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/apex_test.go b/android/apex_test.go
index db02833..512b50f 100644
--- a/android/apex_test.go
+++ b/android/apex_test.go
@@ -29,10 +29,10 @@
{
name: "single",
in: []ApexInfo{
- {"foo", 10000, false, nil, []string{"foo"}},
+ {"foo", "current", false, nil, []string{"foo"}, nil},
},
wantMerged: []ApexInfo{
- {"apex10000", 10000, false, nil, []string{"foo"}},
+ {"apex10000", "current", false, nil, []string{"foo"}, nil},
},
wantAliases: [][2]string{
{"foo", "apex10000"},
@@ -41,12 +41,11 @@
{
name: "merge",
in: []ApexInfo{
- {"foo", 10000, false, SdkRefs{{"baz", "1"}}, []string{"foo"}},
- {"bar", 10000, false, SdkRefs{{"baz", "1"}}, []string{"bar"}},
+ {"foo", "current", false, SdkRefs{{"baz", "1"}}, []string{"foo"}, nil},
+ {"bar", "current", false, SdkRefs{{"baz", "1"}}, []string{"bar"}, nil},
},
wantMerged: []ApexInfo{
- {"apex10000_baz_1", 10000, false, SdkRefs{{"baz", "1"}}, []string{"bar", "foo"}},
- },
+ {"apex10000_baz_1", "current", false, SdkRefs{{"baz", "1"}}, []string{"bar", "foo"}, nil}},
wantAliases: [][2]string{
{"bar", "apex10000_baz_1"},
{"foo", "apex10000_baz_1"},
@@ -55,12 +54,12 @@
{
name: "don't merge version",
in: []ApexInfo{
- {"foo", 10000, false, nil, []string{"foo"}},
- {"bar", 30, false, nil, []string{"bar"}},
+ {"foo", "current", false, nil, []string{"foo"}, nil},
+ {"bar", "30", false, nil, []string{"bar"}, nil},
},
wantMerged: []ApexInfo{
- {"apex30", 30, false, nil, []string{"bar"}},
- {"apex10000", 10000, false, nil, []string{"foo"}},
+ {"apex30", "30", false, nil, []string{"bar"}, nil},
+ {"apex10000", "current", false, nil, []string{"foo"}, nil},
},
wantAliases: [][2]string{
{"bar", "apex30"},
@@ -70,11 +69,11 @@
{
name: "merge updatable",
in: []ApexInfo{
- {"foo", 10000, false, nil, []string{"foo"}},
- {"bar", 10000, true, nil, []string{"bar"}},
+ {"foo", "current", false, nil, []string{"foo"}, nil},
+ {"bar", "current", true, nil, []string{"bar"}, nil},
},
wantMerged: []ApexInfo{
- {"apex10000", 10000, true, nil, []string{"bar", "foo"}},
+ {"apex10000", "current", true, nil, []string{"bar", "foo"}, nil},
},
wantAliases: [][2]string{
{"bar", "apex10000"},
@@ -84,12 +83,12 @@
{
name: "don't merge sdks",
in: []ApexInfo{
- {"foo", 10000, false, SdkRefs{{"baz", "1"}}, []string{"foo"}},
- {"bar", 10000, false, SdkRefs{{"baz", "2"}}, []string{"bar"}},
+ {"foo", "current", false, SdkRefs{{"baz", "1"}}, []string{"foo"}, nil},
+ {"bar", "current", false, SdkRefs{{"baz", "2"}}, []string{"bar"}, nil},
},
wantMerged: []ApexInfo{
- {"apex10000_baz_2", 10000, false, SdkRefs{{"baz", "2"}}, []string{"bar"}},
- {"apex10000_baz_1", 10000, false, SdkRefs{{"baz", "1"}}, []string{"foo"}},
+ {"apex10000_baz_2", "current", false, SdkRefs{{"baz", "2"}}, []string{"bar"}, nil},
+ {"apex10000_baz_1", "current", false, SdkRefs{{"baz", "1"}}, []string{"foo"}, nil},
},
wantAliases: [][2]string{
{"bar", "apex10000_baz_2"},
@@ -99,7 +98,9 @@
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- gotMerged, gotAliases := mergeApexVariations(tt.in)
+ config := TestConfig(buildDir, nil, "", nil)
+ ctx := &configErrorWrapper{config: config}
+ gotMerged, gotAliases := mergeApexVariations(ctx, tt.in)
if !reflect.DeepEqual(gotMerged, tt.wantMerged) {
t.Errorf("mergeApexVariations() gotMerged = %v, want %v", gotMerged, tt.wantMerged)
}
diff --git a/android/api_levels.go b/android/api_levels.go
index 0872066..08328e1 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -24,6 +24,193 @@
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 PathContext, 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 PathContext, 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 PathContext, raw string) ApiLevel {
+ value, err := ApiLevelFromUser(ctx, raw)
+ if err != nil {
+ panic(err.Error())
+ }
+ return value
+}
+
func ApiLevelsSingleton() Singleton {
return &apiLevelsSingleton{}
}
@@ -38,20 +225,55 @@
ctx.Errorf(err.Error())
}
- ctx.Build(pctx, BuildParams{
- Rule: WriteFile,
- Description: "generate " + file.Base(),
- Output: file,
- Args: map[string]string{
- "content": string(jsonStr[:]),
- },
- })
+ WriteFileRule(ctx, file, string(jsonStr))
}
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 +305,6 @@
}).(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 d055a6f..98ff07a 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -78,13 +78,22 @@
},
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 @@
not_windows: {
// Non-windows host variants
},
+ android_arm: {
+ // Any <os>_<arch> combination restricts to that os and arch
+ },
},
}
*/
@@ -125,6 +137,7 @@
Arm64: {
"armv8_a",
"armv8_2a",
+ "armv8-2a-dotprod",
"cortex-a53",
"cortex-a55",
"cortex-a72",
@@ -172,6 +185,9 @@
Arm: {
"neon",
},
+ Arm64: {
+ "dotprod",
+ },
X86: {
"ssse3",
"sse4",
@@ -209,6 +225,11 @@
"neon",
},
},
+ Arm64: {
+ "armv8-2a-dotprod": {
+ "dotprod",
+ },
+ },
X86: {
"amberlake": {
"ssse3",
@@ -569,7 +590,7 @@
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 @@
Generic OsClass = iota
Device
Host
- HostCross
)
func (class OsClass) String() string {
@@ -611,8 +631,6 @@
return "device"
case Host:
return "host"
- case HostCross:
- return "host cross"
default:
panic(fmt.Errorf("unknown class %d", class))
}
@@ -672,6 +690,11 @@
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 @@
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 {
@@ -799,10 +811,16 @@
}
}
-// Identifies the dependency from CommonOS variant to the os specific variants.
-type commonOSTag struct{ blueprint.BaseDependencyTag }
+type archDepTag struct {
+ blueprint.BaseDependencyTag
+ name string
+}
-var commonOsToOsSpecificVariantTag = commonOSTag{}
+// Identifies the dependency from CommonOS variant to the os specific variants.
+var commonOsToOsSpecificVariantTag = archDepTag{name: "common os to os specific"}
+
+// Identifies the dependency from arch variant to the common variant for a "common_first" multilib.
+var firstArchToCommonArchDepTag = archDepTag{name: "first arch to common arch"}
// Get the OsType specific variants for the current CommonOS variant.
//
@@ -819,7 +837,6 @@
}
}
})
-
return variants
}
@@ -897,14 +914,14 @@
osTargets = targets
}
- // only the primary arch in the ramdisk / recovery partition
- if os == Android && (module.InstallInRecovery() || module.InstallInRamdisk()) {
+ // only the primary arch in the ramdisk / vendor_ramdisk / recovery partition
+ if os == Android && (module.InstallInRecovery() || module.InstallInRamdisk() || module.InstallInVendorRamdisk()) {
osTargets = []Target{osTargets[0]}
}
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)
@@ -943,6 +960,12 @@
addTargetProperties(m, targets[i], multiTargets, i == 0)
m.base().setArchProperties(mctx)
}
+
+ if multilib == "common_first" && len(modules) >= 2 {
+ for i := range modules[1:] {
+ mctx.AddInterVariantDependency(firstArchToCommonArchDepTag, modules[i+1], modules[0])
+ }
+ }
}
func addTargetProperties(m Module, target Target, multiTargets []Target, primaryTarget bool) {
@@ -955,7 +978,7 @@
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 +1254,7 @@
// 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 +1294,7 @@
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 +1457,15 @@
// 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 +1522,36 @@
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 +1559,7 @@
NativeBridge: nativeBridgeEnabled,
NativeBridgeHostArchName: nativeBridgeHostArchNameStr,
NativeBridgeRelativePath: nativeBridgeRelativePathStr,
+ HostCross: hostCross,
})
}
@@ -1527,6 +1576,9 @@
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 +1646,7 @@
// 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 +1685,10 @@
{"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"}},
@@ -1684,7 +1717,7 @@
func getAmlAbisConfig() []archConfig {
return []archConfig{
- {"arm", "armv7-a", "", []string{"armeabi-v7a"}},
+ {"arm", "armv7-a-neon", "", []string{"armeabi-v7a"}},
{"arm64", "armv8-a", "", []string{"arm64-v8a"}},
{"x86", "", "", []string{"x86"}},
{"x86_64", "", "", []string{"x86_64"}},
@@ -1786,13 +1819,22 @@
}
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/arch_test.go b/android/arch_test.go
index 8525b03..4cef4c8 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -353,9 +353,9 @@
t.Run(tt.name, func(t *testing.T) {
config := TestArchConfig(buildDir, nil, bp, nil)
- ctx := NewTestArchContext()
+ ctx := NewTestArchContext(config)
ctx.RegisterModuleType("module", archTestModuleFactory)
- ctx.Register(config)
+ ctx.Register()
if tt.config != nil {
tt.config(config)
}
@@ -442,9 +442,9 @@
t.Run(tt.name, func(t *testing.T) {
config := TestArchConfigNativeBridge(buildDir, nil, bp, nil)
- ctx := NewTestArchContext()
+ ctx := NewTestArchContext(config)
ctx.RegisterModuleType("module", archTestModuleFactory)
- ctx.Register(config)
+ ctx.Register()
if tt.config != nil {
tt.config(config)
}
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
new file mode 100644
index 0000000..c87a945
--- /dev/null
+++ b/android/bazel_handler.go
@@ -0,0 +1,363 @@
+// 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 android
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "sync"
+
+ "github.com/google/blueprint/bootstrap"
+)
+
+type CqueryRequestType int
+
+const (
+ getAllFiles CqueryRequestType = iota
+)
+
+// Map key to describe bazel cquery requests.
+type cqueryKey struct {
+ label string
+ requestType CqueryRequestType
+}
+
+type BazelContext interface {
+ // The below methods involve queuing cquery requests to be later invoked
+ // by bazel. If any of these methods return (_, false), then the request
+ // has been queued to be run later.
+
+ // Returns result files built by building the given bazel target label.
+ GetAllFiles(label string) ([]string, bool)
+
+ // TODO(cparsons): Other cquery-related methods should be added here.
+ // ** End cquery methods
+
+ // Issues commands to Bazel to receive results for all cquery requests
+ // queued in the BazelContext.
+ InvokeBazel() error
+
+ // Returns true if bazel is enabled for the given configuration.
+ BazelEnabled() bool
+}
+
+// A context object which tracks queued requests that need to be made to Bazel,
+// and their results after the requests have been made.
+type bazelContext struct {
+ homeDir string
+ bazelPath string
+ outputBase string
+ workspaceDir string
+ buildDir string
+
+ requests map[cqueryKey]bool // cquery requests that have not yet been issued to Bazel
+ requestMutex sync.Mutex // requests can be written in parallel
+
+ results map[cqueryKey]string // Results of cquery requests after Bazel invocations
+}
+
+var _ BazelContext = &bazelContext{}
+
+// A bazel context to use when Bazel is disabled.
+type noopBazelContext struct{}
+
+var _ BazelContext = noopBazelContext{}
+
+// A bazel context to use for tests.
+type MockBazelContext struct {
+ AllFiles map[string][]string
+}
+
+func (m MockBazelContext) GetAllFiles(label string) ([]string, bool) {
+ result, ok := m.AllFiles[label]
+ return result, ok
+}
+
+func (m MockBazelContext) InvokeBazel() error {
+ panic("unimplemented")
+}
+
+func (m MockBazelContext) BazelEnabled() bool {
+ return true
+}
+
+var _ BazelContext = MockBazelContext{}
+
+func (bazelCtx *bazelContext) GetAllFiles(label string) ([]string, bool) {
+ result, ok := bazelCtx.cquery(label, getAllFiles)
+ if ok {
+ bazelOutput := strings.TrimSpace(result)
+ return strings.Split(bazelOutput, ", "), true
+ } else {
+ return nil, false
+ }
+}
+
+func (n noopBazelContext) GetAllFiles(label string) ([]string, bool) {
+ panic("unimplemented")
+}
+
+func (n noopBazelContext) InvokeBazel() error {
+ panic("unimplemented")
+}
+
+func (n noopBazelContext) BazelEnabled() bool {
+ return false
+}
+
+func NewBazelContext(c *config) (BazelContext, error) {
+ // TODO(cparsons): Assess USE_BAZEL=1 instead once "mixed Soong/Bazel builds"
+ // are production ready.
+ if c.Getenv("USE_BAZEL_ANALYSIS") != "1" {
+ return noopBazelContext{}, nil
+ }
+
+ bazelCtx := bazelContext{buildDir: c.buildDir, requests: make(map[cqueryKey]bool)}
+ missingEnvVars := []string{}
+ if len(c.Getenv("BAZEL_HOME")) > 1 {
+ bazelCtx.homeDir = c.Getenv("BAZEL_HOME")
+ } else {
+ missingEnvVars = append(missingEnvVars, "BAZEL_HOME")
+ }
+ if len(c.Getenv("BAZEL_PATH")) > 1 {
+ bazelCtx.bazelPath = c.Getenv("BAZEL_PATH")
+ } else {
+ missingEnvVars = append(missingEnvVars, "BAZEL_PATH")
+ }
+ if len(c.Getenv("BAZEL_OUTPUT_BASE")) > 1 {
+ bazelCtx.outputBase = c.Getenv("BAZEL_OUTPUT_BASE")
+ } else {
+ missingEnvVars = append(missingEnvVars, "BAZEL_OUTPUT_BASE")
+ }
+ if len(c.Getenv("BAZEL_WORKSPACE")) > 1 {
+ bazelCtx.workspaceDir = c.Getenv("BAZEL_WORKSPACE")
+ } else {
+ missingEnvVars = append(missingEnvVars, "BAZEL_WORKSPACE")
+ }
+ if len(missingEnvVars) > 0 {
+ return nil, errors.New(fmt.Sprintf("missing required env vars to use bazel: %s", missingEnvVars))
+ } else {
+ return &bazelCtx, nil
+ }
+}
+
+func (context *bazelContext) BazelEnabled() bool {
+ return true
+}
+
+// Adds a cquery request to the Bazel request queue, to be later invoked, or
+// returns the result of the given request if the request was already made.
+// If the given request was already made (and the results are available), then
+// returns (result, true). If the request is queued but no results are available,
+// then returns ("", false).
+func (context *bazelContext) cquery(label string, requestType CqueryRequestType) (string, bool) {
+ key := cqueryKey{label, requestType}
+ if result, ok := context.results[key]; ok {
+ return result, true
+ } else {
+ context.requestMutex.Lock()
+ defer context.requestMutex.Unlock()
+ context.requests[key] = true
+ return "", false
+ }
+}
+
+func pwdPrefix() string {
+ // Darwin doesn't have /proc
+ if runtime.GOOS != "darwin" {
+ return "PWD=/proc/self/cwd"
+ }
+ return ""
+}
+
+func (context *bazelContext) issueBazelCommand(command string, labels []string,
+ extraFlags ...string) (string, error) {
+
+ cmdFlags := []string{"--bazelrc=build/bazel/common.bazelrc",
+ "--output_base=" + context.outputBase, command}
+ cmdFlags = append(cmdFlags, labels...)
+ cmdFlags = append(cmdFlags, extraFlags...)
+
+ bazelCmd := exec.Command(context.bazelPath, cmdFlags...)
+ bazelCmd.Dir = context.workspaceDir
+ bazelCmd.Env = append(os.Environ(), "HOME="+context.homeDir, pwdPrefix())
+
+ stderr := &bytes.Buffer{}
+ bazelCmd.Stderr = stderr
+
+ if output, err := bazelCmd.Output(); err != nil {
+ return "", fmt.Errorf("bazel command failed. command: [%s], error [%s]", bazelCmd, stderr)
+ } else {
+ return string(output), nil
+ }
+}
+
+func (context *bazelContext) mainBzlFileContents() []byte {
+ contents := `
+# This file is generated by soong_build. Do not edit.
+def _mixed_build_root_impl(ctx):
+ return [DefaultInfo(files = depset(ctx.files.deps))]
+
+mixed_build_root = rule(
+ implementation = _mixed_build_root_impl,
+ attrs = {"deps" : attr.label_list()},
+)
+`
+ return []byte(contents)
+}
+
+func (context *bazelContext) mainBuildFileContents() []byte {
+ formatString := `
+# This file is generated by soong_build. Do not edit.
+load(":main.bzl", "mixed_build_root")
+
+mixed_build_root(name = "buildroot",
+ deps = [%s],
+)
+`
+ var buildRootDeps []string = nil
+ for val, _ := range context.requests {
+ buildRootDeps = append(buildRootDeps, fmt.Sprintf("\"%s\"", val.label))
+ }
+ buildRootDepsString := strings.Join(buildRootDeps, ",\n ")
+
+ return []byte(fmt.Sprintf(formatString, buildRootDepsString))
+}
+
+func (context *bazelContext) cqueryStarlarkFileContents() []byte {
+ formatString := `
+# This file is generated by soong_build. Do not edit.
+getAllFilesLabels = {
+ %s
+}
+
+def format(target):
+ if str(target.label) in getAllFilesLabels:
+ return str(target.label) + ">>" + ', '.join([f.path for f in target.files.to_list()])
+ else:
+ # This target was not requested via cquery, and thus must be a dependency
+ # of a requested target.
+ return ""
+`
+ var buildRootDeps []string = nil
+ // TODO(cparsons): Sort by request type instead of assuming all requests
+ // are of GetAllFiles type.
+ for val, _ := range context.requests {
+ buildRootDeps = append(buildRootDeps, fmt.Sprintf("\"%s\" : True", val.label))
+ }
+ buildRootDepsString := strings.Join(buildRootDeps, ",\n ")
+
+ return []byte(fmt.Sprintf(formatString, buildRootDepsString))
+}
+
+// Issues commands to Bazel to receive results for all cquery requests
+// queued in the BazelContext.
+func (context *bazelContext) InvokeBazel() error {
+ context.results = make(map[cqueryKey]string)
+
+ var cqueryOutput string
+ var err error
+ err = ioutil.WriteFile(
+ absolutePath(filepath.Join(context.buildDir, "main.bzl")),
+ context.mainBzlFileContents(), 0666)
+ if err != nil {
+ return err
+ }
+ err = ioutil.WriteFile(
+ absolutePath(filepath.Join(context.buildDir, "BUILD.bazel")),
+ context.mainBuildFileContents(), 0666)
+ if err != nil {
+ return err
+ }
+ cquery_file_relpath := filepath.Join(context.buildDir, "buildroot.cquery")
+ err = ioutil.WriteFile(
+ absolutePath(cquery_file_relpath),
+ context.cqueryStarlarkFileContents(), 0666)
+ if err != nil {
+ return err
+ }
+ buildroot_label := fmt.Sprintf("//%s:buildroot", context.buildDir)
+ cqueryOutput, err = context.issueBazelCommand("cquery",
+ []string{fmt.Sprintf("deps(%s)", buildroot_label)},
+ "--output=starlark",
+ "--starlark:file="+cquery_file_relpath)
+
+ if err != nil {
+ return err
+ }
+
+ cqueryResults := map[string]string{}
+ for _, outputLine := range strings.Split(cqueryOutput, "\n") {
+ if strings.Contains(outputLine, ">>") {
+ splitLine := strings.SplitN(outputLine, ">>", 2)
+ cqueryResults[splitLine[0]] = splitLine[1]
+ }
+ }
+
+ for val, _ := range context.requests {
+ if cqueryResult, ok := cqueryResults[val.label]; ok {
+ context.results[val] = string(cqueryResult)
+ } else {
+ return fmt.Errorf("missing result for bazel target %s", val.label)
+ }
+ }
+
+ // Issue a build command.
+ // TODO(cparsons): Invoking bazel execution during soong_build should be avoided;
+ // bazel actions should either be added to the Ninja file and executed later,
+ // or bazel should handle execution.
+ // TODO(cparsons): Use --target_pattern_file to avoid command line limits.
+ _, err = context.issueBazelCommand("build", []string{buildroot_label})
+
+ if err != nil {
+ return err
+ }
+
+ // Clear requests.
+ context.requests = map[cqueryKey]bool{}
+ return nil
+}
+
+// Singleton used for registering BUILD file ninja dependencies (needed
+// for correctness of builds which use Bazel.
+func BazelSingleton() Singleton {
+ return &bazelSingleton{}
+}
+
+type bazelSingleton struct{}
+
+func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) {
+ if ctx.Config().BazelContext.BazelEnabled() {
+ bazelBuildList := absolutePath(filepath.Join(
+ filepath.Dir(bootstrap.ModuleListFile), "bazel.list"))
+ ctx.AddNinjaFileDeps(bazelBuildList)
+
+ data, err := ioutil.ReadFile(bazelBuildList)
+ if err != nil {
+ ctx.Errorf(err.Error())
+ }
+ files := strings.Split(strings.TrimSpace(string(data)), "\n")
+ for _, file := range files {
+ ctx.AddNinjaFileDeps(file)
+ }
+ }
+}
diff --git a/android/bazel_overlay.go b/android/bazel_overlay.go
deleted file mode 100644
index a034282..0000000
--- a/android/bazel_overlay.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// 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 android
-
-import (
- "fmt"
- "os"
- "strings"
-
- "github.com/google/blueprint"
-)
-
-// The Bazel Overlay singleton is responsible for generating the Ninja actions
-// for calling the soong_build primary builder in the main build.ninja file.
-func init() {
- RegisterSingletonType("bazel_overlay", BazelOverlaySingleton)
-}
-
-func BazelOverlaySingleton() Singleton {
- return &bazelOverlaySingleton{}
-}
-
-type bazelOverlaySingleton struct{}
-
-func (c *bazelOverlaySingleton) GenerateBuildActions(ctx SingletonContext) {
- // Create a build and rule statement, using the Bazel overlay's WORKSPACE
- // file as the output file marker.
- var deps Paths
- moduleListFilePath := pathForBuildToolDep(ctx, ctx.Config().moduleListFile)
- deps = append(deps, moduleListFilePath)
- deps = append(deps, pathForBuildToolDep(ctx, ctx.Config().ProductVariablesFileName))
-
- bazelOverlayDirectory := PathForOutput(ctx, "bazel_overlay")
- bazelOverlayWorkspaceFile := bazelOverlayDirectory.Join(ctx, "WORKSPACE")
- primaryBuilder := primaryBuilderPath(ctx)
- bazelOverlay := ctx.Rule(pctx, "bazelOverlay",
- blueprint.RuleParams{
- Command: fmt.Sprintf(
- "rm -rf ${outDir}/* && %s --bazel_overlay_dir ${outDir} %s && echo WORKSPACE: `cat %s` > ${outDir}/.overlay-depfile.d",
- primaryBuilder.String(),
- strings.Join(os.Args[1:], " "),
- moduleListFilePath.String(), // Use the contents of Android.bp.list as the depfile.
- ),
- CommandDeps: []string{primaryBuilder.String()},
- Description: fmt.Sprintf(
- "Creating the Bazel overlay workspace with %s at $outDir",
- primaryBuilder.Base()),
- Deps: blueprint.DepsGCC,
- Depfile: "${outDir}/.overlay-depfile.d",
- },
- "outDir")
-
- ctx.Build(pctx, BuildParams{
- Rule: bazelOverlay,
- Output: bazelOverlayWorkspaceFile,
- Inputs: deps,
- Args: map[string]string{
- "outDir": bazelOverlayDirectory.String(),
- },
- })
-
- // Add a phony target for building the bazel overlay
- ctx.Phony("bazel_overlay", bazelOverlayWorkspaceFile)
-}
diff --git a/android/config.go b/android/config.go
index dd622e5..e87a4ac 100644
--- a/android/config.go
+++ b/android/config.go
@@ -21,7 +21,6 @@
"os"
"path/filepath"
"runtime"
- "strconv"
"strings"
"sync"
@@ -37,7 +36,13 @@
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 @@
// 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() {
@@ -79,14 +85,17 @@
// Only available on configs created by TestConfig
TestProductVariables *productVariables
+ BazelContext BazelContext
+
PrimaryBuilder string
ConfigFileName string
ProductVariablesFileName string
- Targets map[OsType][]Target
- BuildOSTarget Target // the Target for tools run on the build machine
- BuildOSCommonTarget Target // the Target for common (java) tools run on the build machine
- AndroidCommonTarget Target // the Target for common modules for the Android device
+ Targets map[OsType][]Target
+ BuildOSTarget Target // the Target for tools run on the build machine
+ BuildOSCommonTarget Target // the Target for common (java) tools run on the build machine
+ AndroidCommonTarget Target // the Target for common modules for the Android device
+ AndroidFirstDeviceTarget Target // the first Target for modules for the Android device
// multilibConflicts for an ArchType is true if there is earlier configured device architecture with the same
// multilib value.
@@ -222,15 +231,17 @@
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,
@@ -240,6 +251,8 @@
// Set testAllowNonExistentPaths so that test contexts don't need to specify every path
// passed to PathForSource or PathForModuleSrc.
testAllowNonExistentPaths: true,
+
+ BazelContext: noopBazelContext{},
}
config.deviceConfig = &deviceConfig{
config: config,
@@ -260,10 +273,10 @@
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 +288,10 @@
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 +305,12 @@
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},
},
}
@@ -308,6 +321,7 @@
config.BuildOSTarget = config.Targets[BuildOs][0]
config.BuildOSCommonTarget = getCommonTargets(config.Targets[BuildOs])[0]
config.AndroidCommonTarget = getCommonTargets(config.Targets[Android])[0]
+ config.AndroidFirstDeviceTarget = firstTarget(config.Targets[Android], "lib64", "lib32")[0]
config.TestProductVariables.DeviceArch = proptools.StringPtr("arm64")
config.TestProductVariables.DeviceArchVariant = proptools.StringPtr("armv8-a")
config.TestProductVariables.DeviceSecondaryArch = proptools.StringPtr("arm")
@@ -316,6 +330,20 @@
return testConfig
}
+// Returns a config object which is "reset" for another bootstrap run.
+// Only per-run data is reset. Data which needs to persist across multiple
+// runs in the same program execution is carried over (such as Bazel context
+// or environment deps).
+func ConfigForAdditionalRun(c Config) (Config, error) {
+ newConfig, err := NewConfig(c.srcDir, c.buildDir, c.moduleListFile)
+ if err != nil {
+ return Config{}, err
+ }
+ newConfig.BazelContext = c.BazelContext
+ newConfig.envDeps = c.envDeps
+ return newConfig, nil
+}
+
// New creates a new Config object. The srcDir argument specifies the path to
// the root source directory. It also loads the config file, if found.
func NewConfig(srcDir, buildDir string, moduleListFile string) (Config, error) {
@@ -403,6 +431,7 @@
config.BuildOSCommonTarget = getCommonTargets(config.Targets[BuildOs])[0]
if len(config.Targets[Android]) > 0 {
config.AndroidCommonTarget = getCommonTargets(config.Targets[Android])[0]
+ config.AndroidFirstDeviceTarget = firstTarget(config.Targets[Android], "lib64", "lib32")[0]
}
if err := config.fromEnv(); err != nil {
@@ -417,6 +446,10 @@
Bool(config.productVariables.GcovCoverage) ||
Bool(config.productVariables.ClangCoverage))
+ config.BazelContext, err = NewBazelContext(config)
+ if err != nil {
+ return Config{}, err
+ }
return Config{config}, nil
}
@@ -614,12 +647,8 @@
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 +671,48 @@
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)
}
}
@@ -739,6 +793,11 @@
return Bool(c.productVariables.Always_use_prebuilt_sdks)
}
+// Returns true if the boot jars check should be skipped.
+func (c *config) SkipBootJarsCheck() bool {
+ return Bool(c.productVariables.Skip_boot_jars_check)
+}
+
func (c *config) Fuchsia() bool {
return Bool(c.productVariables.Fuchsia)
}
@@ -887,6 +946,10 @@
return false
}
+func (c *config) EnforceRROExemptedForModule(name string) bool {
+ return InList(name, c.productVariables.EnforceRROExemptedTargets)
+}
+
func (c *config) EnforceRROExcludedOverlay(path string) bool {
excluded := c.productVariables.EnforceRROExcludedOverlays
if len(excluded) > 0 {
@@ -911,13 +974,21 @@
return c.productVariables.ModulesLoadedByPrivilegedModules
}
-func (c *config) DexpreoptGlobalConfig(ctx PathContext) ([]byte, error) {
+func (c *config) DexpreoptGlobalConfigPath(ctx PathContext) OptionalPath {
if c.productVariables.DexpreoptGlobalConfig == nil {
+ return OptionalPathForPath(nil)
+ }
+ return OptionalPathForPath(
+ pathForBuildToolDep(ctx, *c.productVariables.DexpreoptGlobalConfig))
+}
+
+func (c *config) DexpreoptGlobalConfig(ctx PathContext) ([]byte, error) {
+ path := c.DexpreoptGlobalConfigPath(ctx)
+ if !path.Valid() {
return nil, nil
}
- path := absolutePath(*c.productVariables.DexpreoptGlobalConfig)
- ctx.AddNinjaFileDeps(path)
- return ioutil.ReadFile(path)
+ ctx.AddNinjaFileDeps(path.String())
+ return ioutil.ReadFile(absolutePath(path.String()))
}
func (c *config) FrameworksBaseDirExists(ctx PathContext) bool {
@@ -1087,12 +1158,12 @@
return c.config.productVariables.BoardOdmSepolicyDirs
}
-func (c *deviceConfig) PlatPublicSepolicyDirs() []string {
- return c.config.productVariables.BoardPlatPublicSepolicyDirs
+func (c *deviceConfig) SystemExtPublicSepolicyDirs() []string {
+ return c.config.productVariables.SystemExtPublicSepolicyDirs
}
-func (c *deviceConfig) PlatPrivateSepolicyDirs() []string {
- return c.config.productVariables.BoardPlatPrivateSepolicyDirs
+func (c *deviceConfig) SystemExtPrivateSepolicyDirs() []string {
+ return c.config.productVariables.SystemExtPrivateSepolicyDirs
}
func (c *deviceConfig) SepolicyM4Defs() []string {
@@ -1254,6 +1325,10 @@
return c.config.productVariables.BoardKernelModuleInterfaceVersions
}
+func (c *deviceConfig) BoardMoveRecoveryResourcesToVendorBoot() bool {
+ return Bool(c.config.productVariables.BoardMoveRecoveryResourcesToVendorBoot)
+}
+
// The ConfiguredJarList struct provides methods for handling a list of (apex, jar) pairs.
// Such lists are used in the build system for things like bootclasspath jars or system server jars.
// The apex part is either an apex name, or a special names "platform" or "system_ext". Jar is a
@@ -1274,16 +1349,16 @@
return len(l.jars)
}
-// Apex component of idx-th pair on the list.
-func (l *ConfiguredJarList) apex(idx int) string {
- return l.apexes[idx]
-}
-
// Jar component of idx-th pair on the list.
func (l *ConfiguredJarList) Jar(idx int) string {
return l.jars[idx]
}
+// Apex component of idx-th pair on the list.
+func (l *ConfiguredJarList) Apex(idx int) string {
+ return l.apexes[idx]
+}
+
// If the list contains a pair with the given jar.
func (l *ConfiguredJarList) ContainsJar(jar string) bool {
return InList(jar, l.jars)
@@ -1292,7 +1367,7 @@
// If the list contains the given (apex, jar) pair.
func (l *ConfiguredJarList) containsApexJarPair(apex, jar string) bool {
for i := 0; i < l.Len(); i++ {
- if apex == l.apex(i) && jar == l.Jar(i) {
+ if apex == l.apexes[i] && jar == l.jars[i] {
return true
}
}
@@ -1304,32 +1379,43 @@
return IndexList(jar, l.jars)
}
+func copyAndAppend(list []string, item string) []string {
+ // Create the result list to be 1 longer than the input.
+ result := make([]string, len(list)+1)
+
+ // Copy the whole input list into the result.
+ count := copy(result, list)
+
+ // Insert the extra item at the end.
+ result[count] = item
+
+ return result
+}
+
// Append an (apex, jar) pair to the list.
-func (l *ConfiguredJarList) Append(apex string, jar string) {
- l.apexes = append(l.apexes, apex)
- l.jars = append(l.jars, jar)
+func (l *ConfiguredJarList) Append(apex string, jar string) ConfiguredJarList {
+ // Create a copy of the backing arrays before appending to avoid sharing backing
+ // arrays that are mutated across instances.
+ apexes := copyAndAppend(l.apexes, apex)
+ jars := copyAndAppend(l.jars, jar)
+
+ return ConfiguredJarList{apexes, jars}
}
// Filter out sublist.
-func (l *ConfiguredJarList) RemoveList(list ConfiguredJarList) {
+func (l *ConfiguredJarList) RemoveList(list ConfiguredJarList) ConfiguredJarList {
apexes := make([]string, 0, l.Len())
jars := make([]string, 0, l.Len())
for i, jar := range l.jars {
- apex := l.apex(i)
+ apex := l.apexes[i]
if !list.containsApexJarPair(apex, jar) {
apexes = append(apexes, apex)
jars = append(jars, jar)
}
}
- l.apexes = apexes
- l.jars = jars
-}
-
-// A copy of itself.
-func (l *ConfiguredJarList) CopyOf() ConfiguredJarList {
- return ConfiguredJarList{CopyOf(l.apexes), CopyOf(l.jars)}
+ return ConfiguredJarList{apexes, jars}
}
// A copy of the list of strings containing jar components.
@@ -1342,7 +1428,7 @@
pairs := make([]string, 0, l.Len())
for i, jar := range l.jars {
- apex := l.apex(i)
+ apex := l.apexes[i]
pairs = append(pairs, apex+":"+jar)
}
@@ -1358,6 +1444,26 @@
return paths
}
+// Called when loading configuration from JSON into a configuration structure.
+func (l *ConfiguredJarList) UnmarshalJSON(b []byte) error {
+ // Try and unmarshal into a []string each item of which contains a pair
+ // <apex>:<jar>.
+ var list []string
+ err := json.Unmarshal(b, &list)
+ if err != nil {
+ // Did not work so return
+ return err
+ }
+
+ apexes, jars, err := splitListOfPairsIntoPairOfLists(list)
+ if err != nil {
+ return err
+ }
+ l.apexes = apexes
+ l.jars = jars
+ return nil
+}
+
func ModuleStem(module string) string {
// b/139391334: the stem of framework-minus-apex is framework. This is hard coded here until we
// find a good way to query the stem of a module before any other mutators are run.
@@ -1392,29 +1498,49 @@
return paths
}
+func (l *ConfiguredJarList) String() string {
+ var pairs []string
+ for i := 0; i < l.Len(); i++ {
+ pairs = append(pairs, l.apexes[i]+":"+l.jars[i])
+ }
+ return strings.Join(pairs, ",")
+}
+
+func splitListOfPairsIntoPairOfLists(list []string) ([]string, []string, error) {
+ // Now we need to populate this list by splitting each item in the slice of
+ // pairs and appending them to the appropriate list of apexes or jars.
+ apexes := make([]string, len(list))
+ jars := make([]string, len(list))
+
+ for i, apexjar := range list {
+ apex, jar, err := splitConfiguredJarPair(apexjar)
+ if err != nil {
+ return nil, nil, err
+ }
+ apexes[i] = apex
+ jars[i] = jar
+ }
+
+ return apexes, jars, nil
+}
+
// Expected format for apexJarValue = <apex name>:<jar name>
-func splitConfiguredJarPair(ctx PathContext, str string) (string, string) {
+func splitConfiguredJarPair(str string) (string, string, error) {
pair := strings.SplitN(str, ":", 2)
if len(pair) == 2 {
- return pair[0], pair[1]
+ return pair[0], pair[1], nil
} else {
- ReportPathErrorf(ctx, "malformed (apex, jar) pair: '%s', expected format: <apex>:<jar>", str)
- return "error-apex", "error-jar"
+ return "error-apex", "error-jar", fmt.Errorf("malformed (apex, jar) pair: '%s', expected format: <apex>:<jar>", str)
}
}
-func CreateConfiguredJarList(ctx PathContext, list []string) ConfiguredJarList {
- apexes := make([]string, 0, len(list))
- jars := make([]string, 0, len(list))
-
- l := ConfiguredJarList{apexes, jars}
-
- for _, apexjar := range list {
- apex, jar := splitConfiguredJarPair(ctx, apexjar)
- l.Append(apex, jar)
+func CreateTestConfiguredJarList(list []string) ConfiguredJarList {
+ apexes, jars, err := splitListOfPairsIntoPairOfLists(list)
+ if err != nil {
+ panic(err)
}
- return l
+ return ConfiguredJarList{apexes, jars}
}
func EmptyConfiguredJarList() ConfiguredJarList {
@@ -1425,9 +1551,16 @@
func (c *config) BootJars() []string {
return c.Once(earlyBootJarsKey, func() interface{} {
- ctx := NullPathContext{Config{c}}
- list := CreateConfiguredJarList(ctx,
- append(CopyOf(c.productVariables.BootJars), c.productVariables.UpdatableBootJars...))
- return list.CopyOfJars()
+ list := c.productVariables.BootJars.CopyOfJars()
+ list = append(list, c.productVariables.UpdatableBootJars.CopyOfJars()...)
+ return list
}).([]string)
}
+
+func (c *config) NonUpdatableBootJars() ConfiguredJarList {
+ return c.productVariables.BootJars
+}
+
+func (c *config) UpdatableBootJars() ConfiguredJarList {
+ return c.productVariables.UpdatableBootJars
+}
diff --git a/android/config_test.go b/android/config_test.go
index 274d59f..68f68a0 100644
--- a/android/config_test.go
+++ b/android/config_test.go
@@ -91,3 +91,49 @@
t.Errorf("Expected false")
}
}
+
+func assertStringEquals(t *testing.T, expected, actual string) {
+ if actual != expected {
+ t.Errorf("expected %q found %q", expected, actual)
+ }
+}
+
+func TestConfiguredJarList(t *testing.T) {
+ list1 := CreateTestConfiguredJarList([]string{"apex1:jarA"})
+
+ t.Run("create", func(t *testing.T) {
+ assertStringEquals(t, "apex1:jarA", list1.String())
+ })
+
+ list2 := list1.Append("apex2", "jarB")
+ t.Run("append", func(t *testing.T) {
+ assertStringEquals(t, "apex1:jarA,apex2:jarB", list2.String())
+ })
+
+ t.Run("append does not modify", func(t *testing.T) {
+ assertStringEquals(t, "apex1:jarA", list1.String())
+ })
+
+ // Make sure that two lists created by appending to the same list do not share storage.
+ list3 := list1.Append("apex3", "jarC")
+ t.Run("append does not share", func(t *testing.T) {
+ assertStringEquals(t, "apex1:jarA,apex2:jarB", list2.String())
+ assertStringEquals(t, "apex1:jarA,apex3:jarC", list3.String())
+ })
+
+ list4 := list3.RemoveList(list1)
+ t.Run("remove", func(t *testing.T) {
+ assertStringEquals(t, "apex3:jarC", list4.String())
+ })
+
+ t.Run("remove does not modify", func(t *testing.T) {
+ assertStringEquals(t, "apex1:jarA,apex3:jarC", list3.String())
+ })
+
+ // Make sure that two lists created by removing from the same list do not share storage.
+ list5 := list3.RemoveList(CreateTestConfiguredJarList([]string{"apex3:jarC"}))
+ t.Run("remove", func(t *testing.T) {
+ assertStringEquals(t, "apex3:jarC", list4.String())
+ assertStringEquals(t, "apex1:jarA", list5.String())
+ })
+}
diff --git a/android/csuite_config_test.go b/android/csuite_config_test.go
index bf1a19a..9ac959e 100644
--- a/android/csuite_config_test.go
+++ b/android/csuite_config_test.go
@@ -21,9 +21,9 @@
func testCSuiteConfig(test *testing.T, bpFileContents string) *TestContext {
config := TestArchConfig(buildDir, nil, bpFileContents, nil)
- ctx := NewTestArchContext()
+ ctx := NewTestArchContext(config)
ctx.RegisterModuleType("csuite_config", CSuiteConfigFactory)
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
FailIfErrored(test, errs)
_, errs = ctx.PrepareBuildActions(config)
diff --git a/android/defaults.go b/android/defaults.go
index 0892adf..eb013d7 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -95,6 +95,8 @@
module.setProperties(module.(Module).GetProperties(), module.(Module).base().variableProperties)
module.AddProperties(module.defaults())
+
+ module.base().customizableProperties = module.GetProperties()
}
// A restricted subset of context methods, similar to LoadHookContext.
diff --git a/android/defaults_test.go b/android/defaults_test.go
index d096b2f..2689d86 100644
--- a/android/defaults_test.go
+++ b/android/defaults_test.go
@@ -80,14 +80,14 @@
config := TestConfig(buildDir, nil, bp, nil)
- ctx := NewTestContext()
+ ctx := NewTestContext(config)
ctx.RegisterModuleType("test", defaultsTestModuleFactory)
ctx.RegisterModuleType("defaults", defaultsTestDefaultsFactory)
ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
FailIfErrored(t, errs)
@@ -125,7 +125,7 @@
config := TestConfig(buildDir, nil, bp, nil)
config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
- ctx := NewTestContext()
+ ctx := NewTestContext(config)
ctx.SetAllowMissingDependencies(true)
ctx.RegisterModuleType("test", defaultsTestModuleFactory)
@@ -133,7 +133,7 @@
ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
FailIfErrored(t, errs)
diff --git a/android/defs.go b/android/defs.go
index 83daa03..631dfe8 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -15,8 +15,12 @@
package android
import (
+ "strings"
+ "testing"
+
"github.com/google/blueprint"
_ "github.com/google/blueprint/bootstrap"
+ "github.com/google/blueprint/proptools"
)
var (
@@ -69,8 +73,9 @@
// A symlink rule.
Symlink = pctx.AndroidStaticRule("Symlink",
blueprint.RuleParams{
- Command: "rm -f $out && ln -f -s $fromPath $out",
- Description: "symlink $out",
+ Command: "rm -f $out && ln -f -s $fromPath $out",
+ Description: "symlink $out",
+ SymlinkOutputs: []string{"$out"},
},
"fromPath")
@@ -90,9 +95,9 @@
// ubuntu 14.04 offcially use dash for /bin/sh, and its builtin echo command
// doesn't support -e option. Therefore we force to use /bin/bash when writing out
// content to file.
- WriteFile = pctx.AndroidStaticRule("WriteFile",
+ writeFile = pctx.AndroidStaticRule("writeFile",
blueprint.RuleParams{
- Command: "/bin/bash -c 'echo -e $$0 > $out' '$content'",
+ Command: `/bin/bash -c 'echo -e "$$0" > $out' $content`,
Description: "writing file $out",
},
"content")
@@ -110,3 +115,64 @@
func init() {
pctx.Import("github.com/google/blueprint/bootstrap")
}
+
+var (
+ // echoEscaper escapes a string such that passing it to "echo -e" will produce the input value.
+ echoEscaper = strings.NewReplacer(
+ `\`, `\\`, // First escape existing backslashes so they aren't interpreted by `echo -e`.
+ "\n", `\n`, // Then replace newlines with \n
+ )
+
+ // echoEscaper reverses echoEscaper.
+ echoUnescaper = strings.NewReplacer(
+ `\n`, "\n",
+ `\\`, `\`,
+ )
+
+ // shellUnescaper reverses the replacer in proptools.ShellEscape
+ shellUnescaper = strings.NewReplacer(`'\''`, `'`)
+)
+
+// WriteFileRule creates a ninja rule to write contents to a file. The contents will be escaped
+// so that the file contains exactly the contents passed to the function, plus a trailing newline.
+func WriteFileRule(ctx BuilderContext, outputFile WritablePath, content string) {
+ content = echoEscaper.Replace(content)
+ content = proptools.ShellEscape(content)
+ if content == "" {
+ content = "''"
+ }
+ ctx.Build(pctx, BuildParams{
+ Rule: writeFile,
+ Output: outputFile,
+ Description: "write " + outputFile.Base(),
+ Args: map[string]string{
+ "content": content,
+ },
+ })
+}
+
+// shellUnescape reverses proptools.ShellEscape
+func shellUnescape(s string) string {
+ // Remove leading and trailing quotes if present
+ if len(s) >= 2 && s[0] == '\'' {
+ s = s[1 : len(s)-1]
+ }
+ s = shellUnescaper.Replace(s)
+ return s
+}
+
+// ContentFromFileRuleForTests returns the content that was passed to a WriteFileRule for use
+// in tests.
+func ContentFromFileRuleForTests(t *testing.T, params TestingBuildParams) string {
+ t.Helper()
+ if g, w := params.Rule, writeFile; g != w {
+ t.Errorf("expected params.Rule to be %q, was %q", w, g)
+ return ""
+ }
+
+ content := params.Args["content"]
+ content = shellUnescape(content)
+ content = echoUnescaper.Replace(content)
+
+ return content
+}
diff --git a/android/depset.go b/android/depset.go
index f707094..60ebcac 100644
--- a/android/depset.go
+++ b/android/depset.go
@@ -71,24 +71,26 @@
// NewDepSet returns an immutable DepSet with the given order, direct and transitive contents.
func NewDepSet(order DepSetOrder, direct Paths, transitive []*DepSet) *DepSet {
var directCopy Paths
- var transitiveCopy []*DepSet
+ transitiveCopy := make([]*DepSet, 0, len(transitive))
+
+ for _, dep := range transitive {
+ if dep != nil {
+ if dep.order != order {
+ panic(fmt.Errorf("incompatible order, new DepSet is %s but transitive DepSet is %s",
+ order, dep.order))
+ }
+ transitiveCopy = append(transitiveCopy, dep)
+ }
+ }
+
if order == TOPOLOGICAL {
directCopy = ReversePaths(direct)
- transitiveCopy = reverseDepSets(transitive)
+ reverseDepSetsInPlace(transitiveCopy)
} else {
// Use copy instead of append(nil, ...) to make a slice that is exactly the size of the input
// slice. The DepSet is immutable, there is no need for additional capacity.
directCopy = make(Paths, len(direct))
copy(directCopy, direct)
- transitiveCopy = make([]*DepSet, len(transitive))
- copy(transitiveCopy, transitive)
- }
-
- for _, dep := range transitive {
- if dep.order != order {
- panic(fmt.Errorf("incompatible order, new DepSet is %s but transitive DepSet is %s",
- order, dep.order))
- }
}
return &DepSet{
@@ -157,6 +159,9 @@
// its transitive dependencies, in which case the ordering of the duplicated element is not
// guaranteed).
func (d *DepSet) ToList() Paths {
+ if d == nil {
+ return nil
+ }
var list Paths
d.walk(func(paths Paths) {
list = append(list, paths...)
@@ -181,10 +186,9 @@
}
}
-func reverseDepSets(list []*DepSet) []*DepSet {
- ret := make([]*DepSet, len(list))
- for i := range list {
- ret[i] = list[len(list)-1-i]
+func reverseDepSetsInPlace(list []*DepSet) {
+ for i, j := 0, len(list)-1; i < j; i, j = i+1, j-1 {
+ list[i], list[j] = list[j], list[i]
}
- return ret
+
}
diff --git a/android/env.go b/android/env.go
index c7c96d5..c2a09aa 100644
--- a/android/env.go
+++ b/android/env.go
@@ -41,7 +41,10 @@
// access originalEnv with dependencies. Store the value where soong_build can find it, it will manually
// ensure the dependencies are created.
soongDelveListen = os.Getenv("SOONG_DELVE")
- soongDelvePath, _ = exec.LookPath("dlv")
+ soongDelvePath = os.Getenv("SOONG_DELVE_PATH")
+ if soongDelvePath == "" {
+ soongDelvePath, _ = exec.LookPath("dlv")
+ }
originalEnv = make(map[string]string)
soongDelveEnv = []string{}
@@ -49,7 +52,7 @@
idx := strings.IndexRune(env, '=')
if idx != -1 {
originalEnv[env[:idx]] = env[idx+1:]
- if env[:idx] != "SOONG_DELVE" {
+ if env[:idx] != "SOONG_DELVE" && env[:idx] != "SOONG_DELVE_PATH" {
soongDelveEnv = append(soongDelveEnv, env)
}
}
diff --git a/android/image.go b/android/image.go
index 061bfa5..1a1a423 100644
--- a/android/image.go
+++ b/android/image.go
@@ -26,6 +26,10 @@
// ramdisk partition).
RamdiskVariantNeeded(ctx BaseModuleContext) bool
+ // VendorRamdiskVariantNeeded should return true if the module needs a vendor ramdisk variant (installed on the
+ // vendor ramdisk partition).
+ VendorRamdiskVariantNeeded(ctx BaseModuleContext) bool
+
// RecoveryVariantNeeded should return true if the module needs a recovery variant (installed on the
// recovery partition).
RecoveryVariantNeeded(ctx BaseModuleContext) bool
@@ -53,6 +57,9 @@
// RamdiskVariation means a module to be installed to ramdisk image.
RamdiskVariation string = "ramdisk"
+
+ // VendorRamdiskVariation means a module to be installed to vendor ramdisk image.
+ VendorRamdiskVariation string = "vendor_ramdisk"
)
// imageMutator creates variants for modules that implement the ImageInterface that
@@ -73,6 +80,9 @@
if m.RamdiskVariantNeeded(ctx) {
variations = append(variations, RamdiskVariation)
}
+ if m.VendorRamdiskVariantNeeded(ctx) {
+ variations = append(variations, VendorRamdiskVariation)
+ }
if m.RecoveryVariantNeeded(ctx) {
variations = append(variations, RecoveryVariation)
}
diff --git a/android/makefile_goal.go b/android/makefile_goal.go
index eae3976..b5d9d69 100644
--- a/android/makefile_goal.go
+++ b/android/makefile_goal.go
@@ -93,7 +93,6 @@
func MakefileGoalFactory() Module {
module := &makefileGoal{}
module.AddProperties(&module.properties)
- // This module is device-only
- InitAndroidArchModule(module, DeviceSupported, MultilibFirst)
+ InitAndroidModule(module)
return module
}
diff --git a/android/makevars.go b/android/makevars.go
index 003a9df..3ca7792 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -18,7 +18,6 @@
"bytes"
"fmt"
"sort"
- "strconv"
"strings"
"github.com/google/blueprint"
@@ -31,7 +30,7 @@
}
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())
}
///////////////////////////////////////////////////////////////////////////////
@@ -129,7 +128,7 @@
type MakeVarsProvider func(ctx MakeVarsContext)
func RegisterMakeVarsProvider(pctx PackageContext, provider MakeVarsProvider) {
- makeVarsProviders = append(makeVarsProviders, makeVarsProvider{pctx, provider})
+ makeVarsInitProviders = append(makeVarsInitProviders, makeVarsProvider{pctx, provider})
}
// SingletonMakeVarsProvider is a Singleton with an extra method to provide extra values to be exported to Make.
@@ -143,7 +142,8 @@
// registerSingletonMakeVarsProvider adds a singleton that implements SingletonMakeVarsProvider to the list of
// MakeVarsProviders to run.
func registerSingletonMakeVarsProvider(singleton SingletonMakeVarsProvider) {
- makeVarsProviders = append(makeVarsProviders, makeVarsProvider{pctx, SingletonmakeVarsProviderAdapter(singleton)})
+ singletonMakeVarsProviders = append(singletonMakeVarsProviders,
+ makeVarsProvider{pctx, SingletonmakeVarsProviderAdapter(singleton)})
}
// SingletonmakeVarsProviderAdapter converts a SingletonMakeVarsProvider to a MakeVarsProvider.
@@ -172,7 +172,11 @@
call MakeVarsProvider
}
-var makeVarsProviders []makeVarsProvider
+// Collection of makevars providers that are registered in init() methods.
+var makeVarsInitProviders []makeVarsProvider
+
+// Collection of singleton makevars providers that are not registered as part of init() methods.
+var singletonMakeVarsProviders []makeVarsProvider
type makeVarsContext struct {
SingletonContext
@@ -220,7 +224,7 @@
var vars []makeVarsVariable
var dists []dist
var phonies []phony
- for _, provider := range makeVarsProviders {
+ for _, provider := range append(makeVarsInitProviders) {
mctx := &makeVarsContext{
SingletonContext: ctx,
pctx: provider.pctx,
@@ -233,6 +237,25 @@
dists = append(dists, mctx.dists...)
}
+ for _, provider := range append(singletonMakeVarsProviders) {
+ mctx := &makeVarsContext{
+ SingletonContext: ctx,
+ pctx: provider.pctx,
+ }
+
+ provider.call(mctx)
+
+ vars = append(vars, mctx.vars...)
+ phonies = append(phonies, mctx.phonies...)
+ dists = append(dists, mctx.dists...)
+ }
+
+ // Clear singleton makevars providers after use. Since these are in-memory
+ // singletons, this ensures state is reset if the build tree is processed
+ // multiple times.
+ // TODO(cparsons): Clean up makeVarsProviders to be part of the context.
+ singletonMakeVarsProviders = nil
+
ctx.VisitAllModules(func(m Module) {
if provider, ok := m.(ModuleMakeVarsProvider); ok && m.Enabled() {
mctx := &makeVarsContext{
diff --git a/android/module.go b/android/module.go
index 337ae40..d677406 100644
--- a/android/module.go
+++ b/android/module.go
@@ -43,6 +43,8 @@
Description string
Output WritablePath
Outputs WritablePaths
+ SymlinkOutput WritablePath
+ SymlinkOutputs WritablePaths
ImplicitOutput WritablePath
ImplicitOutputs WritablePaths
Input Path
@@ -61,18 +63,44 @@
// 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 +126,8 @@
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 +140,156 @@
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
@@ -195,6 +348,7 @@
InstallInTestcases() bool
InstallInSanitizerDir() bool
InstallInRamdisk() bool
+ InstallInVendorRamdisk() bool
InstallInRecovery() bool
InstallInRoot() bool
InstallBypassMake() bool
@@ -216,10 +370,8 @@
// 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
}
@@ -252,6 +404,7 @@
InstallInTestcases() bool
InstallInSanitizerDir() bool
InstallInRamdisk() bool
+ InstallInVendorRamdisk() bool
InstallInRecovery() bool
InstallInRoot() bool
InstallBypassMake() bool
@@ -286,7 +439,7 @@
HostRequiredModuleNames() []string
TargetRequiredModuleNames() []string
- filesToInstall() InstallPaths
+ FilesToInstall() InstallPaths
}
// Qualified id for a module
@@ -417,7 +570,7 @@
// 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 {
@@ -472,11 +625,14 @@
// Whether this module is installed to ramdisk
Ramdisk *bool
+ // Whether this module is installed to vendor ramdisk
+ Vendor_ramdisk *bool
+
// Whether this module is built for non-native architecures (also known as native bridge binary)
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 +955,7 @@
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 +982,7 @@
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 +1078,7 @@
}
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 +1098,28 @@
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
}
}
@@ -1092,14 +1248,14 @@
// TODO(ccross): we need to use WalkDeps and have some way to know which dependencies require installation
ctx.VisitDepsDepthFirst(func(m blueprint.Module) {
if a, ok := m.(Module); ok {
- result = append(result, a.filesToInstall()...)
+ result = append(result, a.FilesToInstall()...)
}
})
return result
}
-func (m *ModuleBase) filesToInstall() InstallPaths {
+func (m *ModuleBase) FilesToInstall() InstallPaths {
return m.installFiles
}
@@ -1123,6 +1279,10 @@
return Bool(m.commonProperties.Ramdisk)
}
+func (m *ModuleBase) InstallInVendorRamdisk() bool {
+ return Bool(m.commonProperties.Vendor_ramdisk)
+}
+
func (m *ModuleBase) InstallInRecovery() bool {
return Bool(m.commonProperties.Recovery)
}
@@ -1172,6 +1332,10 @@
return m.base().commonProperties.ImageVariation == RamdiskVariation
}
+func (m *ModuleBase) InVendorRamdisk() bool {
+ return m.base().commonProperties.ImageVariation == VendorRamdiskVariation
+}
+
func (m *ModuleBase) InRecovery() bool {
return m.base().commonProperties.ImageVariation == RecoveryVariation
}
@@ -1350,8 +1514,8 @@
if !ctx.PrimaryArch() {
suffix = append(suffix, ctx.Arch().ArchType.String())
}
- if apex, ok := m.module.(ApexModule); ok && !apex.IsForPlatform() {
- suffix = append(suffix, apex.ApexVariationName())
+ if apexInfo := ctx.Provider(ApexInfoProvider).(ApexInfo); !apexInfo.IsForPlatform() {
+ suffix = append(suffix, apexInfo.ApexVariationName)
}
ctx.Variable(pctx, "moduleDesc", desc)
@@ -1557,6 +1721,21 @@
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)
@@ -1599,6 +1778,27 @@
m.Build(pctx, BuildParams(params))
}
+func validateBuildParams(params blueprint.BuildParams) error {
+ // Validate that the symlink outputs are declared outputs or implicit outputs
+ allOutputs := map[string]bool{}
+ for _, output := range params.Outputs {
+ allOutputs[output] = true
+ }
+ for _, output := range params.ImplicitOutputs {
+ allOutputs[output] = true
+ }
+ for _, symlinkOutput := range params.SymlinkOutputs {
+ if !allOutputs[symlinkOutput] {
+ return fmt.Errorf(
+ "Symlink output %s is not a declared output or implicit output",
+ symlinkOutput)
+ }
+ }
+ return nil
+}
+
+// Convert build parameters from their concrete Android types into their string representations,
+// and combine the singular and plural fields of the same type (e.g. Output and Outputs).
func convertBuildParams(params BuildParams) blueprint.BuildParams {
bparams := blueprint.BuildParams{
Rule: params.Rule,
@@ -1606,6 +1806,7 @@
Deps: params.Deps,
Outputs: params.Outputs.Strings(),
ImplicitOutputs: params.ImplicitOutputs.Strings(),
+ SymlinkOutputs: params.SymlinkOutputs.Strings(),
Inputs: params.Inputs.Strings(),
Implicits: params.Implicits.Strings(),
OrderOnly: params.OrderOnly.Strings(),
@@ -1620,6 +1821,9 @@
if params.Output != nil {
bparams.Outputs = append(bparams.Outputs, params.Output.String())
}
+ if params.SymlinkOutput != nil {
+ bparams.SymlinkOutputs = append(bparams.SymlinkOutputs, params.SymlinkOutput.String())
+ }
if params.ImplicitOutput != nil {
bparams.ImplicitOutputs = append(bparams.ImplicitOutputs, params.ImplicitOutput.String())
}
@@ -1635,6 +1839,7 @@
bparams.Outputs = proptools.NinjaEscapeList(bparams.Outputs)
bparams.ImplicitOutputs = proptools.NinjaEscapeList(bparams.ImplicitOutputs)
+ bparams.SymlinkOutputs = proptools.NinjaEscapeList(bparams.SymlinkOutputs)
bparams.Inputs = proptools.NinjaEscapeList(bparams.Inputs)
bparams.Implicits = proptools.NinjaEscapeList(bparams.Implicits)
bparams.OrderOnly = proptools.NinjaEscapeList(bparams.OrderOnly)
@@ -1691,7 +1896,15 @@
m.buildParams = append(m.buildParams, params)
}
- m.bp.Build(pctx.PackageContext, convertBuildParams(params))
+ bparams := convertBuildParams(params)
+ err := validateBuildParams(bparams)
+ if err != nil {
+ m.ModuleErrorf(
+ "%s: build parameter validation failed: %s",
+ m.ModuleName(),
+ err.Error())
+ }
+ m.bp.Build(pctx.PackageContext, bparams)
}
func (m *moduleContext) Phony(name string, deps ...Path) {
@@ -1877,6 +2090,20 @@
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 +2139,6 @@
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 +2164,7 @@
}
func (b *baseModuleContext) Host() bool {
- return b.os.Class == Host || b.os.Class == HostCross
+ return b.os.Class == Host
}
func (b *baseModuleContext) Device() bool {
@@ -2024,6 +2237,10 @@
return m.module.InstallInRamdisk()
}
+func (m *moduleContext) InstallInVendorRamdisk() bool {
+ return m.module.InstallInVendorRamdisk()
+}
+
func (m *moduleContext) InstallInRecovery() bool {
return m.module.InstallInRecovery()
}
@@ -2411,30 +2628,36 @@
}
// 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/module_test.go b/android/module_test.go
index 6e648d7..6cc1813 100644
--- a/android/module_test.go
+++ b/android/module_test.go
@@ -164,9 +164,6 @@
}
func TestErrorDependsOnDisabledModule(t *testing.T) {
- ctx := NewTestContext()
- ctx.RegisterModuleType("deps", depsModuleFactory)
-
bp := `
deps {
name: "foo",
@@ -180,10 +177,58 @@
config := TestConfig(buildDir, nil, bp, nil)
- ctx.Register(config)
+ ctx := NewTestContext(config)
+ ctx.RegisterModuleType("deps", depsModuleFactory)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
FailIfNoMatchingErrors(t, `module "foo": depends on disabled module "bar"`, errs)
}
+
+func TestValidateCorrectBuildParams(t *testing.T) {
+ config := TestConfig(buildDir, nil, "", nil)
+ pathContext := PathContextForTesting(config)
+ bparams := convertBuildParams(BuildParams{
+ // Test with Output
+ Output: PathForOutput(pathContext, "undeclared_symlink"),
+ SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"),
+ })
+
+ err := validateBuildParams(bparams)
+ if err != nil {
+ t.Error(err)
+ }
+
+ bparams = convertBuildParams(BuildParams{
+ // Test with ImplicitOutput
+ ImplicitOutput: PathForOutput(pathContext, "undeclared_symlink"),
+ SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"),
+ })
+
+ err = validateBuildParams(bparams)
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+func TestValidateIncorrectBuildParams(t *testing.T) {
+ config := TestConfig(buildDir, nil, "", nil)
+ pathContext := PathContextForTesting(config)
+ params := BuildParams{
+ Output: PathForOutput(pathContext, "regular_output"),
+ Outputs: PathsForOutput(pathContext, []string{"out1", "out2"}),
+ ImplicitOutput: PathForOutput(pathContext, "implicit_output"),
+ ImplicitOutputs: PathsForOutput(pathContext, []string{"i_out1", "_out2"}),
+ SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"),
+ }
+
+ bparams := convertBuildParams(params)
+ err := validateBuildParams(bparams)
+ if err != nil {
+ FailIfNoMatchingErrors(t, "undeclared_symlink is not a declared output or implicit output", []error{err})
+ } else {
+ t.Errorf("Expected build params to fail validation: %+v", bparams)
+ }
+}
diff --git a/android/mutator.go b/android/mutator.go
index 5212553..7a10477 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -179,15 +179,24 @@
finalDeps = append(finalDeps, f)
}
+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 {
- BaseModuleContext
+ BaseMutatorContext
- MutatorName() string
-
- Rename(name string)
-
+ // 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 BottomUpMutator func(BottomUpMutatorContext)
type BottomUpMutatorContext interface {
- BaseModuleContext
+ BaseMutatorContext
- MutatorName() 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
- Rename(name string)
-
- AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string)
+ // 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 @@
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) 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) 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/mutator_test.go b/android/mutator_test.go
index 191b535..1c395c7 100644
--- a/android/mutator_test.go
+++ b/android/mutator_test.go
@@ -70,7 +70,7 @@
config := TestConfig(buildDir, nil, bp, nil)
config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
- ctx := NewTestContext()
+ ctx := NewTestContext(config)
ctx.SetAllowMissingDependencies(true)
ctx.RegisterModuleType("test", mutatorTestModuleFactory)
@@ -78,7 +78,7 @@
ctx.TopDown("add_missing_dependencies", addMissingDependenciesMutator)
})
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
@@ -92,7 +92,15 @@
}
func TestModuleString(t *testing.T) {
- ctx := NewTestContext()
+ bp := `
+ test {
+ name: "foo",
+ }
+ `
+
+ config := TestConfig(buildDir, nil, bp, nil)
+
+ ctx := NewTestContext(config)
var moduleStrings []string
@@ -130,15 +138,7 @@
ctx.RegisterModuleType("test", mutatorTestModuleFactory)
- bp := `
- test {
- name: "foo",
- }
- `
-
- config := TestConfig(buildDir, nil, bp, nil)
-
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
FailIfErrored(t, errs)
@@ -190,7 +190,21 @@
}
func TestFinalDepsPhase(t *testing.T) {
- ctx := NewTestContext()
+ bp := `
+ test {
+ name: "common_dep_1",
+ }
+ test {
+ name: "common_dep_2",
+ }
+ test {
+ name: "foo",
+ }
+ `
+
+ config := TestConfig(buildDir, nil, bp, nil)
+
+ ctx := NewTestContext(config)
finalGot := map[string]int{}
@@ -228,20 +242,7 @@
ctx.RegisterModuleType("test", mutatorTestModuleFactory)
- bp := `
- test {
- name: "common_dep_1",
- }
- test {
- name: "common_dep_2",
- }
- test {
- name: "foo",
- }
- `
-
- config := TestConfig(buildDir, nil, bp, nil)
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
FailIfErrored(t, errs)
@@ -267,7 +268,8 @@
}
func TestNoCreateVariationsInFinalDeps(t *testing.T) {
- ctx := NewTestContext()
+ config := TestConfig(buildDir, nil, `test {name: "foo"}`, nil)
+ ctx := NewTestContext(config)
checkErr := func() {
if err := recover(); err == nil || !strings.Contains(fmt.Sprintf("%s", err), "not allowed in FinalDepsMutators") {
@@ -287,8 +289,7 @@
})
ctx.RegisterModuleType("test", mutatorTestModuleFactory)
- config := TestConfig(buildDir, nil, `test {name: "foo"}`, nil)
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
FailIfErrored(t, errs)
diff --git a/android/namespace_test.go b/android/namespace_test.go
index 66c0d89..45e2cdb 100644
--- a/android/namespace_test.go
+++ b/android/namespace_test.go
@@ -635,7 +635,7 @@
func setupTestFromFiles(bps map[string][]byte) (ctx *TestContext, errs []error) {
config := TestConfig(buildDir, nil, "", bps)
- ctx = NewTestContext()
+ ctx = NewTestContext(config)
ctx.RegisterModuleType("test_module", newTestModule)
ctx.RegisterModuleType("soong_namespace", NamespaceFactory)
ctx.Context.RegisterModuleType("blueprint_test_module", newBlueprintTestModule)
@@ -643,7 +643,7 @@
ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
ctx.BottomUp("rename", renameMutator)
})
- ctx.Register(config)
+ ctx.Register()
_, errs = ctx.ParseBlueprintsFiles("Android.bp")
if len(errs) > 0 {
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 56a07dc..1d454e5 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -359,14 +359,14 @@
}
func testNeverallow(config Config) (*TestContext, []error) {
- ctx := NewTestContext()
+ ctx := NewTestContext(config)
ctx.RegisterModuleType("cc_library", newMockCcLibraryModule)
ctx.RegisterModuleType("java_library", newMockJavaLibraryModule)
ctx.RegisterModuleType("java_library_host", newMockJavaLibraryModule)
ctx.RegisterModuleType("java_device_for_host", newMockJavaLibraryModule)
ctx.RegisterModuleType("makefile_goal", newMockMakefileGoalModule)
ctx.PostDepsMutators(RegisterNeverallowMutator)
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseBlueprintsFiles("Android.bp")
if len(errs) > 0 {
diff --git a/android/package_test.go b/android/package_test.go
index 04dfc08..ade95d4 100644
--- a/android/package_test.go
+++ b/android/package_test.go
@@ -86,9 +86,9 @@
// Create a new config per test as visibility information is stored in the config.
config := TestArchConfig(buildDir, nil, "", fs)
- ctx := NewTestArchContext()
+ ctx := NewTestArchContext(config)
RegisterPackageBuildComponents(ctx)
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseBlueprintsFiles(".")
if len(errs) > 0 {
diff --git a/android/path_properties_test.go b/android/path_properties_test.go
index f367b82..f964d9f 100644
--- a/android/path_properties_test.go
+++ b/android/path_properties_test.go
@@ -116,12 +116,12 @@
`
config := TestArchConfig(buildDir, nil, bp, nil)
- ctx := NewTestArchContext()
+ ctx := NewTestArchContext(config)
ctx.RegisterModuleType("test", pathDepsMutatorTestModuleFactory)
ctx.RegisterModuleType("filegroup", FileGroupFactory)
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
diff --git a/android/paths.go b/android/paths.go
index 3825d45..b13979d 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -58,6 +58,7 @@
InstallInTestcases() bool
InstallInSanitizerDir() bool
InstallInRamdisk() bool
+ InstallInVendorRamdisk() bool
InstallInRecovery() bool
InstallInRoot() bool
InstallBypassMake() bool
@@ -1236,7 +1237,12 @@
type InstallPath struct {
basePath
- baseDir string // "../" for Make paths to convert "out/soong" to "out", "" for Soong paths
+ // partitionDir is the part of the InstallPath that is automatically determined according to the context.
+ // For example, it is host/<os>-<arch> for host modules, and target/product/<device>/<partition> for device modules.
+ partitionDir string
+
+ // makePath indicates whether this path is for Soong (false) or Make (true).
+ makePath bool
}
func (p InstallPath) buildDir() string {
@@ -1249,7 +1255,23 @@
func (p InstallPath) writablePath() {}
func (p InstallPath) String() string {
- return filepath.Join(p.config.buildDir, p.baseDir, p.path)
+ if p.makePath {
+ // Make path starts with out/ instead of out/soong.
+ return filepath.Join(p.config.buildDir, "../", p.path)
+ } else {
+ return filepath.Join(p.config.buildDir, p.path)
+ }
+}
+
+// PartitionDir returns the path to the partition where the install path is rooted at. It is
+// out/soong/target/product/<device>/<partition> for device modules, and out/soong/host/<os>-<arch> for host modules.
+// The ./soong is dropped if the install path is for Make.
+func (p InstallPath) PartitionDir() string {
+ if p.makePath {
+ return filepath.Join(p.config.buildDir, "../", p.partitionDir)
+ } else {
+ return filepath.Join(p.config.buildDir, p.partitionDir)
+ }
}
// Join creates a new InstallPath with paths... joined with the current path. The
@@ -1270,7 +1292,7 @@
// ToMakePath returns a new InstallPath that points to Make's install directory instead of Soong's,
// i.e. out/ instead of out/soong/.
func (p InstallPath) ToMakePath() InstallPath {
- p.baseDir = "../"
+ p.makePath = true
return p
}
@@ -1300,10 +1322,10 @@
func pathForInstall(ctx PathContext, os OsType, arch ArchType, partition string, debug bool,
pathComponents ...string) InstallPath {
- var outPaths []string
+ var partionPaths []string
if os.Class == Device {
- outPaths = []string{"target", "product", ctx.Config().DeviceName(), partition}
+ partionPaths = []string{"target", "product", ctx.Config().DeviceName(), partition}
} else {
osName := os.String()
if os == Linux {
@@ -1319,30 +1341,33 @@
if os.Class == Host && (arch == X86_64 || arch == Common) {
archName = "x86"
}
- outPaths = []string{"host", osName + "-" + archName, partition}
+ partionPaths = []string{"host", osName + "-" + archName, partition}
}
if debug {
- outPaths = append([]string{"debug"}, outPaths...)
+ partionPaths = append([]string{"debug"}, partionPaths...)
}
- outPaths = append(outPaths, pathComponents...)
- path, err := validatePath(outPaths...)
+ partionPath, err := validatePath(partionPaths...)
if err != nil {
reportPathError(ctx, err)
}
- ret := InstallPath{basePath{path, ctx.Config(), ""}, ""}
+ base := InstallPath{
+ basePath: basePath{partionPath, ctx.Config(), ""},
+ partitionDir: partionPath,
+ makePath: false,
+ }
- return ret
+ return base.Join(ctx, pathComponents...)
}
func pathForNdkOrSdkInstall(ctx PathContext, prefix string, paths []string) InstallPath {
- paths = append([]string{prefix}, paths...)
- path, err := validatePath(paths...)
- if err != nil {
- reportPathError(ctx, err)
+ base := InstallPath{
+ basePath: basePath{prefix, ctx.Config(), ""},
+ partitionDir: prefix,
+ makePath: false,
}
- return InstallPath{basePath{path, ctx.Config(), ""}, ""}
+ return base.Join(ctx, paths...)
}
func PathForNdkInstall(ctx PathContext, paths ...string) InstallPath {
@@ -1376,6 +1401,19 @@
if !ctx.InstallInRoot() {
partition += "/system"
}
+ } else if ctx.InstallInVendorRamdisk() {
+ // The module is only available after switching root into
+ // /first_stage_ramdisk. To expose the module before switching root
+ // on a device without a dedicated recovery partition, install the
+ // recovery variant.
+ if ctx.DeviceConfig().BoardMoveRecoveryResourcesToVendorBoot() {
+ partition = "vendor-ramdisk/first_stage_ramdisk"
+ } else {
+ partition = "vendor-ramdisk"
+ }
+ if !ctx.InstallInRoot() {
+ partition += "/system"
+ }
} else if ctx.InstallInRecovery() {
if ctx.InstallInRoot() {
partition = "recovery/root"
@@ -1519,6 +1557,72 @@
}
}
+type testModuleInstallPathContext struct {
+ baseModuleContext
+
+ inData bool
+ inTestcases bool
+ inSanitizerDir bool
+ inRamdisk bool
+ inVendorRamdisk bool
+ inRecovery bool
+ inRoot bool
+ forceOS *OsType
+ forceArch *ArchType
+}
+
+func (m testModuleInstallPathContext) Config() Config {
+ return m.baseModuleContext.config
+}
+
+func (testModuleInstallPathContext) AddNinjaFileDeps(deps ...string) {}
+
+func (m testModuleInstallPathContext) InstallInData() bool {
+ return m.inData
+}
+
+func (m testModuleInstallPathContext) InstallInTestcases() bool {
+ return m.inTestcases
+}
+
+func (m testModuleInstallPathContext) InstallInSanitizerDir() bool {
+ return m.inSanitizerDir
+}
+
+func (m testModuleInstallPathContext) InstallInRamdisk() bool {
+ return m.inRamdisk
+}
+
+func (m testModuleInstallPathContext) InstallInVendorRamdisk() bool {
+ return m.inVendorRamdisk
+}
+
+func (m testModuleInstallPathContext) InstallInRecovery() bool {
+ return m.inRecovery
+}
+
+func (m testModuleInstallPathContext) InstallInRoot() bool {
+ return m.inRoot
+}
+
+func (m testModuleInstallPathContext) InstallBypassMake() bool {
+ return false
+}
+
+func (m testModuleInstallPathContext) InstallForceOS() (*OsType, *ArchType) {
+ return m.forceOS, m.forceArch
+}
+
+// Construct a minimal ModuleInstallPathContext for testing. Note that baseModuleContext is
+// default-initialized, which leaves blueprint.baseModuleContext set to nil, so methods that are
+// delegated to it will panic.
+func ModuleInstallPathContextForTesting(config Config) ModuleInstallPathContext {
+ ctx := &testModuleInstallPathContext{}
+ ctx.config = config
+ ctx.os = Android
+ return ctx
+}
+
// Rel performs the same function as filepath.Rel, but reports errors to a PathContext, and reports an error if
// targetPath is not inside basePath.
func Rel(ctx PathContext, basePath string, targetPath string) string {
diff --git a/android/paths_test.go b/android/paths_test.go
index d099f65..14a4773 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -197,57 +197,6 @@
}
}
-type moduleInstallPathContextImpl struct {
- baseModuleContext
-
- inData bool
- inTestcases bool
- inSanitizerDir bool
- inRamdisk bool
- inRecovery bool
- inRoot bool
- forceOS *OsType
- forceArch *ArchType
-}
-
-func (m moduleInstallPathContextImpl) Config() Config {
- return m.baseModuleContext.config
-}
-
-func (moduleInstallPathContextImpl) AddNinjaFileDeps(deps ...string) {}
-
-func (m moduleInstallPathContextImpl) InstallInData() bool {
- return m.inData
-}
-
-func (m moduleInstallPathContextImpl) InstallInTestcases() bool {
- return m.inTestcases
-}
-
-func (m moduleInstallPathContextImpl) InstallInSanitizerDir() bool {
- return m.inSanitizerDir
-}
-
-func (m moduleInstallPathContextImpl) InstallInRamdisk() bool {
- return m.inRamdisk
-}
-
-func (m moduleInstallPathContextImpl) InstallInRecovery() bool {
- return m.inRecovery
-}
-
-func (m moduleInstallPathContextImpl) InstallInRoot() bool {
- return m.inRoot
-}
-
-func (m moduleInstallPathContextImpl) InstallBypassMake() bool {
- return false
-}
-
-func (m moduleInstallPathContextImpl) InstallForceOS() (*OsType, *ArchType) {
- return m.forceOS, m.forceArch
-}
-
func pathTestConfig(buildDir string) Config {
return TestConfig(buildDir, nil, "", nil)
}
@@ -259,37 +208,40 @@
deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
testCases := []struct {
- name string
- ctx *moduleInstallPathContextImpl
- in []string
- out string
+ name string
+ ctx *testModuleInstallPathContext
+ in []string
+ out string
+ partitionDir string
}{
{
name: "host binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: hostTarget.Os,
target: hostTarget,
},
},
- in: []string{"bin", "my_test"},
- out: "host/linux-x86/bin/my_test",
+ in: []string{"bin", "my_test"},
+ out: "host/linux-x86/bin/my_test",
+ partitionDir: "host/linux-x86",
},
{
name: "system binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
},
},
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/system/bin/my_test",
+ in: []string{"bin", "my_test"},
+ out: "target/product/test_device/system/bin/my_test",
+ partitionDir: "target/product/test_device/system",
},
{
name: "vendor binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
@@ -298,12 +250,13 @@
},
},
},
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/vendor/bin/my_test",
+ in: []string{"bin", "my_test"},
+ out: "target/product/test_device/vendor/bin/my_test",
+ partitionDir: "target/product/test_device/vendor",
},
{
name: "odm binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
@@ -312,12 +265,13 @@
},
},
},
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/odm/bin/my_test",
+ in: []string{"bin", "my_test"},
+ out: "target/product/test_device/odm/bin/my_test",
+ partitionDir: "target/product/test_device/odm",
},
{
name: "product binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
@@ -326,12 +280,13 @@
},
},
},
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/product/bin/my_test",
+ in: []string{"bin", "my_test"},
+ out: "target/product/test_device/product/bin/my_test",
+ partitionDir: "target/product/test_device/product",
},
{
name: "system_ext binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
@@ -340,36 +295,39 @@
},
},
},
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/system_ext/bin/my_test",
+ in: []string{"bin", "my_test"},
+ out: "target/product/test_device/system_ext/bin/my_test",
+ partitionDir: "target/product/test_device/system_ext",
},
{
name: "root binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
},
inRoot: true,
},
- in: []string{"my_test"},
- out: "target/product/test_device/root/my_test",
+ in: []string{"my_test"},
+ out: "target/product/test_device/root/my_test",
+ partitionDir: "target/product/test_device/root",
},
{
name: "recovery binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
},
inRecovery: true,
},
- in: []string{"bin/my_test"},
- out: "target/product/test_device/recovery/root/system/bin/my_test",
+ in: []string{"bin/my_test"},
+ out: "target/product/test_device/recovery/root/system/bin/my_test",
+ partitionDir: "target/product/test_device/recovery/root/system",
},
{
name: "recovery root binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
@@ -377,25 +335,27 @@
inRecovery: true,
inRoot: true,
},
- in: []string{"my_test"},
- out: "target/product/test_device/recovery/root/my_test",
+ in: []string{"my_test"},
+ out: "target/product/test_device/recovery/root/my_test",
+ partitionDir: "target/product/test_device/recovery/root",
},
{
name: "system native test binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
},
inData: true,
},
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/nativetest/my_test",
+ in: []string{"nativetest", "my_test"},
+ out: "target/product/test_device/data/nativetest/my_test",
+ partitionDir: "target/product/test_device/data",
},
{
name: "vendor native test binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
@@ -405,12 +365,13 @@
},
inData: true,
},
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/nativetest/my_test",
+ in: []string{"nativetest", "my_test"},
+ out: "target/product/test_device/data/nativetest/my_test",
+ partitionDir: "target/product/test_device/data",
},
{
name: "odm native test binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
@@ -420,12 +381,13 @@
},
inData: true,
},
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/nativetest/my_test",
+ in: []string{"nativetest", "my_test"},
+ out: "target/product/test_device/data/nativetest/my_test",
+ partitionDir: "target/product/test_device/data",
},
{
name: "product native test binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
@@ -435,13 +397,14 @@
},
inData: true,
},
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/nativetest/my_test",
+ in: []string{"nativetest", "my_test"},
+ out: "target/product/test_device/data/nativetest/my_test",
+ partitionDir: "target/product/test_device/data",
},
{
name: "system_ext native test binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
@@ -451,25 +414,27 @@
},
inData: true,
},
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/nativetest/my_test",
+ in: []string{"nativetest", "my_test"},
+ out: "target/product/test_device/data/nativetest/my_test",
+ partitionDir: "target/product/test_device/data",
},
{
name: "sanitized system binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
},
inSanitizerDir: true,
},
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/data/asan/system/bin/my_test",
+ in: []string{"bin", "my_test"},
+ out: "target/product/test_device/data/asan/system/bin/my_test",
+ partitionDir: "target/product/test_device/data/asan/system",
},
{
name: "sanitized vendor binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
@@ -479,12 +444,13 @@
},
inSanitizerDir: true,
},
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/data/asan/vendor/bin/my_test",
+ in: []string{"bin", "my_test"},
+ out: "target/product/test_device/data/asan/vendor/bin/my_test",
+ partitionDir: "target/product/test_device/data/asan/vendor",
},
{
name: "sanitized odm binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
@@ -494,12 +460,13 @@
},
inSanitizerDir: true,
},
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/data/asan/odm/bin/my_test",
+ in: []string{"bin", "my_test"},
+ out: "target/product/test_device/data/asan/odm/bin/my_test",
+ partitionDir: "target/product/test_device/data/asan/odm",
},
{
name: "sanitized product binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
@@ -509,13 +476,14 @@
},
inSanitizerDir: true,
},
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/data/asan/product/bin/my_test",
+ in: []string{"bin", "my_test"},
+ out: "target/product/test_device/data/asan/product/bin/my_test",
+ partitionDir: "target/product/test_device/data/asan/product",
},
{
name: "sanitized system_ext binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
@@ -525,13 +493,14 @@
},
inSanitizerDir: true,
},
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/data/asan/system_ext/bin/my_test",
+ in: []string{"bin", "my_test"},
+ out: "target/product/test_device/data/asan/system_ext/bin/my_test",
+ partitionDir: "target/product/test_device/data/asan/system_ext",
},
{
name: "sanitized system native test binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
@@ -539,12 +508,13 @@
inData: true,
inSanitizerDir: true,
},
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/asan/data/nativetest/my_test",
+ in: []string{"nativetest", "my_test"},
+ out: "target/product/test_device/data/asan/data/nativetest/my_test",
+ partitionDir: "target/product/test_device/data/asan/data",
},
{
name: "sanitized vendor native test binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
@@ -555,12 +525,13 @@
inData: true,
inSanitizerDir: true,
},
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/asan/data/nativetest/my_test",
+ in: []string{"nativetest", "my_test"},
+ out: "target/product/test_device/data/asan/data/nativetest/my_test",
+ partitionDir: "target/product/test_device/data/asan/data",
},
{
name: "sanitized odm native test binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
@@ -571,12 +542,13 @@
inData: true,
inSanitizerDir: true,
},
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/asan/data/nativetest/my_test",
+ in: []string{"nativetest", "my_test"},
+ out: "target/product/test_device/data/asan/data/nativetest/my_test",
+ partitionDir: "target/product/test_device/data/asan/data",
},
{
name: "sanitized product native test binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
@@ -587,12 +559,13 @@
inData: true,
inSanitizerDir: true,
},
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/asan/data/nativetest/my_test",
+ in: []string{"nativetest", "my_test"},
+ out: "target/product/test_device/data/asan/data/nativetest/my_test",
+ partitionDir: "target/product/test_device/data/asan/data",
},
{
name: "sanitized system_ext native test binary",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
@@ -603,33 +576,36 @@
inData: true,
inSanitizerDir: true,
},
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/asan/data/nativetest/my_test",
+ in: []string{"nativetest", "my_test"},
+ out: "target/product/test_device/data/asan/data/nativetest/my_test",
+ partitionDir: "target/product/test_device/data/asan/data",
}, {
name: "device testcases",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
},
inTestcases: true,
},
- in: []string{"my_test", "my_test_bin"},
- out: "target/product/test_device/testcases/my_test/my_test_bin",
+ in: []string{"my_test", "my_test_bin"},
+ out: "target/product/test_device/testcases/my_test/my_test_bin",
+ partitionDir: "target/product/test_device/testcases",
}, {
name: "host testcases",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: hostTarget.Os,
target: hostTarget,
},
inTestcases: true,
},
- in: []string{"my_test", "my_test_bin"},
- out: "host/linux-x86/testcases/my_test/my_test_bin",
+ in: []string{"my_test", "my_test_bin"},
+ out: "host/linux-x86/testcases/my_test/my_test_bin",
+ partitionDir: "host/linux-x86/testcases",
}, {
name: "forced host testcases",
- ctx: &moduleInstallPathContextImpl{
+ ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
@@ -638,8 +614,9 @@
forceOS: &Linux,
forceArch: &X86,
},
- in: []string{"my_test", "my_test_bin"},
- out: "host/linux-x86/testcases/my_test/my_test_bin",
+ in: []string{"my_test", "my_test_bin"},
+ out: "host/linux-x86/testcases/my_test/my_test_bin",
+ partitionDir: "host/linux-x86/testcases",
},
}
@@ -652,10 +629,48 @@
output.basePath.path,
tc.out)
}
+ if output.partitionDir != tc.partitionDir {
+ t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n",
+ output.partitionDir, tc.partitionDir)
+ }
})
}
}
+func TestBaseDirForInstallPath(t *testing.T) {
+ testConfig := pathTestConfig("")
+ deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
+
+ ctx := &testModuleInstallPathContext{
+ baseModuleContext: baseModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
+ }
+ ctx.baseModuleContext.config = testConfig
+
+ actual := PathForModuleInstall(ctx, "foo", "bar")
+ expectedBaseDir := "target/product/test_device/system"
+ if actual.partitionDir != expectedBaseDir {
+ t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n", actual.partitionDir, expectedBaseDir)
+ }
+ expectedRelPath := "foo/bar"
+ if actual.Rel() != expectedRelPath {
+ t.Errorf("unexpected Rel():\n got: %q\nwant: %q\n", actual.Rel(), expectedRelPath)
+ }
+
+ actualAfterJoin := actual.Join(ctx, "baz")
+ // partitionDir is preserved even after joining
+ if actualAfterJoin.partitionDir != expectedBaseDir {
+ t.Errorf("unexpected partitionDir after joining:\n got: %q\nwant: %q\n", actualAfterJoin.partitionDir, expectedBaseDir)
+ }
+ // Rel() is updated though
+ expectedRelAfterJoin := "baz"
+ if actualAfterJoin.Rel() != expectedRelAfterJoin {
+ t.Errorf("unexpected Rel() after joining:\n got: %q\nwant: %q\n", actualAfterJoin.Rel(), expectedRelAfterJoin)
+ }
+}
+
func TestDirectorySortedPaths(t *testing.T) {
config := TestConfig("out", nil, "", map[string][]byte{
"Android.bp": nil,
@@ -965,12 +980,6 @@
func testPathForModuleSrc(t *testing.T, buildDir string, tests []pathForModuleSrcTestCase) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
- ctx := NewTestContext()
-
- ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
- ctx.RegisterModuleType("output_file_provider", pathForModuleSrcOutputFileProviderModuleFactory)
- ctx.RegisterModuleType("filegroup", FileGroupFactory)
-
fgBp := `
filegroup {
name: "a",
@@ -1000,7 +1009,13 @@
config := TestConfig(buildDir, nil, "", mockFS)
- ctx.Register(config)
+ ctx := NewTestContext(config)
+
+ ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
+ ctx.RegisterModuleType("output_file_provider", pathForModuleSrcOutputFileProviderModuleFactory)
+ ctx.RegisterModuleType("filegroup", FileGroupFactory)
+
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"fg/Android.bp", "foo/Android.bp", "ofp/Android.bp"})
FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
@@ -1209,12 +1224,12 @@
config := TestConfig(buildDir, nil, bp, nil)
config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
- ctx := NewTestContext()
+ ctx := NewTestContext(config)
ctx.SetAllowMissingDependencies(true)
ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
FailIfErrored(t, errs)
@@ -1260,7 +1275,7 @@
// boot.art boot.oat
}
-func ExampleOutputPath_FileInSameDir() {
+func ExampleOutputPath_InSameDir() {
ctx := &configErrorWrapper{
config: TestConfig("out", nil, "", nil),
}
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 734871b..294a6e0 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -93,7 +93,7 @@
// more modules like this.
func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path {
if p.srcsSupplier != nil {
- srcs := p.srcsSupplier()
+ srcs := p.srcsSupplier(ctx)
if len(srcs) == 0 {
ctx.PropertyErrorf(p.srcsPropertyName, "missing prebuilt source file")
@@ -122,7 +122,7 @@
// Called to provide the srcs value for the prebuilt module.
//
// Return the src value or nil if it is not available.
-type PrebuiltSrcsSupplier func() []string
+type PrebuiltSrcsSupplier func(ctx BaseModuleContext) []string
// Initialize the module as a prebuilt module that uses the provided supplier to access the
// prebuilt sources of the module.
@@ -156,7 +156,7 @@
panic(fmt.Errorf("srcs must not be nil"))
}
- srcsSupplier := func() []string {
+ srcsSupplier := func(ctx BaseModuleContext) []string {
return *srcs
}
@@ -177,7 +177,7 @@
srcFieldIndex := srcStructField.Index
srcPropertyName := proptools.PropertyNameForField(srcField)
- srcsSupplier := func() []string {
+ srcsSupplier := func(ctx BaseModuleContext) []string {
value := srcPropsValue.FieldByIndex(srcFieldIndex)
if value.Kind() == reflect.Ptr {
value = value.Elem()
@@ -287,7 +287,7 @@
// usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt
// will be used if it is marked "prefer" or if the source module is disabled.
func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool {
- if p.srcsSupplier != nil && len(p.srcsSupplier()) == 0 {
+ if p.srcsSupplier != nil && len(p.srcsSupplier(ctx)) == 0 {
return false
}
diff --git a/android/prebuilt_build_tool.go b/android/prebuilt_build_tool.go
index 1dcf199..e2555e4 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 @@
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 6c3cd9e..9ac3875 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -285,13 +285,13 @@
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()
+ ctx := NewTestArchContext(config)
registerTestPrebuiltBuildComponents(ctx)
ctx.RegisterModuleType("filegroup", FileGroupFactory)
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseBlueprintsFiles("Android.bp")
FailIfErrored(t, errs)
diff --git a/android/queryview.go b/android/queryview.go
new file mode 100644
index 0000000..970ae01
--- /dev/null
+++ b/android/queryview.go
@@ -0,0 +1,78 @@
+// 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 android
+
+import (
+ "fmt"
+ "os"
+ "strings"
+
+ "github.com/google/blueprint"
+)
+
+// The Bazel QueryView singleton is responsible for generating the Ninja actions
+// for calling the soong_build primary builder in the main build.ninja file.
+func init() {
+ RegisterSingletonType("bazel_queryview", BazelQueryViewSingleton)
+}
+
+func BazelQueryViewSingleton() Singleton {
+ return &bazelQueryViewSingleton{}
+}
+
+type bazelQueryViewSingleton struct{}
+
+func (c *bazelQueryViewSingleton) GenerateBuildActions(ctx SingletonContext) {
+ // Create a build and rule statement, using the Bazel QueryView's WORKSPACE
+ // file as the output file marker.
+ var deps Paths
+ moduleListFilePath := pathForBuildToolDep(ctx, ctx.Config().moduleListFile)
+ deps = append(deps, moduleListFilePath)
+ deps = append(deps, pathForBuildToolDep(ctx, ctx.Config().ProductVariablesFileName))
+
+ bazelQueryViewDirectory := PathForOutput(ctx, "queryview")
+ bazelQueryViewWorkspaceFile := bazelQueryViewDirectory.Join(ctx, "WORKSPACE")
+ primaryBuilder := primaryBuilderPath(ctx)
+ bazelQueryView := ctx.Rule(pctx, "bazelQueryView",
+ blueprint.RuleParams{
+ Command: fmt.Sprintf(
+ "rm -rf ${outDir}/* && "+
+ "%s --bazel_queryview_dir ${outDir} %s && "+
+ "echo WORKSPACE: `cat %s` > ${outDir}/.queryview-depfile.d",
+ primaryBuilder.String(),
+ strings.Join(os.Args[1:], " "),
+ moduleListFilePath.String(), // Use the contents of Android.bp.list as the depfile.
+ ),
+ CommandDeps: []string{primaryBuilder.String()},
+ Description: fmt.Sprintf(
+ "[EXPERIMENTAL, PRE-PRODUCTION] Creating the Bazel QueryView workspace with %s at $outDir",
+ primaryBuilder.Base()),
+ Deps: blueprint.DepsGCC,
+ Depfile: "${outDir}/.queryview-depfile.d",
+ },
+ "outDir")
+
+ ctx.Build(pctx, BuildParams{
+ Rule: bazelQueryView,
+ Output: bazelQueryViewWorkspaceFile,
+ Inputs: deps,
+ Args: map[string]string{
+ "outDir": bazelQueryViewDirectory.String(),
+ },
+ })
+
+ // Add a phony target for building the Bazel QueryView
+ ctx.Phony("queryview", bazelQueryViewWorkspaceFile)
+}
diff --git a/android/register.go b/android/register.go
index 036a811..bd824c9 100644
--- a/android/register.go
+++ b/android/register.go
@@ -81,10 +81,11 @@
type Context struct {
*blueprint.Context
+ config Config
}
-func NewContext() *Context {
- ctx := &Context{blueprint.NewContext()}
+func NewContext(config Config) *Context {
+ ctx := &Context{blueprint.NewContext(), config}
ctx.SetSrcDir(absSrcDir)
return ctx
}
@@ -104,6 +105,8 @@
registerMutators(ctx.Context, preArch, preDeps, postDeps, finalDeps)
+ ctx.RegisterSingletonType("bazeldeps", SingletonFactoryAdaptor(BazelSingleton))
+
// Register phony just before makevars so it can write out its phony rules as Make rules
ctx.RegisterSingletonType("phony", SingletonFactoryAdaptor(phonySingletonFactory))
@@ -155,7 +158,7 @@
// Extracting the actual registration into a separate RegisterBuildComponents(ctx) function
// allows it to be used to initialize test context, e.g.
//
-// ctx := android.NewTestContext()
+// ctx := android.NewTestContext(config)
// RegisterBuildComponents(ctx)
var InitRegistrationContext RegistrationContext = &initRegistrationContext{
moduleTypes: make(map[string]ModuleFactory),
diff --git a/android/rule_builder.go b/android/rule_builder.go
index afb5f4e..8dc9d6a 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -246,6 +246,41 @@
return outputList
}
+func (r *RuleBuilder) symlinkOutputSet() map[string]WritablePath {
+ symlinkOutputs := make(map[string]WritablePath)
+ for _, c := range r.commands {
+ for _, symlinkOutput := range c.symlinkOutputs {
+ symlinkOutputs[symlinkOutput.String()] = symlinkOutput
+ }
+ }
+ return symlinkOutputs
+}
+
+// SymlinkOutputs returns the list of paths that the executor (Ninja) would
+// verify, after build edge completion, that:
+//
+// 1) Created output symlinks match the list of paths in this list exactly (no more, no fewer)
+// 2) Created output files are *not* declared in this list.
+//
+// These symlink outputs are expected to be a subset of outputs or implicit
+// outputs, or they would fail validation at build param construction time
+// later, to support other non-rule-builder approaches for constructing
+// statements.
+func (r *RuleBuilder) SymlinkOutputs() WritablePaths {
+ symlinkOutputs := r.symlinkOutputSet()
+
+ var symlinkOutputList WritablePaths
+ for _, symlinkOutput := range symlinkOutputs {
+ symlinkOutputList = append(symlinkOutputList, symlinkOutput)
+ }
+
+ sort.Slice(symlinkOutputList, func(i, j int) bool {
+ return symlinkOutputList[i].String() < symlinkOutputList[j].String()
+ })
+
+ return symlinkOutputList
+}
+
func (r *RuleBuilder) depFileSet() map[string]WritablePath {
depFiles := make(map[string]WritablePath)
for _, c := range r.commands {
@@ -467,6 +502,7 @@
Implicits: r.Inputs(),
Output: output,
ImplicitOutputs: implicitOutputs,
+ SymlinkOutputs: r.SymlinkOutputs(),
Depfile: depFile,
Deps: depFormat,
Description: desc,
@@ -478,14 +514,15 @@
// RuleBuilderCommand, so they can be used chained or unchained. All methods that add text implicitly add a single
// space as a separator from the previous method.
type RuleBuilderCommand struct {
- buf strings.Builder
- inputs Paths
- implicits Paths
- orderOnlys Paths
- outputs WritablePaths
- depFiles WritablePaths
- tools Paths
- rspFileInputs Paths
+ buf strings.Builder
+ inputs Paths
+ implicits Paths
+ orderOnlys Paths
+ outputs WritablePaths
+ symlinkOutputs WritablePaths
+ depFiles WritablePaths
+ tools Paths
+ rspFileInputs Paths
// spans [start,end) of the command that should not be ninja escaped
unescapedSpans [][2]int
@@ -715,6 +752,40 @@
return c
}
+// ImplicitSymlinkOutput declares the specified path as an implicit output that
+// will be a symlink instead of a regular file. Does not modify the command
+// line.
+func (c *RuleBuilderCommand) ImplicitSymlinkOutput(path WritablePath) *RuleBuilderCommand {
+ c.symlinkOutputs = append(c.symlinkOutputs, path)
+ return c.ImplicitOutput(path)
+}
+
+// ImplicitSymlinkOutputs declares the specified paths as implicit outputs that
+// will be a symlinks instead of regular files. Does not modify the command
+// line.
+func (c *RuleBuilderCommand) ImplicitSymlinkOutputs(paths WritablePaths) *RuleBuilderCommand {
+ for _, path := range paths {
+ c.ImplicitSymlinkOutput(path)
+ }
+ return c
+}
+
+// SymlinkOutput declares the specified path as an output that will be a symlink
+// instead of a regular file. Modifies the command line.
+func (c *RuleBuilderCommand) SymlinkOutput(path WritablePath) *RuleBuilderCommand {
+ c.symlinkOutputs = append(c.symlinkOutputs, path)
+ return c.Output(path)
+}
+
+// SymlinkOutputsl declares the specified paths as outputs that will be symlinks
+// instead of regular files. Modifies the command line.
+func (c *RuleBuilderCommand) SymlinkOutputs(paths WritablePaths) *RuleBuilderCommand {
+ for _, path := range paths {
+ c.SymlinkOutput(path)
+ }
+ return c
+}
+
// ImplicitDepFile adds the specified depfile path to the paths returned by RuleBuilder.DepFiles without modifying
// the command line, and causes RuleBuilder.Build file to set the depfile flag for ninja. If multiple depfiles
// are added to commands in a single RuleBuilder then RuleBuilder.Build will add an extra command to merge the
diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go
index c41b067..ca6359d 100644
--- a/android/rule_builder_test.go
+++ b/android/rule_builder_test.go
@@ -35,6 +35,7 @@
"a": nil,
"b": nil,
"ls": nil,
+ "ln": nil,
"turbine": nil,
"java": nil,
"javac": nil,
@@ -67,6 +68,32 @@
// outputs: ["out/linked"]
}
+func ExampleRuleBuilder_SymlinkOutputs() {
+ rule := NewRuleBuilder()
+
+ ctx := pathContext()
+
+ rule.Command().
+ Tool(PathForSource(ctx, "ln")).
+ FlagWithInput("-s ", PathForTesting("a.o")).
+ SymlinkOutput(PathForOutput(ctx, "a"))
+ rule.Command().Text("cp out/a out/b").
+ ImplicitSymlinkOutput(PathForOutput(ctx, "b"))
+
+ fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && "))
+ fmt.Printf("tools: %q\n", rule.Tools())
+ fmt.Printf("inputs: %q\n", rule.Inputs())
+ fmt.Printf("outputs: %q\n", rule.Outputs())
+ fmt.Printf("symlink_outputs: %q\n", rule.SymlinkOutputs())
+
+ // Output:
+ // commands: "ln -s a.o out/a && cp out/a out/b"
+ // tools: ["ln"]
+ // inputs: ["a.o"]
+ // outputs: ["out/a" "out/b"]
+ // symlink_outputs: ["out/a" "out/b"]
+}
+
func ExampleRuleBuilder_Temporary() {
rule := NewRuleBuilder()
@@ -293,6 +320,8 @@
Input(PathForSource(ctx, "Input")).
Output(PathForOutput(ctx, "Output")).
OrderOnly(PathForSource(ctx, "OrderOnly")).
+ SymlinkOutput(PathForOutput(ctx, "SymlinkOutput")).
+ ImplicitSymlinkOutput(PathForOutput(ctx, "ImplicitSymlinkOutput")).
Text("Text").
Tool(PathForSource(ctx, "Tool"))
@@ -318,17 +347,18 @@
}
wantInputs := PathsForSource(ctx, []string{"Implicit", "Input", "input", "input2", "input3"})
- wantOutputs := PathsForOutput(ctx, []string{"ImplicitOutput", "Output", "output", "output2", "output3"})
+ wantOutputs := PathsForOutput(ctx, []string{"ImplicitOutput", "ImplicitSymlinkOutput", "Output", "SymlinkOutput", "output", "output2", "output3"})
wantDepFiles := PathsForOutput(ctx, []string{"DepFile", "depfile", "ImplicitDepFile", "depfile2"})
wantTools := PathsForSource(ctx, []string{"Tool", "tool2"})
wantOrderOnlys := PathsForSource(ctx, []string{"OrderOnly", "OrderOnlys"})
+ wantSymlinkOutputs := PathsForOutput(ctx, []string{"ImplicitSymlinkOutput", "SymlinkOutput"})
t.Run("normal", func(t *testing.T) {
rule := NewRuleBuilder()
addCommands(rule)
wantCommands := []string{
- "out/DepFile Flag FlagWithArg=arg FlagWithDepFile=out/depfile FlagWithInput=input FlagWithOutput=out/output Input out/Output Text Tool after command2 old cmd",
+ "out/DepFile Flag FlagWithArg=arg FlagWithDepFile=out/depfile FlagWithInput=input FlagWithOutput=out/output Input out/Output out/SymlinkOutput Text Tool after command2 old cmd",
"command2 out/depfile2 input2 out/output2 tool2",
"command3 input3 out/output2 out/output3",
}
@@ -345,6 +375,9 @@
if g, w := rule.Outputs(), wantOutputs; !reflect.DeepEqual(w, g) {
t.Errorf("\nwant rule.Outputs() = %#v\n got %#v", w, g)
}
+ if g, w := rule.SymlinkOutputs(), wantSymlinkOutputs; !reflect.DeepEqual(w, g) {
+ t.Errorf("\nwant rule.SymlinkOutputs() = %#v\n got %#v", w, g)
+ }
if g, w := rule.DepFiles(), wantDepFiles; !reflect.DeepEqual(w, g) {
t.Errorf("\nwant rule.DepFiles() = %#v\n got %#v", w, g)
}
@@ -365,7 +398,7 @@
addCommands(rule)
wantCommands := []string{
- "__SBOX_OUT_DIR__/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_OUT_DIR__/depfile FlagWithInput=input FlagWithOutput=__SBOX_OUT_DIR__/output Input __SBOX_OUT_DIR__/Output Text Tool after command2 old cmd",
+ "__SBOX_OUT_DIR__/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_OUT_DIR__/depfile FlagWithInput=input FlagWithOutput=__SBOX_OUT_DIR__/output Input __SBOX_OUT_DIR__/Output __SBOX_OUT_DIR__/SymlinkOutput Text Tool after command2 old cmd",
"command2 __SBOX_OUT_DIR__/depfile2 input2 __SBOX_OUT_DIR__/output2 tool2",
"command3 input3 __SBOX_OUT_DIR__/output2 __SBOX_OUT_DIR__/output3",
}
@@ -474,10 +507,10 @@
`
config := TestConfig(buildDir, nil, bp, fs)
- ctx := NewTestContext()
+ ctx := NewTestContext(config)
ctx.RegisterModuleType("rule_builder_test", testRuleBuilderFactory)
ctx.RegisterSingletonType("rule_builder_test", testRuleBuilderSingletonFactory)
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
FailIfErrored(t, errs)
diff --git a/android/sdk.go b/android/sdk.go
index 9ea7ff4..f2cdc88 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -237,9 +237,25 @@
// * 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 2c51c6c..bb6614d 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -29,6 +29,16 @@
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
@@ -158,6 +168,10 @@
s.buildParams = append(s.buildParams, params)
}
bparams := convertBuildParams(params)
+ err := validateBuildParams(bparams)
+ if err != nil {
+ s.Errorf("%s: build parameter validation failed: %s", s.Name(), err.Error())
+ }
s.SingletonContext.Build(pctx.PackageContext, bparams)
}
diff --git a/android/soong_config_modules_test.go b/android/soong_config_modules_test.go
index f905b1a..b1810b3 100644
--- a/android/soong_config_modules_test.go
+++ b/android/soong_config_modules_test.go
@@ -19,8 +19,24 @@
"testing"
)
+type soongConfigTestDefaultsModuleProperties struct {
+}
+
+type soongConfigTestDefaultsModule struct {
+ ModuleBase
+ DefaultsModuleBase
+}
+
+func soongConfigTestDefaultsModuleFactory() Module {
+ m := &soongConfigTestDefaultsModule{}
+ m.AddProperties(&soongConfigTestModuleProperties{})
+ InitDefaultsModule(m)
+ return m
+}
+
type soongConfigTestModule struct {
ModuleBase
+ DefaultableModuleBase
props soongConfigTestModuleProperties
}
@@ -32,6 +48,7 @@
m := &soongConfigTestModule{}
m.AddProperties(&m.props)
InitAndroidModule(m)
+ InitDefaultableModule(m)
return m
}
@@ -40,13 +57,13 @@
func TestSoongConfigModule(t *testing.T) {
configBp := `
soong_config_module_type {
- name: "acme_test_defaults",
- module_type: "test_defaults",
+ name: "acme_test",
+ module_type: "test",
config_namespace: "acme",
variables: ["board", "feature1", "FEATURE3"],
bool_variables: ["feature2"],
value_variables: ["size"],
- properties: ["cflags", "srcs"],
+ properties: ["cflags", "srcs", "defaults"],
}
soong_config_string_variable {
@@ -66,14 +83,20 @@
importBp := `
soong_config_module_type_import {
from: "SoongConfig.bp",
- module_types: ["acme_test_defaults"],
+ module_types: ["acme_test"],
}
`
bp := `
- acme_test_defaults {
+ test_defaults {
+ name: "foo_defaults",
+ cflags: ["DEFAULT"],
+ }
+
+ acme_test {
name: "foo",
cflags: ["-DGENERIC"],
+ defaults: ["foo_defaults"],
soong_config_variables: {
board: {
soc_a: {
@@ -97,6 +120,46 @@
},
},
}
+
+ test_defaults {
+ name: "foo_defaults_a",
+ cflags: ["DEFAULT_A"],
+ }
+
+ test_defaults {
+ name: "foo_defaults_b",
+ cflags: ["DEFAULT_B"],
+ }
+
+ acme_test {
+ name: "foo_with_defaults",
+ cflags: ["-DGENERIC"],
+ defaults: ["foo_defaults"],
+ soong_config_variables: {
+ board: {
+ soc_a: {
+ cflags: ["-DSOC_A"],
+ defaults: ["foo_defaults_a"],
+ },
+ soc_b: {
+ cflags: ["-DSOC_B"],
+ defaults: ["foo_defaults_b"],
+ },
+ },
+ size: {
+ cflags: ["-DSIZE=%s"],
+ },
+ feature1: {
+ cflags: ["-DFEATURE1"],
+ },
+ feature2: {
+ cflags: ["-DFEATURE2"],
+ },
+ FEATURE3: {
+ cflags: ["-DFEATURE3"],
+ },
+ },
+ }
`
run := func(t *testing.T, bp string, fs map[string][]byte) {
@@ -112,23 +175,33 @@
},
}
- ctx := NewTestContext()
+ ctx := NewTestContext(config)
ctx.RegisterModuleType("soong_config_module_type_import", soongConfigModuleTypeImportFactory)
ctx.RegisterModuleType("soong_config_module_type", soongConfigModuleTypeFactory)
ctx.RegisterModuleType("soong_config_string_variable", soongConfigStringVariableDummyFactory)
ctx.RegisterModuleType("soong_config_bool_variable", soongConfigBoolVariableDummyFactory)
- ctx.RegisterModuleType("test_defaults", soongConfigTestModuleFactory)
- ctx.Register(config)
+ ctx.RegisterModuleType("test_defaults", soongConfigTestDefaultsModuleFactory)
+ ctx.RegisterModuleType("test", soongConfigTestModuleFactory)
+ ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
+ ctx.Register()
_, errs := ctx.ParseBlueprintsFiles("Android.bp")
FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
FailIfErrored(t, errs)
+ basicCFlags := []string{"DEFAULT", "-DGENERIC", "-DSIZE=42", "-DSOC_A", "-DFEATURE1"}
+
foo := ctx.ModuleForTests("foo", "").Module().(*soongConfigTestModule)
- if g, w := foo.props.Cflags, []string{"-DGENERIC", "-DSIZE=42", "-DSOC_A", "-DFEATURE1"}; !reflect.DeepEqual(g, w) {
+ if g, w := foo.props.Cflags, basicCFlags; !reflect.DeepEqual(g, w) {
t.Errorf("wanted foo cflags %q, got %q", w, g)
}
+
+ fooDefaults := ctx.ModuleForTests("foo_with_defaults", "").Module().(*soongConfigTestModule)
+ if g, w := fooDefaults.props.Cflags, append([]string{"DEFAULT_A"}, basicCFlags...); !reflect.DeepEqual(g, w) {
+ t.Errorf("wanted foo_with_defaults cflags %q, got %q", w, g)
+ }
+
}
t.Run("single file", func(t *testing.T) {
diff --git a/android/test_suites.go b/android/test_suites.go
index 34e487e..19444a8 100644
--- a/android/test_suites.go
+++ b/android/test_suites.go
@@ -41,7 +41,7 @@
files[testSuite] = make(map[string]InstallPaths)
}
name := ctx.ModuleName(m)
- files[testSuite][name] = append(files[testSuite][name], tsm.filesToInstall()...)
+ files[testSuite][name] = append(files[testSuite][name], tsm.FilesToInstall()...)
}
}
})
diff --git a/android/testing.go b/android/testing.go
index 8ea4168..d83cecc 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -25,14 +25,14 @@
"github.com/google/blueprint"
)
-func NewTestContext() *TestContext {
+func NewTestContext(config Config) *TestContext {
namespaceExportFilter := func(namespace *Namespace) bool {
return true
}
nameResolver := NewNameResolver(namespaceExportFilter)
ctx := &TestContext{
- Context: &Context{blueprint.NewContext()},
+ Context: &Context{blueprint.NewContext(), config},
NameResolver: nameResolver,
}
@@ -40,11 +40,16 @@
ctx.postDeps = append(ctx.postDeps, registerPathDepsMutator)
+ ctx.SetFs(ctx.config.fs)
+ if ctx.config.mockBpList != "" {
+ ctx.SetModuleListFile(ctx.config.mockBpList)
+ }
+
return ctx
}
-func NewTestArchContext() *TestContext {
- ctx := NewTestContext()
+func NewTestArchContext(config Config) *TestContext {
+ ctx := NewTestContext(config)
ctx.preDeps = append(ctx.preDeps, registerArchMutator)
return ctx
}
@@ -53,7 +58,6 @@
*Context
preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc
NameResolver *NameResolver
- config Config
}
func (ctx *TestContext) PreArchMutators(f RegisterMutatorFunc) {
@@ -77,16 +81,10 @@
ctx.finalDeps = append(ctx.finalDeps, f)
}
-func (ctx *TestContext) Register(config Config) {
- ctx.SetFs(config.fs)
- if config.mockBpList != "" {
- ctx.SetModuleListFile(config.mockBpList)
- }
+func (ctx *TestContext) Register() {
registerMutators(ctx.Context.Context, ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps)
ctx.RegisterSingletonType("env", EnvSingleton)
-
- ctx.config = config
}
func (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) {
diff --git a/android/variable.go b/android/variable.go
index 53f081e..a9a9c87 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -90,6 +90,11 @@
Required []string
Host_required []string
Target_required []string
+ Strip struct {
+ All *bool
+ Keep_symbols *bool
+ Keep_symbols_and_debug_frame *bool
+ }
}
// eng is true for -eng builds, and can be used to turn on additionaly heavyweight debugging
@@ -219,6 +224,7 @@
Unbundled_build *bool `json:",omitempty"`
Unbundled_build_apps *bool `json:",omitempty"`
Always_use_prebuilt_sdks *bool `json:",omitempty"`
+ Skip_boot_jars_check *bool `json:",omitempty"`
Malloc_not_svelte *bool `json:",omitempty"`
Malloc_zero_contents *bool `json:",omitempty"`
Malloc_pattern_fill_contents *bool `json:",omitempty"`
@@ -244,8 +250,8 @@
UncompressPrivAppDex *bool `json:",omitempty"`
ModulesLoadedByPrivilegedModules []string `json:",omitempty"`
- BootJars []string `json:",omitempty"`
- UpdatableBootJars []string `json:",omitempty"`
+ BootJars ConfiguredJarList `json:",omitempty"`
+ UpdatableBootJars ConfiguredJarList `json:",omitempty"`
IntegerOverflowExcludePaths []string `json:",omitempty"`
@@ -304,8 +310,8 @@
BoardVendorSepolicyDirs []string `json:",omitempty"`
BoardOdmSepolicyDirs []string `json:",omitempty"`
- BoardPlatPublicSepolicyDirs []string `json:",omitempty"`
- BoardPlatPrivateSepolicyDirs []string `json:",omitempty"`
+ SystemExtPublicSepolicyDirs []string `json:",omitempty"`
+ SystemExtPrivateSepolicyDirs []string `json:",omitempty"`
BoardSepolicyM4Defs []string `json:",omitempty"`
VendorVars map[string]map[string]string `json:",omitempty"`
@@ -347,6 +353,8 @@
BoardKernelBinaries []string `json:",omitempty"`
BoardKernelModuleInterfaceVersions []string `json:",omitempty"`
+
+ BoardMoveRecoveryResourcesToVendorBoot *bool `json:",omitempty"`
}
func boolPtr(v bool) *bool {
@@ -365,12 +373,12 @@
*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"),
@@ -390,7 +398,7 @@
AAPTPrebuiltDPI: []string{"xhdpi", "xxhdpi"},
Malloc_not_svelte: boolPtr(true),
- Malloc_zero_contents: boolPtr(false),
+ Malloc_zero_contents: boolPtr(true),
Malloc_pattern_fill_contents: boolPtr(false),
Safestack: boolPtr(false),
}
diff --git a/android/variable_test.go b/android/variable_test.go
index 9cafedd..393fe01 100644
--- a/android/variable_test.go
+++ b/android/variable_test.go
@@ -157,23 +157,6 @@
}
func TestProductVariables(t *testing.T) {
- ctx := NewTestContext()
- // A module type that has a srcs property but not a cflags property.
- ctx.RegisterModuleType("module1", testProductVariableModuleFactoryFactory(&struct {
- Srcs []string
- }{}))
- // A module type that has a cflags property but not a srcs property.
- ctx.RegisterModuleType("module2", testProductVariableModuleFactoryFactory(&struct {
- Cflags []string
- }{}))
- // A module type that does not have any properties that match product_variables.
- ctx.RegisterModuleType("module3", testProductVariableModuleFactoryFactory(&struct {
- Foo []string
- }{}))
- ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("variable", VariableMutator).Parallel()
- })
-
// Test that a module can use one product variable even if it doesn't have all the properties
// supported by that product variable.
bp := `
@@ -201,7 +184,24 @@
config := TestConfig(buildDir, nil, bp, nil)
config.TestProductVariables.Eng = proptools.BoolPtr(true)
- ctx.Register(config)
+ ctx := NewTestContext(config)
+ // A module type that has a srcs property but not a cflags property.
+ ctx.RegisterModuleType("module1", testProductVariableModuleFactoryFactory(&struct {
+ Srcs []string
+ }{}))
+ // A module type that has a cflags property but not a srcs property.
+ ctx.RegisterModuleType("module2", testProductVariableModuleFactoryFactory(&struct {
+ Cflags []string
+ }{}))
+ // A module type that does not have any properties that match product_variables.
+ ctx.RegisterModuleType("module3", testProductVariableModuleFactoryFactory(&struct {
+ Foo []string
+ }{}))
+ ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("variable", VariableMutator).Parallel()
+ })
+
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
FailIfErrored(t, errs)
@@ -293,7 +293,7 @@
config := TestConfig(buildDir, nil, bp, nil)
config.TestProductVariables.Eng = boolPtr(true)
- ctx := NewTestContext()
+ ctx := NewTestContext(config)
ctx.RegisterModuleType("test", productVariablesDefaultsTestModuleFactory)
ctx.RegisterModuleType("defaults", productVariablesDefaultsTestDefaultsFactory)
@@ -303,7 +303,7 @@
ctx.BottomUp("variable", VariableMutator).Parallel()
})
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
FailIfErrored(t, errs)
diff --git a/android/visibility.go b/android/visibility.go
index 68da1c4..7eac471 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -17,6 +17,7 @@
import (
"fmt"
"regexp"
+ "sort"
"strings"
"sync"
@@ -350,7 +351,10 @@
case "__subpackages__":
r = subpackagesRule{pkg}
default:
- continue
+ ctx.PropertyErrorf(property, "invalid visibility pattern %q. Must match "+
+ " //<package>:<scope>, //<package> or :<scope> "+
+ "where <scope> is one of \"__pkg__\", \"__subpackages__\"",
+ v)
}
}
@@ -396,7 +400,8 @@
// ensure all the rules on this module are checked.
ctx.PropertyErrorf(property,
"invalid visibility pattern %q must match"+
- " //<package>:<module>, //<package> or :<module>",
+ " //<package>:<scope>, //<package> or :<scope> "+
+ "where <scope> is one of \"__pkg__\", \"__subpackages__\"",
ruleExpression)
return false, "", ""
}
@@ -441,12 +446,19 @@
}
rule := effectiveVisibilityRules(ctx.Config(), depQualified)
- if rule != nil && !rule.matches(qualified) {
- ctx.ModuleErrorf("depends on %s which is not visible to this module", depQualified)
+ if !rule.matches(qualified) {
+ ctx.ModuleErrorf("depends on %s which is not visible to this module\nYou may need to add %q to its visibility", depQualified, "//"+ctx.ModuleDir())
}
})
}
+// 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 +468,12 @@
} 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 +501,63 @@
}
}
+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 +567,7 @@
// 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 +576,13 @@
// 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 ca09345..87a295e 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -731,7 +731,7 @@
}`),
},
expectedErrors: []string{
- `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`,
+ `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module\nYou may need to add "//namespace" to its visibility`,
},
},
{
@@ -760,7 +760,7 @@
}`),
},
expectedErrors: []string{
- `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`,
+ `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module\nYou may need to add "//namespace" to its visibility`,
},
},
{
@@ -1168,7 +1168,7 @@
// Create a new config per test as visibility information is stored in the config.
config := TestArchConfig(buildDir, nil, "", fs)
- ctx := NewTestArchContext()
+ ctx := NewTestArchContext(config)
ctx.RegisterModuleType("mock_library", newMockLibraryModule)
ctx.RegisterModuleType("mock_parent", newMockParentFactory)
ctx.RegisterModuleType("mock_defaults", defaultsFactory)
@@ -1180,7 +1180,7 @@
ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
ctx.PreArchMutators(RegisterVisibilityRuleGatherer)
ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer)
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseBlueprintsFiles(".")
if len(errs) > 0 {
@@ -1270,3 +1270,49 @@
})
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/android/vts_config.go b/android/vts_config.go
deleted file mode 100644
index 77fb9fe..0000000
--- a/android/vts_config.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2016 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 android
-
-import (
- "fmt"
- "io"
- "strings"
-)
-
-func init() {
- RegisterModuleType("vts_config", VtsConfigFactory)
-}
-
-type vtsConfigProperties struct {
- // Override the default (AndroidTest.xml) test manifest file name.
- Test_config *string
- // Additional test suites to add the test to.
- Test_suites []string `android:"arch_variant"`
-}
-
-type VtsConfig struct {
- ModuleBase
- properties vtsConfigProperties
- OutputFilePath OutputPath
-}
-
-func (me *VtsConfig) GenerateAndroidBuildActions(ctx ModuleContext) {
- me.OutputFilePath = PathForModuleOut(ctx, me.BaseModuleName()).OutputPath
-}
-
-func (me *VtsConfig) AndroidMk() AndroidMkData {
- androidMkData := AndroidMkData{
- Class: "FAKE",
- Include: "$(BUILD_SYSTEM)/suite_host_config.mk",
- OutputFile: OptionalPathForPath(me.OutputFilePath),
- }
- androidMkData.Extra = []AndroidMkExtraFunc{
- func(w io.Writer, outputFile Path) {
- if me.properties.Test_config != nil {
- fmt.Fprintf(w, "LOCAL_TEST_CONFIG := %s\n",
- *me.properties.Test_config)
- }
- fmt.Fprintf(w, "LOCAL_COMPATIBILITY_SUITE := vts10 %s\n",
- strings.Join(me.properties.Test_suites, " "))
- },
- }
- return androidMkData
-}
-
-func InitVtsConfigModule(me *VtsConfig) {
- me.AddProperties(&me.properties)
-}
-
-// vts_config generates a Vendor Test Suite (VTS10) configuration file from the
-// <test_config> xml file and stores it in a subdirectory of $(HOST_OUT).
-func VtsConfigFactory() Module {
- module := &VtsConfig{}
- InitVtsConfigModule(module)
- InitAndroidArchModule(module /*TODO: or HostAndDeviceSupported? */, HostSupported, MultilibFirst)
- return module
-}
diff --git a/android/vts_config_test.go b/android/vts_config_test.go
deleted file mode 100644
index 254fa92..0000000
--- a/android/vts_config_test.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2018 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 android
-
-import (
- "testing"
-)
-
-func testVtsConfig(test *testing.T, bpFileContents string) *TestContext {
- config := TestArchConfig(buildDir, nil, bpFileContents, nil)
-
- ctx := NewTestArchContext()
- ctx.RegisterModuleType("vts_config", VtsConfigFactory)
- ctx.Register(config)
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(test, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(test, errs)
- return ctx
-}
-
-func TestVtsConfig(t *testing.T) {
- ctx := testVtsConfig(t, `
-vts_config { name: "plain"}
-vts_config { name: "with_manifest", test_config: "manifest.xml" }
-`)
-
- variants := ctx.ModuleVariantsForTests("plain")
- if len(variants) > 1 {
- t.Errorf("expected 1, got %d", len(variants))
- }
- expectedOutputFilename := ctx.ModuleForTests(
- "plain", variants[0]).Module().(*VtsConfig).OutputFilePath.Base()
- if expectedOutputFilename != "plain" {
- t.Errorf("expected plain, got %q", expectedOutputFilename)
- }
-}
diff --git a/android/writedocs.go b/android/writedocs.go
index 4eb15e6..91c2318 100644
--- a/android/writedocs.go
+++ b/android/writedocs.go
@@ -48,6 +48,13 @@
deps = append(deps, pathForBuildToolDep(ctx, ctx.Config().moduleListFile))
deps = append(deps, pathForBuildToolDep(ctx, ctx.Config().ProductVariablesFileName))
+ // The dexpreopt configuration may not exist, but if it does, it's a dependency
+ // of soong_build.
+ dexpreoptConfigPath := ctx.Config().DexpreoptGlobalConfigPath(ctx)
+ if dexpreoptConfigPath.Valid() {
+ deps = append(deps, dexpreoptConfigPath.Path())
+ }
+
// Generate build system docs for the primary builder. Generating docs reads the source
// files used to build the primary builder, but that dependency will be picked up through
// the dependency on the primary builder itself. There are no dependencies on the
diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go
index eaf06c5..739a965 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -953,8 +953,7 @@
var soongModuleTypes = map[string]bool{}
var includePathToModule = map[string]string{
- "test/vts/tools/build/Android.host_config.mk": "vts_config",
- // The rest will be populated dynamically in androidScope below
+ // The content will be populated dynamically in androidScope below
}
func mapIncludePath(path string) (string, bool) {
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index 2448acc..16cb138 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -1257,19 +1257,6 @@
`,
},
{
- desc: "vts_config",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := vtsconf
-include test/vts/tools/build/Android.host_config.mk
-`,
- expected: `
-vts_config {
- name: "vtsconf",
-}
-`,
- },
- {
desc: "comment with ESC",
in: `
# Comment line 1 \
diff --git a/apex/OWNERS b/apex/OWNERS
index a382ae8..793f3ed 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 0000000..5b8563d
--- /dev/null
+++ b/apex/allowed_deps.txt
@@ -0,0 +1,555 @@
+# 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.common-unstable-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-unstable-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)
+bionic_libc_platform_headers(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:16)
+crtbegin_dynamic(minSdkVersion:apex_inherit)
+crtbegin_dynamic1(minSdkVersion:16)
+crtbegin_dynamic1(minSdkVersion:apex_inherit)
+crtbegin_so(minSdkVersion:16)
+crtbegin_so(minSdkVersion:apex_inherit)
+crtbegin_so1(minSdkVersion:16)
+crtbegin_so1(minSdkVersion:apex_inherit)
+crtbrand(minSdkVersion:16)
+crtbrand(minSdkVersion:apex_inherit)
+crtend_android(minSdkVersion:16)
+crtend_android(minSdkVersion:apex_inherit)
+crtend_so(minSdkVersion:16)
+crtend_so(minSdkVersion:apex_inherit)
+datastallprotosnano(minSdkVersion:29)
+derive_sdk(minSdkVersion:30)
+derive_sdk(minSdkVersion:current)
+derive_sdk_prefer32(minSdkVersion:30)
+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:30)
+framework-sdkextensions(minSdkVersion:current)
+framework-statsd(minSdkVersion:current)
+framework-tethering(minSdkVersion:30)
+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:30)
+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_sysdeps(minSdkVersion:apex_inherit)
+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)
+libclang_rt.hwasan-aarch64-android.llndk(minSdkVersion:(no version))
+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))
+libdmabufheap(minSdkVersion:29)
+libeigen(minSdkVersion:(no version))
+libfifo(minSdkVersion:29)
+libFLAC(minSdkVersion:29)
+libFLAC-config(minSdkVersion:29)
+libFLAC-headers(minSdkVersion:29)
+libflacextractor(minSdkVersion:29)
+libfmq(minSdkVersion:29)
+libfmq-base(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)
+libhwbinder_headers(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:30)
+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++_static(minSdkVersion:16)
+ndk_libc++abi(minSdkVersion:(no version))
+ndk_libc++abi(minSdkVersion:16)
+ndk_libunwind(minSdkVersion:16)
+net-utils-device-common(minSdkVersion:29)
+net-utils-framework-common(minSdkVersion:current)
+netd_aidl_interface-unstable-java(minSdkVersion:29)
+netd_event_listener_interface-ndk_platform(minSdkVersion:29)
+netd_event_listener_interface-unstable-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)
+neuralnetworks_types(minSdkVersion:30)
+neuralnetworks_utils_hal_1_0(minSdkVersion:30)
+neuralnetworks_utils_hal_1_1(minSdkVersion:30)
+neuralnetworks_utils_hal_1_2(minSdkVersion:30)
+neuralnetworks_utils_hal_1_3(minSdkVersion:30)
+neuralnetworks_utils_hal_common(minSdkVersion:30)
+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:30)
+Tethering(minSdkVersion:current)
+TetheringApiCurrentLib(minSdkVersion:30)
+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 1b53a67..993260c 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -135,7 +135,7 @@
}
}
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 @@
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:
@@ -263,6 +264,10 @@
postInstallCommands = append(postInstallCommands, a.compatSymlinks...)
}
}
+
+ // File_contexts of flattened APEXes should be merged into file_contexts.bin
+ fmt.Fprintln(w, "LOCAL_FILE_CONTEXTS :=", a.fileContexts)
+
if len(postInstallCommands) > 0 {
fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD :=", strings.Join(postInstallCommands, " && "))
}
@@ -302,6 +307,7 @@
func (a *apexBundle) androidMkForType() android.AndroidMkData {
return android.AndroidMkData{
+ DistFiles: a.distFiles,
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
moduleNames := []string{}
apexType := a.properties.ApexType
@@ -386,6 +392,9 @@
fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n",
goal, a.installedFilesFile.String(), distFile)
}
+ for _, dist := range data.Entries.GetDistForGoals(a) {
+ fmt.Fprintf(w, dist)
+ }
}
}}
}
diff --git a/apex/apex.go b/apex/apex.go
index 8e35e07..91770f4 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -19,7 +19,6 @@
"path/filepath"
"sort"
"strings"
- "sync"
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
@@ -64,10 +63,10 @@
testTag = dependencyTag{name: "test", payload: true}
keyTag = dependencyTag{name: "key"}
certificateTag = dependencyTag{name: "certificate"}
- usesTag = dependencyTag{name: "uses"}
androidAppTag = dependencyTag{name: "androidApp", payload: true}
rroTag = dependencyTag{name: "rro", payload: true}
bpfTag = dependencyTag{name: "bpf", payload: true}
+ testForTag = dependencyTag{name: "test for"}
apexAvailBaseline = makeApexAvailableBaseline()
@@ -276,8 +275,6 @@
"libc_malloc_debug_backtrace",
"libcamera_client",
"libcamera_metadata",
- "libdexfile_external_headers",
- "libdexfile_support",
"libdvr_headers",
"libexpat",
"libfifo",
@@ -304,10 +301,6 @@
"libmp4extractor",
"libmpeg2extractor",
"libnativebase_headers",
- "libnativebridge-headers",
- "libnativebridge_lazy",
- "libnativeloader-headers",
- "libnativeloader_lazy",
"libnativewindow_headers",
"libnblog",
"liboggextractor",
@@ -431,7 +424,6 @@
"libcodec2_soft_vp9dec",
"libcodec2_soft_vp9enc",
"libcodec2_vndk",
- "libdexfile_support",
"libdvr_headers",
"libfmq",
"libfmq",
@@ -454,8 +446,6 @@
"libmedia_headers",
"libmpeg2dec",
"libnativebase_headers",
- "libnativebridge_lazy",
- "libnativeloader_lazy",
"libnativewindow_headers",
"libpdx_headers",
"libscudo_wrapper",
@@ -563,9 +553,6 @@
"libdebuggerd_common_headers",
"libdebuggerd_handler_core",
"libdebuggerd_handler_fallback",
- "libdexfile_external_headers",
- "libdexfile_support",
- "libdexfile_support_static",
"libdl_static",
"libjemalloc5",
"liblinker_main",
@@ -744,12 +731,6 @@
android.PreDepsMutators(RegisterPreDepsMutators)
android.PostDepsMutators(RegisterPostDepsMutators)
- android.RegisterMakeVarsProvider(pctx, func(ctx android.MakeVarsContext) {
- apexFileContextsInfos := apexFileContextsInfos(ctx.Config())
- sort.Strings(*apexFileContextsInfos)
- ctx.Strict("APEX_FILE_CONTEXTS_INFOS", strings.Join(*apexFileContextsInfos, " "))
- })
-
android.AddNeverAllowRules(createApexPermittedPackagesRules(qModulesPackages())...)
android.AddNeverAllowRules(createApexPermittedPackagesRules(rModulesPackages())...)
}
@@ -777,9 +758,11 @@
func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
ctx.TopDown("apex_deps", apexDepsMutator).Parallel()
ctx.BottomUp("apex_unique", apexUniqueVariationsMutator).Parallel()
+ ctx.BottomUp("apex_test_for_deps", apexTestForDepsMutator).Parallel()
+ ctx.BottomUp("apex_test_for", apexTestForMutator).Parallel()
ctx.BottomUp("apex", apexMutator).Parallel()
+ ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).Parallel()
ctx.BottomUp("apex_flattened", apexFlattenedMutator).Parallel()
- ctx.BottomUp("apex_uses", apexUsesMutator).Parallel()
ctx.BottomUp("mark_platform_availability", markPlatformAvailability).Parallel()
}
@@ -793,13 +776,6 @@
if !ok || a.vndkApex {
return
}
- apexInfo := android.ApexInfo{
- ApexVariationName: mctx.ModuleName(),
- MinSdkVersion: a.minSdkVersion(mctx),
- RequiredSdks: a.RequiredSdks(),
- Updatable: a.Updatable(),
- InApexes: []string{mctx.ModuleName()},
- }
useVndk := a.SocSpecific() || a.DeviceSpecific() || (a.ProductSpecific() && mctx.Config().EnforceProductPartitionInterface())
excludeVndkLibs := useVndk && proptools.Bool(a.properties.Use_vndk_as_stable)
@@ -808,7 +784,9 @@
return
}
- mctx.WalkDeps(func(child, parent android.Module) bool {
+ contents := make(map[string]android.ApexMembership)
+
+ continueApexDepsWalk := func(child, parent android.Module) bool {
am, ok := child.(android.ApexModule)
if !ok || !am.CanHaveApexVariants() {
return false
@@ -821,12 +799,41 @@
return false
}
}
+ return true
+ }
+
+ mctx.WalkDeps(func(child, parent android.Module) bool {
+ if !continueApexDepsWalk(child, parent) {
+ return false
+ }
depName := mctx.OtherModuleName(child)
// If the parent is apexBundle, this child is directly depended.
_, directDep := parent.(*apexBundle)
- android.UpdateApexDependency(apexInfo, depName, directDep)
- am.BuildForApex(apexInfo)
+ contents[depName] = contents[depName].Add(directDep)
+ return true
+ })
+
+ apexContents := android.NewApexContents(mctx.ModuleName(), contents)
+ mctx.SetProvider(ApexBundleInfoProvider, ApexBundleInfo{
+ Contents: apexContents,
+ })
+
+ apexInfo := android.ApexInfo{
+ ApexVariationName: mctx.ModuleName(),
+ MinSdkVersionStr: a.minSdkVersion(mctx).String(),
+ RequiredSdks: a.RequiredSdks(),
+ Updatable: a.Updatable(),
+ InApexes: []string{mctx.ModuleName()},
+ ApexContents: []*android.ApexContents{apexContents},
+ }
+
+ mctx.WalkDeps(func(child, parent android.Module) bool {
+ if !continueApexDepsWalk(child, parent) {
+ return false
+ }
+
+ child.(android.ApexModule).BuildForApex(apexInfo)
return true
})
}
@@ -838,7 +845,40 @@
if am, ok := mctx.Module().(android.ApexModule); ok {
// Check if any dependencies use unique apex variations. If so, use unique apex variations
// for this module.
- am.UpdateUniqueApexVariationsForDeps(mctx)
+ android.UpdateUniqueApexVariationsForDeps(mctx, am)
+ }
+}
+
+func apexTestForDepsMutator(mctx android.BottomUpMutatorContext) {
+ if !mctx.Module().Enabled() {
+ return
+ }
+ // Check if this module is a test for an apex. If so, add a dependency on the apex
+ // in order to retrieve its contents later.
+ if am, ok := mctx.Module().(android.ApexModule); ok {
+ if testFor := am.TestFor(); len(testFor) > 0 {
+ mctx.AddFarVariationDependencies([]blueprint.Variation{
+ {Mutator: "os", Variation: am.Target().OsVariation()},
+ {"arch", "common"},
+ }, testForTag, testFor...)
+ }
+ }
+}
+
+func apexTestForMutator(mctx android.BottomUpMutatorContext) {
+ if !mctx.Module().Enabled() {
+ return
+ }
+
+ if _, ok := mctx.Module().(android.ApexModule); ok {
+ var contents []*android.ApexContents
+ for _, testFor := range mctx.GetDirectDepsWithTag(testForTag) {
+ abInfo := mctx.OtherModuleProvider(testFor, ApexBundleInfoProvider).(ApexBundleInfo)
+ contents = append(contents, abInfo.Contents)
+ }
+ mctx.SetProvider(android.ApexTestForInfoProvider, android.ApexTestForInfo{
+ ApexContents: contents,
+ })
}
}
@@ -899,8 +939,9 @@
if !mctx.Module().Enabled() {
return
}
+
if am, ok := mctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
- am.CreateApexVariations(mctx)
+ android.CreateApexVariations(mctx, am)
} else if a, ok := mctx.Module().(*apexBundle); ok && !a.vndkApex {
// apex bundle itself is mutated so that it and its modules have same
// apex variant.
@@ -917,22 +958,13 @@
}
-var (
- apexFileContextsInfosKey = android.NewOnceKey("apexFileContextsInfosKey")
- apexFileContextsInfosMutex sync.Mutex
-)
-
-func apexFileContextsInfos(config android.Config) *[]string {
- return config.Once(apexFileContextsInfosKey, func() interface{} {
- return &[]string{}
- }).(*[]string)
-}
-
-func addFlattenedFileContextsInfos(ctx android.BaseModuleContext, fileContextsInfo string) {
- apexFileContextsInfosMutex.Lock()
- defer apexFileContextsInfosMutex.Unlock()
- apexFileContextsInfos := apexFileContextsInfos(ctx.Config())
- *apexFileContextsInfos = append(*apexFileContextsInfos, fileContextsInfo)
+func apexDirectlyInAnyMutator(mctx android.BottomUpMutatorContext) {
+ if !mctx.Module().Enabled() {
+ return
+ }
+ if am, ok := mctx.Module().(android.ApexModule); ok {
+ android.UpdateDirectlyInAnyApex(mctx, am)
+ }
}
func apexFlattenedMutator(mctx android.BottomUpMutatorContext) {
@@ -973,12 +1005,6 @@
}
}
-func apexUsesMutator(mctx android.BottomUpMutatorContext) {
- if ab, ok := mctx.Module().(*apexBundle); ok {
- mctx.AddFarVariationDependencies(nil, usesTag, ab.properties.Uses...)
- }
-}
-
var (
useVendorAllowListKey = android.NewOnceKey("useVendorAllowList")
)
@@ -1098,12 +1124,6 @@
HideFromMake bool `blueprint:"mutated"`
- // Indicates this APEX provides C++ shared libaries to other APEXes. Default: false.
- Provide_cpp_shared_libs *bool
-
- // List of providing APEXes' names so that this APEX can depend on provided shared libraries.
- Uses []string
-
// package format of this apex variant; could be non-flattened, flattened, or zip.
// imageApex, zipApex or flattened
ApexType apexPackaging `blueprint:"mutated"`
@@ -1144,6 +1164,12 @@
Payload_fs_type *string
}
+type ApexBundleInfo struct {
+ Contents *android.ApexContents
+}
+
+var ApexBundleInfoProvider = blueprint.NewMutatorProvider(ApexBundleInfo{}, "apex_deps")
+
type apexTargetBundleProperties struct {
Target struct {
// Multilib properties only for android.
@@ -1437,6 +1463,8 @@
lintReports android.Paths
payloadFsType fsType
+
+ distFiles android.TaggedDistFiles
}
func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
@@ -1499,6 +1527,12 @@
}
}
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,
@@ -1928,6 +1962,8 @@
return false
}
+ childApexInfo := ctx.OtherModuleProvider(child, android.ApexInfoProvider).(android.ApexInfo)
+
dt := ctx.OtherModuleDependencyTag(child)
if _, ok := dt.(android.ExcludeFromApexContentsTag); ok {
@@ -1944,7 +1980,7 @@
}
// Check for the indirect dependencies if it is considered as part of the APEX
- if android.InList(ctx.ModuleName(), am.InApexes()) {
+ if android.InList(ctx.ModuleName(), childApexInfo.InApexes) {
return do(ctx, parent, am, false /* externalDep */)
}
@@ -1952,27 +1988,21 @@
})
}
-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
}
- return intVer
+ if apiLevel.IsPreview() {
+ // All codenames should build against "current".
+ return android.FutureApiLevel
+ }
+ return apiLevel
}
func (a *apexBundle) Updatable() bool {
@@ -2022,7 +2052,7 @@
if to.AvailableFor(apexName) || baselineApexAvailable(apexName, toName) {
return true
}
- ctx.ModuleErrorf("%q requires %q that is not available for the APEX. Dependency path:%s", fromName, toName, ctx.GetPathString(true))
+ ctx.ModuleErrorf("%q requires %q that doesn't list the APEX under 'apex_available'. Dependency path:%s", fromName, toName, ctx.GetPathString(true))
// Visit this module's dependencies to check and report any issues with their availability.
return true
})
@@ -2046,7 +2076,9 @@
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
@@ -2056,6 +2088,8 @@
return
}
+ abInfo := ctx.Provider(ApexBundleInfoProvider).(ApexBundleInfo)
+
a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
if ccm, ok := to.(*cc.Module); ok {
apexName := ctx.ModuleName()
@@ -2076,7 +2110,7 @@
return false
}
- isStubLibraryFromOtherApex := ccm.HasStubsVariants() && !android.DirectlyInApex(apexName, toName)
+ isStubLibraryFromOtherApex := ccm.HasStubsVariants() && !abInfo.Contents.DirectlyInApex(toName)
if isStubLibraryFromOtherApex && !externalDep {
ctx.ModuleErrorf("%q required by %q is a native library providing stub. "+
"It shouldn't be included in this APEX via static linking. Dependency path: %s", to.String(), fromName, ctx.GetPathString(false))
@@ -2133,30 +2167,6 @@
var provideNativeLibs []string
var requireNativeLibs []string
- // Check if "uses" requirements are met with dependent apexBundles
- var providedNativeSharedLibs []string
- useVendor := proptools.Bool(a.properties.Use_vendor)
- ctx.VisitDirectDepsBlueprint(func(m blueprint.Module) {
- if ctx.OtherModuleDependencyTag(m) != usesTag {
- return
- }
- otherName := ctx.OtherModuleName(m)
- other, ok := m.(*apexBundle)
- if !ok {
- ctx.PropertyErrorf("uses", "%q is not a provider", otherName)
- return
- }
- if proptools.Bool(other.properties.Use_vendor) != useVendor {
- ctx.PropertyErrorf("use_vendor", "%q has different value of use_vendor", otherName)
- return
- }
- if !proptools.Bool(other.properties.Provide_cpp_shared_libs) {
- ctx.PropertyErrorf("uses", "%q does not provide native_shared_libs", otherName)
- return
- }
- providedNativeSharedLibs = append(providedNativeSharedLibs, other.properties.Native_shared_libs...)
- })
-
var filesInfo []apexFile
// TODO(jiyong) do this using WalkPayloadDeps
ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool {
@@ -2304,18 +2314,14 @@
// tags used below are private (e.g. `cc.sharedDepTag`).
if cc.IsSharedDepTag(depTag) || cc.IsRuntimeDepTag(depTag) {
if cc, ok := child.(*cc.Module); ok {
- if android.InList(cc.Name(), providedNativeSharedLibs) {
- // If we're using a shared library which is provided from other APEX,
- // don't include it in this APEX
- return false
- }
if cc.UseVndk() && proptools.Bool(a.properties.Use_vndk_as_stable) && cc.IsVndk() {
requireNativeLibs = append(requireNativeLibs, ":vndk")
return false
}
af := apexFileForNativeLibrary(ctx, cc, handleSpecialLibs)
af.transitiveDep = true
- if !a.Host() && !android.DirectlyInApex(ctx.ModuleName(), depName) && (cc.IsStubs() || cc.HasStubsVariants()) {
+ abInfo := ctx.Provider(ApexBundleInfoProvider).(ApexBundleInfo)
+ if !a.Host() && !abInfo.Contents.DirectlyInApex(depName) && (cc.IsStubs() || cc.HasStubsVariants()) {
// If the dependency is a stubs lib, don't include it in this APEX,
// but make sure that the lib is installed on the device.
// In case no APEX is having the lib, the lib is installed to the system
@@ -2323,13 +2329,14 @@
//
// Always include if we are a host-apex however since those won't have any
// system libraries.
- if !android.DirectlyInAnyApex(ctx, depName) {
+ if !am.DirectlyInAnyApex() {
// we need a module name for Make
- name := cc.BaseModuleName() + cc.Properties.SubName
- if proptools.Bool(a.properties.Use_vendor) {
+ name := cc.ImplementationModuleName(ctx)
+
+ if !proptools.Bool(a.properties.Use_vendor) {
// we don't use subName(.vendor) for a "use_vendor: true" apex
// which is supposed to be installed in /system
- name = cc.BaseModuleName()
+ name += cc.Properties.SubName
}
if !android.InList(name, a.requiredDeps) {
a.requiredDeps = append(a.requiredDeps, name)
@@ -2362,6 +2369,8 @@
if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
}
+ } else if _, ok := depTag.(android.CopyDirectlyInAnyApexTag); ok {
+ // nothing
} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
ctx.ModuleErrorf("unexpected tag %s for indirect dependency %q", android.PrettyPrintTag(depTag), depName)
}
@@ -2472,6 +2481,8 @@
a.buildApexDependencyInfo(ctx)
a.buildLintReports(ctx)
+
+ a.distFiles = a.GenerateTaggedDistFiles(ctx)
}
// Enforce that Java deps of the apex are using stable SDKs to compile
diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go
index 83a56a2..ee9fc81 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,84 @@
}
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 {
+ apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
if path := binaryInfo.FlatListPath(); path != nil {
- if binaryInfo.Updatable() {
+ if binaryInfo.Updatable() || apexInfo.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: combineFilesRule,
- Description: "Generate " + s.updatableFlatListsPath.String(),
- Inputs: updatableFlatLists,
- Output: s.updatableFlatListsPath,
+ Rule: generateApexDepsInfoFilesRule,
+ Inputs: append(updatableFlatLists, allowedDeps),
+ Output: newAllowedDeps,
})
+
+ s.allowedApexDepsInfoCheckResult = android.PathForOutput(ctx, newAllowedDeps.Rel()+".check")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: diffAllowedApexDepsInfoRule,
+ Input: newAllowedDeps,
+ Output: s.allowedApexDepsInfoCheckResult,
+ Args: map[string]string{
+ "allowed_deps": allowedDeps.String(),
+ "new_allowed_deps": newAllowedDeps.String(),
+ },
+ })
+
+ ctx.Phony("apex-allowed-deps-check", s.allowedApexDepsInfoCheckResult)
+}
+
+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 610f667..33e5077 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -125,8 +125,6 @@
}
func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
- android.ClearApexDependency()
-
bp = bp + `
filegroup {
name: "myapex-file_contexts",
@@ -151,10 +149,8 @@
"system/sepolicy/apex/myapex.updatable-file_contexts": nil,
"system/sepolicy/apex/myapex2-file_contexts": nil,
"system/sepolicy/apex/otherapex-file_contexts": nil,
- "system/sepolicy/apex/commonapex-file_contexts": nil,
"system/sepolicy/apex/com.android.vndk-file_contexts": nil,
"mylib.cpp": nil,
- "mylib_common.cpp": nil,
"mytest.cpp": nil,
"mytest1.cpp": nil,
"mytest2.cpp": nil,
@@ -207,7 +203,7 @@
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 {
@@ -218,7 +214,7 @@
handler(tempFS, config)
}
- ctx := android.NewTestArchContext()
+ ctx := android.NewTestArchContext(config)
// from android package
android.RegisterPackageBuildComponents(ctx)
@@ -263,7 +259,7 @@
ctx.PreDepsMutators(RegisterPreDepsMutators)
ctx.PostDepsMutators(RegisterPostDepsMutators)
- ctx.Register(config)
+ ctx.Register()
return ctx, config
}
@@ -584,18 +580,18 @@
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) {
@@ -827,7 +823,106 @@
ensureNotContains(t, mylib2Cflags, "-include ")
// Ensure that genstub is invoked with --apex
- ensureContains(t, "--apex", ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_3").Rule("genStubSrc").Args["flags"])
+ ensureContains(t, "--apex", ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_shared_3").Rule("genStubSrc").Args["flags"])
+
+ ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
+ "lib64/mylib.so",
+ "lib64/mylib3.so",
+ "lib64/mylib4.so",
+ })
+}
+
+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_shared_29").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_shared_29").Rule("genStubSrc").Args["flags"])
ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
"lib64/mylib.so",
@@ -913,14 +1008,14 @@
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) {
@@ -1173,10 +1268,11 @@
system_shared_libs: [],
stl: "none",
stubs: { versions: ["29","30"] },
+ llndk_stubs: "libbar.llndk",
}
llndk_library {
- name: "libbar",
+ name: "libbar.llndk",
symbol_file: "",
}
`, func(fs map[string][]byte, config android.Config) {
@@ -1222,6 +1318,7 @@
cc_library {
name: "mylib",
srcs: ["mylib.cpp"],
+ system_shared_libs: ["libc", "libm"],
shared_libs: ["libdl#27"],
stl: "none",
apex_available: [ "myapex" ],
@@ -1425,13 +1522,7 @@
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")
}
@@ -1514,10 +1605,12 @@
`)
expectLink := func(from, from_variant, to, to_variant string) {
+ t.Helper()
ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
ensureContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
expectNoLink := func(from, from_variant, to, to_variant string) {
+ t.Helper()
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")
}
@@ -2254,6 +2347,7 @@
enabled: true,
},
vendor_available: true,
+ product_available: true,
}
cc_library {
name: "libvendor",
@@ -2282,30 +2376,40 @@
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) {
@@ -2917,6 +3021,7 @@
name: "libvndk",
srcs: ["mylib.cpp"],
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -2929,6 +3034,7 @@
name: "libvndksp",
srcs: ["mylib.cpp"],
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
@@ -2970,6 +3076,7 @@
name: "libvndk",
srcs: ["libvndk.so"],
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -2982,6 +3089,7 @@
name: "libvndk.arm",
srcs: ["libvndk.arm.so"],
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -3054,6 +3162,7 @@
name: "libvndk27",
version: "27",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -3073,6 +3182,7 @@
name: "libvndk27",
version: "27",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -3126,6 +3236,7 @@
name: "libvndk",
srcs: ["mylib.cpp"],
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -3137,6 +3248,7 @@
name: "libvndk",
version: "27",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -3196,6 +3308,7 @@
name: "libvndk",
srcs: ["mylib.cpp"],
vendor_available: true,
+ product_available: true,
native_bridge_supported: true,
host_supported: true,
vndk: {
@@ -3235,6 +3348,7 @@
name: "libvndk",
srcs: ["mylib.cpp"],
vendor_available: true,
+ product_available: true,
native_bridge_supported: true,
host_supported: true,
vndk: {
@@ -3266,6 +3380,7 @@
version: "27",
target_arch: "arm",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -3282,6 +3397,7 @@
target_arch: "arm",
binder32bit: true,
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -3329,6 +3445,7 @@
cc_library {
name: "libz",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -3540,16 +3657,13 @@
// Ensure that the platform variant ends with _shared
ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_shared")
- if !android.InAnyApex("mylib_common") {
+ if !ctx.ModuleForTests("mylib_common", "android_arm64_armv8-a_shared_apex10000").Module().(*cc.Module).InAnyApex() {
t.Log("Found mylib_common not in any apex!")
t.Fail()
}
}
func TestTestApex(t *testing.T) {
- if android.InAnyApex("mylib_common_test") {
- t.Fatal("mylib_common_test must not be used in any other tests since this checks that global state is not updated in an illegal way!")
- }
ctx, _ := testApex(t, `
apex_test {
name: "myapex",
@@ -4086,131 +4200,6 @@
ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES += myapex.flattened")
}
-func TestApexUsesOtherApex(t *testing.T) {
- ctx, _ := testApex(t, `
- apex {
- name: "myapex",
- key: "myapex.key",
- native_shared_libs: ["mylib"],
- uses: ["commonapex"],
- }
-
- apex {
- name: "commonapex",
- key: "myapex.key",
- native_shared_libs: ["libcommon"],
- provide_cpp_shared_libs: true,
- }
-
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- cc_library {
- name: "mylib",
- srcs: ["mylib.cpp"],
- shared_libs: ["libcommon"],
- system_shared_libs: [],
- stl: "none",
- apex_available: [ "myapex" ],
- }
-
- cc_library {
- name: "libcommon",
- srcs: ["mylib_common.cpp"],
- system_shared_libs: [],
- stl: "none",
- // TODO: remove //apex_available:platform
- apex_available: [
- "//apex_available:platform",
- "commonapex",
- "myapex",
- ],
- }
- `)
-
- module1 := ctx.ModuleForTests("myapex", "android_common_myapex_image")
- apexRule1 := module1.Rule("apexRule")
- copyCmds1 := apexRule1.Args["copy_commands"]
-
- module2 := ctx.ModuleForTests("commonapex", "android_common_commonapex_image")
- apexRule2 := module2.Rule("apexRule")
- copyCmds2 := apexRule2.Args["copy_commands"]
-
- ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_apex10000")
- ensureListContains(t, ctx.ModuleVariantsForTests("libcommon"), "android_arm64_armv8-a_shared_apex10000")
- ensureContains(t, copyCmds1, "image.apex/lib64/mylib.so")
- ensureContains(t, copyCmds2, "image.apex/lib64/libcommon.so")
- ensureNotContains(t, copyCmds1, "image.apex/lib64/libcommon.so")
-}
-
-func TestApexUsesFailsIfNotProvided(t *testing.T) {
- testApexError(t, `uses: "commonapex" does not provide native_shared_libs`, `
- apex {
- name: "myapex",
- key: "myapex.key",
- uses: ["commonapex"],
- }
-
- apex {
- name: "commonapex",
- key: "myapex.key",
- }
-
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
- `)
- testApexError(t, `uses: "commonapex" is not a provider`, `
- apex {
- name: "myapex",
- key: "myapex.key",
- uses: ["commonapex"],
- }
-
- cc_library {
- name: "commonapex",
- system_shared_libs: [],
- stl: "none",
- }
-
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
- `)
-}
-
-func TestApexUsesFailsIfUseVenderMismatch(t *testing.T) {
- testApexError(t, `use_vendor: "commonapex" has different value of use_vendor`, `
- apex {
- name: "myapex",
- key: "myapex.key",
- use_vendor: true,
- uses: ["commonapex"],
- }
-
- apex {
- name: "commonapex",
- key: "myapex.key",
- provide_cpp_shared_libs: true,
- }
-
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
- `, func(fs map[string][]byte, config android.Config) {
- setUseVendorAllowListForTest(config, []string{"myapex"})
- })
-}
-
func TestErrorsIfDepsAreNotEnabled(t *testing.T) {
testApexError(t, `module "myapex" .* depends on disabled module "libfoo"`, `
apex {
@@ -4457,7 +4446,7 @@
func TestApexPropertiesShouldBeDefaultable(t *testing.T) {
// libfoo's apex_available comes from cc_defaults
- testApexError(t, `requires "libfoo" that is not available for the APEX`, `
+ testApexError(t, `requires "libfoo" that doesn't list the APEX under 'apex_available'.`, `
apex {
name: "myapex",
key: "myapex.key",
@@ -4491,7 +4480,7 @@
func TestApexAvailable_DirectDep(t *testing.T) {
// libfoo is not available to myapex, but only to otherapex
- testApexError(t, "requires \"libfoo\" that is not available for the APEX", `
+ testApexError(t, "requires \"libfoo\" that doesn't list the APEX under 'apex_available'.", `
apex {
name: "myapex",
key: "myapex.key",
@@ -4526,7 +4515,7 @@
func TestApexAvailable_IndirectDep(t *testing.T) {
// libbbaz is an indirect dep
- testApexError(t, `requires "libbaz" that is not available for the APEX. Dependency path:
+ testApexError(t, `requires "libbaz" that doesn't list the APEX under 'apex_available'. Dependency path:
.*via tag apex\.dependencyTag.*name:sharedLib.*
.*-> libfoo.*link:shared.*
.*via tag cc\.libraryDependencyTag.*Kind:sharedLibraryDependency.*
@@ -5458,7 +5447,7 @@
}
`, withManifestPackageNameOverrides([]string{"AppFoo:com.android.foo"}))
- bundleConfigRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Description("Bundle Config")
+ bundleConfigRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("bundle_config.json")
content := bundleConfigRule.Args["content"]
ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
@@ -5484,7 +5473,7 @@
set: "AppSet.apks",
}`)
mod := ctx.ModuleForTests("myapex", "android_common_myapex_image")
- bundleConfigRule := mod.Description("Bundle Config")
+ bundleConfigRule := mod.Output("bundle_config.json")
content := bundleConfigRule.Args["content"]
ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
s := mod.Rule("apexRule").Args["copy_commands"]
@@ -5497,6 +5486,36 @@
ensureMatches(t, copyCmds[2], "^unzip .*-d .*/app/AppSet .*/AppSet.zip$")
}
+func TestAppSetBundlePrebuilt(t *testing.T) {
+ ctx, _ := testApex(t, "", func(fs map[string][]byte, config android.Config) {
+ bp := `
+ apex_set {
+ name: "myapex",
+ filename: "foo_v2.apex",
+ sanitized: {
+ none: { set: "myapex.apks", },
+ hwaddress: { set: "myapex.hwasan.apks", },
+ },
+ }`
+ fs["Android.bp"] = []byte(bp)
+
+ config.TestProductVariables.SanitizeDevice = []string{"hwaddress"}
+ })
+
+ m := ctx.ModuleForTests("myapex", "android_common")
+ extractedApex := m.Output(buildDir + "/.intermediates/myapex/android_common/foo_v2.apex")
+
+ actual := extractedApex.Inputs
+ if len(actual) != 1 {
+ t.Errorf("expected a single input")
+ }
+
+ expected := "myapex.hwasan.apks"
+ if actual[0].String() != expected {
+ t.Errorf("expected %s, got %s", expected, actual[0].String())
+ }
+}
+
func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, transformDexpreoptConfig func(*dexpreopt.GlobalConfig)) {
t.Helper()
@@ -5600,7 +5619,9 @@
}
cc.GatherRequiredFilesForTest(fs)
- ctx := android.NewTestArchContext()
+ config := android.TestArchConfig(buildDir, nil, bp, fs)
+
+ ctx := android.NewTestArchContext(config)
ctx.RegisterModuleType("apex", BundleFactory)
ctx.RegisterModuleType("apex_key", ApexKeyFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
@@ -5615,8 +5636,7 @@
ctx.PreDepsMutators(RegisterPreDepsMutators)
ctx.PostDepsMutators(RegisterPostDepsMutators)
- config := android.TestArchConfig(buildDir, nil, bp, fs)
- ctx.Register(config)
+ ctx.Register()
_ = dexpreopt.GlobalSoongConfigForTests(config)
dexpreopt.RegisterToolModulesForTest(ctx)
@@ -5659,12 +5679,9 @@
var err string
var transform func(*dexpreopt.GlobalConfig)
- config := android.TestArchConfig(buildDir, nil, "", nil)
- ctx := android.PathContextForTesting(config)
-
t.Run("updatable jar from ART apex in the ART boot image => ok", func(t *testing.T) {
transform = func(config *dexpreopt.GlobalConfig) {
- config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"com.android.art.something:some-art-lib"})
+ config.ArtApexJars = android.CreateTestConfiguredJarList([]string{"com.android.art.something:some-art-lib"})
}
testNoUpdatableJarsInBootImage(t, "", transform)
})
@@ -5672,7 +5689,7 @@
t.Run("updatable jar from ART apex in the framework boot image => error", func(t *testing.T) {
err = `module "some-art-lib" from updatable apexes \["com.android.art.something"\] is not allowed in the framework boot image`
transform = func(config *dexpreopt.GlobalConfig) {
- config.BootJars = android.CreateConfiguredJarList(ctx, []string{"com.android.art.something:some-art-lib"})
+ config.BootJars = android.CreateTestConfiguredJarList([]string{"com.android.art.something:some-art-lib"})
}
testNoUpdatableJarsInBootImage(t, err, transform)
})
@@ -5680,7 +5697,7 @@
t.Run("updatable jar from some other apex in the ART boot image => error", func(t *testing.T) {
err = `module "some-updatable-apex-lib" from updatable apexes \["some-updatable-apex"\] is not allowed in the ART boot image`
transform = func(config *dexpreopt.GlobalConfig) {
- config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"some-updatable-apex:some-updatable-apex-lib"})
+ config.ArtApexJars = android.CreateTestConfiguredJarList([]string{"some-updatable-apex:some-updatable-apex-lib"})
}
testNoUpdatableJarsInBootImage(t, err, transform)
})
@@ -5688,7 +5705,7 @@
t.Run("non-updatable jar from some other apex in the ART boot image => error", func(t *testing.T) {
err = `module "some-non-updatable-apex-lib" is not allowed in the ART boot image`
transform = func(config *dexpreopt.GlobalConfig) {
- config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"some-non-updatable-apex:some-non-updatable-apex-lib"})
+ config.ArtApexJars = android.CreateTestConfiguredJarList([]string{"some-non-updatable-apex:some-non-updatable-apex-lib"})
}
testNoUpdatableJarsInBootImage(t, err, transform)
})
@@ -5696,14 +5713,14 @@
t.Run("updatable jar from some other apex in the framework boot image => error", func(t *testing.T) {
err = `module "some-updatable-apex-lib" from updatable apexes \["some-updatable-apex"\] is not allowed in the framework boot image`
transform = func(config *dexpreopt.GlobalConfig) {
- config.BootJars = android.CreateConfiguredJarList(ctx, []string{"some-updatable-apex:some-updatable-apex-lib"})
+ config.BootJars = android.CreateTestConfiguredJarList([]string{"some-updatable-apex:some-updatable-apex-lib"})
}
testNoUpdatableJarsInBootImage(t, err, transform)
})
t.Run("non-updatable jar from some other apex in the framework boot image => ok", func(t *testing.T) {
transform = func(config *dexpreopt.GlobalConfig) {
- config.BootJars = android.CreateConfiguredJarList(ctx, []string{"some-non-updatable-apex:some-non-updatable-apex-lib"})
+ config.BootJars = android.CreateTestConfiguredJarList([]string{"some-non-updatable-apex:some-non-updatable-apex-lib"})
}
testNoUpdatableJarsInBootImage(t, "", transform)
})
@@ -5711,7 +5728,7 @@
t.Run("nonexistent jar in the ART boot image => error", func(t *testing.T) {
err = "failed to find a dex jar path for module 'nonexistent'"
transform = func(config *dexpreopt.GlobalConfig) {
- config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"platform:nonexistent"})
+ config.ArtApexJars = android.CreateTestConfiguredJarList([]string{"platform:nonexistent"})
}
testNoUpdatableJarsInBootImage(t, err, transform)
})
@@ -5719,7 +5736,7 @@
t.Run("nonexistent jar in the framework boot image => error", func(t *testing.T) {
err = "failed to find a dex jar path for module 'nonexistent'"
transform = func(config *dexpreopt.GlobalConfig) {
- config.BootJars = android.CreateConfiguredJarList(ctx, []string{"platform:nonexistent"})
+ config.BootJars = android.CreateTestConfiguredJarList([]string{"platform:nonexistent"})
}
testNoUpdatableJarsInBootImage(t, err, transform)
})
@@ -5727,14 +5744,14 @@
t.Run("platform jar in the ART boot image => error", func(t *testing.T) {
err = `module "some-platform-lib" is not allowed in the ART boot image`
transform = func(config *dexpreopt.GlobalConfig) {
- config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"platform:some-platform-lib"})
+ config.ArtApexJars = android.CreateTestConfiguredJarList([]string{"platform:some-platform-lib"})
}
testNoUpdatableJarsInBootImage(t, err, transform)
})
t.Run("platform jar in the framework boot image => ok", func(t *testing.T) {
transform = func(config *dexpreopt.GlobalConfig) {
- config.BootJars = android.CreateConfiguredJarList(ctx, []string{"platform:some-platform-lib"})
+ config.BootJars = android.CreateTestConfiguredJarList([]string{"platform:some-platform-lib"})
}
testNoUpdatableJarsInBootImage(t, "", transform)
})
@@ -5742,7 +5759,6 @@
func testApexPermittedPackagesRules(t *testing.T, errmsg, bp string, apexBootJars []string, rules []android.Rule) {
t.Helper()
- android.ClearApexDependency()
bp += `
apex_key {
name: "myapex.key",
@@ -5755,7 +5771,15 @@
"system/sepolicy/apex/myapex-file_contexts": nil,
}
- ctx := android.NewTestArchContext()
+ config := android.TestArchConfig(buildDir, nil, bp, fs)
+ android.SetTestNeverallowRules(config, rules)
+ updatableBootJars := make([]string, 0, len(apexBootJars))
+ for _, apexBootJar := range apexBootJars {
+ updatableBootJars = append(updatableBootJars, "myapex:"+apexBootJar)
+ }
+ config.TestProductVariables.UpdatableBootJars = android.CreateTestConfiguredJarList(updatableBootJars)
+
+ ctx := android.NewTestArchContext(config)
ctx.RegisterModuleType("apex", BundleFactory)
ctx.RegisterModuleType("apex_key", ApexKeyFactory)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
@@ -5768,15 +5792,7 @@
ctx.PostDepsMutators(RegisterPostDepsMutators)
ctx.PostDepsMutators(android.RegisterNeverallowMutator)
- config := android.TestArchConfig(buildDir, nil, bp, fs)
- android.SetTestNeverallowRules(config, rules)
- updatableBootJars := make([]string, 0, len(apexBootJars))
- for _, apexBootJar := range apexBootJars {
- updatableBootJars = append(updatableBootJars, "myapex:"+apexBootJar)
- }
- config.TestProductVariables.UpdatableBootJars = updatableBootJars
-
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseBlueprintsFiles("Android.bp")
android.FailIfErrored(t, errs)
@@ -6120,7 +6136,7 @@
name: "mylib",
srcs: ["mylib.cpp"],
stubs: {
- versions: ["10000"],
+ versions: ["current"],
},
apex_available: ["myapex"],
}
@@ -6130,7 +6146,7 @@
prefer: false,
srcs: ["prebuilt.so"],
stubs: {
- versions: ["10000"],
+ versions: ["current"],
},
apex_available: ["myapex"],
}
diff --git a/apex/builder.go b/apex/builder.go
index c5680ad..acfb8c5 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -214,7 +214,8 @@
},
})
- 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")
@@ -257,15 +258,34 @@
output := android.PathForModuleOut(ctx, "file_contexts")
rule := android.NewRuleBuilder()
- // remove old file
- rule.Command().Text("rm").FlagWithOutput("-f ", output)
- // copy file_contexts
- rule.Command().Text("cat").Input(fileContexts).Text(">>").Output(output)
- // new line
- rule.Command().Text("echo").Text(">>").Output(output)
- // force-label /apex_manifest.pb and / as system_file so that apexd can read them
- rule.Command().Text("echo").Flag("/apex_manifest\\\\.pb u:object_r:system_file:s0").Text(">>").Output(output)
- rule.Command().Text("echo").Flag("/ u:object_r:system_file:s0").Text(">>").Output(output)
+
+ if a.properties.ApexType == imageApex {
+ // remove old file
+ rule.Command().Text("rm").FlagWithOutput("-f ", output)
+ // copy file_contexts
+ rule.Command().Text("cat").Input(fileContexts).Text(">>").Output(output)
+ // new line
+ rule.Command().Text("echo").Text(">>").Output(output)
+ // force-label /apex_manifest.pb and / as system_file so that apexd can read them
+ rule.Command().Text("echo").Flag("/apex_manifest\\\\.pb u:object_r:system_file:s0").Text(">>").Output(output)
+ rule.Command().Text("echo").Flag("/ u:object_r:system_file:s0").Text(">>").Output(output)
+ } else {
+ // For flattened apexes, install path should be prepended.
+ // File_contexts file should be emiited to make via LOCAL_FILE_CONTEXTS
+ // so that it can be merged into file_contexts.bin
+ apexPath := android.InstallPathToOnDevicePath(ctx, a.installDir.Join(ctx, a.Name()))
+ apexPath = strings.ReplaceAll(apexPath, ".", `\\.`)
+ // remove old file
+ rule.Command().Text("rm").FlagWithOutput("-f ", output)
+ // copy file_contexts
+ rule.Command().Text("awk").Text(`'/object_r/{printf("` + apexPath + `%s\n", $0)}'`).Input(fileContexts).Text(">").Output(output)
+ // new line
+ rule.Command().Text("echo").Text(">>").Output(output)
+ // force-label /apex_manifest.pb and / as system_file so that apexd can read them
+ rule.Command().Text("echo").Flag(apexPath + `/apex_manifest\\.pb u:object_r:system_file:s0`).Text(">>").Output(output)
+ rule.Command().Text("echo").Flag(apexPath + "/ u:object_r:system_file:s0").Text(">>").Output(output)
+ }
+
rule.Build(pctx, ctx, "file_contexts."+a.Name(), "Generate file_contexts")
a.fileContexts = output.OutputPath
@@ -353,14 +373,7 @@
panic(fmt.Errorf("error while marshalling to %q: %#v", output, err))
}
- ctx.Build(pctx, android.BuildParams{
- Rule: android.WriteFile,
- Output: output,
- Description: "Bundle Config " + output.String(),
- Args: map[string]string{
- "content": string(j),
- },
- })
+ android.WriteFileRule(ctx, output, string(j))
return output.OutputPath
}
@@ -426,7 +439,8 @@
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,13 +546,16 @@
optFlags = append(optFlags, "--android_manifest "+androidManifestFile.String())
}
- targetSdkVersion := ctx.Config().DefaultAppTargetSdk()
- // TODO(b/157078772): propagate min_sdk_version to apexer.
- minSdkVersion := ctx.Config().DefaultAppTargetSdk()
+ moduleMinSdkVersion := a.minSdkVersion(ctx)
+ minSdkVersion := moduleMinSdkVersion.String()
- if a.minSdkVersion(ctx) == android.SdkVersion_Android10 {
- minSdkVersion = strconv.Itoa(a.minSdkVersion(ctx))
+ // bundletool doesn't understand what "current" is. We need to transform it to codename
+ if moduleMinSdkVersion.IsCurrent() {
+ minSdkVersion = ctx.Config().DefaultAppTargetSdk(ctx).String()
}
+ // apex module doesn't have a concept of target_sdk_version, hence for the time being
+ // targetSdkVersion == default targetSdkVersion of the branch.
+ targetSdkVersion := strconv.Itoa(ctx.Config().DefaultAppTargetSdk(ctx).FinalOrFutureInt())
if java.UseApiFingerprint(ctx) {
targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", java.ApiFingerprintPath(ctx).String())
@@ -566,7 +583,7 @@
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 +600,7 @@
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())
}
@@ -687,14 +704,7 @@
// instead of `android.PathForOutput`) to return the correct path to the flattened
// APEX (as its contents is installed by Make, not Soong).
factx := flattenedApexContext{ctx}
- apexBundleName := a.Name()
- a.outputFile = android.PathForModuleInstall(&factx, "apex", apexBundleName)
-
- if a.installable() {
- installPath := android.PathForModuleInstall(ctx, "apex", apexBundleName)
- devicePath := android.InstallPathToOnDevicePath(ctx, installPath)
- addFlattenedFileContextsInfos(ctx, apexBundleName+":"+devicePath+":"+a.fileContexts.String())
- }
+ a.outputFile = android.PathForModuleInstall(&factx, "apex", a.Name())
a.buildFilesInfo(ctx)
}
diff --git a/apex/key.go b/apex/key.go
index d2d5786..43764da 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -116,7 +116,7 @@
partition string
}
toString := func(e apexKeyEntry) string {
- format := "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q\\n"
+ format := "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q\n"
if e.presigned {
return fmt.Sprintf(format, e.name, "PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED", e.partition)
} else {
@@ -173,17 +173,9 @@
var filecontent strings.Builder
for _, name := range moduleNames {
- fmt.Fprintf(&filecontent, "%s", toString(apexKeyMap[name]))
+ filecontent.WriteString(toString(apexKeyMap[name]))
}
-
- ctx.Build(pctx, android.BuildParams{
- Rule: android.WriteFile,
- Description: "apexkeys.txt",
- Output: s.output,
- Args: map[string]string{
- "content": filecontent.String(),
- },
- })
+ android.WriteFileRule(ctx, s.output, filecontent.String())
}
func apexKeysTextFactory() android.Singleton {
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 37457e9..ce16d73 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -50,6 +50,10 @@
properties prebuiltCommonProperties
}
+type sanitizedPrebuilt interface {
+ hasSanitizedSource(sanitizer string) bool
+}
+
type prebuiltCommonProperties struct {
ForceDisable bool `blueprint:"mutated"`
}
@@ -75,9 +79,10 @@
forceDisable = forceDisable || ctx.DeviceConfig().NativeCoverageEnabled()
forceDisable = forceDisable || ctx.Config().IsEnvTrue("EMMA_INSTRUMENT")
- // b/137216042 don't use prebuilts when address sanitizer is on
- forceDisable = forceDisable || android.InList("address", ctx.Config().SanitizeDevice()) ||
- android.InList("hwaddress", ctx.Config().SanitizeDevice())
+ // b/137216042 don't use prebuilts when address sanitizer is on, unless the prebuilt has a sanitized source
+ sanitized := ctx.Module().(sanitizedPrebuilt)
+ forceDisable = forceDisable || (android.InList("address", ctx.Config().SanitizeDevice()) && !sanitized.hasSanitizedSource("address"))
+ forceDisable = forceDisable || (android.InList("hwaddress", ctx.Config().SanitizeDevice()) && !sanitized.hasSanitizedSource("hwaddress"))
if forceDisable && p.prebuilt.SourceExists() {
p.properties.ForceDisable = true
@@ -135,6 +140,10 @@
Overrides []string
}
+func (a *Prebuilt) hasSanitizedSource(sanitizer string) bool {
+ return false
+}
+
func (p *Prebuilt) installable() bool {
return p.properties.Installable == nil || proptools.Bool(p.properties.Installable)
}
@@ -266,6 +275,18 @@
// the .apks file path that contains prebuilt apex files to be extracted.
Set *string
+ Sanitized struct {
+ None struct {
+ Set *string
+ }
+ Address struct {
+ Set *string
+ }
+ Hwaddress struct {
+ Set *string
+ }
+ }
+
// whether the extracted apex file installable.
Installable *bool
@@ -284,6 +305,41 @@
Prerelease *bool
}
+func (a *ApexSet) prebuiltSrcs(ctx android.BaseModuleContext) []string {
+ var srcs []string
+ if a.properties.Set != nil {
+ srcs = append(srcs, *a.properties.Set)
+ }
+
+ var sanitizers []string
+ if ctx.Host() {
+ sanitizers = ctx.Config().SanitizeHost()
+ } else {
+ sanitizers = ctx.Config().SanitizeDevice()
+ }
+
+ if android.InList("address", sanitizers) && a.properties.Sanitized.Address.Set != nil {
+ srcs = append(srcs, *a.properties.Sanitized.Address.Set)
+ } else if android.InList("hwaddress", sanitizers) && a.properties.Sanitized.Hwaddress.Set != nil {
+ srcs = append(srcs, *a.properties.Sanitized.Hwaddress.Set)
+ } else if a.properties.Sanitized.None.Set != nil {
+ srcs = append(srcs, *a.properties.Sanitized.None.Set)
+ }
+
+ return srcs
+}
+
+func (a *ApexSet) hasSanitizedSource(sanitizer string) bool {
+ if sanitizer == "address" {
+ return a.properties.Sanitized.Address.Set != nil
+ }
+ if sanitizer == "hwaddress" {
+ return a.properties.Sanitized.Hwaddress.Set != nil
+ }
+
+ return false
+}
+
func (a *ApexSet) installable() bool {
return a.properties.Installable == nil || proptools.Bool(a.properties.Installable)
}
@@ -304,7 +360,12 @@
func apexSetFactory() android.Module {
module := &ApexSet{}
module.AddProperties(&module.properties)
- android.InitSingleSourcePrebuiltModule(module, &module.properties, "Set")
+
+ srcsSupplier := func(ctx android.BaseModuleContext) []string {
+ return module.prebuiltSrcs(ctx)
+ }
+
+ android.InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "set")
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
return module
}
@@ -326,7 +387,7 @@
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 5cc0e2a..f4b12b5 100644
--- a/apex/vndk.go
+++ b/apex/vndk.go
@@ -16,7 +16,6 @@
import (
"path/filepath"
- "strconv"
"strings"
"sync"
@@ -124,10 +123,10 @@
// 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
@@ -153,7 +152,7 @@
}
// TODO(b/124106384): Clean up compat symlinks for ART binaries.
- if strings.HasPrefix(name, "com.android.art.") {
+ if name == "com.android.art" || strings.HasPrefix(name, "com.android.art.") {
addSymlink("/apex/com.android.art/bin/dalvikvm", "$(TARGET_OUT)/bin", "dalvikvm")
dex2oat := "dex2oat32"
if ctx.Config().Android64() {
diff --git a/apex/vndk_test.go b/apex/vndk_test.go
index 60b6ed5..27d93ee 100644
--- a/apex/vndk_test.go
+++ b/apex/vndk_test.go
@@ -25,6 +25,7 @@
name: "libvndk",
srcs: ["mylib.cpp"],
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -37,6 +38,7 @@
name: "libvndksp",
srcs: ["mylib.cpp"],
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
@@ -73,6 +75,7 @@
cc_library {
name: "libfoo",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
diff --git a/bazel/bazelenv.sh b/bazel/bazelenv.sh
new file mode 100755
index 0000000..fcf71f1
--- /dev/null
+++ b/bazel/bazelenv.sh
@@ -0,0 +1,78 @@
+#!/bin/bash
+
+# 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.
+
+# Helper script for setting environment variables required for Bazel/Soong
+# mixed builds prototype. For development use only.
+#
+# Usage:
+# export BAZEL_PATH=[some_bazel_path] && source bazelenv.sh
+#
+# If BAZEL_PATH is not set, `which bazel` will be used
+# to locate the appropriate bazel to use.
+
+
+# Function to find top of the source tree (if $TOP isn't set) by walking up the
+# tree.
+function gettop
+{
+ local TOPFILE=build/soong/root.bp
+ if [ -n "${TOP-}" -a -f "${TOP-}/${TOPFILE}" ] ; then
+ # The following circumlocution ensures we remove symlinks from TOP.
+ (cd $TOP; PWD= /bin/pwd)
+ else
+ if [ -f $TOPFILE ] ; then
+ # The following circumlocution (repeated below as well) ensures
+ # that we record the true directory name and not one that is
+ # faked up with symlink names.
+ PWD= /bin/pwd
+ else
+ local HERE=$PWD
+ T=
+ while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
+ \cd ..
+ T=`PWD= /bin/pwd -P`
+ done
+ \cd $HERE
+ if [ -f "$T/$TOPFILE" ]; then
+ echo $T
+ fi
+ fi
+ fi
+}
+
+BASE_DIR="$(mktemp -d)"
+
+if [ -z "$BAZEL_PATH" ] ; then
+ export BAZEL_PATH="$(which bazel)"
+fi
+
+# TODO(cparsons): Use USE_BAZEL=1 instead once "mixed Soong/Bazel builds" are
+# production ready.
+export USE_BAZEL_ANALYSIS=1
+# TODO(cparsons): Retrieve this information in either envsetup.sh or
+# bazel.sh.
+export BAZEL_HOME="$BASE_DIR/bazelhome"
+export BAZEL_OUTPUT_BASE="$BASE_DIR/output"
+export BAZEL_WORKSPACE="$(gettop)"
+
+echo "USE_BAZEL_ANALYSIS=${USE_BAZEL_ANALYSIS}"
+echo "BAZEL_PATH=${BAZEL_PATH}"
+echo "BAZEL_HOME=${BAZEL_HOME}"
+echo "BAZEL_OUTPUT_BASE=${BAZEL_OUTPUT_BASE}"
+echo "BAZEL_WORKSPACE=${BAZEL_WORKSPACE}"
+
+mkdir -p $BAZEL_HOME
+mkdir -p $BAZEL_OUTPUT_BASE
diff --git a/bazel/master.WORKSPACE.bazel b/bazel/master.WORKSPACE.bazel
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bazel/master.WORKSPACE.bazel
diff --git a/bpf/bpf_test.go b/bpf/bpf_test.go
index d06d7d1..be9e36e 100644
--- a/bpf/bpf_test.go
+++ b/bpf/bpf_test.go
@@ -58,9 +58,9 @@
}
func testContext(config android.Config) *android.TestContext {
- ctx := cc.CreateTestContext()
+ ctx := cc.CreateTestContext(config)
ctx.RegisterModuleType("bpf", BpfFactory)
- ctx.Register(config)
+ ctx.Register()
return ctx
}
diff --git a/build_test.bash b/build_test.bash
index ee979e7..accca0f 100755
--- a/build_test.bash
+++ b/build_test.bash
@@ -43,5 +43,11 @@
;;
esac
+echo
+echo "Running Bazel smoke test..."
+"${TOP}/tools/bazel" --batch --max_idle_secs=1 info
+
+echo
+echo "Running Soong test..."
soong_build_go multiproduct_kati android/soong/cmd/multiproduct_kati
exec "$(getoutdir)/multiproduct_kati" "$@"
diff --git a/cc/Android.bp b/cc/Android.bp
index 831911e..ff2cdf3 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -13,6 +13,7 @@
],
srcs: [
"androidmk.go",
+ "api_level.go",
"builder.go",
"cc.go",
"ccdeps.go",
diff --git a/cc/OWNERS b/cc/OWNERS
new file mode 100644
index 0000000..6d7c30a
--- /dev/null
+++ b/cc/OWNERS
@@ -0,0 +1,4 @@
+per-file ndk_*.go = danalbert@google.com
+per-file tidy.go = srhines@google.com, chh@google.com
+per-file lto.go,pgo.go = srhines@google.com, pirama@google.com, yikong@google.com
+
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 380b4e9..38269cb 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -24,16 +24,17 @@
)
var (
- nativeBridgeSuffix = ".native_bridge"
- productSuffix = ".product"
- vendorSuffix = ".vendor"
- ramdiskSuffix = ".ramdisk"
- recoverySuffix = ".recovery"
- sdkSuffix = ".sdk"
+ nativeBridgeSuffix = ".native_bridge"
+ productSuffix = ".product"
+ vendorSuffix = ".vendor"
+ ramdiskSuffix = ".ramdisk"
+ vendorRamdiskSuffix = ".vendor_ramdisk"
+ recoverySuffix = ".recovery"
+ sdkSuffix = ".sdk"
)
type AndroidMkContext interface {
- Name() string
+ BaseModuleName() string
Target() android.Target
subAndroidMk(*android.AndroidMkEntries, interface{})
Arch() android.Arch
@@ -43,7 +44,9 @@
VndkVersion() string
static() bool
InRamdisk() bool
+ InVendorRamdisk() bool
InRecovery() bool
+ AnyVariantDirectlyInAnyApex() bool
}
type subAndroidMkProvider interface {
@@ -63,7 +66,7 @@
}
func (c *Module) AndroidMkEntries() []android.AndroidMkEntries {
- if c.Properties.HideFromMake || !c.IsForPlatform() {
+ if c.hideApexVariantFromMake || c.Properties.HideFromMake {
return []android.AndroidMkEntries{{
Disabled: true,
}}
@@ -71,10 +74,11 @@
entries := android.AndroidMkEntries{
OutputFile: c.outputFile,
- // TODO(jiyong): add the APEXes providing shared libs to the required modules
- // Currently, adding c.Properties.ApexesProvidingSharedLibs is causing multiple
- // ART APEXes (com.android.art.debug|release) to be installed. And this
- // is breaking some older devices (like marlin) where system.img is small.
+ // TODO(jiyong): add the APEXes providing shared libs to the required
+ // modules Currently, adding c.Properties.ApexesProvidingSharedLibs is
+ // causing multiple ART APEXes (com.android.art and com.android.art.debug)
+ // to be installed. And this is breaking some older devices (like marlin)
+ // where system.img is small.
Required: c.Properties.AndroidMkRuntimeLibs,
Include: "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk",
@@ -83,6 +87,13 @@
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 +160,6 @@
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 +169,7 @@
}
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...)
@@ -197,17 +190,17 @@
}
func (library *libraryDecorator) androidMkWriteExportedFlags(entries *android.AndroidMkEntries) {
- exportedFlags := library.exportedFlags()
- for _, dir := range library.exportedDirs() {
+ exportedFlags := library.flagExporter.flags
+ for _, dir := range library.flagExporter.dirs {
exportedFlags = append(exportedFlags, "-I"+dir.String())
}
- for _, dir := range library.exportedSystemDirs() {
+ for _, dir := range library.flagExporter.systemDirs {
exportedFlags = append(exportedFlags, "-isystem "+dir.String())
}
if len(exportedFlags) > 0 {
entries.AddStrings("LOCAL_EXPORT_CFLAGS", exportedFlags...)
}
- exportedDeps := library.exportedDeps()
+ exportedDeps := library.flagExporter.deps
if len(exportedDeps) > 0 {
entries.AddStrings("LOCAL_EXPORT_C_INCLUDE_DEPS", exportedDeps.Strings()...)
}
@@ -288,9 +281,8 @@
}
})
}
- if len(library.Properties.Stubs.Versions) > 0 &&
- android.DirectlyInAnyApex(ctx, ctx.Name()) && !ctx.InRamdisk() && !ctx.InRecovery() && !ctx.UseVndk() &&
- !ctx.static() {
+ if len(library.Properties.Stubs.Versions) > 0 && !ctx.Host() && ctx.AnyVariantDirectlyInAnyApex() &&
+ !ctx.InRamdisk() && !ctx.InVendorRamdisk() && !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
entries.SubName = ""
@@ -451,9 +443,14 @@
}
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"
+ if !c.buildStubs() {
+ entries.Disabled = true
+ return
+ }
+
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
path, file := filepath.Split(c.installPath.String())
stem, suffix, _ := android.SplitFileExt(file)
@@ -469,6 +466,7 @@
func (c *llndkStubDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
entries.Class = "SHARED_LIBRARIES"
+ entries.OverrideName = c.implementationModuleName(ctx.BaseModuleName())
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
c.libraryDecorator.androidMkWriteExportedFlags(entries)
@@ -489,15 +487,21 @@
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
c.libraryDecorator.androidMkWriteExportedFlags(entries)
- path, file := filepath.Split(c.path.ToMakePath().String())
+ // Specifying stem is to pass check_elf_files when vendor modules link against vndk prebuilt.
+ // We can't use install path because VNDKs are not installed. Instead, Srcs is directly used.
+ _, file := filepath.Split(c.properties.Srcs[0])
stem, suffix, ext := android.SplitFileExt(file)
entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext)
entries.SetString("LOCAL_MODULE_SUFFIX", suffix)
- entries.SetString("LOCAL_MODULE_PATH", path)
entries.SetString("LOCAL_MODULE_STEM", stem)
+
if c.tocFile.Valid() {
entries.SetString("LOCAL_SOONG_TOC", c.tocFile.String())
}
+
+ // VNDK libraries available to vendor are not installed because
+ // they are packaged in VNDK APEX and installed by APEX packages (apex/apex.go)
+ entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
})
}
diff --git a/cc/api_level.go b/cc/api_level.go
new file mode 100644
index 0000000..c93d6ed
--- /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.go b/cc/binary.go
index b3ce5ff..da29412 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -95,6 +95,10 @@
// Names of symlinks to be installed for use in LOCAL_MODULE_SYMLINKS
symlinks []string
+ // If the module has symlink_preferred_arch set, the name of the symlink to the
+ // binary for the preferred arch.
+ preferredArchSymlink string
+
// Output archive of gcno coverage information
coverageOutputFile android.OptionalPath
@@ -251,7 +255,7 @@
} else {
switch ctx.Os() {
case android.Android:
- if ctx.bootstrap() && !ctx.inRecovery() && !ctx.inRamdisk() {
+ if ctx.bootstrap() && !ctx.inRecovery() && !ctx.inRamdisk() && !ctx.inVendorRamdisk() {
flags.DynamicLinker = "/system/bin/bootstrap/linker"
} else {
flags.DynamicLinker = "/system/bin/linker"
@@ -402,7 +406,9 @@
ctx.PropertyErrorf("symlink_preferred_arch", "must also specify suffix")
}
if ctx.TargetPrimary() {
- binary.symlinks = append(binary.symlinks, binary.getStemWithoutSuffix(ctx))
+ symlinkName := binary.getStemWithoutSuffix(ctx)
+ binary.symlinks = append(binary.symlinks, symlinkName)
+ binary.preferredArchSymlink = symlinkName
}
}
@@ -445,19 +451,36 @@
// The original path becomes a symlink to the corresponding file in the
// runtime APEX.
translatedArch := ctx.Target().NativeBridge == android.NativeBridgeEnabled
- if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && InstallToBootstrap(ctx.baseModuleName(), ctx.Config()) && !translatedArch && ctx.apexVariationName() == "" && !ctx.inRamdisk() && !ctx.inRecovery() {
+ if InstallToBootstrap(ctx.baseModuleName(), ctx.Config()) && !ctx.Host() && ctx.directlyInAnyApex() &&
+ !translatedArch && ctx.apexVariationName() == "" && !ctx.inRamdisk() && !ctx.inRecovery() &&
+ !ctx.inVendorRamdisk() {
+
if ctx.Device() && isBionic(ctx.baseModuleName()) {
binary.installSymlinkToRuntimeApex(ctx, file)
}
binary.baseInstaller.subDir = "bootstrap"
}
binary.baseInstaller.install(ctx, file)
+
+ var preferredArchSymlinkPath android.OptionalPath
for _, symlink := range binary.symlinks {
- ctx.InstallSymlink(binary.baseInstaller.installDir(ctx), symlink, binary.baseInstaller.path)
+ installedSymlink := ctx.InstallSymlink(binary.baseInstaller.installDir(ctx), symlink,
+ binary.baseInstaller.path)
+ if symlink == binary.preferredArchSymlink {
+ // If this is the preferred arch symlink, save the installed path for use as the
+ // tool path.
+ preferredArchSymlinkPath = android.OptionalPathForPath(installedSymlink)
+ }
}
if ctx.Os().Class == android.Host {
- binary.toolPath = android.OptionalPathForPath(binary.baseInstaller.path)
+ // If the binary is multilib with a symlink to the preferred architecture, use the
+ // symlink instead of the binary because that's the more "canonical" name.
+ if preferredArchSymlinkPath.Valid() {
+ binary.toolPath = preferredArchSymlinkPath
+ } else {
+ binary.toolPath = android.OptionalPathForPath(binary.baseInstaller.path)
+ }
}
}
diff --git a/cc/binary_sdk_member.go b/cc/binary_sdk_member.go
index a1abc72..ebf89ea 100644
--- a/cc/binary_sdk_member.go
+++ b/cc/binary_sdk_member.go
@@ -40,19 +40,14 @@
func (mt *binarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
targets := mctx.MultiTargets()
- for _, lib := range names {
+ for _, bin := range names {
for _, target := range targets {
- name, version := StubsLibNameAndVersion(lib)
- if version == "" {
- version = LatestStubsVersionFor(mctx.Config(), name)
- }
variations := target.Variations()
if mctx.Device() {
variations = append(variations,
- blueprint.Variation{Mutator: "image", Variation: android.CoreVariation},
- blueprint.Variation{Mutator: "version", Variation: version})
+ blueprint.Variation{Mutator: "image", Variation: android.CoreVariation})
}
- mctx.AddFarVariationDependencies(variations, dependencyTag, name)
+ mctx.AddFarVariationDependencies(variations, dependencyTag, bin)
}
}
}
diff --git a/cc/builder.go b/cc/builder.go
index ef65348..81c09b1 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -221,7 +221,6 @@
ExecStrategy: "${config.REAbiDumperExecStrategy}",
Platform: map[string]string{
remoteexec.PoolKey: "${config.RECXXPool}",
- "InputRootAbsolutePath": android.AbsSrcDirForExistingUseCases(),
},
}, []string{"cFlags", "exportDirs"}, nil)
diff --git a/cc/cc.go b/cc/cc.go
index 70229be..5e4faf2 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -45,9 +45,9 @@
ctx.BottomUp("sdk", sdkMutator).Parallel()
ctx.BottomUp("vndk", VndkMutator).Parallel()
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()
@@ -84,6 +84,7 @@
ctx.TopDown("lto_deps", ltoDepsMutator)
ctx.BottomUp("lto", ltoMutator).Parallel()
+ ctx.BottomUp("check_linktype", checkLinkTypeMutator).Parallel()
ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel()
})
@@ -99,6 +100,9 @@
// 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
@@ -126,6 +130,9 @@
// Paths to .a files
StaticLibs, LateStaticLibs, WholeStaticLibs android.Paths
+ // Transitive static library dependencies of static libraries for use in ordering.
+ TranstiveStaticLibrariesForOrdering *android.DepSet
+
// Paths to .o files
Objs Objects
// Paths to .o files in dependencies that provide them. Note that these lists
@@ -237,6 +244,9 @@
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"`
@@ -245,17 +255,29 @@
// file
Logtags []string
- // Make this module available when building for ramdisk
+ // Make this module available when building for ramdisk.
+ // On device without a dedicated recovery partition, the module is only
+ // available after switching root into
+ // /first_stage_ramdisk. To expose the module before switching root, install
+ // the recovery variant instead.
Ramdisk_available *bool
+ // Make this module available when building for vendor ramdisk.
+ // On device without a dedicated recovery partition, the module is only
+ // available after switching root into
+ // /first_stage_ramdisk. To expose the module before switching root, install
+ // the recovery variant instead.
+ Vendor_ramdisk_available *bool
+
// Make this module available when building for recovery
Recovery_available *bool
// Set by imageMutator
- CoreVariantNeeded bool `blueprint:"mutated"`
- RamdiskVariantNeeded bool `blueprint:"mutated"`
- RecoveryVariantNeeded bool `blueprint:"mutated"`
- ExtraVariants []string `blueprint:"mutated"`
+ CoreVariantNeeded bool `blueprint:"mutated"`
+ RamdiskVariantNeeded bool `blueprint:"mutated"`
+ VendorRamdiskVariantNeeded bool `blueprint:"mutated"`
+ RecoveryVariantNeeded bool `blueprint:"mutated"`
+ ExtraVariants []string `blueprint:"mutated"`
// Allows this module to use non-APEX version of libraries. Useful
// for building binaries that are started before APEXes are activated.
@@ -292,26 +314,39 @@
type VendorProperties struct {
// whether this module should be allowed to be directly depended by other
// modules with `vendor: true`, `proprietary: true`, or `vendor_available:true`.
- // In addition, this module should be allowed to be directly depended by
- // product modules with `product_specific: true`.
- // If set to true, three variants will be built separately, one like
- // normal, another limited to the set of libraries and headers
- // that are exposed to /vendor modules, and the other to /product modules.
+ // If set to true, two variants will be built separately, one like
+ // normal, and the other limited to the set of libraries and headers
+ // that are exposed to /vendor modules.
//
- // The vendor and product variants may be used with a different (newer) /system,
+ // The vendor variant may be used with a different (newer) /system,
// so it shouldn't have any unversioned runtime dependencies, or
// make assumptions about the system that may not be true in the
// future.
//
- // If set to false, this module becomes inaccessible from /vendor or /product
- // modules.
+ // If set to false, this module becomes inaccessible from /vendor modules.
//
// Default value is true when vndk: {enabled: true} or vendor: true.
//
// Nothing happens if BOARD_VNDK_VERSION isn't set in the BoardConfig.mk
- // If PRODUCT_PRODUCT_VNDK_VERSION isn't set, product variant will not be used.
Vendor_available *bool
+ // whether this module should be allowed to be directly depended by other
+ // modules with `product_specific: true` or `product_available: true`.
+ // If set to true, an additional product variant will be built separately
+ // that is limited to the set of libraries and headers that are exposed to
+ // /product modules.
+ //
+ // The product variant may be used with a different (newer) /system,
+ // so it shouldn't have any unversioned runtime dependencies, or
+ // make assumptions about the system that may not be true in the
+ // future.
+ //
+ // It must be set to true by default for vndk: {enabled: true} modules.
+ //
+ // Nothing happens if BOARD_VNDK_VERSION isn't set in the BoardConfig.mk
+ // and PRODUCT_PRODUCT_VNDK_VERSION isn't set.
+ Product_available *bool
+
// whether this module is capable of being loaded with other instance
// (possibly an older version) of the same module in the same process.
// Currently, a shared library that is a member of VNDK (vndk: {enabled: true})
@@ -343,6 +378,7 @@
inProduct() bool
inVendor() bool
inRamdisk() bool
+ inVendorRamdisk() bool
inRecovery() bool
shouldCreateSourceAbiDump() bool
selectedStl() string
@@ -353,12 +389,11 @@
useClangLld(actx ModuleContext) bool
isForPlatform() bool
apexVariationName() string
- apexSdkVersion() int
- hasStubsVariants() bool
- isStubs() bool
+ apexSdkVersion() android.ApiLevel
bootstrap() bool
mustUseVendorVariant() bool
nativeCoverage() bool
+ directlyInAnyApex() bool
}
type ModuleContext interface {
@@ -538,8 +573,15 @@
dataLibDepTag = dependencyTag{name: "data lib"}
runtimeDepTag = dependencyTag{name: "runtime lib"}
testPerSrcDepTag = dependencyTag{name: "test_per_src"}
+ stubImplDepTag = dependencyTag{name: "stub_impl"}
)
+type copyDirectlyInAnyApexDependencyTag dependencyTag
+
+func (copyDirectlyInAnyApexDependencyTag) CopyDirectlyInAnyApex() {}
+
+var _ android.CopyDirectlyInAnyApexTag = copyDirectlyInAnyApexDependencyTag{}
+
func IsSharedDepTag(depTag blueprint.DependencyTag) bool {
ccLibDepTag, ok := depTag.(libraryDependencyTag)
return ok && ccLibDepTag.shared()
@@ -550,6 +592,11 @@
return ok && ccLibDepTag.static()
}
+func IsHeaderDepTag(depTag blueprint.DependencyTag) bool {
+ ccLibDepTag, ok := depTag.(libraryDependencyTag)
+ return ok && ccLibDepTag.header()
+}
+
func IsRuntimeDepTag(depTag blueprint.DependencyTag) bool {
ccDepTag, ok := depTag.(dependencyTag)
return ok && ccDepTag == runtimeDepTag
@@ -592,6 +639,8 @@
lto *lto
pgo *pgo
+ library libraryInterface
+
outputFile android.OptionalPath
cachedToolchain config.Toolchain
@@ -601,20 +650,17 @@
// Flags used to compile this module
flags Flags
- // When calling a linker, if module A depends on module B, then A must precede B in its command
- // line invocation. depsInLinkOrder stores the proper ordering of all of the transitive
- // deps of this module
- depsInLinkOrder android.Paths
-
// only non-nil when this is a shared library that reuses the objects of a static library
- staticVariant LinkableInterface
+ staticAnalogue *StaticLibraryInfo
makeLinkType string
// Kythe (source file indexer) paths for this compilation module
kytheFiles android.Paths
// For apex variants, this is set as apex.min_sdk_version
- apexSdkVersion int
+ apexSdkVersion android.ApiLevel
+
+ hideApexVariantFromMake bool
}
func (c *Module) Toc() android.OptionalPath {
@@ -629,7 +675,7 @@
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()))
@@ -690,6 +736,9 @@
}
func (c *Module) SplitPerApiLevel() bool {
+ if !c.canUseSdk() {
+ return false
+ }
if linker, ok := c.linker.(*objectLinker); ok {
return linker.isCrt()
}
@@ -700,48 +749,14 @@
return c.Properties.AlwaysSdk || Bool(c.Properties.Sdk_variant_only)
}
-func (c *Module) IncludeDirs() android.Paths {
- if c.linker != nil {
- if library, ok := c.linker.(exportedFlagsProducer); ok {
- return library.exportedDirs()
- }
- }
- panic(fmt.Errorf("IncludeDirs called on non-exportedFlagsProducer module: %q", c.BaseModuleName()))
-}
-
-func (c *Module) HasStaticVariant() bool {
- if c.staticVariant != nil {
- return true
- }
- return false
-}
-
-func (c *Module) GetStaticVariant() LinkableInterface {
- return c.staticVariant
-}
-
-func (c *Module) SetDepsInLinkOrder(depsInLinkOrder []android.Path) {
- c.depsInLinkOrder = depsInLinkOrder
-}
-
-func (c *Module) GetDepsInLinkOrder() []android.Path {
- return c.depsInLinkOrder
-}
-
-func (c *Module) StubsVersions() []string {
- if c.linker != nil {
- if library, ok := c.linker.(*libraryDecorator); ok {
- return library.Properties.Stubs.Versions
- }
- }
- panic(fmt.Errorf("StubsVersions called on non-library module: %q", c.BaseModuleName()))
-}
-
func (c *Module) CcLibrary() bool {
if c.linker != nil {
if _, ok := c.linker.(*libraryDecorator); ok {
return true
}
+ if _, ok := c.linker.(*prebuiltLibraryLinker); ok {
+ return true
+ }
}
return false
}
@@ -757,59 +772,6 @@
return false
}
-func (c *Module) SetBuildStubs() {
- if c.linker != nil {
- if library, ok := c.linker.(*libraryDecorator); 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
- }
- }
- panic(fmt.Errorf("SetBuildStubs called on non-library module: %q", c.BaseModuleName()))
-}
-
-func (c *Module) BuildStubs() bool {
- if c.linker != nil {
- if library, ok := c.linker.(*libraryDecorator); ok {
- return library.buildStubs()
- }
- }
- panic(fmt.Errorf("BuildStubs called on non-library module: %q", c.BaseModuleName()))
-}
-
-func (c *Module) SetStubsVersions(version string) {
- if c.linker != nil {
- if library, ok := c.linker.(*libraryDecorator); 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()))
-}
-
-func (c *Module) StubsVersion() string {
- if c.linker != nil {
- if library, ok := c.linker.(*libraryDecorator); ok {
- return library.MutatedProperties.StubsVersion
- }
- if llndk, ok := c.linker.(*llndkStubDecorator); ok {
- return llndk.libraryDecorator.MutatedProperties.StubsVersion
- }
- }
- panic(fmt.Errorf("StubsVersion called on non-library module: %q", c.BaseModuleName()))
-}
-
func (c *Module) SetStatic() {
if c.linker != nil {
if library, ok := c.linker.(libraryInterface); ok {
@@ -928,9 +890,9 @@
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)
@@ -955,19 +917,19 @@
// "product" and "vendor" variant modules return true for this function.
// When BOARD_VNDK_VERSION is set, vendor variants of "vendor_available: true", "vendor: true",
// "soc_specific: true" and more vendor installed modules are included here.
-// When PRODUCT_PRODUCT_VNDK_VERSION is set, product variants of "vendor_available: true" or
+// When PRODUCT_PRODUCT_VNDK_VERSION is set, product variants of "product_available: true" or
// "product_specific: true" modules are included here.
func (c *Module) UseVndk() bool {
return c.Properties.VndkVersion != ""
}
func (c *Module) canUseSdk() bool {
- return c.Os() == android.Android && !c.UseVndk() && !c.InRamdisk() && !c.InRecovery()
+ return c.Os() == android.Android && !c.UseVndk() && !c.InRamdisk() && !c.InRecovery() && !c.InVendorRamdisk()
}
func (c *Module) UseSdk() bool {
if c.canUseSdk() {
- return String(c.Properties.Sdk_version) != "" || c.SplitPerApiLevel()
+ return String(c.Properties.Sdk_version) != ""
}
return false
}
@@ -1043,24 +1005,29 @@
}
func (c *Module) IsStubs() bool {
- if library, ok := c.linker.(*libraryDecorator); ok {
- return library.buildStubs()
- } else if _, ok := c.linker.(*llndkStubDecorator); ok {
- return true
+ if lib := c.library; lib != nil {
+ return lib.buildStubs()
}
return false
}
func (c *Module) HasStubsVariants() bool {
- if library, ok := c.linker.(*libraryDecorator); ok {
- return len(library.Properties.Stubs.Versions) > 0
- }
- if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
- return len(library.Properties.Stubs.Versions) > 0
+ if lib := c.library; lib != nil {
+ return lib.hasStubsVariants()
}
return false
}
+// If this is a stubs library, ImplementationModuleName returns the name of the module that contains
+// the implementation. If it is an implementation library it returns its own name.
+func (c *Module) ImplementationModuleName(ctx android.BaseModuleContext) string {
+ name := ctx.OtherModuleName(c)
+ if versioned, ok := c.linker.(versionedInterface); ok {
+ name = versioned.implementationModuleName(name)
+ }
+ return name
+}
+
func (c *Module) bootstrap() bool {
return Bool(c.Properties.Bootstrap)
}
@@ -1080,41 +1047,6 @@
return false
}
-func (c *Module) ExportedIncludeDirs() android.Paths {
- if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok {
- return flagsProducer.exportedDirs()
- }
- return nil
-}
-
-func (c *Module) ExportedSystemIncludeDirs() android.Paths {
- if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok {
- return flagsProducer.exportedSystemDirs()
- }
- return nil
-}
-
-func (c *Module) ExportedFlags() []string {
- if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok {
- return flagsProducer.exportedFlags()
- }
- return nil
-}
-
-func (c *Module) ExportedDeps() android.Paths {
- if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok {
- return flagsProducer.exportedDeps()
- }
- return nil
-}
-
-func (c *Module) ExportedGeneratedHeaders() android.Paths {
- if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok {
- return flagsProducer.exportedGeneratedHeaders()
- }
- return nil
-}
-
func (c *Module) ExcludeFromVendorSnapshot() bool {
return Bool(c.Properties.Exclude_from_vendor_snapshot)
}
@@ -1272,10 +1204,15 @@
// Host modules do not need ABI dumps.
return false
}
- if ctx.isStubs() || ctx.isNDKStubLibrary() {
+ if ctx.isNDKStubLibrary() {
// Stubs do not need ABI dumps.
return false
}
+ if lib := ctx.mod.library; lib != nil && lib.buildStubs() {
+ // Stubs do not need ABI dumps.
+ return false
+ }
+
return true
}
@@ -1299,25 +1236,17 @@
}
func (ctx *moduleContextImpl) isForPlatform() bool {
- return ctx.mod.IsForPlatform()
+ return ctx.ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
}
func (ctx *moduleContextImpl) apexVariationName() string {
- return ctx.mod.ApexVariationName()
+ return ctx.ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).ApexVariationName
}
-func (ctx *moduleContextImpl) apexSdkVersion() int {
+func (ctx *moduleContextImpl) apexSdkVersion() android.ApiLevel {
return ctx.mod.apexSdkVersion
}
-func (ctx *moduleContextImpl) hasStubsVariants() bool {
- return ctx.mod.HasStubsVariants()
-}
-
-func (ctx *moduleContextImpl) isStubs() bool {
- return ctx.mod.IsStubs()
-}
-
func (ctx *moduleContextImpl) bootstrap() bool {
return ctx.mod.bootstrap()
}
@@ -1326,6 +1255,10 @@
return ctx.mod.nativeCoverage()
}
+func (ctx *moduleContextImpl) directlyInAnyApex() bool {
+ return ctx.mod.DirectlyInAnyApex()
+}
+
func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
return &Module{
hod: hod,
@@ -1374,65 +1307,6 @@
return nil
}
-// orderDeps reorders dependencies into a list such that if module A depends on B, then
-// A will precede B in the resultant list.
-// This is convenient for passing into a linker.
-// Note that directSharedDeps should be the analogous static library for each shared lib dep
-func orderDeps(directStaticDeps []android.Path, directSharedDeps []android.Path, allTransitiveDeps map[android.Path][]android.Path) (orderedAllDeps []android.Path, orderedDeclaredDeps []android.Path) {
- // If A depends on B, then
- // Every list containing A will also contain B later in the list
- // So, after concatenating all lists, the final instance of B will have come from the same
- // original list as the final instance of A
- // So, the final instance of B will be later in the concatenation than the final A
- // So, keeping only the final instance of A and of B ensures that A is earlier in the output
- // list than B
- for _, dep := range directStaticDeps {
- orderedAllDeps = append(orderedAllDeps, dep)
- orderedAllDeps = append(orderedAllDeps, allTransitiveDeps[dep]...)
- }
- for _, dep := range directSharedDeps {
- orderedAllDeps = append(orderedAllDeps, dep)
- orderedAllDeps = append(orderedAllDeps, allTransitiveDeps[dep]...)
- }
-
- orderedAllDeps = android.LastUniquePaths(orderedAllDeps)
-
- // We don't want to add any new dependencies into directStaticDeps (to allow the caller to
- // intentionally exclude or replace any unwanted transitive dependencies), so we limit the
- // resultant list to only what the caller has chosen to include in directStaticDeps
- _, orderedDeclaredDeps = android.FilterPathList(orderedAllDeps, directStaticDeps)
-
- return orderedAllDeps, orderedDeclaredDeps
-}
-
-func orderStaticModuleDeps(module LinkableInterface, staticDeps []LinkableInterface, sharedDeps []LinkableInterface) (results []android.Path) {
- // convert Module to Path
- var depsInLinkOrder []android.Path
- allTransitiveDeps := make(map[android.Path][]android.Path, len(staticDeps))
- staticDepFiles := []android.Path{}
- for _, dep := range staticDeps {
- // The OutputFile may not be valid for a variant not present, and the AllowMissingDependencies flag is set.
- if dep.OutputFile().Valid() {
- allTransitiveDeps[dep.OutputFile().Path()] = dep.GetDepsInLinkOrder()
- staticDepFiles = append(staticDepFiles, dep.OutputFile().Path())
- }
- }
- sharedDepFiles := []android.Path{}
- for _, sharedDep := range sharedDeps {
- if sharedDep.HasStaticVariant() {
- staticAnalogue := sharedDep.GetStaticVariant()
- allTransitiveDeps[staticAnalogue.OutputFile().Path()] = staticAnalogue.GetDepsInLinkOrder()
- sharedDepFiles = append(sharedDepFiles, staticAnalogue.OutputFile().Path())
- }
- }
-
- // reorder the dependencies based on transitive dependencies
- depsInLinkOrder, results = orderDeps(staticDepFiles, sharedDepFiles, allTransitiveDeps)
- module.SetDepsInLinkOrder(depsInLinkOrder)
-
- return results
-}
-
func (c *Module) IsTestPerSrcAllTestsVariation() bool {
test, ok := c.linker.(testPerSrc)
return ok && test.isAllTestsVariation()
@@ -1481,6 +1355,11 @@
return
}
+ apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ if !apexInfo.IsForPlatform() {
+ c.hideApexVariantFromMake = true
+ }
+
c.makeLinkType = c.getMakeLinkType(actx)
c.Properties.SubName = ""
@@ -1491,7 +1370,7 @@
_, llndk := c.linker.(*llndkStubDecorator)
_, llndkHeader := c.linker.(*llndkHeadersDecorator)
- if llndk || llndkHeader || (c.UseVndk() && c.HasVendorVariant()) {
+ if llndk || llndkHeader || (c.UseVndk() && c.HasNonSystemVariants()) {
// .vendor.{version} suffix is added for vendor variant or .product.{version} suffix is
// added for product variant only when we have vendor and product variants with core
// variant. The suffix is not added for vendor-only or product-only module.
@@ -1502,6 +1381,8 @@
c.Properties.SubName += vendorSuffix
} else if c.InRamdisk() && !c.OnlyInRamdisk() {
c.Properties.SubName += ramdiskSuffix
+ } else if c.InVendorRamdisk() && !c.OnlyInVendorRamdisk() {
+ c.Properties.SubName += vendorRamdiskSuffix
} else if c.InRecovery() && !c.OnlyInRecovery() {
c.Properties.SubName += recoverySuffix
} else if c.IsSdkVariant() && (c.Properties.SdkAndPlatformVariantVisibleToMake || c.SplitPerApiLevel()) {
@@ -1612,23 +1493,22 @@
// force anything in the make world to link against the stubs library.
// (unless it is explicitly referenced via .bootstrap suffix or the
// module is marked with 'bootstrap: true').
- if c.HasStubsVariants() &&
- android.DirectlyInAnyApex(ctx, ctx.baseModuleName()) && !c.InRamdisk() &&
+ if c.HasStubsVariants() && c.AnyVariantDirectlyInAnyApex() && !c.InRamdisk() &&
!c.InRecovery() && !c.UseVndk() && !c.static() && !c.isCoverageVariant() &&
- c.IsStubs() {
+ c.IsStubs() && !c.InVendorRamdisk() {
c.Properties.HideFromMake = false // unhide
// Note: this is still non-installable
}
// glob exported headers for snapshot, if BOARD_VNDK_VERSION is current.
if i, ok := c.linker.(snapshotLibraryInterface); ok && ctx.DeviceConfig().VndkVersion() == "current" {
- if isSnapshotAware(ctx, c) {
+ if isSnapshotAware(ctx, c, apexInfo) {
i.collectHeadersForSnapshot(ctx)
}
}
}
- if c.installable() {
+ if c.installable(apexInfo) {
c.installer.install(ctx, c.outputFile.Path())
if ctx.Failed() {
return
@@ -1682,11 +1562,13 @@
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)
}
}
@@ -1792,7 +1674,7 @@
if m.UseSdk() {
return []blueprint.Variation{
{Mutator: "sdk", Variation: "sdk"},
- {Mutator: "ndk_api", Variation: m.SdkVersion()},
+ {Mutator: "version", Variation: m.SdkVersion()},
}
}
return []blueprint.Variation{
@@ -1800,6 +1682,24 @@
}
}
+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 != "" && CanBeOrLinkAgainstVersionVariants(c) {
+ // Version is explicitly specified. i.e. libFoo#30
+ variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version})
+ depTag.explicitlyVersioned = true
+ }
+
+ if far {
+ ctx.AddFarVariationDependencies(variations, depTag, name)
+ } else {
+ ctx.AddVariationDependencies(variations, depTag, name)
+ }
+}
+
func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
if !c.Enabled() {
return
@@ -1815,6 +1715,8 @@
deps := c.deps(ctx)
+ c.Properties.AndroidMkSystemSharedLibs = deps.SystemSharedLibs
+
variantNdkLibs := []string{}
variantLateNdkLibs := []string{}
if ctx.Os() == android.Android {
@@ -1892,11 +1794,9 @@
}
buildStubs := false
- if c.linker != nil {
- if library, ok := c.linker.(*libraryDecorator); ok {
- if library.buildStubs() {
- buildStubs = true
- }
+ if versioned, ok := c.linker.(versionedInterface); ok {
+ if versioned.buildStubs() {
+ buildStubs = true
}
}
@@ -1986,30 +1886,6 @@
}, 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 +1902,10 @@
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 +1916,10 @@
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{
@@ -2058,11 +1940,10 @@
actx.AddDependency(c, depTag, gen)
}
- actx.AddVariationDependencies(nil, objDepTag, deps.ObjFiles...)
-
vendorSnapshotObjects := vendorSnapshotObjects(actx.Config())
crtVariations := GetCrtVariations(ctx, c)
+ actx.AddVariationDependencies(crtVariations, objDepTag, deps.ObjFiles...)
if deps.CrtBegin != "" {
actx.AddVariationDependencies(crtVariations, CrtBeginDepTag,
rewriteSnapshotLibs(deps.CrtBegin, vendorSnapshotObjects))
@@ -2082,13 +1963,13 @@
ndkStubDepTag := libraryDependencyTag{Kind: sharedLibraryDependency, ndk: true, makeSuffix: "." + version}
actx.AddVariationDependencies([]blueprint.Variation{
- {Mutator: "ndk_api", Variation: version},
+ {Mutator: "version", Variation: version},
{Mutator: "link", Variation: "shared"},
}, ndkStubDepTag, variantNdkLibs...)
ndkLateStubDepTag := libraryDependencyTag{Kind: sharedLibraryDependency, Order: lateLibraryDependency, ndk: true, makeSuffix: "." + version}
actx.AddVariationDependencies([]blueprint.Variation{
- {Mutator: "ndk_api", Variation: version},
+ {Mutator: "version", Variation: version},
{Mutator: "link", Variation: "shared"},
}, ndkLateStubDepTag, variantLateNdkLibs...)
@@ -2110,7 +1991,7 @@
// Whether a module can link to another module, taking into
// account NDK linking.
-func checkLinkType(ctx android.ModuleContext, from LinkableInterface, to LinkableInterface,
+func checkLinkType(ctx android.BaseModuleContext, from LinkableInterface, to LinkableInterface,
tag blueprint.DependencyTag) {
switch t := tag.(type) {
@@ -2130,9 +2011,9 @@
// VNDK is cc.Module supported only for now.
if ccFrom, ok := from.(*Module); ok && from.UseVndk() {
- // Though vendor code is limited by the vendor mutator,
- // each vendor-available module needs to check
- // link-type for VNDK.
+ // Though allowed dependency is limited by the image mutator,
+ // each vendor and product module needs to check link-type
+ // for VNDK.
if ccTo, ok := to.(*Module); ok {
if ccFrom.vndkdep != nil {
ccFrom.vndkdep.vndkCheckLinkType(ctx, ccTo, tag)
@@ -2150,22 +2031,28 @@
// Ramdisk code is not NDK
return
}
+ if from.InVendorRamdisk() {
+ // Vendor ramdisk code is not NDK
+ return
+ }
if from.InRecovery() {
// Recovery code is not NDK
return
}
- if to.ToolchainLibrary() {
- // These are always allowed
- return
- }
- if to.NdkPrebuiltStl() {
- // These are allowed, but they don't set sdk_version
- return
- }
- if to.StubDecorator() {
- // These aren't real libraries, but are the stub shared libraries that are included in
- // the NDK.
- return
+ if c, ok := to.(*Module); ok {
+ if c.ToolchainLibrary() {
+ // These are always allowed
+ return
+ }
+ if c.NdkPrebuiltStl() {
+ // These are allowed, but they don't set sdk_version
+ return
+ }
+ if c.StubDecorator() {
+ // These aren't real libraries, but are the stub shared libraries that are included in
+ // the NDK.
+ return
+ }
}
if strings.HasPrefix(ctx.ModuleName(), "libclang_rt.") && to.Module().Name() == "libc++" {
@@ -2230,6 +2117,18 @@
}
}
+func checkLinkTypeMutator(ctx android.BottomUpMutatorContext) {
+ if c, ok := ctx.Module().(*Module); ok {
+ ctx.VisitDirectDeps(func(dep android.Module) {
+ depTag := ctx.OtherModuleDependencyTag(dep)
+ ccDep, ok := dep.(LinkableInterface)
+ if ok {
+ checkLinkType(ctx, c, ccDep, depTag)
+ }
+ })
+ }
+}
+
// Tests whether the dependent library is okay to be double loaded inside a single process.
// If a library has a vendor variant and is a (transitive) dependency of an LLNDK library,
// it is subject to be double loaded. Such lib should be explicitly marked as double_loadable: true
@@ -2238,16 +2137,17 @@
check := func(child, parent android.Module) bool {
to, ok := child.(*Module)
if !ok {
- // follow thru cc.Defaults, etc.
- return true
+ return false
}
if lib, ok := to.linker.(*libraryDecorator); !ok || !lib.shared() {
return false
}
- // if target lib has no vendor variant, keep checking dependency graph
- if !to.HasVendorVariant() {
+ // Even if target lib has no vendor variant, keep checking dependency
+ // graph in case it depends on vendor_available or product_available
+ // but not double_loadable transtively.
+ if !to.HasNonSystemVariants() {
return true
}
@@ -2273,25 +2173,56 @@
}
}
+// Returns the highest version which is <= maxSdkVersion.
+// For example, with maxSdkVersion is 10 and versionList is [9,11]
+// it returns 9 as string. The list of stubs must be in order from
+// oldest to newest.
+func (c *Module) chooseSdkVersion(ctx android.PathContext, stubsInfo []SharedLibraryStubsInfo,
+ maxSdkVersion android.ApiLevel) (SharedLibraryStubsInfo, error) {
+
+ for i := range stubsInfo {
+ stubInfo := stubsInfo[len(stubsInfo)-i-1]
+ var ver android.ApiLevel
+ if stubInfo.Version == "" {
+ ver = android.FutureApiLevel
+ } else {
+ var err error
+ ver, err = android.ApiLevelFromUser(ctx, stubInfo.Version)
+ if err != nil {
+ return SharedLibraryStubsInfo{}, err
+ }
+ }
+ if ver.LessThanOrEqualTo(maxSdkVersion) {
+ return stubInfo, nil
+ }
+ }
+ var versionList []string
+ for _, stubInfo := range stubsInfo {
+ versionList = append(versionList, stubInfo.Version)
+ }
+ return SharedLibraryStubsInfo{}, fmt.Errorf("not found a version(<=%s) in versionList: %v", maxSdkVersion.String(), versionList)
+}
+
// Convert dependencies to paths. Returns a PathDeps containing paths
func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
var depPaths PathDeps
- directStaticDeps := []LinkableInterface{}
- directSharedDeps := []LinkableInterface{}
+ var directStaticDeps []StaticLibraryInfo
+ var directSharedDeps []SharedLibraryInfo
- reexportExporter := func(exporter exportedFlagsProducer) {
- depPaths.ReexportedDirs = append(depPaths.ReexportedDirs, exporter.exportedDirs()...)
- depPaths.ReexportedSystemDirs = append(depPaths.ReexportedSystemDirs, exporter.exportedSystemDirs()...)
- depPaths.ReexportedFlags = append(depPaths.ReexportedFlags, exporter.exportedFlags()...)
- depPaths.ReexportedDeps = append(depPaths.ReexportedDeps, exporter.exportedDeps()...)
- depPaths.ReexportedGeneratedHeaders = append(depPaths.ReexportedGeneratedHeaders, exporter.exportedGeneratedHeaders()...)
+ reexportExporter := func(exporter FlagExporterInfo) {
+ depPaths.ReexportedDirs = append(depPaths.ReexportedDirs, exporter.IncludeDirs...)
+ depPaths.ReexportedSystemDirs = append(depPaths.ReexportedSystemDirs, exporter.SystemIncludeDirs...)
+ depPaths.ReexportedFlags = append(depPaths.ReexportedFlags, exporter.Flags...)
+ depPaths.ReexportedDeps = append(depPaths.ReexportedDeps, exporter.Deps...)
+ depPaths.ReexportedGeneratedHeaders = append(depPaths.ReexportedGeneratedHeaders, exporter.GeneratedHeaders...)
}
// For the dependency from platform to apex, use the latest stubs
c.apexSdkVersion = android.FutureApiLevel
- if !c.IsForPlatform() {
- c.apexSdkVersion = c.ApexProperties.Info.MinSdkVersion
+ apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ if !apexInfo.IsForPlatform() {
+ c.apexSdkVersion = apexInfo.MinSdkVersion(ctx)
}
if android.InList("hwaddress", ctx.Config().SanitizeDevice()) {
@@ -2369,132 +2300,30 @@
return
}
- // re-exporting flags
if depTag == reuseObjTag {
- // reusing objects only make sense for cc.Modules.
- if ccReuseDep, ok := ccDep.(*Module); ok && ccDep.CcLibraryInterface() {
- c.staticVariant = ccDep
- objs, exporter := ccReuseDep.compiler.(libraryInterface).reuseObjs()
+ // Skip reused objects for stub libraries, they use their own stub object file instead.
+ // The reuseObjTag dependency still exists because the LinkageMutator runs before the
+ // version mutator, so the stubs variant is created from the shared variant that
+ // already has the reuseObjTag dependency on the static variant.
+ if !c.library.buildStubs() {
+ staticAnalogue := ctx.OtherModuleProvider(dep, StaticLibraryInfoProvider).(StaticLibraryInfo)
+ objs := staticAnalogue.ReuseObjects
depPaths.Objs = depPaths.Objs.Append(objs)
- reexportExporter(exporter)
- return
+ depExporterInfo := ctx.OtherModuleProvider(dep, FlagExporterInfoProvider).(FlagExporterInfo)
+ reexportExporter(depExporterInfo)
}
+ return
}
- if depTag == staticVariantTag {
- // staticVariants are a cc.Module specific concept.
- if _, ok := ccDep.(*Module); ok && ccDep.CcLibraryInterface() {
- c.staticVariant = ccDep
- return
- }
- }
-
- checkLinkType(ctx, c, ccDep, depTag)
-
linkFile := ccDep.OutputFile()
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
}
- if ccDep.CcLibrary() && !libDepTag.static() {
- depIsStubs := ccDep.BuildStubs()
- depHasStubs := VersionVariantAvailable(c) && ccDep.HasStubsVariants()
- depInSameApexes := android.DirectlyInAllApexes(c.InApexes(), depName)
- depInPlatform := !android.DirectlyInAnyApex(ctx, depName)
-
- var useThisDep bool
- if depIsStubs && libDepTag.explicitlyVersioned {
- // Always respect dependency to the versioned stubs (i.e. libX#10)
- useThisDep = true
- } else if !depHasStubs {
- // Use non-stub variant if that is the only choice
- // (i.e. depending on a lib without stubs.version property)
- useThisDep = true
- } else if c.IsForPlatform() {
- // If not building for APEX, use stubs only when it is from
- // an APEX (and not from platform)
- useThisDep = (depInPlatform != depIsStubs)
- if c.bootstrap() {
- // However, for host, ramdisk, recovery or bootstrap modules,
- // always link to non-stub variant
- useThisDep = !depIsStubs
- }
- for _, testFor := range c.TestFor() {
- // Another exception: if this module is bundled with an APEX, then
- // it is linked with the non-stub variant of a module in the APEX
- // as if this is part of the APEX.
- if android.DirectlyInApex(testFor, depName) {
- useThisDep = !depIsStubs
- break
- }
- }
- } else {
- // If building for APEX, use stubs when the parent is in any APEX that
- // the child is not in.
- useThisDep = (depInSameApexes != depIsStubs)
- }
-
- // 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)
- if err != nil {
- ctx.OtherModuleErrorf(dep, err.Error())
- return
- }
- if versionToUse != ccDep.StubsVersion() {
- useThisDep = false
- }
- }
-
- if !useThisDep {
- return // stop processing this dep
- }
- }
- if c.UseVndk() {
- if m, ok := ccDep.(*Module); ok && m.IsStubs() { // LLNDK
- // by default, use current version of LLNDK
- versionToUse := ""
- versions := stubsVersionsFor(ctx.Config())[depName]
- 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)
- if err != nil {
- ctx.OtherModuleErrorf(dep, err.Error())
- return
- }
- }
- if versionToUse != ccDep.StubsVersion() {
- return
- }
- }
- }
-
- depPaths.IncludeDirs = append(depPaths.IncludeDirs, ccDep.IncludeDirs()...)
-
- // Exporting flags only makes sense for cc.Modules
- if _, ok := ccDep.(*Module); ok {
- if i, ok := ccDep.(*Module).linker.(exportedFlagsProducer); ok {
- depPaths.SystemIncludeDirs = append(depPaths.SystemIncludeDirs, i.exportedSystemDirs()...)
- depPaths.GeneratedDeps = append(depPaths.GeneratedDeps, i.exportedDeps()...)
- depPaths.Flags = append(depPaths.Flags, i.exportedFlags()...)
-
- if libDepTag.reexportFlags {
- reexportExporter(i)
- // Add these re-exported flags to help header-abi-dumper to infer the abi exported by a library.
- // Re-exported shared library headers must be included as well since they can help us with type information
- // about template instantiations (instantiated from their headers).
- // -isystem headers are not included since for bionic libraries, abi-filtering is taken care of by version
- // scripts.
- c.sabi.Properties.ReexportedIncludes = append(
- c.sabi.Properties.ReexportedIncludes, i.exportedDirs().Strings()...)
- }
- }
- }
+ depExporterInfo := ctx.OtherModuleProvider(dep, FlagExporterInfoProvider).(FlagExporterInfo)
var ptr *android.Paths
var depPtr *android.Paths
@@ -2505,6 +2334,65 @@
case libDepTag.header():
// nothing
case libDepTag.shared():
+ if !ctx.OtherModuleHasProvider(dep, SharedLibraryInfoProvider) {
+ if !ctx.Config().AllowMissingDependencies() {
+ ctx.ModuleErrorf("module %q is not a shared library", depName)
+ } else {
+ ctx.AddMissingDependencies([]string{depName})
+ }
+ return
+ }
+ sharedLibraryInfo := ctx.OtherModuleProvider(dep, SharedLibraryInfoProvider).(SharedLibraryInfo)
+ sharedLibraryStubsInfo := ctx.OtherModuleProvider(dep, SharedLibraryImplementationStubsInfoProvider).(SharedLibraryImplementationStubsInfo)
+
+ if !libDepTag.explicitlyVersioned && len(sharedLibraryStubsInfo.SharedLibraryStubsInfos) > 0 {
+ useStubs := false
+
+ if lib := moduleLibraryInterface(dep); lib.buildStubs() && c.UseVndk() { // LLNDK
+ if !apexInfo.IsForPlatform() {
+ // For platform libraries, use current version of LLNDK
+ // If this is for use_vendor apex we will apply the same rules
+ // of apex sdk enforcement below to choose right version.
+ useStubs = true
+ }
+ } else if apexInfo.IsForPlatform() {
+ // If not building for APEX, use stubs only when it is from
+ // an APEX (and not from platform)
+ // However, for host, ramdisk, vendor_ramdisk, recovery or bootstrap modules,
+ // always link to non-stub variant
+ useStubs = dep.(android.ApexModule).AnyVariantDirectlyInAnyApex() && !c.bootstrap()
+ // Another exception: if this module is bundled with an APEX, then
+ // it is linked with the non-stub variant of a module in the APEX
+ // as if this is part of the APEX.
+ testFor := ctx.Provider(android.ApexTestForInfoProvider).(android.ApexTestForInfo)
+ for _, apexContents := range testFor.ApexContents {
+ if apexContents.DirectlyInApex(depName) {
+ useStubs = false
+ break
+ }
+ }
+ } else {
+ // If building for APEX, use stubs when the parent is in any APEX that
+ // the child is not in.
+ useStubs = !android.DirectlyInAllApexes(apexInfo, depName)
+ }
+
+ // when to use (unspecified) stubs, check min_sdk_version and choose the right one
+ if useStubs {
+ sharedLibraryStubsInfo, err :=
+ c.chooseSdkVersion(ctx, sharedLibraryStubsInfo.SharedLibraryStubsInfos, c.apexSdkVersion)
+ if err != nil {
+ ctx.OtherModuleErrorf(dep, err.Error())
+ return
+ }
+ sharedLibraryInfo = sharedLibraryStubsInfo.SharedLibraryInfo
+ depExporterInfo = sharedLibraryStubsInfo.FlagExporterInfo
+ }
+ }
+
+ linkFile = android.OptionalPathForPath(sharedLibraryInfo.SharedLibrary)
+ depFile = sharedLibraryInfo.TableOfContents
+
ptr = &depPaths.SharedLibs
switch libDepTag.Order {
case earlyLibraryDependency:
@@ -2513,44 +2401,41 @@
case normalLibraryDependency:
ptr = &depPaths.SharedLibs
depPtr = &depPaths.SharedLibsDeps
- directSharedDeps = append(directSharedDeps, ccDep)
+ directSharedDeps = append(directSharedDeps, sharedLibraryInfo)
case lateLibraryDependency:
ptr = &depPaths.LateSharedLibs
depPtr = &depPaths.LateSharedLibsDeps
default:
panic(fmt.Errorf("unexpected library dependency order %d", libDepTag.Order))
}
- depFile = ccDep.Toc()
case libDepTag.static():
+ if !ctx.OtherModuleHasProvider(dep, StaticLibraryInfoProvider) {
+ if !ctx.Config().AllowMissingDependencies() {
+ ctx.ModuleErrorf("module %q is not a static library", depName)
+ } else {
+ ctx.AddMissingDependencies([]string{depName})
+ }
+ return
+ }
+ staticLibraryInfo := ctx.OtherModuleProvider(dep, StaticLibraryInfoProvider).(StaticLibraryInfo)
+ linkFile = android.OptionalPathForPath(staticLibraryInfo.StaticLibrary)
if libDepTag.wholeStatic {
ptr = &depPaths.WholeStaticLibs
- if !ccDep.CcLibraryInterface() || !ccDep.Static() {
- ctx.ModuleErrorf("module %q not a static library", depName)
- return
- }
-
- // Because the static library objects are included, this only makes sense
- // 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())
- } else {
- depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(staticLib.objs())
- }
+ if len(staticLibraryInfo.Objects.objFiles) > 0 {
+ depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(staticLibraryInfo.Objects)
} else {
- ctx.ModuleErrorf(
- "non-cc.Modules cannot be included as whole static libraries.", depName)
- return
+ // 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 {
switch libDepTag.Order {
case earlyLibraryDependency:
@@ -2559,7 +2444,7 @@
// static dependencies will be handled separately so they can be ordered
// using transitive dependencies.
ptr = nil
- directStaticDeps = append(directStaticDeps, ccDep)
+ directStaticDeps = append(directStaticDeps, staticLibraryInfo)
case lateLibraryDependency:
ptr = &depPaths.LateStaticLibs
default:
@@ -2583,10 +2468,10 @@
staticLib.objs().coverageFiles...)
depPaths.StaticLibObjs.sAbiDumpFiles = append(depPaths.StaticLibObjs.sAbiDumpFiles,
staticLib.objs().sAbiDumpFiles...)
- } else if c, ok := ccDep.(LinkableInterface); ok {
+ } else {
// Handle non-CC modules here
depPaths.StaticLibObjs.coverageFiles = append(depPaths.StaticLibObjs.coverageFiles,
- c.CoverageFiles()...)
+ ccDep.CoverageFiles()...)
}
}
@@ -2610,17 +2495,34 @@
*depPtr = append(*depPtr, dep.Path())
}
+ depPaths.IncludeDirs = append(depPaths.IncludeDirs, depExporterInfo.IncludeDirs...)
+ depPaths.SystemIncludeDirs = append(depPaths.SystemIncludeDirs, depExporterInfo.SystemIncludeDirs...)
+ depPaths.GeneratedDeps = append(depPaths.GeneratedDeps, depExporterInfo.Deps...)
+ depPaths.Flags = append(depPaths.Flags, depExporterInfo.Flags...)
+
+ if libDepTag.reexportFlags {
+ reexportExporter(depExporterInfo)
+ // Add these re-exported flags to help header-abi-dumper to infer the abi exported by a library.
+ // Re-exported shared library headers must be included as well since they can help us with type information
+ // about template instantiations (instantiated from their headers).
+ // -isystem headers are not included since for bionic libraries, abi-filtering is taken care of by version
+ // scripts.
+ c.sabi.Properties.ReexportedIncludes = append(
+ c.sabi.Properties.ReexportedIncludes, depExporterInfo.IncludeDirs.Strings()...)
+ }
+
makeLibName := c.makeLibName(ctx, ccDep, depName) + libDepTag.makeSuffix
switch {
case libDepTag.header():
c.Properties.AndroidMkHeaderLibs = append(
c.Properties.AndroidMkHeaderLibs, makeLibName)
case libDepTag.shared():
- if ccDep.CcLibrary() {
- if ccDep.BuildStubs() && android.InAnyApex(depName) {
+ if lib := moduleLibraryInterface(dep); lib != nil {
+ if lib.buildStubs() && dep.(android.ApexModule).InAnyApex() {
// Add the dependency to the APEX(es) providing the library so that
// m <module> can trigger building the APEXes as well.
- for _, an := range android.GetApexesForModule(depName) {
+ depApexInfo := ctx.OtherModuleProvider(dep, android.ApexInfoProvider).(android.ApexInfo)
+ for _, an := range depApexInfo.InApexes {
c.Properties.ApexesProvidingSharedLibs = append(
c.Properties.ApexesProvidingSharedLibs, an)
}
@@ -2662,7 +2564,9 @@
})
// use the ordered dependencies as this module's dependencies
- depPaths.StaticLibs = append(depPaths.StaticLibs, orderStaticModuleDeps(c, directStaticDeps, directSharedDeps)...)
+ orderedStaticPaths, transitiveStaticLibs := orderStaticModuleDeps(directStaticDeps, directSharedDeps)
+ depPaths.TranstiveStaticLibrariesForOrdering = transitiveStaticLibs
+ depPaths.StaticLibs = append(depPaths.StaticLibs, orderedStaticPaths...)
// Dedup exported flags from dependencies
depPaths.Flags = android.FirstUniqueStrings(depPaths.Flags)
@@ -2682,6 +2586,38 @@
return depPaths
}
+// orderStaticModuleDeps rearranges the order of the static library dependencies of the module
+// to match the topological order of the dependency tree, including any static analogues of
+// direct shared libraries. It returns the ordered static dependencies, and an android.DepSet
+// of the transitive dependencies.
+func orderStaticModuleDeps(staticDeps []StaticLibraryInfo, sharedDeps []SharedLibraryInfo) (ordered android.Paths, transitive *android.DepSet) {
+ transitiveStaticLibsBuilder := android.NewDepSetBuilder(android.TOPOLOGICAL)
+ var staticPaths android.Paths
+ for _, staticDep := range staticDeps {
+ staticPaths = append(staticPaths, staticDep.StaticLibrary)
+ transitiveStaticLibsBuilder.Transitive(staticDep.TransitiveStaticLibrariesForOrdering)
+ }
+ for _, sharedDep := range sharedDeps {
+ if sharedDep.StaticAnalogue != nil {
+ transitiveStaticLibsBuilder.Transitive(sharedDep.StaticAnalogue.TransitiveStaticLibrariesForOrdering)
+ }
+ }
+ transitiveStaticLibs := transitiveStaticLibsBuilder.Build()
+
+ orderedTransitiveStaticLibs := transitiveStaticLibs.ToList()
+
+ // reorder the dependencies based on transitive dependencies
+ staticPaths = android.FirstUniquePaths(staticPaths)
+ _, orderedStaticPaths := android.FilterPathList(orderedTransitiveStaticLibs, staticPaths)
+
+ if len(orderedStaticPaths) != len(staticPaths) {
+ missing, _ := android.FilterPathList(staticPaths, orderedStaticPaths)
+ panic(fmt.Errorf("expected %d ordered static paths , got %d, missing %q %q %q", len(staticPaths), len(orderedStaticPaths), missing, orderedStaticPaths, staticPaths))
+ }
+
+ return orderedStaticPaths, transitiveStaticLibs
+}
+
// baseLibName trims known prefixes and suffixes
func baseLibName(depName string) string {
libName := strings.TrimSuffix(depName, llndkLibrarySuffix)
@@ -2716,7 +2652,8 @@
}
}
- if ctx.DeviceConfig().VndkUseCoreVariant() && ccDep.IsVndk() && !ccDep.MustUseVendorVariant() && !c.InRamdisk() && !c.InRecovery() {
+ if ctx.DeviceConfig().VndkUseCoreVariant() && ccDep.IsVndk() && !ccDep.MustUseVendorVariant() &&
+ !c.InRamdisk() && !c.InVendorRamdisk() && !c.InRecovery() {
// The vendor module is a no-vendor-variant VNDK library. Depend on the
// core module instead.
return libName
@@ -2728,6 +2665,8 @@
return libName + vendorPublicLibrarySuffix
} else if ccDep.InRamdisk() && !ccDep.OnlyInRamdisk() {
return libName + ramdiskSuffix
+ } else if ccDep.InVendorRamdisk() && !ccDep.OnlyInVendorRamdisk() {
+ return libName + vendorRamdiskSuffix
} else if ccDep.InRecovery() && !ccDep.OnlyInRecovery() {
return libName + recoverySuffix
} else if ccDep.Module().Target().NativeBridge == android.NativeBridgeEnabled {
@@ -2758,6 +2697,10 @@
return c.InRamdisk()
}
+func (c *Module) InstallInVendorRamdisk() bool {
+ return c.InVendorRamdisk()
+}
+
func (c *Module) InstallInRecovery() bool {
return c.InRecovery()
}
@@ -2847,6 +2790,7 @@
return "native:vndk_private"
}
if c.IsVndk() && !c.isVndkExt() {
+ // Product_available, if defined, must have the same value with Vendor_available.
if Bool(c.VendorProperties.Vendor_available) {
return "native:vndk"
}
@@ -2858,6 +2802,8 @@
return "native:vendor"
} else if c.InRamdisk() {
return "native:ramdisk"
+ } else if c.InVendorRamdisk() {
+ return "native:vendor_ramdisk"
} else if c.InRecovery() {
return "native:recovery"
} else if c.Target().Os == android.Android && String(c.Properties.Sdk_version) != "" {
@@ -2875,12 +2821,10 @@
// Overrides ApexModule.IsInstallabeToApex()
// Only shared/runtime libraries and "test_per_src" tests are installable to APEX.
func (c *Module) IsInstallableToApex() bool {
- if shared, ok := c.linker.(interface {
- shared() bool
- }); ok {
+ if lib := c.library; lib != nil {
// Stub libs and prebuilt libs in a versioned SDK are not
// installable to APEX even though they are shared libs.
- return shared.shared() && !c.IsStubs() && c.ContainingSdk().Unversioned()
+ return lib.shared() && !lib.buildStubs() && c.ContainingSdk().Unversioned()
} else if _, ok := c.linker.(testPerSrc); ok {
return true
}
@@ -2924,7 +2868,7 @@
c.installer.everInstallable()
}
-func (c *Module) installable() bool {
+func (c *Module) installable(apexInfo android.ApexInfo) bool {
ret := c.EverInstallable() &&
// Check to see whether the module has been configured to not be installed.
proptools.BoolDefault(c.Properties.Installable, true) &&
@@ -2933,7 +2877,7 @@
// The platform variant doesn't need further condition. Apex variants however might not
// be installable because it will likely to be included in the APEX and won't appear
// in the system partition.
- if c.IsForPlatform() {
+ if apexInfo.IsForPlatform() {
return ret
}
@@ -2979,28 +2923,15 @@
return false
}
}
- if depTag == llndkImplDep {
- // We don't track beyond LLNDK
+ if depTag == stubImplDepTag || depTag == llndkImplDep {
+ // We don't track beyond LLNDK or from an implementation library to its stubs.
return false
}
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 +2955,17 @@
// 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 +3019,8 @@
<OProperties{},
&PgoProperties{},
&android.ProtoProperties{},
+ // RustBindgenProperties is included here so that cc_defaults can be used for rust_bindgen modules.
+ &RustBindgenClangProperties{},
)
android.InitDefaultsModule(module)
@@ -3089,43 +3028,10 @@
return module
}
-func squashVendorSrcs(m *Module) {
- if lib, ok := m.compiler.(*libraryDecorator); ok {
- lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
- lib.baseCompiler.Properties.Target.Vendor.Srcs...)
-
- lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
- lib.baseCompiler.Properties.Target.Vendor.Exclude_srcs...)
-
- lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
- lib.baseCompiler.Properties.Target.Vendor.Exclude_generated_sources...)
- }
-}
-
-func squashRecoverySrcs(m *Module) {
- if lib, ok := m.compiler.(*libraryDecorator); ok {
- lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
- lib.baseCompiler.Properties.Target.Recovery.Srcs...)
-
- lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
- lib.baseCompiler.Properties.Target.Recovery.Exclude_srcs...)
-
- lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
- lib.baseCompiler.Properties.Target.Recovery.Exclude_generated_sources...)
- }
-}
-
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 a4c0677..f616cf3 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -20,7 +20,6 @@
"os"
"path/filepath"
"reflect"
- "sort"
"strings"
"testing"
@@ -54,8 +53,8 @@
func testCcWithConfig(t *testing.T, config android.Config) *android.TestContext {
t.Helper()
- ctx := CreateTestContext()
- ctx.Register(config)
+ ctx := CreateTestContext(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
android.FailIfErrored(t, errs)
@@ -85,8 +84,8 @@
func testCcErrorWithConfig(t *testing.T, pattern string, config android.Config) {
t.Helper()
- ctx := CreateTestContext()
- ctx.Register(config)
+ ctx := CreateTestContext(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
if len(errs) > 0 {
@@ -104,6 +103,7 @@
}
func testCcError(t *testing.T, pattern string, bp string) {
+ t.Helper()
config := TestConfig(buildDir, android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
@@ -112,6 +112,7 @@
}
func testCcErrorProductVndk(t *testing.T, pattern string, bp string) {
+ t.Helper()
config := TestConfig(buildDir, android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.ProductVndkVersion = StringPtr("current")
@@ -295,8 +296,8 @@
func checkWriteFileOutput(t *testing.T, params android.TestingBuildParams, expected []string) {
t.Helper()
- assertString(t, params.Rule.String(), android.WriteFile.String())
- actual := strings.FieldsFunc(strings.ReplaceAll(params.Args["content"], "\\n", "\n"), func(r rune) bool { return r == '\n' })
+ content := android.ContentFromFileRuleForTests(t, params)
+ actual := strings.FieldsFunc(content, func(r rune) bool { return r == '\n' })
assertArrayString(t, actual, expected)
}
@@ -325,6 +326,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -334,6 +336,7 @@
cc_library {
name: "libvndk_private",
vendor_available: false,
+ product_available: false,
vndk: {
enabled: true,
},
@@ -344,6 +347,7 @@
cc_library {
name: "libvndk_sp",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
@@ -355,6 +359,7 @@
cc_library {
name: "libvndk_sp_private",
vendor_available: false,
+ product_available: false,
vndk: {
enabled: true,
support_system_process: true,
@@ -385,14 +390,22 @@
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", "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)
+ // subdir == "" because VNDK libs are not supposed to be installed separately.
+ // They are installed as part of VNDK APEX instead.
+ checkVndkModule(t, ctx, "libvndk", "", false, "", vendorVariant)
+ checkVndkModule(t, ctx, "libvndk_private", "", false, "", vendorVariant)
+ checkVndkModule(t, ctx, "libvndk_sp", "", true, "", vendorVariant)
+ checkVndkModule(t, ctx, "libvndk_sp_private", "", true, "", vendorVariant)
+
+ checkVndkModule(t, ctx, "libvndk", "", false, "", productVariant)
+ checkVndkModule(t, ctx, "libvndk_private", "", false, "", productVariant)
+ checkVndkModule(t, ctx, "libvndk_sp", "", true, "", productVariant)
+ checkVndkModule(t, ctx, "libvndk_sp_private", "", true, "", productVariant)
// Check VNDK snapshot output.
@@ -451,6 +464,7 @@
cc_library {
name: "libvndk_host_supported",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -460,6 +474,7 @@
cc_library {
name: "libvndk_host_supported_but_disabled_on_device",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -500,6 +515,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -509,6 +525,7 @@
cc_library {
name: "libvndk_sp",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
@@ -519,6 +536,7 @@
cc_library {
name: "libvndk2",
vendor_available: false,
+ product_available: false,
vndk: {
enabled: true,
},
@@ -644,6 +662,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -662,12 +681,28 @@
})
}
+func TestVndkModuleError(t *testing.T) {
+ // Check the error message for vendor_available and product_available properties.
+ testCcError(t, "product_available: may not have different value than `vendor_available`", `
+ cc_library {
+ name: "libvndk",
+ vendor_available: true,
+ product_available: false,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ }
+ `)
+}
+
func TestVndkDepError(t *testing.T) {
// Check whether an error is emitted when a VNDK lib depends on a system lib.
testCcError(t, "dependency \".*\" of \".*\" missing variant", `
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -686,6 +721,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -705,6 +741,7 @@
cc_library {
name: "libvndk_sp",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
@@ -724,6 +761,7 @@
cc_library {
name: "libvndk_sp",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
@@ -744,6 +782,7 @@
cc_library {
name: "libvndk_sp",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
@@ -755,6 +794,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -767,6 +807,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -786,6 +827,7 @@
cc_library {
name: "libvndkprivate",
vendor_available: false,
+ product_available: false,
vndk: {
enabled: true,
},
@@ -805,6 +847,7 @@
cc_library {
name: "libvndksp",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
@@ -825,6 +868,7 @@
cc_library {
name: "libvndkspprivate",
vendor_available: false,
+ product_available: false,
vndk: {
enabled: true,
support_system_process: true,
@@ -847,16 +891,18 @@
cc_library {
name: "libllndk",
shared_libs: ["libdoubleloadable"],
+ llndk_stubs: "libllndk.llndk",
}
llndk_library {
- name: "libllndk",
+ name: "libllndk.llndk",
symbol_file: "",
}
cc_library {
name: "libdoubleloadable",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -868,16 +914,18 @@
cc_library {
name: "libllndk",
shared_libs: ["libvndksp"],
+ llndk_stubs: "libllndk.llndk",
}
llndk_library {
- name: "libllndk",
+ name: "libllndk.llndk",
symbol_file: "",
}
cc_library {
name: "libvndksp",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
@@ -904,6 +952,7 @@
cc_library {
name: "libdoubleloadable",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -914,6 +963,7 @@
cc_library {
name: "libnondoubleloadable",
vendor_available: false,
+ product_available: false,
vndk: {
enabled: true,
},
@@ -925,10 +975,11 @@
cc_library {
name: "libllndk",
shared_libs: ["libcoreonly"],
+ llndk_stubs: "libllndk.llndk",
}
llndk_library {
- name: "libllndk",
+ name: "libllndk.llndk",
symbol_file: "",
}
@@ -951,6 +1002,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -1084,6 +1136,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -1118,12 +1171,14 @@
version: "BOARD",
target_arch: "arm64",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
arch: {
arm64: {
srcs: ["libvndk.so"],
+ export_include_dirs: ["include/libvndk"],
},
},
}
@@ -1150,6 +1205,7 @@
shared_libs: ["libvndk"],
static_libs: ["libvendor", "libvendor_without_snapshot"],
compile_multilib: "64",
+ srcs: ["client.cpp"],
}
cc_binary {
@@ -1161,6 +1217,7 @@
system_shared_libs: [],
static_libs: ["libvndk"],
compile_multilib: "64",
+ srcs: ["bin.cpp"],
}
vendor_snapshot_static {
@@ -1171,6 +1228,7 @@
arch: {
arm64: {
src: "libvndk.a",
+ export_include_dirs: ["include/libvndk"],
},
},
}
@@ -1183,6 +1241,7 @@
arch: {
arm64: {
src: "libvendor.so",
+ export_include_dirs: ["include/libvendor"],
},
},
}
@@ -1195,6 +1254,7 @@
arch: {
arm64: {
src: "libvendor.a",
+ export_include_dirs: ["include/libvendor"],
},
},
}
@@ -1214,22 +1274,27 @@
depsBp := GatherRequiredDepsForTest(android.Android)
mockFS := map[string][]byte{
- "deps/Android.bp": []byte(depsBp),
- "framework/Android.bp": []byte(frameworkBp),
- "vendor/Android.bp": []byte(vendorProprietaryBp),
- "vendor/libvndk.a": nil,
- "vendor/libvendor.a": nil,
- "vendor/libvendor.so": nil,
- "vendor/bin": nil,
- "vndk/Android.bp": []byte(vndkBp),
- "vndk/libvndk.so": nil,
+ "deps/Android.bp": []byte(depsBp),
+ "framework/Android.bp": []byte(frameworkBp),
+ "vendor/Android.bp": []byte(vendorProprietaryBp),
+ "vendor/bin": nil,
+ "vendor/bin.cpp": nil,
+ "vendor/client.cpp": nil,
+ "vendor/include/libvndk/a.h": nil,
+ "vendor/include/libvendor/b.h": nil,
+ "vendor/libvndk.a": nil,
+ "vendor/libvendor.a": nil,
+ "vendor/libvendor.so": nil,
+ "vndk/Android.bp": []byte(vndkBp),
+ "vndk/include/libvndk/a.h": nil,
+ "vndk/libvndk.so": nil,
}
config := TestConfig(buildDir, android.Android, nil, "", mockFS)
config.TestProductVariables.DeviceVndkVersion = StringPtr("BOARD")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
- ctx := CreateTestContext()
- ctx.Register(config)
+ ctx := CreateTestContext(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "vendor/Android.bp", "vndk/Android.bp"})
android.FailIfErrored(t, errs)
@@ -1241,27 +1306,41 @@
binaryVariant := "android_vendor.BOARD_arm64_armv8-a"
// libclient uses libvndk.vndk.BOARD.arm64, libvendor.vendor_static.BOARD.arm64, libvendor_without_snapshot
- libclientLdRule := ctx.ModuleForTests("libclient", sharedVariant).Rule("ld")
- libclientFlags := libclientLdRule.Args["libFlags"]
+ libclientCcFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("cc").Args["cFlags"]
+ for _, includeFlags := range []string{
+ "-Ivndk/include/libvndk", // libvndk
+ "-Ivendor/include/libvendor", // libvendor
+ } {
+ if !strings.Contains(libclientCcFlags, includeFlags) {
+ t.Errorf("flags for libclient must contain %#v, but was %#v.",
+ includeFlags, libclientCcFlags)
+ }
+ }
+ libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("ld").Args["libFlags"]
for _, input := range [][]string{
[]string{sharedVariant, "libvndk.vndk.BOARD.arm64"},
[]string{staticVariant, "libvendor.vendor_static.BOARD.arm64"},
[]string{staticVariant, "libvendor_without_snapshot"},
} {
outputPaths := getOutputPaths(ctx, input[0] /* variant */, []string{input[1]} /* module name */)
- if !strings.Contains(libclientFlags, outputPaths[0].String()) {
- t.Errorf("libflags for libclient must contain %#v, but was %#v", outputPaths[0], libclientFlags)
+ if !strings.Contains(libclientLdFlags, outputPaths[0].String()) {
+ t.Errorf("libflags for libclient must contain %#v, but was %#v", outputPaths[0], libclientLdFlags)
}
}
// bin_without_snapshot uses libvndk.vendor_static.BOARD.arm64
- binWithoutSnapshotLdRule := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("ld")
- binWithoutSnapshotFlags := binWithoutSnapshotLdRule.Args["libFlags"]
+ binWithoutSnapshotCcFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("cc").Args["cFlags"]
+ if !strings.Contains(binWithoutSnapshotCcFlags, "-Ivendor/include/libvndk") {
+ t.Errorf("flags for bin_without_snapshot must contain %#v, but was %#v.",
+ "-Ivendor/include/libvndk", binWithoutSnapshotCcFlags)
+ }
+
+ binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("ld").Args["libFlags"]
libVndkStaticOutputPaths := getOutputPaths(ctx, staticVariant, []string{"libvndk.vendor_static.BOARD.arm64"})
- if !strings.Contains(binWithoutSnapshotFlags, libVndkStaticOutputPaths[0].String()) {
+ if !strings.Contains(binWithoutSnapshotLdFlags, libVndkStaticOutputPaths[0].String()) {
t.Errorf("libflags for bin_without_snapshot must contain %#v, but was %#v",
- libVndkStaticOutputPaths[0], binWithoutSnapshotFlags)
+ libVndkStaticOutputPaths[0], binWithoutSnapshotLdFlags)
}
// libvendor.so is installed by libvendor.vendor_shared.BOARD.arm64
@@ -1372,8 +1451,8 @@
config := TestConfig(buildDir, android.Android, nil, "", mockFS)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
- ctx := CreateTestContext()
- ctx.Register(config)
+ ctx := CreateTestContext(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "device/Android.bp"})
android.FailIfErrored(t, errs)
@@ -1462,8 +1541,8 @@
config := TestConfig(buildDir, android.Android, nil, "", mockFS)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
- ctx := CreateTestContext()
- ctx.Register(config)
+ ctx := CreateTestContext(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "device/Android.bp"})
android.FailIfErrored(t, errs)
@@ -1503,8 +1582,8 @@
config := TestConfig(buildDir, android.Android, nil, "", mockFS)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
- ctx := CreateTestContext()
- ctx.Register(config)
+ ctx := CreateTestContext(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp"})
android.FailIfErrored(t, errs)
@@ -1524,16 +1603,18 @@
cc_library {
name: "libllndk",
shared_libs: ["libnondoubleloadable"],
+ llndk_stubs: "libllndk.llndk",
}
llndk_library {
- name: "libllndk",
+ name: "libllndk.llndk",
symbol_file: "",
}
cc_library {
name: "libnondoubleloadable",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -1546,10 +1627,11 @@
name: "libllndk",
no_libcrt: true,
shared_libs: ["libnondoubleloadable"],
+ llndk_stubs: "libllndk.llndk",
}
llndk_library {
- name: "libllndk",
+ name: "libllndk.llndk",
symbol_file: "",
}
@@ -1586,6 +1668,7 @@
cc_library {
name: "libnondoubleloadable",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -1597,6 +1680,7 @@
cc_library {
name: "libdoubleloadable",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -1607,6 +1691,7 @@
cc_library {
name: "libnondoubleloadable",
vendor_available: false,
+ product_available: false,
vndk: {
enabled: true,
},
@@ -1618,10 +1703,11 @@
cc_library {
name: "libllndk",
shared_libs: ["libcoreonly"],
+ llndk_stubs: "libllndk.llndk",
}
llndk_library {
- name: "libllndk",
+ name: "libllndk.llndk",
symbol_file: "",
}
@@ -1638,12 +1724,43 @@
`)
}
+func TestCheckVndkMembershipBeforeDoubleLoadable(t *testing.T) {
+ testCcError(t, "module \"libvndksp\" variant .*: .*: VNDK-SP must only depend on VNDK-SP", `
+ cc_library {
+ name: "libvndksp",
+ shared_libs: ["libanothervndksp"],
+ vendor_available: true,
+ product_available: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ }
+ }
+
+ cc_library {
+ name: "libllndk",
+ shared_libs: ["libanothervndksp"],
+ }
+
+ llndk_library {
+ name: "libllndk",
+ symbol_file: "",
+ }
+
+ cc_library {
+ name: "libanothervndksp",
+ vendor_available: true,
+ }
+ `)
+}
+
func TestVndkExt(t *testing.T) {
// This test checks the VNDK-Ext properties.
bp := `
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -1652,6 +1769,7 @@
cc_library {
name: "libvndk2",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -1659,6 +1777,9 @@
vendor: {
suffix: "-suffix",
},
+ product: {
+ suffix: "-suffix",
+ },
},
nocrt: true,
}
@@ -1726,6 +1847,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -1756,6 +1878,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -1786,6 +1909,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -1806,6 +1930,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -1826,6 +1951,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -1846,6 +1972,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -1856,6 +1983,7 @@
name: "libvndk_ext_product",
product_specific: true,
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
extends: "libvndk",
@@ -1871,6 +1999,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -1893,6 +2022,7 @@
cc_library {
name: "libvndk_sp",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
@@ -1919,6 +2049,7 @@
cc_library {
name: "libvndk",
vendor_available: false,
+ product_available: false,
vndk: {
enabled: true,
},
@@ -1940,6 +2071,7 @@
cc_library {
name: "libvndk",
vendor_available: false,
+ product_available: false,
vndk: {
enabled: true,
},
@@ -1964,6 +2096,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -1983,6 +2116,7 @@
cc_library {
name: "libvndk_sp",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
@@ -2016,6 +2150,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -2045,6 +2180,7 @@
cc_library {
name: "libvndk_sp",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
@@ -2077,6 +2213,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -2097,6 +2234,7 @@
cc_library {
name: "libvndk_sp",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
@@ -2144,6 +2282,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -2153,6 +2292,7 @@
cc_library {
name: "libvndk_sp",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
@@ -2179,6 +2319,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -2198,6 +2339,7 @@
cc_library {
name: "libvndk_sp",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
@@ -2226,6 +2368,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -2245,6 +2388,7 @@
cc_library {
name: "libvndk2",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -2257,6 +2401,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -2276,6 +2421,7 @@
cc_library {
name: "libvndk2",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -2292,6 +2438,7 @@
cc_library {
name: "libvndk_sp",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
@@ -2313,6 +2460,7 @@
cc_library {
name: "libvndk_sp_2",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
@@ -2326,6 +2474,7 @@
cc_library {
name: "libvndk_sp",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -2345,6 +2494,7 @@
cc_library {
name: "libvndk_sp2",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -2362,14 +2512,16 @@
bp := `
cc_library {
name: "libllndk",
+ llndk_stubs: "libllndk.llndk",
}
llndk_library {
- name: "libllndk",
+ name: "libllndk.llndk",
symbol_file: "",
}
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -2378,6 +2530,7 @@
cc_library {
name: "libvndk_sp",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
@@ -2390,6 +2543,11 @@
nocrt: true,
}
cc_library {
+ name: "libpa",
+ product_available: true,
+ nocrt: true,
+ }
+ cc_library {
name: "libproduct_va",
product_specific: true,
vendor_available: true,
@@ -2402,7 +2560,7 @@
"libllndk",
"libvndk",
"libvndk_sp",
- "libva",
+ "libpa",
"libproduct_va",
],
nocrt: true,
@@ -2428,8 +2586,8 @@
ctx := testCcWithConfig(t, config)
- checkVndkModule(t, ctx, "libvndk", "vndk-VER", false, "", productVariant)
- checkVndkModule(t, ctx, "libvndk_sp", "vndk-sp-VER", true, "", productVariant)
+ checkVndkModule(t, ctx, "libvndk", "", false, "", productVariant)
+ checkVndkModule(t, ctx, "libvndk_sp", "", true, "", productVariant)
}
func TestEnforceProductVndkVersionErrors(t *testing.T) {
@@ -2474,6 +2632,7 @@
cc_library {
name: "libvndk_private",
vendor_available: false,
+ product_available: false,
vndk: {
enabled: true,
},
@@ -2517,6 +2676,7 @@
cc_library {
name: "libvndk",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -2524,6 +2684,7 @@
cc_library {
name: "libvndksp",
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
@@ -2532,6 +2693,7 @@
cc_library {
name: "libvndkprivate",
vendor_available: false,
+ product_available: false,
vndk: {
enabled: true,
},
@@ -2554,6 +2716,7 @@
target_arch: "arm",
binder32bit: true,
vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
},
@@ -2565,16 +2728,18 @@
}
cc_library {
name: "libllndk",
+ llndk_stubs: "libllndk.llndk",
}
llndk_library {
- name: "libllndk",
+ name: "libllndk.llndk",
symbol_file: "",
}
cc_library {
name: "libllndkprivate",
+ llndk_stubs: "libllndkprivate.llndk",
}
llndk_library {
- name: "libllndkprivate",
+ name: "libllndkprivate.llndk",
vendor_available: false,
symbol_file: "",
}`
@@ -2890,59 +3055,6 @@
return modulesInOrder, allDeps
}
-func TestLinkReordering(t *testing.T) {
- for _, testCase := range staticLinkDepOrderTestCases {
- errs := []string{}
-
- // parse testcase
- _, givenTransitiveDeps := parseModuleDeps(testCase.inStatic)
- expectedModuleNames, expectedTransitiveDeps := parseModuleDeps(testCase.outOrdered)
- if testCase.allOrdered == "" {
- // allow the test case to skip specifying allOrdered
- testCase.allOrdered = testCase.outOrdered
- }
- _, expectedAllDeps := parseModuleDeps(testCase.allOrdered)
- _, givenAllSharedDeps := parseModuleDeps(testCase.inShared)
-
- // For each module whose post-reordered dependencies were specified, validate that
- // reordering the inputs produces the expected outputs.
- for _, moduleName := range expectedModuleNames {
- moduleDeps := givenTransitiveDeps[moduleName]
- givenSharedDeps := givenAllSharedDeps[moduleName]
- orderedAllDeps, orderedDeclaredDeps := orderDeps(moduleDeps, givenSharedDeps, givenTransitiveDeps)
-
- correctAllOrdered := expectedAllDeps[moduleName]
- if !reflect.DeepEqual(orderedAllDeps, correctAllOrdered) {
- errs = append(errs, fmt.Sprintf("orderDeps returned incorrect orderedAllDeps."+
- "\nin static:%q"+
- "\nin shared:%q"+
- "\nmodule: %v"+
- "\nexpected: %s"+
- "\nactual: %s",
- testCase.inStatic, testCase.inShared, moduleName, correctAllOrdered, orderedAllDeps))
- }
-
- correctOutputDeps := expectedTransitiveDeps[moduleName]
- if !reflect.DeepEqual(correctOutputDeps, orderedDeclaredDeps) {
- errs = append(errs, fmt.Sprintf("orderDeps returned incorrect orderedDeclaredDeps."+
- "\nin static:%q"+
- "\nin shared:%q"+
- "\nmodule: %v"+
- "\nexpected: %s"+
- "\nactual: %s",
- testCase.inStatic, testCase.inShared, moduleName, correctOutputDeps, orderedDeclaredDeps))
- }
- }
-
- if len(errs) > 0 {
- sort.Strings(errs)
- for _, err := range errs {
- t.Error(err)
- }
- }
- }
-}
-
func getOutputPaths(ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) {
for _, moduleName := range moduleNames {
module := ctx.ModuleForTests(moduleName, variant).Module().(*Module)
@@ -2977,8 +3089,8 @@
variant := "android_arm64_armv8-a_static"
moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
- actual := moduleA.depsInLinkOrder
- expected := getOutputPaths(ctx, variant, []string{"c", "b", "d"})
+ actual := ctx.ModuleProvider(moduleA, StaticLibraryInfoProvider).(StaticLibraryInfo).TransitiveStaticLibrariesForOrdering.ToList()
+ expected := getOutputPaths(ctx, variant, []string{"a", "c", "b", "d"})
if !reflect.DeepEqual(actual, expected) {
t.Errorf("staticDeps orderings were not propagated correctly"+
@@ -3011,8 +3123,8 @@
variant := "android_arm64_armv8-a_static"
moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
- actual := moduleA.depsInLinkOrder
- expected := getOutputPaths(ctx, variant, []string{"c", "b"})
+ actual := ctx.ModuleProvider(moduleA, StaticLibraryInfoProvider).(StaticLibraryInfo).TransitiveStaticLibrariesForOrdering.ToList()
+ expected := getOutputPaths(ctx, variant, []string{"a", "c", "b"})
if !reflect.DeepEqual(actual, expected) {
t.Errorf("staticDeps orderings did not account for shared libs"+
@@ -3025,6 +3137,7 @@
}
func checkEquals(t *testing.T, message string, expected, actual interface{}) {
+ t.Helper()
if !reflect.DeepEqual(actual, expected) {
t.Errorf(message+
"\nactual: %v"+
@@ -3040,19 +3153,20 @@
cc_library {
name: "libllndk",
stubs: { versions: ["1", "2"] },
+ llndk_stubs: "libllndk.llndk",
}
llndk_library {
- name: "libllndk",
+ name: "libllndk.llndk",
}
`)
actual := ctx.ModuleVariantsForTests("libllndk.llndk")
expected := []string{
- "android_vendor.VER_arm64_armv8-a_shared",
"android_vendor.VER_arm64_armv8-a_shared_1",
"android_vendor.VER_arm64_armv8-a_shared_2",
- "android_vendor.VER_arm_armv7-a-neon_shared",
+ "android_vendor.VER_arm64_armv8-a_shared",
"android_vendor.VER_arm_armv7-a-neon_shared_1",
"android_vendor.VER_arm_armv7-a-neon_shared_2",
+ "android_vendor.VER_arm_armv7-a-neon_shared",
}
checkEquals(t, "variants for llndk stubs", expected, actual)
@@ -3070,10 +3184,15 @@
export_include_dirs: ["my_include"],
}
llndk_library {
- name: "libllndk",
+ name: "libllndk.llndk",
export_llndk_headers: ["libllndk_headers"],
}
cc_library {
+ name: "libllndk",
+ llndk_stubs: "libllndk.llndk",
+ }
+
+ cc_library {
name: "libvendor",
shared_libs: ["libllndk"],
vendor: true,
@@ -3581,7 +3700,7 @@
cc_binary {
name: "mybin",
srcs: ["foo.c"],
- static_libs: ["libfooB"],
+ static_libs: ["libfooC", "libfooB"],
static_executable: true,
stl: "none",
}
@@ -3602,8 +3721,8 @@
},
}`)
- mybin := ctx.ModuleForTests("mybin", "android_arm64_armv8-a").Module().(*Module)
- actual := mybin.depsInLinkOrder
+ mybin := ctx.ModuleForTests("mybin", "android_arm64_armv8-a").Rule("ld")
+ actual := mybin.Implicits[:2]
expected := getOutputPaths(ctx, "android_arm64_armv8-a_static", []string{"libfooB", "libfooC"})
if !reflect.DeepEqual(actual, expected) {
@@ -3763,11 +3882,11 @@
config := TestConfig(buildDir, android.Android, nil, bp, nil)
config.TestProductVariables.Debuggable = BoolPtr(true)
- ctx := CreateTestContext()
+ ctx := CreateTestContext(config)
ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("variable", android.VariableMutator).Parallel()
})
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
android.FailIfErrored(t, errs)
@@ -3779,3 +3898,46 @@
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(config)
+ ctx.SetAllowMissingDependencies(true)
+ ctx.Register()
+
+ _, 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 46328e9..0058b8c 100644
--- a/cc/check.go
+++ b/cc/check.go
@@ -38,6 +38,8 @@
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 c268dec..3c86d20 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -143,21 +143,21 @@
} `android:"arch_variant"`
Target struct {
- Vendor struct {
- // list of source files that should only be used in the
- // vendor variant of the C/C++ module.
+ Vendor, Product struct {
+ // list of source files that should only be used in vendor or
+ // product variant of the C/C++ module.
Srcs []string `android:"path"`
- // list of source files that should not be used to
- // build the vendor variant of the C/C++ module.
+ // list of source files that should not be used to build vendor
+ // or product variant of the C/C++ module.
Exclude_srcs []string `android:"path"`
- // List of additional cflags that should be used to build the vendor
- // variant of the C/C++ module.
+ // List of additional cflags that should be used to build vendor
+ // or product variant of the C/C++ module.
Cflags []string
- // list of generated sources that should not be used to
- // build the vendor variant of the C/C++ module.
+ // list of generated sources that should not be used to build
+ // vendor or product variant of the C/C++ module.
Exclude_generated_sources []string
}
Recovery struct {
@@ -177,6 +177,15 @@
// build the recovery variant of the C/C++ module.
Exclude_generated_sources []string
}
+ Vendor_ramdisk struct {
+ // list of source files that should not be used to
+ // build the vendor ramdisk variant of the C/C++ module.
+ Exclude_srcs []string `android:"path"`
+
+ // List of additional cflags that should be used to build the vendor ramdisk
+ // variant of the C/C++ module.
+ Cflags []string
+ }
}
Proto struct {
@@ -289,7 +298,9 @@
CheckBadCompilerFlags(ctx, "conlyflags", compiler.Properties.Conlyflags)
CheckBadCompilerFlags(ctx, "asflags", compiler.Properties.Asflags)
CheckBadCompilerFlags(ctx, "vendor.cflags", compiler.Properties.Target.Vendor.Cflags)
+ CheckBadCompilerFlags(ctx, "product.cflags", compiler.Properties.Target.Product.Cflags)
CheckBadCompilerFlags(ctx, "recovery.cflags", compiler.Properties.Target.Recovery.Cflags)
+ CheckBadCompilerFlags(ctx, "vendor_ramdisk.cflags", compiler.Properties.Target.Vendor_ramdisk.Cflags)
esc := proptools.NinjaAndShellEscapeList
@@ -354,10 +365,16 @@
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 +403,7 @@
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
}
@@ -457,7 +474,12 @@
flags.Local.ConlyFlags = append([]string{"-std=" + cStd}, flags.Local.ConlyFlags...)
flags.Local.CppFlags = append([]string{"-std=" + cppStd}, flags.Local.CppFlags...)
- if ctx.useVndk() {
+ if ctx.inVendor() {
+ flags.Local.CFlags = append(flags.Local.CFlags, esc(compiler.Properties.Target.Vendor.Cflags)...)
+ }
+
+ if ctx.inProduct() {
+ // TODO(b/150902910): must use 'compiler.Properties.Target.Product.Cflags'
flags.Local.CFlags = append(flags.Local.CFlags, esc(compiler.Properties.Target.Vendor.Cflags)...)
}
@@ -465,6 +487,10 @@
flags.Local.CFlags = append(flags.Local.CFlags, esc(compiler.Properties.Target.Recovery.Cflags)...)
}
+ if ctx.inVendorRamdisk() {
+ flags.Local.CFlags = append(flags.Local.CFlags, esc(compiler.Properties.Target.Vendor_ramdisk.Cflags)...)
+ }
+
// We can enforce some rules more strictly in the code we own. strict
// indicates if this is code that we can be stricter with. If we have
// rules that we want to apply to *our* code (but maybe can't for
@@ -646,3 +672,43 @@
}
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/OWNERS b/cc/config/OWNERS
index b2f54e5..701db92 100644
--- a/cc/config/OWNERS
+++ b/cc/config/OWNERS
@@ -1 +1,3 @@
per-file vndk.go = smoreland@google.com, victoryang@google.com
+per-file clang.go,global.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
+
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 62d8cc8..e6024aa 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -34,6 +34,9 @@
"armv8-2a": []string{
"-march=armv8.2-a",
},
+ "armv8-2a-dotprod": []string{
+ "-march=armv8.2-a+dotprod",
+ },
}
arm64Ldflags = []string{
@@ -100,6 +103,7 @@
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 @@
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 @@
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/arm64_linux_host.go b/cc/config/arm64_linux_host.go
index 74642c2..59c52d1 100644
--- a/cc/config/arm64_linux_host.go
+++ b/cc/config/arm64_linux_host.go
@@ -29,6 +29,10 @@
// which stands for "Android device target". Keeping PIC on is required because
// many modules we have (e.g. Bionic) assume PIC.
"-fpic",
+
+ // This is normally in ClangExtraTargetCflags, but that's for device and we need
+ // the same for host
+ "-nostdlibinc",
))
linuxCrossLdflags = ClangFilterUnknownCflags([]string{
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 7db405c..441bff2 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -42,7 +42,6 @@
"-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 @@
// 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 @@
// 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 @@
"-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 @@
"-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 32f163d..e5cb7ee 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -46,6 +46,7 @@
"-O2",
"-g",
+ "-fdebug-info-for-profiling",
"-fno-strict-aliasing",
@@ -114,6 +115,12 @@
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 +133,10 @@
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{
@@ -201,6 +206,7 @@
pctx.PrefixedExistentPathsForSourcesVariable("CommonGlobalIncludes", "-I",
[]string{
"system/core/include",
+ "system/logging/liblog/include",
"system/media/audio/include",
"hardware/libhardware/include",
"hardware/libhardware_legacy/include",
diff --git a/cc/config/vndk.go b/cc/config/vndk.go
index f7d30c2..eb3d16f 100644
--- a/cc/config/vndk.go
+++ b/cc/config/vndk.go
@@ -26,6 +26,7 @@
"android.hardware.power-ndk_platform",
"android.hardware.rebootescrow-ndk_platform",
"android.hardware.vibrator-ndk_platform",
+ "android.system.keystore2-unstable-ndk_platform",
"libbinder",
"libcrypto",
"libexpat",
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index b5b5553..b77df79 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -39,6 +39,9 @@
// 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 5295418..dddfe94 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -38,6 +38,9 @@
// 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 {
@@ -164,17 +167,32 @@
// that should be installed in the fuzz target output directories. This function
// returns true, unless:
// - The module is not a shared library, or
-// - The module is a header, stub, or vendor-linked library.
+// - The module is a header, stub, or vendor-linked library, or
+// - The module is a prebuilt and its source is available, or
+// - The module is a versioned member of an SDK snapshot.
func isValidSharedDependency(dependency android.Module) bool {
// TODO(b/144090547): We should be parsing these modules using
// ModuleDependencyTag instead of the current brute-force checking.
- if linkable, ok := dependency.(LinkableInterface); !ok || // Discard non-linkables.
- !linkable.CcLibraryInterface() || !linkable.Shared() || // Discard static libs.
- linkable.UseVndk() || // Discard vendor linked libraries.
+ linkable, ok := dependency.(LinkableInterface)
+ if !ok || !linkable.CcLibraryInterface() {
+ // Discard non-linkables.
+ return false
+ }
+
+ if !linkable.Shared() {
+ // Discard static libs.
+ return false
+ }
+
+ if linkable.UseVndk() {
+ // Discard vendor linked libraries.
+ return false
+ }
+
+ if lib := moduleLibraryInterface(dependency); lib != nil && lib.buildStubs() && linkable.CcLibrary() {
// Discard stubs libs (only CCLibrary variants). Prebuilt libraries should not
// be excluded on the basis of they're not CCLibrary()'s.
- (linkable.CcLibrary() && linkable.BuildStubs()) {
return false
}
@@ -187,6 +205,20 @@
}
}
+ // If the same library is present both as source and a prebuilt we must pick
+ // only one to avoid a conflict. Always prefer the source since the prebuilt
+ // probably won't be built with sanitizers enabled.
+ if prebuilt, ok := dependency.(android.PrebuiltInterface); ok &&
+ prebuilt.Prebuilt() != nil && prebuilt.Prebuilt().SourceExists() {
+ return false
+ }
+
+ // Discard versioned members of SDK snapshots, because they will conflict with
+ // unversioned ones.
+ if sdkMember, ok := dependency.(android.SdkAware); ok && !sdkMember.ContainingSdk().Unversioned() {
+ return false
+ }
+
return true
}
@@ -246,14 +278,7 @@
if fuzz.Properties.Fuzz_config != nil {
configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
- ctx.Build(pctx, android.BuildParams{
- Rule: android.WriteFile,
- Description: "fuzzer infrastructure configuration",
- Output: configPath,
- Args: map[string]string{
- "content": fuzz.Properties.Fuzz_config.String(),
- },
- })
+ android.WriteFileRule(ctx, configPath, fuzz.Properties.Fuzz_config.String())
fuzz.config = configPath
}
@@ -369,10 +394,10 @@
return
}
- // Discard ramdisk + recovery modules, they're duplicates of
+ // Discard ramdisk + vendor_ramdisk + recovery modules, they're duplicates of
// fuzz targets we're going to package anyway.
if !ccModule.Enabled() || ccModule.Properties.PreventInstall ||
- ccModule.InRamdisk() || ccModule.InRecovery() {
+ ccModule.InRamdisk() || ccModule.InVendorRamdisk() || ccModule.InRecovery() {
return
}
diff --git a/cc/genrule.go b/cc/genrule.go
index cce4a83..3668e2b 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -24,10 +24,12 @@
}
type GenruleExtraProperties struct {
- Vendor_available *bool
- Ramdisk_available *bool
- Recovery_available *bool
- Sdk_version *string
+ Vendor_available *bool
+ Product_available *bool
+ Ramdisk_available *bool
+ Vendor_ramdisk_available *bool
+ Recovery_available *bool
+ Sdk_version *string
}
// cc_genrule is a genrule that can depend on other cc_* objects.
@@ -61,13 +63,17 @@
return false
}
- return Bool(g.Vendor_available) || !(ctx.SocSpecific() || ctx.DeviceSpecific())
+ return Bool(g.Vendor_available) || Bool(g.Product_available) || !(ctx.SocSpecific() || ctx.DeviceSpecific())
}
func (g *GenruleExtraProperties) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
return Bool(g.Ramdisk_available)
}
+func (g *GenruleExtraProperties) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return Bool(g.Vendor_ramdisk_available)
+}
+
func (g *GenruleExtraProperties) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
return Bool(g.Recovery_available)
}
@@ -95,7 +101,8 @@
return variants
}
- if Bool(g.Vendor_available) || ctx.ProductSpecific() {
+ // TODO(b/150902910): vendor_available will not create product variant. Remove Bool(g.Vendor_available)
+ if Bool(g.Vendor_available) || Bool(g.Product_available) || ctx.ProductSpecific() {
variants = append(variants, ProductVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
if vndkVersion := ctx.DeviceConfig().ProductVndkVersion(); vndkVersion != "current" {
variants = append(variants, ProductVariationPrefix+vndkVersion)
diff --git a/cc/genrule_test.go b/cc/genrule_test.go
index a366f76..0c7952b 100644
--- a/cc/genrule_test.go
+++ b/cc/genrule_test.go
@@ -22,9 +22,9 @@
)
func testGenruleContext(config android.Config) *android.TestContext {
- ctx := android.NewTestArchContext()
+ ctx := android.NewTestArchContext(config)
ctx.RegisterModuleType("cc_genrule", genRuleFactory)
- ctx.Register(config)
+ ctx.Register()
return ctx
}
diff --git a/cc/image.go b/cc/image.go
index ea6f567..3d6769e 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -27,12 +27,13 @@
type imageVariantType string
const (
- coreImageVariant imageVariantType = "core"
- vendorImageVariant imageVariantType = "vendor"
- productImageVariant imageVariantType = "product"
- ramdiskImageVariant imageVariantType = "ramdisk"
- recoveryImageVariant imageVariantType = "recovery"
- hostImageVariant imageVariantType = "host"
+ coreImageVariant imageVariantType = "core"
+ vendorImageVariant imageVariantType = "vendor"
+ productImageVariant imageVariantType = "product"
+ ramdiskImageVariant imageVariantType = "ramdisk"
+ vendorRamdiskImageVariant imageVariantType = "vendor_ramdisk"
+ recoveryImageVariant imageVariantType = "recovery"
+ hostImageVariant imageVariantType = "host"
)
func (c *Module) getImageVariantType() imageVariantType {
@@ -44,6 +45,8 @@
return productImageVariant
} else if c.InRamdisk() {
return ramdiskImageVariant
+ } else if c.InVendorRamdisk() {
+ return vendorRamdiskImageVariant
} else if c.InRecovery() {
return recoveryImageVariant
} else {
@@ -62,13 +65,14 @@
)
func (ctx *moduleContext) ProductSpecific() bool {
+ //TODO(b/150902910): Replace HasNonSystemVariants() with HasProductVariant()
return ctx.ModuleContext.ProductSpecific() ||
- (ctx.mod.HasVendorVariant() && ctx.mod.inProduct() && !ctx.mod.IsVndk())
+ (ctx.mod.HasNonSystemVariants() && ctx.mod.inProduct())
}
func (ctx *moduleContext) SocSpecific() bool {
return ctx.ModuleContext.SocSpecific() ||
- (ctx.mod.HasVendorVariant() && ctx.mod.inVendor() && !ctx.mod.IsVndk())
+ (ctx.mod.HasVendorVariant() && ctx.mod.inVendor())
}
func (ctx *moduleContextImpl) inProduct() bool {
@@ -83,16 +87,29 @@
return ctx.mod.InRamdisk()
}
+func (ctx *moduleContextImpl) inVendorRamdisk() bool {
+ return ctx.mod.InVendorRamdisk()
+}
+
func (ctx *moduleContextImpl) inRecovery() bool {
return ctx.mod.InRecovery()
}
-// Returns true only when this module is configured to have core, product and vendor
-// variants.
+// Returns true when this module is configured to have core and vendor variants.
func (c *Module) HasVendorVariant() bool {
return c.IsVndk() || Bool(c.VendorProperties.Vendor_available)
}
+// Returns true when this module is configured to have core and product variants.
+func (c *Module) HasProductVariant() bool {
+ return c.IsVndk() || Bool(c.VendorProperties.Product_available)
+}
+
+// Returns true when this module is configured to have core and either product or vendor variants.
+func (c *Module) HasNonSystemVariants() bool {
+ return c.IsVndk() || Bool(c.VendorProperties.Vendor_available) || Bool(c.VendorProperties.Product_available)
+}
+
// Returns true if the module is "product" variant. Usually these modules are installed in /product
func (c *Module) inProduct() bool {
return c.Properties.ImageVariationPrefix == ProductVariationPrefix
@@ -107,6 +124,10 @@
return c.ModuleBase.InRamdisk() || c.ModuleBase.InstallInRamdisk()
}
+func (c *Module) InVendorRamdisk() bool {
+ return c.ModuleBase.InVendorRamdisk() || c.ModuleBase.InstallInVendorRamdisk()
+}
+
func (c *Module) InRecovery() bool {
return c.ModuleBase.InRecovery() || c.ModuleBase.InstallInRecovery()
}
@@ -115,6 +136,10 @@
return c.ModuleBase.InstallInRamdisk()
}
+func (c *Module) OnlyInVendorRamdisk() bool {
+ return c.ModuleBase.InstallInVendorRamdisk()
+}
+
func (c *Module) OnlyInRecovery() bool {
return c.ModuleBase.InstallInRecovery()
}
@@ -124,9 +149,30 @@
vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
productSpecific := mctx.ProductSpecific()
- if m.VendorProperties.Vendor_available != nil && vendorSpecific {
- mctx.PropertyErrorf("vendor_available",
- "doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific:true`")
+ if m.VendorProperties.Vendor_available != nil {
+ if vendorSpecific {
+ mctx.PropertyErrorf("vendor_available",
+ "doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific:true`")
+ }
+ // If defined, make sure vendor_available and product_available has the
+ // same value since `false` for these properties means the module is
+ // for system only but provides the variant.
+ if m.VendorProperties.Product_available != nil {
+ if Bool(m.VendorProperties.Vendor_available) != Bool(m.VendorProperties.Product_available) {
+ mctx.PropertyErrorf("product_available", "may not have different value than `vendor_available`")
+ }
+ }
+ }
+
+ if m.VendorProperties.Product_available != nil {
+ if productSpecific {
+ mctx.PropertyErrorf("product_available",
+ "doesn't make sense at the same time as `product_specific: true`")
+ }
+ if vendorSpecific {
+ mctx.PropertyErrorf("product_available",
+ "cannot provide product variant from a vendor module. Please use `product_specific: true` with `vendor_available: true`")
+ }
}
if vndkdep := m.vndkdep; vndkdep != nil {
@@ -138,6 +184,9 @@
} else if m.VendorProperties.Vendor_available != nil {
mctx.PropertyErrorf("vendor_available",
"must not set at the same time as `vndk: {extends: \"...\"}`")
+ } else if m.VendorProperties.Product_available != nil {
+ mctx.PropertyErrorf("product_available",
+ "must not set at the same time as `vndk: {extends: \"...\"}`")
}
} else {
if vndkdep.isVndkExt() {
@@ -165,6 +214,7 @@
var coreVariantNeeded bool = false
var ramdiskVariantNeeded bool = false
+ var vendorRamdiskVariantNeeded bool = false
var recoveryVariantNeeded bool = false
var vendorVariants []string
@@ -215,21 +265,25 @@
} else {
mctx.ModuleErrorf("version is unknown for snapshot prebuilt")
}
- } 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.
+ } else if m.HasNonSystemVariants() && !m.isVndkExt() {
+ // This will be available to /system unless it is product_specific
+ // which will be handled later.
coreVariantNeeded = true
// We assume that modules under proprietary paths are compatible for
// BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
// PLATFORM_VNDK_VERSION.
- if isVendorProprietaryModule(mctx) {
- vendorVariants = append(vendorVariants, boardVndkVersion)
- } else {
- vendorVariants = append(vendorVariants, platformVndkVersion)
+ if m.HasVendorVariant() {
+ if isVendorProprietaryModule(mctx) {
+ vendorVariants = append(vendorVariants, boardVndkVersion)
+ } else {
+ vendorVariants = append(vendorVariants, platformVndkVersion)
+ }
}
// vendor_available modules are also available to /product.
+ // TODO(b/150902910): product variant will be created only if
+ // m.HasProductVariant() is true.
productVariants = append(productVariants, platformVndkVersion)
// VNDK is always PLATFORM_VNDK_VERSION
if !m.IsVndk() {
@@ -283,6 +337,15 @@
coreVariantNeeded = false
}
+ if Bool(m.Properties.Vendor_ramdisk_available) {
+ vendorRamdiskVariantNeeded = true
+ }
+
+ if m.ModuleBase.InstallInVendorRamdisk() {
+ vendorRamdiskVariantNeeded = true
+ coreVariantNeeded = false
+ }
+
if Bool(m.Properties.Recovery_available) {
recoveryVariantNeeded = true
}
@@ -301,6 +364,7 @@
}
m.Properties.RamdiskVariantNeeded = ramdiskVariantNeeded
+ m.Properties.VendorRamdiskVariantNeeded = vendorRamdiskVariantNeeded
m.Properties.RecoveryVariantNeeded = recoveryVariantNeeded
m.Properties.CoreVariantNeeded = coreVariantNeeded
}
@@ -313,6 +377,10 @@
return c.Properties.RamdiskVariantNeeded
}
+func (c *Module) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return c.Properties.VendorRamdiskVariantNeeded
+}
+
func (c *Module) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
return c.Properties.RecoveryVariantNeeded
}
@@ -321,10 +389,58 @@
return c.Properties.ExtraVariants
}
+func squashVendorSrcs(m *Module) {
+ if lib, ok := m.compiler.(*libraryDecorator); ok {
+ lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
+ lib.baseCompiler.Properties.Target.Vendor.Srcs...)
+
+ lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
+ lib.baseCompiler.Properties.Target.Vendor.Exclude_srcs...)
+
+ lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
+ lib.baseCompiler.Properties.Target.Vendor.Exclude_generated_sources...)
+ }
+}
+
+func squashProductSrcs(m *Module) {
+ if lib, ok := m.compiler.(*libraryDecorator); ok {
+ lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
+ lib.baseCompiler.Properties.Target.Product.Srcs...)
+
+ lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
+ lib.baseCompiler.Properties.Target.Product.Exclude_srcs...)
+
+ lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
+ lib.baseCompiler.Properties.Target.Product.Exclude_generated_sources...)
+ }
+}
+
+func squashRecoverySrcs(m *Module) {
+ if lib, ok := m.compiler.(*libraryDecorator); ok {
+ lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
+ lib.baseCompiler.Properties.Target.Recovery.Srcs...)
+
+ lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
+ lib.baseCompiler.Properties.Target.Recovery.Exclude_srcs...)
+
+ lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
+ lib.baseCompiler.Properties.Target.Recovery.Exclude_generated_sources...)
+ }
+}
+
+func squashVendorRamdiskSrcs(m *Module) {
+ if lib, ok := m.compiler.(*libraryDecorator); ok {
+ lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, lib.baseCompiler.Properties.Target.Vendor_ramdisk.Exclude_srcs...)
+ }
+}
+
func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string, module android.Module) {
m := module.(*Module)
if variant == android.RamdiskVariation {
m.MakeAsPlatform()
+ } else if variant == android.VendorRamdiskVariation {
+ m.MakeAsPlatform()
+ squashVendorRamdiskSrcs(m)
} else if variant == android.RecoveryVariation {
m.MakeAsPlatform()
squashRecoverySrcs(m)
@@ -343,6 +459,7 @@
} else if strings.HasPrefix(variant, ProductVariationPrefix) {
m.Properties.ImageVariationPrefix = ProductVariationPrefix
m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix)
+ // TODO (b/150902910): This will be replaced with squashProductSrcs(m).
squashVendorSrcs(m)
}
}
diff --git a/cc/kernel_headers.go b/cc/kernel_headers.go
index 796de62..9ea988a 100644
--- a/cc/kernel_headers.go
+++ b/cc/kernel_headers.go
@@ -26,6 +26,7 @@
if ctx.Device() {
f := &stub.libraryDecorator.flagExporter
f.reexportSystemDirs(android.PathsForSource(ctx, ctx.DeviceConfig().DeviceKernelHeaderDirs())...)
+ f.setProvider(ctx)
}
return stub.libraryDecorator.linkStatic(ctx, flags, deps, objs)
}
diff --git a/cc/library.go b/cc/library.go
index 92853b5..eeddd90 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -19,8 +19,6 @@
"io"
"path/filepath"
"regexp"
- "sort"
- "strconv"
"strings"
"sync"
@@ -74,7 +72,7 @@
Suffix *string `android:"arch_variant"`
Target struct {
- Vendor struct {
+ Vendor, Product struct {
// set suffix of the name of the output
Suffix *string `android:"arch_variant"`
}
@@ -112,6 +110,9 @@
// Inject boringssl hash into the shared library. This is only intended for use by external/boringssl.
Inject_bssl_hash *bool `android:"arch_variant"`
+
+ // If this is an LLNDK library, the name of the equivalent llndk_library module.
+ Llndk_stubs *string
}
type StaticProperties struct {
@@ -123,7 +124,10 @@
}
type StaticOrSharedProperties struct {
- Srcs []string `android:"path,arch_variant"`
+ Srcs []string `android:"path,arch_variant"`
+
+ Sanitized Sanitized `android:"arch_variant"`
+
Cflags []string `android:"arch_variant"`
Enabled *bool `android:"arch_variant"`
@@ -152,6 +156,8 @@
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 {
@@ -166,11 +172,11 @@
Export_system_include_dirs []string `android:"arch_variant"`
Target struct {
- Vendor struct {
+ Vendor, Product struct {
// list of exported include directories, like
- // export_include_dirs, that will be applied to the
- // vendor variant of this library. This will overwrite
- // any other declarations.
+ // export_include_dirs, that will be applied to
+ // vendor or product variant of this library.
+ // This will overwrite any other declarations.
Override_export_include_dirs []string
}
}
@@ -247,6 +253,7 @@
}
func (f *flagExporter) exportedIncludes(ctx ModuleContext) android.Paths {
+ // TODO(b/150902910): product variant must use Target.Product
if ctx.useVndk() && f.Properties.Target.Vendor.Override_export_include_dirs != nil {
return android.PathsForModuleSrc(ctx, f.Properties.Target.Vendor.Override_export_include_dirs)
} else {
@@ -291,36 +298,16 @@
f.headers = append(f.headers, headers...)
}
-func (f *flagExporter) exportedDirs() android.Paths {
- return f.dirs
+func (f *flagExporter) setProvider(ctx android.ModuleContext) {
+ ctx.SetProvider(FlagExporterInfoProvider, FlagExporterInfo{
+ IncludeDirs: f.dirs,
+ SystemIncludeDirs: f.systemDirs,
+ Flags: f.flags,
+ Deps: f.deps,
+ GeneratedHeaders: f.headers,
+ })
}
-func (f *flagExporter) exportedSystemDirs() android.Paths {
- return f.systemDirs
-}
-
-func (f *flagExporter) exportedFlags() []string {
- return f.flags
-}
-
-func (f *flagExporter) exportedDeps() android.Paths {
- return f.deps
-}
-
-func (f *flagExporter) exportedGeneratedHeaders() android.Paths {
- return f.headers
-}
-
-type exportedFlagsProducer interface {
- exportedDirs() android.Paths
- exportedSystemDirs() android.Paths
- exportedFlags() []string
- exportedDeps() android.Paths
- exportedGeneratedHeaders() android.Paths
-}
-
-var _ exportedFlagsProducer = (*flagExporter)(nil)
-
// libraryDecorator wraps baseCompiler, baseLinker and baseInstaller to provide library-specific
// functionality: static vs. shared linkage, reusing object files for shared libraries
type libraryDecorator struct {
@@ -338,10 +325,6 @@
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
@@ -370,7 +353,7 @@
// Location of the file that should be copied to dist dir when requested
distFile android.Path
- versionScriptPath android.ModuleGenPath
+ versionScriptPath android.OptionalPath
post_install_cmds []string
@@ -379,6 +362,8 @@
useCoreVariant bool
checkSameCoreVariant bool
+ skipAPIDefine bool
+
// Decorated interfaces
*baseCompiler
*baseLinker
@@ -400,7 +385,7 @@
// can't be globbed, and they should be manually collected.
// So, we first filter out intermediate directories (which contains generated headers)
// from exported directories, and then glob headers under remaining directories.
- for _, path := range append(l.exportedDirs(), l.exportedSystemDirs()...) {
+ for _, path := range append(android.CopyOfPaths(l.flagExporter.dirs), l.flagExporter.systemDirs...) {
dir := path.String()
// Skip if dir is for generated headers
if strings.HasPrefix(dir, android.PathForOutput(ctx).String()) {
@@ -452,7 +437,7 @@
}
// Collect generated headers
- for _, header := range append(l.exportedGeneratedHeaders(), l.exportedDeps()...) {
+ for _, header := range append(android.CopyOfPaths(l.flagExporter.headers), l.flagExporter.deps...) {
// TODO(b/148123511): remove exportedDeps after cleaning up genrule
if strings.HasSuffix(header.Base(), "-phony") {
continue
@@ -603,7 +588,7 @@
}
}
}
- if Bool(enabled) || ctx.hasStubsVariants() {
+ if Bool(enabled) || library.hasStubsVariants() {
return "PLATFORM"
}
return ""
@@ -614,7 +599,7 @@
return false
}
if !ctx.isForPlatform() {
- if !ctx.hasStubsVariants() {
+ if !library.hasStubsVariants() {
// Skip ABI checks if this library is for APEX but isn't exported.
return false
}
@@ -632,7 +617,7 @@
func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
if library.buildStubs() {
objs, versionScript := compileStubLibrary(ctx, flags, String(library.Properties.Stubs.Symbol_file), library.MutatedProperties.StubsVersion, "--apex")
- library.versionScriptPath = versionScript
+ library.versionScriptPath = android.OptionalPathForPath(versionScript)
return objs
}
@@ -682,11 +667,12 @@
}
type libraryInterface interface {
- getWholeStaticMissingDeps() []string
+ versionedInterface
+
static() bool
shared() bool
objs() Objects
- reuseObjs() (Objects, exportedFlagsProducer)
+ reuseObjs() Objects
toc() android.OptionalPath
// Returns true if the build options for the module have selected a static or shared build
@@ -703,6 +689,23 @@
availableFor(string) bool
}
+type versionedInterface interface {
+ buildStubs() bool
+ setBuildStubs()
+ hasStubsVariants() bool
+ setStubsVersion(string)
+ stubsVersion() string
+
+ stubsVersions(ctx android.BaseMutatorContext) []string
+ setAllStubsVersions([]string)
+ allStubsVersions() []string
+
+ implementationModuleName(name string) string
+}
+
+var _ libraryInterface = (*libraryDecorator)(nil)
+var _ versionedInterface = (*libraryDecorator)(nil)
+
func (library *libraryDecorator) getLibNameHelper(baseModuleName string, useVndk bool) string {
name := library.libName
if name == "" {
@@ -714,6 +717,7 @@
suffix := ""
if useVndk {
+ // TODO(b/150902910): product variant must use Target.Product
suffix = String(library.Properties.Target.Vendor.Suffix)
}
if suffix == "" {
@@ -810,6 +814,7 @@
deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, library.SharedProperties.Shared.Export_shared_lib_headers...)
deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.SharedProperties.Shared.Export_static_lib_headers...)
}
+ // TODO(b/150902910): product variant must use Target.Product
if ctx.useVndk() {
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, library.baseLinker.Properties.Target.Vendor.Exclude_static_libs)
deps.SharedLibs = removeListFromList(deps.SharedLibs, library.baseLinker.Properties.Target.Vendor.Exclude_shared_libs)
@@ -831,6 +836,13 @@
deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, library.baseLinker.Properties.Target.Ramdisk.Exclude_shared_libs)
deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, library.baseLinker.Properties.Target.Ramdisk.Exclude_static_libs)
}
+ if ctx.inVendorRamdisk() {
+ deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, library.baseLinker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
+ deps.SharedLibs = removeListFromList(deps.SharedLibs, library.baseLinker.Properties.Target.Vendor_ramdisk.Exclude_shared_libs)
+ deps.StaticLibs = removeListFromList(deps.StaticLibs, library.baseLinker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
+ deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, library.baseLinker.Properties.Target.Vendor_ramdisk.Exclude_shared_libs)
+ deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, library.baseLinker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
+ }
return deps
}
@@ -889,10 +901,19 @@
library.coverageOutputFile = TransformCoverageFilesToZip(ctx, library.objects, ctx.ModuleName())
- library.wholeStaticMissingDeps = ctx.GetMissingDependencies()
-
ctx.CheckbuildFile(outputFile)
+ ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
+ StaticLibrary: outputFile,
+ ReuseObjects: library.reuseObjects,
+ Objects: library.objects,
+
+ TransitiveStaticLibrariesForOrdering: android.NewDepSetBuilder(android.TOPOLOGICAL).
+ Direct(outputFile).
+ Transitive(deps.TranstiveStaticLibrariesForOrdering).
+ Build(),
+ })
+
return outputFile
}
@@ -929,15 +950,15 @@
linkerDeps = append(linkerDeps, forceWeakSymbols.Path())
}
}
- if library.buildStubs() {
+ if library.versionScriptPath.Valid() {
linkerScriptFlags := "-Wl,--version-script," + library.versionScriptPath.String()
flags.Local.LdFlags = append(flags.Local.LdFlags, linkerScriptFlags)
- linkerDeps = append(linkerDeps, library.versionScriptPath)
+ linkerDeps = append(linkerDeps, library.versionScriptPath.Path())
}
fileName := library.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
outputFile := android.PathForModuleOut(ctx, fileName)
- ret := outputFile
+ unstrippedOutputFile := outputFile
var implicitOutputs android.WritablePaths
if ctx.Windows() {
@@ -1019,9 +1040,42 @@
objs.sAbiDumpFiles = append(objs.sAbiDumpFiles, deps.WholeStaticLibObjs.sAbiDumpFiles...)
library.coverageOutputFile = TransformCoverageFilesToZip(ctx, objs, library.getLibName(ctx))
- library.linkSAbiDumpFiles(ctx, objs, fileName, ret)
+ library.linkSAbiDumpFiles(ctx, objs, fileName, unstrippedOutputFile)
- return ret
+ var staticAnalogue *StaticLibraryInfo
+ if static := ctx.GetDirectDepsWithTag(staticVariantTag); len(static) > 0 {
+ s := ctx.OtherModuleProvider(static[0], StaticLibraryInfoProvider).(StaticLibraryInfo)
+ staticAnalogue = &s
+ }
+
+ ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
+ TableOfContents: android.OptionalPathForPath(tocFile),
+ SharedLibrary: unstrippedOutputFile,
+ UnstrippedSharedLibrary: library.unstrippedOutputFile,
+ CoverageSharedLibrary: library.coverageOutputFile,
+ StaticAnalogue: staticAnalogue,
+ })
+
+ stubs := ctx.GetDirectDepsWithTag(stubImplDepTag)
+ if len(stubs) > 0 {
+ var stubsInfo []SharedLibraryStubsInfo
+ for _, stub := range stubs {
+ stubInfo := ctx.OtherModuleProvider(stub, SharedLibraryInfoProvider).(SharedLibraryInfo)
+ flagInfo := ctx.OtherModuleProvider(stub, FlagExporterInfoProvider).(FlagExporterInfo)
+ stubsInfo = append(stubsInfo, SharedLibraryStubsInfo{
+ Version: moduleLibraryInterface(stub).stubsVersion(),
+ SharedLibraryInfo: stubInfo,
+ FlagExporterInfo: flagInfo,
+ })
+ }
+ ctx.SetProvider(SharedLibraryImplementationStubsInfoProvider, SharedLibraryImplementationStubsInfo{
+ SharedLibraryStubsInfos: stubsInfo,
+
+ IsLLNDK: ctx.isLlndk(ctx.Config()),
+ })
+ }
+
+ return unstrippedOutputFile
}
func (library *libraryDecorator) unstrippedOutputFilePath() android.Path {
@@ -1155,7 +1209,8 @@
isVendor := ctx.useVndk()
isOwnerPlatform := Bool(library.Properties.Sysprop.Platform)
- if !ctx.inRamdisk() && !ctx.inRecovery() && (isProduct || (isOwnerPlatform == isVendor)) {
+ if !ctx.inRamdisk() && !ctx.inVendorRamdisk() && !ctx.inRecovery() &&
+ (isProduct || (isOwnerPlatform == isVendor)) {
dir = android.PathForModuleGen(ctx, "sysprop/public", "include")
}
}
@@ -1165,10 +1220,12 @@
library.addExportedGeneratedHeaders(library.baseCompiler.pathDeps...)
}
- if library.buildStubs() {
- library.reexportFlags("-D" + versioningMacroName(ctx.ModuleName()) + "=" + library.stubsVersion())
+ if library.buildStubs() && !library.skipAPIDefine {
+ library.reexportFlags("-D" + versioningMacroName(ctx.Module().(*Module).ImplementationModuleName(ctx)) + "=" + library.stubsVersion())
}
+ library.flagExporter.setProvider(ctx)
+
return out
}
@@ -1182,16 +1239,12 @@
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
}
-func (library *libraryDecorator) reuseObjs() (Objects, exportedFlagsProducer) {
- return library.reuseObjects, &library.flagExporter
+func (library *libraryDecorator) reuseObjs() Objects {
+ return library.reuseObjects
}
func (library *libraryDecorator) toc() android.OptionalPath {
@@ -1209,19 +1262,23 @@
func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) {
if library.shared() {
if ctx.Device() && ctx.useVndk() {
- if ctx.isVndkSp() {
- library.baseInstaller.subDir = "vndk-sp"
- } else if ctx.isVndk() {
+ // set subDir for VNDK extensions
+ if ctx.isVndkExt() {
+ if ctx.isVndkSp() {
+ library.baseInstaller.subDir = "vndk-sp"
+ } else {
+ library.baseInstaller.subDir = "vndk"
+ }
+ }
+
+ // In some cases we want to use core variant for VNDK-Core libs
+ if ctx.isVndk() && !ctx.isVndkSp() && !ctx.isVndkExt() {
mayUseCoreVariant := true
if ctx.mustUseVendorVariant() {
mayUseCoreVariant = false
}
- if ctx.isVndkExt() {
- mayUseCoreVariant = false
- }
-
if ctx.Config().CFIEnabledForPath(ctx.ModuleDir()) && ctx.Arch().ArchType == android.Arm64 {
mayUseCoreVariant = false
}
@@ -1232,28 +1289,26 @@
library.useCoreVariant = true
}
}
- library.baseInstaller.subDir = "vndk"
}
- // Append a version to vndk or vndk-sp directories on the system partition.
+ // do not install vndk libs
+ // vndk libs are packaged into VNDK APEX
if ctx.isVndk() && !ctx.isVndkExt() {
- vndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
- if vndkVersion != "current" && vndkVersion != "" {
- library.baseInstaller.subDir += "-" + vndkVersion
- }
+ return
}
- } else if len(library.Properties.Stubs.Versions) > 0 && android.DirectlyInAnyApex(ctx, ctx.ModuleName()) {
+ } else if len(library.Properties.Stubs.Versions) > 0 && !ctx.Host() && ctx.directlyInAnyApex() {
// Bionic libraries (e.g. libc.so) is installed to the bootstrap subdirectory.
// The original path becomes a symlink to the corresponding file in the
// runtime APEX.
translatedArch := ctx.Target().NativeBridge == android.NativeBridgeEnabled
- if InstallToBootstrap(ctx.baseModuleName(), ctx.Config()) && !library.buildStubs() && !translatedArch && !ctx.inRamdisk() && !ctx.inRecovery() {
+ if InstallToBootstrap(ctx.baseModuleName(), ctx.Config()) && !library.buildStubs() &&
+ !translatedArch && !ctx.inRamdisk() && !ctx.inVendorRamdisk() && !ctx.inRecovery() {
if ctx.Device() {
library.installSymlinkToRuntimeApex(ctx, file)
}
library.baseInstaller.subDir = "bootstrap"
}
- } else if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && ctx.isLlndk(ctx.Config()) && !isBionic(ctx.baseModuleName()) {
+ } else if ctx.directlyInAnyApex() && ctx.isLlndk(ctx.Config()) && !isBionic(ctx.baseModuleName()) {
// Skip installing LLNDK (non-bionic) libraries moved to APEX.
ctx.Module().SkipInstall()
}
@@ -1262,7 +1317,7 @@
}
if Bool(library.Properties.Static_ndk_lib) && library.static() &&
- !ctx.useVndk() && !ctx.inRamdisk() && !ctx.inRecovery() && ctx.Device() &&
+ !ctx.useVndk() && !ctx.inRamdisk() && !ctx.inVendorRamdisk() && !ctx.inRecovery() && ctx.Device() &&
library.baseLinker.sanitize.isUnsanitizedVariant() &&
!library.buildStubs() && ctx.sdkVersion() == "" {
installPath := getNdkSysrootBase(ctx).Join(
@@ -1320,6 +1375,10 @@
library.MutatedProperties.BuildStatic = false
}
+func (library *libraryDecorator) implementationModuleName(name string) string {
+ return name
+}
+
func (library *libraryDecorator) buildStubs() bool {
return library.MutatedProperties.BuildStubs
}
@@ -1328,16 +1387,40 @@
if library.Properties.Header_abi_checker.Symbol_file != nil {
return library.Properties.Header_abi_checker.Symbol_file
}
- if ctx.hasStubsVariants() && library.Properties.Stubs.Symbol_file != nil {
+ if library.hasStubsVariants() && library.Properties.Stubs.Symbol_file != nil {
return library.Properties.Stubs.Symbol_file
}
return nil
}
+func (library *libraryDecorator) hasStubsVariants() bool {
+ return len(library.Properties.Stubs.Versions) > 0
+}
+
+func (library *libraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
+ return library.Properties.Stubs.Versions
+}
+
+func (library *libraryDecorator) setStubsVersion(version string) {
+ library.MutatedProperties.StubsVersion = version
+}
+
func (library *libraryDecorator) stubsVersion() string {
return library.MutatedProperties.StubsVersion
}
+func (library *libraryDecorator) setBuildStubs() {
+ library.MutatedProperties.BuildStubs = true
+}
+
+func (library *libraryDecorator) setAllStubsVersions(versions []string) {
+ library.MutatedProperties.AllStubsVersions = versions
+}
+
+func (library *libraryDecorator) allStubsVersions() []string {
+ return library.MutatedProperties.AllStubsVersions
+}
+
func (library *libraryDecorator) isLatestStubVersion() bool {
versions := library.Properties.Stubs.Versions
return versions[len(versions)-1] == library.stubsVersion()
@@ -1403,6 +1486,7 @@
module.compiler = library
module.linker = library
module.installer = library
+ module.library = library
return module, library
}
@@ -1433,10 +1517,10 @@
sharedCompiler.baseCompiler.Properties.Srcs
sharedCompiler.baseCompiler.Properties.Srcs = nil
sharedCompiler.baseCompiler.Properties.Generated_sources = nil
- } else {
- // This dep is just to reference static variant from shared variant
- mctx.AddInterVariantDependency(staticVariantTag, shared, static)
}
+
+ // This dep is just to reference static variant from shared variant
+ mctx.AddInterVariantDependency(staticVariantTag, shared, static)
}
}
@@ -1517,105 +1601,128 @@
}
}
-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(android.CopyOf(versions), "")
- modules := mctx.CreateLocalVariations(versions...)
+ modules := mctx.CreateLocalVariations(variants...)
for i, m := range modules {
- if versions[i] != "" {
- m.(LinkableInterface).SetBuildStubs()
- m.(LinkableInterface).SetStubsVersions(versions[i])
+ if variants[i] != "" {
+ c := m.(*Module)
+ c.Properties.HideFromMake = true
+ c.sanitize = nil
+ c.stl = nil
+ c.Properties.PreventInstall = true
+ lib := moduleLibraryInterface(m)
+ lib.setBuildStubs()
+ lib.setStubsVersion(variants[i])
+ // The implementation depends on the stubs
+ mctx.AddInterVariantDependency(stubImplDepTag, modules[len(modules)-1], modules[i])
}
}
mctx.AliasVariation("")
+ latestVersion := ""
+ if len(versions) > 0 {
+ latestVersion = versions[len(versions)-1]
+ }
+ mctx.CreateAliasVariation("latest", latestVersion)
}
-func VersionVariantAvailable(module interface {
+func createPerApiVersionVariations(mctx android.BottomUpMutatorContext, minSdkVersion string) {
+ from, err := nativeApiLevelFromUser(mctx, minSdkVersion)
+ if err != nil {
+ mctx.PropertyErrorf("min_sdk_version", err.Error())
+ return
+ }
+
+ versionStrs := ndkLibraryVersions(mctx, from)
+ modules := mctx.CreateLocalVariations(versionStrs...)
+
+ for i, module := range modules {
+ module.(*Module).Properties.Sdk_version = StringPtr(versionStrs[i])
+ }
+}
+
+func CanBeOrLinkAgainstVersionVariants(module interface {
Host() bool
InRamdisk() bool
+ InVendorRamdisk() bool
InRecovery() bool
}) bool {
- return !module.Host() && !module.InRamdisk() && !module.InRecovery()
+ return !module.Host() && !module.InRamdisk() && !module.InVendorRamdisk() && !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) {
- 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() {
+func CanBeVersionVariant(module interface {
+ Host() bool
+ InRamdisk() bool
+ InVendorRamdisk() bool
+ InRecovery() bool
+ CcLibraryInterface() bool
+ Shared() bool
+}) bool {
+ return CanBeOrLinkAgainstVersionVariants(module) &&
+ module.CcLibraryInterface() && module.Shared()
+}
+
+func moduleLibraryInterface(module android.Module) libraryInterface {
+ if m, ok := module.(*Module); ok {
+ return m.library
+ }
+ return nil
+}
+
+// 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 := moduleLibraryInterface(mctx.Module()); library != nil && CanBeVersionVariant(mctx.Module().(*Module)) {
+ if library.buildShared() {
+ versions := library.stubsVersions(mctx)
+ if len(versions) > 0 {
+ normalizeVersions(mctx, versions)
+ if mctx.Failed() {
+ return
+ }
+ // 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
}
-
- stubsVersionsLock.Lock()
- defer stubsVersionsLock.Unlock()
- // save the list of versions for later use
- stubsVersionsFor(mctx.Config())[mctx.ModuleName()] = versions
-
- createVersionVariations(mctx, 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
- }
-
- mctx.CreateLocalVariations("")
- mctx.AliasVariation("")
+// 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 := moduleLibraryInterface(mctx.Module()); library != nil && CanBeVersionVariant(mctx.Module().(*Module)) {
+ createVersionVariations(mctx, library.allStubsVersions())
return
}
+
+ if m, ok := mctx.Module().(*Module); ok {
+ if m.SplitPerApiLevel() && m.IsSdkVariant() {
+ if mctx.Os() != android.Android {
+ return
+ }
+ createPerApiVersionVariations(mctx, m.MinSdkVersion())
+ }
+ }
}
// maybeInjectBoringSSLHash adds a rule to run bssl_inject_hash on the output file if the module has the
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index ecfdc99..3f2cf49 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -80,13 +80,12 @@
for _, target := range targets {
name, version := StubsLibNameAndVersion(lib)
if version == "" {
- version = LatestStubsVersionFor(mctx.Config(), name)
+ version = "latest"
}
variations := target.Variations()
if mctx.Device() {
variations = append(variations,
- blueprint.Variation{Mutator: "image", Variation: android.CoreVariation},
- blueprint.Variation{Mutator: "version", Variation: version})
+ blueprint.Variation{Mutator: "image", Variation: android.CoreVariation})
}
if mt.linkTypes == nil {
mctx.AddFarVariationDependencies(variations, dependencyTag, name)
@@ -94,6 +93,10 @@
for _, linkType := range mt.linkTypes {
libVariations := append(variations,
blueprint.Variation{Mutator: "link", Variation: linkType})
+ if mctx.Device() && linkType == "shared" {
+ libVariations = append(libVariations,
+ blueprint.Variation{Mutator: "version", Variation: version})
+ }
mctx.AddFarVariationDependencies(libVariations, dependencyTag, name)
}
}
@@ -127,6 +130,10 @@
pbm.AddProperty("vendor_available", true)
}
+ if proptools.Bool(ccModule.VendorProperties.Product_available) {
+ pbm.AddProperty("product_available", true)
+ }
+
sdkVersion := ccModule.SdkVersion()
if sdkVersion != "" {
pbm.AddProperty("sdk_version", sdkVersion)
@@ -221,10 +228,7 @@
// 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 +299,9 @@
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,31 +372,48 @@
// 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
}
func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
+ addOutputFile := true
ccModule := variant.(*Module)
- // If the library has some link types then it produces an output binary file, otherwise it
- // is header only.
- if !p.memberType.noOutputFiles {
- p.outputFile = getRequiredMemberOutputFile(ctx, ccModule)
+ if s := ccModule.sanitize; s != nil {
+ // We currently do not capture sanitizer flags for libs with sanitizers
+ // enabled, because they may vary among variants that cannot be represented
+ // in the input blueprint files. In particular, sanitizerDepsMutator enables
+ // various sanitizers on dependencies, but in many cases only on static
+ // ones, and we cannot specify sanitizer flags at the link type level (i.e.
+ // in StaticOrSharedProperties).
+ if s.isUnsanitizedVariant() {
+ // This still captures explicitly disabled sanitizers, which may be
+ // necessary to avoid cyclic dependencies.
+ p.Sanitize = s.Properties.Sanitize
+ } else {
+ // Do not add the output file to the snapshot if we don't represent it
+ // properly.
+ addOutputFile = false
+ }
}
+ exportedInfo := ctx.SdkModuleContext().OtherModuleProvider(variant, FlagExporterInfoProvider).(FlagExporterInfo)
+
// Separate out the generated include dirs (which are arch specific) from the
// include dirs (which may not be).
exportedIncludeDirs, exportedGeneratedIncludeDirs := android.FilterPathListPredicate(
- ccModule.ExportedIncludeDirs(), isGeneratedHeaderDirectory)
+ exportedInfo.IncludeDirs, isGeneratedHeaderDirectory)
p.name = variant.Name()
p.archType = ccModule.Target().Arch.ArchType.String()
@@ -403,28 +424,32 @@
// Take a copy before filtering out duplicates to avoid changing the slice owned by the
// ccModule.
- dirs := append(android.Paths(nil), ccModule.ExportedSystemIncludeDirs()...)
+ dirs := append(android.Paths(nil), exportedInfo.SystemIncludeDirs...)
p.ExportedSystemIncludeDirs = android.FirstUniquePaths(dirs)
- p.ExportedFlags = ccModule.ExportedFlags()
+ p.ExportedFlags = exportedInfo.Flags
if ccModule.linker != nil {
specifiedDeps := specifiedDeps{}
specifiedDeps = ccModule.linker.linkerSpecifiedDeps(specifiedDeps)
- if !ccModule.HasStubsVariants() {
- // Propagate dynamic dependencies for implementation libs, but not stubs.
- p.SharedLibs = specifiedDeps.sharedLibs
+ if lib := ccModule.library; lib != nil {
+ if !lib.hasStubsVariants() {
+ // Propagate dynamic dependencies for implementation libs, but not stubs.
+ p.SharedLibs = specifiedDeps.sharedLibs
+ } else {
+ // 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 = lib.allStubsVersions()
+ }
}
p.SystemSharedLibs = specifiedDeps.systemSharedLibs
}
- p.exportedGeneratedHeaders = ccModule.ExportedGeneratedHeaders()
+ p.exportedGeneratedHeaders = exportedInfo.GeneratedHeaders
- if ccModule.HasStubsVariants() {
- p.StubsVersion = ccModule.StubsVersion()
- }
-
- if ccModule.sanitize != nil && proptools.Bool(ccModule.sanitize.Properties.Sanitize.Never) {
- p.SanitizeNever = true
+ if !p.memberType.noOutputFiles && addOutputFile {
+ p.outputFile = getRequiredMemberOutputFile(ctx, ccModule)
}
}
diff --git a/cc/library_test.go b/cc/library_test.go
index cb16725..49838b4 100644
--- a/cc/library_test.go
+++ b/cc/library_test.go
@@ -195,7 +195,7 @@
name: "libfoo",
srcs: ["foo.c"],
stubs: {
- versions: ["29", "R", "10000"],
+ versions: ["29", "R", "current"],
},
}
`
@@ -204,7 +204,7 @@
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 @@
name: "libfoo",
srcs: ["foo.c"],
stubs: {
- versions: ["29", "10000", "R"],
+ versions: ["29", "current", "R"],
},
}
`
@@ -233,10 +233,10 @@
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 4c84163..0609b28 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -14,23 +14,9 @@
OutputFile() android.OptionalPath
CoverageFiles() android.Paths
- IncludeDirs() android.Paths
- SetDepsInLinkOrder([]android.Path)
- GetDepsInLinkOrder() []android.Path
-
- HasStaticVariant() bool
- GetStaticVariant() LinkableInterface
-
NonCcVariants() bool
- StubsVersions() []string
- BuildStubs() bool
- SetBuildStubs()
- SetStubsVersions(string)
- StubsVersion() string
- HasStubsVariants() bool
SelectedStl() string
- ApiLevel() string
BuildStaticVariant() bool
BuildSharedVariant() bool
@@ -45,6 +31,9 @@
InRamdisk() bool
OnlyInRamdisk() bool
+ InVendorRamdisk() bool
+ OnlyInVendorRamdisk() bool
+
InRecovery() bool
OnlyInRecovery() bool
@@ -58,9 +47,7 @@
AlwaysSdk() bool
IsSdkVariant() bool
- ToolchainLibrary() bool
- NdkPrebuiltStl() bool
- StubDecorator() bool
+ SplitPerApiLevel() bool
}
var (
@@ -76,3 +63,58 @@
func StaticDepTag() blueprint.DependencyTag {
return libraryDependencyTag{Kind: staticLibraryDependency}
}
+
+func HeaderDepTag() blueprint.DependencyTag {
+ return libraryDependencyTag{Kind: headerLibraryDependency}
+}
+
+type SharedLibraryInfo struct {
+ SharedLibrary android.Path
+ UnstrippedSharedLibrary android.Path
+
+ TableOfContents android.OptionalPath
+ CoverageSharedLibrary android.OptionalPath
+
+ StaticAnalogue *StaticLibraryInfo
+}
+
+var SharedLibraryInfoProvider = blueprint.NewProvider(SharedLibraryInfo{})
+
+type SharedLibraryImplementationStubsInfo struct {
+ SharedLibraryStubsInfos []SharedLibraryStubsInfo
+
+ IsLLNDK bool
+}
+
+var SharedLibraryImplementationStubsInfoProvider = blueprint.NewProvider(SharedLibraryImplementationStubsInfo{})
+
+type SharedLibraryStubsInfo struct {
+ Version string
+ SharedLibraryInfo SharedLibraryInfo
+ FlagExporterInfo FlagExporterInfo
+}
+
+var SharedLibraryStubsInfoProvider = blueprint.NewProvider(SharedLibraryStubsInfo{})
+
+type StaticLibraryInfo struct {
+ StaticLibrary android.Path
+ Objects Objects
+ ReuseObjects Objects
+
+ // This isn't the actual transitive DepSet, shared library dependencies have been
+ // converted into static library analogues. It is only used to order the static
+ // library dependencies that were specified for the current module.
+ TransitiveStaticLibrariesForOrdering *android.DepSet
+}
+
+var StaticLibraryInfoProvider = blueprint.NewProvider(StaticLibraryInfo{})
+
+type FlagExporterInfo struct {
+ IncludeDirs android.Paths
+ SystemIncludeDirs android.Paths
+ Flags []string
+ Deps android.Paths
+ GeneratedHeaders android.Paths
+}
+
+var FlagExporterInfoProvider = blueprint.NewProvider(FlagExporterInfo{})
diff --git a/cc/linker.go b/cc/linker.go
index 58f8a29..cbf8898 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -96,32 +96,32 @@
Runtime_libs []string `android:"arch_variant"`
Target struct {
- Vendor struct {
- // list of shared libs that only should be used to build the vendor
- // variant of the C/C++ module.
+ Vendor, Product struct {
+ // list of shared libs that only should be used to build vendor or
+ // product variant of the C/C++ module.
Shared_libs []string
- // list of static libs that only should be used to build the vendor
- // variant of the C/C++ module.
+ // list of static libs that only should be used to build vendor or
+ // product variant of the C/C++ module.
Static_libs []string
- // list of shared libs that should not be used to build the vendor variant
- // of the C/C++ module.
+ // list of shared libs that should not be used to build vendor or
+ // product variant of the C/C++ module.
Exclude_shared_libs []string
- // list of static libs that should not be used to build the vendor variant
- // of the C/C++ module.
+ // list of static libs that should not be used to build vendor or
+ // product variant of the C/C++ module.
Exclude_static_libs []string
- // list of header libs that should not be used to build the vendor variant
- // of the C/C++ module.
+ // list of header libs that should not be used to build vendor or
+ // product variant of the C/C++ module.
Exclude_header_libs []string
- // list of runtime libs that should not be installed along with the vendor
- // variant of the C/C++ module.
+ // list of runtime libs that should not be installed along with
+ // vendor or variant of the C/C++ module.
Exclude_runtime_libs []string
- // version script for this vendor variant
+ // version script for vendor or product variant
Version_script *string `android:"arch_variant"`
}
Recovery struct {
@@ -158,6 +158,15 @@
// the ramdisk variant of the C/C++ module.
Exclude_static_libs []string
}
+ Vendor_ramdisk struct {
+ // list of shared libs that should not be used to build
+ // the recovery variant of the C/C++ module.
+ Exclude_shared_libs []string
+
+ // list of static libs that should not be used to build
+ // the vendor ramdisk variant of the C/C++ module.
+ Exclude_static_libs []string
+ }
Platform struct {
// list of shared libs that should be use to build the platform variant
// of a module that sets sdk_version. This should rarely be necessary,
@@ -234,6 +243,7 @@
deps.WholeStaticLibs = append(deps.WholeStaticLibs, "libbuildversion")
}
+ // TODO(b/150902910): product variant must use Target.Product
if ctx.useVndk() {
deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Target.Vendor.Shared_libs...)
deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Vendor.Exclude_shared_libs)
@@ -259,12 +269,20 @@
}
if ctx.inRamdisk() {
- deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Recovery.Exclude_shared_libs)
- deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Recovery.Exclude_shared_libs)
- deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Target.Recovery.Static_libs...)
- deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs)
- deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Recovery.Exclude_static_libs)
- deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs)
+ deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Ramdisk.Exclude_shared_libs)
+ deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Ramdisk.Exclude_shared_libs)
+ deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Target.Ramdisk.Static_libs...)
+ deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Ramdisk.Exclude_static_libs)
+ deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Ramdisk.Exclude_static_libs)
+ deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Ramdisk.Exclude_static_libs)
+ }
+
+ if ctx.inVendorRamdisk() {
+ deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Vendor_ramdisk.Exclude_shared_libs)
+ deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Vendor_ramdisk.Exclude_shared_libs)
+ deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
+ deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
+ deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
}
if !ctx.useSdk() {
@@ -278,19 +296,19 @@
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 +318,12 @@
// 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() {
@@ -462,6 +480,7 @@
versionScript := ctx.ExpandOptionalSource(
linker.Properties.Version_script, "version_script")
+ // TODO(b/150902910): product variant must use Target.Product
if ctx.useVndk() && linker.Properties.Target.Vendor.Version_script != nil {
versionScript = ctx.ExpandOptionalSource(
linker.Properties.Target.Vendor.Version_script,
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index b3f9d61..212720b 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -15,17 +15,14 @@
package cc
import (
+ "fmt"
"path/filepath"
"strings"
"android/soong/android"
-
- "github.com/google/blueprint"
)
-var llndkImplDep = struct {
- blueprint.DependencyTag
-}{}
+var llndkImplDep = dependencyTag{name: "llndk impl"}
var (
llndkLibrarySuffix = ".llndk"
@@ -58,9 +55,11 @@
// Whether the system library uses symbol versions.
Unversioned *bool
- // whether this module can be directly depended upon by libs that are installed to /vendor.
- // When set to false, this module can only be depended on by VNDK libraries, not vendor
- // libraries. This effectively hides this module from vendors. Default value is true.
+ // whether this module can be directly depended upon by libs that are installed
+ // to /vendor and /product.
+ // When set to false, this module can only be depended on by VNDK libraries, not
+ // vendor nor product libraries. This effectively hides this module from
+ // non-system modules. Default value is true.
Vendor_available *bool
// list of llndk headers to re-export include directories from.
@@ -72,10 +71,11 @@
Properties llndkLibraryProperties
- exportHeadersTimestamp android.OptionalPath
- versionScriptPath android.ModuleGenPath
+ movedToApex bool
}
+var _ versionedInterface = (*llndkStubDecorator)(nil)
+
func (stub *llndkStubDecorator) compilerFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags {
flags = stub.baseCompiler.compilerFlags(ctx, flags, deps)
return addStubLibraryCompilerFlags(flags)
@@ -91,7 +91,9 @@
vndkVer = stub.stubsVersion()
}
objs, versionScript := compileStubLibrary(ctx, flags, String(stub.Properties.Symbol_file), vndkVer, "--llndk")
- stub.versionScriptPath = versionScript
+ if !Bool(stub.Properties.Unversioned) {
+ stub.versionScriptPath = android.OptionalPathForPath(versionScript)
+ }
return objs
}
@@ -103,12 +105,14 @@
}
func (stub *llndkStubDecorator) Name(name string) string {
+ if strings.HasSuffix(name, llndkLibrarySuffix) {
+ return name
+ }
return name + llndkLibrarySuffix
}
func (stub *llndkStubDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
- stub.libraryDecorator.libName = strings.TrimSuffix(ctx.ModuleName(),
- llndkLibrarySuffix)
+ stub.libraryDecorator.libName = stub.implementationModuleName(ctx.ModuleName())
return stub.libraryDecorator.linkerFlags(ctx, flags)
}
@@ -135,10 +139,9 @@
func (stub *llndkStubDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps,
objs Objects) android.Path {
- if !Bool(stub.Properties.Unversioned) {
- linkerScriptFlag := "-Wl,--version-script," + stub.versionScriptPath.String()
- flags.Local.LdFlags = append(flags.Local.LdFlags, linkerScriptFlag)
- flags.LdFlagsDeps = append(flags.LdFlagsDeps, stub.versionScriptPath)
+ impl := ctx.GetDirectDepWithTag(stub.implementationModuleName(ctx.ModuleName()), llndkImplDep)
+ if implApexModule, ok := impl.(android.ApexModule); ok {
+ stub.movedToApex = implApexModule.DirectlyInAnyApex()
}
if len(stub.Properties.Export_preprocessed_headers) > 0 {
@@ -163,10 +166,6 @@
stub.libraryDecorator.flagExporter.Properties.Export_include_dirs = []string{}
}
- if stub.stubsVersion() != "" {
- stub.reexportFlags("-D" + versioningMacroName(ctx.baseModuleName()) + "=" + stub.stubsVersion())
- }
-
return stub.libraryDecorator.link(ctx, flags, deps, objs)
}
@@ -174,6 +173,25 @@
return false
}
+func (stub *llndkStubDecorator) implementationModuleName(name string) string {
+ return strings.TrimSuffix(name, llndkLibrarySuffix)
+}
+
+func (stub *llndkStubDecorator) buildStubs() bool {
+ return true
+}
+
+func (stub *llndkStubDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
+ // Get the versions from the implementation module.
+ impls := ctx.GetDirectDepsWithTag(llndkImplDep)
+ if len(impls) > 1 {
+ panic(fmt.Errorf("Expected single implmenetation library, got %d", len(impls)))
+ } else if len(impls) == 1 {
+ return moduleLibraryInterface(impls[0]).allStubsVersions()
+ }
+ return nil
+}
+
func NewLLndkStubLibrary() *Module {
module, library := NewLibrary(android.DeviceSupported)
library.BuildOnlyShared()
@@ -188,6 +206,7 @@
module.compiler = stub
module.linker = stub
module.installer = nil
+ module.library = stub
module.AddProperties(
&module.Properties,
@@ -235,6 +254,7 @@
module.compiler = nil
module.linker = decorator
module.installer = nil
+ module.library = decorator
module.AddProperties(
&module.Properties,
diff --git a/cc/lto.go b/cc/lto.go
index 9868cdf..a3b28d9 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -52,6 +52,9 @@
// 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,15 @@
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()
+ vndk := ctx.isVndk() // b/169217596
+ if !staticLib && !hostBin && !vndk {
+ if !lto.Never() && !lto.FullLTO() {
+ lto.Properties.Lto.Thin = boolPtr(true)
+ }
+ }
}
}
@@ -88,7 +100,7 @@
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 +109,11 @@
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 +126,11 @@
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 +138,31 @@
// 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 +183,11 @@
}
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 +204,19 @@
// 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 fe3efc0..9097e7b 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -16,7 +16,6 @@
import (
"fmt"
- "strconv"
"strings"
"sync"
@@ -52,6 +51,10 @@
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,11 +80,6 @@
// 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
- ApiLevel string `blueprint:"mutated"`
-
// True if this API is not yet ready to be shipped in the NDK. It will be
// available in the platform for testing, but will be excluded from the
// sysroot provided to the NDK proper.
@@ -96,155 +94,68 @@
versionScriptPath android.ModuleGenPath
parsedCoverageXmlPath android.ModuleOutPath
installPath android.Path
+
+ apiLevel android.ApiLevel
+ firstVersion android.ApiLevel
+ unversionedUntil android.ApiLevel
}
-// OMG GO
-func intMax(a int, b int) int {
- if a > b {
- return a
- } else {
- return b
- }
+var _ versionedInterface = (*stubDecorator)(nil)
+
+func shouldUseVersionScript(ctx BaseModuleContext, stub *stubDecorator) bool {
+ return stub.apiLevel.GreaterThanOrEqualTo(stub.unversionedUntil)
}
-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
+func (stub *stubDecorator) implementationModuleName(name string) string {
+ return strings.TrimSuffix(name, ndkLibrarySuffix)
}
-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
+func ndkLibraryVersions(ctx android.BaseMutatorContext, from android.ApiLevel) []string {
+ 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, android.FutureApiLevel.String())
- 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
+ return versionStrs
}
-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())
+func (this *stubDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
+ if !ctx.Module().Enabled() {
+ return nil
+ }
+ firstVersion, err := nativeApiLevelFromUser(ctx,
+ String(this.properties.First_version))
if err != nil {
- ctx.PropertyErrorf(propName, err.Error())
+ ctx.PropertyErrorf("first_version", err.Error())
+ return nil
}
-
- 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))
- }
- versionStrs = append(versionStrs, ctx.Config().PlatformVersionActiveCodenames()...)
- versionStrs = append(versionStrs, "current")
-
- modules := ctx.CreateVariations(versionStrs...)
- for i, module := range modules {
- perSplit(module.(*Module), versionStrs[i])
- }
+ return ndkLibraryVersions(ctx, firstVersion)
}
-func NdkApiMutator(ctx android.BottomUpMutatorContext) {
- if m, ok := ctx.Module().(*Module); ok {
- if m.Enabled() {
- if compiler, ok := m.compiler.(*stubDecorator); ok {
- if ctx.Os() != android.Android {
- // These modules are always android.DeviceEnabled only, but
- // those include Fuchsia devices, which we don't support.
- ctx.Module().Disable()
- return
- }
- generatePerApiVariants(ctx, m, "first_version",
- String(compiler.properties.First_version),
- func(m *Module, version string) {
- m.compiler.(*stubDecorator).properties.ApiLevel =
- version
- })
- } 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
- })
- }
- }
+func (this *stubDecorator) initializeProperties(ctx BaseModuleContext) bool {
+ this.apiLevel = nativeApiLevelOrPanic(ctx, this.stubsVersion())
+
+ 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) {
@@ -340,11 +251,21 @@
ctx.PropertyErrorf("symbol_file", "must end with .map.txt")
}
+ if !c.buildStubs() {
+ // NDK libraries have no implementation variant, nothing to do
+ return Objects{}
+ }
+
+ 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,17 +287,18 @@
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 !stub.buildStubs() {
+ // NDK libraries have no implementation variant, nothing to do
+ return nil
}
- 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)
}
+ stub.libraryDecorator.skipAPIDefine = true
return stub.libraryDecorator.link(ctx, flags, deps, objs)
}
@@ -386,8 +308,6 @@
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 +316,7 @@
}
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)
}
@@ -413,6 +333,7 @@
module.compiler = stub
module.linker = stub
module.installer = stub
+ module.library = stub
module.Properties.AlwaysSdk = true
module.Properties.Sdk_version = StringPtr("current")
diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go
index acdc581..793ab37 100644
--- a/cc/ndk_prebuilt.go
+++ b/cc/ndk_prebuilt.go
@@ -166,7 +166,7 @@
ctx.ModuleErrorf("NDK prebuilt libraries must have an ndk_lib prefixed name")
}
- ndk.exportIncludesAsSystem(ctx)
+ ndk.libraryDecorator.flagExporter.exportIncludesAsSystem(ctx)
libName := strings.TrimPrefix(ctx.ModuleName(), "ndk_")
libExt := flags.Toolchain.ShlibSuffix()
@@ -175,5 +175,23 @@
}
libDir := getNdkStlLibDir(ctx)
- return libDir.Join(ctx, libName+libExt)
+ lib := libDir.Join(ctx, libName+libExt)
+
+ ndk.libraryDecorator.flagExporter.setProvider(ctx)
+
+ if ndk.static() {
+ depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(lib).Build()
+ ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
+ StaticLibrary: lib,
+
+ TransitiveStaticLibrariesForOrdering: depSet,
+ })
+ } else {
+ ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
+ SharedLibrary: lib,
+ UnstrippedSharedLibrary: lib,
+ })
+ }
+
+ return lib
}
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index 56fd54b..70b15c1 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -131,7 +131,7 @@
}
if m, ok := module.(*Module); ok {
- if installer, ok := m.installer.(*stubDecorator); ok {
+ if installer, ok := m.installer.(*stubDecorator); ok && m.library.buildStubs() {
if ctx.Config().ExcludeDraftNdkApis() &&
installer.properties.Draft {
return
diff --git a/cc/ndkstubgen/__init__.py b/cc/ndkstubgen/__init__.py
index 2f4326a..86bf6ff 100755
--- a/cc/ndkstubgen/__init__.py
+++ b/cc/ndkstubgen/__init__.py
@@ -20,13 +20,16 @@
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 @@
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 @@
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 @@
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 0000000..82aa7eb
--- /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 70bcf78..6d2c9d6 100755
--- a/cc/ndkstubgen/test_ndkstubgen.py
+++ b/cc/ndkstubgen/test_ndkstubgen.py
@@ -21,19 +21,20 @@
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 @@
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 IntegrationTest(unittest.TestCase):
- def test_integration(self):
+ def test_integration(self) -> None:
api_map = {
'O': 9000,
'P': 9001,
@@ -178,14 +180,14 @@
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 @@
""")
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 @@
*;
};
"""))
- 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 @@
""")
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 @@
} 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 @@
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 @@
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 @@
""")
self.assertEqual(expected_version, version_file.getvalue())
-def main():
+
+def main() -> None:
suite = unittest.TestLoader().loadTestsFromName(__name__)
unittest.TextTestRunner(verbosity=3).run(suite)
diff --git a/cc/object.go b/cc/object.go
index 778d131..ab2672b 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -96,11 +96,6 @@
func (*objectLinker) linkerInit(ctx BaseModuleContext) {}
func (object *objectLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
- if ctx.useVndk() && ctx.toolchain().Bionic() {
- // Needed for VNDK builds where bionic headers aren't automatically added.
- deps.LateSharedLibs = append(deps.LateSharedLibs, "libc")
- }
-
deps.HeaderLibs = append(deps.HeaderLibs, object.Properties.Header_libs...)
deps.ObjFiles = append(deps.ObjFiles, object.Properties.Objs...)
return deps
diff --git a/cc/pgo.go b/cc/pgo.go
index 6bf0ad0..3cf550a 100644
--- a/cc/pgo.go
+++ b/cc/pgo.go
@@ -41,7 +41,6 @@
var pgoProfileProjectsConfigKey = android.NewOnceKey("PgoProfileProjects")
const profileInstrumentFlag = "-fprofile-generate=/data/local/tmp"
-const profileSamplingFlag = "-gmlt -fdebug-info-for-profiling"
const profileUseInstrumentFormat = "-fprofile-use=%s"
const profileUseSamplingFormat = "-fprofile-sample-accurate -fprofile-sample-use=%s"
@@ -70,6 +69,7 @@
PgoPresent bool `blueprint:"mutated"`
ShouldProfileModule bool `blueprint:"mutated"`
PgoCompile bool `blueprint:"mutated"`
+ PgoInstrLink bool `blueprint:"mutated"`
}
type pgo struct {
@@ -89,20 +89,16 @@
}
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 {
flags.Local.CFlags = append(flags.Local.CFlags, props.Pgo.Cflags...)
-
- flags.Local.CFlags = append(flags.Local.CFlags, profileSamplingFlag)
- flags.Local.LdFlags = append(flags.Local.LdFlags, profileSamplingFlag)
return flags
}
@@ -250,10 +246,12 @@
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 +284,42 @@
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 1ee096e..8873883 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "path/filepath"
)
func init() {
@@ -37,10 +38,11 @@
}
type prebuiltLinkerProperties struct {
-
// a prebuilt library or binary. Can reference a genrule module that generates an executable file.
Srcs []string `android:"path,arch_variant"`
+ Sanitized Sanitized `android:"arch_variant"`
+
// Check the prebuilt ELF files (e.g. DT_SONAME, DT_NEEDED, resolution of undefined
// symbols, etc), default true.
Check_elf_files *bool
@@ -96,15 +98,17 @@
func (p *prebuiltLibraryLinker) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
- p.libraryDecorator.exportIncludes(ctx)
- p.libraryDecorator.reexportDirs(deps.ReexportedDirs...)
- p.libraryDecorator.reexportSystemDirs(deps.ReexportedSystemDirs...)
- p.libraryDecorator.reexportFlags(deps.ReexportedFlags...)
- p.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
- p.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
+ p.libraryDecorator.flagExporter.exportIncludes(ctx)
+ p.libraryDecorator.flagExporter.reexportDirs(deps.ReexportedDirs...)
+ p.libraryDecorator.flagExporter.reexportSystemDirs(deps.ReexportedSystemDirs...)
+ p.libraryDecorator.flagExporter.reexportFlags(deps.ReexportedFlags...)
+ p.libraryDecorator.flagExporter.reexportDeps(deps.ReexportedDeps...)
+ p.libraryDecorator.flagExporter.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
+
+ p.libraryDecorator.flagExporter.setProvider(ctx)
// TODO(ccross): verify shared library dependencies
- srcs := p.prebuiltSrcs()
+ srcs := p.prebuiltSrcs(ctx)
if len(srcs) > 0 {
builderFlags := flagsToBuilderFlags(flags)
@@ -116,6 +120,12 @@
in := android.PathForModuleSrc(ctx, srcs[0])
if p.static() {
+ depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(in).Build()
+ ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
+ StaticLibrary: in,
+
+ TransitiveStaticLibrariesForOrdering: depSet,
+ })
return in
}
@@ -169,6 +179,13 @@
},
})
+ ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
+ SharedLibrary: outputFile,
+ UnstrippedSharedLibrary: p.unstrippedOutputFile,
+
+ TableOfContents: p.tocFile,
+ })
+
return outputFile
}
}
@@ -176,15 +193,18 @@
return nil
}
-func (p *prebuiltLibraryLinker) prebuiltSrcs() []string {
+func (p *prebuiltLibraryLinker) prebuiltSrcs(ctx android.BaseModuleContext) []string {
+ sanitize := ctx.Module().(*Module).sanitize
srcs := p.properties.Srcs
+ srcs = append(srcs, srcsForSanitizer(sanitize, p.properties.Sanitized)...)
if p.static() {
srcs = append(srcs, p.libraryDecorator.StaticProperties.Static.Srcs...)
+ srcs = append(srcs, srcsForSanitizer(sanitize, p.libraryDecorator.StaticProperties.Static.Sanitized)...)
}
if p.shared() {
srcs = append(srcs, p.libraryDecorator.SharedProperties.Shared.Srcs...)
+ srcs = append(srcs, srcsForSanitizer(sanitize, p.libraryDecorator.SharedProperties.Shared.Sanitized)...)
}
-
return srcs
}
@@ -208,11 +228,12 @@
libraryDecorator: library,
}
module.linker = prebuilt
+ module.library = prebuilt
module.AddProperties(&prebuilt.properties)
- srcsSupplier := func() []string {
- return prebuilt.prebuiltSrcs()
+ srcsSupplier := func(ctx android.BaseModuleContext) []string {
+ return prebuilt.prebuiltSrcs(ctx)
}
android.InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs")
@@ -360,13 +381,18 @@
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,
},
})
@@ -419,3 +445,28 @@
android.InitPrebuiltModule(module, &prebuilt.properties.Srcs)
return module, binary
}
+
+type Sanitized struct {
+ None struct {
+ Srcs []string `android:"path,arch_variant"`
+ } `android:"arch_variant"`
+ Address struct {
+ Srcs []string `android:"path,arch_variant"`
+ } `android:"arch_variant"`
+ Hwaddress struct {
+ Srcs []string `android:"path,arch_variant"`
+ } `android:"arch_variant"`
+}
+
+func srcsForSanitizer(sanitize *sanitize, sanitized Sanitized) []string {
+ if sanitize == nil {
+ return nil
+ }
+ if Bool(sanitize.Properties.Sanitize.Address) && sanitized.Address.Srcs != nil {
+ return sanitized.Address.Srcs
+ }
+ if Bool(sanitize.Properties.Sanitize.Hwaddress) && sanitized.Hwaddress.Srcs != nil {
+ return sanitized.Hwaddress.Srcs
+ }
+ return sanitized.None.Srcs
+}
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index 52416ac..5bf334e 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -23,9 +23,9 @@
"github.com/google/blueprint"
)
-func testPrebuilt(t *testing.T, bp string, fs map[string][]byte) *android.TestContext {
+func testPrebuilt(t *testing.T, bp string, fs map[string][]byte, handlers ...configCustomizer) *android.TestContext {
config := TestConfig(buildDir, android.Android, nil, bp, fs)
- ctx := CreateTestContext()
+ ctx := CreateTestContext(config)
// Enable androidmk support.
// * Register the singleton
@@ -34,7 +34,11 @@
android.RegisterAndroidMkBuildComponents(ctx)
android.SetInMakeForTests(config)
- ctx.Register(config)
+ for _, handler := range handlers {
+ handler(config)
+ }
+
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
@@ -42,6 +46,8 @@
return ctx
}
+type configCustomizer func(config android.Config)
+
func TestPrebuilt(t *testing.T) {
bp := `
cc_library {
@@ -321,3 +327,62 @@
assertString(t, libfooDep.String(),
filepath.Join(buildDir, ".intermediates/libfoo/linux_glibc_x86_64_shared/libfoo.so"))
}
+
+func TestPrebuiltLibrarySanitized(t *testing.T) {
+ bp := `cc_prebuilt_library {
+ name: "libtest",
+ static: {
+ sanitized: { none: { srcs: ["libf.a"], }, hwaddress: { srcs: ["libf.hwasan.a"], }, },
+ },
+ shared: {
+ sanitized: { none: { srcs: ["libf.so"], }, hwaddress: { srcs: ["hwasan/libf.so"], }, },
+ },
+ }
+ cc_prebuilt_library_static {
+ name: "libtest_static",
+ sanitized: { none: { srcs: ["libf.a"], }, hwaddress: { srcs: ["libf.hwasan.a"], }, },
+ }
+ cc_prebuilt_library_shared {
+ name: "libtest_shared",
+ sanitized: { none: { srcs: ["libf.so"], }, hwaddress: { srcs: ["hwasan/libf.so"], }, },
+ }`
+
+ fs := map[string][]byte{
+ "libf.a": nil,
+ "libf.hwasan.a": nil,
+ "libf.so": nil,
+ "hwasan/libf.so": nil,
+ }
+
+ // Without SANITIZE_TARGET.
+ ctx := testPrebuilt(t, bp, fs)
+
+ shared_rule := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip")
+ assertString(t, shared_rule.Input.String(), "libf.so")
+
+ static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
+ assertString(t, static.OutputFile().Path().Base(), "libf.a")
+
+ shared_rule2 := ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip")
+ assertString(t, shared_rule2.Input.String(), "libf.so")
+
+ static2 := ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static").Module().(*Module)
+ assertString(t, static2.OutputFile().Path().Base(), "libf.a")
+
+ // With SANITIZE_TARGET=hwaddress
+ ctx = testPrebuilt(t, bp, fs, func(config android.Config) {
+ config.TestProductVariables.SanitizeDevice = []string{"hwaddress"}
+ })
+
+ shared_rule = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip")
+ assertString(t, shared_rule.Input.String(), "hwasan/libf.so")
+
+ static = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
+ assertString(t, static.OutputFile().Path().Base(), "libf.hwasan.a")
+
+ shared_rule2 = ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip")
+ assertString(t, shared_rule2.Input.String(), "hwasan/libf.so")
+
+ static2 = ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
+ assertString(t, static2.OutputFile().Path().Base(), "libf.hwasan.a")
+}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 174dcfe..b1326d9 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -139,56 +139,59 @@
return t == asan || t == fuzzer || t == hwasan
}
-type SanitizeProperties struct {
- // enable AddressSanitizer, ThreadSanitizer, or UndefinedBehaviorSanitizer
- Sanitize struct {
- Never *bool `android:"arch_variant"`
+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"`
+ // main sanitizers
+ Address *bool `android:"arch_variant"`
+ Thread *bool `android:"arch_variant"`
+ Hwaddress *bool `android:"arch_variant"`
- // local sanitizers
+ // 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"`
+ Misc_undefined []string `android:"arch_variant"`
+ No_recover []string
+ }
- // A modifier for ASAN and HWASAN for write only instrumentation
- Writeonly *bool `android:"arch_variant"`
+ // value to pass to -fsanitize-recover=
+ Recover []string
- // 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
- }
+ // value to pass to -fsanitize-blacklist
+ Blocklist *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"`
+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 {
@@ -373,8 +376,8 @@
}
// HWASan ramdisk (which is built from recovery) goes over some bootloader limit.
- // Keep libc instrumented so that ramdisk / recovery can run hwasan-instrumented code if necessary.
- if (ctx.inRamdisk() || ctx.inRecovery()) && !strings.HasPrefix(ctx.ModuleDir(), "bionic/libc") {
+ // Keep libc instrumented so that ramdisk / vendor_ramdisk / recovery can run hwasan-instrumented code if necessary.
+ if (ctx.inRamdisk() || ctx.inVendorRamdisk() || ctx.inRecovery()) && !strings.HasPrefix(ctx.ModuleDir(), "bionic/libc") {
s.Hwaddress = nil
}
@@ -1037,7 +1040,7 @@
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
diff --git a/cc/sdk.go b/cc/sdk.go
index b68baad..ec57f06 100644
--- a/cc/sdk.go
+++ b/cc/sdk.go
@@ -32,11 +32,11 @@
switch m := ctx.Module().(type) {
case LinkableInterface:
if m.AlwaysSdk() {
- if !m.UseSdk() {
+ if !m.UseSdk() && !m.SplitPerApiLevel() {
ctx.ModuleErrorf("UseSdk() must return true when AlwaysSdk is set, did the factory forget to set Sdk_version?")
}
ctx.CreateVariations("sdk")
- } else if m.UseSdk() {
+ } else if m.UseSdk() || m.SplitPerApiLevel() {
modules := ctx.CreateVariations("", "sdk")
modules[0].(*Module).Properties.Sdk_version = nil
modules[1].(*Module).Properties.IsSdkVariant = true
diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go
index f27d166..05c06ac 100644
--- a/cc/snapshot_utils.go
+++ b/cc/snapshot_utils.go
@@ -22,7 +22,6 @@
)
type snapshotLibraryInterface interface {
- exportedFlagsProducer
libraryInterface
collectHeadersForSnapshot(ctx android.ModuleContext)
snapshotHeaders() android.Paths
@@ -58,10 +57,10 @@
return snapshot, found
}
-func isSnapshotAware(ctx android.ModuleContext, m *Module) bool {
- if _, _, ok := isVndkSnapshotLibrary(ctx.DeviceConfig(), m); ok {
+func isSnapshotAware(ctx android.ModuleContext, m *Module, apexInfo android.ApexInfo) bool {
+ if _, _, ok := isVndkSnapshotLibrary(ctx.DeviceConfig(), m, apexInfo); ok {
return ctx.Config().VndkSnapshotBuildArtifacts()
- } else if isVendorSnapshotModule(m, isVendorProprietaryPath(ctx.ModuleDir())) {
+ } else if isVendorSnapshotModule(m, isVendorProprietaryPath(ctx.ModuleDir()), apexInfo) {
return true
}
return false
@@ -94,13 +93,6 @@
func writeStringToFile(ctx android.SingletonContext, content, out string) android.OutputPath {
outPath := android.PathForOutput(ctx, out)
- ctx.Build(pctx, android.BuildParams{
- Rule: android.WriteFile,
- Output: outPath,
- Description: "WriteFile " + out,
- Args: map[string]string{
- "content": content,
- },
- })
+ android.WriteFileRule(ctx, outPath, content)
return outPath
}
diff --git a/cc/stl.go b/cc/stl.go
index e18fe95..406fa3a 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -17,7 +17,6 @@
import (
"android/soong/android"
"fmt"
- "strconv"
)
func getNdkStlFamily(m LinkableInterface) string {
@@ -136,23 +135,8 @@
}
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 faa3823..5678e7d 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
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 @@
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 @@
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 0000000..82aa7eb
--- /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 c91131f..92b1399 100644
--- a/cc/symbolfile/test_symbolfile.py
+++ b/cc/symbolfile/test_symbolfile.py
@@ -19,12 +19,13 @@
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 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 SymbolPresenceTest(unittest.TestCase):
- def test_symbol_in_arch(self):
- self.assertTrue(symbolfile.symbol_in_arch([], 'arm'))
- self.assertTrue(symbolfile.symbol_in_arch(['arm'], 'arm'))
+ 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(['x86'], 'arm'))
+ self.assertFalse(symbolfile.symbol_in_arch([Tag('x86')], Arch('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))
+ 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(['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))
+ 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))
-
- self.assertTrue(
- symbolfile.should_omit_version(
- symbolfile.Version('foo', None, ['platform-only'], []), 'arm',
+ symbolfile.Version('foo_PLATFORM', None, [], []), Arch('arm'),
9, False, False))
- def test_omit_llndk(self):
self.assertTrue(
symbolfile.should_omit_version(
- symbolfile.Version('foo', None, ['llndk'], []), 'arm', 9,
- False, False))
+ symbolfile.Version('foo', None, [Tag('platform-only')], []),
+ Arch('arm'), 9, False, False))
- self.assertFalse(
- symbolfile.should_omit_version(
- symbolfile.Version('foo', None, [], []), 'arm', 9, True,
- False))
- self.assertFalse(
- symbolfile.should_omit_version(
- symbolfile.Version('foo', None, ['llndk'], []), 'arm', 9, True,
- False))
-
- def test_omit_apex(self):
+ def test_omit_llndk(self) -> None:
self.assertTrue(
symbolfile.should_omit_version(
- symbolfile.Version('foo', None, ['apex'], []), '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, False,
+ symbolfile.Version('foo', None, [], []), Arch('arm'), 9, True,
+ False))
+ self.assertFalse(
+ symbolfile.should_omit_version(
+ symbolfile.Version('foo', None, [Tag('llndk')], []),
+ Arch('arm'), 9, True, False))
+
+ def test_omit_apex(self) -> None:
+ self.assertTrue(
+ symbolfile.should_omit_version(
+ symbolfile.Version('foo', None, [Tag('apex')], []),
+ Arch('arm'), 9, False, False))
+
+ self.assertFalse(
+ symbolfile.should_omit_version(
+ 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))
-
- self.assertTrue(
- symbolfile.should_omit_version(
- symbolfile.Version('foo', None, ['x86'], []), 'arm', 9, False,
- False))
-
- def test_omit_api(self):
- self.assertFalse(
- symbolfile.should_omit_version(
- symbolfile.Version('foo', None, [], []), 'arm', 9, False,
- False))
- self.assertFalse(
- symbolfile.should_omit_version(
- symbolfile.Version('foo', None, ['introduced=9'], []), 'arm',
+ symbolfile.Version('foo', None, [Tag('arm')], []), Arch('arm'),
9, False, False))
self.assertTrue(
symbolfile.should_omit_version(
- symbolfile.Version('foo', None, ['introduced=14'], []), 'arm',
+ symbolfile.Version('foo', None, [Tag('x86')], []), Arch('arm'),
9, False, False))
+ def test_omit_api(self) -> None:
+ self.assertFalse(
+ symbolfile.should_omit_version(
+ symbolfile.Version('foo', None, [], []), Arch('arm'), 9, False,
+ False))
+ self.assertFalse(
+ symbolfile.should_omit_version(
+ symbolfile.Version('foo', None, [Tag('introduced=9')], []),
+ Arch('arm'), 9, False, False))
+
+ self.assertTrue(
+ symbolfile.should_omit_version(
+ 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))
- self.assertFalse(
- symbolfile.should_omit_symbol(symbolfile.Symbol('foo', ['llndk']),
- 'arm', 9, True, False))
-
- def test_omit_apex(self):
- self.assertTrue(
- symbolfile.should_omit_symbol(symbolfile.Symbol('foo', ['apex']),
- 'arm', 9, False, False))
-
- self.assertFalse(
- symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []), 'arm',
- 9, False, True))
- self.assertFalse(
- symbolfile.should_omit_symbol(symbolfile.Symbol('foo', ['apex']),
- 'arm', 9, False, True))
-
- def test_omit_arch(self):
- self.assertFalse(
- symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []), 'arm',
- 9, False, False))
- self.assertFalse(
- symbolfile.should_omit_symbol(symbolfile.Symbol('foo', ['arm']),
- 'arm', 9, False, False))
-
- self.assertTrue(
- symbolfile.should_omit_symbol(symbolfile.Symbol('foo', ['x86']),
- 'arm', 9, False, False))
-
- def test_omit_api(self):
- self.assertFalse(
- symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []), 'arm',
- 9, False, False))
+ symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []),
+ Arch('arm'), 9, True, False))
self.assertFalse(
symbolfile.should_omit_symbol(
- symbolfile.Symbol('foo', ['introduced=9']), 'arm', 9, False,
+ symbolfile.Symbol('foo', [Tag('llndk')]), Arch('arm'), 9, True,
+ False))
+
+ def test_omit_apex(self) -> None:
+ self.assertTrue(
+ symbolfile.should_omit_symbol(
+ symbolfile.Symbol('foo', [Tag('apex')]), Arch('arm'), 9, False,
+ False))
+
+ self.assertFalse(
+ symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []),
+ Arch('arm'), 9, False, True))
+ self.assertFalse(
+ symbolfile.should_omit_symbol(
+ symbolfile.Symbol('foo', [Tag('apex')]), Arch('arm'), 9, False,
+ True))
+
+ def test_omit_arch(self) -> None:
+ self.assertFalse(
+ symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []),
+ Arch('arm'), 9, False, False))
+ self.assertFalse(
+ symbolfile.should_omit_symbol(
+ symbolfile.Symbol('foo', [Tag('arm')]), Arch('arm'), 9, False,
False))
self.assertTrue(
symbolfile.should_omit_symbol(
- symbolfile.Symbol('foo', ['introduced=14']), 'arm', 9, False,
+ symbolfile.Symbol('foo', [Tag('x86')]), Arch('arm'), 9, False,
False))
+ def test_omit_api(self) -> None:
+ self.assertFalse(
+ symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []),
+ Arch('arm'), 9, False, False))
+ self.assertFalse(
+ symbolfile.should_omit_symbol(
+ symbolfile.Symbol('foo', [Tag('introduced=9')]), Arch('arm'),
+ 9, False, False))
+
+ self.assertTrue(
+ symbolfile.should_omit_symbol(
+ 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 @@
# 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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/cc/test_data_test.go b/cc/test_data_test.go
index ae59e2f..426dfc5 100644
--- a/cc/test_data_test.go
+++ b/cc/test_data_test.go
@@ -122,10 +122,10 @@
"dir/baz": nil,
"dir/bar/baz": nil,
})
- ctx := android.NewTestContext()
+ ctx := android.NewTestContext(config)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("test", newTest)
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseBlueprintsFiles("Blueprints")
android.FailIfErrored(t, errs)
diff --git a/cc/testing.go b/cc/testing.go
index 52f0829..5a311f4 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -40,6 +40,7 @@
name: "libatomic",
defaults: ["linux_bionic_supported"],
vendor_available: true,
+ product_available: true,
recovery_available: true,
native_bridge_supported: true,
src: "",
@@ -48,6 +49,7 @@
toolchain_library {
name: "libcompiler_rt-extras",
vendor_available: true,
+ product_available: true,
recovery_available: true,
src: "",
}
@@ -55,6 +57,7 @@
toolchain_library {
name: "libclang_rt.builtins-arm-android",
vendor_available: true,
+ product_available: true,
recovery_available: true,
native_bridge_supported: true,
src: "",
@@ -63,6 +66,7 @@
toolchain_library {
name: "libclang_rt.builtins-aarch64-android",
vendor_available: true,
+ product_available: true,
recovery_available: true,
native_bridge_supported: true,
src: "",
@@ -72,6 +76,7 @@
name: "libclang_rt.hwasan-aarch64-android",
nocrt: true,
vendor_available: true,
+ product_available: true,
recovery_available: true,
system_shared_libs: [],
stl: "none",
@@ -85,6 +90,7 @@
toolchain_library {
name: "libclang_rt.builtins-i686-android",
vendor_available: true,
+ product_available: true,
recovery_available: true,
native_bridge_supported: true,
src: "",
@@ -94,6 +100,7 @@
name: "libclang_rt.builtins-x86_64-android",
defaults: ["linux_bionic_supported"],
vendor_available: true,
+ product_available: true,
recovery_available: true,
native_bridge_supported: true,
src: "",
@@ -102,6 +109,7 @@
toolchain_library {
name: "libclang_rt.fuzzer-arm-android",
vendor_available: true,
+ product_available: true,
recovery_available: true,
src: "",
}
@@ -109,6 +117,7 @@
toolchain_library {
name: "libclang_rt.fuzzer-aarch64-android",
vendor_available: true,
+ product_available: true,
recovery_available: true,
src: "",
}
@@ -116,6 +125,7 @@
toolchain_library {
name: "libclang_rt.fuzzer-i686-android",
vendor_available: true,
+ product_available: true,
recovery_available: true,
src: "",
}
@@ -124,6 +134,7 @@
name: "libclang_rt.fuzzer-x86_64-android",
defaults: ["linux_bionic_supported"],
vendor_available: true,
+ product_available: true,
recovery_available: true,
src: "",
}
@@ -131,6 +142,7 @@
toolchain_library {
name: "libclang_rt.fuzzer-x86_64",
vendor_available: true,
+ product_available: true,
recovery_available: true,
src: "",
}
@@ -139,6 +151,7 @@
cc_prebuilt_library_shared {
name: "libclang_rt.ubsan_standalone-aarch64-android",
vendor_available: true,
+ product_available: true,
recovery_available: true,
system_shared_libs: [],
srcs: [""],
@@ -148,6 +161,7 @@
name: "libgcc",
defaults: ["linux_bionic_supported"],
vendor_available: true,
+ product_available: true,
recovery_available: true,
src: "",
}
@@ -156,6 +170,7 @@
name: "libgcc_stripped",
defaults: ["linux_bionic_supported"],
vendor_available: true,
+ product_available: true,
recovery_available: true,
sdk_version: "current",
src: "",
@@ -172,9 +187,10 @@
stubs: {
versions: ["27", "28", "29"],
},
+ llndk_stubs: "libc.llndk",
}
llndk_library {
- name: "libc",
+ name: "libc.llndk",
symbol_file: "",
sdk_version: "current",
}
@@ -193,9 +209,10 @@
"//apex_available:platform",
"myapex"
],
+ llndk_stubs: "libm.llndk",
}
llndk_library {
- name: "libm",
+ name: "libm.llndk",
symbol_file: "",
sdk_version: "current",
}
@@ -204,6 +221,7 @@
cc_library {
name: "libprofile-extras",
vendor_available: true,
+ product_available: true,
recovery_available: true,
native_coverage: false,
system_shared_libs: [],
@@ -213,6 +231,7 @@
cc_library {
name: "libprofile-clang-extras",
vendor_available: true,
+ product_available: true,
recovery_available: true,
native_coverage: false,
system_shared_libs: [],
@@ -222,6 +241,7 @@
cc_library {
name: "libprofile-extras_ndk",
vendor_available: true,
+ product_available: true,
native_coverage: false,
system_shared_libs: [],
stl: "none",
@@ -231,6 +251,7 @@
cc_library {
name: "libprofile-clang-extras_ndk",
vendor_available: true,
+ product_available: true,
native_coverage: false,
system_shared_libs: [],
stl: "none",
@@ -253,9 +274,10 @@
"//apex_available:platform",
"myapex"
],
+ llndk_stubs: "libdl.llndk",
}
llndk_library {
- name: "libdl",
+ name: "libdl.llndk",
symbol_file: "",
sdk_version: "current",
}
@@ -265,9 +287,10 @@
nocrt: true,
system_shared_libs: [],
recovery_available: true,
+ llndk_stubs: "libft2.llndk",
}
llndk_library {
- name: "libft2",
+ name: "libft2.llndk",
symbol_file: "",
vendor_available: false,
sdk_version: "current",
@@ -279,6 +302,7 @@
system_shared_libs: [],
stl: "none",
vendor_available: true,
+ product_available: true,
recovery_available: true,
host_supported: true,
min_sdk_version: "29",
@@ -294,6 +318,7 @@
system_shared_libs: [],
stl: "none",
vendor_available: true,
+ product_available: true,
recovery_available: true,
host_supported: true,
min_sdk_version: "29",
@@ -314,6 +339,7 @@
stl: "none",
host_supported: false,
vendor_available: true,
+ product_available: true,
recovery_available: true,
min_sdk_version: "29",
apex_available: [
@@ -328,6 +354,7 @@
system_shared_libs: [],
stl: "none",
vendor_available: true,
+ product_available: true,
recovery_available: true,
}
@@ -336,6 +363,7 @@
defaults: ["linux_bionic_supported"],
recovery_available: true,
vendor_available: true,
+ product_available: true,
native_bridge_supported: true,
stl: "none",
min_sdk_version: "16",
@@ -517,8 +545,8 @@
return config
}
-func CreateTestContext() *android.TestContext {
- ctx := android.NewTestArchContext()
+func CreateTestContext(config android.Config) *android.TestContext {
+ ctx := android.NewTestArchContext(config)
ctx.RegisterModuleType("cc_fuzz", FuzzFactory)
ctx.RegisterModuleType("cc_test", TestFactory)
ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
diff --git a/cc/toolchain_library.go b/cc/toolchain_library.go
index 19f5ea4..0c934ad 100644
--- a/cc/toolchain_library.go
+++ b/cc/toolchain_library.go
@@ -66,6 +66,7 @@
module.stl = nil
module.sanitize = nil
module.installer = nil
+ module.library = toolchainLibrary
module.Properties.Sdk_version = StringPtr("current")
return module.Init()
}
@@ -84,24 +85,31 @@
}
srcPath := android.PathForSource(ctx, *library.Properties.Src)
-
- if library.stripper.StripProperties.Strip.Keep_symbols_list != nil {
- fileName := ctx.ModuleName() + staticLibraryExtension
- outputFile := android.PathForModuleOut(ctx, fileName)
- stripFlags := flagsToStripFlags(flags)
- library.stripper.StripStaticLib(ctx, srcPath, outputFile, stripFlags)
- return outputFile
- }
+ outputFile := android.Path(srcPath)
if library.Properties.Repack_objects_to_keep != nil {
fileName := ctx.ModuleName() + staticLibraryExtension
- outputFile := android.PathForModuleOut(ctx, fileName)
- TransformArchiveRepack(ctx, srcPath, outputFile, library.Properties.Repack_objects_to_keep)
-
- return outputFile
+ repackedPath := android.PathForModuleOut(ctx, fileName)
+ TransformArchiveRepack(ctx, outputFile, repackedPath, library.Properties.Repack_objects_to_keep)
+ outputFile = repackedPath
}
- return srcPath
+ if library.stripper.StripProperties.Strip.Keep_symbols_list != nil {
+ fileName := ctx.ModuleName() + staticLibraryExtension
+ strippedPath := android.PathForModuleOut(ctx, fileName)
+ stripFlags := flagsToStripFlags(flags)
+ library.stripper.StripStaticLib(ctx, outputFile, strippedPath, stripFlags)
+ outputFile = strippedPath
+ }
+
+ depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(outputFile).Build()
+ ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
+ StaticLibrary: outputFile,
+
+ TransitiveStaticLibrariesForOrdering: depSet,
+ })
+
+ return outputFile
}
func (library *toolchainLibraryDecorator) nativeCoverage() bool {
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 2819f49..78bde38 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -223,8 +223,26 @@
tocFile := android.PathForModuleOut(ctx, libName+".toc")
p.tocFile = android.OptionalPathForPath(tocFile)
TransformSharedObjectToToc(ctx, in, tocFile, builderFlags)
+
+ ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
+ SharedLibrary: in,
+ UnstrippedSharedLibrary: p.unstrippedOutputFile,
+
+ TableOfContents: p.tocFile,
+ })
}
+ if p.static() {
+ depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(in).Build()
+ ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
+ StaticLibrary: in,
+
+ TransitiveStaticLibrariesForOrdering: depSet,
+ })
+ }
+
+ p.libraryDecorator.flagExporter.setProvider(ctx)
+
return in
}
@@ -537,7 +555,7 @@
// AOSP. They are not guaranteed to be compatible with older vendor images. (e.g. might
// depend on newer VNDK) So they are captured as vendor snapshot To build older vendor
// image and newer system image altogether.
-func isVendorSnapshotModule(m *Module, inVendorProprietaryPath bool) bool {
+func isVendorSnapshotModule(m *Module, inVendorProprietaryPath bool, apexInfo android.ApexInfo) bool {
if !m.Enabled() || m.Properties.HideFromMake {
return false
}
@@ -562,7 +580,7 @@
return false
}
// the module must be installed in /vendor
- if !m.IsForPlatform() || m.isSnapshotPrebuilt() || !m.inVendor() {
+ if !apexInfo.IsForPlatform() || m.isSnapshotPrebuilt() || !m.inVendor() {
return false
}
// skip kernel_headers which always depend on vendor
@@ -735,13 +753,14 @@
var propOut string
if l, ok := m.linker.(snapshotLibraryInterface); ok {
+ exporterInfo := ctx.ModuleProvider(m, FlagExporterInfoProvider).(FlagExporterInfo)
// library flags
- prop.ExportedFlags = l.exportedFlags()
- for _, dir := range l.exportedDirs() {
+ prop.ExportedFlags = exporterInfo.Flags
+ for _, dir := range exporterInfo.IncludeDirs {
prop.ExportedDirs = append(prop.ExportedDirs, filepath.Join("include", dir.String()))
}
- for _, dir := range l.exportedSystemDirs() {
+ for _, dir := range exporterInfo.SystemIncludeDirs {
prop.ExportedSystemDirs = append(prop.ExportedSystemDirs, filepath.Join("include", dir.String()))
}
// shared libs dependencies aren't meaningful on static or header libs
@@ -825,6 +844,7 @@
moduleDir := ctx.ModuleDir(module)
inVendorProprietaryPath := isVendorProprietaryPath(moduleDir)
+ apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
if m.ExcludeFromVendorSnapshot() {
if inVendorProprietaryPath {
@@ -842,7 +862,7 @@
}
}
- if !isVendorSnapshotModule(m, inVendorProprietaryPath) {
+ if !isVendorSnapshotModule(m, inVendorProprietaryPath, apexInfo) {
return
}
@@ -985,9 +1005,10 @@
// But we can't just check SocSpecific() since we already passed the image mutator.
// Check ramdisk and recovery to see if we are real "vendor: true" module.
ramdisk_available := module.InRamdisk() && !module.OnlyInRamdisk()
+ vendor_ramdisk_available := module.InVendorRamdisk() && !module.OnlyInVendorRamdisk()
recovery_available := module.InRecovery() && !module.OnlyInRecovery()
- if !ramdisk_available && !recovery_available {
+ if !ramdisk_available && !recovery_available && !vendor_ramdisk_available {
vendorSnapshotsLock.Lock()
defer vendorSnapshotsLock.Unlock()
diff --git a/cc/vndk.go b/cc/vndk.go
index 9a2fa09..4a005f3 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -62,8 +62,8 @@
// declared as a VNDK or VNDK-SP module. The vendor variant
// will be installed in /system instead of /vendor partition.
//
- // `vendor_available` must be explicitly set to either true or
- // false together with `vndk: {enabled: true}`.
+ // `vendor_available` and `product_available` must be explicitly
+ // set to either true or false together with `vndk: {enabled: true}`.
Enabled *bool
// declared as a VNDK-SP module, which is a subset of VNDK.
@@ -129,13 +129,16 @@
return "native:vendor:vndkspext"
}
-func (vndk *vndkdep) vndkCheckLinkType(ctx android.ModuleContext, to *Module, tag blueprint.DependencyTag) {
+// VNDK link type check from a module with UseVndk() == true.
+func (vndk *vndkdep) vndkCheckLinkType(ctx android.BaseModuleContext, to *Module, tag blueprint.DependencyTag) {
if to.linker == nil {
return
}
if !vndk.isVndk() {
- // Non-VNDK modules (those installed to /vendor, /product, or /system/product) can't depend
- // on modules marked with vendor_available: false.
+ // Non-VNDK modules those installed to /vendor or /system/vendor
+ // can't depend on modules marked with vendor_available: false;
+ // or those installed to /product or /system/product can't depend
+ // on modules marked with product_available: false.
violation := false
if lib, ok := to.linker.(*llndkStubDecorator); ok && !Bool(lib.Properties.Vendor_available) {
violation = true
@@ -174,6 +177,7 @@
to.Name())
return
}
+ // TODO(b/150902910): vndk-ext for product must check product_available.
if !Bool(to.VendorProperties.Vendor_available) {
ctx.ModuleErrorf(
"`extends` refers module %q which does not have `vendor_available: true`",
@@ -247,7 +251,7 @@
}
func isLlndkLibrary(baseModuleName string, config android.Config) bool {
- _, ok := llndkLibraries(config)[baseModuleName]
+ _, ok := llndkLibraries(config)[strings.TrimSuffix(baseModuleName, llndkLibrarySuffix)]
return ok
}
@@ -290,8 +294,8 @@
func processLlndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {
lib := m.linker.(*llndkStubDecorator)
- name := m.BaseModuleName()
- filename := m.BaseModuleName() + ".so"
+ name := m.ImplementationModuleName(mctx)
+ filename := name + ".so"
vndkLibrariesLock.Lock()
defer vndkLibrariesLock.Unlock()
@@ -300,6 +304,7 @@
if !Bool(lib.Properties.Vendor_available) {
vndkPrivateLibraries(mctx.Config())[name] = filename
}
+
if mctx.OtherModuleExists(name) {
mctx.AddFarVariationDependencies(m.Target().Variations(), llndkImplDep, name)
}
@@ -312,7 +317,7 @@
panic(err)
}
- if m.HasStubsVariants() && name != "libz" {
+ if lib := m.library; lib != nil && lib.hasStubsVariants() && name != "libz" {
// b/155456180 libz is the ONLY exception here. We don't want to make
// libz an LLNDK library because we in general can't guarantee that
// libz will behave consistently especially about the compression.
@@ -337,6 +342,8 @@
} else {
vndkCoreLibraries(mctx.Config())[name] = filename
}
+ // As `vendor_available` and `product_available` has the same value for VNDK modules,
+ // we don't need to check both values.
if !Bool(m.VendorProperties.Vendor_available) {
vndkPrivateLibraries(mctx.Config())[name] = filename
}
@@ -480,14 +487,7 @@
}
txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath
- ctx.Build(pctx, android.BuildParams{
- Rule: android.WriteFile,
- Output: txt.outputFile,
- Description: "Writing " + txt.outputFile.String(),
- Args: map[string]string{
- "content": strings.Join(list, "\\n"),
- },
- })
+ android.WriteFileRule(ctx, txt.outputFile, strings.Join(list, "\n"))
installPath := android.PathForModuleInstall(ctx, "etc")
ctx.InstallFile(installPath, filename, txt.outputFile)
@@ -533,11 +533,16 @@
vndkSnapshotZipFile android.OptionalPath
}
-func isVndkSnapshotLibrary(config android.DeviceConfig, m *Module) (i snapshotLibraryInterface, vndkType string, isVndkSnapshotLib bool) {
+func isVndkSnapshotLibrary(config android.DeviceConfig, m *Module,
+ apexInfo android.ApexInfo) (i snapshotLibraryInterface, vndkType string, isVndkSnapshotLib bool) {
+
if m.Target().NativeBridge == android.NativeBridgeEnabled {
return nil, "", false
}
- if !m.inVendor() || !m.installable() || m.isSnapshotPrebuilt() {
+ // !inVendor: There's product/vendor variants for VNDK libs. We only care about vendor variants.
+ // !installable: Snapshot only cares about "installable" modules.
+ // isSnapshotPrebuilt: Snapshotting a snapshot doesn't make sense.
+ if !m.inVendor() || !m.installable(apexInfo) || m.isSnapshotPrebuilt() {
return nil, "", false
}
l, ok := m.linker.(snapshotLibraryInterface)
@@ -617,7 +622,7 @@
var headers android.Paths
- installVndkSnapshotLib := func(m *Module, l snapshotLibraryInterface, vndkType string) (android.Paths, bool) {
+ installVndkSnapshotLib := func(m *Module, vndkType string) (android.Paths, bool) {
var ret android.Paths
targetArch := "arch-" + m.Target().Arch.ArchType.String()
@@ -636,9 +641,10 @@
ExportedFlags []string `json:",omitempty"`
RelativeInstallPath string `json:",omitempty"`
}{}
- prop.ExportedFlags = l.exportedFlags()
- prop.ExportedDirs = l.exportedDirs().Strings()
- prop.ExportedSystemDirs = l.exportedSystemDirs().Strings()
+ exportedInfo := ctx.ModuleProvider(m, FlagExporterInfoProvider).(FlagExporterInfo)
+ prop.ExportedFlags = exportedInfo.Flags
+ prop.ExportedDirs = exportedInfo.IncludeDirs.Strings()
+ prop.ExportedSystemDirs = exportedInfo.SystemIncludeDirs.Strings()
prop.RelativeInstallPath = m.RelativeInstallPath()
propOut := snapshotLibOut + ".json"
@@ -659,14 +665,16 @@
return
}
- l, vndkType, ok := isVndkSnapshotLibrary(ctx.DeviceConfig(), m)
+ apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+
+ l, vndkType, ok := isVndkSnapshotLibrary(ctx.DeviceConfig(), m, apexInfo)
if !ok {
return
}
// install .so files for appropriate modules.
// Also install .json files if VNDK_SNAPSHOT_BUILD_ARTIFACTS
- libs, ok := installVndkSnapshotLib(m, l, vndkType)
+ libs, ok := installVndkSnapshotLib(m, vndkType)
if !ok {
return
}
@@ -731,7 +739,7 @@
/*
module_paths.txt contains paths on which VNDK modules are defined.
e.g.,
- libbase.so system/core/base
+ libbase.so system/libbase
libc.so bionic/libc
...
*/
@@ -810,27 +818,27 @@
merged = append(merged, addPrefix(filterOutLibClangRt(vndkcore), "VNDK-core: ")...)
merged = append(merged, addPrefix(vndkprivate, "VNDK-private: ")...)
c.vndkLibrariesFile = android.PathForOutput(ctx, "vndk", "vndk.libraries.txt")
- ctx.Build(pctx, android.BuildParams{
- Rule: android.WriteFile,
- Output: c.vndkLibrariesFile,
- Description: "Writing " + c.vndkLibrariesFile.String(),
- Args: map[string]string{
- "content": strings.Join(merged, "\\n"),
- },
- })
+ android.WriteFileRule(ctx, c.vndkLibrariesFile, strings.Join(merged, "\n"))
}
func (c *vndkSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
// Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to avoid installing libraries on /system if
// they been moved to an apex.
- movedToApexLlndkLibraries := []string{}
- for lib := range llndkLibraries(ctx.Config()) {
- // Skip bionic libs, they are handled in different manner
- if android.DirectlyInAnyApex(¬OnHostContext{}, lib) && !isBionic(lib) {
- movedToApexLlndkLibraries = append(movedToApexLlndkLibraries, lib)
+ movedToApexLlndkLibraries := make(map[string]bool)
+ ctx.VisitAllModules(func(module android.Module) {
+ if m, ok := module.(*Module); ok {
+ if llndk, ok := m.linker.(*llndkStubDecorator); ok {
+ // Skip bionic libs, they are handled in different manner
+ name := llndk.implementationModuleName(m.BaseModuleName())
+ if llndk.movedToApex && !isBionic(name) {
+ movedToApexLlndkLibraries[name] = true
+ }
+ }
}
- }
- ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES", strings.Join(movedToApexLlndkLibraries, " "))
+ })
+
+ ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES",
+ strings.Join(android.SortedStringKeys(movedToApexLlndkLibraries), " "))
// Make uses LLNDK_LIBRARIES to determine which libraries to install.
// HWASAN is only part of the LL-NDK in builds in which libc depends on HWASAN.
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index 9484760..c0320eb 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -34,6 +34,7 @@
// version: "27",
// target_arch: "arm64",
// vendor_available: true,
+// product_available: true,
// vndk: {
// enabled: true,
// },
@@ -52,7 +53,7 @@
// VNDK snapshot version.
Version *string
- // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64_ab')
+ // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64')
Target_arch *string
// If the prebuilt snapshot lib is built with 32 bit binder, this must be set to true.
@@ -162,6 +163,15 @@
p.androidMkSuffix = ""
}
+ ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
+ SharedLibrary: in,
+ UnstrippedSharedLibrary: p.unstrippedOutputFile,
+
+ TableOfContents: p.tocFile,
+ })
+
+ p.libraryDecorator.flagExporter.setProvider(ctx)
+
return in
}
@@ -192,21 +202,7 @@
}
func (p *vndkPrebuiltLibraryDecorator) install(ctx ModuleContext, file android.Path) {
- arches := ctx.DeviceConfig().Arches()
- if len(arches) == 0 || arches[0].ArchType.String() != p.arch() {
- return
- }
- if ctx.DeviceConfig().BinderBitness() != p.binderBit() {
- return
- }
- if p.shared() {
- if ctx.isVndkSp() {
- p.baseInstaller.subDir = "vndk-sp-" + p.version()
- } else if ctx.isVndk() {
- p.baseInstaller.subDir = "vndk-" + p.version()
- }
- p.baseInstaller.install(ctx, file)
- }
+ // do not install vndk libs
}
func vndkPrebuiltSharedLibrary() *Module {
@@ -237,6 +233,14 @@
&prebuilt.properties,
)
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ // empty BOARD_VNDK_VERSION implies that the device won't support
+ // system only OTA. In this case, VNDK snapshots aren't needed.
+ if ctx.DeviceConfig().VndkVersion() == "" {
+ ctx.Module().Disable()
+ }
+ })
+
return module
}
@@ -248,6 +252,7 @@
// version: "27",
// target_arch: "arm64",
// vendor_available: true,
+// product_available: true,
// vndk: {
// enabled: true,
// },
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index 7329aee..0a9b156 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -412,7 +412,9 @@
ctx.Status.AddOutput(terminal.NewStatusOutput(ctx.Writer, "", false,
build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD")))
- config := build.NewConfig(ctx, flag.Args()...)
+ args := append([]string(nil), flag.Args()...)
+ args = append(args, "--skip-soong-tests")
+ config := build.NewConfig(ctx, args...)
config.Environment().Set("OUT_DIR", outDir)
if !*keepArtifacts {
config.Environment().Set("EMPTY_NINJA_FILE", "true")
diff --git a/cmd/soong_build/Android.bp b/cmd/soong_build/Android.bp
index 4ebbe68..680c00a 100644
--- a/cmd/soong_build/Android.bp
+++ b/cmd/soong_build/Android.bp
@@ -26,10 +26,10 @@
srcs: [
"main.go",
"writedocs.go",
- "bazel_overlay.go",
+ "queryview.go",
],
testSrcs: [
- "bazel_overlay_test.go",
+ "queryview_test.go",
],
primaryBuilder: true,
}
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 01a39a2..b88803a 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -26,13 +26,13 @@
)
var (
- docFile string
- bazelOverlayDir string
+ docFile string
+ bazelQueryViewDir string
)
func init() {
flag.StringVar(&docFile, "soong_docs", "", "build documentation file to output")
- flag.StringVar(&bazelOverlayDir, "bazel_overlay_dir", "", "path to the bazel overlay directory")
+ flag.StringVar(&bazelQueryViewDir, "bazel_queryview_dir", "", "path to the bazel queryview directory")
}
func newNameResolver(config android.Config) *android.NameResolver {
@@ -51,30 +51,34 @@
return android.NewNameResolver(exportFilter)
}
+func newContext(srcDir string, configuration android.Config) *android.Context {
+ ctx := android.NewContext(configuration)
+ ctx.Register()
+ if !shouldPrepareBuildActions() {
+ configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions)
+ }
+ ctx.SetNameInterface(newNameResolver(configuration))
+ ctx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
+ return ctx
+}
+
+func newConfig(srcDir string) android.Config {
+ configuration, err := android.NewConfig(srcDir, bootstrap.BuildDir, bootstrap.ModuleListFile)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s", err)
+ os.Exit(1)
+ }
+ return configuration
+}
+
func main() {
android.ReexecWithDelveMaybe()
flag.Parse()
// The top-level Blueprints file is passed as the first argument.
srcDir := filepath.Dir(flag.Arg(0))
-
- ctx := android.NewContext()
- ctx.Register()
-
- configuration, err := android.NewConfig(srcDir, bootstrap.BuildDir, bootstrap.ModuleListFile)
- if err != nil {
- fmt.Fprintf(os.Stderr, "%s", err)
- os.Exit(1)
- }
-
- if !shouldPrepareBuildActions() {
- configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions)
- }
-
- ctx.SetNameInterface(newNameResolver(configuration))
-
- ctx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
-
+ var ctx *android.Context
+ configuration := newConfig(srcDir)
extraNinjaDeps := []string{configuration.ConfigFileName, configuration.ProductVariablesFileName}
// Read the SOONG_DELVE again through configuration so that there is a dependency on the environment variable
@@ -84,11 +88,34 @@
// enabled even if it completed successfully.
extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.BuildDir(), "always_rerun_for_delve"))
}
-
- bootstrap.Main(ctx.Context, configuration, extraNinjaDeps...)
-
- if bazelOverlayDir != "" {
- if err := createBazelOverlay(ctx, bazelOverlayDir); err != nil {
+ if configuration.BazelContext.BazelEnabled() {
+ // Bazel-enabled mode. Soong runs in two passes.
+ // First pass: Analyze the build tree, but only store all bazel commands
+ // needed to correctly evaluate the tree in the second pass.
+ // TODO(cparsons): Don't output any ninja file, as the second pass will overwrite
+ // the incorrect results from the first pass, and file I/O is expensive.
+ firstCtx := newContext(srcDir, configuration)
+ configuration.SetStopBefore(bootstrap.StopBeforeWriteNinja)
+ bootstrap.Main(firstCtx.Context, configuration, extraNinjaDeps...)
+ // Invoke bazel commands and save results for second pass.
+ if err := configuration.BazelContext.InvokeBazel(); err != nil {
+ fmt.Fprintf(os.Stderr, "%s", err)
+ os.Exit(1)
+ }
+ // Second pass: Full analysis, using the bazel command results. Output ninja file.
+ secondPassConfig, err := android.ConfigForAdditionalRun(configuration)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s", err)
+ os.Exit(1)
+ }
+ ctx = newContext(srcDir, secondPassConfig)
+ bootstrap.Main(ctx.Context, secondPassConfig, extraNinjaDeps...)
+ } else {
+ ctx = newContext(srcDir, configuration)
+ bootstrap.Main(ctx.Context, configuration, extraNinjaDeps...)
+ }
+ if bazelQueryViewDir != "" {
+ if err := createBazelQueryView(ctx, bazelQueryViewDir); err != nil {
fmt.Fprintf(os.Stderr, "%s", err)
os.Exit(1)
}
@@ -105,7 +132,7 @@
// to affect the command line of the primary builder.
if shouldPrepareBuildActions() {
metricsFile := filepath.Join(bootstrap.BuildDir, "soong_build_metrics.pb")
- err = android.WriteMetrics(configuration, metricsFile)
+ err := android.WriteMetrics(configuration, metricsFile)
if err != nil {
fmt.Fprintf(os.Stderr, "error writing soong_build metrics %s: %s", metricsFile, err)
os.Exit(1)
@@ -114,7 +141,7 @@
}
func shouldPrepareBuildActions() bool {
- // If we're writing soong_docs or bazel_overlay, don't write build.ninja or
+ // If we're writing soong_docs or queryview, don't write build.ninja or
// collect metrics.
- return docFile == "" && bazelOverlayDir == ""
+ return docFile == "" && bazelQueryViewDir == ""
}
diff --git a/cmd/soong_build/bazel_overlay.go b/cmd/soong_build/queryview.go
similarity index 86%
rename from cmd/soong_build/bazel_overlay.go
rename to cmd/soong_build/queryview.go
index 72e0fbd..27856b5 100644
--- a/cmd/soong_build/bazel_overlay.go
+++ b/cmd/soong_build/queryview.go
@@ -31,7 +31,7 @@
const (
// The default `load` preamble for every generated BUILD file.
soongModuleLoad = `package(default_visibility = ["//visibility:public"])
-load("//:soong_module.bzl", "soong_module")
+load("//build/bazel/queryview_rules:soong_module.bzl", "soong_module")
`
@@ -62,7 +62,7 @@
soongModuleBzl = `
%s
-load(":providers.bzl", "SoongModuleInfo")
+load("//build/bazel/queryview_rules:providers.bzl", "SoongModuleInfo")
def _generic_soong_module_impl(ctx):
return [
@@ -149,31 +149,6 @@
"string": true, // e.g. "a"
}
- // TODO(b/166563303): Specific properties of some module types aren't
- // recognized by the documentation generator. As a workaround, hardcode a
- // mapping of the module type to prop name to prop type here, and ultimately
- // fix the documentation generator to also parse these properties correctly.
- additionalPropTypes = map[string]map[string]string{
- // sdk and module_exports props are created at runtime using reflection.
- // bpdocs isn't wired up to read runtime generated structs.
- "sdk": {
- "java_header_libs": "string_list",
- "java_sdk_libs": "string_list",
- "java_system_modules": "string_list",
- "native_header_libs": "string_list",
- "native_libs": "string_list",
- "native_objects": "string_list",
- "native_shared_libs": "string_list",
- "native_static_libs": "string_list",
- },
- "module_exports": {
- "java_libs": "string_list",
- "java_tests": "string_list",
- "native_binaries": "string_list",
- "native_shared_libs": "string_list",
- },
- }
-
// Certain module property names are blocklisted/ignored here, for the reasons commented.
ignoredPropNames = map[string]bool{
"name": true, // redundant, since this is explicitly generated for every target
@@ -395,7 +370,7 @@
// Canonicalize and normalize module property types to Bazel attribute types
starlarkAttrType := prop.Type
- if starlarkAttrType == "list of strings" {
+ if starlarkAttrType == "list of string" {
starlarkAttrType = "string_list"
} else if starlarkAttrType == "int64" {
starlarkAttrType = "int"
@@ -421,7 +396,7 @@
ruleShims := map[string]RuleShim{}
for _, pkg := range packages {
- content := "load(\":providers.bzl\", \"SoongModuleInfo\")\n"
+ content := "load(\"//build/bazel/queryview_rules:providers.bzl\", \"SoongModuleInfo\")\n"
bzlFileName := strings.ReplaceAll(pkg.Path, "android/soong/", "")
bzlFileName = strings.ReplaceAll(bzlFileName, ".", "_")
@@ -439,8 +414,19 @@
attrs += propToAttr(prop, prop.Name)
}
- for propName, propType := range additionalPropTypes[moduleTypeTemplate.Name] {
- attrs += fmt.Sprintf(" %q: attr.%s(),\n", propName, propType)
+ moduleTypeName := moduleTypeTemplate.Name
+
+ // Certain SDK-related module types dynamically inject properties, instead of declaring
+ // them as structs. These properties are registered in an SdkMemberTypesRegistry. If
+ // the module type name matches, add these properties into the rule definition.
+ var registeredTypes []android.SdkMemberType
+ if moduleTypeName == "module_exports" || moduleTypeName == "module_exports_snapshot" {
+ registeredTypes = android.ModuleExportsMemberTypes.RegisteredTypes()
+ } else if moduleTypeName == "sdk" || moduleTypeName == "sdk_snapshot" {
+ registeredTypes = android.SdkMemberTypes.RegisteredTypes()
+ }
+ for _, memberType := range registeredTypes {
+ attrs += fmt.Sprintf(" %q: attr.string_list(),\n", memberType.SdkPropertyName())
}
attrs += " },"
@@ -455,10 +441,10 @@
return ruleShims, nil
}
-func createBazelOverlay(ctx *android.Context, bazelOverlayDir string) error {
+func createBazelQueryView(ctx *android.Context, bazelQueryViewDir string) error {
blueprintCtx := ctx.Context
blueprintCtx.VisitAllModules(func(module blueprint.Module) {
- buildFile, err := buildFileForModule(blueprintCtx, module)
+ buildFile, err := buildFileForModule(blueprintCtx, module, bazelQueryViewDir)
if err != nil {
panic(err)
}
@@ -466,16 +452,15 @@
buildFile.Write([]byte(generateSoongModuleTarget(blueprintCtx, module) + "\n\n"))
buildFile.Close()
})
+ var err error
- if err := writeReadOnlyFile(bazelOverlayDir, "WORKSPACE", ""); err != nil {
+ // Write top level files: WORKSPACE and BUILD. These files are empty.
+ if err = writeReadOnlyFile(bazelQueryViewDir, "WORKSPACE", ""); err != nil {
return err
}
- if err := writeReadOnlyFile(bazelOverlayDir, "BUILD", ""); err != nil {
- return err
- }
-
- if err := writeReadOnlyFile(bazelOverlayDir, "providers.bzl", providersBzl); err != nil {
+ // Used to denote that the top level directory is a package.
+ if err = writeReadOnlyFile(bazelQueryViewDir, "BUILD", ""); err != nil {
return err
}
@@ -488,13 +473,22 @@
return err
}
+ // Write .bzl Starlark files into the bazel_rules top level directory (provider and rule definitions)
+ bazelRulesDir := bazelQueryViewDir + "/build/bazel/queryview_rules"
+ if err = writeReadOnlyFile(bazelRulesDir, "BUILD", ""); err != nil {
+ return err
+ }
+ if err = writeReadOnlyFile(bazelRulesDir, "providers.bzl", providersBzl); err != nil {
+ return err
+ }
+
for bzlFileName, ruleShim := range ruleShims {
- if err := writeReadOnlyFile(bazelOverlayDir, bzlFileName+".bzl", ruleShim.content); err != nil {
+ if err = writeReadOnlyFile(bazelRulesDir, bzlFileName+".bzl", ruleShim.content); err != nil {
return err
}
}
- return writeReadOnlyFile(bazelOverlayDir, "soong_module.bzl", generateSoongModuleBzl(ruleShims))
+ return writeReadOnlyFile(bazelRulesDir, "soong_module.bzl", generateSoongModuleBzl(ruleShims))
}
// Generate the content of soong_module.bzl with the rule shim load statements
@@ -503,7 +497,7 @@
var loadStmts string
var moduleRuleMap string
for bzlFileName, ruleShim := range bzlLoads {
- loadStmt := "load(\"//:"
+ loadStmt := "load(\"//build/bazel/queryview_rules:"
loadStmt += bzlFileName
loadStmt += ".bzl\""
for _, rule := range ruleShim.rules {
@@ -569,12 +563,11 @@
attributes)
}
-func buildFileForModule(ctx *blueprint.Context, module blueprint.Module) (*os.File, error) {
+func buildFileForModule(
+ ctx *blueprint.Context, module blueprint.Module, bazelQueryViewDir string) (*os.File, error) {
// Create nested directories for the BUILD file
- dirPath := filepath.Join(bazelOverlayDir, packagePath(ctx, module))
- if _, err := os.Stat(dirPath); os.IsNotExist(err) {
- os.MkdirAll(dirPath, os.ModePerm)
- }
+ dirPath := filepath.Join(bazelQueryViewDir, packagePath(ctx, module))
+ createDirectoryIfNonexistent(dirPath)
// Open the file for appending, and create it if it doesn't exist
f, err := os.OpenFile(
filepath.Join(dirPath, "BUILD.bazel"),
@@ -596,10 +589,17 @@
return f, nil
}
-// The overlay directory should be read-only, sufficient for bazel query. The files
+func createDirectoryIfNonexistent(dir string) {
+ if _, err := os.Stat(dir); os.IsNotExist(err) {
+ os.MkdirAll(dir, os.ModePerm)
+ }
+}
+
+// The QueryView directory should be read-only, sufficient for bazel query. The files
// are not intended to be edited by end users.
func writeReadOnlyFile(dir string, baseName string, content string) error {
- pathToFile := filepath.Join(bazelOverlayDir, baseName)
+ createDirectoryIfNonexistent(dir)
+ pathToFile := filepath.Join(dir, baseName)
// 0444 is read-only
return ioutil.WriteFile(pathToFile, []byte(content), 0444)
}
diff --git a/cmd/soong_build/bazel_overlay_test.go b/cmd/soong_build/queryview_test.go
similarity index 95%
rename from cmd/soong_build/bazel_overlay_test.go
rename to cmd/soong_build/queryview_test.go
index f0c8515..525802a 100644
--- a/cmd/soong_build/bazel_overlay_test.go
+++ b/cmd/soong_build/queryview_test.go
@@ -28,7 +28,7 @@
func setUp() {
var err error
- buildDir, err = ioutil.TempDir("", "bazel_overlay_test")
+ buildDir, err = ioutil.TempDir("", "bazel_queryview_test")
if err != nil {
panic(err)
}
@@ -63,7 +63,7 @@
return module
}
-func TestGenerateBazelOverlayFromBlueprint(t *testing.T) {
+func TestGenerateBazelQueryViewFromBlueprint(t *testing.T) {
testCases := []struct {
bp string
expectedBazelTarget string
@@ -234,9 +234,9 @@
for _, testCase := range testCases {
config := android.TestConfig(buildDir, nil, testCase.bp, nil)
- ctx := android.NewTestContext()
+ ctx := android.NewTestContext(config)
ctx.RegisterModuleType("custom", customModuleFactory)
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
android.FailIfErrored(t, errs)
@@ -277,7 +277,7 @@
},
bpdoc.Property{
Name: "string_list_prop",
- Type: "list of strings",
+ Type: "list of string",
},
bpdoc.Property{
Name: "nested_prop",
@@ -362,7 +362,7 @@
}
}
- expectedBzl := `load(":providers.bzl", "SoongModuleInfo")
+ expectedBzl := `load("//build/bazel/queryview_rules:providers.bzl", "SoongModuleInfo")
def _foo_binary_impl(ctx):
return [SoongModuleInfo()]
@@ -440,7 +440,7 @@
}
actualSoongModuleBzl := generateSoongModuleBzl(ruleShims)
- expectedLoad := "load(\"//:foo.bzl\", \"foo_binary\", \"foo_library\", \"foo_test_\")"
+ expectedLoad := "load(\"//build/bazel/queryview_rules:foo.bzl\", \"foo_binary\", \"foo_library\", \"foo_test_\")"
expectedRuleMap := `soong_module_rule_map = {
"foo_binary": foo_binary,
"foo_library": foo_library,
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 4aa62be..aee8e5a 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -119,9 +119,9 @@
func main() {
buildStarted := time.Now()
- c, args := getCommand(os.Args)
- if c == nil {
- fmt.Fprintf(os.Stderr, "The `soong` native UI is not yet available.\n")
+ c, args, err := getCommand(os.Args)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error parsing `soong` args: %s.\n", err)
os.Exit(1)
}
@@ -139,6 +139,7 @@
met := metrics.New()
met.SetBuildDateTime(buildStarted)
+ met.SetBuildCommand(os.Args)
stat := &status.Status{}
defer stat.Finish()
@@ -173,7 +174,7 @@
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)
+ build.PrintOutDirWarning(buildCtx, config)
os.MkdirAll(logsDir, 0777)
log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
@@ -471,6 +472,10 @@
}
toBuild := build.BuildAll
+ if config.UseBazel() {
+ toBuild = build.BuildAllWithBazel
+ }
+
if config.Checkbuild() {
toBuild |= build.RunBuildTests
}
@@ -479,14 +484,14 @@
// getCommand finds the appropriate command based on args[1] flag. args[0]
// is the soong_ui filename.
-func getCommand(args []string) (*command, []string) {
+func getCommand(args []string) (*command, []string, error) {
if len(args) < 2 {
- return nil, args
+ return nil, nil, fmt.Errorf("Too few arguments: %q", args)
}
for _, c := range commands {
if c.flag == args[1] {
- return &c, args[2:]
+ return &c, args[2:], nil
}
// special case for --make-mode: if soong_ui was called from
@@ -495,11 +500,11 @@
// TODO: Remove this hack once it has been fixed.
if c.flag == makeModeFlagName {
if inList(makeModeFlagName, args) {
- return &c, args[1:]
+ return &c, args[1:], nil
}
}
}
// command not found
- return nil, args
+ return nil, nil, fmt.Errorf("Command not found: %q", args)
}
diff --git a/dexpreopt/Android.bp b/dexpreopt/Android.bp
index b8f7ea6..35f90df 100644
--- a/dexpreopt/Android.bp
+++ b/dexpreopt/Android.bp
@@ -2,11 +2,13 @@
name: "soong-dexpreopt",
pkgPath: "android/soong/dexpreopt",
srcs: [
+ "class_loader_context.go",
"config.go",
"dexpreopt.go",
"testing.go",
],
testSrcs: [
+ "class_loader_context_test.go",
"dexpreopt_test.go",
],
deps: [
diff --git a/dexpreopt/class_loader_context.go b/dexpreopt/class_loader_context.go
new file mode 100644
index 0000000..b910a70
--- /dev/null
+++ b/dexpreopt/class_loader_context.go
@@ -0,0 +1,376 @@
+// 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 dexpreopt
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ "android/soong/android"
+)
+
+// These libs are added as <uses-library> dependencies for apps if the targetSdkVersion in the
+// app manifest is less than the specified version. This is needed because these libraries haven't
+// existed prior to certain SDK version, but classes in them were in bootclasspath jars, etc.
+// Some of the compatibility libraries are optional (their <uses-library> tag has "required=false"),
+// so that if this library is missing this in not a build or run-time error.
+var OrgApacheHttpLegacy = "org.apache.http.legacy"
+var AndroidTestBase = "android.test.base"
+var AndroidTestMock = "android.test.mock"
+var AndroidHidlBase = "android.hidl.base-V1.0-java"
+var AndroidHidlManager = "android.hidl.manager-V1.0-java"
+
+var OptionalCompatUsesLibs28 = []string{
+ OrgApacheHttpLegacy,
+}
+var OptionalCompatUsesLibs30 = []string{
+ AndroidTestBase,
+ AndroidTestMock,
+}
+var CompatUsesLibs29 = []string{
+ AndroidHidlBase,
+ AndroidHidlManager,
+}
+var OptionalCompatUsesLibs = append(android.CopyOf(OptionalCompatUsesLibs28), OptionalCompatUsesLibs30...)
+var CompatUsesLibs = android.CopyOf(CompatUsesLibs29)
+
+const UnknownInstallLibraryPath = "error"
+
+// AnySdkVersion means that the class loader context is needed regardless of the targetSdkVersion
+// of the app. The numeric value affects the key order in the map and, as a result, the order of
+// arguments passed to construct_context.py (high value means that the unconditional context goes
+// last). We use the converntional "current" SDK level (10000), but any big number would do as well.
+const AnySdkVersion int = android.FutureApiLevelInt
+
+// ClassLoaderContext is a tree of libraries used by the dexpreopted module with their dependencies.
+// The context is used by dex2oat to compile the module and recorded in the AOT-compiled files, so
+// that it can be checked agains the run-time class loader context on device. If there is a mismatch
+// at runtime, AOT-compiled code is rejected.
+type ClassLoaderContext struct {
+ // The name of the library (same as the name of the module that contains it).
+ Name string
+
+ // On-host build path to the library dex file (used in dex2oat argument --class-loader-context).
+ Host android.Path
+
+ // On-device install path (used in dex2oat argument --stored-class-loader-context).
+ Device string
+
+ // Nested class loader subcontexts for dependencies.
+ Subcontexts []*ClassLoaderContext
+
+ // If the library is a shared library. This affects which elements of class loader context are
+ // added as <uses-library> tags by the manifest_fixer (dependencies of shared libraries aren't).
+ IsSharedLibrary bool
+}
+
+// ClassLoaderContextMap is a map from SDK version to a class loader context.
+// There is a special entry with key AnySdkVersion that stores unconditional class loader context.
+// Other entries store conditional contexts that should be added for some apps that have
+// targetSdkVersion in the manifest lower than the key SDK version.
+type ClassLoaderContextMap map[int][]*ClassLoaderContext
+
+// Add class loader context for the given library to the map entry for the given SDK version.
+func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathContext, sdkVer int, lib string,
+ shared bool, hostPath, installPath android.Path, strict bool, nestedClcMap ClassLoaderContextMap) error {
+
+ // If missing dependencies are allowed, the build shouldn't fail when a <uses-library> is
+ // not found. However, this is likely to result is disabling dexpreopt, as it won't be
+ // possible to construct class loader context without on-host and on-device library paths.
+ strict = strict && !ctx.Config().AllowMissingDependencies()
+
+ if hostPath == nil && strict {
+ return fmt.Errorf("unknown build path to <uses-library> \"%s\"", lib)
+ }
+
+ devicePath := UnknownInstallLibraryPath
+ if installPath == nil {
+ if android.InList(lib, CompatUsesLibs) || android.InList(lib, OptionalCompatUsesLibs) {
+ // Assume that compatibility libraries are installed in /system/framework.
+ installPath = android.PathForModuleInstall(ctx, "framework", lib+".jar")
+ } else if strict {
+ return fmt.Errorf("unknown install path to <uses-library> \"%s\"", lib)
+ } else {
+ // For some stub libraries the only known thing is the name of their implementation
+ // library, but the library itself is unavailable (missing or part of a prebuilt). In
+ // such cases we still need to add the library to <uses-library> tags in the manifest,
+ // but we cannot use it for dexpreopt.
+ }
+ }
+ if installPath != nil {
+ devicePath = android.InstallPathToOnDevicePath(ctx, installPath.(android.InstallPath))
+ }
+
+ // Nested class loader context shouldn't have conditional part (it is allowed only at the top level).
+ for ver, _ := range nestedClcMap {
+ if ver != AnySdkVersion {
+ clcStr, _ := ComputeClassLoaderContext(nestedClcMap)
+ return fmt.Errorf("nested class loader context shouldn't have conditional part: %s", clcStr)
+ }
+ }
+ subcontexts := nestedClcMap[AnySdkVersion]
+
+ // If the library with this name is already present as one of the unconditional top-level
+ // components, do not re-add it.
+ for _, clc := range clcMap[sdkVer] {
+ if clc.Name == lib {
+ return nil
+ }
+ }
+
+ clcMap[sdkVer] = append(clcMap[sdkVer], &ClassLoaderContext{
+ Name: lib,
+ Host: hostPath,
+ Device: devicePath,
+ Subcontexts: subcontexts,
+ IsSharedLibrary: shared,
+ })
+ return nil
+}
+
+// Wrapper around addContext that reports errors.
+func (clcMap ClassLoaderContextMap) addContextOrReportError(ctx android.ModuleInstallPathContext, sdkVer int, lib string,
+ shared bool, hostPath, installPath android.Path, strict bool, nestedClcMap ClassLoaderContextMap) {
+
+ err := clcMap.addContext(ctx, sdkVer, lib, shared, hostPath, installPath, strict, nestedClcMap)
+ if err != nil {
+ ctx.ModuleErrorf(err.Error())
+ }
+}
+
+// Add class loader context. Fail on unknown build/install paths.
+func (clcMap ClassLoaderContextMap) AddContext(ctx android.ModuleInstallPathContext, lib string,
+ shared bool, hostPath, installPath android.Path) {
+
+ clcMap.addContextOrReportError(ctx, AnySdkVersion, lib, shared, hostPath, installPath, true, nil)
+}
+
+// Add class loader context if the library exists. Don't fail on unknown build/install paths.
+func (clcMap ClassLoaderContextMap) MaybeAddContext(ctx android.ModuleInstallPathContext, lib *string,
+ shared bool, hostPath, installPath android.Path) {
+
+ if lib != nil {
+ clcMap.addContextOrReportError(ctx, AnySdkVersion, *lib, shared, hostPath, installPath, false, nil)
+ }
+}
+
+// Add class loader context for the given SDK version. Fail on unknown build/install paths.
+func (clcMap ClassLoaderContextMap) AddContextForSdk(ctx android.ModuleInstallPathContext, sdkVer int,
+ lib string, shared bool, hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) {
+
+ clcMap.addContextOrReportError(ctx, sdkVer, lib, shared, hostPath, installPath, true, nestedClcMap)
+}
+
+// Merge the other class loader context map into this one, do not override existing entries.
+// The implicitRootLib parameter is the name of the library for which the other class loader
+// context map was constructed. If the implicitRootLib is itself a <uses-library>, it should be
+// already present in the class loader context (with the other context as its subcontext) -- in
+// that case do not re-add the other context. Otherwise add the other context at the top-level.
+func (clcMap ClassLoaderContextMap) AddContextMap(otherClcMap ClassLoaderContextMap, implicitRootLib string) {
+ if otherClcMap == nil {
+ return
+ }
+
+ // If the implicit root of the merged map is already present as one of top-level subtrees, do
+ // not merge it second time.
+ for _, clc := range clcMap[AnySdkVersion] {
+ if clc.Name == implicitRootLib {
+ return
+ }
+ }
+
+ for sdkVer, otherClcs := range otherClcMap {
+ for _, otherClc := range otherClcs {
+ alreadyHave := false
+ for _, clc := range clcMap[sdkVer] {
+ if clc.Name == otherClc.Name {
+ alreadyHave = true
+ break
+ }
+ }
+ if !alreadyHave {
+ clcMap[sdkVer] = append(clcMap[sdkVer], otherClc)
+ }
+ }
+ }
+}
+
+// List of libraries in the unconditional class loader context, excluding dependencies of shared
+// libraries. These libraries should be in the <uses-library> tags in the manifest. Some of them may
+// be present in the original manifest, others are added by the manifest_fixer.
+func (clcMap ClassLoaderContextMap) UsesLibs() (ulibs []string) {
+ if clcMap != nil {
+ // compatibility libraries (those in conditional context) are not added to <uses-library> tags
+ ulibs = usesLibsRec(clcMap[AnySdkVersion])
+ ulibs = android.FirstUniqueStrings(ulibs)
+ }
+ return ulibs
+}
+
+func usesLibsRec(clcs []*ClassLoaderContext) (ulibs []string) {
+ for _, clc := range clcs {
+ ulibs = append(ulibs, clc.Name)
+ // <uses-library> tags in the manifest should not include dependencies of shared libraries,
+ // because PackageManager already tracks all such dependencies and automatically adds their
+ // class loader contexts as subcontext of the shared library.
+ if !clc.IsSharedLibrary {
+ ulibs = append(ulibs, usesLibsRec(clc.Subcontexts)...)
+ }
+ }
+ return ulibs
+}
+
+// Now that the full unconditional context is known, reconstruct conditional context.
+// Apply filters for individual libraries, mirroring what the PackageManager does when it
+// constructs class loader context on device.
+//
+// TODO(b/132357300): remove "android.hidl.manager" and "android.hidl.base" for non-system apps.
+//
+func fixClassLoaderContext(clcMap ClassLoaderContextMap) {
+ usesLibs := clcMap.UsesLibs()
+
+ for sdkVer, clcs := range clcMap {
+ if sdkVer == AnySdkVersion {
+ continue
+ }
+ fixedClcs := []*ClassLoaderContext{}
+ for _, clc := range clcs {
+ if android.InList(clc.Name, usesLibs) {
+ // skip compatibility libraries that are already included in unconditional context
+ } else if clc.Name == AndroidTestMock && !android.InList("android.test.runner", usesLibs) {
+ // android.test.mock is only needed as a compatibility library (in conditional class
+ // loader context) if android.test.runner is used, otherwise skip it
+ } else {
+ fixedClcs = append(fixedClcs, clc)
+ }
+ clcMap[sdkVer] = fixedClcs
+ }
+ }
+}
+
+// Return true if all build/install library paths are valid (including recursive subcontexts),
+// otherwise return false. A build path is valid if it's not nil. An install path is valid if it's
+// not equal to a special "error" value.
+func validateClassLoaderContext(clcMap ClassLoaderContextMap) (bool, error) {
+ for sdkVer, clcs := range clcMap {
+ if valid, err := validateClassLoaderContextRec(sdkVer, clcs); !valid || err != nil {
+ return valid, err
+ }
+ }
+ return true, nil
+}
+
+func validateClassLoaderContextRec(sdkVer int, clcs []*ClassLoaderContext) (bool, error) {
+ for _, clc := range clcs {
+ if clc.Host == nil || clc.Device == UnknownInstallLibraryPath {
+ if sdkVer == AnySdkVersion {
+ // Return error if dexpreopt doesn't know paths to one of the <uses-library>
+ // dependencies. In the future we may need to relax this and just disable dexpreopt.
+ return false, fmt.Errorf("invalid path for <uses-library> \"%s\"", clc.Name)
+ } else {
+ // No error for compatibility libraries, as Soong doesn't know if they are needed
+ // (this depends on the targetSdkVersion in the manifest), but the CLC is invalid.
+ return false, nil
+ }
+ }
+ if valid, err := validateClassLoaderContextRec(sdkVer, clc.Subcontexts); !valid || err != nil {
+ return valid, err
+ }
+ }
+ return true, nil
+}
+
+// Return the class loader context as a string, and a slice of build paths for all dependencies.
+// Perform a depth-first preorder traversal of the class loader context tree for each SDK version.
+// Return the resulting string and a slice of on-host build paths to all library dependencies.
+func ComputeClassLoaderContext(clcMap ClassLoaderContextMap) (clcStr string, paths android.Paths) {
+ for _, sdkVer := range android.SortedIntKeys(clcMap) { // determinisitc traversal order
+ sdkVerStr := fmt.Sprintf("%d", sdkVer)
+ if sdkVer == AnySdkVersion {
+ sdkVerStr = "any" // a special keyword that means any SDK version
+ }
+ hostClc, targetClc, hostPaths := computeClassLoaderContextRec(clcMap[sdkVer])
+ if hostPaths != nil {
+ clcStr += fmt.Sprintf(" --host-context-for-sdk %s %s", sdkVerStr, hostClc)
+ clcStr += fmt.Sprintf(" --target-context-for-sdk %s %s", sdkVerStr, targetClc)
+ }
+ paths = append(paths, hostPaths...)
+ }
+ return clcStr, android.FirstUniquePaths(paths)
+}
+
+func computeClassLoaderContextRec(clcs []*ClassLoaderContext) (string, string, android.Paths) {
+ var paths android.Paths
+ var clcsHost, clcsTarget []string
+
+ for _, clc := range clcs {
+ subClcHost, subClcTarget, subPaths := computeClassLoaderContextRec(clc.Subcontexts)
+ if subPaths != nil {
+ subClcHost = "{" + subClcHost + "}"
+ subClcTarget = "{" + subClcTarget + "}"
+ }
+
+ clcsHost = append(clcsHost, "PCL["+clc.Host.String()+"]"+subClcHost)
+ clcsTarget = append(clcsTarget, "PCL["+clc.Device+"]"+subClcTarget)
+
+ paths = append(paths, clc.Host)
+ paths = append(paths, subPaths...)
+ }
+
+ clcHost := strings.Join(clcsHost, "#")
+ clcTarget := strings.Join(clcsTarget, "#")
+
+ return clcHost, clcTarget, paths
+}
+
+// Paths to a <uses-library> on host and on device.
+type jsonLibraryPath struct {
+ Host string
+ Device string
+}
+
+// Class loader contexts that come from Make (via JSON dexpreopt.config) files have simpler
+// structure than Soong class loader contexts: they are flat maps from a <uses-library> name to its
+// on-host and on-device paths. There are no nested subcontexts. It is a limitation of the current
+// Make implementation.
+type jsonClassLoaderContext map[string]jsonLibraryPath
+
+// A map from SDK version (represented with a JSON string) to JSON class loader context.
+type jsonClassLoaderContextMap map[string]jsonClassLoaderContext
+
+// Convert JSON class loader context map to ClassLoaderContextMap.
+func fromJsonClassLoaderContext(ctx android.PathContext, jClcMap jsonClassLoaderContextMap) ClassLoaderContextMap {
+ clcMap := make(ClassLoaderContextMap)
+ for sdkVerStr, clc := range jClcMap {
+ sdkVer, ok := strconv.Atoi(sdkVerStr)
+ if ok != nil {
+ if sdkVerStr == "any" {
+ sdkVer = AnySdkVersion
+ } else {
+ android.ReportPathErrorf(ctx, "failed to parse SDK version in dexpreopt.config: '%s'", sdkVerStr)
+ }
+ }
+ for lib, path := range clc {
+ clcMap[sdkVer] = append(clcMap[sdkVer], &ClassLoaderContext{
+ Name: lib,
+ Host: constructPath(ctx, path.Host),
+ Device: path.Device,
+ Subcontexts: nil,
+ })
+ }
+ }
+ return clcMap
+}
diff --git a/dexpreopt/class_loader_context_test.go b/dexpreopt/class_loader_context_test.go
new file mode 100644
index 0000000..abfca27
--- /dev/null
+++ b/dexpreopt/class_loader_context_test.go
@@ -0,0 +1,236 @@
+// 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 dexpreopt
+
+// This file contains unit tests for class loader context structure.
+// For class loader context tests involving .bp files, see TestUsesLibraries in java package.
+
+import (
+ "reflect"
+ "strings"
+ "testing"
+
+ "android/soong/android"
+)
+
+const (
+ shared = true // dependencies are not added to uses libs
+ nonshared = false // dependencies are added to uses libs
+)
+
+func TestCLC(t *testing.T) {
+ // Construct class loader context with the following structure:
+ // .
+ // ├── 29
+ // │ ├── android.hidl.manager
+ // │ └── android.hidl.base
+ // │
+ // └── any
+ // ├── a
+ // ├── b
+ // ├── c
+ // ├── d
+ // │ ├── a2
+ // │ ├── b2
+ // │ └── c2
+ // │ ├── a1
+ // │ └── b1
+ // ├── f
+ // ├── a3
+ // └── b3
+ //
+ ctx := testContext()
+
+ m := make(ClassLoaderContextMap)
+
+ m.AddContext(ctx, "a", nonshared, buildPath(ctx, "a"), installPath(ctx, "a"))
+ m.AddContext(ctx, "b", shared, buildPath(ctx, "b"), installPath(ctx, "b"))
+
+ // "Maybe" variant in the good case: add as usual.
+ c := "c"
+ m.MaybeAddContext(ctx, &c, nonshared, buildPath(ctx, "c"), installPath(ctx, "c"))
+
+ // "Maybe" variant in the bad case: don't add library with unknown name, keep going.
+ m.MaybeAddContext(ctx, nil, nonshared, nil, nil)
+
+ // Add some libraries with nested subcontexts.
+
+ m1 := make(ClassLoaderContextMap)
+ m1.AddContext(ctx, "a1", nonshared, buildPath(ctx, "a1"), installPath(ctx, "a1"))
+ m1.AddContext(ctx, "b1", shared, buildPath(ctx, "b1"), installPath(ctx, "b1"))
+
+ m2 := make(ClassLoaderContextMap)
+ m2.AddContext(ctx, "a2", nonshared, buildPath(ctx, "a2"), installPath(ctx, "a2"))
+ m2.AddContext(ctx, "b2", shared, buildPath(ctx, "b2"), installPath(ctx, "b2"))
+ m2.AddContextForSdk(ctx, AnySdkVersion, "c2", shared, buildPath(ctx, "c2"), installPath(ctx, "c2"), m1)
+
+ m3 := make(ClassLoaderContextMap)
+ m3.AddContext(ctx, "a3", nonshared, buildPath(ctx, "a3"), installPath(ctx, "a3"))
+ m3.AddContext(ctx, "b3", shared, buildPath(ctx, "b3"), installPath(ctx, "b3"))
+
+ m.AddContextForSdk(ctx, AnySdkVersion, "d", nonshared, buildPath(ctx, "d"), installPath(ctx, "d"), m2)
+ // When the same library is both in conditional and unconditional context, it should be removed
+ // from conditional context.
+ m.AddContextForSdk(ctx, 42, "f", nonshared, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
+ m.AddContextForSdk(ctx, AnySdkVersion, "f", nonshared, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
+
+ // Merge map with implicit root library that is among toplevel contexts => does nothing.
+ m.AddContextMap(m1, "c")
+ // Merge map with implicit root library that is not among toplevel contexts => all subcontexts
+ // of the other map are added as toplevel contexts.
+ m.AddContextMap(m3, "m_g")
+
+ // Compatibility libraries with unknown install paths get default paths.
+ m.AddContextForSdk(ctx, 29, AndroidHidlManager, nonshared, buildPath(ctx, AndroidHidlManager), nil, nil)
+ m.AddContextForSdk(ctx, 29, AndroidHidlBase, nonshared, buildPath(ctx, AndroidHidlBase), nil, nil)
+
+ // Add "android.test.mock" to conditional CLC, observe that is gets removed because it is only
+ // needed as a compatibility library if "android.test.runner" is in CLC as well.
+ m.AddContextForSdk(ctx, 30, AndroidTestMock, nonshared, buildPath(ctx, AndroidTestMock), nil, nil)
+
+ valid, validationError := validateClassLoaderContext(m)
+
+ fixClassLoaderContext(m)
+
+ var haveStr string
+ var havePaths android.Paths
+ var haveUsesLibs []string
+ if valid && validationError == nil {
+ haveStr, havePaths = ComputeClassLoaderContext(m)
+ haveUsesLibs = m.UsesLibs()
+ }
+
+ // Test that validation is successful (all paths are known).
+ t.Run("validate", func(t *testing.T) {
+ if !(valid && validationError == nil) {
+ t.Errorf("invalid class loader context")
+ }
+ })
+
+ // Test that class loader context structure is correct.
+ t.Run("string", func(t *testing.T) {
+ wantStr := " --host-context-for-sdk 29 " +
+ "PCL[out/" + AndroidHidlManager + ".jar]#" +
+ "PCL[out/" + AndroidHidlBase + ".jar]" +
+ " --target-context-for-sdk 29 " +
+ "PCL[/system/framework/" + AndroidHidlManager + ".jar]#" +
+ "PCL[/system/framework/" + AndroidHidlBase + ".jar]" +
+ " --host-context-for-sdk any " +
+ "PCL[out/a.jar]#PCL[out/b.jar]#PCL[out/c.jar]#PCL[out/d.jar]" +
+ "{PCL[out/a2.jar]#PCL[out/b2.jar]#PCL[out/c2.jar]" +
+ "{PCL[out/a1.jar]#PCL[out/b1.jar]}}#" +
+ "PCL[out/f.jar]#PCL[out/a3.jar]#PCL[out/b3.jar]" +
+ " --target-context-for-sdk any " +
+ "PCL[/system/a.jar]#PCL[/system/b.jar]#PCL[/system/c.jar]#PCL[/system/d.jar]" +
+ "{PCL[/system/a2.jar]#PCL[/system/b2.jar]#PCL[/system/c2.jar]" +
+ "{PCL[/system/a1.jar]#PCL[/system/b1.jar]}}#" +
+ "PCL[/system/f.jar]#PCL[/system/a3.jar]#PCL[/system/b3.jar]"
+ if wantStr != haveStr {
+ t.Errorf("\nwant class loader context: %s\nhave class loader context: %s", wantStr, haveStr)
+ }
+ })
+
+ // Test that all expected build paths are gathered.
+ t.Run("paths", func(t *testing.T) {
+ wantPaths := []string{
+ "out/android.hidl.manager-V1.0-java.jar", "out/android.hidl.base-V1.0-java.jar",
+ "out/a.jar", "out/b.jar", "out/c.jar", "out/d.jar",
+ "out/a2.jar", "out/b2.jar", "out/c2.jar",
+ "out/a1.jar", "out/b1.jar",
+ "out/f.jar", "out/a3.jar", "out/b3.jar",
+ }
+ if !reflect.DeepEqual(wantPaths, havePaths.Strings()) {
+ t.Errorf("\nwant paths: %s\nhave paths: %s", wantPaths, havePaths)
+ }
+ })
+
+ // Test for libraries that are added by the manifest_fixer.
+ t.Run("uses libs", func(t *testing.T) {
+ wantUsesLibs := []string{"a", "b", "c", "d", "a2", "b2", "c2", "f", "a3", "b3"}
+ if !reflect.DeepEqual(wantUsesLibs, haveUsesLibs) {
+ t.Errorf("\nwant uses libs: %s\nhave uses libs: %s", wantUsesLibs, haveUsesLibs)
+ }
+ })
+}
+
+// Test that an unexpected unknown build path causes immediate error.
+func TestCLCUnknownBuildPath(t *testing.T) {
+ ctx := testContext()
+ m := make(ClassLoaderContextMap)
+ err := m.addContext(ctx, AnySdkVersion, "a", nonshared, nil, nil, true, nil)
+ checkError(t, err, "unknown build path to <uses-library> \"a\"")
+}
+
+// Test that an unexpected unknown install path causes immediate error.
+func TestCLCUnknownInstallPath(t *testing.T) {
+ ctx := testContext()
+ m := make(ClassLoaderContextMap)
+ err := m.addContext(ctx, AnySdkVersion, "a", nonshared, buildPath(ctx, "a"), nil, true, nil)
+ checkError(t, err, "unknown install path to <uses-library> \"a\"")
+}
+
+func TestCLCMaybeAdd(t *testing.T) {
+ ctx := testContext()
+
+ m := make(ClassLoaderContextMap)
+ a := "a"
+ m.MaybeAddContext(ctx, &a, nonshared, nil, nil)
+
+ // The library should be added to <uses-library> tags by the manifest_fixer.
+ t.Run("maybe add", func(t *testing.T) {
+ haveUsesLibs := m.UsesLibs()
+ wantUsesLibs := []string{"a"}
+ if !reflect.DeepEqual(wantUsesLibs, haveUsesLibs) {
+ t.Errorf("\nwant uses libs: %s\nhave uses libs: %s", wantUsesLibs, haveUsesLibs)
+ }
+ })
+
+ // But class loader context in such cases should raise an error on validation.
+ t.Run("validate", func(t *testing.T) {
+ _, err := validateClassLoaderContext(m)
+ checkError(t, err, "invalid path for <uses-library> \"a\"")
+ })
+}
+
+// An attempt to add conditional nested subcontext should fail.
+func TestCLCNestedConditional(t *testing.T) {
+ ctx := testContext()
+ m1 := make(ClassLoaderContextMap)
+ m1.AddContextForSdk(ctx, 42, "a", nonshared, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
+ m := make(ClassLoaderContextMap)
+ err := m.addContext(ctx, AnySdkVersion, "b", nonshared, buildPath(ctx, "b"), installPath(ctx, "b"), true, m1)
+ checkError(t, err, "nested class loader context shouldn't have conditional part")
+}
+
+func checkError(t *testing.T, have error, want string) {
+ if have == nil {
+ t.Errorf("\nwant error: '%s'\nhave: none", want)
+ } else if msg := have.Error(); !strings.HasPrefix(msg, want) {
+ t.Errorf("\nwant error: '%s'\nhave error: '%s'\n", want, msg)
+ }
+}
+
+func testContext() android.ModuleInstallPathContext {
+ config := android.TestConfig("out", nil, "", nil)
+ return android.ModuleInstallPathContextForTesting(config)
+}
+
+func buildPath(ctx android.PathContext, lib string) android.Path {
+ return android.PathForOutput(ctx, lib+".jar")
+}
+
+func installPath(ctx android.ModuleInstallPathContext, lib string) android.InstallPath {
+ return android.PathForModuleInstall(ctx, lib+".jar")
+}
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 21f7bb3..f52ecb4 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -100,94 +100,6 @@
ConstructContext android.Path
}
-// These libs are added as optional dependencies (<uses-library> with android:required set to false).
-// This is because they haven't existed prior to certain SDK version, but classes in them were in
-// bootclasspath jars, etc. So making them hard dependencies (android:required=true) would prevent
-// apps from being installed to such legacy devices.
-var OptionalCompatUsesLibs = []string{
- "org.apache.http.legacy",
- "android.test.base",
- "android.test.mock",
-}
-
-var CompatUsesLibs = []string{
- "android.hidl.base-V1.0-java",
- "android.hidl.manager-V1.0-java",
-}
-
-const UnknownInstallLibraryPath = "error"
-
-// LibraryPath contains paths to the library DEX jar on host and on device.
-type LibraryPath struct {
- Host android.Path
- Device string
-}
-
-// LibraryPaths is a map from library name to on-host and on-device paths to its DEX jar.
-type LibraryPaths map[string]*LibraryPath
-
-// Add a new library path to the map, unless a path for this library already exists.
-// If necessary, check that the build and install paths exist.
-func (libPaths LibraryPaths) addLibraryPath(ctx android.ModuleContext, lib string,
- hostPath, installPath android.Path, strict bool) {
-
- // If missing dependencies are allowed, the build shouldn't fail when a <uses-library> is
- // not found. However, this is likely to result is disabling dexpreopt, as it won't be
- // possible to construct class loader context without on-host and on-device library paths.
- strict = strict && !ctx.Config().AllowMissingDependencies()
-
- if hostPath == nil && strict {
- android.ReportPathErrorf(ctx, "unknown build path to <uses-library> '%s'", lib)
- }
-
- if installPath == nil {
- if android.InList(lib, CompatUsesLibs) || android.InList(lib, OptionalCompatUsesLibs) {
- // Assume that compatibility libraries are installed in /system/framework.
- installPath = android.PathForModuleInstall(ctx, "framework", lib+".jar")
- } else if strict {
- android.ReportPathErrorf(ctx, "unknown install path to <uses-library> '%s'", lib)
- }
- }
-
- // Add a library only if the build and install path to it is known.
- if _, present := libPaths[lib]; !present {
- var devicePath string
- if installPath != nil {
- devicePath = android.InstallPathToOnDevicePath(ctx, installPath.(android.InstallPath))
- } else {
- // For some stub libraries the only known thing is the name of their implementation
- // library, but the library itself is unavailable (missing or part of a prebuilt). In
- // such cases we still need to add the library to <uses-library> tags in the manifest,
- // but we cannot use if for dexpreopt.
- devicePath = UnknownInstallLibraryPath
- }
- libPaths[lib] = &LibraryPath{hostPath, devicePath}
- }
-}
-
-// Add a new library path to the map. Enforce checks that the library paths exist.
-func (libPaths LibraryPaths) AddLibraryPath(ctx android.ModuleContext, lib string, hostPath, installPath android.Path) {
- libPaths.addLibraryPath(ctx, lib, hostPath, installPath, true)
-}
-
-// Add a new library path to the map, if the library exists (name is not nil).
-// Don't enforce checks that the library paths exist. Some libraries may be missing from the build,
-// but their names still need to be added to <uses-library> tags in the manifest.
-func (libPaths LibraryPaths) MaybeAddLibraryPath(ctx android.ModuleContext, lib *string, hostPath, installPath android.Path) {
- if lib != nil {
- libPaths.addLibraryPath(ctx, *lib, hostPath, installPath, false)
- }
-}
-
-// Add library paths from the second map to the first map (do not override existing entries).
-func (libPaths LibraryPaths) AddLibraryPaths(otherPaths LibraryPaths) {
- for lib, path := range otherPaths {
- if _, present := libPaths[lib]; !present {
- libPaths[lib] = path
- }
- }
-}
-
type ModuleConfig struct {
Name string
DexLocation string // dex location on device
@@ -202,10 +114,8 @@
ProfileIsTextListing bool
ProfileBootListing android.OptionalPath
- EnforceUsesLibraries bool
- OptionalUsesLibraries []string
- UsesLibraries []string
- LibraryPaths LibraryPaths
+ EnforceUsesLibraries bool
+ ClassLoaderContexts ClassLoaderContextMap
Archs []android.ArchType
DexPreoptImages []android.Path
@@ -268,12 +178,8 @@
// Copies of entries in GlobalConfig that are not constructable without extra parameters. They will be
// used to construct the real value manually below.
- BootJars []string
- UpdatableBootJars []string
- ArtApexJars []string
- UpdatableSystemServerJars []string
- DirtyImageObjects string
- BootImageProfiles []string
+ DirtyImageObjects string
+ BootImageProfiles []string
}
config := GlobalJSONConfig{}
@@ -283,10 +189,6 @@
}
// Construct paths that require a PathContext.
- config.GlobalConfig.BootJars = android.CreateConfiguredJarList(ctx, config.BootJars)
- config.GlobalConfig.UpdatableBootJars = android.CreateConfiguredJarList(ctx, config.UpdatableBootJars)
- config.GlobalConfig.ArtApexJars = android.CreateConfiguredJarList(ctx, config.ArtApexJars)
- config.GlobalConfig.UpdatableSystemServerJars = android.CreateConfiguredJarList(ctx, config.UpdatableSystemServerJars)
config.GlobalConfig.DirtyImageObjects = android.OptionalPathForPath(constructPath(ctx, config.DirtyImageObjects))
config.GlobalConfig.BootImageProfiles = constructPaths(ctx, config.BootImageProfiles)
@@ -352,13 +254,6 @@
// from Make to read the module dexpreopt.config written in the Make config
// stage.
func ParseModuleConfig(ctx android.PathContext, data []byte) (*ModuleConfig, error) {
- type jsonLibraryPath struct {
- Host string
- Device string
- }
-
- type jsonLibraryPaths map[string]jsonLibraryPath
-
type ModuleJSONConfig struct {
*ModuleConfig
@@ -368,24 +263,12 @@
DexPath string
ManifestPath string
ProfileClassListing string
- LibraryPaths jsonLibraryPaths
+ ClassLoaderContexts jsonClassLoaderContextMap
DexPreoptImages []string
DexPreoptImageLocations []string
PreoptBootClassPathDexFiles []string
}
- // convert JSON map of library paths to LibraryPaths
- constructLibraryPaths := func(ctx android.PathContext, paths jsonLibraryPaths) LibraryPaths {
- m := LibraryPaths{}
- for lib, path := range paths {
- m[lib] = &LibraryPath{
- constructPath(ctx, path.Host),
- path.Device,
- }
- }
- return m
- }
-
config := ModuleJSONConfig{}
err := json.Unmarshal(data, &config)
@@ -398,7 +281,7 @@
config.ModuleConfig.DexPath = constructPath(ctx, config.DexPath)
config.ModuleConfig.ManifestPath = constructPath(ctx, config.ManifestPath)
config.ModuleConfig.ProfileClassListing = android.OptionalPathForPath(constructPath(ctx, config.ProfileClassListing))
- config.ModuleConfig.LibraryPaths = constructLibraryPaths(ctx, config.LibraryPaths)
+ config.ModuleConfig.ClassLoaderContexts = fromJsonClassLoaderContext(ctx, config.ClassLoaderContexts)
config.ModuleConfig.DexPreoptImages = constructPaths(ctx, config.DexPreoptImages)
config.ModuleConfig.DexPreoptImageLocations = config.DexPreoptImageLocations
config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles)
@@ -603,13 +486,7 @@
return
}
- ctx.Build(pctx, android.BuildParams{
- Rule: android.WriteFile,
- Output: android.PathForOutput(ctx, "dexpreopt_soong.config"),
- Args: map[string]string{
- "content": string(data),
- },
- })
+ android.WriteFileRule(ctx, android.PathForOutput(ctx, "dexpreopt_soong.config"), string(data))
}
func (s *globalSoongConfigSingleton) MakeVars(ctx android.MakeVarsContext) {
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 4dbda49..65380fe 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -81,14 +81,18 @@
}
if !dexpreoptDisabled(ctx, global, module) {
- if clc := genClassLoaderContext(ctx, global, module); clc != nil {
+ if valid, err := validateClassLoaderContext(module.ClassLoaderContexts); err != nil {
+ android.ReportPathErrorf(ctx, err.Error())
+ } else if valid {
+ fixClassLoaderContext(module.ClassLoaderContexts)
+
appImage := (generateProfile || module.ForceCreateAppImage || global.DefaultAppImages) &&
!module.NoCreateAppImage
generateDM := shouldGenerateDM(module, global)
for archIdx, _ := range module.Archs {
- dexpreoptCommand(ctx, globalSoong, global, module, rule, archIdx, *clc, profile, appImage, generateDM)
+ dexpreoptCommand(ctx, globalSoong, global, module, rule, archIdx, profile, appImage, generateDM)
}
}
}
@@ -194,124 +198,9 @@
return profilePath
}
-type classLoaderContext struct {
- // The class loader context using paths in the build.
- Host android.Paths
-
- // The class loader context using paths as they will be on the device.
- Target []string
-}
-
-// A map of class loader contexts for each SDK version.
-// A map entry for "any" version contains libraries that are unconditionally added to class loader
-// context. Map entries for existing versions contains libraries that were in the default classpath
-// until that API version, and should be added to class loader context if and only if the
-// targetSdkVersion in the manifest or APK is less than that API version.
-type classLoaderContextMap map[int]*classLoaderContext
-
-const anySdkVersion int = 9999 // should go last in class loader context
-
-func (m classLoaderContextMap) getValue(sdkVer int) *classLoaderContext {
- if _, ok := m[sdkVer]; !ok {
- m[sdkVer] = &classLoaderContext{}
- }
- return m[sdkVer]
-}
-
-func (m classLoaderContextMap) addLibs(sdkVer int, module *ModuleConfig, libs ...string) bool {
- clc := m.getValue(sdkVer)
- for _, lib := range libs {
- if p := pathForLibrary(module, lib); p != nil {
- clc.Host = append(clc.Host, p.Host)
- clc.Target = append(clc.Target, p.Device)
- } else {
- return false
- }
- }
- return true
-}
-
-func (m classLoaderContextMap) addSystemServerLibs(sdkVer int, ctx android.PathContext, module *ModuleConfig, libs ...string) {
- clc := m.getValue(sdkVer)
- for _, lib := range libs {
- clc.Host = append(clc.Host, SystemServerDexJarHostPath(ctx, lib))
- clc.Target = append(clc.Target, filepath.Join("/system/framework", lib+".jar"))
- }
-}
-
-// genClassLoaderContext generates host and target class loader context to be passed to the dex2oat
-// command for the dexpreopted module. There are three possible cases:
-//
-// 1. System server jars. They have a special class loader context that includes other system
-// server jars.
-//
-// 2. Library jars or APKs which have precise list of their <uses-library> libs. Their class loader
-// context includes build and on-device paths to these libs. In some cases it may happen that
-// the path to a <uses-library> is unknown (e.g. the dexpreopted module may depend on stubs
-// library, whose implementation library is missing from the build altogether). In such case
-// dexpreopting with the <uses-library> is impossible, and dexpreopting without it is pointless,
-// as the runtime classpath won't match and the dexpreopted code will be discarded. Therefore in
-// such cases the function returns nil, which disables dexpreopt.
-//
-// 2. All other library jars or APKs for which the exact <uses-library> list is unknown. They use
-// the unsafe &-classpath workaround that means empty class loader context and absence of runtime
-// check that the class loader context provided by the PackageManager agrees with the stored
-// class loader context recorded in the .odex file.
-//
-func genClassLoaderContext(ctx android.PathContext, global *GlobalConfig, module *ModuleConfig) *classLoaderContextMap {
- classLoaderContexts := make(classLoaderContextMap)
- systemServerJars := NonUpdatableSystemServerJars(ctx, global)
-
- if jarIndex := android.IndexList(module.Name, systemServerJars); jarIndex >= 0 {
- // System server jars should be dexpreopted together: class loader context of each jar
- // should include all preceding jars on the system server classpath.
- classLoaderContexts.addSystemServerLibs(anySdkVersion, ctx, module, systemServerJars[:jarIndex]...)
-
- } else if module.EnforceUsesLibraries {
- // Unconditional class loader context.
- usesLibs := append(copyOf(module.UsesLibraries), module.OptionalUsesLibraries...)
- if !classLoaderContexts.addLibs(anySdkVersion, module, usesLibs...) {
- return nil
- }
-
- // Conditional class loader context for API version < 28.
- const httpLegacy = "org.apache.http.legacy"
- if !contains(usesLibs, httpLegacy) {
- if !classLoaderContexts.addLibs(28, module, httpLegacy) {
- return nil
- }
- }
-
- // Conditional class loader context for API version < 29.
- usesLibs29 := []string{
- "android.hidl.base-V1.0-java",
- "android.hidl.manager-V1.0-java",
- }
- if !classLoaderContexts.addLibs(29, module, usesLibs29...) {
- return nil
- }
-
- // Conditional class loader context for API version < 30.
- const testBase = "android.test.base"
- if !contains(usesLibs, testBase) {
- if !classLoaderContexts.addLibs(30, module, testBase) {
- return nil
- }
- }
-
- } else {
- // Pass special class loader context to skip the classpath and collision check.
- // This will get removed once LOCAL_USES_LIBRARIES is enforced.
- // Right now LOCAL_USES_LIBRARIES is opt in, for the case where it's not specified we still default
- // to the &.
- }
-
- return &classLoaderContexts
-}
-
func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig,
- module *ModuleConfig, rule *android.RuleBuilder, archIdx int, classLoaderContexts classLoaderContextMap,
- profile android.WritablePath, appImage bool, generateDM bool) {
+ module *ModuleConfig, rule *android.RuleBuilder, archIdx int, profile android.WritablePath,
+ appImage bool, generateDM bool) {
arch := module.Archs[archIdx]
@@ -348,6 +237,16 @@
rule.Command().FlagWithOutput("rm -f ", odexPath)
if jarIndex := android.IndexList(module.Name, systemServerJars); jarIndex >= 0 {
+ // System server jars should be dexpreopted together: class loader context of each jar
+ // should include all preceding jars on the system server classpath.
+
+ var clcHost android.Paths
+ var clcTarget []string
+ for _, lib := range systemServerJars[:jarIndex] {
+ clcHost = append(clcHost, SystemServerDexJarHostPath(ctx, lib))
+ clcTarget = append(clcTarget, filepath.Join("/system/framework", lib+".jar"))
+ }
+
// Copy the system server jar to a predefined location where dex2oat will find it.
dexPathHost := SystemServerDexJarHostPath(ctx, module.Name)
rule.Command().Text("mkdir -p").Flag(filepath.Dir(dexPathHost.String()))
@@ -355,11 +254,11 @@
checkSystemServerOrder(ctx, jarIndex)
- clc := classLoaderContexts[anySdkVersion]
rule.Command().
- Text("class_loader_context_arg=--class-loader-context=PCL[" + strings.Join(clc.Host.Strings(), ":") + "]").
- Implicits(clc.Host).
- Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + strings.Join(clc.Target, ":") + "]")
+ Text("class_loader_context_arg=--class-loader-context=PCL[" + strings.Join(clcHost.Strings(), ":") + "]").
+ Implicits(clcHost).
+ Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + strings.Join(clcTarget, ":") + "]")
+
} else if module.EnforceUsesLibraries {
// Generate command that saves target SDK version in a shell variable.
if module.ManifestPath != nil {
@@ -379,21 +278,15 @@
}
// Generate command that saves host and target class loader context in shell variables.
+ clc, paths := ComputeClassLoaderContext(module.ClassLoaderContexts)
cmd := rule.Command().
Text(`eval "$(`).Tool(globalSoong.ConstructContext).
- Text(` --target-sdk-version ${target_sdk_version}`)
- for _, ver := range android.SortedIntKeys(classLoaderContexts) {
- clc := classLoaderContexts.getValue(ver)
- verString := fmt.Sprintf("%d", ver)
- if ver == anySdkVersion {
- verString = "any" // a special keyword that means any SDK version
- }
- cmd.Textf(`--host-classpath-for-sdk %s %s`, verString, strings.Join(clc.Host.Strings(), ":")).
- Implicits(clc.Host).
- Textf(`--target-classpath-for-sdk %s %s`, verString, strings.Join(clc.Target, ":"))
- }
+ Text(` --target-sdk-version ${target_sdk_version}`).
+ Text(clc).Implicits(paths)
cmd.Text(`)"`)
+
} else {
+ // Other libraries or APKs for which the exact <uses-library> list is unknown.
// Pass special class loader context to skip the classpath and collision check.
// This will get removed once LOCAL_USES_LIBRARIES is enforced.
// Right now LOCAL_USES_LIBRARIES is opt in, for the case where it's not specified we still default
@@ -589,14 +482,6 @@
return filepath.Join(filepath.Dir(filepath.Dir(path.String())), filepath.Base(path.String()))
}
-func pathForLibrary(module *ModuleConfig, lib string) *LibraryPath {
- if path, ok := module.LibraryPaths[lib]; ok && path.Host != nil && path.Device != "error" {
- return path
- } else {
- return nil
- }
-}
-
func makefileMatch(pattern, s string) bool {
percent := strings.IndexByte(pattern, '%')
switch percent {
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index ec31549..feabd70 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -44,9 +44,7 @@
ProfileClassListing: android.OptionalPath{},
ProfileIsTextListing: false,
EnforceUsesLibraries: false,
- OptionalUsesLibraries: nil,
- UsesLibraries: nil,
- LibraryPaths: nil,
+ ClassLoaderContexts: nil,
Archs: []android.ArchType{android.Arm},
DexPreoptImages: android.Paths{android.PathForTesting("system/framework/arm/boot.art")},
DexPreoptImagesDeps: []android.OutputPaths{android.OutputPaths{}},
diff --git a/docs/OWNERS b/docs/OWNERS
new file mode 100644
index 0000000..d143317
--- /dev/null
+++ b/docs/OWNERS
@@ -0,0 +1 @@
+per-file map_files.md = danalbert@google.com, enh@google.com, jiyong@google.com
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 5dd2a86..44b8149 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -59,8 +59,19 @@
Filename_from_src *bool `android:"arch_variant"`
// Make this module available when building for ramdisk.
+ // On device without a dedicated recovery partition, the module is only
+ // available after switching root into
+ // /first_stage_ramdisk. To expose the module before switching root, install
+ // the recovery variant instead.
Ramdisk_available *bool
+ // Make this module available when building for vendor ramdisk.
+ // On device without a dedicated recovery partition, the module is only
+ // available after switching root into
+ // /first_stage_ramdisk. To expose the module before switching root, install
+ // the recovery variant instead.
+ Vendor_ramdisk_available *bool
+
// Make this module available when building for recovery.
Recovery_available *bool
@@ -105,6 +116,18 @@
return p.inRamdisk()
}
+func (p *PrebuiltEtc) inVendorRamdisk() bool {
+ return p.ModuleBase.InVendorRamdisk() || p.ModuleBase.InstallInVendorRamdisk()
+}
+
+func (p *PrebuiltEtc) onlyInVendorRamdisk() bool {
+ return p.ModuleBase.InstallInVendorRamdisk()
+}
+
+func (p *PrebuiltEtc) InstallInVendorRamdisk() bool {
+ return p.inVendorRamdisk()
+}
+
func (p *PrebuiltEtc) inRecovery() bool {
return p.ModuleBase.InRecovery() || p.ModuleBase.InstallInRecovery()
}
@@ -122,13 +145,18 @@
func (p *PrebuiltEtc) ImageMutatorBegin(ctx android.BaseModuleContext) {}
func (p *PrebuiltEtc) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
- return !p.ModuleBase.InstallInRecovery() && !p.ModuleBase.InstallInRamdisk()
+ return !p.ModuleBase.InstallInRecovery() && !p.ModuleBase.InstallInRamdisk() &&
+ !p.ModuleBase.InstallInVendorRamdisk()
}
func (p *PrebuiltEtc) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
return proptools.Bool(p.properties.Ramdisk_available) || p.ModuleBase.InstallInRamdisk()
}
+func (p *PrebuiltEtc) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return proptools.Bool(p.properties.Vendor_ramdisk_available) || p.ModuleBase.InstallInVendorRamdisk()
+}
+
func (p *PrebuiltEtc) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
return proptools.Bool(p.properties.Recovery_available) || p.ModuleBase.InstallInRecovery()
}
@@ -172,13 +200,7 @@
}
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 +227,13 @@
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.
@@ -214,6 +242,13 @@
Output: p.outputFilePath,
Input: p.sourceFilePath,
})
+
+ if p.Installable() {
+ installPath := ctx.InstallFile(p.installDirPath, p.outputFilePath.Base(), p.outputFilePath)
+ for _, sl := range p.properties.Symlinks {
+ ctx.InstallSymlink(p.installDirPath, sl, installPath)
+ }
+ }
}
func (p *PrebuiltEtc) AndroidMkEntries() []android.AndroidMkEntries {
@@ -221,6 +256,9 @@
if p.inRamdisk() && !p.onlyInRamdisk() {
nameSuffix = ".ramdisk"
}
+ if p.inVendorRamdisk() && !p.onlyInVendorRamdisk() {
+ nameSuffix = ".vendor_ramdisk"
+ }
if p.inRecovery() && !p.onlyInRecovery() {
nameSuffix = ".recovery"
}
diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go
index 8fc36c2..6c4c0b6 100644
--- a/etc/prebuilt_etc_test.go
+++ b/etc/prebuilt_etc_test.go
@@ -58,7 +58,7 @@
config := android.TestArchConfig(buildDir, nil, bp, fs)
- ctx := android.NewTestArchContext()
+ ctx := android.NewTestArchContext(config)
ctx.RegisterModuleType("prebuilt_etc", PrebuiltEtcFactory)
ctx.RegisterModuleType("prebuilt_etc_host", PrebuiltEtcHostFactory)
ctx.RegisterModuleType("prebuilt_usr_share", PrebuiltUserShareFactory)
@@ -66,7 +66,7 @@
ctx.RegisterModuleType("prebuilt_font", PrebuiltFontFactory)
ctx.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory)
ctx.RegisterModuleType("prebuilt_dsp", PrebuiltDSPFactory)
- ctx.Register(config)
+ ctx.Register()
return ctx, config
}
diff --git a/finder/finder.go b/finder/finder.go
index 6513fa3..5413fa6 100644
--- a/finder/finder.go
+++ b/finder/finder.go
@@ -103,6 +103,9 @@
// IncludeFiles are file names to include as matches
IncludeFiles []string
+
+ // IncludeSuffixes are filename suffixes to include as matches.
+ IncludeSuffixes []string
}
// a cacheConfig stores the inputs that determine what should be included in the cache
@@ -1310,6 +1313,20 @@
return stats
}
+func (f *Finder) shouldIncludeFile(fileName string) bool {
+ for _, includedName := range f.cacheMetadata.Config.IncludeFiles {
+ if fileName == includedName {
+ return true
+ }
+ }
+ for _, includeSuffix := range f.cacheMetadata.Config.IncludeSuffixes {
+ if strings.HasSuffix(fileName, includeSuffix) {
+ return true
+ }
+ }
+ return false
+}
+
// pruneCacheCandidates removes the items that we don't want to include in our persistent cache
func (f *Finder) pruneCacheCandidates(items *DirEntries) {
@@ -1326,13 +1343,9 @@
// remove any files that aren't the ones we want to include
writeIndex := 0
for _, fileName := range items.FileNames {
- // include only these files
- for _, includedName := range f.cacheMetadata.Config.IncludeFiles {
- if fileName == includedName {
- items.FileNames[writeIndex] = fileName
- writeIndex++
- break
- }
+ if f.shouldIncludeFile(fileName) {
+ items.FileNames[writeIndex] = fileName
+ writeIndex++
}
}
// resize
diff --git a/finder/finder_test.go b/finder/finder_test.go
index 88b0c05..788dbdd 100644
--- a/finder/finder_test.go
+++ b/finder/finder_test.go
@@ -21,6 +21,7 @@
"os"
"path/filepath"
"sort"
+ "strings"
"testing"
"android/soong/finder/fs"
@@ -92,6 +93,7 @@
nil,
nil,
[]string{"findme.txt", "skipme.txt"},
+ nil,
},
)
defer finder.Shutdown()
@@ -104,6 +106,46 @@
fs.AssertSameResponse(t, foundPaths, absoluteMatches)
}
+// runTestWithSuffixes creates a few files, searches for findme.txt or any file
+// with suffix `.findme_ext` and checks for the expected matches
+func runTestWithSuffixes(t *testing.T, existentPaths []string, expectedMatches []string) {
+ filesystem := newFs()
+ root := "/tmp"
+ filesystem.MkDirs(root)
+ for _, path := range existentPaths {
+ fs.Create(t, filepath.Join(root, path), filesystem)
+ }
+
+ finder := newFinder(t,
+ filesystem,
+ CacheParams{
+ "/cwd",
+ []string{root},
+ nil,
+ nil,
+ []string{"findme.txt", "skipme.txt"},
+ []string{".findme_ext"},
+ },
+ )
+ defer finder.Shutdown()
+
+ foundPaths := finder.FindMatching(root,
+ func(entries DirEntries) (dirs []string, files []string) {
+ matches := []string{}
+ for _, foundName := range entries.FileNames {
+ if foundName == "findme.txt" || strings.HasSuffix(foundName, ".findme_ext") {
+ matches = append(matches, foundName)
+ }
+ }
+ return entries.DirNames, matches
+ })
+ absoluteMatches := []string{}
+ for i := range expectedMatches {
+ absoluteMatches = append(absoluteMatches, filepath.Join(root, expectedMatches[i]))
+ }
+ fs.AssertSameResponse(t, foundPaths, absoluteMatches)
+}
+
// testAgainstSeveralThreadcounts runs the given test for each threadcount that we care to test
func testAgainstSeveralThreadcounts(t *testing.T, tester func(t *testing.T, numThreads int)) {
// test singlethreaded, multithreaded, and also using the same number of threads as
@@ -135,6 +177,13 @@
)
}
+func TestIncludeFilesAndSuffixes(t *testing.T) {
+ runTestWithSuffixes(t,
+ []string{"findme.txt", "skipme.txt", "alsome.findme_ext"},
+ []string{"findme.txt", "alsome.findme_ext"},
+ )
+}
+
func TestNestedDirectories(t *testing.T) {
runSimpleTest(t,
[]string{"findme.txt", "skipme.txt", "subdir/findme.txt", "subdir/skipme.txt"},
@@ -142,6 +191,13 @@
)
}
+func TestNestedDirectoriesWithSuffixes(t *testing.T) {
+ runTestWithSuffixes(t,
+ []string{"findme.txt", "skipme.txt", "subdir/findme.txt", "subdir/skipme.txt", "subdir/alsome.findme_ext"},
+ []string{"findme.txt", "subdir/findme.txt", "subdir/alsome.findme_ext"},
+ )
+}
+
func TestEmptyDirectory(t *testing.T) {
runSimpleTest(t,
[]string{},
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 1cec289..53b9dbe 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -81,6 +81,12 @@
label string
}
+// TODO(cparsons): Move to a common location when there is more than just
+// genrule with a bazel_module property.
+type bazelModuleProperties struct {
+ Label string
+}
+
type generatorProperties struct {
// The command to run on one or more input files. Cmd supports substitution of a few variables
//
@@ -113,8 +119,10 @@
// input files to exclude
Exclude_srcs []string `android:"path,arch_variant"`
-}
+ // in bazel-enabled mode, the bazel label to evaluate instead of this module
+ Bazel_module bazelModuleProperties
+}
type Module struct {
android.ModuleBase
android.DefaultableModuleBase
@@ -186,6 +194,20 @@
}
}
+// Returns true if information was available from Bazel, false if bazel invocation still needs to occur.
+func (c *Module) generateBazelBuildActions(ctx android.ModuleContext, label string) bool {
+ bazelCtx := ctx.Config().BazelContext
+ filePaths, ok := bazelCtx.GetAllFiles(label)
+ if ok {
+ var bazelOutputFiles android.Paths
+ for _, bazelOutputFile := range filePaths {
+ bazelOutputFiles = append(bazelOutputFiles, android.PathForSource(ctx, bazelOutputFile))
+ }
+ c.outputFiles = bazelOutputFiles
+ c.outputDeps = bazelOutputFiles
+ }
+ return ok
+}
func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
g.subName = ctx.ModuleSubDir()
@@ -456,26 +478,29 @@
g.outputFiles = outputFiles.Paths()
- // For <= 6 outputs, just embed those directly in the users. Right now, that covers >90% of
- // the genrules on AOSP. That will make things simpler to look at the graph in the common
- // case. For larger sets of outputs, inject a phony target in between to limit ninja file
- // growth.
- if len(g.outputFiles) <= 6 {
- g.outputDeps = g.outputFiles
- } else {
- phonyFile := android.PathForModuleGen(ctx, "genrule-phony")
-
- ctx.Build(pctx, android.BuildParams{
- Rule: blueprint.Phony,
- Output: phonyFile,
- Inputs: g.outputFiles,
- })
-
- g.outputDeps = android.Paths{phonyFile}
+ bazelModuleLabel := g.properties.Bazel_module.Label
+ bazelActionsUsed := false
+ if ctx.Config().BazelContext.BazelEnabled() && len(bazelModuleLabel) > 0 {
+ bazelActionsUsed = g.generateBazelBuildActions(ctx, bazelModuleLabel)
}
-
+ if !bazelActionsUsed {
+ // For <= 6 outputs, just embed those directly in the users. Right now, that covers >90% of
+ // the genrules on AOSP. That will make things simpler to look at the graph in the common
+ // case. For larger sets of outputs, inject a phony target in between to limit ninja file
+ // growth.
+ if len(g.outputFiles) <= 6 {
+ g.outputDeps = g.outputFiles
+ } else {
+ phonyFile := android.PathForModuleGen(ctx, "genrule-phony")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: blueprint.Phony,
+ Output: phonyFile,
+ Inputs: g.outputFiles,
+ })
+ g.outputDeps = android.Paths{phonyFile}
+ }
+ }
}
-
func hashSrcFiles(srcFiles android.Paths) string {
h := sha256.New()
for _, src := range srcFiles {
@@ -536,13 +561,12 @@
func (g *Module) AndroidMk() android.AndroidMkData {
return android.AndroidMkData{
- Include: "$(BUILD_PHONY_PACKAGE)",
- Class: "FAKE",
+ Class: "ETC",
OutputFile: android.OptionalPathForPath(g.outputFiles[0]),
SubName: g.subName,
Extra: []android.AndroidMkExtraFunc{
func(w io.Writer, outputFile android.Path) {
- fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES :=", strings.Join(g.outputDeps.Strings(), " "))
+ fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
},
},
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
@@ -555,7 +579,8 @@
}
}
-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
@@ -579,6 +604,7 @@
func (x noopImageInterface) ImageMutatorBegin(android.BaseModuleContext) {}
func (x noopImageInterface) CoreVariantNeeded(android.BaseModuleContext) bool { return false }
func (x noopImageInterface) RamdiskVariantNeeded(android.BaseModuleContext) bool { return false }
+func (x noopImageInterface) VendorRamdiskVariantNeeded(android.BaseModuleContext) bool { return false }
func (x noopImageInterface) RecoveryVariantNeeded(android.BaseModuleContext) bool { return false }
func (x noopImageInterface) ExtraImageVariations(ctx android.BaseModuleContext) []string { return nil }
func (x noopImageInterface) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 4b36600..c19078f 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -53,14 +53,14 @@
func testContext(config android.Config) *android.TestContext {
- ctx := android.NewTestArchContext()
+ ctx := android.NewTestArchContext(config)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("tool", toolFactory)
registerGenruleBuildComponents(ctx)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
- ctx.Register(config)
+ ctx.Register()
return ctx
}
@@ -721,6 +721,39 @@
}
}
+func TestGenruleWithBazel(t *testing.T) {
+ bp := `
+ genrule {
+ name: "foo",
+ out: ["one.txt", "two.txt"],
+ bazel_module: { label: "//foo/bar:bar" },
+ }
+ `
+
+ config := testConfig(bp, nil)
+ config.BazelContext = android.MockBazelContext{
+ AllFiles: map[string][]string{
+ "//foo/bar:bar": []string{"bazelone.txt", "bazeltwo.txt"}}}
+
+ ctx := testContext(config)
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ if errs == nil {
+ _, errs = ctx.PrepareBuildActions(config)
+ }
+ if errs != nil {
+ t.Fatal(errs)
+ }
+ gen := ctx.ModuleForTests("foo", "").Module().(*Module)
+
+ expectedOutputFiles := []string{"bazelone.txt", "bazeltwo.txt"}
+ if !reflect.DeepEqual(gen.outputFiles.Strings(), expectedOutputFiles) {
+ t.Errorf("Expected output files: %q, actual: %q", expectedOutputFiles, gen.outputFiles)
+ }
+ if !reflect.DeepEqual(gen.outputDeps.Strings(), expectedOutputFiles) {
+ t.Errorf("Expected output deps: %q, actual: %q", expectedOutputFiles, gen.outputDeps)
+ }
+}
+
type testTool struct {
android.ModuleBase
outputFile android.Path
diff --git a/java/Android.bp b/java/Android.bp
index 92e8ca4..9e8dc78 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -22,6 +22,7 @@
"androidmk.go",
"app_builder.go",
"app.go",
+ "boot_jars.go",
"builder.go",
"device_host_converter.go",
"dex.go",
diff --git a/java/aar.go b/java/aar.go
index 667dd9d..051715d 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -34,10 +34,16 @@
ExportedStaticPackages() android.Paths
ExportedManifests() android.Paths
ExportedAssets() android.OptionalPath
+ SetRROEnforcedForDependent(enforce bool)
+ IsRROEnforced(ctx android.BaseModuleContext) bool
}
func init() {
RegisterAARBuildComponents(android.InitRegistrationContext)
+
+ android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel()
+ })
}
func RegisterAARBuildComponents(ctx android.RegistrationContext) {
@@ -82,6 +88,9 @@
// do not include AndroidManifest from dependent libraries
Dont_merge_manifests *bool
+
+ // true if RRO is enforced for any of the dependent modules
+ RROEnforcedForDependent bool `blueprint:"mutated"`
}
type aapt struct {
@@ -100,7 +109,6 @@
useEmbeddedNativeLibs bool
useEmbeddedDex bool
usesNonSdkApis bool
- sdkLibraries dexpreopt.LibraryPaths
hasNoCode bool
LoggingParent string
resourceFiles android.Paths
@@ -117,6 +125,18 @@
path android.Path
}
+// Propagate RRO enforcement flag to static lib dependencies transitively.
+func propagateRROEnforcementMutator(ctx android.TopDownMutatorContext) {
+ m := ctx.Module()
+ if d, ok := m.(AndroidLibraryDependency); ok && d.IsRROEnforced(ctx) {
+ ctx.VisitDirectDepsWithTag(staticLibTag, func(d android.Module) {
+ if a, ok := d.(AndroidLibraryDependency); ok {
+ a.SetRROEnforcedForDependent(true)
+ }
+ })
+ }
+}
+
func (a *aapt) ExportPackage() android.Path {
return a.exportPackage
}
@@ -133,6 +153,17 @@
return a.assetPackage
}
+func (a *aapt) SetRROEnforcedForDependent(enforce bool) {
+ a.aaptProperties.RROEnforcedForDependent = enforce
+}
+
+func (a *aapt) IsRROEnforced(ctx android.BaseModuleContext) bool {
+ // True if RRO is enforced for this module or...
+ return ctx.Config().EnforceRROForModule(ctx.ModuleName()) ||
+ // if RRO is enforced for any of its dependents, and this module is not exempted.
+ (a.aaptProperties.RROEnforcedForDependent && !ctx.Config().EnforceRROExemptedForModule(ctx.ModuleName()))
+}
+
func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext,
manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths,
resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) {
@@ -156,7 +187,7 @@
dir: dir,
files: androidResourceGlob(ctx, dir),
})
- resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, dir)
+ resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, a, dir)
overlayDirs = append(overlayDirs, resOverlayDirs...)
rroDirs = append(rroDirs, resRRODirs...)
}
@@ -189,7 +220,7 @@
// Version code
if !hasVersionCode {
- linkFlags = append(linkFlags, "--version-code", ctx.Config().PlatformSdkVersion())
+ linkFlags = append(linkFlags, "--version-code", ctx.Config().PlatformSdkVersion().String())
}
if !hasVersionName {
@@ -227,18 +258,17 @@
CommandDeps: []string{"${config.Zip2ZipCmd}"},
})
-func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, extraLinkFlags ...string) {
+func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext,
+ classLoaderContexts dexpreopt.ClassLoaderContextMap, extraLinkFlags ...string) {
- transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assetPackages, libDeps, libFlags, sdkLibraries :=
- aaptLibs(ctx, sdkContext)
-
- a.sdkLibraries = sdkLibraries
+ transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assetPackages, libDeps, libFlags :=
+ aaptLibs(ctx, sdkContext, classLoaderContexts)
// App manifest file
manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
- manifestPath := manifestFixer(ctx, manifestSrcPath, sdkContext, sdkLibraries,
+ manifestPath := manifestFixer(ctx, manifestSrcPath, sdkContext, classLoaderContexts,
a.isLibrary, a.useEmbeddedNativeLibs, a.usesNonSdkApis, a.useEmbeddedDex, a.hasNoCode,
a.LoggingParent)
@@ -359,29 +389,31 @@
}
// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
-func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStaticLibs, transitiveStaticLibManifests android.Paths,
- staticRRODirs []rroDir, assets, deps android.Paths, flags []string, sdkLibraries dexpreopt.LibraryPaths) {
+func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext, classLoaderContexts dexpreopt.ClassLoaderContextMap) (
+ transitiveStaticLibs, transitiveStaticLibManifests android.Paths, staticRRODirs []rroDir, assets, deps android.Paths, flags []string) {
var sharedLibs android.Paths
+ if classLoaderContexts == nil {
+ // Not all callers need to compute class loader context, those who don't just pass nil.
+ // Create a temporary class loader context here (it will be computed, but not used).
+ classLoaderContexts = make(dexpreopt.ClassLoaderContextMap)
+ }
+
sdkDep := decodeSdkDep(ctx, sdkContext)
if sdkDep.useFiles {
sharedLibs = append(sharedLibs, sdkDep.jars...)
}
- sdkLibraries = make(dexpreopt.LibraryPaths)
-
ctx.VisitDirectDeps(func(module android.Module) {
+ depName := ctx.OtherModuleName(module)
+
var exportPackage android.Path
aarDep, _ := module.(AndroidLibraryDependency)
if aarDep != nil {
exportPackage = aarDep.ExportPackage()
}
- if dep, ok := module.(Dependency); ok {
- sdkLibraries.AddLibraryPaths(dep.ExportedSdkLibs())
- }
-
switch ctx.OtherModuleDependencyTag(module) {
case instrumentationForTag:
// Nothing, instrumentationForTag is treated as libTag for javac but not for aapt2.
@@ -394,7 +426,7 @@
// (including the java_sdk_library) itself then append any implicit sdk library
// names to the list of sdk libraries to be added to the manifest.
if component, ok := module.(SdkLibraryComponentDependency); ok {
- sdkLibraries.MaybeAddLibraryPath(ctx, component.OptionalImplicitSdkLibrary(),
+ classLoaderContexts.MaybeAddContext(ctx, component.OptionalImplicitSdkLibrary(), true,
component.DexJarBuildPath(), component.DexJarInstallPath())
}
@@ -407,22 +439,30 @@
transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...)
transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...)
- sdkLibraries.AddLibraryPaths(aarDep.ExportedSdkLibs())
+ classLoaderContexts.AddContextMap(aarDep.ClassLoaderContexts(), depName)
if aarDep.ExportedAssets().Valid() {
assets = append(assets, aarDep.ExportedAssets().Path())
}
- outer:
- for _, d := range aarDep.ExportedRRODirs() {
- for _, e := range staticRRODirs {
- if d.path == e.path {
- continue outer
+ if !ctx.Config().EnforceRROExemptedForModule(ctx.ModuleName()) {
+ outer:
+ for _, d := range aarDep.ExportedRRODirs() {
+ for _, e := range staticRRODirs {
+ if d.path == e.path {
+ continue outer
+ }
}
+ staticRRODirs = append(staticRRODirs, d)
}
- staticRRODirs = append(staticRRODirs, d)
}
}
}
+
+ // Add nested dependencies after processing the direct dependency: if it is a <uses-library>,
+ // nested context is added as its subcontext, and should not be re-added at the top-level.
+ if dep, ok := module.(Dependency); ok {
+ classLoaderContexts.AddContextMap(dep.ClassLoaderContexts(), depName)
+ }
})
deps = append(deps, sharedLibs...)
@@ -439,7 +479,7 @@
transitiveStaticLibs = android.FirstUniquePaths(transitiveStaticLibs)
transitiveStaticLibManifests = android.FirstUniquePaths(transitiveStaticLibManifests)
- return transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assets, deps, flags, sdkLibraries
+ return transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assets, deps, flags
}
type AndroidLibrary struct {
@@ -474,8 +514,10 @@
func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.aapt.isLibrary = true
- a.aapt.buildActions(ctx, sdkContext(a))
- a.exportedSdkLibs = a.aapt.sdkLibraries
+ a.classLoaderContexts = make(dexpreopt.ClassLoaderContextMap)
+ a.aapt.buildActions(ctx, sdkContext(a), a.classLoaderContexts)
+
+ a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
ctx.CheckbuildFile(a.proguardOptionsFile)
ctx.CheckbuildFile(a.exportPackage)
@@ -500,6 +542,8 @@
ctx.CheckbuildFile(a.aarFile)
}
+ a.exportedProguardFlagFiles = append(a.exportedProguardFlagFiles,
+ android.PathsForModuleSrc(ctx, a.dexProperties.Optimize.Proguard_flags_files)...)
ctx.VisitDirectDeps(func(m android.Module) {
if lib, ok := m.(AndroidLibraryDependency); ok && ctx.OtherModuleDependencyTag(m) == staticLibTag {
a.exportedProguardFlagFiles = append(a.exportedProguardFlagFiles, lib.ExportedProguardFlagFiles()...)
@@ -569,6 +613,24 @@
manifest android.WritablePath
exportedStaticPackages android.Paths
+
+ hideApexVariantFromMake bool
+
+ aarPath android.Path
+}
+
+var _ android.OutputFileProducer = (*AARImport)(nil)
+
+// For OutputFileProducer interface
+func (a *AARImport) OutputFiles(tag string) (android.Paths, error) {
+ switch tag {
+ case ".aar":
+ return []android.Path{a.aarPath}, nil
+ case "":
+ return []android.Path{a.classpathFile}, nil
+ default:
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+ }
}
func (a *AARImport) sdkVersion() sdkSpec {
@@ -621,6 +683,17 @@
return android.OptionalPath{}
}
+// RRO enforcement is not available on aar_import since its RRO dirs are not
+// exported.
+func (a *AARImport) SetRROEnforcedForDependent(enforce bool) {
+}
+
+// RRO enforcement is not available on aar_import since its RRO dirs are not
+// exported.
+func (a *AARImport) IsRROEnforced(ctx android.BaseModuleContext) bool {
+ return false
+}
+
func (a *AARImport) Prebuilt() *android.Prebuilt {
return &a.prebuilt
}
@@ -662,13 +735,15 @@
return
}
+ a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
+
aarName := ctx.ModuleName() + ".aar"
- var aar android.Path
- aar = android.PathForModuleSrc(ctx, a.properties.Aars[0])
+ a.aarPath = android.PathForModuleSrc(ctx, a.properties.Aars[0])
+
if Bool(a.properties.Jetifier) {
- inputFile := aar
- aar = android.PathForModuleOut(ctx, "jetifier", aarName)
- TransformJetifier(ctx, aar.(android.WritablePath), inputFile)
+ inputFile := a.aarPath
+ a.aarPath = android.PathForModuleOut(ctx, "jetifier", aarName)
+ TransformJetifier(ctx, a.aarPath.(android.WritablePath), inputFile)
}
extractedAARDir := android.PathForModuleOut(ctx, "aar")
@@ -678,7 +753,7 @@
ctx.Build(pctx, android.BuildParams{
Rule: unzipAAR,
- Input: aar,
+ Input: a.aarPath,
Outputs: android.WritablePaths{a.classpathFile, a.proguardFlags, a.manifest},
Description: "unzip AAR",
Args: map[string]string{
@@ -692,7 +767,7 @@
compileFlags := []string{"--pseudo-localize"}
compiledResDir := android.PathForModuleOut(ctx, "flat-res")
flata := compiledResDir.Join(ctx, "gen_res.flata")
- aapt2CompileZip(ctx, flata, aar, "res", compileFlags)
+ aapt2CompileZip(ctx, flata, a.aarPath, "res", compileFlags)
a.exportPackage = android.PathForModuleOut(ctx, "package-res.apk")
// the subdir "android" is required to be filtered by package names
@@ -712,12 +787,11 @@
linkFlags = append(linkFlags, "--manifest "+a.manifest.String())
linkDeps = append(linkDeps, a.manifest)
- transitiveStaticLibs, staticLibManifests, staticRRODirs, transitiveAssets, libDeps, libFlags, sdkLibraries :=
- aaptLibs(ctx, sdkContext(a))
+ transitiveStaticLibs, staticLibManifests, staticRRODirs, transitiveAssets, libDeps, libFlags :=
+ aaptLibs(ctx, sdkContext(a), nil)
_ = staticLibManifests
_ = staticRRODirs
- _ = sdkLibraries
linkDeps = append(linkDeps, libDeps...)
linkFlags = append(linkFlags, libFlags...)
@@ -758,7 +832,7 @@
return nil
}
-func (a *AARImport) ExportedSdkLibs() dexpreopt.LibraryPaths {
+func (a *AARImport) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
return nil
}
@@ -774,7 +848,8 @@
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/android_manifest.go b/java/android_manifest.go
index 62cd112..c76bb2f 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -43,8 +43,9 @@
"args", "libs")
// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
-func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext, sdkLibraries dexpreopt.LibraryPaths,
- isLibrary, useEmbeddedNativeLibs, usesNonSdkApis, useEmbeddedDex, hasNoCode bool, loggingParent string) android.Path {
+func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext,
+ classLoaderContexts dexpreopt.ClassLoaderContextMap, isLibrary, useEmbeddedNativeLibs, usesNonSdkApis,
+ useEmbeddedDex, hasNoCode bool, loggingParent string) android.Path {
var args []string
if isLibrary {
@@ -70,7 +71,7 @@
args = append(args, "--use-embedded-dex")
}
- for _, usesLib := range android.SortedStringKeys(sdkLibraries) {
+ for _, usesLib := range classLoaderContexts.UsesLibs() {
if inList(usesLib, dexpreopt.OptionalCompatUsesLibs) {
args = append(args, "--optional-uses-library", usesLib)
} else {
diff --git a/java/android_resources.go b/java/android_resources.go
index c2bc746..720d3a5 100644
--- a/java/android_resources.go
+++ b/java/android_resources.go
@@ -23,6 +23,7 @@
func init() {
android.RegisterPreSingletonType("overlay", OverlaySingletonFactory)
+
}
var androidResourceIgnoreFilenames = []string{
@@ -66,13 +67,13 @@
files android.Paths
}
-func overlayResourceGlob(ctx android.ModuleContext, dir android.Path) (res []globbedResourceDir,
+func overlayResourceGlob(ctx android.ModuleContext, a *aapt, dir android.Path) (res []globbedResourceDir,
rroDirs []rroDir) {
overlayData := ctx.Config().Get(overlayDataKey).([]overlayGlobResult)
// Runtime resource overlays (RRO) may be turned on by the product config for some modules
- rroEnabled := ctx.Config().EnforceRROForModule(ctx.ModuleName())
+ rroEnabled := a.IsRROEnforced(ctx)
for _, data := range overlayData {
files := data.paths.PathsInDirectory(filepath.Join(data.dir, dir.String()))
diff --git a/java/androidmk.go b/java/androidmk.go
index 65c44a3..f263cb8 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -23,8 +23,7 @@
func (library *Library) AndroidMkEntriesHostDex() android.AndroidMkEntries {
hostDexNeeded := Bool(library.deviceProperties.Hostdex) && !library.Host()
- if !library.IsForPlatform() {
- // Don't emit hostdex modules from the APEX variants
+ if library.hideApexVariantFromMake {
hostDexNeeded = false
}
@@ -61,22 +60,15 @@
func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
var entriesList []android.AndroidMkEntries
- mainEntries := android.AndroidMkEntries{Disabled: true}
-
- // For a java library built for an APEX, we don't need Make module
- hideFromMake := !library.IsForPlatform()
- // If not available for platform, don't emit to make.
- if !library.ApexModuleBase.AvailableFor(android.AvailableToPlatform) {
- hideFromMake = true
- }
- if hideFromMake {
- // May still need to add some additional dependencies. This will be called
- // once for the platform variant (even if it is not being used) and once each
- // for the APEX specific variants. In order to avoid adding the dependency
- // multiple times only add it for the platform variant.
+ if library.hideApexVariantFromMake {
+ // For a java library built for an APEX we don't need Make module
+ entriesList = append(entriesList, android.AndroidMkEntries{Disabled: true})
+ } else if !library.ApexModuleBase.AvailableFor(android.AvailableToPlatform) {
+ // Platform variant. If not available for the platform, we don't need Make module.
+ // May still need to add some additional dependencies.
checkedModulePaths := library.additionalCheckedModules
- if library.IsForPlatform() && len(checkedModulePaths) != 0 {
- mainEntries = android.AndroidMkEntries{
+ if len(checkedModulePaths) != 0 {
+ entriesList = append(entriesList, android.AndroidMkEntries{
Class: "FAKE",
// Need at least one output file in order for this to take effect.
OutputFile: android.OptionalPathForPath(checkedModulePaths[0]),
@@ -86,10 +78,12 @@
entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", checkedModulePaths.Strings()...)
},
},
- }
+ })
+ } else {
+ entriesList = append(entriesList, android.AndroidMkEntries{Disabled: true})
}
} else {
- mainEntries = android.AndroidMkEntries{
+ entriesList = append(entriesList, android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
DistFiles: library.distFiles,
OutputFile: android.OptionalPathForPath(library.outputFile),
@@ -121,7 +115,7 @@
entries.SetPath("LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR", library.jacocoReportClassesFile)
}
- entries.AddStrings("LOCAL_EXPORT_SDK_LIBRARIES", android.SortedStringKeys(library.exportedSdkLibs)...)
+ entries.AddStrings("LOCAL_EXPORT_SDK_LIBRARIES", library.classLoaderContexts.UsesLibs()...)
if len(library.additionalCheckedModules) != 0 {
entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", library.additionalCheckedModules.Strings()...)
@@ -134,12 +128,11 @@
entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", library.linter.reports)
},
},
- }
+ })
}
- hostDexEntries := library.AndroidMkEntriesHostDex()
+ entriesList = append(entriesList, library.AndroidMkEntriesHostDex())
- entriesList = append(entriesList, mainEntries, hostDexEntries)
return entriesList
}
@@ -189,7 +182,7 @@
}
func (prebuilt *Import) AndroidMkEntries() []android.AndroidMkEntries {
- if !prebuilt.IsForPlatform() || !prebuilt.ContainingSdk().Unversioned() {
+ if prebuilt.hideApexVariantFromMake || !prebuilt.ContainingSdk().Unversioned() {
return []android.AndroidMkEntries{android.AndroidMkEntries{
Disabled: true,
}}
@@ -211,7 +204,7 @@
}
func (prebuilt *DexImport) AndroidMkEntries() []android.AndroidMkEntries {
- if !prebuilt.IsForPlatform() {
+ if prebuilt.hideApexVariantFromMake {
return []android.AndroidMkEntries{android.AndroidMkEntries{
Disabled: true,
}}
@@ -224,10 +217,6 @@
func(entries *android.AndroidMkEntries) {
if prebuilt.dexJarFile != nil {
entries.SetPath("LOCAL_SOONG_DEX_JAR", prebuilt.dexJarFile)
- // TODO(b/125517186): export the dex jar as a classes jar to match some mis-uses in Make until
- // boot_jars_package_check.mk can check dex jars.
- entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.dexJarFile)
- entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.dexJarFile)
}
if len(prebuilt.dexpreopter.builtInstalled) > 0 {
entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", prebuilt.dexpreopter.builtInstalled)
@@ -239,7 +228,7 @@
}
func (prebuilt *AARImport) AndroidMkEntries() []android.AndroidMkEntries {
- if !prebuilt.IsForPlatform() {
+ if prebuilt.hideApexVariantFromMake {
return []android.AndroidMkEntries{{
Disabled: true,
}}
@@ -309,7 +298,7 @@
}
func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
- if !app.IsForPlatform() || app.appProperties.HideFromMake {
+ if app.hideApexVariantFromMake || app.appProperties.HideFromMake {
return []android.AndroidMkEntries{android.AndroidMkEntries{
Disabled: true,
}}
@@ -458,7 +447,7 @@
}
func (a *AndroidLibrary) AndroidMkEntries() []android.AndroidMkEntries {
- if !a.IsForPlatform() {
+ if a.hideApexVariantFromMake {
return []android.AndroidMkEntries{{
Disabled: true,
}}
@@ -556,9 +545,6 @@
if dstubs.annotationsZip != nil {
entries.SetPath("LOCAL_DROIDDOC_ANNOTATIONS_ZIP", dstubs.annotationsZip)
}
- if dstubs.jdiffDocZip != nil {
- entries.SetPath("LOCAL_DROIDDOC_JDIFF_DOC_ZIP", dstubs.jdiffDocZip)
- }
if dstubs.metadataZip != nil {
entries.SetPath("LOCAL_DROIDDOC_METADATA_ZIP", dstubs.metadataZip)
}
@@ -638,7 +624,7 @@
}
func (a *AndroidAppImport) AndroidMkEntries() []android.AndroidMkEntries {
- if !a.IsForPlatform() {
+ if a.hideApexVariantFromMake {
// The non-platform variant is placed inside APEX. No reason to
// make it available to Make.
return nil
diff --git a/java/app.go b/java/app.go
index ae7373f..17de8b9 100755
--- a/java/app.go
+++ b/java/app.go
@@ -157,7 +157,7 @@
"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()),
@@ -379,7 +379,6 @@
"can only be set for modules that set sdk_version")
}
- tag := &jniDependencyTag{}
for _, jniTarget := range ctx.MultiTargets() {
variation := append(jniTarget.Variations(),
blueprint.Variation{Mutator: "link", Variation: "shared"})
@@ -393,7 +392,7 @@
Bool(a.appProperties.Jni_uses_sdk_apis) {
variation = append(variation, blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
}
- ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs...)
+ ctx.AddFarVariationDependencies(variation, jniLibTag, a.appProperties.Jni_libs...)
}
a.usesLibrary.deps(ctx, sdkDep.hasFrameworkLibs())
@@ -436,7 +435,7 @@
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())
}
@@ -480,8 +479,9 @@
ctx.PropertyErrorf("min_sdk_version", "invalid value %q: %s", a.minSdkVersion(), err)
}
+ apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
return (minSdkVersion >= 23 && Bool(a.appProperties.Use_embedded_native_libs)) ||
- !a.IsForPlatform()
+ !apexInfo.IsForPlatform()
}
// Returns whether this module should have the dex file stored uncompressed in the APK.
@@ -504,8 +504,9 @@
}
func (a *AndroidApp) shouldEmbedJnis(ctx android.BaseModuleContext) bool {
+ apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
return ctx.Config().UnbundledBuild() || Bool(a.appProperties.Use_embedded_native_libs) ||
- !a.IsForPlatform() || a.appProperties.AlwaysPackageNativeLibs
+ !apexInfo.IsForPlatform() || a.appProperties.AlwaysPackageNativeLibs
}
func generateAaptRenamePackageFlags(packageName string, renameResourcesPackage bool) []string {
@@ -564,9 +565,8 @@
aaptLinkFlags = append(aaptLinkFlags, a.additionalAaptFlags...)
a.aapt.splitNames = a.appProperties.Package_splits
- a.aapt.sdkLibraries = a.exportedSdkLibs
a.aapt.LoggingParent = String(a.overridableAppProperties.Logging_parent)
- a.aapt.buildActions(ctx, sdkContext(a), aaptLinkFlags...)
+ a.aapt.buildActions(ctx, sdkContext(a), a.classLoaderContexts, aaptLinkFlags...)
// apps manifests are handled by aapt, don't let Module see them
a.properties.Manifest = nil
@@ -600,7 +600,7 @@
return android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk")
}
-func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext, sdkLibs dexpreopt.LibraryPaths) android.Path {
+func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path {
a.dexpreopter.installPath = a.installPath(ctx)
if a.dexProperties.Uncompress_dex == nil {
// If the value was not force-set by the user, use reasonable default based on the module.
@@ -608,12 +608,8 @@
}
a.dexpreopter.uncompressedDex = *a.dexProperties.Uncompress_dex
a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
- a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs
- a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx)
- a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx)
- a.dexpreopter.libraryPaths.AddLibraryPaths(sdkLibs)
+ a.dexpreopter.classLoaderContexts = a.classLoaderContexts
a.dexpreopter.manifestFile = a.mergedManifestFile
- a.exportedSdkLibs = make(dexpreopt.LibraryPaths)
if ctx.ModuleName() != "framework-res" {
a.Module.compile(ctx, a.aaptSrcJar)
@@ -641,7 +637,7 @@
// Work with the team to come up with a new format that handles multilib modules properly
// and change this.
if len(ctx.Config().Targets[android.Android]) == 1 ||
- ctx.Config().Targets[android.Android][0].Arch.ArchType == jni.target.Arch.ArchType {
+ ctx.Config().AndroidFirstDeviceTarget.Arch.ArchType == jni.target.Arch.ArchType {
a.jniCoverageOutputs = append(a.jniCoverageOutputs, jni.coverageFile.Path())
}
}
@@ -678,7 +674,7 @@
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
}
@@ -756,6 +752,10 @@
func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
var apkDeps android.Paths
+ if !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform() {
+ a.hideApexVariantFromMake = true
+ }
+
a.aapt.useEmbeddedNativeLibs = a.useEmbeddedNativeLibs(ctx)
a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex)
@@ -779,6 +779,8 @@
a.aapt.noticeFile = a.noticeOutputs.HtmlGzOutput
}
+ a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
+
// Process all building blocks, from AAPT to certificates.
a.aaptBuildActions(ctx)
@@ -786,7 +788,7 @@
a.usesLibrary.freezeEnforceUsesLibraries()
// Add implicit SDK libraries to <uses-library> list.
- for _, usesLib := range android.SortedStringKeys(a.aapt.sdkLibraries) {
+ for _, usesLib := range a.classLoaderContexts.UsesLibs() {
a.usesLibrary.addLib(usesLib, inList(usesLib, dexpreopt.OptionalCompatUsesLibs))
}
@@ -803,7 +805,7 @@
a.linter.resources = a.aapt.resourceFiles
a.linter.buildModuleReportZip = ctx.Config().UnbundledBuildApps()
- dexJarFile := a.dexBuildActions(ctx, a.aapt.sdkLibraries)
+ dexJarFile := a.dexBuildActions(ctx)
jniLibs, certificateDeps := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis))
jniJarFile := a.jniBuildActions(jniLibs, ctx)
@@ -850,8 +852,10 @@
BuildBundleModule(ctx, bundleFile, a.exportPackage, jniJarFile, dexJarFile)
a.bundleFile = bundleFile
+ apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+
// Install the app package.
- if (Bool(a.Module.properties.Installable) || ctx.Host()) && a.IsForPlatform() {
+ if (Bool(a.Module.properties.Installable) || ctx.Host()) && apexInfo.IsForPlatform() {
ctx.InstallFile(a.installDir, a.outputFile.Base(), a.outputFile)
for _, extra := range a.extraOutputFiles {
ctx.InstallFile(a.installDir, extra.Base(), extra)
@@ -979,7 +983,7 @@
}
func (a *AndroidApp) Updatable() bool {
- return Bool(a.appProperties.Updatable) || a.ApexModuleBase.Updatable()
+ return Bool(a.appProperties.Updatable)
}
func (a *AndroidApp) getCertString(ctx android.BaseModuleContext) string {
@@ -1335,6 +1339,8 @@
preprocessed bool
installPath android.InstallPath
+
+ hideApexVariantFromMake bool
}
type AndroidAppImportProperties struct {
@@ -1392,7 +1398,7 @@
}
archProps := reflect.ValueOf(a.archVariants).Elem().FieldByName("Arch")
- archType := ctx.Config().Targets[android.Android][0].Arch.ArchType
+ archType := ctx.Config().AndroidFirstDeviceTarget.Arch.ArchType
MergePropertiesFromVariant(ctx, &a.properties, archProps, archType.Name)
}
@@ -1481,6 +1487,11 @@
}
func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext) {
+ apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ if !apexInfo.IsForPlatform() {
+ a.hideApexVariantFromMake = true
+ }
+
numCertPropsSet := 0
if String(a.properties.Certificate) != "" {
numCertPropsSet++
@@ -1526,9 +1537,7 @@
a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
- a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs
- a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx)
- a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx)
+ a.dexpreopter.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
dexOutput := a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
if a.dexpreopter.uncompressedDex {
@@ -1569,7 +1578,7 @@
// TODO: Optionally compress the output apk.
- if a.IsForPlatform() {
+ if apexInfo.IsForPlatform() {
a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile)
}
@@ -1637,7 +1646,8 @@
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
}
@@ -1837,7 +1847,7 @@
aaptLinkFlags = append(aaptLinkFlags,
"--rename-overlay-target-package "+*r.overridableProperties.Target_package_name)
}
- r.aapt.buildActions(ctx, r, aaptLinkFlags...)
+ r.aapt.buildActions(ctx, r, nil, aaptLinkFlags...)
// Sign the built package
_, certificates := collectAppDeps(ctx, r, false, false)
@@ -1947,8 +1957,9 @@
if hasFrameworkLibs {
// Dexpreopt needs paths to the dex jars of these libraries in order to construct
// class loader context for dex2oat. Add them as a dependency with a special tag.
- ctx.AddVariationDependencies(nil, usesLibTag, dexpreopt.CompatUsesLibs...)
- ctx.AddVariationDependencies(nil, usesLibTag, dexpreopt.OptionalCompatUsesLibs...)
+ ctx.AddVariationDependencies(nil, usesLibCompat29Tag, dexpreopt.CompatUsesLibs29...)
+ ctx.AddVariationDependencies(nil, usesLibCompat28Tag, dexpreopt.OptionalCompatUsesLibs28...)
+ ctx.AddVariationDependencies(nil, usesLibCompat30Tag, dexpreopt.OptionalCompatUsesLibs30...)
}
}
}
@@ -1960,25 +1971,33 @@
return optionalUsesLibs
}
-// usesLibraryPaths returns a map of module names of shared library dependencies to the paths
+// Returns a map of module names of shared library dependencies to the paths
// to their dex jars on host and on device.
-func (u *usesLibrary) usesLibraryPaths(ctx android.ModuleContext) dexpreopt.LibraryPaths {
- usesLibPaths := make(dexpreopt.LibraryPaths)
+func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext) dexpreopt.ClassLoaderContextMap {
+ clcMap := make(dexpreopt.ClassLoaderContextMap)
if !ctx.Config().UnbundledBuild() {
- ctx.VisitDirectDepsWithTag(usesLibTag, func(m android.Module) {
- dep := ctx.OtherModuleName(m)
- if lib, ok := m.(Dependency); ok {
- usesLibPaths.AddLibraryPath(ctx, dep, lib.DexJarBuildPath(), lib.DexJarInstallPath())
- } else if ctx.Config().AllowMissingDependencies() {
- ctx.AddMissingDependencies([]string{dep})
- } else {
- ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must be a java library", dep)
+ ctx.VisitDirectDeps(func(m android.Module) {
+ if tag, ok := ctx.OtherModuleDependencyTag(m).(usesLibraryDependencyTag); ok {
+ dep := ctx.OtherModuleName(m)
+ if lib, ok := m.(Dependency); ok {
+ clcMap.AddContextForSdk(ctx, tag.sdkVersion, dep, isSharedSdkLibrary(m),
+ lib.DexJarBuildPath(), lib.DexJarInstallPath(), lib.ClassLoaderContexts())
+ } else if ctx.Config().AllowMissingDependencies() {
+ ctx.AddMissingDependencies([]string{dep})
+ } else {
+ ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must be a java library", dep)
+ }
}
})
}
- return usesLibPaths
+ return clcMap
+}
+
+func isSharedSdkLibrary(m android.Module) bool {
+ lib, ok := m.(SdkLibraryDependency)
+ return ok && lib.IsSharedLibrary()
}
// enforceUsesLibraries returns true of <uses-library> tags should be checked against uses_libs and optional_uses_libs
diff --git a/java/app_test.go b/java/app_test.go
index 5367971..6429ab8 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -59,7 +59,7 @@
func testApp(t *testing.T, bp string) *android.TestContext {
config := testAppConfig(nil, bp, nil)
- ctx := testContext()
+ ctx := testContext(config)
run(t, ctx, config)
@@ -220,7 +220,7 @@
config.TestProductVariables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI
config.TestProductVariables.Platform_sdk_version = &test.sdkVersion
config.Targets[android.Android] = test.targets
- ctx := testContext()
+ ctx := testContext(config)
run(t, ctx, config)
module := ctx.ModuleForTests("foo", "android_common")
const packedSplitApks = "foo.zip"
@@ -657,7 +657,7 @@
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
config := testConfig(nil, fmt.Sprintf(bp, testCase.prop), fs)
- ctx := testContext()
+ ctx := testContext(config)
run(t, ctx, config)
module := ctx.ModuleForTests("foo", "android_common")
@@ -848,19 +848,17 @@
"lib": {
buildDir + "/.intermediates/lib2/android_common/package-res.apk",
"lib/res/res/values/strings.xml",
- "device/vendor/blah/overlay/lib/res/values/strings.xml",
},
},
rroDirs: map[string][]string{
"foo": {
"device:device/vendor/blah/overlay/foo/res",
- // Enforce RRO on "foo" could imply RRO on static dependencies, but for now it doesn't.
- // "device/vendor/blah/overlay/lib/res",
"product:product/vendor/blah/overlay/foo/res",
+ "device:device/vendor/blah/overlay/lib/res",
},
"bar": nil,
- "lib": nil,
+ "lib": {"device:device/vendor/blah/overlay/lib/res"},
},
},
{
@@ -975,7 +973,7 @@
config.TestProductVariables.EnforceRROExcludedOverlays = testCase.enforceRROExcludedOverlays
}
- ctx := testContext()
+ ctx := testContext(config)
run(t, ctx, config)
resourceListToFiles := func(module android.TestingModule, list []string) (files []string) {
@@ -1041,7 +1039,7 @@
}
func checkSdkVersion(t *testing.T, config android.Config, expectedSdkVersion string) {
- ctx := testContext()
+ ctx := testContext(config)
run(t, ctx, config)
@@ -1078,6 +1076,7 @@
platformSdkFinal bool
expectedMinSdkVersion string
platformApis bool
+ activeCodenames []string
}{
{
name: "current final SDK",
@@ -1094,6 +1093,7 @@
platformSdkCodename: "OMR1",
platformSdkFinal: false,
expectedMinSdkVersion: "OMR1",
+ activeCodenames: []string{"OMR1"},
},
{
name: "default final SDK",
@@ -1112,11 +1112,14 @@
platformSdkCodename: "OMR1",
platformSdkFinal: false,
expectedMinSdkVersion: "OMR1",
+ activeCodenames: []string{"OMR1"},
},
{
name: "14",
sdkVersion: "14",
expectedMinSdkVersion: "14",
+ platformSdkCodename: "S",
+ activeCodenames: []string{"S"},
},
}
@@ -1137,6 +1140,7 @@
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 +1183,6 @@
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",
},
@@ -1638,7 +1633,7 @@
if test.certificateOverride != "" {
config.TestProductVariables.CertificateOverrides = []string{test.certificateOverride}
}
- ctx := testContext()
+ ctx := testContext(config)
run(t, ctx, config)
foo := ctx.ModuleForTests("foo", "android_common")
@@ -1703,7 +1698,7 @@
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
config := testAppConfig(nil, test.bp, nil)
- ctx := testContext()
+ ctx := testContext(config)
run(t, ctx, config)
foo := ctx.ModuleForTests("foo", "android_common")
@@ -1763,7 +1758,7 @@
if test.packageNameOverride != "" {
config.TestProductVariables.PackageNameOverrides = []string{test.packageNameOverride}
}
- ctx := testContext()
+ ctx := testContext(config)
run(t, ctx, config)
foo := ctx.ModuleForTests("foo", "android_common")
@@ -1798,7 +1793,7 @@
`
config := testAppConfig(nil, bp, nil)
config.TestProductVariables.ManifestPackageNameOverrides = []string{"foo:org.dandroid.bp"}
- ctx := testContext()
+ ctx := testContext(config)
run(t, ctx, config)
@@ -2421,7 +2416,7 @@
config := testAppConfig(nil, bp, nil)
config.TestProductVariables.AAPTPreferredConfig = test.aaptPreferredConfig
config.TestProductVariables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI
- ctx := testContext()
+ ctx := testContext(config)
run(t, ctx, config)
@@ -2757,19 +2752,6 @@
android_app {
name: "app",
srcs: ["a.java"],
- libs: ["qux", "quuz"],
- static_libs: ["static-runtime-helper"],
- uses_libs: ["foo"],
- sdk_version: "current",
- optional_uses_libs: [
- "bar",
- "baz",
- ],
- }
-
- android_app {
- name: "app_with_stub_deps",
- srcs: ["a.java"],
libs: ["qux", "quuz.stubs"],
static_libs: ["static-runtime-helper"],
uses_libs: ["foo"],
@@ -2784,7 +2766,7 @@
name: "prebuilt",
apk: "prebuilts/apk/app.apk",
certificate: "platform",
- uses_libs: ["foo"],
+ uses_libs: ["foo", "android.test.runner"],
optional_uses_libs: [
"bar",
"baz",
@@ -2795,12 +2777,11 @@
config := testAppConfig(nil, bp, nil)
config.TestProductVariables.MissingUsesLibraries = []string{"baz"}
- ctx := testContext()
+ ctx := testContext(config)
run(t, ctx, config)
app := ctx.ModuleForTests("app", "android_common")
- appWithStubDeps := ctx.ModuleForTests("app_with_stub_deps", "android_common")
prebuilt := ctx.ModuleForTests("prebuilt", "android_common")
// Test that implicit dependencies on java_sdk_library instances are passed to the manifest.
@@ -2823,7 +2804,7 @@
cmd = prebuilt.Rule("verify_uses_libraries").RuleParams.Command
- if w := `uses_library_names="foo"`; !strings.Contains(cmd, w) {
+ if w := `uses_library_names="foo android.test.runner"`; !strings.Contains(cmd, w) {
t.Errorf("wanted %q in %q", w, cmd)
}
@@ -2831,25 +2812,51 @@
t.Errorf("wanted %q in %q", w, cmd)
}
- // Test that all present libraries are preopted, including implicit SDK dependencies
+ // Test that all present libraries are preopted, including implicit SDK dependencies, possibly stubs
cmd = app.Rule("dexpreopt").RuleParams.Command
- w := `--target-classpath-for-sdk any` +
- ` /system/framework/foo.jar` +
- `:/system/framework/quuz.jar` +
- `:/system/framework/qux.jar` +
- `:/system/framework/runtime-library.jar` +
- `:/system/framework/bar.jar`
+ w := `--target-context-for-sdk any ` +
+ `PCL[/system/framework/qux.jar]#` +
+ `PCL[/system/framework/quuz.jar]#` +
+ `PCL[/system/framework/foo.jar]#` +
+ `PCL[/system/framework/bar.jar]#` +
+ `PCL[/system/framework/runtime-library.jar]`
if !strings.Contains(cmd, w) {
t.Errorf("wanted %q in %q", w, cmd)
}
- // TODO(skvadrik) fix dexpreopt for stub libraries for which the implementation is present
- if appWithStubDeps.MaybeRule("dexpreopt").RuleParams.Command != "" {
- t.Errorf("dexpreopt should be disabled for apps with dependencies on stub libraries")
+ // Test conditional context for target SDK version 28.
+ if w := `--target-context-for-sdk 28` +
+ ` PCL[/system/framework/org.apache.http.legacy.jar] `; !strings.Contains(cmd, w) {
+ t.Errorf("wanted %q in %q", w, cmd)
+ }
+
+ // Test conditional context for target SDK version 29.
+ if w := `--target-context-for-sdk 29` +
+ ` PCL[/system/framework/android.hidl.base-V1.0-java.jar]` +
+ `#PCL[/system/framework/android.hidl.manager-V1.0-java.jar] `; !strings.Contains(cmd, w) {
+ t.Errorf("wanted %q in %q", w, cmd)
+ }
+
+ // Test conditional context for target SDK version 30.
+ // "android.test.mock" is absent because "android.test.runner" is not used.
+ if w := `--target-context-for-sdk 30` +
+ ` PCL[/system/framework/android.test.base.jar] `; !strings.Contains(cmd, w) {
+ t.Errorf("wanted %q in %q", w, cmd)
}
cmd = prebuilt.Rule("dexpreopt").RuleParams.Command
- if w := `--target-classpath-for-sdk any /system/framework/foo.jar:/system/framework/bar.jar`; !strings.Contains(cmd, w) {
+ if w := `--target-context-for-sdk any` +
+ ` PCL[/system/framework/foo.jar]` +
+ `#PCL[/system/framework/android.test.runner.jar]` +
+ `#PCL[/system/framework/bar.jar] `; !strings.Contains(cmd, w) {
+ t.Errorf("wanted %q in %q", w, cmd)
+ }
+
+ // Test conditional context for target SDK version 30.
+ // "android.test.mock" is present because "android.test.runner" is used.
+ if w := `--target-context-for-sdk 30` +
+ ` PCL[/system/framework/android.test.base.jar]` +
+ `#PCL[/system/framework/android.test.mock.jar] `; !strings.Contains(cmd, w) {
t.Errorf("wanted %q in %q", w, cmd)
}
}
@@ -3122,7 +3129,7 @@
config.TestProductVariables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
}
- ctx := testContext()
+ ctx := testContext(config)
run(t, ctx, config)
@@ -3202,7 +3209,7 @@
}
`
config := testAppConfig(nil, bp, fs)
- ctx := testContext()
+ ctx := testContext(config)
run(t, ctx, config)
m := ctx.ModuleForTests("foo", "android_common")
@@ -3404,3 +3411,145 @@
checkAapt2LinkFlag(t, aapt2Flags, "rename-overlay-target-package", expected.targetPackageFlag)
}
}
+
+func TestEnforceRRO_propagatesToDependencies(t *testing.T) {
+ testCases := []struct {
+ name string
+ enforceRROTargets []string
+ enforceRROExemptTargets []string
+ rroDirs map[string][]string
+ }{
+ {
+ name: "no RRO",
+ enforceRROTargets: nil,
+ enforceRROExemptTargets: nil,
+ rroDirs: map[string][]string{
+ "foo": nil,
+ "bar": nil,
+ },
+ },
+ {
+ name: "enforce RRO on all",
+ enforceRROTargets: []string{"*"},
+ enforceRROExemptTargets: nil,
+ rroDirs: map[string][]string{
+ "foo": {"product/vendor/blah/overlay/lib2/res"},
+ "bar": {"product/vendor/blah/overlay/lib2/res"},
+ },
+ },
+ {
+ name: "enforce RRO on foo",
+ enforceRROTargets: []string{"foo"},
+ enforceRROExemptTargets: nil,
+ rroDirs: map[string][]string{
+ "foo": {"product/vendor/blah/overlay/lib2/res"},
+ "bar": {"product/vendor/blah/overlay/lib2/res"},
+ },
+ },
+ {
+ name: "enforce RRO on foo, bar exempted",
+ enforceRROTargets: []string{"foo"},
+ enforceRROExemptTargets: []string{"bar"},
+ rroDirs: map[string][]string{
+ "foo": {"product/vendor/blah/overlay/lib2/res"},
+ "bar": nil,
+ },
+ },
+ }
+
+ productResourceOverlays := []string{
+ "product/vendor/blah/overlay",
+ }
+
+ fs := map[string][]byte{
+ "lib2/res/values/strings.xml": nil,
+ "product/vendor/blah/overlay/lib2/res/values/strings.xml": nil,
+ }
+
+ bp := `
+ android_app {
+ name: "foo",
+ sdk_version: "current",
+ resource_dirs: [],
+ static_libs: ["lib"],
+ }
+
+ android_app {
+ name: "bar",
+ sdk_version: "current",
+ resource_dirs: [],
+ static_libs: ["lib"],
+ }
+
+ android_library {
+ name: "lib",
+ sdk_version: "current",
+ resource_dirs: [],
+ static_libs: ["lib2"],
+ }
+
+ android_library {
+ name: "lib2",
+ sdk_version: "current",
+ resource_dirs: ["lib2/res"],
+ }
+ `
+
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ config := testAppConfig(nil, bp, fs)
+ config.TestProductVariables.ProductResourceOverlays = productResourceOverlays
+ if testCase.enforceRROTargets != nil {
+ config.TestProductVariables.EnforceRROTargets = testCase.enforceRROTargets
+ }
+ if testCase.enforceRROExemptTargets != nil {
+ config.TestProductVariables.EnforceRROExemptedTargets = testCase.enforceRROExemptTargets
+ }
+
+ ctx := testContext(config)
+ run(t, ctx, config)
+
+ modules := []string{"foo", "bar"}
+ for _, moduleName := range modules {
+ module := ctx.ModuleForTests(moduleName, "android_common")
+ mkEntries := android.AndroidMkEntriesForTest(t, config, "", module.Module())[0]
+ actualRRODirs := mkEntries.EntryMap["LOCAL_SOONG_PRODUCT_RRO_DIRS"]
+ if !reflect.DeepEqual(actualRRODirs, testCase.rroDirs[moduleName]) {
+ t.Errorf("exected %s LOCAL_SOONG_PRODUCT_RRO_DIRS entry: %v\ngot:%q",
+ moduleName, testCase.rroDirs[moduleName], actualRRODirs)
+ }
+ }
+ })
+ }
+}
+
+func TestExportedProguardFlagFiles(t *testing.T) {
+ ctx, _ := testJava(t, `
+ android_app {
+ name: "foo",
+ sdk_version: "current",
+ static_libs: ["lib1"],
+ }
+
+ android_library {
+ name: "lib1",
+ sdk_version: "current",
+ optimize: {
+ proguard_flags_files: ["lib1proguard.cfg"],
+ }
+ }
+ `)
+
+ m := ctx.ModuleForTests("foo", "android_common")
+ hasLib1Proguard := false
+ for _, s := range m.Rule("java.r8").Implicits.Strings() {
+ if s == "lib1proguard.cfg" {
+ hasLib1Proguard = true
+ break
+ }
+ }
+
+ if !hasLib1Proguard {
+ t.Errorf("App does not use library proguard config")
+ }
+}
diff --git a/java/boot_jars.go b/java/boot_jars.go
new file mode 100644
index 0000000..e706547
--- /dev/null
+++ b/java/boot_jars.go
@@ -0,0 +1,119 @@
+// 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 java
+
+import (
+ "android/soong/android"
+)
+
+func init() {
+ android.RegisterSingletonType("boot_jars", bootJarsSingletonFactory)
+}
+
+func bootJarsSingletonFactory() android.Singleton {
+ return &bootJarsSingleton{}
+}
+
+type bootJarsSingleton struct{}
+
+func populateMapFromConfiguredJarList(ctx android.SingletonContext, moduleToApex map[string]string, list android.ConfiguredJarList, name string) bool {
+ for i := 0; i < list.Len(); i++ {
+ module := list.Jar(i)
+ // Ignore jacocoagent it is only added when instrumenting and so has no impact on
+ // app compatibility.
+ if module == "jacocoagent" {
+ continue
+ }
+ apex := list.Apex(i)
+ if existing, ok := moduleToApex[module]; ok {
+ ctx.Errorf("Configuration property %q is invalid as it contains multiple references to module (%s) in APEXes (%s and %s)",
+ module, existing, apex)
+ return false
+ }
+
+ moduleToApex[module] = apex
+ }
+
+ return true
+}
+
+func (b *bootJarsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ config := ctx.Config()
+ if config.SkipBootJarsCheck() {
+ return
+ }
+
+ // Populate a map from module name to APEX from the boot jars. If there is a problem
+ // such as duplicate modules then fail and return immediately.
+ moduleToApex := make(map[string]string)
+ if !populateMapFromConfiguredJarList(ctx, moduleToApex, config.NonUpdatableBootJars(), "BootJars") ||
+ !populateMapFromConfiguredJarList(ctx, moduleToApex, config.UpdatableBootJars(), "UpdatableBootJars") {
+ return
+ }
+
+ // Map from module name to the correct apex variant.
+ nameToApexVariant := make(map[string]android.Module)
+
+ // Scan all the modules looking for the module/apex variants corresponding to the
+ // boot jars.
+ ctx.VisitAllModules(func(module android.Module) {
+ name := ctx.ModuleName(module)
+ if apex, ok := moduleToApex[name]; ok {
+ apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+ if (apex == "platform" && apexInfo.IsForPlatform()) || apexInfo.InApex(apex) {
+ // The module name/apex variant should be unique in the system but double check
+ // just in case something has gone wrong.
+ if existing, ok := nameToApexVariant[name]; ok {
+ ctx.Errorf("found multiple variants matching %s:%s: %q and %q", apex, name, existing, module)
+ }
+ nameToApexVariant[name] = module
+ }
+ }
+ })
+
+ timestamp := android.PathForOutput(ctx, "boot-jars-package-check/stamp")
+
+ rule := android.NewRuleBuilder()
+ checkBootJars := rule.Command().BuiltTool(ctx, "check_boot_jars").
+ Input(ctx.Config().HostToolPath(ctx, "dexdump")).
+ Input(android.PathForSource(ctx, "build/soong/scripts/check_boot_jars/package_allowed_list.txt"))
+
+ // If this is not an unbundled build and missing dependencies are not allowed
+ // then all the boot jars listed must have been found.
+ strict := !config.UnbundledBuild() && !config.AllowMissingDependencies()
+
+ // Iterate over the module names on the boot classpath in order
+ for _, name := range android.SortedStringKeys(moduleToApex) {
+ if apexVariant, ok := nameToApexVariant[name]; ok {
+ if dep, ok := apexVariant.(interface{ DexJarBuildPath() android.Path }); ok {
+ // Add the dex implementation jar for the module to be checked.
+ checkBootJars.Input(dep.DexJarBuildPath())
+ } else {
+ ctx.Errorf("module %q is of type %q which is not supported as a boot jar", name, ctx.ModuleType(apexVariant))
+ }
+ } else if strict {
+ ctx.Errorf("boot jars package check failed as it could not find module %q for apex %q", name, moduleToApex[name])
+ }
+ }
+
+ checkBootJars.Text("&& touch").Output(timestamp)
+ rule.Build(pctx, ctx, "boot_jars_package_check", "check boot jar packages")
+
+ // The check-boot-jars phony target depends on the timestamp created if the check succeeds.
+ ctx.Phony("check-boot-jars", timestamp)
+
+ // The droidcore phony target depends on the check-boot-jars phony target
+ ctx.Phony("droidcore", android.PathForPhony(ctx, "check-boot-jars"))
+}
diff --git a/java/builder.go b/java/builder.go
index 3043e46..cd35245 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -572,14 +572,7 @@
}
func GenerateMainClassManifest(ctx android.ModuleContext, outputFile android.WritablePath, mainClass string) {
- ctx.Build(pctx, android.BuildParams{
- Rule: android.WriteFile,
- Description: "manifest",
- Output: outputFile,
- Args: map[string]string{
- "content": "Main-Class: " + mainClass + "\n",
- },
- })
+ android.WriteFileRule(ctx, outputFile, "Main-Class: "+mainClass+"\n")
}
func TransformZipAlign(ctx android.ModuleContext, outputFile android.WritablePath, inputFile android.Path) {
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index 40a2280..cd395b1 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -163,7 +163,7 @@
return nil
}
-func (d *DeviceHostConverter) ExportedSdkLibs() dexpreopt.LibraryPaths {
+func (d *DeviceHostConverter) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
return nil
}
diff --git a/java/dex.go b/java/dex.go
index 21a5926..055d479 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -135,6 +135,7 @@
"$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/dexpreopt.go b/java/dexpreopt.go
index f1b7178..a21fb76 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -33,11 +33,9 @@
isTest bool
isPresignedPrebuilt bool
- manifestFile android.Path
- usesLibs []string
- optionalUsesLibs []string
- enforceUsesLibs bool
- libraryPaths dexpreopt.LibraryPaths
+ manifestFile android.Path
+ enforceUsesLibs bool
+ classLoaderContexts dexpreopt.ClassLoaderContextMap
builtInstalled string
}
@@ -94,7 +92,7 @@
}
// Don't preopt APEX variant module
- if am, ok := ctx.Module().(android.ApexModule); ok && !am.IsForPlatform() {
+ if apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo); !apexInfo.IsForPlatform() {
return true
}
@@ -193,10 +191,8 @@
ProfileIsTextListing: profileIsTextListing,
ProfileBootListing: profileBootListing,
- EnforceUsesLibraries: d.enforceUsesLibs,
- OptionalUsesLibraries: d.optionalUsesLibs,
- UsesLibraries: d.usesLibs,
- LibraryPaths: d.libraryPaths,
+ EnforceUsesLibraries: d.enforceUsesLibs,
+ ClassLoaderContexts: d.classLoaderContexts,
Archs: archs,
DexPreoptImages: images,
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 3addc1a..f9975ba 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -238,6 +238,13 @@
dumpOatRules(ctx, d.defaultBootImage)
}
+func isHostdex(module android.Module) bool {
+ if lib, ok := module.(*Library); ok {
+ return Bool(lib.deviceProperties.Hostdex)
+ }
+ return false
+}
+
// Inspect this module to see if it contains a bootclasspath dex jar.
// Note that the same jar may occur in multiple modules.
// This logic is tested in the apex package to avoid import cycle apex <-> java.
@@ -259,12 +266,13 @@
}
// Check that this module satisfies constraints for a particular boot image.
- apex, isApexModule := module.(android.ApexModule)
- fromUpdatableApex := isApexModule && apex.Updatable()
+ _, isApexModule := module.(android.ApexModule)
+ apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+ fromUpdatableApex := isApexModule && apexInfo.Updatable
if image.name == artBootImageName {
- if isApexModule && len(apex.InApexes()) > 0 && allHavePrefix(apex.InApexes(), "com.android.art.") {
+ if isApexModule && len(apexInfo.InApexes) > 0 && allHavePrefix(apexInfo.InApexes, "com.android.art") {
// ok: found the jar in the ART apex
- } else if isApexModule && apex.IsForPlatform() && Bool(module.(*Library).deviceProperties.Hostdex) {
+ } else if isApexModule && apexInfo.IsForPlatform() && isHostdex(module) {
// exception (skip and continue): special "hostdex" platform variant
return -1, nil
} else if name == "jacocoagent" && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
@@ -272,7 +280,7 @@
return -1, nil
} else if fromUpdatableApex {
// error: this jar is part of an updatable apex other than ART
- ctx.Errorf("module %q from updatable apexes %q is not allowed in the ART boot image", name, apex.InApexes())
+ ctx.Errorf("module %q from updatable apexes %q is not allowed in the ART boot image", name, apexInfo.InApexes)
} else {
// error: this jar is part of the platform or a non-updatable apex
ctx.Errorf("module %q is not allowed in the ART boot image", name)
@@ -282,7 +290,7 @@
// ok: this jar is part of the platform or a non-updatable apex
} else {
// error: this jar is part of an updatable apex
- ctx.Errorf("module %q from updatable apexes %q is not allowed in the framework boot image", name, apex.InApexes())
+ ctx.Errorf("module %q from updatable apexes %q is not allowed in the framework boot image", name, apexInfo.InApexes)
}
} else {
panic("unknown boot image: " + image.name)
@@ -293,7 +301,7 @@
func allHavePrefix(list []string, prefix string) bool {
for _, s := range list {
- if !strings.HasPrefix(s, prefix) {
+ if s != prefix && !strings.HasPrefix(s, prefix+".") {
return false
}
}
@@ -643,14 +651,8 @@
updatableBcpPackagesName := "updatable-bcp-packages.txt"
updatableBcpPackages := image.dir.Join(ctx, updatableBcpPackagesName)
- ctx.Build(pctx, android.BuildParams{
- Rule: android.WriteFile,
- Output: updatableBcpPackages,
- Args: map[string]string{
- // WriteFile automatically adds the last end-of-line.
- "content": strings.Join(updatablePackages, "\\n"),
- },
- })
+ // WriteFileRule automatically adds the last end-of-line.
+ android.WriteFileRule(ctx, updatableBcpPackages, strings.Join(updatablePackages, "\n"))
rule := android.NewRuleBuilder()
rule.MissingDeps(missingDeps)
@@ -712,13 +714,7 @@
func writeGlobalConfigForMake(ctx android.SingletonContext, path android.WritablePath) {
data := dexpreopt.GetGlobalConfigRawData(ctx)
- ctx.Build(pctx, android.BuildParams{
- Rule: android.WriteFile,
- Output: path,
- Args: map[string]string{
- "content": string(data),
- },
- })
+ android.WriteFileRule(ctx, path, string(data))
}
// Export paths for default boot image to Make
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index 4a8d3cd..95fe5e1 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -48,10 +48,10 @@
pathCtx := android.PathContextForTesting(config)
dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx)
- dexpreoptConfig.BootJars = android.CreateConfiguredJarList(pathCtx, []string{"platform:foo", "platform:bar", "platform:baz"})
+ dexpreoptConfig.BootJars = android.CreateTestConfiguredJarList([]string{"platform:foo", "platform:bar", "platform:baz"})
dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig)
- ctx := testContext()
+ ctx := testContext(config)
RegisterDexpreoptBootJarsComponents(ctx)
run(t, ctx, config)
@@ -87,7 +87,7 @@
ruleFile := "boot-foo.art"
expectedInputs := []string{
- "dex_artjars/android/apex/com.android.art/javalib/arm64/boot.art",
+ "dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art",
"dex_bootjars_input/foo.jar",
"dex_bootjars_input/bar.jar",
"dex_bootjars_input/baz.jar",
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index f0d82ff..c315124 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -81,15 +81,14 @@
targets := dexpreoptTargets(ctx)
deviceDir := android.PathForOutput(ctx, ctx.Config().DeviceName())
- artModules := global.ArtApexJars.CopyOf()
+ artModules := global.ArtApexJars
// With EMMA_INSTRUMENT_FRAMEWORK=true the Core libraries depend on jacoco.
if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
- artModules.Append("com.android.art", "jacocoagent")
+ artModules = artModules.Append("com.android.art", "jacocoagent")
}
- frameworkModules := global.BootJars.CopyOf()
- frameworkModules.RemoveList(artModules)
+ frameworkModules := global.BootJars.RemoveList(artModules)
- artSubdir := "apex/com.android.art/javalib"
+ artSubdir := "apex/art_boot_images/javalib"
frameworkSubdir := "system/framework"
// ART config for the primary boot image in the ART apex.
diff --git a/java/droiddoc.go b/java/droiddoc.go
index e39a556..c7a27c2 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -19,7 +19,6 @@
"path/filepath"
"strings"
- "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -30,16 +29,6 @@
func init() {
RegisterDocsBuildComponents(android.InitRegistrationContext)
RegisterStubsBuildComponents(android.InitRegistrationContext)
-
- // Register sdk member type.
- android.RegisterSdkMemberType(&droidStubsSdkMemberType{
- SdkMemberTypeBase: android.SdkMemberTypeBase{
- PropertyName: "stubs_sources",
- // stubs_sources can be used with sdk to provide the source stubs for APIs provided by
- // the APEX.
- SupportsSdk: true,
- },
- })
}
func RegisterDocsBuildComponents(ctx android.RegistrationContext) {
@@ -253,11 +242,19 @@
// 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.
Generate_stubs *bool
+ // if set to true, provides a hint to the build system that this rule uses a lot of memory,
+ // whicih can be used for scheduling purposes
+ High_mem *bool
+
// is set to true, Metalava will allow framework SDK to contain API levels annotations.
Api_levels_annotations_enabled *bool
@@ -270,10 +267,6 @@
// if set to true, collect the values used by the Dev tools and
// write them in files packaged with the SDK. Defaults to false.
Write_sdk_values *bool
-
- // If set to true, .xml based public API file will be also generated, and
- // JDiff tool will be invoked to genreate javadoc files. Defaults to false.
- Jdiff_enabled *bool
}
//
@@ -582,9 +575,8 @@
srcFiles = filterByPackage(srcFiles, j.properties.Filter_packages)
// While metalava needs package html files, it does not need them to be explicit on the command
- // line. More importantly, the metalava rsp file is also used by the subsequent jdiff action if
- // jdiff_enabled=true. javadoc complains if it receives html files on the command line. The filter
- // below excludes html files from the rsp file for both metalava and jdiff. Note that the html
+ // line. javadoc complains if it receives html files on the command line. The filter
+ // below excludes html files from the rsp file metalava. Note that the html
// files are still included as implicit inputs for successful remote execution and correct
// incremental builds.
filterHtml := func(srcs []android.Path) []android.Path {
@@ -1017,10 +1009,8 @@
annotationsZip android.WritablePath
apiVersionsXml android.WritablePath
- apiFilePath android.Path
-
- jdiffDocZip android.WritablePath
- jdiffStubsSrcJar android.WritablePath
+ apiFilePath android.Path
+ removedApiFilePath android.Path
metadataZip android.WritablePath
metadataDir android.WritablePath
@@ -1060,6 +1050,10 @@
return android.Paths{d.stubsSrcJar}, nil
case ".docs.zip":
return android.Paths{d.docZip}, nil
+ case ".api.txt":
+ return android.Paths{d.apiFilePath}, nil
+ case ".removed-api.txt":
+ return android.Paths{d.removedApiFilePath}, nil
case ".annotations.zip":
return android.Paths{d.annotationsZip}, nil
case ".api_versions.xml":
@@ -1074,7 +1068,7 @@
}
func (d *Droidstubs) RemovedApiFilePath() android.Path {
- return d.removedApiFile
+ return d.removedApiFilePath
}
func (d *Droidstubs) StubsSrcJar() android.Path {
@@ -1125,6 +1119,9 @@
d.apiFile = android.PathForModuleOut(ctx, filename)
cmd.FlagWithOutput("--api ", d.apiFile)
d.apiFilePath = d.apiFile
+ } else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
+ // If check api is disabled then make the source file available for export.
+ d.apiFilePath = android.PathForModuleSrc(ctx, sourceApiFile)
}
if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
@@ -1133,6 +1130,10 @@
filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
d.removedApiFile = android.PathForModuleOut(ctx, filename)
cmd.FlagWithOutput("--removed-api ", d.removedApiFile)
+ d.removedApiFilePath = d.removedApiFile
+ } else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
+ // If check api is disabled then make the source removed api file available for export.
+ d.removedApiFilePath = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
}
if String(d.properties.Removed_dex_api_filename) != "" {
@@ -1150,7 +1151,9 @@
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 +1231,7 @@
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")
@@ -1248,30 +1251,8 @@
})
}
-func (d *Droidstubs) apiToXmlFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
- if Bool(d.properties.Jdiff_enabled) && d.apiFile != nil {
- if d.apiFile.String() == "" {
- ctx.ModuleErrorf("API signature file has to be specified in Metalava when jdiff is enabled.")
- }
-
- d.apiXmlFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_api.xml")
- cmd.FlagWithOutput("--api-xml ", d.apiXmlFile)
-
- if String(d.properties.Check_api.Last_released.Api_file) == "" {
- ctx.PropertyErrorf("check_api.last_released.api_file",
- "has to be non-empty if jdiff was enabled!")
- }
-
- lastReleasedApi := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file))
- d.lastReleasedApiXmlFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_last_released_api.xml")
- cmd.FlagWithInput("--convert-to-jdiff ", lastReleasedApi).Output(d.lastReleasedApiXmlFile)
- }
-}
-
func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
srcJarList android.Path, bootclasspath, classpath classpath, sourcepaths android.Paths, implicitsRsp android.WritablePath, sandbox bool) *android.RuleBuilderCommand {
- // Metalava uses lots of memory, restrict the number of metalava jobs that can run in parallel.
- rule.HighMem()
cmd := rule.Command()
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA") {
rule.Remoteable(android.RemoteRuleSupports{RBE: true})
@@ -1298,6 +1279,7 @@
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).
@@ -1352,6 +1334,11 @@
rule := android.NewRuleBuilder()
+ if BoolDefault(d.properties.High_mem, false) {
+ // This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
+ rule.HighMem()
+ }
+
generateStubs := BoolDefault(d.properties.Generate_stubs, true)
var stubsDir android.OptionalPath
if generateStubs {
@@ -1375,7 +1362,6 @@
d.annotationsFlags(ctx, cmd)
d.inclusionAnnotationsFlags(ctx, cmd)
d.apiLevelsAnnotationsFlags(ctx, cmd)
- d.apiToXmlFlags(ctx, cmd)
if android.InList("--generate-documentation", d.Javadoc.args) {
// Currently Metalava have the ability to invoke Javadoc in a seperate process.
@@ -1411,9 +1397,7 @@
// 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.
}
@@ -1654,74 +1638,6 @@
rule.Build(pctx, ctx, "nullabilityWarningsCheck", "nullability warnings check")
}
-
- if Bool(d.properties.Jdiff_enabled) {
- if len(d.Javadoc.properties.Out) > 0 {
- ctx.PropertyErrorf("out", "out property may not be combined with jdiff")
- }
-
- outDir := android.PathForModuleOut(ctx, "jdiff-out")
- srcJarDir := android.PathForModuleOut(ctx, "jdiff-srcjars")
- stubsDir := android.PathForModuleOut(ctx, "jdiff-stubsDir")
-
- rule := android.NewRuleBuilder()
-
- // Please sync with android-api-council@ before making any changes for the name of jdiffDocZip below
- // since there's cron job downstream that fetch this .zip file periodically.
- // See b/116221385 for reference.
- d.jdiffDocZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"jdiff-docs.zip")
- d.jdiffStubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"jdiff-stubs.srcjar")
-
- jdiff := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "jdiff.jar")
-
- rule.Command().Text("rm -rf").Text(outDir.String()).Text(stubsDir.String())
- rule.Command().Text("mkdir -p").Text(outDir.String()).Text(stubsDir.String())
-
- srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars)
-
- cmd := javadocBootclasspathCmd(ctx, rule, d.Javadoc.srcFiles, outDir, srcJarDir, srcJarList,
- deps.bootClasspath, deps.classpath, d.sourcepaths)
-
- cmd.Flag("-J-Xmx1600m").
- Flag("-XDignore.symbol.file").
- FlagWithArg("-doclet ", "jdiff.JDiff").
- FlagWithInput("-docletpath ", jdiff).
- Flag("-quiet")
-
- if d.apiXmlFile != nil {
- cmd.FlagWithArg("-newapi ", strings.TrimSuffix(d.apiXmlFile.Base(), d.apiXmlFile.Ext())).
- FlagWithArg("-newapidir ", filepath.Dir(d.apiXmlFile.String())).
- Implicit(d.apiXmlFile)
- }
-
- if d.lastReleasedApiXmlFile != nil {
- cmd.FlagWithArg("-oldapi ", strings.TrimSuffix(d.lastReleasedApiXmlFile.Base(), d.lastReleasedApiXmlFile.Ext())).
- FlagWithArg("-oldapidir ", filepath.Dir(d.lastReleasedApiXmlFile.String())).
- Implicit(d.lastReleasedApiXmlFile)
- }
-
- rule.Command().
- BuiltTool(ctx, "soong_zip").
- Flag("-write_if_changed").
- Flag("-d").
- FlagWithOutput("-o ", d.jdiffDocZip).
- FlagWithArg("-C ", outDir.String()).
- FlagWithArg("-D ", outDir.String())
-
- rule.Command().
- BuiltTool(ctx, "soong_zip").
- Flag("-write_if_changed").
- Flag("-jar").
- FlagWithOutput("-o ", d.jdiffStubsSrcJar).
- FlagWithArg("-C ", stubsDir.String()).
- FlagWithArg("-D ", stubsDir.String())
-
- rule.Restat()
-
- zipSyncCleanupCmd(rule, srcJarDir)
-
- rule.Build(pctx, ctx, "jdiff", "jdiff")
- }
}
//
@@ -1902,47 +1818,3 @@
InitDroiddocModule(module, android.HostAndDeviceSupported)
return module
}
-
-type droidStubsSdkMemberType struct {
- android.SdkMemberTypeBase
-}
-
-func (mt *droidStubsSdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
- mctx.AddVariationDependencies(nil, dependencyTag, names...)
-}
-
-func (mt *droidStubsSdkMemberType) IsInstance(module android.Module) bool {
- _, ok := module.(*Droidstubs)
- return ok
-}
-
-func (mt *droidStubsSdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
- return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_stubs_sources")
-}
-
-func (mt *droidStubsSdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
- return &droidStubsInfoProperties{}
-}
-
-type droidStubsInfoProperties struct {
- android.SdkMemberPropertiesBase
-
- StubsSrcJar android.Path
-}
-
-func (p *droidStubsInfoProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
- droidstubs := variant.(*Droidstubs)
- p.StubsSrcJar = droidstubs.stubsSrcJar
-}
-
-func (p *droidStubsInfoProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
- if p.StubsSrcJar != nil {
- builder := ctx.SnapshotBuilder()
-
- snapshotRelativeDir := filepath.Join("java", ctx.Name()+"_stubs_sources")
-
- builder.UnzipToSnapshot(p.StubsSrcJar, snapshotRelativeDir)
-
- propertySet.AddProperty("srcs", []string{snapshotRelativeDir})
- }
-}
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index b6af3bf..1f80e77 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -18,6 +18,7 @@
"fmt"
"android/soong/android"
+ "android/soong/genrule"
)
func init() {
@@ -92,31 +93,34 @@
// 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.
@@ -158,10 +162,9 @@
// For a java lib included in an APEX, only take the one built for
// the platform variant, and skip the variants for APEXes.
// Otherwise, the hiddenapi tool will complain about duplicated classes
- if a, ok := module.(android.ApexModule); ok {
- if android.InAnyApex(module.Name()) && !a.IsForPlatform() {
- return
- }
+ apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+ if !apexInfo.IsForPlatform() {
+ return
}
bootDexJars = append(bootDexJars, jar)
@@ -208,43 +211,30 @@
rule.Build(pctx, ctx, "hiddenAPIStubFlagsFile", "hiddenapi stub flags")
}
-func moduleForGreyListRemovedApis(ctx android.SingletonContext, module android.Module) bool {
- switch ctx.ModuleName(module) {
- case "api-stubs-docs", "system-api-stubs-docs", "android.car-stubs-docs", "android.car-system-stubs-docs":
- return true
- default:
- return false
- }
-}
-
// flagsRule creates a rule to build hiddenapi-flags.csv out of flags.csv files generated for boot image modules and
// the unsupported API.
func flagsRule(ctx android.SingletonContext) android.Path {
var flagsCSV android.Paths
- var greylistRemovedApis android.Paths
+ var combinedRemovedApis android.Path
ctx.VisitAllModules(func(module android.Module) {
if h, ok := module.(hiddenAPIIntf); ok {
if csv := h.flagsCSV(); csv != nil {
flagsCSV = append(flagsCSV, csv)
}
- } else if ds, ok := module.(*Droidstubs); ok {
- // Track @removed public and system APIs via corresponding droidstubs targets.
- // These APIs are not present in the stubs, however, we have to keep allowing access
- // to them at runtime.
- if moduleForGreyListRemovedApis(ctx, module) {
- greylistRemovedApis = append(greylistRemovedApis, ds.removedDexApiFile)
+ } else if g, ok := module.(*genrule.Module); ok {
+ if ctx.ModuleName(module) == "combined-removed-dex" {
+ if len(g.GeneratedSourceFiles()) != 1 || combinedRemovedApis != nil {
+ ctx.Errorf("Expected 1 combined-removed-dex module that generates 1 output file.")
+ }
+ combinedRemovedApis = g.GeneratedSourceFiles()[0]
}
}
})
- combinedRemovedApis := android.PathForOutput(ctx, "hiddenapi", "combined-removed-dex.txt")
- ctx.Build(pctx, android.BuildParams{
- Rule: android.Cat,
- Inputs: greylistRemovedApis,
- Output: combinedRemovedApis,
- Description: "Combine removed apis for " + combinedRemovedApis.String(),
- })
+ if combinedRemovedApis == nil {
+ ctx.Errorf("Failed to find combined-removed-dex.")
+ }
rule := android.NewRuleBuilder()
@@ -259,17 +249,19 @@
Inputs(flagsCSV).
FlagWithInput("--unsupported ",
android.PathForSource(ctx, "frameworks/base/config/hiddenapi-unsupported.txt")).
- FlagWithInput("--unsupported-ignore-conflicts ", combinedRemovedApis).
+ FlagWithInput("--unsupported ", combinedRemovedApis).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed").
FlagWithInput("--max-target-q ",
android.PathForSource(ctx, "frameworks/base/config/hiddenapi-max-target-q.txt")).
FlagWithInput("--max-target-p ",
android.PathForSource(ctx, "frameworks/base/config/hiddenapi-max-target-p.txt")).
- FlagWithInput("--max-target-o-ignore-conflicts ",
- android.PathForSource(ctx, "frameworks/base/config/hiddenapi-max-target-o.txt")).
+ FlagWithInput("--max-target-o ", android.PathForSource(
+ ctx, "frameworks/base/config/hiddenapi-max-target-o.txt")).Flag("--ignore-conflicts ").
FlagWithInput("--blocked ",
android.PathForSource(ctx, "frameworks/base/config/hiddenapi-force-blocked.txt")).
- FlagWithInput("--unsupported-packages ",
- android.PathForSource(ctx, "frameworks/base/config/hiddenapi-unsupported-packages.txt")).
+ FlagWithInput("--blocked ",
+ android.PathForSource(ctx, "frameworks/base/config/hiddenapi-temp-blocklist.txt")).
+ FlagWithInput("--unsupported ", android.PathForSource(
+ ctx, "frameworks/base/config/hiddenapi-unsupported-packages.txt")).Flag("--packages ").
FlagWithOutput("--output ", tempPath)
commitChangeForRestat(rule, tempPath, outputPath)
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index bcca93a..34a4856 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -16,35 +16,49 @@
import (
"android/soong/android"
+ "fmt"
"strings"
"testing"
+
+ "github.com/google/blueprint/proptools"
)
func testConfigWithBootJars(bp string, bootJars []string) android.Config {
config := testConfig(nil, bp, nil)
- config.TestProductVariables.BootJars = bootJars
+ config.TestProductVariables.BootJars = android.CreateTestConfiguredJarList(bootJars)
return config
}
-func testContextWithHiddenAPI() *android.TestContext {
- ctx := testContext()
+func testContextWithHiddenAPI(config android.Config) *android.TestContext {
+ ctx := testContext(config)
ctx.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory)
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()
+ ctx := testContextWithHiddenAPI(config)
run(t, ctx, config)
+ return ctx
+}
- return ctx, config
+func testHiddenAPIBootJars(t *testing.T, bp string, bootJars []string) (*android.TestContext, android.Config) {
+ config := testConfigWithBootJars(bp, bootJars)
+
+ 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 TestHiddenAPISingletonWithPrebuilt(t *testing.T) {
- ctx, _ := testHiddenAPI(t, `
+ ctx, _ := testHiddenAPIBootJars(t, `
java_import {
name: "foo",
jars: ["a.jar"],
@@ -78,7 +92,7 @@
}
func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) {
- ctx, _ := testHiddenAPI(t, `
+ ctx, _ := testHiddenAPIBootJars(t, `
java_library {
name: "foo",
srcs: ["a.java"],
@@ -107,7 +121,7 @@
}
func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) {
- ctx, _ := testHiddenAPI(t, `
+ ctx, _ := testHiddenAPIBootJars(t, `
java_library {
name: "foo",
srcs: ["a.java"],
@@ -134,3 +148,72 @@
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 d67e9e0..5ded041 100644
--- a/java/java.go
+++ b/java/java.go
@@ -416,8 +416,8 @@
// manifest file to use instead of properties.Manifest
overrideManifest android.OptionalPath
- // map of SDK libs exported by this java module to their build and install paths
- exportedSdkLibs dexpreopt.LibraryPaths
+ // map of SDK version to class loader context
+ classLoaderContexts dexpreopt.ClassLoaderContextMap
// list of plugins that this java module is exporting
exportedPluginJars android.Paths
@@ -451,6 +451,8 @@
// Collect the module directory for IDE info in java/jdeps.go.
modulePaths []string
+
+ hideApexVariantFromMake bool
}
func (j *Module) addHostProperties() {
@@ -507,7 +509,7 @@
ImplementationJars() android.Paths
ResourceJars() android.Paths
AidlIncludeDirs() android.Paths
- ExportedSdkLibs() dexpreopt.LibraryPaths
+ ClassLoaderContexts() dexpreopt.ClassLoaderContextMap
ExportedPlugins() (android.Paths, []string)
SrcJarArgs() ([]string, android.Paths)
BaseModuleName() string
@@ -545,13 +547,20 @@
name string
}
-type jniDependencyTag struct {
- blueprint.BaseDependencyTag
+type usesLibraryDependencyTag struct {
+ dependencyTag
+ sdkVersion int // SDK version in which the library appared as a standalone library.
+}
+
+func makeUsesLibraryDependencyTag(sdkVersion int) usesLibraryDependencyTag {
+ return usesLibraryDependencyTag{
+ dependencyTag: dependencyTag{name: fmt.Sprintf("uses-library-%d", sdkVersion)},
+ sdkVersion: sdkVersion,
+ }
}
func IsJniDepTag(depTag blueprint.DependencyTag) bool {
- _, ok := depTag.(*jniDependencyTag)
- return ok
+ return depTag == jniLibTag
}
var (
@@ -569,8 +578,12 @@
proguardRaiseTag = dependencyTag{name: "proguard-raise"}
certificateTag = dependencyTag{name: "certificate"}
instrumentationForTag = dependencyTag{name: "instrumentation_for"}
- usesLibTag = dependencyTag{name: "uses-library"}
extraLintCheckTag = dependencyTag{name: "extra-lint-check"}
+ jniLibTag = dependencyTag{name: "jnilib"}
+ usesLibTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion)
+ usesLibCompat28Tag = makeUsesLibraryDependencyTag(28)
+ usesLibCompat29Tag = makeUsesLibraryDependencyTag(29)
+ usesLibCompat30Tag = makeUsesLibraryDependencyTag(30)
)
func IsLibDepTag(depTag blueprint.DependencyTag) bool {
@@ -638,8 +651,9 @@
// Force enable the instrumentation for java code that is built for APEXes ...
// except for the jacocoagent itself (because instrumenting jacocoagent using jacocoagent
// doesn't make sense) or framework libraries (e.g. libraries found in the InstrumentFrameworkModules list) unless EMMA_INSTRUMENT_FRAMEWORK is true.
+ apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
isJacocoAgent := ctx.ModuleName() == "jacocoagent"
- if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && !isJacocoAgent && !j.IsForPlatform() {
+ if j.DirectlyInAnyApex() && !isJacocoAgent && !apexInfo.IsForPlatform() {
if !inList(ctx.ModuleName(), config.InstrumentFrameworkModules) {
return true
} else if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
@@ -735,9 +749,21 @@
return ret
}
- ctx.AddVariationDependencies(nil, libTag, rewriteSyspropLibs(j.properties.Libs, "libs")...)
+ libDeps := ctx.AddVariationDependencies(nil, libTag, rewriteSyspropLibs(j.properties.Libs, "libs")...)
ctx.AddVariationDependencies(nil, staticLibTag, rewriteSyspropLibs(j.properties.Static_libs, "static_libs")...)
+ // For library dependencies that are component libraries (like stubs), add the implementation
+ // as a dependency (dexpreopt needs to be against the implementation library, not stubs).
+ for _, dep := range libDeps {
+ if dep != nil {
+ if component, ok := dep.(SdkLibraryComponentDependency); ok {
+ if lib := component.OptionalSdkLibraryImplementation(); lib != nil {
+ ctx.AddVariationDependencies(nil, usesLibTag, *lib)
+ }
+ }
+ }
+ }
+
ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), pluginTag, j.properties.Plugins...)
ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), exportedPluginTag, j.properties.Exported_plugins...)
@@ -986,7 +1012,7 @@
otherName := ctx.OtherModuleName(module)
tag := ctx.OtherModuleDependencyTag(module)
- if _, ok := tag.(*jniDependencyTag); ok {
+ if IsJniDepTag(tag) {
// Handled by AndroidApp.collectAppDeps
return
}
@@ -1001,7 +1027,8 @@
case libTag:
deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
// names of sdk libs that are directly depended are exported
- j.exportedSdkLibs.MaybeAddLibraryPath(ctx, dep.OptionalImplicitSdkLibrary(), dep.DexJarBuildPath(), dep.DexJarInstallPath())
+ j.classLoaderContexts.MaybeAddContext(ctx, dep.OptionalImplicitSdkLibrary(), true,
+ dep.DexJarBuildPath(), dep.DexJarInstallPath())
case staticLibTag:
ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
}
@@ -1012,7 +1039,7 @@
case libTag, instrumentationForTag:
deps.classpath = append(deps.classpath, dep.HeaderJars()...)
// sdk lib names from dependencies are re-exported
- j.exportedSdkLibs.AddLibraryPaths(dep.ExportedSdkLibs())
+ j.classLoaderContexts.AddContextMap(dep.ClassLoaderContexts(), otherName)
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
pluginJars, pluginClasses := dep.ExportedPlugins()
addPlugins(&deps, pluginJars, pluginClasses...)
@@ -1024,7 +1051,7 @@
deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars()...)
deps.staticResourceJars = append(deps.staticResourceJars, dep.ResourceJars()...)
// sdk lib names from dependencies are re-exported
- j.exportedSdkLibs.AddLibraryPaths(dep.ExportedSdkLibs())
+ j.classLoaderContexts.AddContextMap(dep.ClassLoaderContexts(), otherName)
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
pluginJars, pluginClasses := dep.ExportedPlugins()
addPlugins(&deps, pluginJars, pluginClasses...)
@@ -1161,18 +1188,6 @@
// javaVersion flag.
flags.javaVersion = getJavaVersion(ctx, String(j.properties.Java_version), sdkContext(j))
- // javac flags.
- javacFlags := j.properties.Javacflags
- if flags.javaVersion.usesJavaModules() {
- javacFlags = append(javacFlags, j.properties.Openjdk9.Javacflags...)
- }
- if ctx.Config().MinimizeJavaDebugInfo() && !ctx.Host() {
- // For non-host binaries, override the -g flag passed globally to remove
- // local variable debug info to reduce disk and memory usage.
- javacFlags = append(javacFlags, "-g:source,lines")
- }
- javacFlags = append(javacFlags, "-Xlint:-dep-ann")
-
if ctx.Config().RunErrorProne() {
if config.ErrorProneClasspath == nil {
ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?")
@@ -1223,24 +1238,77 @@
}
}
- if j.properties.Patch_module != nil && flags.javaVersion.usesJavaModules() {
- // Manually specify build directory in case it is not under the repo root.
- // (javac doesn't seem to expand into symbolc links when searching for patch-module targets, so
- // just adding a symlink under the root doesn't help.)
- patchPaths := ".:" + ctx.Config().BuildDir()
- classPath := flags.classpath.FormJavaClassPath("")
- if classPath != "" {
- patchPaths += ":" + classPath
- }
- javacFlags = append(javacFlags, "--patch-module="+String(j.properties.Patch_module)+"="+patchPaths)
- }
-
// systemModules
flags.systemModules = deps.systemModules
// aidl flags.
flags.aidlFlags, flags.aidlDeps = j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs)
+ return flags
+}
+
+func (j *Module) collectJavacFlags(
+ ctx android.ModuleContext, flags javaBuilderFlags, srcFiles android.Paths) javaBuilderFlags {
+ // javac flags.
+ javacFlags := j.properties.Javacflags
+
+ if ctx.Config().MinimizeJavaDebugInfo() && !ctx.Host() {
+ // For non-host binaries, override the -g flag passed globally to remove
+ // local variable debug info to reduce disk and memory usage.
+ javacFlags = append(javacFlags, "-g:source,lines")
+ }
+ javacFlags = append(javacFlags, "-Xlint:-dep-ann")
+
+ if flags.javaVersion.usesJavaModules() {
+ javacFlags = append(javacFlags, j.properties.Openjdk9.Javacflags...)
+
+ if j.properties.Patch_module != nil {
+ // Manually specify build directory in case it is not under the repo root.
+ // (javac doesn't seem to expand into symbolic links when searching for patch-module targets, so
+ // just adding a symlink under the root doesn't help.)
+ patchPaths := []string{".", ctx.Config().BuildDir()}
+
+ // b/150878007
+ //
+ // Workaround to support *Bazel-executed* JDK9 javac in Bazel's
+ // execution root for --patch-module. If this javac command line is
+ // invoked within Bazel's execution root working directory, the top
+ // level directories (e.g. libcore/, tools/, frameworks/) are all
+ // symlinks. JDK9 javac does not traverse into symlinks, which causes
+ // --patch-module to fail source file lookups when invoked in the
+ // execution root.
+ //
+ // Short of patching javac or enumerating *all* directories as possible
+ // input dirs, manually add the top level dir of the source files to be
+ // compiled.
+ topLevelDirs := map[string]bool{}
+ for _, srcFilePath := range srcFiles {
+ srcFileParts := strings.Split(srcFilePath.String(), "/")
+ // Ignore source files that are already in the top level directory
+ // as well as generated files in the out directory. The out
+ // directory may be an absolute path, which means srcFileParts[0] is the
+ // empty string, so check that as well. Note that "out" in Bazel's execution
+ // root is *not* a symlink, which doesn't cause problems for --patch-modules
+ // anyway, so it's fine to not apply this workaround for generated
+ // source files.
+ if len(srcFileParts) > 1 &&
+ srcFileParts[0] != "" &&
+ srcFileParts[0] != "out" {
+ topLevelDirs[srcFileParts[0]] = true
+ }
+ }
+ patchPaths = append(patchPaths, android.SortedStringKeys(topLevelDirs)...)
+
+ classPath := flags.classpath.FormJavaClassPath("")
+ if classPath != "" {
+ patchPaths = append(patchPaths, classPath)
+ }
+ javacFlags = append(
+ javacFlags,
+ "--patch-module="+String(j.properties.Patch_module)+"="+strings.Join(patchPaths, ":"))
+ }
+ }
+
if len(javacFlags) > 0 {
// optimization.
ctx.Variable(pctx, "javacFlags", strings.Join(javacFlags, " "))
@@ -1271,6 +1339,10 @@
srcFiles = j.genSources(ctx, srcFiles, flags)
+ // Collect javac flags only after computing the full set of srcFiles to
+ // ensure that the --patch-module lookup paths are complete.
+ flags = j.collectJavacFlags(ctx, flags, srcFiles)
+
srcJars := srcFiles.FilterByExt(".srcjar")
srcJars = append(srcJars, deps.srcJars...)
if aaptSrcJar != nil {
@@ -1590,7 +1662,8 @@
j.implementationAndResourcesJar = implementationAndResourcesJar
// Enable dex compilation for the APEX variants, unless it is disabled explicitly
- if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && !j.IsForPlatform() {
+ apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ if j.DirectlyInAnyApex() && !apexInfo.IsForPlatform() {
if j.dexProperties.Compile_dex == nil {
j.dexProperties.Compile_dex = proptools.BoolPtr(true)
}
@@ -1658,7 +1731,7 @@
if v := sdkSpec.version; v.isNumbered() {
return v.String()
} else {
- return ctx.Config().DefaultAppTargetSdk()
+ return ctx.Config().DefaultAppTargetSdk(ctx).String()
}
}
@@ -1672,7 +1745,7 @@
j.linter.compileSdkVersion = lintSDKVersionString(j.sdkVersion())
j.linter.javaLanguageLevel = flags.javaVersion.String()
j.linter.kotlinLanguageLevel = "1.3"
- if j.ApexVariationName() != "" && ctx.Config().UnbundledBuildApps() {
+ if !apexInfo.IsForPlatform() && ctx.Config().UnbundledBuildApps() {
j.linter.buildModuleReportZip = true
}
j.linter.lint(ctx)
@@ -1830,8 +1903,8 @@
return j.exportAidlIncludeDirs
}
-func (j *Module) ExportedSdkLibs() dexpreopt.LibraryPaths {
- return j.exportedSdkLibs
+func (j *Module) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
+ return j.classLoaderContexts
}
func (j *Module) ExportedPlugins() (android.Paths, []string) {
@@ -1876,7 +1949,8 @@
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 +1962,7 @@
if err != nil {
return err
}
- if int(ver) > sdkVersion {
+ if ver.ApiLevel(ctx).GreaterThan(sdkVersion) {
return fmt.Errorf("newer SDK(%v)", ver)
}
return nil
@@ -1933,7 +2007,7 @@
func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bool {
// Store uncompressed (and aligned) any dex files from jars in APEXes.
- if am, ok := ctx.Module().(android.ApexModule); ok && !am.IsForPlatform() {
+ if apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo); !apexInfo.IsForPlatform() {
return true
}
@@ -1955,6 +2029,11 @@
}
func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ if !apexInfo.IsForPlatform() {
+ j.hideApexVariantFromMake = true
+ }
+
j.checkSdkVersions(ctx)
j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")
j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary
@@ -1963,13 +2042,13 @@
j.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter))
}
j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
- j.exportedSdkLibs = make(dexpreopt.LibraryPaths)
+ j.classLoaderContexts = make(dexpreopt.ClassLoaderContextMap)
j.compile(ctx, nil)
// Collect the module directory for IDE info in java/jdeps.go.
j.modulePaths = append(j.modulePaths, ctx.ModuleDir())
- exclusivelyForApex := android.InAnyApex(ctx.ModuleName()) && !j.IsForPlatform()
+ exclusivelyForApex := !apexInfo.IsForPlatform()
if (Bool(j.properties.Installable) || ctx.Host()) && !exclusivelyForApex {
var extraInstallDeps android.Paths
if j.InstallMixin != nil {
@@ -1983,11 +2062,12 @@
// add the name of that java_sdk_library to the exported sdk libs to make sure
// that, if necessary, a <uses-library> element for that java_sdk_library is
// added to the Android manifest.
- j.exportedSdkLibs.MaybeAddLibraryPath(ctx, j.OptionalImplicitSdkLibrary(), j.DexJarBuildPath(), j.DexJarInstallPath())
+ j.classLoaderContexts.MaybeAddContext(ctx, j.OptionalImplicitSdkLibrary(), true,
+ j.DexJarBuildPath(), j.DexJarInstallPath())
// A non-SDK library may provide a <uses-library> (the name may be different from the module name).
if lib := proptools.String(j.usesLibraryProperties.Provides_uses_lib); lib != "" {
- j.exportedSdkLibs.AddLibraryPath(ctx, lib, j.DexJarBuildPath(), j.DexJarInstallPath())
+ j.classLoaderContexts.AddContext(ctx, lib, true, j.DexJarBuildPath(), j.DexJarInstallPath())
}
j.distFiles = j.GenerateTaggedDistFiles(ctx)
@@ -2414,6 +2494,10 @@
// Name of the class containing main to be inserted into the manifest as Main-Class.
Main_class *string
+
+ // Names of modules containing JNI libraries that should be installed alongside the host
+ // variant of the binary.
+ Jni_libs []string
}
type Binary struct {
@@ -2454,18 +2538,21 @@
j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh")
}
- // Depend on the installed jar so that the wrapper doesn't get executed by
- // another build rule before the jar has been installed.
- jarFile := ctx.PrimaryModule().(*Binary).installFile
-
+ // The host installation rules make the installed wrapper depend on all the dependencies
+ // of the wrapper variant, which will include the common variant's jar file and any JNI
+ // libraries. This is verified by TestBinary.
j.binaryFile = ctx.InstallExecutable(android.PathForModuleInstall(ctx, "bin"),
- ctx.ModuleName(), j.wrapperFile, jarFile)
+ ctx.ModuleName(), j.wrapperFile)
}
}
func (j *Binary) DepsMutator(ctx android.BottomUpMutatorContext) {
if ctx.Arch().ArchType == android.Common {
j.deps(ctx)
+ } else {
+ // This dependency ensures the host installation rules will install the jni libraries
+ // when the wrapper is installed.
+ ctx.AddVariationDependencies(nil, jniLibTag, j.binaryProperties.Jni_libs...)
}
}
@@ -2559,8 +2646,10 @@
dexJarFile android.Path
combinedClasspathFile android.Path
- exportedSdkLibs dexpreopt.LibraryPaths
+ classLoaderContexts dexpreopt.ClassLoaderContextMap
exportAidlIncludeDirs android.Paths
+
+ hideApexVariantFromMake bool
}
func (j *Import) sdkVersion() sdkSpec {
@@ -2616,6 +2705,10 @@
}
func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ if !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform() {
+ j.hideApexVariantFromMake = true
+ }
+
jars := android.PathsForModuleSrc(ctx, j.properties.Jars)
jarName := j.Stem() + ".jar"
@@ -2628,7 +2721,7 @@
TransformJetifier(ctx, outputFile, inputFile)
}
j.combinedClasspathFile = outputFile
- j.exportedSdkLibs = make(dexpreopt.LibraryPaths)
+ j.classLoaderContexts = make(dexpreopt.ClassLoaderContextMap)
var flags javaBuilderFlags
@@ -2642,7 +2735,7 @@
case libTag, staticLibTag:
flags.classpath = append(flags.classpath, dep.HeaderJars()...)
// sdk lib names from dependencies are re-exported
- j.exportedSdkLibs.AddLibraryPaths(dep.ExportedSdkLibs())
+ j.classLoaderContexts.AddContextMap(dep.ClassLoaderContexts(), otherName)
case bootClasspathTag:
flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars()...)
}
@@ -2651,7 +2744,8 @@
case libTag:
flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
// names of sdk libs that are directly depended are exported
- j.exportedSdkLibs.AddLibraryPath(ctx, otherName, dep.DexJarBuildPath(), dep.DexJarInstallPath())
+ j.classLoaderContexts.AddContext(ctx, otherName, dep.IsSharedLibrary(),
+ dep.DexJarBuildPath(), dep.DexJarInstallPath())
}
}
})
@@ -2666,7 +2760,8 @@
// add the name of that java_sdk_library to the exported sdk libs to make sure
// that, if necessary, a <uses-library> element for that java_sdk_library is
// added to the Android manifest.
- j.exportedSdkLibs.MaybeAddLibraryPath(ctx, j.OptionalImplicitSdkLibrary(), outputFile, installFile)
+ j.classLoaderContexts.MaybeAddContext(ctx, j.OptionalImplicitSdkLibrary(), true,
+ outputFile, installFile)
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)
@@ -2698,6 +2793,17 @@
}
}
+func (j *Import) OutputFiles(tag string) (android.Paths, error) {
+ switch tag {
+ case "", ".jar":
+ return android.Paths{j.combinedClasspathFile}, nil
+ default:
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+ }
+}
+
+var _ android.OutputFileProducer = (*Import)(nil)
+
var _ Dependency = (*Import)(nil)
func (j *Import) HeaderJars() android.Paths {
@@ -2737,8 +2843,8 @@
return j.exportAidlIncludeDirs
}
-func (j *Import) ExportedSdkLibs() dexpreopt.LibraryPaths {
- return j.exportedSdkLibs
+func (j *Import) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
+ return j.classLoaderContexts
}
func (j *Import) ExportedPlugins() (android.Paths, []string) {
@@ -2753,7 +2859,8 @@
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
}
@@ -2847,6 +2954,8 @@
maybeStrippedDexJarFile android.Path
dexpreopter
+
+ hideApexVariantFromMake bool
}
func (j *DexImport) Prebuilt() *android.Prebuilt {
@@ -2882,6 +2991,11 @@
ctx.PropertyErrorf("jars", "exactly one jar must be provided")
}
+ apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ if !apexInfo.IsForPlatform() {
+ j.hideApexVariantFromMake = true
+ }
+
j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")
j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter)
@@ -2926,7 +3040,7 @@
j.maybeStrippedDexJarFile = dexOutputFile
- if j.IsForPlatform() {
+ if apexInfo.IsForPlatform() {
ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
j.Stem()+".jar", dexOutputFile)
}
@@ -2936,7 +3050,8 @@
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 9e63577..87d6ebb 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -70,9 +70,9 @@
return config
}
-func testContext() *android.TestContext {
+func testContext(config android.Config) *android.TestContext {
- ctx := android.NewTestArchContext()
+ ctx := android.NewTestArchContext(config)
RegisterJavaBuildComponents(ctx)
RegisterAppBuildComponents(ctx)
RegisterAARBuildComponents(ctx)
@@ -102,6 +102,10 @@
dexpreopt.RegisterToolModulesForTest(ctx)
+ ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel()
+ })
+
return ctx
}
@@ -111,7 +115,7 @@
pathCtx := android.PathContextForTesting(config)
dexpreopt.SetTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx))
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseBlueprintsFiles("Android.bp")
android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
@@ -125,12 +129,12 @@
func testJavaErrorWithConfig(t *testing.T, pattern string, config android.Config) (*android.TestContext, android.Config) {
t.Helper()
- ctx := testContext()
+ ctx := testContext(config)
pathCtx := android.PathContextForTesting(config)
dexpreopt.SetTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx))
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseBlueprintsFiles("Android.bp")
if len(errs) > 0 {
android.FailIfNoMatchingErrors(t, pattern, errs)
@@ -159,7 +163,7 @@
func testJavaWithConfig(t *testing.T, config android.Config) (*android.TestContext, android.Config) {
t.Helper()
- ctx := testContext()
+ ctx := testContext(config)
run(t, ctx, config)
return ctx, config
@@ -456,6 +460,14 @@
name: "bar",
srcs: ["b.java"],
static_libs: ["foo"],
+ jni_libs: ["libjni"],
+ }
+
+ cc_library_shared {
+ name: "libjni",
+ host_supported: true,
+ device_supported: false,
+ stl: "none",
}
`)
@@ -466,10 +478,17 @@
barWrapper := ctx.ModuleForTests("bar", buildOS+"_x86_64")
barWrapperDeps := barWrapper.Output("bar").Implicits.Strings()
+ libjni := ctx.ModuleForTests("libjni", buildOS+"_x86_64_shared")
+ libjniSO := libjni.Rule("Cp").Output.String()
+
// Test that the install binary wrapper depends on the installed jar file
- if len(barWrapperDeps) != 1 || barWrapperDeps[0] != barJar {
- t.Errorf("expected binary wrapper implicits [%q], got %v",
- barJar, barWrapperDeps)
+ if g, w := barWrapperDeps, barJar; !android.InList(w, g) {
+ t.Errorf("expected binary wrapper implicits to contain %q, got %q", w, g)
+ }
+
+ // Test that the install binary wrapper depends on the installed JNI libraries
+ if g, w := barWrapperDeps, libjniSO; !android.InList(w, g) {
+ t.Errorf("expected binary wrapper implicits to contain %q, got %q", w, g)
}
}
@@ -1213,31 +1232,24 @@
func TestDroidstubs(t *testing.T) {
ctx, _ := testJavaWithFS(t, `
droiddoc_exported_dir {
- name: "droiddoc-templates-sdk",
- path: ".",
+ name: "droiddoc-templates-sdk",
+ path: ".",
}
droidstubs {
- name: "bar-stubs",
- srcs: [
- "bar-doc/a.java",
- ],
- api_levels_annotations_dirs: [
- "droiddoc-templates-sdk",
- ],
- api_levels_annotations_enabled: true,
+ name: "bar-stubs",
+ srcs: ["bar-doc/a.java"],
+ api_levels_annotations_dirs: ["droiddoc-templates-sdk"],
+ api_levels_annotations_enabled: true,
}
droidstubs {
- name: "bar-stubs-other",
- srcs: [
- "bar-doc/a.java",
- ],
- api_levels_annotations_dirs: [
- "droiddoc-templates-sdk",
- ],
- api_levels_annotations_enabled: true,
- api_levels_jar_filename: "android.other.jar",
+ name: "bar-stubs-other",
+ srcs: ["bar-doc/a.java"],
+ high_mem: true,
+ api_levels_annotations_dirs: ["droiddoc-templates-sdk"],
+ api_levels_annotations_enabled: true,
+ api_levels_jar_filename: "android.other.jar",
}
`,
map[string][]byte{
@@ -1246,23 +1258,31 @@
testcases := []struct {
moduleName string
expectedJarFilename string
+ high_mem bool
}{
{
moduleName: "bar-stubs",
expectedJarFilename: "android.jar",
+ high_mem: false,
},
{
moduleName: "bar-stubs-other",
expectedJarFilename: "android.other.jar",
+ high_mem: true,
},
}
for _, c := range testcases {
m := ctx.ModuleForTests(c.moduleName, "android_common")
metalava := m.Rule("metalava")
+ rp := metalava.RuleParams
expected := "--android-jar-pattern ./%/public/" + c.expectedJarFilename
- if actual := metalava.RuleParams.Command; !strings.Contains(actual, expected) {
+ if actual := rp.Command; !strings.Contains(actual, expected) {
t.Errorf("For %q, expected metalava argument %q, but was not found %q", c.moduleName, expected, actual)
}
+
+ if actual := rp.Pool != nil && strings.Contains(rp.Pool.String(), "highmem"); actual != c.high_mem {
+ t.Errorf("Expected %q high_mem to be %v, was %v", c.moduleName, c.high_mem, actual)
+ }
}
}
@@ -1412,9 +1432,33 @@
name: "core",
sdk_version: "none",
system_modules: "none",
- }`),
+ }
+
+ filegroup {
+ name: "core-jar",
+ srcs: [":core{.jar}"],
+ }
+`),
})
- ctx := testContext()
+ ctx := testContext(config)
+ run(t, ctx, config)
+}
+
+func TestJavaImport(t *testing.T) {
+ config := testConfig(nil, "", map[string][]byte{
+ "libcore/Android.bp": []byte(`
+ java_import {
+ name: "core",
+ sdk_version: "none",
+ }
+
+ filegroup {
+ name: "core-jar",
+ srcs: [":core{.jar}"],
+ }
+`),
+ })
+ ctx := testContext(config)
run(t, ctx, config)
}
@@ -1487,6 +1531,12 @@
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,16 +1583,56 @@
"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 {
- sdkLibs := android.SortedStringKeys(quxLib.ExportedSdkLibs())
- if w := []string{"bar", "foo", "fred", "quuz"}; !reflect.DeepEqual(w, sdkLibs) {
+ sdkLibs := quxLib.ClassLoaderContexts().UsesLibs()
+ if w := []string{"foo", "bar", "fred", "quuz"}; !reflect.DeepEqual(w, sdkLibs) {
t.Errorf("qux should export %q but exports %q", w, sdkLibs)
}
}
}
+func TestJavaSdkLibrary_StubOrImplOnlyLibs(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_sdk_library {
+ name: "sdk_lib",
+ srcs: ["a.java"],
+ impl_only_libs: ["foo"],
+ stub_only_libs: ["bar"],
+ }
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ }
+ java_library {
+ name: "bar",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ }
+ `)
+
+ for _, implName := range []string{"sdk_lib", "sdk_lib.impl"} {
+ implJavacCp := ctx.ModuleForTests(implName, "android_common").Rule("javac").Args["classpath"]
+ if !strings.Contains(implJavacCp, "/foo.jar") || strings.Contains(implJavacCp, "/bar.jar") {
+ t.Errorf("%v javac classpath %v does not contain foo and not bar", implName, implJavacCp)
+ }
+ }
+ stubName := apiScopePublic.stubsLibraryModuleName("sdk_lib")
+ stubsJavacCp := ctx.ModuleForTests(stubName, "android_common").Rule("javac").Args["classpath"]
+ if strings.Contains(stubsJavacCp, "/foo.jar") || !strings.Contains(stubsJavacCp, "/bar.jar") {
+ t.Errorf("stubs javac classpath %v does not contain bar and not foo", stubsJavacCp)
+ }
+}
+
func TestJavaSdkLibrary_DoNotAccessImplWhenItIsNotBuilt(t *testing.T) {
ctx, _ := testJava(t, `
java_sdk_library {
@@ -1956,7 +2046,14 @@
java_library {
name: "baz",
- srcs: ["c.java"],
+ srcs: [
+ "c.java",
+ // Tests for b/150878007
+ "dir/d.java",
+ "dir2/e.java",
+ "dir2/f.java",
+ "nested/dir/g.java"
+ ],
patch_module: "java.base",
}
`
@@ -1965,7 +2062,8 @@
checkPatchModuleFlag(t, ctx, "foo", "")
expected := "java.base=.:" + buildDir
checkPatchModuleFlag(t, ctx, "bar", expected)
- expected = "java.base=" + strings.Join([]string{".", buildDir, moduleToPath("ext"), moduleToPath("framework")}, ":")
+ expected = "java.base=" + strings.Join([]string{
+ ".", buildDir, "dir", "dir2", "nested", moduleToPath("ext"), moduleToPath("framework")}, ":")
checkPatchModuleFlag(t, ctx, "baz", expected)
})
}
diff --git a/java/lint.go b/java/lint.go
index 3a210cc..3df582f 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -451,10 +451,13 @@
return
}
- if apex, ok := m.(android.ApexModule); ok && apex.NotAvailableForPlatform() && apex.IsForPlatform() {
- // There are stray platform variants of modules in apexes that are not available for
- // the platform, and they sometimes can't be built. Don't depend on them.
- return
+ if apex, ok := m.(android.ApexModule); ok && apex.NotAvailableForPlatform() {
+ apexInfo := ctx.ModuleProvider(m, android.ApexInfoProvider).(android.ApexInfo)
+ if apexInfo.IsForPlatform() {
+ // There are stray platform variants of modules in apexes that are not available for
+ // the platform, and they sometimes can't be built. Don't depend on them.
+ return
+ }
}
if l, ok := m.(lintOutputsIntf); ok {
diff --git a/java/robolectric.go b/java/robolectric.go
index ec112bc..62d1d99 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -31,7 +31,6 @@
}
var robolectricDefaultLibs = []string{
- "robolectric_android-all-stub",
"Robolectric_all-target",
"mockito-robolectric-prebuilt",
"truth-prebuilt",
@@ -99,7 +98,8 @@
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 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) 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")
@@ -385,8 +389,10 @@
}
runtimeFromSourceJar := android.OutputFileForModule(ctx, runtimeFromSourceModule, "")
+ // TODO(murj) Update this to ctx.Config().PlatformSdkCodename() once the platform
+ // classes like android.os.Build are updated to S.
runtimeName := fmt.Sprintf("android-all-%s-robolectric-r0.jar",
- ctx.Config().PlatformSdkCodename())
+ "R")
installedRuntime := ctx.InstallFile(androidAllDir, runtimeName, runtimeFromSourceJar)
r.runtimes = append(r.runtimes, installedRuntime)
}
diff --git a/java/sdk.go b/java/sdk.go
index 56fa12b..971791f 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -107,7 +107,7 @@
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 @@
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 @@
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 @@
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 @@
// 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 1a5ef54..13cd5f9 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -257,7 +257,7 @@
})
apiScopeTest = initApiScope(&apiScope{
name: "test",
- extends: apiScopePublic,
+ extends: apiScopeSystem,
legacyEnabledStatus: (*SdkLibrary).generateTestAndSystemScopesByDefault,
scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
return &module.sdkLibraryProperties.Test
@@ -388,6 +388,9 @@
// visibility property.
Stubs_source_visibility []string
+ // List of Java libraries that will be in the classpath when building the implementation lib
+ Impl_only_libs []string `android:"arch_variant"`
+
// List of Java libraries that will be in the classpath when building stubs
Stub_only_libs []string `android:"arch_variant"`
@@ -589,6 +592,9 @@
// 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 +607,9 @@
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 +642,10 @@
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"
@@ -660,6 +673,11 @@
return c.namingScheme.apiModuleName(apiScope, c.moduleBase.BaseModuleName())
}
+// If the SDK library is a shared library.
+func (c *commonToSdkLibraryAndImport) IsSharedLibrary() bool {
+ return c.sharedLibrary()
+}
+
// The component names for different outputs of the java_sdk_library.
//
// They are similar to the names used for the child modules it creates
@@ -732,6 +750,14 @@
}
} 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
}
}
@@ -852,6 +878,12 @@
return e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack
}
+// to satisfy SdkLibraryComponentDependency
+func (e *EmbeddableSdkLibraryComponent) OptionalSdkLibraryImplementation() *string {
+ // Currently implementation library name is the same as the SDK library name.
+ return e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack
+}
+
// Implemented by modules that are (or possibly could be) a component of a java_sdk_library
// (including the java_sdk_library) itself.
type SdkLibraryComponentDependency interface {
@@ -862,6 +894,9 @@
//
// Returns the name of the optional implicit SDK library or nil, if there isn't one.
OptionalImplicitSdkLibrary() *string
+
+ // The name of the implementation library for the optional SDK library or nil, if there isn't one.
+ OptionalSdkLibraryImplementation() *string
}
// Make sure that all the module types that are components of java_sdk_library/_import
@@ -888,6 +923,9 @@
// jars for the stubs. The latter should only be needed when generating JavaDoc as otherwise
// they are identical to the corresponding header jars.
SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths
+
+ // If the SDK library is a shared library.
+ IsSharedLibrary() bool
}
type SdkLibrary struct {
@@ -1014,6 +1052,8 @@
}
func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ module.generateCommonBuildActions(ctx)
+
// Only build an implementation library if required.
if module.requiresRuntimeImplementationLibrary() {
module.Library.GenerateAndroidBuildActions(ctx)
@@ -1108,12 +1148,16 @@
Name *string
Visibility []string
Instrument bool
+ Libs []string
ConfigurationName *string
}{
Name: proptools.StringPtr(module.implLibraryModuleName()),
Visibility: visibility,
// Set the instrument property to ensure it is instrumented when instrumentation is required.
Instrument: true,
+ // Set the impl_only libs. Note that the module's "Libs" get appended as well, via the
+ // addition of &module.properties below.
+ Libs: module.sdkLibraryProperties.Impl_only_libs,
// Make the created library behave as if it had the same name as this module.
ConfigurationName: moduleNamePtr,
@@ -1203,6 +1247,7 @@
Sdk_version *string
System_modules *string
Libs []string
+ Output_javadoc_comments *bool
Arg_files []string
Args *string
Java_version *string
@@ -1278,6 +1323,11 @@
}
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
@@ -1384,22 +1434,14 @@
return android.Paths{jarPath.Path()}
}
-// Get the apex names for module, nil if it is for platform.
-func getApexNamesForModule(module android.Module) []string {
- if apex, ok := module.(android.ApexModule); ok {
- return apex.InApexes()
- }
-
- return nil
-}
-
// Check to see if the other module is within the same set of named APEXes as this module.
//
// If either this or the other module are on the platform then this will return
// false.
-func withinSameApexesAs(module android.ApexModule, other android.Module) bool {
- names := module.InApexes()
- return len(names) > 0 && reflect.DeepEqual(names, getApexNamesForModule(other))
+func withinSameApexesAs(ctx android.BaseModuleContext, other android.Module) bool {
+ apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ otherApexInfo := ctx.OtherModuleProvider(other, android.ApexInfoProvider).(android.ApexInfo)
+ return len(otherApexInfo.InApexes) > 0 && reflect.DeepEqual(apexInfo.InApexes, otherApexInfo.InApexes)
}
func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion sdkSpec, headerJars bool) android.Paths {
@@ -1418,7 +1460,7 @@
// Only allow access to the implementation library in the following condition:
// * No sdk_version specified on the referencing module.
// * The referencing module is in the same apex as this.
- if sdkVersion.kind == sdkPrivate || withinSameApexesAs(module, ctx.Module()) {
+ if sdkVersion.kind == sdkPrivate || withinSameApexesAs(ctx, module) {
if headerJars {
return module.HeaderJars()
} else {
@@ -1538,6 +1580,9 @@
defer javaSdkLibrariesLock.Unlock()
*javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
}
+
+ // Add the impl_only_libs *after* we're done using the Libs prop in submodules.
+ module.properties.Libs = append(module.properties.Libs, module.sdkLibraryProperties.Impl_only_libs...)
}
func (module *SdkLibrary) InitSdkLibraryProperties() {
@@ -1878,7 +1923,8 @@
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 +1934,8 @@
}
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)
@@ -1932,7 +1980,7 @@
// For consistency with SdkLibrary make the implementation jar available to libraries that
// are within the same APEX.
implLibraryModule := module.implLibraryModule
- if implLibraryModule != nil && withinSameApexesAs(module, ctx.Module()) {
+ if implLibraryModule != nil && withinSameApexesAs(ctx, module) {
if headerJars {
return implLibraryModule.HeaderJars()
} else {
@@ -2028,6 +2076,8 @@
outputFilePath android.OutputPath
installDirPath android.InstallPath
+
+ hideApexVariantFromMake bool
}
type sdkLibraryXmlProperties struct {
@@ -2078,19 +2128,20 @@
// 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
}
// File path to the runtime implementation library
-func (module *sdkLibraryXml) implPath() string {
+func (module *sdkLibraryXml) implPath(ctx android.ModuleContext) string {
implName := proptools.String(module.properties.Lib_name)
- if apexName := module.ApexVariationName(); apexName != "" {
+ if apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo); !apexInfo.IsForPlatform() {
// TODO(b/146468504): ApexVariationName() is only a soong module name, not apex name.
// In most cases, this works fine. But when apex_name is set or override_apex is used
// this can be wrong.
- return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexName, implName)
+ return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexInfo.ApexVariationName, implName)
}
partition := "system"
if module.SocSpecific() {
@@ -2106,8 +2157,10 @@
}
func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ module.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
+
libName := proptools.String(module.properties.Lib_name)
- xmlContent := fmt.Sprintf(permissionsTemplate, libName, module.implPath())
+ xmlContent := fmt.Sprintf(permissionsTemplate, libName, module.implPath(ctx))
module.outputFilePath = android.PathForModuleOut(ctx, libName+".xml").OutputPath
rule := android.NewRuleBuilder()
@@ -2121,7 +2174,7 @@
}
func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries {
- if !module.IsForPlatform() {
+ if module.hideApexVariantFromMake {
return []android.AndroidMkEntries{android.AndroidMkEntries{
Disabled: true,
}}
@@ -2179,6 +2232,9 @@
// 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 +2274,7 @@
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) {
@@ -2243,10 +2300,11 @@
scopeSet.AddProperty("jars", jars)
// Merge the stubs source jar into the snapshot zip so that when it is unpacked
- // the source files are also unpacked.
+ // the source files are also unpacked. Use a glob so that if the directory is missing
+ // (because there are no stubs sources for this scope) it will not fail.
snapshotRelativeDir := filepath.Join(scopeDir, ctx.Name()+"_stub_sources")
ctx.SnapshotBuilder().UnzipToSnapshot(properties.StubsSrcJar, snapshotRelativeDir)
- scopeSet.AddProperty("stub_srcs", []string{snapshotRelativeDir})
+ scopeSet.AddProperty("stub_srcs", []string{snapshotRelativeDir + "/**/*.java"})
if properties.CurrentApiFile != nil {
currentApiSnapshotPath := filepath.Join(scopeDir, ctx.Name()+".txt")
@@ -2266,6 +2324,16 @@
}
}
+ 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/sdk_test.go b/java/sdk_test.go
index 776069d..dc90ea3 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -356,7 +356,7 @@
config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
config.TestProductVariables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
}
- ctx := testContext()
+ ctx := testContext(config)
run(t, ctx, config)
checkClasspath(t, ctx, true /* isJava8 */)
@@ -377,7 +377,7 @@
config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
config.TestProductVariables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
}
- ctx := testContext()
+ ctx := testContext(config)
run(t, ctx, config)
checkClasspath(t, ctx, false /* isJava8 */)
@@ -401,7 +401,7 @@
config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
config.TestProductVariables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
}
- ctx := testContext()
+ ctx := testContext(config)
run(t, ctx, config)
checkClasspath(t, ctx, true /* isJava8 */)
@@ -417,7 +417,7 @@
config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
config.TestProductVariables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
}
- ctx := testContext()
+ ctx := testContext(config)
run(t, ctx, config)
checkClasspath(t, ctx, false /* isJava8 */)
diff --git a/java/testing.go b/java/testing.go
index 322dc9e..ab13121 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -22,6 +22,7 @@
"android/soong/android"
"android/soong/cc"
+ "android/soong/dexpreopt"
"android/soong/python"
"github.com/google/blueprint"
@@ -55,6 +56,8 @@
"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 +91,7 @@
"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%'
@@ -150,6 +153,24 @@
`, extra)
}
+ // For class loader context and <uses-library> tests.
+ dexpreoptModules := []string{"android.test.runner"}
+ dexpreoptModules = append(dexpreoptModules, dexpreopt.CompatUsesLibs...)
+ dexpreoptModules = append(dexpreoptModules, dexpreopt.OptionalCompatUsesLibs...)
+
+ for _, extra := range dexpreoptModules {
+ bp += fmt.Sprintf(`
+ java_library {
+ name: "%s",
+ srcs: ["a.java"],
+ sdk_version: "none",
+ system_modules: "stable-core-platform-api-stubs-system-modules",
+ compile_dex: true,
+ installable: true,
+ }
+ `, extra)
+ }
+
bp += `
java_library {
name: "framework",
@@ -164,48 +185,7 @@
android_app {
name: "framework-res",
sdk_version: "core_platform",
- }
-
- java_library {
- name: "android.hidl.base-V1.0-java",
- srcs: ["a.java"],
- sdk_version: "none",
- system_modules: "stable-core-platform-api-stubs-system-modules",
- installable: true,
- }
-
- java_library {
- name: "android.hidl.manager-V1.0-java",
- srcs: ["a.java"],
- sdk_version: "none",
- system_modules: "stable-core-platform-api-stubs-system-modules",
- installable: true,
- }
-
- java_library {
- name: "org.apache.http.legacy",
- srcs: ["a.java"],
- sdk_version: "none",
- system_modules: "stable-core-platform-api-stubs-system-modules",
- installable: true,
- }
-
- java_library {
- name: "android.test.base",
- srcs: ["a.java"],
- sdk_version: "none",
- system_modules: "stable-core-platform-api-stubs-system-modules",
- installable: true,
- }
-
- java_library {
- name: "android.test.mock",
- srcs: ["a.java"],
- sdk_version: "none",
- system_modules: "stable-core-platform-api-stubs-system-modules",
- installable: true,
- }
- `
+ }`
systemModules := []string{
"core-current-stubs-system-modules",
diff --git a/linkerconfig/Android.bp b/linkerconfig/Android.bp
new file mode 100644
index 0000000..8807a2e
--- /dev/null
+++ b/linkerconfig/Android.bp
@@ -0,0 +1,17 @@
+bootstrap_go_package {
+ name: "soong-linkerconfig",
+ pkgPath: "android/soong/linkerconfig",
+ deps: [
+ "blueprint",
+ "soong",
+ "soong-android",
+ "soong-etc",
+ ],
+ srcs: [
+ "linkerconfig.go",
+ ],
+ testSrcs: [
+ "linkerconfig_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/linkerconfig/linkerconfig.go b/linkerconfig/linkerconfig.go
new file mode 100644
index 0000000..1c44c74
--- /dev/null
+++ b/linkerconfig/linkerconfig.go
@@ -0,0 +1,108 @@
+// Copyright (C) 2020 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.
+
+package linkerconfig
+
+import (
+ "android/soong/android"
+ "android/soong/etc"
+
+ "github.com/google/blueprint/proptools"
+)
+
+var (
+ pctx = android.NewPackageContext("android/soong/linkerconfig")
+)
+
+func init() {
+ pctx.HostBinToolVariable("conv_linker_config", "conv_linker_config")
+ android.RegisterModuleType("linker_config", linkerConfigFactory)
+}
+
+type linkerConfigProperties struct {
+ // source linker configuration property file
+ Src *string `android:"path"`
+
+ // If set to true, allow module to be installed to one of the partitions.
+ // Default value is true.
+ // Installable should be marked as false for APEX configuration to avoid
+ // conflicts of configuration on /system/etc directory.
+ Installable *bool
+}
+
+type linkerConfig struct {
+ android.ModuleBase
+ properties linkerConfigProperties
+
+ outputFilePath android.OutputPath
+ installDirPath android.InstallPath
+}
+
+// Implement PrebuiltEtcModule interface to fit in APEX prebuilt list.
+var _ etc.PrebuiltEtcModule = (*linkerConfig)(nil)
+
+func (l *linkerConfig) BaseDir() string {
+ return "etc"
+}
+
+func (l *linkerConfig) SubDir() string {
+ return ""
+}
+
+func (l *linkerConfig) OutputFile() android.OutputPath {
+ return l.outputFilePath
+}
+
+func (l *linkerConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ inputFile := android.PathForModuleSrc(ctx, android.String(l.properties.Src))
+ l.outputFilePath = android.PathForModuleOut(ctx, "linker.config.pb").OutputPath
+ l.installDirPath = android.PathForModuleInstall(ctx, "etc")
+ linkerConfigRule := android.NewRuleBuilder()
+ linkerConfigRule.Command().
+ BuiltTool(ctx, "conv_linker_config").
+ Flag("proto").
+ FlagWithInput("-s ", inputFile).
+ FlagWithOutput("-o ", l.outputFilePath)
+ linkerConfigRule.Build(pctx, ctx, "conv_linker_config",
+ "Generate linker config protobuf "+l.outputFilePath.String())
+
+ if proptools.BoolDefault(l.properties.Installable, true) {
+ ctx.InstallFile(l.installDirPath, l.outputFilePath.Base(), l.outputFilePath)
+ }
+}
+
+// linker_config generates protobuf file from json file. This protobuf file will be used from
+// linkerconfig while generating ld.config.txt. Format of this file can be found from
+// https://android.googlesource.com/platform/system/linkerconfig/+/master/README.md
+func linkerConfigFactory() android.Module {
+ m := &linkerConfig{}
+ m.AddProperties(&m.properties)
+ android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibFirst)
+ return m
+}
+
+func (l *linkerConfig) AndroidMkEntries() []android.AndroidMkEntries {
+ installable := proptools.BoolDefault(l.properties.Installable, true)
+ return []android.AndroidMkEntries{android.AndroidMkEntries{
+ Class: "ETC",
+ OutputFile: android.OptionalPathForPath(l.outputFilePath),
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(entries *android.AndroidMkEntries) {
+ entries.SetString("LOCAL_MODULE_PATH", l.installDirPath.ToMakePath().String())
+ entries.SetString("LOCAL_INSTALLED_MODULE_STEM", l.outputFilePath.Base())
+ entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !installable)
+ },
+ },
+ }}
+}
diff --git a/linkerconfig/linkerconfig_test.go b/linkerconfig/linkerconfig_test.go
new file mode 100644
index 0000000..01f4657
--- /dev/null
+++ b/linkerconfig/linkerconfig_test.go
@@ -0,0 +1,127 @@
+// Copyright (C) 2020 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.
+
+package linkerconfig
+
+import (
+ "android/soong/android"
+ "io/ioutil"
+ "os"
+ "reflect"
+ "testing"
+)
+
+var buildDir string
+
+func setUp() {
+ var err error
+ buildDir, err = ioutil.TempDir("", "soong_etc_test")
+ if err != nil {
+ panic(err)
+ }
+}
+
+func tearDown() {
+ os.RemoveAll(buildDir)
+}
+
+func TestMain(m *testing.M) {
+ run := func() int {
+ setUp()
+ defer tearDown()
+
+ return m.Run()
+ }
+
+ os.Exit(run())
+}
+
+func testContext(t *testing.T, bp string) (*android.TestContext, android.Config) {
+ t.Helper()
+
+ fs := map[string][]byte{
+ "linker.config.json": nil,
+ }
+
+ config := android.TestArchConfig(buildDir, nil, bp, fs)
+
+ ctx := android.NewTestArchContext(config)
+ ctx.RegisterModuleType("linker_config", linkerConfigFactory)
+ ctx.Register()
+
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
+
+ return ctx, config
+}
+
+func TestBaseLinkerConfig(t *testing.T) {
+ ctx, config := testContext(t, `
+ linker_config {
+ name: "linker-config-base",
+ src: "linker.config.json",
+ }
+ `)
+
+ expected := map[string][]string{
+ "LOCAL_MODULE": {"linker-config-base"},
+ "LOCAL_MODULE_CLASS": {"ETC"},
+ "LOCAL_INSTALLED_MODULE_STEM": {"linker.config.pb"},
+ }
+
+ p := ctx.ModuleForTests("linker-config-base", "android_arm64_armv8-a").Module().(*linkerConfig)
+
+ if p.outputFilePath.Base() != "linker.config.pb" {
+ t.Errorf("expected linker.config.pb, got %q", p.outputFilePath.Base())
+ }
+
+ entries := android.AndroidMkEntriesForTest(t, config, "", p)[0]
+ for k, expectedValue := range expected {
+ if value, ok := entries.EntryMap[k]; ok {
+ if !reflect.DeepEqual(value, expectedValue) {
+ t.Errorf("Value of %s is '%s', but expected as '%s'", k, value, expectedValue)
+ }
+ } else {
+ t.Errorf("%s is not defined", k)
+ }
+ }
+
+ if value, ok := entries.EntryMap["LOCAL_UNINSTALLABLE_MODULE"]; ok {
+ t.Errorf("Value of LOCAL_UNINSTALLABLE_MODULE is %s, but expected as empty", value)
+ }
+}
+
+func TestUninstallableLinkerConfig(t *testing.T) {
+ ctx, config := testContext(t, `
+ linker_config {
+ name: "linker-config-base",
+ src: "linker.config.json",
+ installable: false,
+ }
+ `)
+
+ expected := []string{"true"}
+
+ p := ctx.ModuleForTests("linker-config-base", "android_arm64_armv8-a").Module().(*linkerConfig)
+ entries := android.AndroidMkEntriesForTest(t, config, "", p)[0]
+ if value, ok := entries.EntryMap["LOCAL_UNINSTALLABLE_MODULE"]; ok {
+ if !reflect.DeepEqual(value, expected) {
+ t.Errorf("LOCAL_UNINSTALLABLE_MODULE is expected to be true but %s", value)
+ }
+ } else {
+ t.Errorf("LOCAL_UNINSTALLABLE_MODULE is not defined")
+ }
+}
diff --git a/linkerconfig/proto/Android.bp b/linkerconfig/proto/Android.bp
new file mode 100644
index 0000000..c04887e
--- /dev/null
+++ b/linkerconfig/proto/Android.bp
@@ -0,0 +1,28 @@
+cc_library_static {
+ name: "lib_linker_config_proto_lite",
+ host_supported: true,
+ recovery_available: true,
+ proto: {
+ export_proto_headers: true,
+ type: "lite",
+ },
+ srcs: ["linker_config.proto"],
+}
+
+python_library_host {
+ name: "linker_config_proto",
+ version: {
+ py2: {
+ enabled: false,
+ },
+ py3: {
+ enabled: true,
+ },
+ },
+ srcs: [
+ "linker_config.proto",
+ ],
+ proto: {
+ canonical_path_from_root: false,
+ },
+}
diff --git a/linkerconfig/proto/OWNERS b/linkerconfig/proto/OWNERS
new file mode 100644
index 0000000..31f0460
--- /dev/null
+++ b/linkerconfig/proto/OWNERS
@@ -0,0 +1,3 @@
+kiyoungkim@google.com
+jiyong@google.com
+jooyung@google.com
diff --git a/linkerconfig/proto/linker_config.proto b/linkerconfig/proto/linker_config.proto
new file mode 100644
index 0000000..fec66c8
--- /dev/null
+++ b/linkerconfig/proto/linker_config.proto
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+// This format file defines configuration file for linkerconfig. Details on this
+// format can be found from
+// https://android.googlesource.com/platform/system/linkerconfig/+/master/README.md
+
+syntax = "proto3";
+
+package android.linkerconfig.proto;
+
+message LinkerConfig {
+ // Extra permitted paths
+ repeated string permittedPaths = 1;
+
+ // Force APEX namespace visible
+ bool visible = 2;
+
+ // Providing libs from the module
+ repeated string provideLibs = 3;
+
+ // Required libs from the module
+ repeated string requireLibs = 4;
+}
diff --git a/python/androidmk.go b/python/androidmk.go
index 247b80d..8ad5889 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 @@
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 5a74926..1d2400e 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -79,7 +79,7 @@
}
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 65c1352..0c8d613 100644
--- a/python/library.go
+++ b/python/library.go
@@ -26,7 +26,7 @@
}
func PythonLibraryHostFactory() android.Module {
- module := newModule(android.HostSupportedNoCross, android.MultilibFirst)
+ module := newModule(android.HostSupported, android.MultilibFirst)
return module.Init()
}
diff --git a/python/python.go b/python/python.go
index 479c729..e4c8e94 100644
--- a/python/python.go
+++ b/python/python.go
@@ -101,6 +101,13 @@
// this property name is hidden from users' perspectives, and soong will populate it during
// runtime.
Actual_version string `blueprint:"mutated"`
+
+ // true, if the module is required to be built with actual_version.
+ Enabled *bool `blueprint:"mutated"`
+
+ // true, if the binary is required to be built with embedded launcher.
+ // TODO(nanzhang): Remove this flag when embedded Python3 is supported later.
+ Embedded_launcher *bool `blueprint:"mutated"`
}
type pathMapping struct {
@@ -228,15 +235,18 @@
return func(mctx android.BottomUpMutatorContext) {
if base, ok := mctx.Module().(*Module); ok {
versionNames := []string{}
+ versionProps := []VersionProperties{}
// PY3 is first so that we alias the PY3 variant rather than PY2 if both
// are available
if !(base.properties.Version.Py3.Enabled != nil &&
*(base.properties.Version.Py3.Enabled) == false) {
versionNames = append(versionNames, pyVersion3)
+ versionProps = append(versionProps, base.properties.Version.Py3)
}
if base.properties.Version.Py2.Enabled != nil &&
*(base.properties.Version.Py2.Enabled) == true {
versionNames = append(versionNames, pyVersion2)
+ versionProps = append(versionProps, base.properties.Version.Py2)
}
modules := mctx.CreateVariations(versionNames...)
if len(versionNames) > 0 {
@@ -245,6 +255,11 @@
for i, v := range versionNames {
// set the actual version for Python module.
modules[i].(*Module).properties.Actual_version = v
+ // append versioned properties for the Python module
+ err := proptools.AppendMatchingProperties([]interface{}{&modules[i].(*Module).properties}, &versionProps[i], nil)
+ if err != nil {
+ panic(err)
+ }
}
}
}
@@ -270,15 +285,8 @@
}
}
-func (p *Module) isEmbeddedLauncherEnabled(actual_version string) bool {
- switch actual_version {
- case pyVersion2:
- return Bool(p.properties.Version.Py2.Embedded_launcher)
- case pyVersion3:
- return Bool(p.properties.Version.Py3.Embedded_launcher)
- }
-
- return false
+func (p *Module) isEmbeddedLauncherEnabled() bool {
+ return Bool(p.properties.Embedded_launcher)
}
func hasSrcExt(srcs []string, ext string) bool {
@@ -292,18 +300,7 @@
}
func (p *Module) hasSrcExt(ctx android.BottomUpMutatorContext, ext string) bool {
- if hasSrcExt(p.properties.Srcs, protoExt) {
- return true
- }
- switch p.properties.Actual_version {
- case pyVersion2:
- return hasSrcExt(p.properties.Version.Py2.Srcs, protoExt)
- case pyVersion3:
- return hasSrcExt(p.properties.Version.Py3.Srcs, protoExt)
- default:
- panic(fmt.Errorf("unknown Python Actual_version: %q for module: %q.",
- p.properties.Actual_version, ctx.ModuleName()))
- }
+ return hasSrcExt(p.properties.Srcs, ext)
}
func (p *Module) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -312,13 +309,12 @@
if p.hasSrcExt(ctx, protoExt) && p.Name() != "libprotobuf-python" {
ctx.AddVariationDependencies(nil, pythonLibTag, "libprotobuf-python")
}
+ ctx.AddVariationDependencies(nil, pythonLibTag, android.LastUniqueStrings(p.properties.Libs)...)
+
switch p.properties.Actual_version {
case pyVersion2:
- ctx.AddVariationDependencies(nil, pythonLibTag,
- uniqueLibs(ctx, p.properties.Libs, "version.py2.libs",
- p.properties.Version.Py2.Libs)...)
- if p.bootstrapper != nil && p.isEmbeddedLauncherEnabled(pyVersion2) {
+ if p.bootstrapper != nil && p.isEmbeddedLauncherEnabled() {
ctx.AddVariationDependencies(nil, pythonLibTag, "py2-stdlib")
launcherModule := "py2-launcher"
@@ -340,11 +336,8 @@
}
case pyVersion3:
- ctx.AddVariationDependencies(nil, pythonLibTag,
- uniqueLibs(ctx, p.properties.Libs, "version.py3.libs",
- p.properties.Version.Py3.Libs)...)
- if p.bootstrapper != nil && p.isEmbeddedLauncherEnabled(pyVersion3) {
+ if p.bootstrapper != nil && p.isEmbeddedLauncherEnabled() {
ctx.AddVariationDependencies(nil, pythonLibTag, "py3-stdlib")
launcherModule := "py3-launcher"
@@ -375,34 +368,6 @@
}
}
-// check "libs" duplicates from current module dependencies.
-func uniqueLibs(ctx android.BottomUpMutatorContext,
- commonLibs []string, versionProp string, versionLibs []string) []string {
- set := make(map[string]string)
- ret := []string{}
-
- // deps from "libs" property.
- for _, l := range commonLibs {
- if _, found := set[l]; found {
- ctx.PropertyErrorf("libs", "%q has duplicates within libs.", l)
- } else {
- set[l] = "libs"
- ret = append(ret, l)
- }
- }
- // deps from "version.pyX.libs" property.
- for _, l := range versionLibs {
- if _, found := set[l]; found {
- ctx.PropertyErrorf(versionProp, "%q has duplicates within %q.", set[l])
- } else {
- set[l] = versionProp
- ret = append(ret, l)
- }
- }
-
- return ret
-}
-
func (p *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
p.GeneratePythonBuildActions(ctx)
@@ -410,11 +375,7 @@
if p.bootstrapper != nil {
p.walkTransitiveDeps(ctx)
embeddedLauncher := false
- if p.properties.Actual_version == pyVersion2 {
- embeddedLauncher = p.isEmbeddedLauncherEnabled(pyVersion2)
- } else {
- embeddedLauncher = p.isEmbeddedLauncherEnabled(pyVersion3)
- }
+ embeddedLauncher = p.isEmbeddedLauncherEnabled()
p.installSource = p.bootstrapper.bootstrap(ctx, p.properties.Actual_version,
embeddedLauncher, p.srcsPathMappings, p.srcsZip, p.depsSrcsZips)
}
@@ -439,17 +400,6 @@
// expand python files from "srcs" property.
srcs := p.properties.Srcs
exclude_srcs := p.properties.Exclude_srcs
- switch p.properties.Actual_version {
- case pyVersion2:
- srcs = append(srcs, p.properties.Version.Py2.Srcs...)
- exclude_srcs = append(exclude_srcs, p.properties.Version.Py2.Exclude_srcs...)
- case pyVersion3:
- srcs = append(srcs, p.properties.Version.Py3.Srcs...)
- exclude_srcs = append(exclude_srcs, p.properties.Version.Py3.Exclude_srcs...)
- default:
- panic(fmt.Errorf("unknown Python Actual_version: %q for module: %q.",
- p.properties.Actual_version, ctx.ModuleName()))
- }
expandedSrcs := android.PathsForModuleSrcExcludes(ctx, srcs, exclude_srcs)
requiresSrcs := true
if p.bootstrapper != nil && !p.bootstrapper.autorun() {
diff --git a/python/python_test.go b/python/python_test.go
index 23db24e..64bc4f6 100644
--- a/python/python_test.go
+++ b/python/python_test.go
@@ -329,13 +329,13 @@
for _, d := range data {
t.Run(d.desc, func(t *testing.T) {
config := android.TestConfig(buildDir, nil, "", d.mockFiles)
- ctx := android.NewTestContext()
+ ctx := android.NewTestContext(config)
ctx.PreDepsMutators(RegisterPythonPreDepsMutators)
ctx.RegisterModuleType("python_library_host", PythonLibraryHostFactory)
ctx.RegisterModuleType("python_binary_host", PythonBinaryHostFactory)
ctx.RegisterModuleType("python_defaults", defaultsFactory)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
- ctx.Register(config)
+ ctx.Register()
_, testErrs := ctx.ParseBlueprintsFiles(bpFile)
android.FailIfErrored(t, testErrs)
_, actErrs := ctx.PrepareBuildActions(config)
@@ -395,10 +395,11 @@
if !reflect.DeepEqual(actualPyRunfiles, expectedPyRunfiles) {
testErrs = append(testErrs, errors.New(fmt.Sprintf(
- `binary "%s" variant "%s" has unexpected pyRunfiles: %q!`,
+ `binary "%s" variant "%s" has unexpected pyRunfiles: %q! (expected: %q)`,
base.Name(),
base.properties.Actual_version,
- actualPyRunfiles)))
+ actualPyRunfiles,
+ expectedPyRunfiles)))
}
if base.srcsZip.String() != strings.Replace(expectedSrcsZip, "@prefix@", buildDir, 1) {
diff --git a/python/test.go b/python/test.go
index a669c73..434e71a 100644
--- a/python/test.go
+++ b/python/test.go
@@ -34,6 +34,10 @@
// 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 @@
testProperties TestProperties
testConfig android.Path
+
+ data []android.DataPath
}
func (test *testDecorator) bootstrapperProps() []interface{} {
@@ -59,6 +65,12 @@
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 edae0e6..29e4bd7 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -156,7 +156,7 @@
}
func (sourceProvider *BaseSourceProvider) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
- outFile := sourceProvider.OutputFile
+ outFile := sourceProvider.OutputFiles[0]
ret.Class = "ETC"
ret.OutputFile = android.OptionalPathForPath(outFile)
ret.SubName += sourceProvider.subName
@@ -178,6 +178,10 @@
}
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 1d02453..af39d38 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -24,6 +24,16 @@
}
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 @@
"-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 @@
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 @@
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) 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 cfef57a..b44a5bc 100644
--- a/rust/binary_test.go
+++ b/rust/binary_test.go
@@ -30,6 +30,13 @@
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 @@
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 @@
}
}
+// 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 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 cafdb8b..7cc0fc8 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -21,16 +21,18 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/cc"
+ cc_config "android/soong/cc/config"
)
var (
defaultBindgenFlags = []string{""}
// bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures.
- bindgenClangVersion = "clang-r383902c"
+ bindgenClangVersion = "clang-r399163b"
//TODO(b/160803703) Use a prebuilt bindgen instead of the built bindgen.
- _ = pctx.SourcePathVariable("bindgenCmd", "out/host/${config.HostPrebuiltTag}/bin/bindgen")
+ _ = pctx.HostBinToolVariable("bindgenCmd", "bindgen")
_ = pctx.SourcePathVariable("bindgenClang",
"${cc_config.ClangBase}/${config.HostPrebuiltTag}/"+bindgenClangVersion+"/bin/clang")
_ = pctx.SourcePathVariable("bindgenLibClang",
@@ -56,38 +58,67 @@
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 {
@@ -119,9 +150,21 @@
esc := proptools.NinjaAndShellEscapeList
+ // Filter out invalid cflags
+ for _, flag := range b.ClangProperties.Cflags {
+ if flag == "-x c++" || flag == "-xc++" {
+ ctx.PropertyErrorf("cflags",
+ "-x c++ should not be specified in cflags; setting cpp_std specifies this is a C++ header, or change the file extension to '.hpp' or '.hh'")
+ }
+ if strings.HasPrefix(flag, "-std=") {
+ ctx.PropertyErrorf("cflags",
+ "-std should not be specified in cflags; instead use c_std or cpp_std")
+ }
+ }
+
// 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 +177,19 @@
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
@@ -158,18 +214,20 @@
},
})
- b.BaseSourceProvider.OutputFile = outputFile
+ b.BaseSourceProvider.OutputFiles = android.Paths{outputFile}
return outputFile
}
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 +242,7 @@
bindgen := &bindgenDecorator{
BaseSourceProvider: NewSourceProvider(),
Properties: BindgenProperties{},
+ ClangProperties: cc.RustBindgenClangProperties{},
}
module := NewSourceProviderModule(hod, bindgen, false)
@@ -194,10 +253,10 @@
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 191da9b..c7ce42b 100644
--- a/rust/bindgen_test.go
+++ b/rust/bindgen_test.go
@@ -23,6 +23,7 @@
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 @@
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 @@
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 @@
}
`)
- 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,73 @@
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")
+ }
+}
+
+func TestBindgenDisallowedFlags(t *testing.T) {
+ // Make sure passing '-x c++' to cflags generates an error
+ testRustError(t, "cflags: -x c\\+\\+ should not be specified in cflags.*", `
+ rust_bindgen {
+ name: "libbad_flag",
+ wrapper_src: "src/any.h",
+ crate_name: "bindgen",
+ stem: "libbindgen",
+ source_stem: "bindings",
+ cflags: ["-x c++"]
+ }
+ `)
+
+ // Make sure passing '-std=' to cflags generates an error
+ testRustError(t, "cflags: -std should not be specified in cflags.*", `
+ rust_bindgen {
+ name: "libbad_flag",
+ wrapper_src: "src/any.h",
+ crate_name: "bindgen",
+ stem: "libbindgen",
+ source_stem: "bindings",
+ cflags: ["-std=foo"]
+ }
+ `)
+}
diff --git a/rust/builder.go b/rust/builder.go
index 654b1e6..6079e30 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -15,6 +15,7 @@
package rust
import (
+ "path/filepath"
"strings"
"github.com/google/blueprint"
@@ -22,6 +23,7 @@
"android/soong/android"
"android/soong/cc"
+ "android/soong/rust/config"
)
var (
@@ -138,6 +140,13 @@
crate_name := ctx.RustModule().CrateName()
targetTriple := ctx.toolchain().RustTriple()
+ // libstd requires a specific environment variable to be set. This is
+ // not officially documented and may be removed in the future. See
+ // https://github.com/rust-lang/rust/blob/master/library/std/src/env.rs#L866.
+ if crate_name == "std" {
+ envVars = append(envVars, "STD_ENV_ARCH="+config.StdEnvArch[ctx.RustModule().Arch().ArchType])
+ }
+
inputs = append(inputs, main)
// Collect rustc flags
@@ -191,7 +200,9 @@
profileEmitArg := strings.TrimPrefix(cc.PwdPrefix(), "PWD=") + "/"
if outputFile.Ext() != "" {
- gcnoFile = android.PathForModuleOut(ctx, pathtools.ReplaceExtension(outputFile.Base(), "gcno"))
+ // rustc seems to split the output filename at the first '.' when determining the gcno filename
+ // so we need to do the same here.
+ gcnoFile = android.PathForModuleOut(ctx, strings.Split(outputFile.Base(), ".")[0]+".gcno")
rustcFlags = append(rustcFlags, "-Z profile-emit="+profileEmitArg+android.PathForModuleOut(
ctx, pathtools.ReplaceExtension(outputFile.Base(), "gcda")).String())
} else {
@@ -227,7 +238,18 @@
},
})
implicits = append(implicits, outputs.Paths()...)
- envVars = append(envVars, "OUT_DIR=$$PWD/"+moduleGenDir.String())
+
+ // We must calculate an absolute path for OUT_DIR since Rust's include! macro (which normally consumes this)
+ // assumes that paths are relative to the source file.
+ var outDirPrefix string
+ if !filepath.IsAbs(moduleGenDir.String()) {
+ // If OUT_DIR is not absolute, we use $$PWD to generate an absolute path (os.Getwd() returns '/')
+ outDirPrefix = "$$PWD/"
+ } else {
+ // If OUT_DIR is absolute, then moduleGenDir will be an absolute path, so we don't need to set this to anything.
+ outDirPrefix = ""
+ }
+ envVars = append(envVars, "OUT_DIR="+filepath.Join(outDirPrefix, moduleGenDir.String()))
}
if flags.Clippy {
diff --git a/rust/clippy_test.go b/rust/clippy_test.go
index 7815aab..132b7b8 100644
--- a/rust/clippy_test.go
+++ b/rust/clippy_test.go
@@ -65,8 +65,8 @@
t.Run("path="+tc.modulePath, func(t *testing.T) {
config := android.TestArchConfig(buildDir, nil, bp, fs)
- ctx := CreateTestContext()
- ctx.Register(config)
+ ctx := CreateTestContext(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{tc.modulePath + "Android.bp"})
android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
diff --git a/rust/compiler.go b/rust/compiler.go
index 664578d..8d2f09c 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -24,6 +24,14 @@
"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 @@
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 @@
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 56a8ef8..a6dba9e 100644
--- a/rust/compiler_test.go
+++ b/rust/compiler_test.go
@@ -152,8 +152,8 @@
t.Run("path="+tc.modulePath, func(t *testing.T) {
config := android.TestArchConfig(buildDir, nil, bp, fs)
- ctx := CreateTestContext()
- ctx.Register(config)
+ ctx := CreateTestContext(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{tc.modulePath + "Android.bp"})
android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
@@ -191,7 +191,7 @@
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/OWNERS b/rust/config/OWNERS
new file mode 100644
index 0000000..dfff873
--- /dev/null
+++ b/rust/config/OWNERS
@@ -0,0 +1,2 @@
+per-file global.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
+
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
index 62d469e..3ad32fa 100644
--- a/rust/config/allowed_list.go
+++ b/rust/config/allowed_list.go
@@ -1,14 +1,22 @@
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/1458238
+ // for an example.
+ // TODO(b/160223496): enable rustfmt globally.
RustAllowedPaths = []string{
+ "external/adhd",
+ "external/crosvm",
"external/minijail",
"external/rust",
- "external/crosvm",
- "external/adhd",
+ "external/vm_tools/p9",
"frameworks/native/libs/binder/rust",
+ "packages/modules/Virtualization",
"prebuilts/rust",
+ "system/bt",
"system/extras/profcollectd",
+ "system/hardware/interfaces/keystore2",
"system/security",
"system/tools/aidl",
}
diff --git a/rust/config/arm64_device.go b/rust/config/arm64_device.go
index 7d13c42..21b22a4 100644
--- a/rust/config/arm64_device.go
+++ b/rust/config/arm64_device.go
@@ -28,6 +28,7 @@
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 ac4f1c6..adfe917 100644
--- a/rust/config/arm_device.go
+++ b/rust/config/arm_device.go
@@ -52,7 +52,7 @@
}
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 6a5251b..6e268a0 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
var pctx = android.NewPackageContext("android/soong/rust/config")
var (
- RustDefaultVersion = "1.45.2"
+ RustDefaultVersion = "1.47.0"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2018"
Stdlibs = []string{
@@ -32,6 +32,15 @@
"libtest",
}
+ // Mapping between Soong internal arch types and std::env constants.
+ // Required as Rust uses aarch64 when Soong uses arm64.
+ StdEnvArch = map[android.ArchType]string{
+ android.Arm: "arm",
+ android.Arm64: "aarch64",
+ android.X86: "x86",
+ android.X86_64: "x86_64",
+ }
+
GlobalRustFlags = []string{
"--remap-path-prefix $$(pwd)=",
"-C codegen-units=1",
diff --git a/rust/coverage_test.go b/rust/coverage_test.go
index 73673d0..e7f873e 100644
--- a/rust/coverage_test.go
+++ b/rust/coverage_test.go
@@ -154,13 +154,13 @@
}
// 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") ||
- !android.SuffixInList(libfooZipInputs, "android_arm64_armv8-a_dylib_cov/libfoo.dylib.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.gcno") {
t.Fatalf("missing expected coverage files for rust 'fizz' binary: %#v", libfooZipInputs)
}
if !android.SuffixInList(buzzZipInputs, "android_arm64_armv8-a_cov/obj/foo.gcno") ||
diff --git a/rust/library.go b/rust/library.go
index a442933..ae33f0f 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -15,10 +15,17 @@
package rust
import (
+ "fmt"
"regexp"
"strings"
"android/soong/android"
+ "android/soong/cc"
+)
+
+var (
+ DylibStdlibSuffix = ".dylib-std"
+ RlibStdlibSuffix = ".rlib-std"
)
func init() {
@@ -49,6 +56,9 @@
// 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 +79,15 @@
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 +106,8 @@
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 +120,11 @@
setDylib()
setShared()
setStatic()
+ setSource()
+
+ // Set libstd linkage
+ setRlibStd()
+ setDylibStd()
// Build a specific library variant
BuildOnlyFFI()
@@ -121,6 +143,10 @@
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 +159,18 @@
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 +201,14 @@
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 +223,17 @@
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 +397,7 @@
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"
}
@@ -435,11 +485,35 @@
library.coverageOutputZipFile = TransformCoverageFilesToZip(ctx, coverageFiles, library.getStem(ctx))
if library.rlib() || library.dylib() {
- library.exportLinkDirs(deps.linkDirs...)
- library.exportDepFlags(deps.depFlags...)
- library.exportLinkObjects(deps.linkObjects...)
+ library.flagExporter.exportLinkDirs(deps.linkDirs...)
+ library.flagExporter.exportDepFlags(deps.depFlags...)
+ library.flagExporter.exportLinkObjects(deps.linkObjects...)
}
+ if library.static() || library.shared() {
+ ctx.SetProvider(cc.FlagExporterInfoProvider, cc.FlagExporterInfo{
+ IncludeDirs: library.includeDirs,
+ })
+ }
+
+ if library.shared() {
+ ctx.SetProvider(cc.SharedLibraryInfoProvider, cc.SharedLibraryInfo{
+ SharedLibrary: outputFile,
+ UnstrippedSharedLibrary: outputFile,
+ })
+ }
+
+ if library.static() {
+ depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(outputFile).Build()
+ ctx.SetProvider(cc.StaticLibraryInfoProvider, cc.StaticLibraryInfo{
+ StaticLibrary: outputFile,
+
+ TransitiveStaticLibrariesForOrdering: depSet,
+ })
+ }
+
+ library.flagExporter.setProvider(ctx)
+
return outputFile
}
@@ -450,6 +524,13 @@
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 +559,85 @@
}
}
+// 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 f1bc050..fec3992 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -37,7 +37,7 @@
}`)
// 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 @@
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 @@
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 @@
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/prebuilt.go b/rust/prebuilt.go
index f9c8934..94fe1e5 100644
--- a/rust/prebuilt.go
+++ b/rust/prebuilt.go
@@ -93,7 +93,8 @@
}
func (prebuilt *prebuiltLibraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
- prebuilt.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...)
+ prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...)
+ prebuilt.flagExporter.setProvider(ctx)
srcPath, paths := srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs())
if len(paths) > 0 {
diff --git a/rust/project_json.go b/rust/project_json.go
index 8310479..5697408 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -30,16 +30,6 @@
//
// $ 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 @@
// 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 @@
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().AndroidFirstDeviceTarget.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 @@
})
}
-// 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 @@
}
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 8521940..69288fc 100644
--- a/rust/project_json_test.go
+++ b/rust/project_json_test.go
@@ -18,25 +18,19 @@
"encoding/json"
"io/ioutil"
"path/filepath"
+ "strings"
"testing"
"android/soong/android"
- "android/soong/cc"
)
// testProjectJson run the generation of rust-project.json. It returns the raw
// content of the generated file.
-func testProjectJson(t *testing.T, bp string, fs map[string][]byte) []byte {
- cc.GatherRequiredFilesForTest(fs)
-
- env := map[string]string{"SOONG_GEN_RUST_PROJECT": "1"}
- config := android.TestArchConfig(buildDir, env, bp, fs)
- ctx := CreateTestContext()
- ctx.Register(config)
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
+func testProjectJson(t *testing.T, bp string) []byte {
+ tctx := newTestRustCtx(t, bp)
+ tctx.env = map[string]string{"SOONG_GEN_RUST_PROJECT": "1"}
+ tctx.generateConfig()
+ tctx.parse(t)
// The JSON file is generated via WriteFileToOutputDir. Therefore, it
// won't appear in the Output of the TestingSingleton. Manually verify
@@ -86,12 +80,8 @@
crate_name: "b",
rlibs: ["liba"],
}
- ` + GatherRequiredDepsForTest()
- fs := map[string][]byte{
- "a/src/lib.rs": nil,
- "b/src/lib.rs": nil,
- }
- jsonContent := testProjectJson(t, bp, fs)
+ `
+ jsonContent := testProjectJson(t, bp)
validateJsonCrates(t, jsonContent)
}
@@ -100,22 +90,48 @@
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",
}
- ` + GatherRequiredDepsForTest()
- fs := map[string][]byte{
- "src/lib.rs": nil,
+ rust_library_host {
+ name: "libb",
+ srcs: ["src/lib.rs"],
+ rustlibs: ["libbindings2"],
+ crate_name: "b"
}
- jsonContent := testProjectJson(t, bp, fs)
- validateJsonCrates(t, jsonContent)
+ rust_bindgen_host {
+ name: "libbindings2",
+ crate_name: "bindings2",
+ source_stem: "bindings2",
+ wrapper_src: "src/any.h",
+ }
+ `
+ jsonContent := testProjectJson(t, bp)
+ 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) {
@@ -136,13 +152,8 @@
crate_name: "b",
rustlibs: ["liba1", "liba2"],
}
- ` + GatherRequiredDepsForTest()
- fs := map[string][]byte{
- "a1/src/lib.rs": nil,
- "a2/src/lib.rs": nil,
- "b/src/lib.rs": nil,
- }
- jsonContent := testProjectJson(t, bp, fs)
+ `
+ jsonContent := testProjectJson(t, bp)
crates := validateJsonCrates(t, jsonContent)
for _, crate := range crates {
c := crate.(map[string]interface{})
diff --git a/rust/protobuf.go b/rust/protobuf.go
index 897300f..76fed30 100644
--- a/rust/protobuf.go
+++ b/rust/protobuf.go
@@ -15,6 +15,9 @@
package rust
import (
+ "fmt"
+ "strings"
+
"android/soong/android"
)
@@ -22,9 +25,22 @@
defaultProtobufFlags = []string{""}
)
+const (
+ grpcSuffix = "_grpc"
+)
+
+type PluginType int
+
+const (
+ Protobuf PluginType = iota
+ Grpc
+)
+
func init() {
android.RegisterModuleType("rust_protobuf", RustProtobufFactory)
android.RegisterModuleType("rust_protobuf_host", RustProtobufHostFactory)
+ android.RegisterModuleType("rust_grpcio", RustGrpcioFactory)
+ android.RegisterModuleType("rust_grpcio_host", RustGrpcioHostFactory)
}
var _ SourceProvider = (*protobufDecorator)(nil)
@@ -35,41 +51,101 @@
// List of additional flags to pass to aprotoc
Proto_flags []string `android:"arch_variant"`
+
+ // List of libraries which export include paths required for this module
+ Header_libs []string `android:"arch_variant"`
}
type protobufDecorator struct {
*BaseSourceProvider
Properties ProtobufProperties
+ plugin PluginType
}
func (proto *protobufDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) android.Path {
var protoFlags android.ProtoFlags
- pluginPath := ctx.Config().HostToolPath(ctx, "protoc-gen-rust")
+ var pluginPaths android.Paths
protoFlags.OutTypeFlag = "--rust_out"
+ outDir := android.PathForModuleOut(ctx)
- protoFlags.Flags = append(protoFlags.Flags, " --plugin="+pluginPath.String())
+ pluginPaths, protoFlags = proto.setupPlugin(ctx, protoFlags, outDir)
+
protoFlags.Flags = append(protoFlags.Flags, defaultProtobufFlags...)
protoFlags.Flags = append(protoFlags.Flags, proto.Properties.Proto_flags...)
- protoFlags.Deps = append(protoFlags.Deps, pluginPath)
+ protoFlags.Deps = append(protoFlags.Deps, pluginPaths...)
protoFile := android.OptionalPathForModuleSrc(ctx, proto.Properties.Proto)
if !protoFile.Valid() {
ctx.PropertyErrorf("proto", "invalid path to proto file")
}
- outDir := android.PathForModuleOut(ctx)
- depFile := android.PathForModuleOut(ctx, proto.BaseSourceProvider.getStem(ctx)+".d")
- outputs := android.WritablePaths{android.PathForModuleOut(ctx, proto.BaseSourceProvider.getStem(ctx)+".rs")}
+ // Add exported dependency include paths
+ for _, include := range deps.depIncludePaths {
+ protoFlags.Flags = append(protoFlags.Flags, "-I"+include.String())
+ }
+
+ stem := proto.BaseSourceProvider.getStem(ctx)
+ // rust protobuf-codegen output <stem>.rs
+ stemFile := android.PathForModuleOut(ctx, stem+".rs")
+ // add mod_<stem>.rs to import <stem>.rs
+ modFile := android.PathForModuleOut(ctx, "mod_"+stem+".rs")
+ // mod_<stem>.rs is the main/first output file to be included/compiled
+ outputs := android.WritablePaths{modFile, stemFile}
+ if proto.plugin == Grpc {
+ outputs = append(outputs, android.PathForModuleOut(ctx, stem+grpcSuffix+".rs"))
+ }
+ depFile := android.PathForModuleOut(ctx, "mod_"+stem+".d")
rule := android.NewRuleBuilder()
android.ProtoRule(ctx, rule, protoFile.Path(), protoFlags, protoFlags.Deps, outDir, depFile, outputs)
+ rule.Command().Text("printf '" + proto.getModFileContents(ctx) + "' >").Output(modFile)
rule.Build(pctx, ctx, "protoc_"+protoFile.Path().Rel(), "protoc "+protoFile.Path().Rel())
- proto.BaseSourceProvider.OutputFile = outputs[0]
- return outputs[0]
+ proto.BaseSourceProvider.OutputFiles = android.Paths{modFile, stemFile}
+ return modFile
+}
+
+func (proto *protobufDecorator) getModFileContents(ctx ModuleContext) string {
+ stem := proto.BaseSourceProvider.getStem(ctx)
+ lines := []string{
+ "// @generated",
+ fmt.Sprintf("pub mod %s;", stem),
+ }
+
+ if proto.plugin == Grpc {
+ lines = append(lines, fmt.Sprintf("pub mod %s%s;", stem, grpcSuffix))
+ lines = append(
+ lines,
+ "pub mod empty {",
+ " pub use protobuf::well_known_types::Empty;",
+ "}")
+ }
+
+ return strings.Join(lines, "\\n")
+}
+
+func (proto *protobufDecorator) setupPlugin(ctx ModuleContext, protoFlags android.ProtoFlags, outDir android.ModuleOutPath) (android.Paths, android.ProtoFlags) {
+ pluginPaths := []android.Path{}
+
+ if proto.plugin == Protobuf {
+ pluginPath := ctx.Config().HostToolPath(ctx, "protoc-gen-rust")
+ pluginPaths = append(pluginPaths, pluginPath)
+ protoFlags.Flags = append(protoFlags.Flags, "--plugin="+pluginPath.String())
+ } else if proto.plugin == Grpc {
+ grpcPath := ctx.Config().HostToolPath(ctx, "grpc_rust_plugin")
+ protobufPath := ctx.Config().HostToolPath(ctx, "protoc-gen-rust")
+ pluginPaths = append(pluginPaths, grpcPath, protobufPath)
+ protoFlags.Flags = append(protoFlags.Flags, "--grpc_out="+outDir.String())
+ protoFlags.Flags = append(protoFlags.Flags, "--plugin=protoc-gen-grpc="+grpcPath.String())
+ protoFlags.Flags = append(protoFlags.Flags, "--plugin=protoc-gen-rust="+protobufPath.String())
+ } else {
+ ctx.ModuleErrorf("Unknown protobuf plugin type requested")
+ }
+
+ return pluginPaths, protoFlags
}
func (proto *protobufDecorator) SourceProviderProps() []interface{} {
@@ -79,6 +155,13 @@
func (proto *protobufDecorator) SourceProviderDeps(ctx DepsContext, deps Deps) Deps {
deps = proto.BaseSourceProvider.SourceProviderDeps(ctx, deps)
deps.Rustlibs = append(deps.Rustlibs, "libprotobuf")
+ deps.HeaderLibs = append(deps.SharedLibs, proto.Properties.Header_libs...)
+
+ if proto.plugin == Grpc {
+ deps.Rustlibs = append(deps.Rustlibs, "libgrpcio", "libfutures")
+ deps.HeaderLibs = append(deps.HeaderLibs, "libprotobuf-cpp-full")
+ }
+
return deps
}
@@ -97,10 +180,34 @@
return module.Init()
}
+func RustGrpcioFactory() android.Module {
+ module, _ := NewRustGrpcio(android.HostAndDeviceSupported)
+ return module.Init()
+}
+
+// A host-only variant of rust_protobuf. Refer to rust_protobuf for more details.
+func RustGrpcioHostFactory() android.Module {
+ module, _ := NewRustGrpcio(android.HostSupported)
+ return module.Init()
+}
+
func NewRustProtobuf(hod android.HostOrDeviceSupported) (*Module, *protobufDecorator) {
protobuf := &protobufDecorator{
BaseSourceProvider: NewSourceProvider(),
Properties: ProtobufProperties{},
+ plugin: Protobuf,
+ }
+
+ module := NewSourceProviderModule(hod, protobuf, false)
+
+ return module, protobuf
+}
+
+func NewRustGrpcio(hod android.HostOrDeviceSupported) (*Module, *protobufDecorator) {
+ protobuf := &protobufDecorator{
+ BaseSourceProvider: NewSourceProvider(),
+ Properties: ProtobufProperties{},
+ plugin: Grpc,
}
module := NewSourceProviderModule(hod, protobuf, false)
diff --git a/rust/protobuf_test.go b/rust/protobuf_test.go
index a9dbf39..845911f 100644
--- a/rust/protobuf_test.go
+++ b/rust/protobuf_test.go
@@ -15,8 +15,10 @@
package rust
import (
- "android/soong/android"
+ "strings"
"testing"
+
+ "android/soong/android"
)
func TestRustProtobuf(t *testing.T) {
@@ -26,14 +28,93 @@
proto: "buf.proto",
crate_name: "rust_proto",
source_stem: "buf",
+ shared_libs: ["libfoo_shared"],
+ static_libs: ["libfoo_static"],
+ }
+ cc_library_shared {
+ name: "libfoo_shared",
+ export_include_dirs: ["shared_include"],
+ }
+ cc_library_static {
+ name: "libfoo_static",
+ export_include_dirs: ["static_include"],
}
`)
- // Check that there's a rule to generate the expected output
- _ = ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_dylib").Output("buf.rs")
-
// Check that libprotobuf is added as a dependency.
librust_proto := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_dylib").Module().(*Module)
if !android.InList("libprotobuf", librust_proto.Properties.AndroidMkDylibs) {
t.Errorf("libprotobuf dependency missing for rust_protobuf (dependency missing from AndroidMkDylibs)")
}
+
+ // Make sure the correct plugin is being used.
+ librust_proto_out := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_source").Output("buf.rs")
+ cmd := librust_proto_out.RuleParams.Command
+ if w := "protoc-gen-rust"; !strings.Contains(cmd, w) {
+ t.Errorf("expected %q in %q", w, cmd)
+ }
+
+ // Check exported include directories
+ if w := "-Ishared_include"; !strings.Contains(cmd, w) {
+ t.Errorf("expected %q in %q", w, cmd)
+ }
+ if w := "-Istatic_include"; !strings.Contains(cmd, w) {
+ t.Errorf("expected %q in %q", w, cmd)
+ }
+}
+
+func TestRustGrpcio(t *testing.T) {
+ ctx := testRust(t, `
+ rust_grpcio {
+ name: "librust_grpcio",
+ proto: "buf.proto",
+ crate_name: "rust_grpcio",
+ source_stem: "buf",
+ shared_libs: ["libfoo_shared"],
+ static_libs: ["libfoo_static"],
+ }
+ cc_library_shared {
+ name: "libfoo_shared",
+ export_include_dirs: ["shared_include"],
+ }
+ cc_library_static {
+ name: "libfoo_static",
+ export_include_dirs: ["static_include"],
+ }
+ `)
+
+ // Check that libprotobuf is added as a dependency.
+ librust_grpcio_module := ctx.ModuleForTests("librust_grpcio", "android_arm64_armv8-a_dylib").Module().(*Module)
+ if !android.InList("libprotobuf", librust_grpcio_module.Properties.AndroidMkDylibs) {
+ t.Errorf("libprotobuf dependency missing for rust_grpcio (dependency missing from AndroidMkDylibs)")
+ }
+
+ // Check that libgrpcio is added as a dependency.
+ if !android.InList("libgrpcio", librust_grpcio_module.Properties.AndroidMkDylibs) {
+ t.Errorf("libgrpcio dependency missing for rust_grpcio (dependency missing from AndroidMkDylibs)")
+ }
+
+ // Check that libfutures is added as a dependency.
+ if !android.InList("libfutures", librust_grpcio_module.Properties.AndroidMkDylibs) {
+ t.Errorf("libfutures dependency missing for rust_grpcio (dependency missing from AndroidMkDylibs)")
+ }
+
+ // Make sure the correct plugin is being used.
+ librust_grpcio_out := ctx.ModuleForTests("librust_grpcio", "android_arm64_armv8-a_source").Output("buf_grpc.rs")
+ cmd := librust_grpcio_out.RuleParams.Command
+ if w := "protoc-gen-grpc"; !strings.Contains(cmd, w) {
+ t.Errorf("expected %q in %q", w, cmd)
+ }
+
+ // Check exported include directories
+ if w := "-Ishared_include"; !strings.Contains(cmd, w) {
+ t.Errorf("expected %q in %q", w, cmd)
+ }
+ if w := "-Istatic_include"; !strings.Contains(cmd, w) {
+ t.Errorf("expected %q in %q", w, cmd)
+ }
+
+ // Check that we're including the exported directory from libprotobuf-cpp-full
+ if w := "-Ilibprotobuf-cpp-full-includes"; !strings.Contains(cmd, w) {
+ t.Errorf("expected %q in %q", w, cmd)
+ }
}
diff --git a/rust/rust.go b/rust/rust.go
index b98992c..5b94045 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -40,6 +40,7 @@
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 @@
sourceProvider SourceProvider
subAndroidMkOnce map[SubAndroidMkProvider]bool
- outputFile android.OptionalPath
- generatedFile android.OptionalPath
+ outputFile android.OptionalPath
}
func (mod *Module) OutputFiles(tag string) (android.Paths, error) {
@@ -118,6 +118,10 @@
return mod.InRamdisk()
}
+func (mod *Module) VendorRamdiskVariantNeeded(android.BaseModuleContext) bool {
+ return mod.InVendorRamdisk()
+}
+
func (mod *Module) RecoveryVariantNeeded(android.BaseModuleContext) bool {
return mod.InRecovery()
}
@@ -129,14 +133,6 @@
func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string, module android.Module) {
}
-func (mod *Module) BuildStubs() bool {
- return false
-}
-
-func (mod *Module) HasStubsVariants() bool {
- return false
-}
-
func (mod *Module) SelectedStl() string {
return ""
}
@@ -150,10 +146,6 @@
panic(fmt.Errorf("NonCcVariants called on non-library module: %q", mod.BaseModuleName()))
}
-func (mod *Module) ApiLevel() string {
- panic(fmt.Errorf("Called ApiLevel on Rust module %q; stubs libraries are not yet supported.", mod.BaseModuleName()))
-}
-
func (mod *Module) Static() bool {
if mod.compiler != nil {
if library, ok := mod.compiler.(libraryInterface); ok {
@@ -185,6 +177,10 @@
return false
}
+func (mod *Module) OnlyInVendorRamdisk() bool {
+ return false
+}
+
func (mod *Module) OnlyInRecovery() bool {
return false
}
@@ -221,15 +217,7 @@
return false
}
-func (mod *Module) ToolchainLibrary() bool {
- return false
-}
-
-func (mod *Module) NdkPrebuiltStl() bool {
- return false
-}
-
-func (mod *Module) StubDecorator() bool {
+func (mod *Module) SplitPerApiLevel() bool {
return false
}
@@ -237,9 +225,11 @@
Dylibs []string
Rlibs []string
Rustlibs []string
+ Stdlibs []string
ProcMacros []string
SharedLibs []string
StaticLibs []string
+ HeaderLibs []string
CrtBegin, CrtEnd string
}
@@ -293,13 +283,10 @@
Disabled() bool
SetDisabled()
- static() bool
+ stdLinkage(ctx *depsContext) RustLinkage
}
type exportedFlagsProducer interface {
- exportedLinkDirs() []string
- exportedDepFlags() []string
- exportedLinkObjects() []string
exportLinkDirs(...string)
exportDepFlags(...string)
exportLinkObjects(...string)
@@ -311,18 +298,6 @@
linkObjects []string
}
-func (flagExporter *flagExporter) exportedLinkDirs() []string {
- return flagExporter.linkDirs
-}
-
-func (flagExporter *flagExporter) exportedDepFlags() []string {
- return flagExporter.depFlags
-}
-
-func (flagExporter *flagExporter) exportedLinkObjects() []string {
- return flagExporter.linkObjects
-}
-
func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) {
flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...))
}
@@ -335,16 +310,28 @@
flagExporter.linkObjects = android.FirstUniqueStrings(append(flagExporter.linkObjects, flags...))
}
+func (flagExporter *flagExporter) setProvider(ctx ModuleContext) {
+ ctx.SetProvider(FlagExporterInfoProvider, FlagExporterInfo{
+ Flags: flagExporter.depFlags,
+ LinkDirs: flagExporter.linkDirs,
+ LinkObjects: flagExporter.linkObjects,
+ })
+}
+
var _ exportedFlagsProducer = (*flagExporter)(nil)
func NewFlagExporter() *flagExporter {
- return &flagExporter{
- depFlags: []string{},
- linkDirs: []string{},
- linkObjects: []string{},
- }
+ return &flagExporter{}
}
+type FlagExporterInfo struct {
+ Flags []string
+ LinkDirs []string // TODO: this should be android.Paths
+ LinkObjects []string // TODO: this should be android.Paths
+}
+
+var FlagExporterInfoProvider = blueprint.NewProvider(FlagExporterInfo{})
+
func (mod *Module) isCoverageVariant() bool {
return mod.coverage.Properties.IsCoverageVariant
}
@@ -386,6 +373,7 @@
module.AddProperties(props...)
module.AddProperties(
&BaseProperties{},
+ &BindgenProperties{},
&BaseCompilerProperties{},
&BinaryCompilerProperties{},
&LibraryCompilerProperties{},
@@ -394,6 +382,7 @@
&SourceProviderProperties{},
&TestProperties{},
&cc.CoverageProperties{},
+ &cc.RustBindgenClangProperties{},
&ClippyProperties{},
)
@@ -454,18 +443,6 @@
panic(fmt.Errorf("SetShared called on non-library module: %q", mod.BaseModuleName()))
}
-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) StubsVersion() string {
- panic("SetStubsVersions not yet implemented for rust modules")
-}
-
func (mod *Module) BuildStaticVariant() bool {
if mod.compiler != nil {
if library, ok := mod.compiler.(libraryInterface); ok {
@@ -484,31 +461,10 @@
panic(fmt.Errorf("BuildSharedVariant called on non-library module: %q", mod.BaseModuleName()))
}
-// Rust module deps don't have a link order (?)
-func (mod *Module) SetDepsInLinkOrder([]android.Path) {}
-
-func (mod *Module) GetDepsInLinkOrder() []android.Path {
- return []android.Path{}
-}
-
-func (mod *Module) GetStaticVariant() cc.LinkableInterface {
- return nil
-}
-
func (mod *Module) Module() android.Module {
return mod
}
-func (mod *Module) StubsVersions() []string {
- // For now, Rust has no stubs versions.
- if mod.compiler != nil {
- if _, ok := mod.compiler.(libraryInterface); ok {
- return []string{}
- }
- }
- panic(fmt.Errorf("StubsVersions called on non-library module: %q", mod.BaseModuleName()))
-}
-
func (mod *Module) OutputFile() android.OptionalPath {
return mod.outputFile
}
@@ -517,12 +473,6 @@
// For now, Rust has no notion of the recovery image
return false
}
-func (mod *Module) HasStaticVariant() bool {
- if mod.GetStaticVariant() != nil {
- return true
- }
- return false
-}
func (mod *Module) CoverageFiles() android.Paths {
if mod.compiler != nil {
@@ -677,12 +627,20 @@
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())
+ } else {
+ sourceMod := actx.GetDirectDepWithTag(mod.Name(), sourceDepTag)
+ sourceLib := sourceMod.(*Module).compiler.(*libraryDecorator)
+ mod.sourceProvider.setOutputFiles(sourceLib.sourceProvider.Srcs())
+ }
}
if mod.compiler != nil && !mod.compiler.Disabled() {
@@ -733,6 +691,7 @@
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 +700,10 @@
}
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 +743,15 @@
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)
@@ -814,10 +776,11 @@
}
//Append the dependencies exportedDirs, except for proc-macros which target a different arch/OS
- if lib, ok := rustDep.compiler.(exportedFlagsProducer); ok && depTag != procMacroDepTag {
- depPaths.linkDirs = append(depPaths.linkDirs, lib.exportedLinkDirs()...)
- depPaths.depFlags = append(depPaths.depFlags, lib.exportedDepFlags()...)
- depPaths.linkObjects = append(depPaths.linkObjects, lib.exportedLinkObjects()...)
+ if depTag != procMacroDepTag {
+ exportedInfo := ctx.OtherModuleProvider(dep, FlagExporterInfoProvider).(FlagExporterInfo)
+ depPaths.linkDirs = append(depPaths.linkDirs, exportedInfo.LinkDirs...)
+ depPaths.depFlags = append(depPaths.depFlags, exportedInfo.Flags...)
+ depPaths.linkObjects = append(depPaths.linkObjects, exportedInfo.LinkObjects...)
}
if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag {
@@ -857,27 +820,30 @@
case cc.IsStaticDepTag(depTag):
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
- depPaths.depIncludePaths = append(depPaths.depIncludePaths, ccDep.IncludeDirs()...)
- if mod, ok := ccDep.(*cc.Module); ok {
- depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, mod.ExportedSystemIncludeDirs()...)
- depPaths.depClangFlags = append(depPaths.depClangFlags, mod.ExportedFlags()...)
- depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, mod.ExportedGeneratedHeaders()...)
- }
+ exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo)
+ depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
+ depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
+ depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
+ depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
depPaths.coverageFiles = append(depPaths.coverageFiles, ccDep.CoverageFiles()...)
directStaticLibDeps = append(directStaticLibDeps, ccDep)
mod.Properties.AndroidMkStaticLibs = append(mod.Properties.AndroidMkStaticLibs, depName)
case cc.IsSharedDepTag(depTag):
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
- depPaths.depIncludePaths = append(depPaths.depIncludePaths, ccDep.IncludeDirs()...)
- if mod, ok := ccDep.(*cc.Module); ok {
- depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, mod.ExportedSystemIncludeDirs()...)
- depPaths.depClangFlags = append(depPaths.depClangFlags, mod.ExportedFlags()...)
- depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, mod.ExportedGeneratedHeaders()...)
- }
+ exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo)
+ depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
+ depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
+ depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
+ depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
directSharedLibDeps = append(directSharedLibDeps, ccDep)
mod.Properties.AndroidMkSharedLibs = append(mod.Properties.AndroidMkSharedLibs, depName)
exportDep = true
+ case cc.IsHeaderDepTag(depTag):
+ exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo)
+ depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
+ depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
+ depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
case depTag == cc.CrtBeginDepTag:
depPaths.CrtBegin = linkObject
case depTag == cc.CrtEndDepTag:
@@ -967,32 +933,55 @@
}
deps := mod.deps(ctx)
- commonDepVariations := []blueprint.Variation{}
- if cc.VersionVariantAvailable(mod) {
- commonDepVariations = append(commonDepVariations,
- blueprint.Variation{Mutator: "version", Variation: ""})
- }
+ var commonDepVariations []blueprint.Variation
if !mod.Host() {
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...)
@@ -1000,7 +989,9 @@
blueprint.Variation{Mutator: "link", Variation: "static"}),
cc.StaticDepTag(), deps.StaticLibs...)
- crtVariations := append(cc.GetCrtVariations(ctx, mod), commonDepVariations...)
+ actx.AddVariationDependencies(nil, cc.HeaderDepTag(), deps.HeaderLibs...)
+
+ crtVariations := cc.GetCrtVariations(ctx, mod)
if deps.CrtBegin != "" {
actx.AddVariationDependencies(crtVariations, cc.CrtBeginDepTag, deps.CrtBegin)
}
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 89ce359..14bbd0b 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -54,10 +54,58 @@
os.Exit(run())
}
-func testConfig(bp string) android.Config {
- bp = bp + GatherRequiredDepsForTest()
+// testRust returns a TestContext in which a basic environment has been setup.
+// This environment contains a few mocked files. See testRustCtx.useMockedFs
+// for the list of these files.
+func testRust(t *testing.T, bp string) *android.TestContext {
+ tctx := newTestRustCtx(t, bp)
+ tctx.useMockedFs()
+ tctx.generateConfig()
+ return tctx.parse(t)
+}
- fs := map[string][]byte{
+// testRustCov returns a TestContext in which a basic environment has been
+// setup. This environment explicitly enables coverage.
+func testRustCov(t *testing.T, bp string) *android.TestContext {
+ tctx := newTestRustCtx(t, bp)
+ tctx.useMockedFs()
+ tctx.generateConfig()
+ tctx.enableCoverage(t)
+ return tctx.parse(t)
+}
+
+// testRustError ensures that at least one error was raised and its value
+// matches the pattern provided. The error can be either in the parsing of the
+// Blueprint or when generating the build actions.
+func testRustError(t *testing.T, pattern string, bp string) {
+ tctx := newTestRustCtx(t, bp)
+ tctx.useMockedFs()
+ tctx.generateConfig()
+ tctx.parseError(t, pattern)
+}
+
+// testRustCtx is used to build a particular test environment. Unless your
+// tests requires a specific setup, prefer the wrapping functions: testRust,
+// testRustCov or testRustError.
+type testRustCtx struct {
+ bp string
+ fs map[string][]byte
+ env map[string]string
+ config *android.Config
+}
+
+// newTestRustCtx returns a new testRustCtx for the Blueprint definition argument.
+func newTestRustCtx(t *testing.T, bp string) *testRustCtx {
+ // TODO (b/140435149)
+ if runtime.GOOS != "linux" {
+ t.Skip("Rust Soong tests can only be run on Linux hosts currently")
+ }
+ return &testRustCtx{bp: bp}
+}
+
+// useMockedFs setup a default mocked filesystem for the test environment.
+func (tctx *testRustCtx) useMockedFs() {
+ tctx.fs = map[string][]byte{
"foo.rs": nil,
"foo.c": nil,
"src/bar.rs": nil,
@@ -66,57 +114,51 @@
"liby.so": nil,
"libz.so": nil,
}
-
- cc.GatherRequiredFilesForTest(fs)
-
- return android.TestArchConfig(buildDir, nil, bp, fs)
}
-func testRust(t *testing.T, bp string) *android.TestContext {
- return testRustContext(t, bp, false)
+// generateConfig creates the android.Config based on the bp, fs and env
+// attributes of the testRustCtx.
+func (tctx *testRustCtx) generateConfig() {
+ tctx.bp = tctx.bp + GatherRequiredDepsForTest()
+ cc.GatherRequiredFilesForTest(tctx.fs)
+ config := android.TestArchConfig(buildDir, tctx.env, tctx.bp, tctx.fs)
+ tctx.config = &config
}
-func testRustCov(t *testing.T, bp string) *android.TestContext {
- return testRustContext(t, bp, true)
-}
-
-func testRustContext(t *testing.T, bp string, coverage bool) *android.TestContext {
- // TODO (b/140435149)
- if runtime.GOOS != "linux" {
- t.Skip("Only the Linux toolchain is supported for Rust")
+// enableCoverage configures the test to enable coverage.
+func (tctx *testRustCtx) enableCoverage(t *testing.T) {
+ if tctx.config == nil {
+ t.Fatalf("tctx.config not been generated yet. Please call generateConfig first.")
}
+ tctx.config.TestProductVariables.GcovCoverage = proptools.BoolPtr(true)
+ tctx.config.TestProductVariables.Native_coverage = proptools.BoolPtr(true)
+ tctx.config.TestProductVariables.NativeCoveragePaths = []string{"*"}
+}
- t.Helper()
- config := testConfig(bp)
-
- if coverage {
- config.TestProductVariables.GcovCoverage = proptools.BoolPtr(true)
- config.TestProductVariables.Native_coverage = proptools.BoolPtr(true)
- config.TestProductVariables.NativeCoveragePaths = []string{"*"}
+// parse validates the configuration and parses the Blueprint file. It returns
+// a TestContext which can be used to retrieve the generated modules via
+// ModuleForTests.
+func (tctx testRustCtx) parse(t *testing.T) *android.TestContext {
+ if tctx.config == nil {
+ t.Fatalf("tctx.config not been generated yet. Please call generateConfig first.")
}
-
- ctx := CreateTestContext()
- ctx.Register(config)
-
+ ctx := CreateTestContext(*tctx.config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
+ _, errs = ctx.PrepareBuildActions(*tctx.config)
android.FailIfErrored(t, errs)
-
return ctx
}
-func testRustError(t *testing.T, pattern string, bp string) {
- // TODO (b/140435149)
- if runtime.GOOS != "linux" {
- t.Skip("Only the Linux toolchain is supported for Rust")
+// parseError parses the Blueprint file and ensure that at least one error
+// matching the provided pattern is observed.
+func (tctx testRustCtx) parseError(t *testing.T, pattern string) {
+ if tctx.config == nil {
+ t.Fatalf("tctx.config not been generated yet. Please call generateConfig first.")
}
-
- t.Helper()
- config := testConfig(bp)
-
- ctx := CreateTestContext()
- ctx.Register(config)
+ ctx := CreateTestContext(*tctx.config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
if len(errs) > 0 {
@@ -124,7 +166,7 @@
return
}
- _, errs = ctx.PrepareBuildActions(config)
+ _, errs = ctx.PrepareBuildActions(*tctx.config)
if len(errs) > 0 {
android.FailIfNoMatchingErrors(t, pattern, errs)
return
@@ -189,7 +231,7 @@
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 +295,7 @@
}
`)
- 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 +321,15 @@
// 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 +407,6 @@
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 755a369..436518c 100644
--- a/rust/source_provider.go
+++ b/rust/source_provider.go
@@ -30,7 +30,7 @@
type BaseSourceProvider struct {
Properties SourceProviderProperties
- OutputFile android.Path
+ OutputFiles android.Paths
subAndroidMkOnce map[SubAndroidMkProvider]bool
subName string
}
@@ -43,10 +43,11 @@
SourceProviderProps() []interface{}
SourceProviderDeps(ctx DepsContext, deps Deps) Deps
setSubName(subName string)
+ setOutputFiles(outputFiles android.Paths)
}
func (sp *BaseSourceProvider) Srcs() android.Paths {
- return android.Paths{sp.OutputFile}
+ return sp.OutputFiles
}
func (sp *BaseSourceProvider) GenerateSource(ctx ModuleContext, deps PathDeps) android.Path {
@@ -95,3 +96,7 @@
func (sp *BaseSourceProvider) setSubName(subName string) {
sp.subName = subName
}
+
+func (sp *BaseSourceProvider) setOutputFiles(outputFiles android.Paths) {
+ sp.OutputFiles = outputFiles
+}
diff --git a/rust/test.go b/rust/test.go
index d93fc31..bc7f53c 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -133,3 +133,7 @@
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 2382b18..fea2ad0 100644
--- a/rust/test_test.go
+++ b/rust/test_test.go
@@ -17,6 +17,8 @@
import (
"strings"
"testing"
+
+ "android/soong/android"
)
func TestRustTest(t *testing.T) {
@@ -33,3 +35,35 @@
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 0144c82..66877a9 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -32,6 +32,7 @@
srcs: ["libstd.so"],
},
host_supported: true,
+ sysroot: true,
}
rust_prebuilt_library {
name: "libtest_x86_64-unknown-linux-gnu",
@@ -43,6 +44,7 @@
srcs: ["libtest.so"],
},
host_supported: true,
+ sysroot: true,
}
rust_prebuilt_library {
name: "libstd_x86_64-apple-darwin",
@@ -54,6 +56,7 @@
srcs: ["libstd.so"],
},
host_supported: true,
+ sysroot: true,
}
rust_prebuilt_library {
name: "libtest_x86_64-apple-darwin",
@@ -65,6 +68,7 @@
srcs: ["libtest.so"],
},
host_supported: true,
+ sysroot: true,
}
//////////////////////////////
// Device module requirements
@@ -75,6 +79,13 @@
nocrt: true,
system_shared_libs: [],
}
+ cc_library {
+ name: "libprotobuf-cpp-full",
+ no_libcrt: true,
+ nocrt: true,
+ system_shared_libs: [],
+ export_include_dirs: ["libprotobuf-cpp-full-includes"],
+ }
rust_library {
name: "libstd",
crate_name: "std",
@@ -82,6 +93,7 @@
no_stdlibs: true,
host_supported: true,
native_coverage: false,
+ sysroot: true,
}
rust_library {
name: "libtest",
@@ -90,6 +102,7 @@
no_stdlibs: true,
host_supported: true,
native_coverage: false,
+ sysroot: true,
}
rust_library {
name: "libprotobuf",
@@ -97,13 +110,25 @@
srcs: ["foo.rs"],
host_supported: true,
}
+ rust_library {
+ name: "libgrpcio",
+ crate_name: "grpcio",
+ srcs: ["foo.rs"],
+ host_supported: true,
+ }
+ rust_library {
+ name: "libfutures",
+ crate_name: "futures",
+ srcs: ["foo.rs"],
+ host_supported: true,
+ }
` + cc.GatherRequiredDepsForTest(android.NoOsType)
return bp
}
-func CreateTestContext() *android.TestContext {
- ctx := android.NewTestArchContext()
+func CreateTestContext(config android.Config) *android.TestContext {
+ ctx := android.NewTestArchContext(config)
android.RegisterPrebuiltMutators(ctx)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
cc.RegisterRequiredBuildComponentsForTest(ctx)
@@ -111,6 +136,7 @@
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)
@@ -125,6 +151,8 @@
ctx.RegisterModuleType("rust_ffi_host", RustFFIHostFactory)
ctx.RegisterModuleType("rust_ffi_host_shared", RustFFISharedHostFactory)
ctx.RegisterModuleType("rust_ffi_host_static", RustFFIStaticHostFactory)
+ ctx.RegisterModuleType("rust_grpcio", RustGrpcioFactory)
+ ctx.RegisterModuleType("rust_grpcio_host", RustGrpcioHostFactory)
ctx.RegisterModuleType("rust_proc_macro", ProcMacroFactory)
ctx.RegisterModuleType("rust_protobuf", RustProtobufFactory)
ctx.RegisterModuleType("rust_protobuf_host", RustProtobufHostFactory)
@@ -134,6 +162,7 @@
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/Android.bp b/scripts/Android.bp
index 7782c68..dd03f28 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -1,4 +1,20 @@
python_binary_host {
+ name: "check_boot_jars",
+ main: "check_boot_jars/check_boot_jars.py",
+ srcs: [
+ "check_boot_jars/check_boot_jars.py",
+ ],
+ version: {
+ py2: {
+ enabled: true,
+ },
+ py3: {
+ enabled: false,
+ },
+ },
+}
+
+python_binary_host {
name: "manifest_fixer",
main: "manifest_fixer.py",
srcs: [
@@ -206,3 +222,22 @@
"ninja_rsp.py",
],
}
+
+python_binary_host {
+ name: "conv_linker_config",
+ srcs: [
+ "conv_linker_config.py",
+ ],
+ version: {
+ py2: {
+ enabled: false,
+ },
+ py3: {
+ enabled: true,
+ embedded_launcher: true,
+ },
+ },
+ libs: [
+ "linker_config_proto",
+ ],
+}
diff --git a/scripts/OWNERS b/scripts/OWNERS
index 8c64424..8198083 100644
--- a/scripts/OWNERS
+++ b/scripts/OWNERS
@@ -2,3 +2,4 @@
per-file build-mainline-modules.sh = ngeoffray@google.com,paulduffin@google.com,mast@google.com
per-file build-aml-prebuilts.sh = ngeoffray@google.com,paulduffin@google.com,mast@google.com
per-file construct_context.py = ngeoffray@google.com,calin@google.com,mathieuc@google.com,skvadrik@google.com
+per-file conv_linker_config.py = kiyoungkim@google.com, jiyong@google.com, jooyung@google.com
diff --git a/scripts/build-aml-prebuilts.sh b/scripts/build-aml-prebuilts.sh
index ef5565d..89fb1a5 100755
--- a/scripts/build-aml-prebuilts.sh
+++ b/scripts/build-aml-prebuilts.sh
@@ -37,6 +37,14 @@
OUT_DIR=${OUT_DIR}/get_build_var get_build_var "$@"
}
+readonly SOONG_OUT=${OUT_DIR}/soong
+mkdir -p ${SOONG_OUT}
+
+# Some Soong build rules may require this, and the failure mode if it's missing
+# is confusing (b/172548608).
+readonly BUILD_NUMBER="$(my_get_build_var BUILD_NUMBER)"
+echo -n ${BUILD_NUMBER} > ${SOONG_OUT}/build_number.txt
+
readonly PLATFORM_SDK_VERSION="$(my_get_build_var PLATFORM_SDK_VERSION)"
readonly PLATFORM_VERSION="$(my_get_build_var PLATFORM_VERSION)"
PLATFORM_VERSION_ALL_CODENAMES="$(my_get_build_var PLATFORM_VERSION_ALL_CODENAMES)"
@@ -61,8 +69,6 @@
USE_GOMA=false
fi
-readonly SOONG_OUT=${OUT_DIR}/soong
-mkdir -p ${SOONG_OUT}
readonly SOONG_VARS=${SOONG_OUT}/soong.variables
# Aml_abis: true
@@ -73,6 +79,8 @@
# - Enable Bionic on host as ART needs prebuilts for it.
cat > ${SOONG_VARS}.new << EOF
{
+ "BuildNumberFile": "build_number.txt",
+
"Platform_sdk_version": ${PLATFORM_SDK_VERSION},
"Platform_sdk_codename": "${PLATFORM_VERSION}",
"Platform_version_active_codenames": ${PLATFORM_VERSION_ALL_CODENAMES},
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index c5ec8d1..b8dd7aa 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -3,13 +3,13 @@
# Non exhaustive list of modules where we want prebuilts. More can be added as
# needed.
MAINLINE_MODULES=(
+ com.android.art
com.android.art.debug
- com.android.art.release
com.android.art.testing
com.android.conscrypt
+ com.android.i18n
com.android.runtime
com.android.tzdata
- com.android.i18n
)
# List of SDKs and module exports we know of.
diff --git a/scripts/check_boot_jars/check_boot_jars.py b/scripts/check_boot_jars/check_boot_jars.py
new file mode 100755
index 0000000..c271211
--- /dev/null
+++ b/scripts/check_boot_jars/check_boot_jars.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+
+"""
+Check boot jars.
+
+Usage: check_boot_jars.py <dexdump_path> <package_allow_list_file> <jar1> <jar2> ...
+"""
+import logging
+import os.path
+import re
+import subprocess
+import sys
+import xml.etree.ElementTree
+
+
+# The compiled allow list RE.
+allow_list_re = None
+
+
+def LoadAllowList(filename):
+ """ Load and compile allow list regular expressions from filename.
+ """
+ lines = []
+ with open(filename, 'r') as f:
+ for line in f:
+ line = line.strip()
+ if not line or line.startswith('#'):
+ continue
+ lines.append(line)
+ combined_re = r'^(%s)$' % '|'.join(lines)
+ global allow_list_re
+ try:
+ allow_list_re = re.compile(combined_re)
+ except re.error:
+ logging.exception(
+ 'Cannot compile package allow list regular expression: %r',
+ combined_re)
+ allow_list_re = None
+ return False
+ return True
+
+def CheckDexJar(dexdump_path, allow_list_path, jar):
+ """Check a dex jar file.
+ """
+ # Use dexdump to generate the XML representation of the dex jar file.
+ p = subprocess.Popen(args='%s -l xml %s' % (dexdump_path, jar),
+ stdout=subprocess.PIPE, shell=True)
+ stdout, _ = p.communicate()
+ if p.returncode != 0:
+ return False
+
+ packages = 0
+ try:
+ # TODO(b/172063475) - improve performance
+ root = xml.etree.ElementTree.fromstring(stdout)
+ except xml.etree.ElementTree.ParseError as e:
+ print >> sys.stderr, 'Error processing jar %s - %s' % (jar, e)
+ print >> sys.stderr, stdout
+ return False
+ for package_elt in root.iterfind('package'):
+ packages += 1
+ package_name = package_elt.get('name')
+ if not package_name or not allow_list_re.match(package_name):
+ # Report the name of a class in the package as it is easier to navigate to
+ # the source of a concrete class than to a package which is often required
+ # to investigate this failure.
+ class_name = package_elt[0].get('name')
+ if package_name != "":
+ class_name = package_name + "." + class_name
+ print >> sys.stderr, ('Error: %s contains class file %s, whose package name "%s" is empty or'
+ ' not in the allow list %s of packages allowed on the bootclasspath.'
+ % (jar, class_name, package_name, allow_list_path))
+ return False
+ if packages == 0:
+ print >> sys.stderr, ('Error: %s does not contain any packages.' % jar)
+ return False
+ return True
+
+
+def main(argv):
+ if len(argv) < 3:
+ print __doc__
+ return 1
+ dexdump_path = argv[0]
+ allow_list_path = argv[1]
+
+ if not LoadAllowList(allow_list_path):
+ return 1
+
+ passed = True
+ for jar in argv[2:]:
+ if not CheckDexJar(dexdump_path, allow_list_path, jar):
+ passed = False
+ if not passed:
+ return 1
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/scripts/check_boot_jars/package_allowed_list.txt b/scripts/check_boot_jars/package_allowed_list.txt
new file mode 100644
index 0000000..18ab427
--- /dev/null
+++ b/scripts/check_boot_jars/package_allowed_list.txt
@@ -0,0 +1,248 @@
+# Boot jar package name allowed list.
+# Each line is interpreted as a regular expression.
+
+###################################################
+# core-libart.jar & core-oj.jar
+java\.awt\.font
+java\.beans
+java\.io
+java\.lang
+java\.lang\.annotation
+java\.lang\.invoke
+java\.lang\.ref
+java\.lang\.reflect
+java\.math
+java\.net
+java\.nio
+java\.nio\.file
+java\.nio\.file\.spi
+java\.nio\.file\.attribute
+java\.nio\.channels
+java\.nio\.channels\.spi
+java\.nio\.charset
+java\.nio\.charset\.spi
+java\.security
+java\.security\.acl
+java\.security\.cert
+java\.security\.interfaces
+java\.security\.spec
+java\.sql
+java\.text
+java\.text\.spi
+java\.time
+java\.time\.chrono
+java\.time\.format
+java\.time\.temporal
+java\.time\.zone
+java\.util
+java\.util\.concurrent
+java\.util\.concurrent\.atomic
+java\.util\.concurrent\.locks
+java\.util\.function
+java\.util\.jar
+java\.util\.logging
+java\.util\.prefs
+java\.util\.regex
+java\.util\.spi
+java\.util\.stream
+java\.util\.zip
+# TODO: Remove javax.annotation.processing if possible, see http://b/132338110:
+javax\.annotation\.processing
+javax\.crypto
+javax\.crypto\.interfaces
+javax\.crypto\.spec
+javax\.net
+javax\.net\.ssl
+javax\.security\.auth
+javax\.security\.auth\.callback
+javax\.security\.auth\.login
+javax\.security\.auth\.x500
+javax\.security\.cert
+javax\.sql
+javax\.xml
+javax\.xml\.datatype
+javax\.xml\.namespace
+javax\.xml\.parsers
+javax\.xml\.transform
+javax\.xml\.transform\.dom
+javax\.xml\.transform\.sax
+javax\.xml\.transform\.stream
+javax\.xml\.validation
+javax\.xml\.xpath
+jdk\.internal\.util
+jdk\.internal\.vm\.annotation
+jdk\.net
+org\.w3c\.dom
+org\.w3c\.dom\.ls
+org\.w3c\.dom\.traversal
+# OpenJdk internal implementation.
+sun\.invoke\.util
+sun\.invoke\.empty
+sun\.misc
+sun\.util.*
+sun\.text.*
+sun\.security.*
+sun\.reflect.*
+sun\.nio.*
+sun\.net.*
+com\.sun\..*
+
+# TODO: Move these internal org.apache.harmony classes to libcore.*
+org\.apache\.harmony\.crypto\.internal
+org\.apache\.harmony\.dalvik
+org\.apache\.harmony\.dalvik\.ddmc
+org\.apache\.harmony\.luni\.internal\.util
+org\.apache\.harmony\.security
+org\.apache\.harmony\.security\.asn1
+org\.apache\.harmony\.security\.fortress
+org\.apache\.harmony\.security\.pkcs10
+org\.apache\.harmony\.security\.pkcs7
+org\.apache\.harmony\.security\.pkcs8
+org\.apache\.harmony\.security\.provider\.crypto
+org\.apache\.harmony\.security\.utils
+org\.apache\.harmony\.security\.x501
+org\.apache\.harmony\.security\.x509
+org\.apache\.harmony\.security\.x509\.tsp
+org\.apache\.harmony\.xml
+org\.apache\.harmony\.xml\.dom
+org\.apache\.harmony\.xml\.parsers
+
+org\.json
+org\.xmlpull\.v1
+org\.xmlpull\.v1\.sax2
+
+# TODO: jarjar org.kxml2.io to com.android org\.kxml2\.io
+org\.kxml2\.io
+org\.xml
+org\.xml\.sax
+org\.xml\.sax\.ext
+org\.xml\.sax\.helpers
+
+dalvik\..*
+libcore\..*
+android\..*
+com\.android\..*
+###################################################
+# android.test.base.jar
+junit\.extensions
+junit\.framework
+android\.test
+android\.test\.suitebuilder\.annotation
+
+
+###################################################
+# ext.jar
+# TODO: jarjar javax.sip to com.android
+javax\.sip
+javax\.sip\.address
+javax\.sip\.header
+javax\.sip\.message
+
+# TODO: jarjar org.apache.commons to com.android
+org\.apache\.commons\.codec
+org\.apache\.commons\.codec\.binary
+org\.apache\.commons\.codec\.language
+org\.apache\.commons\.codec\.net
+org\.apache\.commons\.logging
+org\.apache\.commons\.logging\.impl
+org\.apache\.http
+org\.apache\.http\.auth
+org\.apache\.http\.auth\.params
+org\.apache\.http\.client
+org\.apache\.http\.client\.entity
+org\.apache\.http\.client\.methods
+org\.apache\.http\.client\.params
+org\.apache\.http\.client\.protocol
+org\.apache\.http\.client\.utils
+org\.apache\.http\.conn
+org\.apache\.http\.conn\.params
+org\.apache\.http\.conn\.routing
+org\.apache\.http\.conn\.scheme
+org\.apache\.http\.conn\.ssl
+org\.apache\.http\.conn\.util
+org\.apache\.http\.cookie
+org\.apache\.http\.cookie\.params
+org\.apache\.http\.entity
+org\.apache\.http\.impl
+org\.apache\.http\.impl\.auth
+org\.apache\.http\.impl\.client
+org\.apache\.http\.impl\.client
+org\.apache\.http\.impl\.conn
+org\.apache\.http\.impl\.conn\.tsccm
+org\.apache\.http\.impl\.cookie
+org\.apache\.http\.impl\.entity
+org\.apache\.http\.impl\.io
+org\.apache\.http\.impl\.io
+org\.apache\.http\.io
+org\.apache\.http\.message
+org\.apache\.http\.params
+org\.apache\.http\.protocol
+org\.apache\.http\.util
+
+# TODO: jarjar gov.nist to com.android
+gov\.nist\.core
+gov\.nist\.core\.net
+gov\.nist\.javax\.sip
+gov\.nist\.javax\.sip\.address
+gov\.nist\.javax\.sip\.clientauthutils
+gov\.nist\.javax\.sip\.header
+gov\.nist\.javax\.sip\.header\.extensions
+gov\.nist\.javax\.sip\.header\.ims
+gov\.nist\.javax\.sip\.message
+gov\.nist\.javax\.sip\.parser
+gov\.nist\.javax\.sip\.parser\.extensions
+gov\.nist\.javax\.sip\.parser\.ims
+gov\.nist\.javax\.sip\.stack
+
+org\.ccil\.cowan\.tagsoup
+org\.ccil\.cowan\.tagsoup\.jaxp
+
+###################################################
+# framework.jar
+javax\.microedition\.khronos\.opengles
+javax\.microedition\.khronos\.egl
+
+android
+
+###################################################
+# apache-xml.jar
+org\.apache\.xml\.res
+org\.apache\.xml\.utils
+org\.apache\.xml\.utils\.res
+org\.apache\.xml\.dtm
+org\.apache\.xml\.dtm\.ref
+org\.apache\.xml\.dtm\.ref\.dom2dtm
+org\.apache\.xml\.dtm\.ref\.sax2dtm
+org\.apache\.xml\.serializer
+org\.apache\.xml\.serializer\.utils
+org\.apache\.xml\.serializer\.dom3
+org\.apache\.xpath
+org\.apache\.xpath\.operations
+org\.apache\.xpath\.domapi
+org\.apache\.xpath\.functions
+org\.apache\.xpath\.res
+org\.apache\.xpath\.axes
+org\.apache\.xpath\.objects
+org\.apache\.xpath\.patterns
+org\.apache\.xpath\.jaxp
+org\.apache\.xpath\.compiler
+org\.apache\.xalan
+org\.apache\.xalan\.res
+org\.apache\.xalan\.templates
+org\.apache\.xalan\.serialize
+org\.apache\.xalan\.extensions
+org\.apache\.xalan\.processor
+org\.apache\.xalan\.transformer
+org\.apache\.xalan\.xslt
+
+###################################################
+# Packages in the google namespace across all bootclasspath jars.
+com\.google\.android\..*
+com\.google\.vr\.platform.*
+com\.google\.i18n\.phonenumbers\..*
+com\.google\.i18n\.phonenumbers
+
+###################################################
+# Packages used for Android in Chrome OS
+org\.chromium\.arc
+org\.chromium\.arc\..*
diff --git a/scripts/construct_context.py b/scripts/construct_context.py
index 8717fe3..6f9edc4 100755
--- a/scripts/construct_context.py
+++ b/scripts/construct_context.py
@@ -29,41 +29,32 @@
parser = argparse.ArgumentParser()
parser.add_argument('--target-sdk-version', default='', dest='sdk',
help='specify target SDK version (as it appears in the manifest)')
- parser.add_argument('--host-classpath-for-sdk', dest='host_classpaths',
- action='append', nargs=2, metavar=('sdk','classpath'),
- help='specify classpath on host for a given SDK version or "any" version')
- parser.add_argument('--target-classpath-for-sdk', dest='target_classpaths',
- action='append', nargs=2, metavar=('sdk','classpath'),
- help='specify classpath on target for a given SDK version or "any" version')
+ parser.add_argument('--host-context-for-sdk', dest='host_contexts',
+ action='append', nargs=2, metavar=('sdk','context'),
+ help='specify context on host for a given SDK version or "any" version')
+ parser.add_argument('--target-context-for-sdk', dest='target_contexts',
+ action='append', nargs=2, metavar=('sdk','context'),
+ help='specify context on target for a given SDK version or "any" version')
return parser.parse_args(args)
-# The hidl.manager shared library has a dependency on hidl.base. We manually
-# add that information to the class loader context if we see those libraries.
-HIDL_MANAGER = 'android.hidl.manager-V1.0-java'
-HIDL_BASE = 'android.hidl.base-V1.0-java'
-
-# Special keyword that means that the classpath should be added to class loader
+# Special keyword that means that the context should be added to class loader
# context regardless of the target SDK version.
any_sdk = 'any'
-# We assume that the order of classpath arguments passed to this script is
+# We assume that the order of context arguments passed to this script is
# correct (matches the order computed by package manager). It is possible to
# sort them here, but Soong needs to use deterministic order anyway, so it can
# as well use the correct order.
-def construct_context(versioned_classpaths, target_sdk):
+def construct_context(versioned_contexts, target_sdk):
context = []
- for [sdk, classpath] in versioned_classpaths:
+ for [sdk, ctx] in versioned_contexts:
if sdk == any_sdk or compare_version_gt(sdk, target_sdk):
- for jar in classpath.split(':'):
- pcl = 'PCL[%s]' % jar
- if HIDL_MANAGER in jar:
- pcl += '{PCL[%s]}' % jar.replace(HIDL_MANAGER, HIDL_BASE, 1)
- context.append(pcl)
+ context.append(ctx)
return context
def construct_contexts(args):
- host_context = construct_context(args.host_classpaths, args.sdk)
- target_context = construct_context(args.target_classpaths, args.sdk)
+ host_context = construct_context(args.host_contexts, args.sdk)
+ target_context = construct_context(args.target_contexts, args.sdk)
context_sep = '#'
return ('class_loader_context_arg=--class-loader-context=PCL[]{%s} ; ' % context_sep.join(host_context) +
'stored_class_loader_context_arg=--stored-class-loader-context=PCL[]{%s}' % context_sep.join(target_context))
@@ -74,10 +65,10 @@
args = parse_args(sys.argv[1:])
if not args.sdk:
raise SystemExit('target sdk version is not set')
- if not args.host_classpaths:
- raise SystemExit('host classpath is not set')
- if not args.target_classpaths:
- raise SystemExit('target classpath is not set')
+ if not args.host_contexts:
+ raise SystemExit('host context is not set')
+ if not args.target_contexts:
+ raise SystemExit('target context is not set')
print(construct_contexts(args))
diff --git a/scripts/construct_context_test.py b/scripts/construct_context_test.py
index 0b0b0a3..3b05f90 100755
--- a/scripts/construct_context_test.py
+++ b/scripts/construct_context_test.py
@@ -27,53 +27,47 @@
args = cc.parse_args(arglist)
return cc.construct_contexts(args)
-classpaths = [
- '--host-classpath-for-sdk', '28', 'out/zdir/z.jar',
- '--target-classpath-for-sdk', '28', '/system/z.jar',
- '--host-classpath-for-sdk', '29', 'out/xdir/x.jar:out/ydir/y.jar',
- '--target-classpath-for-sdk', '29', '/system/x.jar:/product/y.jar',
- '--host-classpath-for-sdk', 'any', 'out/adir/a.jar:out/android.hidl.manager-V1.0-java.jar:out/bdir/b.jar',
- '--target-classpath-for-sdk', 'any', '/system/a.jar:/system/android.hidl.manager-V1.0-java.jar:/product/b.jar',
+contexts = [
+ '--host-context-for-sdk', '28', 'PCL[out/zdir/z.jar]',
+ '--target-context-for-sdk', '28', 'PCL[/system/z.jar]',
+ '--host-context-for-sdk', '29', 'PCL[out/xdir/x.jar]#PCL[out/ydir/y.jar]',
+ '--target-context-for-sdk', '29', 'PCL[/system/x.jar]#PCL[/product/y.jar]',
+ '--host-context-for-sdk', 'any', 'PCL[out/adir/a.jar]#PCL[out/bdir/b.jar]',
+ '--target-context-for-sdk', 'any', 'PCL[/system/a.jar]#PCL[/product/b.jar]',
]
class ConstructContextTest(unittest.TestCase):
def test_construct_context_28(self):
- args = ['--target-sdk-version', '28'] + classpaths
+ args = ['--target-sdk-version', '28'] + contexts
result = construct_contexts(args)
expect = ('class_loader_context_arg=--class-loader-context=PCL[]{PCL[out/xdir/x.jar]'
'#PCL[out/ydir/y.jar]'
'#PCL[out/adir/a.jar]'
- '#PCL[out/android.hidl.manager-V1.0-java.jar]{PCL[out/android.hidl.base-V1.0-java.jar]}'
'#PCL[out/bdir/b.jar]}'
' ; '
'stored_class_loader_context_arg=--stored-class-loader-context=PCL[]{PCL[/system/x.jar]'
'#PCL[/product/y.jar]'
'#PCL[/system/a.jar]'
- '#PCL[/system/android.hidl.manager-V1.0-java.jar]{PCL[/system/android.hidl.base-V1.0-java.jar]}'
'#PCL[/product/b.jar]}')
self.assertEqual(result, expect)
def test_construct_context_29(self):
- args = ['--target-sdk-version', '29'] + classpaths
+ args = ['--target-sdk-version', '29'] + contexts
result = construct_contexts(args)
expect = ('class_loader_context_arg=--class-loader-context=PCL[]{PCL[out/adir/a.jar]'
- '#PCL[out/android.hidl.manager-V1.0-java.jar]{PCL[out/android.hidl.base-V1.0-java.jar]}'
'#PCL[out/bdir/b.jar]}'
' ; '
'stored_class_loader_context_arg=--stored-class-loader-context=PCL[]{PCL[/system/a.jar]'
- '#PCL[/system/android.hidl.manager-V1.0-java.jar]{PCL[/system/android.hidl.base-V1.0-java.jar]}'
'#PCL[/product/b.jar]}')
self.assertEqual(result, expect)
def test_construct_context_S(self):
- args = ['--target-sdk-version', 'S'] + classpaths
+ args = ['--target-sdk-version', 'S'] + contexts
result = construct_contexts(args)
expect = ('class_loader_context_arg=--class-loader-context=PCL[]{PCL[out/adir/a.jar]'
- '#PCL[out/android.hidl.manager-V1.0-java.jar]{PCL[out/android.hidl.base-V1.0-java.jar]}'
'#PCL[out/bdir/b.jar]}'
' ; '
'stored_class_loader_context_arg=--stored-class-loader-context=PCL[]{PCL[/system/a.jar]'
- '#PCL[/system/android.hidl.manager-V1.0-java.jar]{PCL[/system/android.hidl.base-V1.0-java.jar]}'
'#PCL[/product/b.jar]}')
self.assertEqual(result, expect)
diff --git a/scripts/conv_linker_config.py b/scripts/conv_linker_config.py
new file mode 100644
index 0000000..81425fb
--- /dev/null
+++ b/scripts/conv_linker_config.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2020 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.
+""" A tool to convert json file into pb with linker config format."""
+
+import argparse
+import collections
+import json
+
+import linker_config_pb2
+from google.protobuf.json_format import ParseDict
+from google.protobuf.text_format import MessageToString
+
+
+def Proto(args):
+ json_content = ''
+ with open(args.source) as f:
+ for line in f:
+ if not line.lstrip().startswith('//'):
+ json_content += line
+ obj = json.loads(json_content, object_pairs_hook=collections.OrderedDict)
+ pb = ParseDict(obj, linker_config_pb2.LinkerConfig())
+ with open(args.output, 'wb') as f:
+ f.write(pb.SerializeToString())
+
+
+def Print(args):
+ with open(args.source, 'rb') as f:
+ pb = linker_config_pb2.LinkerConfig()
+ pb.ParseFromString(f.read())
+ print(MessageToString(pb))
+
+
+def GetArgParser():
+ parser = argparse.ArgumentParser()
+ subparsers = parser.add_subparsers()
+
+ parser_proto = subparsers.add_parser(
+ 'proto', help='Convert the input JSON configuration file into protobuf.')
+ parser_proto.add_argument(
+ '-s',
+ '--source',
+ required=True,
+ type=str,
+ help='Source linker configuration file in JSON.')
+ parser_proto.add_argument(
+ '-o',
+ '--output',
+ required=True,
+ type=str,
+ help='Target path to create protobuf file.')
+ parser_proto.set_defaults(func=Proto)
+
+ print_proto = subparsers.add_parser(
+ 'print', help='Print configuration in human-readable text format.')
+ print_proto.add_argument(
+ '-s',
+ '--source',
+ required=True,
+ type=str,
+ help='Source linker configuration file in protobuf.')
+ print_proto.set_defaults(func=Print)
+
+ return parser
+
+
+def main():
+ args = GetArgParser().parse_args()
+ args.func(args)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/update-apex-allowed-deps.sh b/scripts/update-apex-allowed-deps.sh
new file mode 100755
index 0000000..872d746
--- /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}"
diff --git a/sdk/bp.go b/sdk/bp.go
index 68fe7ab..11ec8c6 100644
--- a/sdk/bp.go
+++ b/sdk/bp.go
@@ -16,6 +16,8 @@
import (
"fmt"
+ "reflect"
+ "strings"
"android/soong/android"
)
@@ -33,7 +35,82 @@
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) 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 c630c25..e1edc51 100644
--- a/sdk/bp_test.go
+++ b/sdk/bp_test.go
@@ -18,8 +18,142 @@
"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 8c9e228..b1eebe9 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -108,6 +108,8 @@
cc_prebuilt_library_shared {
name: "mysdk_sdkmember@current",
sdk_member_name: "sdkmember",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
host_supported: true,
installable: false,
stl: "none",
@@ -119,10 +121,8 @@
android_arm64: {
srcs: ["android/arm64/lib/sdkmember.so"],
},
- linux_glibc: {
- enabled: true,
- },
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["linux_glibc/x86_64/lib/sdkmember.so"],
},
},
@@ -131,6 +131,8 @@
cc_prebuilt_library_shared {
name: "sdkmember",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
host_supported: true,
stl: "none",
compile_multilib: "64",
@@ -141,10 +143,8 @@
android_arm64: {
srcs: ["android/arm64/lib/sdkmember.so"],
},
- linux_glibc: {
- enabled: true,
- },
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["linux_glibc/x86_64/lib/sdkmember.so"],
},
},
@@ -152,6 +152,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
host_supported: true,
native_shared_libs: ["mysdk_sdkmember@current"],
compile_multilib: "64",
@@ -159,7 +160,7 @@
host: {
enabled: false,
},
- linux_glibc: {
+ linux_glibc_x86_64: {
enabled: true,
},
},
@@ -353,6 +354,8 @@
cc_prebuilt_object {
name: "mysdk_crtobj@current",
sdk_member_name: "crtobj",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
stl: "none",
compile_multilib: "both",
sanitize: {
@@ -371,6 +374,8 @@
cc_prebuilt_object {
name: "crtobj",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
stl: "none",
compile_multilib: "both",
sanitize: {
@@ -388,6 +393,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
native_objects: ["mysdk_crtobj@current"],
}
`),
@@ -435,8 +441,10 @@
)
}
-// 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,17 @@
"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: {
+ integer_overflow: false,
+ },
},
},
stl: "none",
@@ -467,17 +483,31 @@
cc_prebuilt_library_shared {
name: "mysdk_mynativelib@current",
sdk_member_name: "mynativelib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
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: {
+ integer_overflow: false,
+ },
},
arm: {
srcs: ["arm/lib/mynativelib.so"],
+ sanitize: {
+ integer_overflow: true,
+ },
},
},
}
@@ -485,22 +515,37 @@
cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
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: {
+ 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"],
}
`),
@@ -535,6 +580,8 @@
cc_prebuilt_binary {
name: "mymodule_exports_mynativebinary@current",
sdk_member_name: "mynativebinary",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
installable: false,
compile_multilib: "both",
arch: {
@@ -550,6 +597,8 @@
cc_prebuilt_binary {
name: "mynativebinary",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
compile_multilib: "both",
arch: {
arm64: {
@@ -563,6 +612,7 @@
module_exports_snapshot {
name: "mymodule_exports@current",
+ visibility: ["//visibility:public"],
native_binaries: ["mymodule_exports_mynativebinary@current"],
}
`),
@@ -611,6 +661,8 @@
cc_prebuilt_binary {
name: "myexports_mynativebinary@current",
sdk_member_name: "mynativebinary",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
installable: false,
@@ -620,20 +672,21 @@
enabled: false,
},
linux_glibc: {
- enabled: true,
compile_multilib: "both",
},
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["linux_glibc/x86_64/bin/mynativebinary"],
},
linux_glibc_x86: {
+ enabled: true,
srcs: ["linux_glibc/x86/bin/mynativebinary"],
},
windows: {
- enabled: true,
compile_multilib: "64",
},
windows_x86_64: {
+ enabled: true,
srcs: ["windows/x86_64/bin/mynativebinary.exe"],
},
},
@@ -642,6 +695,8 @@
cc_prebuilt_binary {
name: "mynativebinary",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
stl: "none",
@@ -650,20 +705,21 @@
enabled: false,
},
linux_glibc: {
- enabled: true,
compile_multilib: "both",
},
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["linux_glibc/x86_64/bin/mynativebinary"],
},
linux_glibc_x86: {
+ enabled: true,
srcs: ["linux_glibc/x86/bin/mynativebinary"],
},
windows: {
- enabled: true,
compile_multilib: "64",
},
windows_x86_64: {
+ enabled: true,
srcs: ["windows/x86_64/bin/mynativebinary.exe"],
},
},
@@ -671,19 +727,25 @@
module_exports_snapshot {
name: "myexports@current",
+ visibility: ["//visibility:public"],
device_supported: false,
host_supported: true,
native_binaries: ["myexports_mynativebinary@current"],
target: {
+ windows: {
+ compile_multilib: "64",
+ },
host: {
enabled: false,
},
- linux_glibc: {
+ linux_glibc_x86_64: {
enabled: true,
},
- windows: {
+ linux_glibc_x86: {
enabled: true,
- compile_multilib: "64",
+ },
+ windows_x86_64: {
+ enabled: true,
},
},
}
@@ -749,6 +811,8 @@
cc_prebuilt_binary {
name: "myexports_mynativebinary@current",
sdk_member_name: "mynativebinary",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
installable: false,
@@ -758,10 +822,8 @@
host: {
enabled: false,
},
- linux_bionic: {
- enabled: true,
- },
linux_bionic_x86_64: {
+ enabled: true,
srcs: ["x86_64/bin/mynativebinary"],
},
},
@@ -770,6 +832,8 @@
cc_prebuilt_binary {
name: "mynativebinary",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
stl: "none",
@@ -778,10 +842,8 @@
host: {
enabled: false,
},
- linux_bionic: {
- enabled: true,
- },
linux_bionic_x86_64: {
+ enabled: true,
srcs: ["x86_64/bin/mynativebinary"],
},
},
@@ -790,6 +852,8 @@
cc_prebuilt_library_shared {
name: "myexports_mynativelib@current",
sdk_member_name: "mynativelib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
installable: false,
@@ -799,10 +863,8 @@
host: {
enabled: false,
},
- linux_bionic: {
- enabled: true,
- },
linux_bionic_x86_64: {
+ enabled: true,
srcs: ["x86_64/lib/mynativelib.so"],
},
},
@@ -811,6 +873,8 @@
cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
stl: "none",
@@ -819,10 +883,8 @@
host: {
enabled: false,
},
- linux_bionic: {
- enabled: true,
- },
linux_bionic_x86_64: {
+ enabled: true,
srcs: ["x86_64/lib/mynativelib.so"],
},
},
@@ -830,6 +892,7 @@
module_exports_snapshot {
name: "myexports@current",
+ visibility: ["//visibility:public"],
device_supported: false,
host_supported: true,
native_binaries: ["myexports_mynativebinary@current"],
@@ -839,7 +902,7 @@
host: {
enabled: false,
},
- linux_bionic: {
+ linux_bionic_x86_64: {
enabled: true,
},
},
@@ -883,6 +946,8 @@
cc_prebuilt_binary {
name: "mymodule_exports_linker@current",
sdk_member_name: "linker",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
installable: false,
@@ -894,13 +959,12 @@
host: {
enabled: false,
},
- linux_glibc: {
- enabled: true,
- },
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["x86_64/bin/linker"],
},
linux_glibc_x86: {
+ enabled: true,
srcs: ["x86/bin/linker"],
},
},
@@ -909,6 +973,8 @@
cc_prebuilt_binary {
name: "linker",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
stl: "none",
@@ -919,13 +985,12 @@
host: {
enabled: false,
},
- linux_glibc: {
- enabled: true,
- },
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["x86_64/bin/linker"],
},
linux_glibc_x86: {
+ enabled: true,
srcs: ["x86/bin/linker"],
},
},
@@ -933,6 +998,7 @@
module_exports_snapshot {
name: "mymodule_exports@current",
+ visibility: ["//visibility:public"],
device_supported: false,
host_supported: true,
native_binaries: ["mymodule_exports_linker@current"],
@@ -940,7 +1006,10 @@
host: {
enabled: false,
},
- linux_glibc: {
+ linux_glibc_x86_64: {
+ enabled: true,
+ },
+ linux_glibc_x86: {
enabled: true,
},
},
@@ -982,6 +1051,7 @@
cc_prebuilt_library_shared {
name: "mysdk_mynativelib@current",
sdk_member_name: "mynativelib",
+ visibility: ["//visibility:public"],
apex_available: [
"apex1",
"apex2",
@@ -1005,6 +1075,7 @@
cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
+ visibility: ["//visibility:public"],
apex_available: [
"apex1",
"apex2",
@@ -1026,6 +1097,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
native_shared_libs: ["mysdk_mynativelib@current"],
}
`),
@@ -1110,6 +1182,8 @@
cc_prebuilt_library_shared {
name: "mysdk_mynativelib@current",
sdk_member_name: "mynativelib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
installable: false,
stl: "none",
compile_multilib: "both",
@@ -1130,6 +1204,8 @@
cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
stl: "none",
compile_multilib: "both",
shared_libs: [
@@ -1149,6 +1225,8 @@
cc_prebuilt_library_shared {
name: "mysdk_myothernativelib@current",
sdk_member_name: "myothernativelib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
installable: false,
stl: "none",
compile_multilib: "both",
@@ -1166,6 +1244,8 @@
cc_prebuilt_library_shared {
name: "myothernativelib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
stl: "none",
compile_multilib: "both",
system_shared_libs: ["libm"],
@@ -1182,6 +1262,8 @@
cc_prebuilt_library_shared {
name: "mysdk_mysystemnativelib@current",
sdk_member_name: "mysystemnativelib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
installable: false,
stl: "none",
compile_multilib: "both",
@@ -1198,6 +1280,8 @@
cc_prebuilt_library_shared {
name: "mysystemnativelib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
stl: "none",
compile_multilib: "both",
arch: {
@@ -1212,6 +1296,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
native_shared_libs: [
"mysdk_mynativelib@current",
"mysdk_myothernativelib@current",
@@ -1263,6 +1348,8 @@
cc_prebuilt_library_shared {
name: "mysdk_mynativelib@current",
sdk_member_name: "mynativelib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
installable: false,
@@ -1274,14 +1361,13 @@
host: {
enabled: false,
},
- linux_glibc: {
- enabled: true,
- },
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["x86_64/lib/mynativelib.so"],
export_include_dirs: ["x86_64/include_gen/mynativelib"],
},
linux_glibc_x86: {
+ enabled: true,
srcs: ["x86/lib/mynativelib.so"],
export_include_dirs: ["x86/include_gen/mynativelib"],
},
@@ -1291,6 +1377,8 @@
cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
sdk_version: "minimum",
@@ -1301,14 +1389,13 @@
host: {
enabled: false,
},
- linux_glibc: {
- enabled: true,
- },
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["x86_64/lib/mynativelib.so"],
export_include_dirs: ["x86_64/include_gen/mynativelib"],
},
linux_glibc_x86: {
+ enabled: true,
srcs: ["x86/lib/mynativelib.so"],
export_include_dirs: ["x86/include_gen/mynativelib"],
},
@@ -1317,6 +1404,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
device_supported: false,
host_supported: true,
native_shared_libs: ["mysdk_mynativelib@current"],
@@ -1324,7 +1412,10 @@
host: {
enabled: false,
},
- linux_glibc: {
+ linux_glibc_x86_64: {
+ enabled: true,
+ },
+ linux_glibc_x86: {
enabled: true,
},
},
@@ -1381,6 +1472,8 @@
cc_prebuilt_library_shared {
name: "mysdk_mynativelib@current",
sdk_member_name: "mynativelib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
installable: false,
@@ -1390,20 +1483,21 @@
enabled: false,
},
linux_glibc: {
- enabled: true,
compile_multilib: "both",
},
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["linux_glibc/x86_64/lib/mynativelib.so"],
},
linux_glibc_x86: {
+ enabled: true,
srcs: ["linux_glibc/x86/lib/mynativelib.so"],
},
windows: {
- enabled: true,
compile_multilib: "64",
},
windows_x86_64: {
+ enabled: true,
srcs: ["windows/x86_64/lib/mynativelib.dll"],
},
},
@@ -1412,6 +1506,8 @@
cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
stl: "none",
@@ -1420,20 +1516,21 @@
enabled: false,
},
linux_glibc: {
- enabled: true,
compile_multilib: "both",
},
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["linux_glibc/x86_64/lib/mynativelib.so"],
},
linux_glibc_x86: {
+ enabled: true,
srcs: ["linux_glibc/x86/lib/mynativelib.so"],
},
windows: {
- enabled: true,
compile_multilib: "64",
},
windows_x86_64: {
+ enabled: true,
srcs: ["windows/x86_64/lib/mynativelib.dll"],
},
},
@@ -1441,19 +1538,25 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
device_supported: false,
host_supported: true,
native_shared_libs: ["mysdk_mynativelib@current"],
target: {
+ windows: {
+ compile_multilib: "64",
+ },
host: {
enabled: false,
},
- linux_glibc: {
+ linux_glibc_x86_64: {
enabled: true,
},
- windows: {
+ linux_glibc_x86: {
enabled: true,
- compile_multilib: "64",
+ },
+ windows_x86_64: {
+ enabled: true,
},
},
}
@@ -1494,6 +1597,8 @@
cc_prebuilt_library_static {
name: "myexports_mynativelib@current",
sdk_member_name: "mynativelib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
installable: false,
stl: "none",
compile_multilib: "both",
@@ -1513,6 +1618,8 @@
cc_prebuilt_library_static {
name: "mynativelib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
stl: "none",
compile_multilib: "both",
export_include_dirs: ["include/include"],
@@ -1530,6 +1637,7 @@
module_exports_snapshot {
name: "myexports@current",
+ visibility: ["//visibility:public"],
native_static_libs: ["myexports_mynativelib@current"],
}
`),
@@ -1579,6 +1687,8 @@
cc_prebuilt_library_static {
name: "myexports_mynativelib@current",
sdk_member_name: "mynativelib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
installable: false,
@@ -1589,14 +1699,13 @@
host: {
enabled: false,
},
- linux_glibc: {
- enabled: true,
- },
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["x86_64/lib/mynativelib.a"],
export_include_dirs: ["x86_64/include_gen/mynativelib"],
},
linux_glibc_x86: {
+ enabled: true,
srcs: ["x86/lib/mynativelib.a"],
export_include_dirs: ["x86/include_gen/mynativelib"],
},
@@ -1606,6 +1715,8 @@
cc_prebuilt_library_static {
name: "mynativelib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
stl: "none",
@@ -1615,14 +1726,13 @@
host: {
enabled: false,
},
- linux_glibc: {
- enabled: true,
- },
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["x86_64/lib/mynativelib.a"],
export_include_dirs: ["x86_64/include_gen/mynativelib"],
},
linux_glibc_x86: {
+ enabled: true,
srcs: ["x86/lib/mynativelib.a"],
export_include_dirs: ["x86/include_gen/mynativelib"],
},
@@ -1631,6 +1741,7 @@
module_exports_snapshot {
name: "myexports@current",
+ visibility: ["//visibility:public"],
device_supported: false,
host_supported: true,
native_static_libs: ["myexports_mynativelib@current"],
@@ -1638,7 +1749,10 @@
host: {
enabled: false,
},
- linux_glibc: {
+ linux_glibc_x86_64: {
+ enabled: true,
+ },
+ linux_glibc_x86: {
enabled: true,
},
},
@@ -1684,6 +1798,8 @@
cc_prebuilt_library {
name: "myexports_mynativelib@current",
sdk_member_name: "mynativelib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
installable: false,
recovery_available: true,
vendor_available: true,
@@ -1713,6 +1829,8 @@
cc_prebuilt_library {
name: "mynativelib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
recovery_available: true,
vendor_available: true,
stl: "none",
@@ -1740,6 +1858,7 @@
module_exports_snapshot {
name: "myexports@current",
+ visibility: ["//visibility:public"],
native_libs: ["myexports_mynativelib@current"],
}
`),
@@ -1789,6 +1908,8 @@
cc_prebuilt_library_static {
name: "myexports_mynativelib@current",
sdk_member_name: "mynativelib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
installable: false,
@@ -1799,10 +1920,8 @@
host: {
enabled: false,
},
- linux_glibc: {
- enabled: true,
- },
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["x86_64/lib/mynativelib.a"],
export_include_dirs: ["x86_64/include_gen/mynativelib"],
},
@@ -1812,6 +1931,8 @@
cc_prebuilt_library_static {
name: "mynativelib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
stl: "none",
@@ -1821,10 +1942,8 @@
host: {
enabled: false,
},
- linux_glibc: {
- enabled: true,
- },
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["x86_64/lib/mynativelib.a"],
export_include_dirs: ["x86_64/include_gen/mynativelib"],
},
@@ -1833,6 +1952,7 @@
module_exports_snapshot {
name: "myexports@current",
+ visibility: ["//visibility:public"],
device_supported: false,
host_supported: true,
native_static_libs: ["myexports_mynativelib@current"],
@@ -1841,7 +1961,7 @@
host: {
enabled: false,
},
- linux_glibc: {
+ linux_glibc_x86_64: {
enabled: true,
},
},
@@ -1877,6 +1997,8 @@
cc_prebuilt_library_headers {
name: "mysdk_mynativeheaders@current",
sdk_member_name: "mynativeheaders",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
stl: "none",
compile_multilib: "both",
export_include_dirs: ["include/include"],
@@ -1885,6 +2007,8 @@
cc_prebuilt_library_headers {
name: "mynativeheaders",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
stl: "none",
compile_multilib: "both",
export_include_dirs: ["include/include"],
@@ -1892,6 +2016,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
native_header_libs: ["mysdk_mynativeheaders@current"],
}
`),
@@ -1926,6 +2051,8 @@
cc_prebuilt_library_headers {
name: "mysdk_mynativeheaders@current",
sdk_member_name: "mynativeheaders",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
stl: "none",
@@ -1935,7 +2062,10 @@
host: {
enabled: false,
},
- linux_glibc: {
+ linux_glibc_x86_64: {
+ enabled: true,
+ },
+ linux_glibc_x86: {
enabled: true,
},
},
@@ -1944,6 +2074,8 @@
cc_prebuilt_library_headers {
name: "mynativeheaders",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
stl: "none",
@@ -1953,7 +2085,10 @@
host: {
enabled: false,
},
- linux_glibc: {
+ linux_glibc_x86_64: {
+ enabled: true,
+ },
+ linux_glibc_x86: {
enabled: true,
},
},
@@ -1961,6 +2096,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
device_supported: false,
host_supported: true,
native_header_libs: ["mysdk_mynativeheaders@current"],
@@ -1968,7 +2104,10 @@
host: {
enabled: false,
},
- linux_glibc: {
+ linux_glibc_x86_64: {
+ enabled: true,
+ },
+ linux_glibc_x86: {
enabled: true,
},
},
@@ -2011,6 +2150,8 @@
cc_prebuilt_library_headers {
name: "mysdk_mynativeheaders@current",
sdk_member_name: "mynativeheaders",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
host_supported: true,
stl: "none",
compile_multilib: "both",
@@ -2023,15 +2164,22 @@
export_include_dirs: ["android/include/include-android"],
},
linux_glibc: {
- enabled: true,
export_include_dirs: ["linux_glibc/include/include-host"],
},
+ linux_glibc_x86_64: {
+ enabled: true,
+ },
+ linux_glibc_x86: {
+ enabled: true,
+ },
},
}
cc_prebuilt_library_headers {
name: "mynativeheaders",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
host_supported: true,
stl: "none",
compile_multilib: "both",
@@ -2044,21 +2192,30 @@
export_include_dirs: ["android/include/include-android"],
},
linux_glibc: {
- enabled: true,
export_include_dirs: ["linux_glibc/include/include-host"],
},
+ linux_glibc_x86_64: {
+ enabled: true,
+ },
+ linux_glibc_x86: {
+ enabled: true,
+ },
},
}
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
host_supported: true,
native_header_libs: ["mysdk_mynativeheaders@current"],
target: {
host: {
enabled: false,
},
- linux_glibc: {
+ linux_glibc_x86_64: {
+ enabled: true,
+ },
+ linux_glibc_x86: {
enabled: true,
},
},
@@ -2102,6 +2259,8 @@
cc_prebuilt_library_shared {
name: "mysdk_sslnil@current",
sdk_member_name: "sslnil",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
installable: false,
compile_multilib: "both",
arch: {
@@ -2117,6 +2276,8 @@
cc_prebuilt_library_shared {
name: "sslnil",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
compile_multilib: "both",
arch: {
arm64: {
@@ -2131,6 +2292,8 @@
cc_prebuilt_library_shared {
name: "mysdk_sslempty@current",
sdk_member_name: "sslempty",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
installable: false,
compile_multilib: "both",
system_shared_libs: [],
@@ -2147,6 +2310,8 @@
cc_prebuilt_library_shared {
name: "sslempty",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
compile_multilib: "both",
system_shared_libs: [],
arch: {
@@ -2162,6 +2327,8 @@
cc_prebuilt_library_shared {
name: "mysdk_sslnonempty@current",
sdk_member_name: "sslnonempty",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
installable: false,
compile_multilib: "both",
system_shared_libs: ["mysdk_sslnil@current"],
@@ -2178,6 +2345,8 @@
cc_prebuilt_library_shared {
name: "sslnonempty",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
compile_multilib: "both",
system_shared_libs: ["sslnil"],
arch: {
@@ -2192,6 +2361,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
native_shared_libs: [
"mysdk_sslnil@current",
"mysdk_sslempty@current",
@@ -2225,6 +2395,8 @@
cc_prebuilt_library_shared {
name: "mysdk_sslvariants@current",
sdk_member_name: "sslvariants",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
host_supported: true,
installable: false,
compile_multilib: "both",
@@ -2241,13 +2413,12 @@
android_arm: {
srcs: ["android/arm/lib/sslvariants.so"],
},
- linux_glibc: {
- enabled: true,
- },
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["linux_glibc/x86_64/lib/sslvariants.so"],
},
linux_glibc_x86: {
+ enabled: true,
srcs: ["linux_glibc/x86/lib/sslvariants.so"],
},
},
@@ -2256,6 +2427,8 @@
cc_prebuilt_library_shared {
name: "sslvariants",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
host_supported: true,
compile_multilib: "both",
target: {
@@ -2271,13 +2444,12 @@
android_arm: {
srcs: ["android/arm/lib/sslvariants.so"],
},
- linux_glibc: {
- enabled: true,
- },
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["linux_glibc/x86_64/lib/sslvariants.so"],
},
linux_glibc_x86: {
+ enabled: true,
srcs: ["linux_glibc/x86/lib/sslvariants.so"],
},
},
@@ -2285,13 +2457,17 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
host_supported: true,
native_shared_libs: ["mysdk_sslvariants@current"],
target: {
host: {
enabled: false,
},
- linux_glibc: {
+ linux_glibc_x86_64: {
+ enabled: true,
+ },
+ linux_glibc_x86: {
enabled: true,
},
},
@@ -2327,10 +2503,16 @@
cc_prebuilt_library_shared {
name: "mysdk_stubslib@current",
sdk_member_name: "stubslib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
installable: false,
compile_multilib: "both",
stubs: {
- versions: ["3"],
+ versions: [
+ "1",
+ "2",
+ "3",
+ ],
},
arch: {
arm64: {
@@ -2345,9 +2527,15 @@
cc_prebuilt_library_shared {
name: "stubslib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
compile_multilib: "both",
stubs: {
- versions: ["3"],
+ versions: [
+ "1",
+ "2",
+ "3",
+ ],
},
arch: {
arm64: {
@@ -2361,6 +2549,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
native_shared_libs: ["mysdk_stubslib@current"],
}
`))
@@ -2397,11 +2586,17 @@
cc_prebuilt_library_shared {
name: "mysdk_stubslib@current",
sdk_member_name: "stubslib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
host_supported: true,
installable: false,
compile_multilib: "both",
stubs: {
- versions: ["3"],
+ versions: [
+ "1",
+ "2",
+ "3",
+ ],
},
target: {
host: {
@@ -2413,13 +2608,12 @@
android_arm: {
srcs: ["android/arm/lib/stubslib.so"],
},
- linux_glibc: {
- enabled: true,
- },
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["linux_glibc/x86_64/lib/stubslib.so"],
},
linux_glibc_x86: {
+ enabled: true,
srcs: ["linux_glibc/x86/lib/stubslib.so"],
},
},
@@ -2428,10 +2622,16 @@
cc_prebuilt_library_shared {
name: "stubslib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
host_supported: true,
compile_multilib: "both",
stubs: {
- versions: ["3"],
+ versions: [
+ "1",
+ "2",
+ "3",
+ ],
},
target: {
host: {
@@ -2443,13 +2643,12 @@
android_arm: {
srcs: ["android/arm/lib/stubslib.so"],
},
- linux_glibc: {
- enabled: true,
- },
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["linux_glibc/x86_64/lib/stubslib.so"],
},
linux_glibc_x86: {
+ enabled: true,
srcs: ["linux_glibc/x86/lib/stubslib.so"],
},
},
@@ -2457,13 +2656,17 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
host_supported: true,
native_shared_libs: ["mysdk_stubslib@current"],
target: {
host: {
enabled: false,
},
- linux_glibc: {
+ linux_glibc_x86_64: {
+ enabled: true,
+ },
+ linux_glibc_x86: {
enabled: true,
},
},
@@ -2493,6 +2696,8 @@
cc_prebuilt_library_shared {
name: "mysdk_mylib@current",
sdk_member_name: "mylib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
host_supported: true,
installable: false,
unique_host_soname: true,
@@ -2507,13 +2712,12 @@
android_arm: {
srcs: ["android/arm/lib/mylib.so"],
},
- linux_glibc: {
- enabled: true,
- },
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["linux_glibc/x86_64/lib/mylib-host.so"],
},
linux_glibc_x86: {
+ enabled: true,
srcs: ["linux_glibc/x86/lib/mylib-host.so"],
},
},
@@ -2522,6 +2726,8 @@
cc_prebuilt_library_shared {
name: "mylib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
host_supported: true,
unique_host_soname: true,
compile_multilib: "both",
@@ -2535,13 +2741,12 @@
android_arm: {
srcs: ["android/arm/lib/mylib.so"],
},
- linux_glibc: {
- enabled: true,
- },
linux_glibc_x86_64: {
+ enabled: true,
srcs: ["linux_glibc/x86_64/lib/mylib-host.so"],
},
linux_glibc_x86: {
+ enabled: true,
srcs: ["linux_glibc/x86/lib/mylib-host.so"],
},
},
@@ -2549,13 +2754,17 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
host_supported: true,
native_shared_libs: ["mysdk_mylib@current"],
target: {
host: {
enabled: false,
},
- linux_glibc: {
+ linux_glibc_x86_64: {
+ enabled: true,
+ },
+ linux_glibc_x86: {
enabled: true,
},
},
@@ -2569,3 +2778,77 @@
`),
)
}
+
+func TestNoSanitizerMembers(t *testing.T) {
+ result := testSdkWithCc(t, `
+ sdk {
+ name: "mysdk",
+ native_shared_libs: ["mynativelib"],
+ }
+
+ cc_library_shared {
+ name: "mynativelib",
+ srcs: ["Test.cpp"],
+ export_include_dirs: ["include"],
+ arch: {
+ arm64: {
+ export_system_include_dirs: ["arm64/include"],
+ sanitize: {
+ hwaddress: true,
+ },
+ },
+ },
+ }
+ `)
+
+ result.CheckSnapshot("mysdk", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_library_shared {
+ name: "mysdk_mynativelib@current",
+ sdk_member_name: "mynativelib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ installable: false,
+ compile_multilib: "both",
+ export_include_dirs: ["include/include"],
+ arch: {
+ arm64: {
+ export_system_include_dirs: ["arm64/include/arm64/include"],
+ },
+ arm: {
+ srcs: ["arm/lib/mynativelib.so"],
+ },
+ },
+}
+
+cc_prebuilt_library_shared {
+ name: "mynativelib",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ compile_multilib: "both",
+ export_include_dirs: ["include/include"],
+ arch: {
+ arm64: {
+ export_system_include_dirs: ["arm64/include/arm64/include"],
+ },
+ arm: {
+ srcs: ["arm/lib/mynativelib.so"],
+ },
+ },
+}
+
+sdk_snapshot {
+ name: "mysdk@current",
+ visibility: ["//visibility:public"],
+ native_shared_libs: ["mysdk_mynativelib@current"],
+}
+`),
+ checkAllCopyRules(`
+include/Test.h -> include/include/Test.h
+arm64/include/Arm64Test.h -> arm64/include/arm64/include/Arm64Test.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so`),
+ )
+}
diff --git a/sdk/exports_test.go b/sdk/exports_test.go
index 20e2521..1c59244 100644
--- a/sdk/exports_test.go
+++ b/sdk/exports_test.go
@@ -49,17 +49,22 @@
java_import {
name: "myexports_myjavalib@current",
sdk_member_name: "myjavalib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
jars: ["java/myjavalib.jar"],
}
java_import {
name: "myjavalib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
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 a7ee8d1..ec8ebb3 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -43,6 +43,7 @@
"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,22 @@
java_import {
name: "mysdk_sdkmember@current",
sdk_member_name: "sdkmember",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
jars: ["java/sdkmember.jar"],
}
java_import {
name: "sdkmember",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
jars: ["java/sdkmember.jar"],
}
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
java_header_libs: ["mysdk_sdkmember@current"],
}
`))
@@ -242,17 +248,22 @@
java_import {
name: "mysdk_myjavalib@current",
sdk_member_name: "myjavalib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
jars: ["java/myjavalib.jar"],
}
java_import {
name: "myjavalib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
jars: ["java/myjavalib.jar"],
}
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
java_header_libs: ["mysdk_myjavalib@current"],
}
@@ -294,6 +305,8 @@
java_import {
name: "mysdk_myjavalib@current",
sdk_member_name: "myjavalib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
jars: ["java/myjavalib.jar"],
@@ -302,6 +315,8 @@
java_import {
name: "myjavalib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
jars: ["java/myjavalib.jar"],
@@ -309,6 +324,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
device_supported: false,
host_supported: true,
java_header_libs: ["mysdk_myjavalib@current"],
@@ -346,6 +362,8 @@
java_import {
name: "mysdk_myjavalib@current",
sdk_member_name: "myjavalib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
host_supported: true,
target: {
android: {
@@ -360,6 +378,8 @@
java_import {
name: "myjavalib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
host_supported: true,
target: {
android: {
@@ -373,6 +393,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
host_supported: true,
java_header_libs: ["mysdk_myjavalib@current"],
}
@@ -412,17 +433,22 @@
java_import {
name: "myexports_myjavalib@current",
sdk_member_name: "myjavalib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
jars: ["java/myjavalib.jar"],
}
java_import {
name: "myjavalib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
jars: ["java/myjavalib.jar"],
}
module_exports_snapshot {
name: "myexports@current",
+ visibility: ["//visibility:public"],
java_libs: ["myexports_myjavalib@current"],
}
@@ -464,6 +490,8 @@
java_import {
name: "myexports_myjavalib@current",
sdk_member_name: "myjavalib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
jars: ["java/myjavalib.jar"],
@@ -472,6 +500,8 @@
java_import {
name: "myjavalib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
jars: ["java/myjavalib.jar"],
@@ -479,6 +509,7 @@
module_exports_snapshot {
name: "myexports@current",
+ visibility: ["//visibility:public"],
device_supported: false,
host_supported: true,
java_libs: ["myexports_myjavalib@current"],
@@ -515,6 +546,8 @@
java_test_import {
name: "myexports_myjavatests@current",
sdk_member_name: "myjavatests",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
jars: ["java/myjavatests.jar"],
test_config: "java/myjavatests-AndroidTest.xml",
}
@@ -522,12 +555,15 @@
java_test_import {
name: "myjavatests",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
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 +601,8 @@
java_test_import {
name: "myexports_myjavatests@current",
sdk_member_name: "myjavatests",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
jars: ["java/myjavatests.jar"],
@@ -574,6 +612,8 @@
java_test_import {
name: "myjavatests",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
jars: ["java/myjavatests.jar"],
@@ -582,6 +622,7 @@
module_exports_snapshot {
name: "myexports@current",
+ visibility: ["//visibility:public"],
device_supported: false,
host_supported: true,
java_tests: ["myexports_myjavatests@current"],
@@ -594,142 +635,6 @@
)
}
-func testSdkWithDroidstubs(t *testing.T, bp string) *testSdkResult {
- t.Helper()
-
- fs := map[string][]byte{
- "foo/bar/Foo.java": nil,
- "stubs-sources/foo/bar/Foo.java": nil,
- }
- return testSdkWithFs(t, bp, fs)
-}
-
-// Note: This test does not verify that a droidstubs can be referenced, either
-// directly or indirectly from an APEX as droidstubs can never be a part of an
-// apex.
-func TestBasicSdkWithDroidstubs(t *testing.T) {
- testSdkWithDroidstubs(t, `
- sdk {
- name: "mysdk",
- stubs_sources: ["mystub"],
- }
- sdk_snapshot {
- name: "mysdk@10",
- stubs_sources: ["mystub_mysdk@10"],
- }
- prebuilt_stubs_sources {
- name: "mystub_mysdk@10",
- sdk_member_name: "mystub",
- srcs: ["stubs-sources/foo/bar/Foo.java"],
- }
- droidstubs {
- name: "mystub",
- srcs: ["foo/bar/Foo.java"],
- sdk_version: "none",
- system_modules: "none",
- }
- java_library {
- name: "myjavalib",
- srcs: [":mystub"],
- sdk_version: "none",
- system_modules: "none",
- }
- `)
-}
-
-func TestSnapshotWithDroidstubs(t *testing.T) {
- result := testSdkWithDroidstubs(t, `
- module_exports {
- name: "myexports",
- stubs_sources: ["myjavaapistubs"],
- }
-
- droidstubs {
- name: "myjavaapistubs",
- srcs: ["foo/bar/Foo.java"],
- system_modules: "none",
- sdk_version: "none",
- }
- `)
-
- result.CheckSnapshot("myexports", "",
- checkAndroidBpContents(`
-// This is auto-generated. DO NOT EDIT.
-
-prebuilt_stubs_sources {
- name: "myexports_myjavaapistubs@current",
- sdk_member_name: "myjavaapistubs",
- srcs: ["java/myjavaapistubs_stubs_sources"],
-}
-
-prebuilt_stubs_sources {
- name: "myjavaapistubs",
- prefer: false,
- srcs: ["java/myjavaapistubs_stubs_sources"],
-}
-
-module_exports_snapshot {
- name: "myexports@current",
- stubs_sources: ["myexports_myjavaapistubs@current"],
-}
-
-`),
- checkAllCopyRules(""),
- checkMergeZips(".intermediates/myexports/common_os/tmp/java/myjavaapistubs_stubs_sources.zip"),
- )
-}
-
-func TestHostSnapshotWithDroidstubs(t *testing.T) {
- result := testSdkWithDroidstubs(t, `
- module_exports {
- name: "myexports",
- device_supported: false,
- host_supported: true,
- stubs_sources: ["myjavaapistubs"],
- }
-
- droidstubs {
- name: "myjavaapistubs",
- device_supported: false,
- host_supported: true,
- srcs: ["foo/bar/Foo.java"],
- system_modules: "none",
- sdk_version: "none",
- }
- `)
-
- result.CheckSnapshot("myexports", "",
- checkAndroidBpContents(`
-// This is auto-generated. DO NOT EDIT.
-
-prebuilt_stubs_sources {
- name: "myexports_myjavaapistubs@current",
- sdk_member_name: "myjavaapistubs",
- device_supported: false,
- host_supported: true,
- srcs: ["java/myjavaapistubs_stubs_sources"],
-}
-
-prebuilt_stubs_sources {
- name: "myjavaapistubs",
- prefer: false,
- device_supported: false,
- host_supported: true,
- srcs: ["java/myjavaapistubs_stubs_sources"],
-}
-
-module_exports_snapshot {
- name: "myexports@current",
- device_supported: false,
- host_supported: true,
- stubs_sources: ["myexports_myjavaapistubs@current"],
-}
-`),
- checkAllCopyRules(""),
- checkMergeZips(".intermediates/myexports/common_os/tmp/java/myjavaapistubs_stubs_sources.zip"),
- )
-}
-
func TestSnapshotWithJavaSystemModules(t *testing.T) {
result := testSdkWithJava(t, `
sdk {
@@ -765,12 +670,16 @@
java_import {
name: "mysdk_exported-system-module@current",
sdk_member_name: "exported-system-module",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
jars: ["java/exported-system-module.jar"],
}
java_import {
name: "exported-system-module",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
jars: ["java/exported-system-module.jar"],
}
@@ -778,6 +687,7 @@
name: "mysdk_system-module@current",
sdk_member_name: "system-module",
visibility: ["//visibility:private"],
+ apex_available: ["//apex_available:platform"],
jars: ["java/system-module.jar"],
}
@@ -785,12 +695,14 @@
name: "mysdk_system-module",
prefer: false,
visibility: ["//visibility:private"],
+ apex_available: ["//apex_available:platform"],
jars: ["java/system-module.jar"],
}
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 +712,7 @@
java_system_modules_import {
name: "my-system-modules",
prefer: false,
+ visibility: ["//visibility:public"],
libs: [
"mysdk_system-module",
"exported-system-module",
@@ -808,6 +721,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
java_header_libs: ["mysdk_exported-system-module@current"],
java_system_modules: ["mysdk_my-system-modules@current"],
}
@@ -853,6 +767,7 @@
name: "mysdk_system-module@current",
sdk_member_name: "system-module",
visibility: ["//visibility:private"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
jars: ["java/system-module.jar"],
@@ -862,6 +777,7 @@
name: "mysdk_system-module",
prefer: false,
visibility: ["//visibility:private"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
jars: ["java/system-module.jar"],
@@ -870,6 +786,7 @@
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 +795,7 @@
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 +803,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
device_supported: false,
host_supported: true,
java_system_modules: ["mysdk_my-system-modules@current"],
@@ -938,6 +857,8 @@
java_import {
name: "myexports_hostjavalib@current",
sdk_member_name: "hostjavalib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
jars: ["java/hostjavalib.jar"],
@@ -946,6 +867,8 @@
java_import {
name: "hostjavalib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
jars: ["java/hostjavalib.jar"],
@@ -954,18 +877,24 @@
java_import {
name: "myexports_androidjavalib@current",
sdk_member_name: "androidjavalib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
jars: ["java/androidjavalib.jar"],
}
java_import {
name: "androidjavalib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
jars: ["java/androidjavalib.jar"],
}
java_import {
name: "myexports_myjavalib@current",
sdk_member_name: "myjavalib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
host_supported: true,
target: {
android: {
@@ -980,6 +909,8 @@
java_import {
name: "myjavalib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
host_supported: true,
target: {
android: {
@@ -993,6 +924,7 @@
module_exports_snapshot {
name: "myexports@current",
+ visibility: ["//visibility:public"],
host_supported: true,
java_libs: ["myexports_myjavalib@current"],
target: {
@@ -1039,25 +971,26 @@
java_sdk_library_import {
name: "mysdk_myjavalib@current",
sdk_member_name: "myjavalib",
+ visibility: ["//visibility:public"],
apex_available: ["//apex_available:anyapex"],
shared_library: false,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
},
system: {
jars: ["sdk_library/system/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/system/myjavalib.txt",
removed_api: "sdk_library/system/myjavalib-removed.txt",
sdk_version: "system_current",
},
test: {
jars: ["sdk_library/test/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/test/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/test/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/test/myjavalib.txt",
removed_api: "sdk_library/test/myjavalib-removed.txt",
sdk_version: "test_current",
@@ -1067,25 +1000,26 @@
java_sdk_library_import {
name: "myjavalib",
prefer: false,
+ visibility: ["//visibility:public"],
apex_available: ["//apex_available:anyapex"],
shared_library: false,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
},
system: {
jars: ["sdk_library/system/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/system/myjavalib.txt",
removed_api: "sdk_library/system/myjavalib-removed.txt",
sdk_version: "system_current",
},
test: {
jars: ["sdk_library/test/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/test/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/test/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/test/myjavalib.txt",
removed_api: "sdk_library/test/myjavalib-removed.txt",
sdk_version: "test_current",
@@ -1094,6 +1028,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
java_sdk_libs: ["mysdk_myjavalib@current"],
}
`),
@@ -1137,10 +1072,12 @@
java_sdk_library_import {
name: "mysdk_myjavalib@current",
sdk_member_name: "myjavalib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "none",
@@ -1150,10 +1087,12 @@
java_sdk_library_import {
name: "myjavalib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "none",
@@ -1162,6 +1101,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
java_sdk_libs: ["mysdk_myjavalib@current"],
}
`),
@@ -1201,10 +1141,12 @@
java_sdk_library_import {
name: "mysdk_myjavalib@current",
sdk_member_name: "myjavalib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "module_current",
@@ -1214,10 +1156,12 @@
java_sdk_library_import {
name: "myjavalib",
prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "module_current",
@@ -1226,6 +1170,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
java_sdk_libs: ["mysdk_myjavalib@current"],
}
`),
@@ -1268,18 +1213,19 @@
java_sdk_library_import {
name: "mysdk_myjavalib@current",
sdk_member_name: "myjavalib",
+ visibility: ["//visibility:public"],
apex_available: ["//apex_available:anyapex"],
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
},
system: {
jars: ["sdk_library/system/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/system/myjavalib.txt",
removed_api: "sdk_library/system/myjavalib-removed.txt",
sdk_version: "system_current",
@@ -1289,18 +1235,19 @@
java_sdk_library_import {
name: "myjavalib",
prefer: false,
+ visibility: ["//visibility:public"],
apex_available: ["//apex_available:anyapex"],
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
},
system: {
jars: ["sdk_library/system/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/system/myjavalib.txt",
removed_api: "sdk_library/system/myjavalib-removed.txt",
sdk_version: "system_current",
@@ -1309,6 +1256,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
java_sdk_libs: ["mysdk_myjavalib@current"],
}
`),
@@ -1358,25 +1306,26 @@
java_sdk_library_import {
name: "mysdk_myjavalib@current",
sdk_member_name: "myjavalib",
+ visibility: ["//visibility:public"],
apex_available: ["//apex_available:anyapex"],
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
},
system: {
jars: ["sdk_library/system/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/system/myjavalib.txt",
removed_api: "sdk_library/system/myjavalib-removed.txt",
sdk_version: "system_current",
},
module_lib: {
jars: ["sdk_library/module-lib/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/module-lib/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/module-lib/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/module-lib/myjavalib.txt",
removed_api: "sdk_library/module-lib/myjavalib-removed.txt",
sdk_version: "module_current",
@@ -1386,25 +1335,26 @@
java_sdk_library_import {
name: "myjavalib",
prefer: false,
+ visibility: ["//visibility:public"],
apex_available: ["//apex_available:anyapex"],
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
},
system: {
jars: ["sdk_library/system/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/system/myjavalib.txt",
removed_api: "sdk_library/system/myjavalib-removed.txt",
sdk_version: "system_current",
},
module_lib: {
jars: ["sdk_library/module-lib/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/module-lib/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/module-lib/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/module-lib/myjavalib.txt",
removed_api: "sdk_library/module-lib/myjavalib-removed.txt",
sdk_version: "module_current",
@@ -1413,6 +1363,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
java_sdk_libs: ["mysdk_myjavalib@current"],
}
`),
@@ -1463,18 +1414,19 @@
java_sdk_library_import {
name: "mysdk_myjavalib@current",
sdk_member_name: "myjavalib",
+ visibility: ["//visibility:public"],
apex_available: ["//apex_available:anyapex"],
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
},
system_server: {
jars: ["sdk_library/system-server/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/system-server/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/system-server/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/system-server/myjavalib.txt",
removed_api: "sdk_library/system-server/myjavalib-removed.txt",
sdk_version: "system_server_current",
@@ -1484,18 +1436,19 @@
java_sdk_library_import {
name: "myjavalib",
prefer: false,
+ visibility: ["//visibility:public"],
apex_available: ["//apex_available:anyapex"],
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
},
system_server: {
jars: ["sdk_library/system-server/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/system-server/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/system-server/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/system-server/myjavalib.txt",
removed_api: "sdk_library/system-server/myjavalib-removed.txt",
sdk_version: "system_server_current",
@@ -1504,6 +1457,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
java_sdk_libs: ["mysdk_myjavalib@current"],
}
`),
@@ -1548,12 +1502,13 @@
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,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
@@ -1563,12 +1518,13 @@
java_sdk_library_import {
name: "myjavalib",
prefer: false,
+ visibility: ["//visibility:public"],
apex_available: ["//apex_available:anyapex"],
naming_scheme: "default",
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
@@ -1577,6 +1533,7 @@
sdk_snapshot {
name: "mysdk@current",
+ visibility: ["//visibility:public"],
java_sdk_libs: ["mysdk_myjavalib@current"],
}
`),
@@ -1590,3 +1547,77 @@
),
)
}
+
+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"],
+ apex_available: ["//apex_available:platform"],
+ 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/**/*.java"],
+ 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"],
+ apex_available: ["//apex_available:platform"],
+ 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/**/*.java"],
+ 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 7591020..50b0886 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -75,6 +75,20 @@
// 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 @@
// 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 ef62b79..c4dc41b 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -108,6 +108,9 @@
// generated sdk_snapshot.
":__subpackages__",
],
+ prebuilt_visibility: [
+ "//prebuilts/mysdk",
+ ],
java_header_libs: [
"myjavalib",
"mypublicjavalib",
@@ -176,7 +179,9 @@
visibility: [
"//other/foo",
"//package",
+ "//prebuilts/mysdk",
],
+ apex_available: ["//apex_available:platform"],
jars: ["java/myjavalib.jar"],
}
@@ -186,7 +191,9 @@
visibility: [
"//other/foo",
"//package",
+ "//prebuilts/mysdk",
],
+ apex_available: ["//apex_available:platform"],
jars: ["java/myjavalib.jar"],
}
@@ -194,6 +201,7 @@
name: "mysdk_mypublicjavalib@current",
sdk_member_name: "mypublicjavalib",
visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
jars: ["java/mypublicjavalib.jar"],
}
@@ -201,6 +209,7 @@
name: "mypublicjavalib",
prefer: false,
visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
jars: ["java/mypublicjavalib.jar"],
}
@@ -210,7 +219,9 @@
visibility: [
"//other/bar",
"//package",
+ "//prebuilts/mysdk",
],
+ apex_available: ["//apex_available:platform"],
jars: ["java/mydefaultedjavalib.jar"],
}
@@ -220,21 +231,31 @@
visibility: [
"//other/bar",
"//package",
+ "//prebuilts/mysdk",
],
+ apex_available: ["//apex_available:platform"],
jars: ["java/mydefaultedjavalib.jar"],
}
java_import {
name: "mysdk_myprivatejavalib@current",
sdk_member_name: "myprivatejavalib",
- visibility: ["//package"],
+ visibility: [
+ "//package",
+ "//prebuilts/mysdk",
+ ],
+ apex_available: ["//apex_available:platform"],
jars: ["java/myprivatejavalib.jar"],
}
java_import {
name: "myprivatejavalib",
prefer: false,
- visibility: ["//package"],
+ visibility: [
+ "//package",
+ "//prebuilts/mysdk",
+ ],
+ apex_available: ["//apex_available:platform"],
jars: ["java/myprivatejavalib.jar"],
}
@@ -254,6 +275,40 @@
`))
}
+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 b53558d..5f520e5 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -68,19 +68,19 @@
// 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},
}
}
}
- ctx := android.NewTestArchContext()
+ ctx := android.NewTestArchContext(config)
// Enable androidmk support.
// * Register the singleton
@@ -89,11 +89,12 @@
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)
@@ -128,7 +129,7 @@
ctx.PreDepsMutators(RegisterPreDepsMutators)
ctx.PostDepsMutators(RegisterPostDepsMutators)
- ctx.Register(config)
+ ctx.Register()
return ctx, config
}
@@ -217,6 +218,22 @@
}
}
+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 537ab13..ba63542 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -300,7 +300,7 @@
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)
}
@@ -347,35 +347,11 @@
targetPropertySet := snapshotModule.AddPropertySet("target")
- // If host is supported and any member is host OS dependent then disable host
- // by default, so that we can enable each host OS variant explicitly. This
- // avoids problems with implicitly enabled OS variants when the snapshot is
- // used, which might be different from this run (e.g. different build OS).
- hasHostOsDependentMember := false
- if s.HostSupported() {
- for _, memberRef := range memberRefs {
- if memberRef.memberType.IsHostOsDependent() {
- hasHostOsDependentMember = true
- break
- }
- }
- if hasHostOsDependentMember {
- hostPropertySet := targetPropertySet.AddPropertySet("host")
- hostPropertySet.AddProperty("enabled", false)
- }
- }
-
// Iterate over the os types in a fixed order.
for _, osType := range s.getPossibleOsTypes() {
if sdkVariant, ok := osTypeToMemberProperties[osType]; ok {
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) {
- osPropertySet.AddProperty("enabled", true)
- }
-
variantProps := variantToProperties[sdkVariant]
if variantProps.Compile_multilib != "" && variantProps.Compile_multilib != "both" {
osPropertySet.AddProperty("compile_multilib", variantProps.Compile_multilib)
@@ -385,6 +361,31 @@
}
}
+ // If host is supported and any member is host OS dependent then disable host
+ // by default, so that we can enable each host OS variant explicitly. This
+ // avoids problems with implicitly enabled OS variants when the snapshot is
+ // used, which might be different from this run (e.g. different build OS).
+ if s.HostSupported() {
+ var supportedHostTargets []string
+ for _, memberRef := range memberRefs {
+ if memberRef.memberType.IsHostOsDependent() && memberRef.variant.Target().Os.Class == android.Host {
+ targetString := memberRef.variant.Target().Os.String() + "_" + memberRef.variant.Target().Arch.ArchType.String()
+ if !android.InList(targetString, supportedHostTargets) {
+ supportedHostTargets = append(supportedHostTargets, targetString)
+ }
+ }
+ }
+ if len(supportedHostTargets) > 0 {
+ hostPropertySet := targetPropertySet.AddPropertySet("host")
+ hostPropertySet.AddProperty("enabled", false)
+ }
+ // Enable the <os>_<arch> variant explicitly when we've disabled it by default on host.
+ for _, hostTarget := range supportedHostTargets {
+ propertySet := targetPropertySet.AddPropertySet(hostTarget)
+ propertySet.AddProperty("enabled", true)
+ }
+ }
+
// Prune any empty property sets.
snapshotModule.transform(pruneEmptySetTransformer{})
@@ -720,18 +721,44 @@
} 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)
}
}
+ // Where available copy apex_available properties from the member.
+ if apexAware, ok := variant.(interface{ ApexAvailable() []string }); ok {
+ apexAvailable := apexAware.ApexAvailable()
+ if len(apexAvailable) == 0 {
+ // //apex_available:platform is the default.
+ apexAvailable = []string{android.AvailableToPlatform}
+ }
+
+ // Add in any baseline apex available settings.
+ apexAvailable = append(apexAvailable, apex.BaselineApexAvailable(member.Name())...)
+
+ // Remove duplicates and sort.
+ apexAvailable = android.FirstUniqueStrings(apexAvailable)
+ sort.Strings(apexAvailable)
+
+ m.AddProperty("apex_available", apexAvailable)
+ }
+
deviceSupported := false
hostSupported := false
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
@@ -740,22 +767,6 @@
addHostDeviceSupportedProperties(deviceSupported, hostSupported, m)
- // Where available copy apex_available properties from the member.
- if apexAware, ok := variant.(interface{ ApexAvailable() []string }); ok {
- apexAvailable := apexAware.ApexAvailable()
-
- // Add in any baseline apex available settings.
- apexAvailable = append(apexAvailable, apex.BaselineApexAvailable(member.Name())...)
-
- if len(apexAvailable) > 0 {
- // Remove duplicates and sort.
- apexAvailable = android.FirstUniqueStrings(apexAvailable)
- sort.Strings(apexAvailable)
-
- m.AddProperty("apex_available", apexAvailable)
- }
- }
-
// Disable installation in the versioned module of those modules that are ever installable.
if installable, ok := variant.(interface{ EverInstallable() bool }); ok {
if installable.EverInstallable() {
@@ -977,7 +988,7 @@
archTypeName := archType.Name
archVariants := variantsByArchName[archTypeName]
- archInfo := newArchSpecificInfo(ctx, archType, osSpecificVariantPropertiesFactory, archVariants)
+ archInfo := newArchSpecificInfo(ctx, archType, osType, osSpecificVariantPropertiesFactory, archVariants)
osInfo.archInfos = append(osInfo.archInfos, archInfo)
}
@@ -1060,12 +1071,6 @@
osPropertySet = targetPropertySet.AddPropertySet(osType.Name)
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) {
- osPropertySet.AddProperty("enabled", true)
- }
-
// Arch specific properties need to be added to an os and arch specific
// section prefixed with <os>_.
archOsPrefix = osType.Name + "_"
@@ -1086,7 +1091,7 @@
func (osInfo *osTypeSpecificInfo) isHostVariant() bool {
osClass := osInfo.osType.Class
- return osClass == android.Host || osClass == android.HostCross
+ return osClass == android.Host
}
var _ isHostVariant = (*osTypeSpecificInfo)(nil)
@@ -1099,6 +1104,7 @@
baseInfo
archType android.ArchType
+ osType android.OsType
linkInfos []*linkTypeSpecificInfo
}
@@ -1107,10 +1113,10 @@
// Create a new archTypeSpecificInfo for the specified arch type and its properties
// structures populated with information from the variants.
-func newArchSpecificInfo(ctx android.SdkMemberContext, archType android.ArchType, variantPropertiesFactory variantPropertiesFactoryFunc, archVariants []android.Module) *archTypeSpecificInfo {
+func newArchSpecificInfo(ctx android.SdkMemberContext, archType android.ArchType, osType android.OsType, variantPropertiesFactory variantPropertiesFactoryFunc, archVariants []android.Module) *archTypeSpecificInfo {
// Create an arch specific info into which the variant properties can be copied.
- archInfo := &archTypeSpecificInfo{archType: archType}
+ archInfo := &archTypeSpecificInfo{archType: archType, osType: osType}
// Create the properties into which the arch type specific properties will be
// added.
@@ -1174,6 +1180,10 @@
func (archInfo *archTypeSpecificInfo) addToPropertySet(ctx *memberContext, archPropertySet android.BpPropertySet, archOsPrefix string) {
archTypeName := archInfo.archType.Name
archTypePropertySet := archPropertySet.AddPropertySet(archOsPrefix + archTypeName)
+ // Enable the <os>_<arch> variant explicitly when we've disabled it by default on host.
+ if ctx.memberType.IsHostOsDependent() && archInfo.osType.Class == android.Host {
+ archTypePropertySet.AddProperty("enabled", true)
+ }
addSdkMemberPropertiesToSet(ctx, archInfo.Properties, archTypePropertySet)
for _, linkInfo := range archInfo.linkInfos {
@@ -1323,7 +1333,7 @@
}
}
if s.HostSupported() {
- if osType.Class == android.Host || osType.Class == android.HostCross {
+ if osType.Class == android.Host {
osTypes = append(osTypes, osType)
}
}
@@ -1348,7 +1358,8 @@
// 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 +1396,18 @@
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 +1437,7 @@
// 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 +1459,15 @@
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 +1531,8 @@
// 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 f3f4a4a..7e5c344 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -66,8 +66,19 @@
Symlinks []string `android:"arch_variant"`
// Make this module available when building for ramdisk.
+ // On device without a dedicated recovery partition, the module is only
+ // available after switching root into
+ // /first_stage_ramdisk. To expose the module before switching root, install
+ // the recovery variant instead.
Ramdisk_available *bool
+ // Make this module available when building for vendor ramdisk.
+ // On device without a dedicated recovery partition, the module is only
+ // available after switching root into
+ // /first_stage_ramdisk. To expose the module before switching root, install
+ // the recovery variant instead.
+ Vendor_ramdisk_available *bool
+
// Make this module available when building for recovery.
Recovery_available *bool
}
@@ -176,6 +187,10 @@
return proptools.Bool(s.properties.Ramdisk_available) || s.ModuleBase.InstallInRamdisk()
}
+func (s *ShBinary) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return proptools.Bool(s.properties.Vendor_ramdisk_available) || s.ModuleBase.InstallInVendorRamdisk()
+}
+
func (s *ShBinary) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
return proptools.Bool(s.properties.Recovery_available) || s.ModuleBase.InstallInRecovery()
}
@@ -261,7 +276,7 @@
ctx.AddFarVariationDependencies(append(ctx.Target().Variations(), sharedLibVariations...),
shTestDataLibsTag, s.testProperties.Data_libs...)
if ctx.Target().Os.Class == android.Host && len(ctx.Config().Targets[android.Android]) > 0 {
- deviceVariations := ctx.Config().Targets[android.Android][0].Variations()
+ deviceVariations := ctx.Config().AndroidFirstDeviceTarget.Variations()
ctx.AddFarVariationDependencies(deviceVariations, shTestDataDeviceBinsTag, s.testProperties.Data_device_bins...)
ctx.AddFarVariationDependencies(append(deviceVariations, sharedLibVariations...),
shTestDataDeviceLibsTag, s.testProperties.Data_device_libs...)
@@ -313,6 +328,15 @@
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/sh/sh_binary_test.go b/sh/sh_binary_test.go
index 0aa607b..c664461 100644
--- a/sh/sh_binary_test.go
+++ b/sh/sh_binary_test.go
@@ -45,13 +45,13 @@
config := android.TestArchConfig(buildDir, nil, bp, fs)
- ctx := android.NewTestArchContext()
+ ctx := android.NewTestArchContext(config)
ctx.RegisterModuleType("sh_test", ShTestFactory)
ctx.RegisterModuleType("sh_test_host", ShTestHostFactory)
cc.RegisterRequiredBuildComponentsForTest(ctx)
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
diff --git a/shared/paths.go b/shared/paths.go
index f5dc5ac..24ba057 100644
--- a/shared/paths.go
+++ b/shared/paths.go
@@ -24,3 +24,17 @@
func TempDirForOutDir(outDir string) (tempPath string) {
return filepath.Join(outDir, ".temp")
}
+
+// BazelMetricsDir returns the path where a set of bazel profile
+// files are stored for later processed by the metrics pipeline.
+func BazelMetricsDir(outDir string) string {
+ return filepath.Join(outDir, "bazel_metrics")
+}
+
+// BazelMetricsFilename returns the bazel profile filename based
+// on the action name. This is to help to store a set of bazel
+// profiles since bazel may execute multiple times during a single
+// build.
+func BazelMetricsFilename(outDir, actionName string) string {
+ return filepath.Join(BazelMetricsDir(outDir), actionName+"_bazel_profile.gz")
+}
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 768c8e5..1740ba8 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -143,6 +143,9 @@
// Make this module available when building for vendor
Vendor_available *bool
+ // Make this module available when building for product
+ Product_available *bool
+
// list of .sysprop files which defines the properties.
Srcs []string `android:"path"`
@@ -310,7 +313,8 @@
}}
}
-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")
}
@@ -352,6 +356,7 @@
Recovery *bool
Recovery_available *bool
Vendor_available *bool
+ Product_available *bool
Host_supported *bool
Apex_available []string
Min_sdk_version *string
@@ -403,13 +408,21 @@
// ctx's Platform or Specific functions represent where this sysprop_library installed.
installedInSystem := ctx.Platform() || ctx.SystemExtSpecific()
installedInVendorOrOdm := ctx.SocSpecific() || ctx.DeviceSpecific()
+ installedInProduct := ctx.ProductSpecific()
isOwnerPlatform := false
- stub := "sysprop-library-stub-"
+ var stub string
+
+ if installedInVendorOrOdm {
+ stub = "sysprop-library-stub-vendor"
+ } else if installedInProduct {
+ stub = "sysprop-library-stub-product"
+ } else {
+ stub = "sysprop-library-stub-platform"
+ }
switch m.Owner() {
case "Platform":
// Every partition can access platform-defined properties
- stub += "platform"
isOwnerPlatform = true
case "Vendor":
// System can't access vendor's properties
@@ -417,14 +430,12 @@
ctx.ModuleErrorf("None of soc_specific, device_specific, product_specific is true. " +
"System can't access sysprop_library owned by Vendor")
}
- stub += "vendor"
case "Odm":
// Only vendor can access Odm-defined properties
if !installedInVendorOrOdm {
ctx.ModuleErrorf("Neither soc_speicifc nor device_specific is true. " +
"Odm-defined properties should be accessed only in Vendor or Odm")
}
- stub += "vendor"
default:
ctx.PropertyErrorf("property_owner",
"Unknown value %s: must be one of Platform, Vendor or Odm", m.Owner())
@@ -442,6 +453,7 @@
ccProps.Target.Host.Static_libs = []string{"libbase", "liblog"}
ccProps.Recovery_available = m.properties.Recovery_available
ccProps.Vendor_available = m.properties.Vendor_available
+ ccProps.Product_available = m.properties.Product_available
ccProps.Host_supported = m.properties.Host_supported
ccProps.Apex_available = m.ApexProperties.Apex_available
ccProps.Min_sdk_version = m.properties.Cpp.Min_sdk_version
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 711129c..b8b93f6 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -57,7 +57,7 @@
func testContext(config android.Config) *android.TestContext {
- ctx := android.NewTestArchContext()
+ ctx := android.NewTestArchContext(config)
java.RegisterJavaBuildComponents(ctx)
java.RegisterAppBuildComponents(ctx)
java.RegisterSystemModulesBuildComponents(ctx)
@@ -76,7 +76,7 @@
ctx.RegisterModuleType("sysprop_library", syspropLibraryFactory)
- ctx.Register(config)
+ ctx.Register()
return ctx
}
@@ -103,6 +103,8 @@
"api/sysprop-platform-on-product-latest.txt": nil,
"api/sysprop-vendor-current.txt": nil,
"api/sysprop-vendor-latest.txt": nil,
+ "api/sysprop-vendor-on-product-current.txt": nil,
+ "api/sysprop-vendor-on-product-latest.txt": nil,
"api/sysprop-odm-current.txt": nil,
"api/sysprop-odm-latest.txt": nil,
"framework/aidl/a.aidl": nil,
@@ -182,8 +184,15 @@
srcs: ["com/android/VendorProperties.sysprop"],
api_packages: ["com.android"],
property_owner: "Vendor",
+ vendor: true,
+ }
+
+ sysprop_library {
+ name: "sysprop-vendor-on-product",
+ srcs: ["com/android/VendorProperties.sysprop"],
+ api_packages: ["com.android"],
+ property_owner: "Vendor",
product_specific: true,
- vendor_available: true,
}
sysprop_library {
@@ -213,7 +222,7 @@
srcs: ["c.java"],
sdk_version: "system_current",
product_specific: true,
- libs: ["sysprop-platform", "sysprop-vendor"],
+ libs: ["sysprop-platform", "sysprop-vendor-on-product"],
}
java_library {
@@ -240,7 +249,7 @@
name: "cc-client-product",
srcs: ["d.cpp"],
product_specific: true,
- static_libs: ["sysprop-platform-on-product", "sysprop-vendor"],
+ static_libs: ["sysprop-platform-on-product", "sysprop-vendor-on-product"],
}
cc_library {
@@ -268,6 +277,7 @@
system_shared_libs: [],
recovery_available: true,
host_supported: true,
+ llndk_stubs: "liblog.llndk",
}
cc_binary_host {
@@ -276,7 +286,7 @@
}
llndk_library {
- name: "liblog",
+ name: "liblog.llndk",
symbol_file: "",
}
@@ -290,6 +300,12 @@
soc_specific: true,
sdk_version: "core_current",
}
+
+ java_library {
+ name: "sysprop-library-stub-product",
+ product_specific: true,
+ sdk_version: "core_current",
+ }
`)
// Check for generated cc_library
@@ -317,13 +333,14 @@
expectedApexAvailableOnLibrary, library.ApexProperties.Apex_available)
}
- // core variant of vendor-owned sysprop_library is for product
- ctx.ModuleForTests("libsysprop-vendor", variant)
+ // product variant of vendor-owned sysprop_library
+ ctx.ModuleForTests("libsysprop-vendor-on-product", variant)
}
ctx.ModuleForTests("sysprop-platform", "android_common")
ctx.ModuleForTests("sysprop-platform_public", "android_common")
ctx.ModuleForTests("sysprop-vendor", "android_common")
+ ctx.ModuleForTests("sysprop-vendor-on-product", "android_common")
// Check for exported includes
coreVariant := "android_arm64_armv8-a_static"
@@ -336,7 +353,7 @@
platformOnProductPath := "libsysprop-platform-on-product/android_arm64_armv8-a_static/gen/sysprop/public/include"
vendorInternalPath := "libsysprop-vendor/android_vendor.VER_arm64_armv8-a_static/gen/sysprop/include"
- vendorPublicPath := "libsysprop-vendor/android_arm64_armv8-a_static/gen/sysprop/public/include"
+ vendorPublicPath := "libsysprop-vendor-on-product/android_arm64_armv8-a_static/gen/sysprop/public/include"
platformClient := ctx.ModuleForTests("cc-client-platform", coreVariant)
platformFlags := platformClient.Rule("cc").Args["cFlags"]
diff --git a/tradefed/Android.bp b/tradefed/Android.bp
index 6e5e533..4e4e6a7 100644
--- a/tradefed/Android.bp
+++ b/tradefed/Android.bp
@@ -12,3 +12,20 @@
],
pluginFor: ["soong_build"],
}
+
+bootstrap_go_package {
+ name: "soong-suite-harness",
+ pkgPath: "android/soong/tradefed/suite_harness",
+ deps: [
+ "blueprint",
+ "blueprint-pathtools",
+ "blueprint-proptools",
+ "soong",
+ "soong-android",
+ "soong-java",
+ ],
+ srcs: [
+ "suite_harness/tradefed_binary.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/tradefed/suite_harness/tradefed_binary.go b/tradefed/suite_harness/tradefed_binary.go
new file mode 100644
index 0000000..a421d8b
--- /dev/null
+++ b/tradefed/suite_harness/tradefed_binary.go
@@ -0,0 +1,163 @@
+// Copyright 2018 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 suite_harness
+
+import (
+ "strings"
+
+ "github.com/google/blueprint"
+
+ "android/soong/android"
+ "android/soong/java"
+)
+
+var pctx = android.NewPackageContext("android/soong/tradefed/suite_harness")
+
+func init() {
+ android.RegisterModuleType("tradefed_binary_host", tradefedBinaryFactory)
+
+ pctx.Import("android/soong/android")
+}
+
+type TradefedBinaryProperties struct {
+ Short_name string
+ Full_name string
+ Version string
+ Prepend_platform_version_name bool
+}
+
+// tradefedBinaryFactory creates an empty module for the tradefed_binary module type,
+// which is a java_binary with some additional processing in tradefedBinaryLoadHook.
+func tradefedBinaryFactory() android.Module {
+ props := &TradefedBinaryProperties{}
+ module := java.BinaryHostFactory()
+ module.AddProperties(props)
+ android.AddLoadHook(module, tradefedBinaryLoadHook(props))
+
+ return module
+}
+
+const genSuffix = "-gen"
+
+// tradefedBinaryLoadHook adds extra resources and libraries to tradefed_binary modules.
+func tradefedBinaryLoadHook(tfb *TradefedBinaryProperties) func(ctx android.LoadHookContext) {
+ return func(ctx android.LoadHookContext) {
+ genName := ctx.ModuleName() + genSuffix
+ version := tfb.Version
+ if tfb.Prepend_platform_version_name {
+ version = ctx.Config().PlatformVersionName() + tfb.Version
+ }
+
+ // Create a submodule that generates the test-suite-info.properties file
+ // and copies DynamicConfig.xml if it is present.
+ ctx.CreateModule(tradefedBinaryGenFactory,
+ &TradefedBinaryGenProperties{
+ Name: &genName,
+ Short_name: tfb.Short_name,
+ Full_name: tfb.Full_name,
+ Version: version,
+ })
+
+ props := struct {
+ Java_resources []string
+ Libs []string
+ }{}
+
+ // Add dependencies required by all tradefed_binary modules.
+ props.Libs = []string{
+ "tradefed",
+ "tradefed-test-framework",
+ "loganalysis",
+ "compatibility-host-util",
+ }
+
+ // Add the files generated by the submodule created above to the resources.
+ props.Java_resources = []string{":" + genName}
+
+ ctx.AppendProperties(&props)
+
+ }
+}
+
+type TradefedBinaryGenProperties struct {
+ Name *string
+ Short_name string
+ Full_name string
+ Version string
+}
+
+type tradefedBinaryGen struct {
+ android.ModuleBase
+
+ properties TradefedBinaryGenProperties
+
+ gen android.Paths
+}
+
+func tradefedBinaryGenFactory() android.Module {
+ tfg := &tradefedBinaryGen{}
+ tfg.AddProperties(&tfg.properties)
+ android.InitAndroidModule(tfg)
+ return tfg
+}
+
+func (tfg *tradefedBinaryGen) DepsMutator(android.BottomUpMutatorContext) {}
+
+var tradefedBinaryGenRule = pctx.StaticRule("tradefedBinaryGenRule", blueprint.RuleParams{
+ Command: `rm -f $out && touch $out && ` +
+ `echo "# This file is auto generated by Android.mk. Do not modify." >> $out && ` +
+ `echo "build_number = $$(cat ${buildNumberFile})" >> $out && ` +
+ `echo "target_arch = ${arch}" >> $out && ` +
+ `echo "name = ${name}" >> $out && ` +
+ `echo "fullname = ${fullname}" >> $out && ` +
+ `echo "version = ${version}" >> $out`,
+}, "buildNumberFile", "arch", "name", "fullname", "version")
+
+func (tfg *tradefedBinaryGen) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ buildNumberFile := ctx.Config().BuildNumberFile(ctx)
+ outputFile := android.PathForModuleOut(ctx, "test-suite-info.properties")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: tradefedBinaryGenRule,
+ Output: outputFile,
+ OrderOnly: android.Paths{buildNumberFile},
+ Args: map[string]string{
+ "buildNumberFile": buildNumberFile.String(),
+ "arch": ctx.Config().DevicePrimaryArchType().String(),
+ "name": tfg.properties.Short_name,
+ "fullname": tfg.properties.Full_name,
+ "version": tfg.properties.Version,
+ },
+ })
+
+ tfg.gen = append(tfg.gen, outputFile)
+
+ dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
+ if dynamicConfig.Valid() {
+ outputFile := android.PathForModuleOut(ctx, strings.TrimSuffix(ctx.ModuleName(), genSuffix)+".dynamic")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: dynamicConfig.Path(),
+ Output: outputFile,
+ })
+
+ tfg.gen = append(tfg.gen, outputFile)
+ }
+}
+
+func (tfg *tradefedBinaryGen) Srcs() android.Paths {
+ return append(android.Paths(nil), tfg.gen...)
+}
+
+var _ android.SourceFileProducer = (*tradefedBinaryGen)(nil)
diff --git a/ui/build/Android.bp b/ui/build/Android.bp
index 4ef2721..c314b7b 100644
--- a/ui/build/Android.bp
+++ b/ui/build/Android.bp
@@ -39,6 +39,7 @@
"blueprint-microfactory",
],
srcs: [
+ "bazel.go",
"build.go",
"cleanbuild.go",
"config.go",
diff --git a/ui/build/bazel.go b/ui/build/bazel.go
new file mode 100644
index 0000000..7cc7caf
--- /dev/null
+++ b/ui/build/bazel.go
@@ -0,0 +1,140 @@
+// 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 build
+
+import (
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "android/soong/shared"
+ "android/soong/ui/metrics"
+)
+
+// Main entry point to construct the Bazel build command line, environment variables
+// and post-processing steps (e.g. converge output directories)
+func runBazel(ctx Context, config Config) {
+ ctx.BeginTrace(metrics.RunBazel, "bazel")
+ defer ctx.EndTrace()
+
+ // "droid" is the default ninja target.
+ // TODO(b/160568333): stop hardcoding 'droid' to support building any
+ // Ninja target.
+ outputGroups := "droid"
+ if len(config.ninjaArgs) > 0 {
+ // At this stage, the residue slice of args passed to ninja
+ // are the ninja targets to build, which can correspond directly
+ // to ninja_build's output_groups.
+ outputGroups = strings.Join(config.ninjaArgs, ",")
+ }
+
+ config.environ.Set("COMBINED_NINJA", config.CombinedNinjaFile())
+ config.environ.Set("KATI_NINJA", config.KatiBuildNinjaFile())
+ config.environ.Set("PACKAGE_NINJA", config.KatiPackageNinjaFile())
+ config.environ.Set("SOONG_NINJA", config.SoongNinjaFile())
+
+ bazelExecutable := filepath.Join("tools", "bazel")
+ cmd := Command(ctx, config, "bazel", bazelExecutable)
+
+ if extra_startup_args, ok := cmd.Environment.Get("BAZEL_STARTUP_ARGS"); ok {
+ cmd.Args = append(cmd.Args, strings.Fields(extra_startup_args)...)
+ }
+
+ actionName := "build"
+ cmd.Args = append(cmd.Args,
+ actionName,
+ "--output_groups="+outputGroups,
+ "--profile="+filepath.Join(shared.BazelMetricsFilename(config.OutDir(), actionName)),
+ "--slim_profile=true",
+ )
+
+ if extra_build_args, ok := cmd.Environment.Get("BAZEL_BUILD_ARGS"); ok {
+ cmd.Args = append(cmd.Args, strings.Fields(extra_build_args)...)
+ }
+
+ cmd.Args = append(cmd.Args,
+ "//:"+config.TargetProduct()+"-"+config.TargetBuildVariant(),
+ )
+
+ if pathEnvValue, ok := config.environ.Get("PATH"); ok {
+ cmd.Environment.Set("PATH", pathEnvValue)
+ cmd.Args = append(cmd.Args, "--action_env=PATH="+pathEnvValue)
+ }
+ cmd.Environment.Set("DIST_DIR", config.DistDir())
+ cmd.Environment.Set("SHELL", "/bin/bash")
+
+ ctx.Println(cmd.Cmd)
+ cmd.Dir = filepath.Join(config.OutDir(), "..")
+ ctx.Status.Status("Starting Bazel..")
+ cmd.RunAndStreamOrFatal()
+
+ // Obtain the Bazel output directory for ninja_build.
+ infoCmd := Command(ctx, config, "bazel", bazelExecutable)
+
+ if extra_startup_args, ok := infoCmd.Environment.Get("BAZEL_STARTUP_ARGS"); ok {
+ infoCmd.Args = append(infoCmd.Args, strings.Fields(extra_startup_args)...)
+ }
+
+ infoCmd.Args = append(infoCmd.Args,
+ "info",
+ "output_path",
+ )
+
+ infoCmd.Environment.Set("DIST_DIR", config.DistDir())
+ infoCmd.Environment.Set("SHELL", "/bin/bash")
+ infoCmd.Dir = filepath.Join(config.OutDir(), "..")
+ ctx.Status.Status("Getting Bazel Info..")
+ outputBasePath := string(infoCmd.OutputOrFatal())
+ // TODO: Don't hardcode out/ as the bazel output directory. This is
+ // currently hardcoded as ninja_build.output_root.
+ bazelNinjaBuildOutputRoot := filepath.Join(outputBasePath, "..", "out")
+
+ symlinkOutdir(ctx, config, bazelNinjaBuildOutputRoot, ".")
+}
+
+// For all files F recursively under rootPath/relativePath, creates symlinks
+// such that OutDir/F resolves to rootPath/F via symlinks.
+func symlinkOutdir(ctx Context, config Config, rootPath string, relativePath string) {
+ destDir := filepath.Join(rootPath, relativePath)
+ os.MkdirAll(destDir, 0755)
+ files, err := ioutil.ReadDir(destDir)
+ if err != nil {
+ ctx.Fatal(err)
+ }
+ for _, f := range files {
+ destPath := filepath.Join(destDir, f.Name())
+ srcPath := filepath.Join(config.OutDir(), relativePath, f.Name())
+ if statResult, err := os.Stat(srcPath); err == nil {
+ if statResult.Mode().IsDir() && f.IsDir() {
+ // Directory under OutDir already exists, so recurse on its contents.
+ symlinkOutdir(ctx, config, rootPath, filepath.Join(relativePath, f.Name()))
+ } else if !statResult.Mode().IsDir() && !f.IsDir() {
+ // File exists both in source and destination, and it's not a directory
+ // in either location. Do nothing.
+ // This can arise for files which are generated under OutDir outside of
+ // soong_build, such as .bootstrap files.
+ } else {
+ // File is a directory in one location but not the other. Raise an error.
+ ctx.Fatalf("Could not link %s to %s due to conflict", srcPath, destPath)
+ }
+ } else if os.IsNotExist(err) {
+ // Create symlink srcPath -> fullDestPath.
+ os.Symlink(destPath, srcPath)
+ } else {
+ ctx.Fatalf("Unable to stat %s: %s", srcPath, err)
+ }
+ }
+}
diff --git a/ui/build/build.go b/ui/build/build.go
index 396f54c..1cf2023 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -84,8 +84,10 @@
BuildSoong = 1 << iota
BuildKati = 1 << iota
BuildNinja = 1 << iota
+ BuildBazel = 1 << iota
RunBuildTests = 1 << iota
BuildAll = BuildProductConfig | BuildSoong | BuildKati | BuildNinja
+ BuildAllWithBazel = BuildProductConfig | BuildSoong | BuildKati | BuildBazel
)
func checkProblematicFiles(ctx Context) {
@@ -257,6 +259,10 @@
// Run ninja
runNinja(ctx, config)
}
+
+ if what&BuildBazel != 0 {
+ runBazel(ctx, config)
+ }
}
// distGzipFile writes a compressed copy of src to the distDir if dist is enabled. Failures
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index e1123e0..03e884a 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -80,6 +80,10 @@
return filepath.Join(hostOutPath, path)
}
+ hostCommonOut := func(path string) string {
+ return filepath.Join(config.hostOutRoot(), "common", path)
+ }
+
productOutPath := config.ProductOut()
productOut := func(path string) string {
return filepath.Join(productOutPath, path)
@@ -101,6 +105,7 @@
hostOut("vts"),
hostOut("vts10"),
hostOut("vts-core"),
+ hostCommonOut("obj/PACKAGING"),
productOut("*.img"),
productOut("*.zip"),
productOut("android-info.txt"),
@@ -122,6 +127,7 @@
productOut("system"),
productOut("system_other"),
productOut("vendor"),
+ productOut("vendor_dlkm"),
productOut("product"),
productOut("system_ext"),
productOut("oem"),
@@ -131,6 +137,7 @@
productOut("coverage"),
productOut("installer"),
productOut("odm"),
+ productOut("odm_dlkm"),
productOut("sysloader"),
productOut("testcases"))
}
diff --git a/ui/build/config.go b/ui/build/config.go
index e9a8fc9..641aae6 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -24,6 +24,7 @@
"time"
"android/soong/shared"
+
"github.com/golang/protobuf/proto"
smpb "android/soong/ui/metrics/metrics_proto"
@@ -40,12 +41,13 @@
buildDateTime string
// From the arguments
- parallel int
- keepGoing int
- verbose bool
- checkbuild bool
- dist bool
- skipMake bool
+ parallel int
+ keepGoing int
+ verbose bool
+ checkbuild bool
+ dist bool
+ skipMake bool
+ skipSoongTests bool
// From the product config
katiArgs []string
@@ -183,6 +185,11 @@
"EMPTY_NINJA_FILE",
)
+ if ret.UseGoma() || ret.ForceUseGoma() {
+ ctx.Println("Goma for Android has been deprecated and replaced with RBE. See go/rbe_for_android for instructions on how to use RBE.")
+ ctx.Fatalln("USE_GOMA / FORCE_USE_GOMA flag is no longer supported.")
+ }
+
// Tell python not to spam the source tree with .pyc files.
ret.environ.Set("PYTHONDONTWRITEBYTECODE", "1")
@@ -267,6 +274,16 @@
}
}
+ bpd := shared.BazelMetricsDir(ret.OutDir())
+ if err := os.RemoveAll(bpd); err != nil {
+ ctx.Fatalf("Unable to remove bazel profile directory %q: %v", bpd, err)
+ }
+ if ret.UseBazel() {
+ if err := os.MkdirAll(bpd, 0777); err != nil {
+ ctx.Fatalf("Failed to create bazel profile directory %q: %v", bpd, err)
+ }
+ }
+
c := Config{ret}
storeConfigMetrics(ctx, c)
return c
@@ -286,10 +303,17 @@
}
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)
+
+ s := &smpb.SystemResourceInfo{
+ TotalPhysicalMemory: proto.Uint64(config.TotalRAM()),
+ AvailableCpus: proto.Int32(int32(runtime.NumCPU())),
+ }
+ ctx.Metrics.SystemResourceInfo(s)
}
// getConfigArgs processes the command arguments based on the build action and creates a set of new
@@ -513,6 +537,8 @@
c.verbose = true
} else if arg == "--skip-make" {
c.skipMake = true
+ } else if arg == "--skip-soong-tests" {
+ c.skipSoongTests = true
} else if len(arg) > 0 && arg[0] == '-' {
parseArgNum := func(def int) int {
if len(arg) > 2 {
@@ -778,6 +804,18 @@
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)
@@ -812,6 +850,16 @@
return false
}
+func (c *configImpl) UseBazel() bool {
+ if v, ok := c.environ.Get("USE_BAZEL"); ok {
+ v = strings.TrimSpace(v)
+ if v != "" && v != "false" {
+ return true
+ }
+ }
+ return false
+}
+
func (c *configImpl) StartRBE() bool {
if !c.UseRBE() {
return false
@@ -827,6 +875,11 @@
}
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/context.go b/ui/build/context.go
index 3945ce0..43e1e0f 100644
--- a/ui/build/context.go
+++ b/ui/build/context.go
@@ -48,7 +48,7 @@
c.Tracer.Begin(desc, c.Thread)
}
if c.Metrics != nil {
- c.Metrics.TimeTracer.Begin(name, desc, c.Thread)
+ c.Metrics.EventTracer.Begin(name, desc, c.Thread)
}
}
@@ -58,7 +58,7 @@
c.Tracer.End(c.Thread)
}
if c.Metrics != nil {
- c.Metrics.SetTimeMetrics(c.Metrics.TimeTracer.End(c.Thread))
+ c.Metrics.SetTimeMetrics(c.Metrics.EventTracer.End(c.Thread))
}
}
diff --git a/ui/build/exec.go b/ui/build/exec.go
index 053bbae..8f92269 100644
--- a/ui/build/exec.go
+++ b/ui/build/exec.go
@@ -66,8 +66,11 @@
}
func (c *Cmd) report() {
- if c.Cmd.ProcessState != nil {
- rusage := c.Cmd.ProcessState.SysUsage().(*syscall.Rusage)
+ if state := c.Cmd.ProcessState; state != nil {
+ if c.ctx.Metrics != nil {
+ c.ctx.Metrics.EventTracer.AddProcResInfo(c.name, state)
+ }
+ rusage := state.SysUsage().(*syscall.Rusage)
c.ctx.Verbosef("%q finished with exit code %d (%s real, %s user, %s system, %dMB maxrss)",
c.name, c.Cmd.ProcessState.ExitCode(),
time.Since(c.started).Round(time.Millisecond),
diff --git a/ui/build/finder.go b/ui/build/finder.go
index c019ea2..7a85657 100644
--- a/ui/build/finder.go
+++ b/ui/build/finder.go
@@ -63,10 +63,13 @@
"AndroidProducts.mk",
"Android.bp",
"Blueprints",
+ "BUILD.bazel",
"CleanSpec.mk",
"OWNERS",
"TEST_MAPPING",
+ "WORKSPACE",
},
+ IncludeSuffixes: []string{".bzl"},
}
dumpDir := config.FileListDir()
f, err = finder.New(cacheParams, filesystem, logger.New(ioutil.Discard),
@@ -77,6 +80,16 @@
return f
}
+func findBazelFiles(entries finder.DirEntries) (dirNames []string, fileNames []string) {
+ matches := []string{}
+ for _, foundName := range entries.FileNames {
+ if foundName == "BUILD.bazel" || foundName == "WORKSPACE" || strings.HasSuffix(foundName, ".bzl") {
+ matches = append(matches, foundName)
+ }
+ }
+ return entries.DirNames, matches
+}
+
// FindSources searches for source files known to <f> and writes them to the filesystem for
// use later.
func FindSources(ctx Context, config Config, f *finder.Finder) {
@@ -99,6 +112,12 @@
ctx.Fatalf("Could not export product list: %v", err)
}
+ bazelFiles := f.FindMatching(".", findBazelFiles)
+ err = dumpListToFile(ctx, config, bazelFiles, filepath.Join(dumpDir, "bazel.list"))
+ if err != nil {
+ ctx.Fatalf("Could not export bazel BUILD list: %v", err)
+ }
+
cleanSpecs := f.FindFirstNamedAt(".", "CleanSpec.mk")
err = dumpListToFile(ctx, config, cleanSpecs, filepath.Join(dumpDir, "CleanSpec.mk.list"))
if err != nil {
diff --git a/ui/build/kati.go b/ui/build/kati.go
index f6d3a57..f6c0f52 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -68,6 +68,7 @@
"--ninja_suffix=" + config.KatiSuffix() + extraSuffix,
"--no_ninja_prelude",
"--use_ninja_phony_output",
+ "--use_ninja_symlink_outputs",
"--regen",
"--ignore_optional_include=" + filepath.Join(config.OutDir(), "%.P"),
"--detect_android_echo",
diff --git a/ui/build/rbe.go b/ui/build/rbe.go
index c4b829d..64f3d4c 100644
--- a/ui/build/rbe.go
+++ b/ui/build/rbe.go
@@ -34,6 +34,8 @@
// RBE metrics proto buffer file
rbeMetricsPBFilename = "rbe_metrics.pb"
+
+ defaultOutDir = "out"
)
func rbeCommand(ctx Context, config Config, rbeCmd string) string {
@@ -152,12 +154,15 @@
}
}
-// 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() {
+// PrintOutDirWarning prints a warning to indicate to the user that
+// setting output directory to a path other than "out" in an RBE enabled
+// build can cause slow builds.
+func PrintOutDirWarning(ctx Context, config Config) {
+ if config.UseRBE() && config.OutDir() != defaultOutDir {
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, "\033[33mWARNING:\033[0m")
+ fmt.Fprintln(ctx.Writer, fmt.Sprintf("Setting OUT_DIR to a path other than %v may result in slow RBE builds.", defaultOutDir))
+ fmt.Fprintln(ctx.Writer, "See http://go/android_rbe_out_dir for a workaround.")
fmt.Fprintln(ctx.Writer, "")
}
}
diff --git a/ui/build/soong.go b/ui/build/soong.go
index fb21430..b20237c 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -38,7 +38,12 @@
ctx.BeginTrace(metrics.RunSoong, "blueprint bootstrap")
defer ctx.EndTrace()
- cmd := Command(ctx, config, "blueprint bootstrap", "build/blueprint/bootstrap.bash", "-t", "-n")
+ args := []string{"-n"}
+ if !config.skipSoongTests {
+ args = append(args, "-t")
+ }
+
+ cmd := Command(ctx, config, "blueprint bootstrap", "build/blueprint/bootstrap.bash", args...)
cmd.Environment.Set("BLUEPRINTDIR", "./build/blueprint")
cmd.Environment.Set("BOOTSTRAP", "./build/blueprint/bootstrap.bash")
cmd.Environment.Set("BUILDDIR", config.SoongOutDir())
diff --git a/ui/build/test_build.go b/ui/build/test_build.go
index 83b3807..3164680 100644
--- a/ui/build/test_build.go
+++ b/ui/build/test_build.go
@@ -68,6 +68,12 @@
miniBootstrapDir := filepath.Join(outDir, "soong", ".minibootstrap")
modulePathsDir := filepath.Join(outDir, ".module_paths")
variablesFilePath := filepath.Join(outDir, "soong", "soong.variables")
+ // dexpreopt.config is an input to the soong_docs action, which runs the
+ // soong_build primary builder. However, this file is created from $(shell)
+ // invocation at Kati parse time, so it's not an explicit output of any
+ // Ninja action, but it is present during the build itself and can be
+ // treated as an source file.
+ dexpreoptConfigFilePath := filepath.Join(outDir, "soong", "dexpreopt.config")
danglingRules := make(map[string]bool)
@@ -81,7 +87,8 @@
if strings.HasPrefix(line, bootstrapDir) ||
strings.HasPrefix(line, miniBootstrapDir) ||
strings.HasPrefix(line, modulePathsDir) ||
- line == variablesFilePath {
+ line == variablesFilePath ||
+ line == dexpreoptConfigFilePath {
// Leaf node is in one of Soong's bootstrap directories, which do not have
// full build rules in the primary build.ninja file.
continue
diff --git a/ui/metrics/Android.bp b/ui/metrics/Android.bp
index 8188a69..95c8f5c 100644
--- a/ui/metrics/Android.bp
+++ b/ui/metrics/Android.bp
@@ -23,10 +23,10 @@
],
srcs: [
"metrics.go",
- "time.go",
+ "event.go",
],
testSrcs: [
- "time_test.go",
+ "event_test.go",
],
}
diff --git a/ui/metrics/event.go b/ui/metrics/event.go
new file mode 100644
index 0000000..6becfd1
--- /dev/null
+++ b/ui/metrics/event.go
@@ -0,0 +1,104 @@
+// Copyright 2018 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 metrics
+
+import (
+ "os"
+ "syscall"
+ "time"
+
+ "android/soong/ui/metrics/metrics_proto"
+ "android/soong/ui/tracer"
+ "github.com/golang/protobuf/proto"
+)
+
+// for testing purpose only
+var _now = now
+
+type event struct {
+ desc string
+ name string
+
+ // the time that the event started to occur.
+ start time.Time
+
+ // The list of process resource information that was executed
+ procResInfo []*soong_metrics_proto.ProcessResourceInfo
+}
+
+type EventTracer interface {
+ Begin(name, desc string, thread tracer.Thread)
+ End(thread tracer.Thread) soong_metrics_proto.PerfInfo
+ AddProcResInfo(string, *os.ProcessState)
+}
+
+type eventTracerImpl struct {
+ activeEvents []event
+}
+
+var _ EventTracer = &eventTracerImpl{}
+
+func now() time.Time {
+ return time.Now()
+}
+
+// AddProcResInfo adds information on an executed process such as max resident set memory
+// and the number of voluntary context switches.
+func (t *eventTracerImpl) AddProcResInfo(name string, state *os.ProcessState) {
+ if len(t.activeEvents) < 1 {
+ return
+ }
+
+ rusage := state.SysUsage().(*syscall.Rusage)
+ // The implementation of the metrics system is a stacked based system. The steps of the
+ // build system in the UI layer is sequential so the Begin function is invoked when a
+ // function (or scoped code) is invoked. That is translated to a new event which is added
+ // at the end of the activeEvents array. When the invoking function is completed, End is
+ // invoked which is a pop operation from activeEvents.
+ curEvent := &t.activeEvents[len(t.activeEvents)-1]
+ curEvent.procResInfo = append(curEvent.procResInfo, &soong_metrics_proto.ProcessResourceInfo{
+ Name: proto.String(name),
+ UserTimeMicros: proto.Uint64(uint64(rusage.Utime.Usec)),
+ SystemTimeMicros: proto.Uint64(uint64(rusage.Stime.Usec)),
+ MinorPageFaults: proto.Uint64(uint64(rusage.Minflt)),
+ MajorPageFaults: proto.Uint64(uint64(rusage.Majflt)),
+ // ru_inblock and ru_oublock are measured in blocks of 512 bytes.
+ IoInputKb: proto.Uint64(uint64(rusage.Inblock / 2)),
+ IoOutputKb: proto.Uint64(uint64(rusage.Oublock / 2)),
+ VoluntaryContextSwitches: proto.Uint64(uint64(rusage.Nvcsw)),
+ InvoluntaryContextSwitches: proto.Uint64(uint64(rusage.Nivcsw)),
+ })
+}
+
+func (t *eventTracerImpl) Begin(name, desc string, _ tracer.Thread) {
+ t.activeEvents = append(t.activeEvents, event{name: name, desc: desc, start: _now()})
+}
+
+func (t *eventTracerImpl) End(tracer.Thread) soong_metrics_proto.PerfInfo {
+ if len(t.activeEvents) < 1 {
+ panic("Internal error: No pending events for endAt to end!")
+ }
+ lastEvent := t.activeEvents[len(t.activeEvents)-1]
+ t.activeEvents = t.activeEvents[:len(t.activeEvents)-1]
+ realTime := uint64(_now().Sub(lastEvent.start).Nanoseconds())
+
+ return soong_metrics_proto.PerfInfo{
+ Desc: proto.String(lastEvent.desc),
+ Name: proto.String(lastEvent.name),
+ StartTime: proto.Uint64(uint64(lastEvent.start.UnixNano())),
+ RealTime: proto.Uint64(realTime),
+ ProcessesResourceInfo: lastEvent.procResInfo,
+ }
+}
diff --git a/ui/metrics/time_test.go b/ui/metrics/event_test.go
similarity index 88%
rename from ui/metrics/time_test.go
rename to ui/metrics/event_test.go
index d73080a..6fc0b50 100644
--- a/ui/metrics/time_test.go
+++ b/ui/metrics/event_test.go
@@ -28,14 +28,14 @@
_now = func() time.Time { return startTime.Add(dur) }
defer func() { _now = initialNow }()
- timeTracer := &timeTracerImpl{}
- timeTracer.activeEvents = append(timeTracer.activeEvents, timeEvent{
+ eventTracer := &eventTracerImpl{}
+ eventTracer.activeEvents = append(eventTracer.activeEvents, event{
desc: "test",
name: "test",
start: startTime,
})
- perf := timeTracer.End(tracer.Thread(0))
+ perf := eventTracer.End(tracer.Thread(0))
if perf.GetRealTime() != uint64(dur.Nanoseconds()) {
t.Errorf("got %d, want %d nanoseconds for event duration", perf.GetRealTime(), dur.Nanoseconds())
}
diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go
index f5552a3..7031042 100644
--- a/ui/metrics/metrics.go
+++ b/ui/metrics/metrics.go
@@ -18,6 +18,7 @@
"io/ioutil"
"os"
"runtime"
+ "strings"
"time"
"github.com/golang/protobuf/proto"
@@ -31,19 +32,20 @@
RunSetupTool = "setup"
RunShutdownTool = "shutdown"
RunSoong = "soong"
+ RunBazel = "bazel"
TestRun = "test"
Total = "total"
)
type Metrics struct {
- metrics soong_metrics_proto.MetricsBase
- TimeTracer TimeTracer
+ metrics soong_metrics_proto.MetricsBase
+ EventTracer EventTracer
}
func New() (metrics *Metrics) {
m := &Metrics{
- metrics: soong_metrics_proto.MetricsBase{},
- TimeTracer: &timeTracerImpl{},
+ metrics: soong_metrics_proto.MetricsBase{},
+ EventTracer: &eventTracerImpl{},
}
return m
}
@@ -52,17 +54,14 @@
switch perf.GetName() {
case RunKati:
m.metrics.KatiRuns = append(m.metrics.KatiRuns, &perf)
- break
case RunSoong:
m.metrics.SoongRuns = append(m.metrics.SoongRuns, &perf)
- break
+ case RunBazel:
+ m.metrics.BazelRuns = append(m.metrics.BazelRuns, &perf)
case PrimaryNinja:
m.metrics.NinjaRuns = append(m.metrics.NinjaRuns, &perf)
- break
case Total:
m.metrics.Total = &perf
- default:
- // ignored
}
}
@@ -70,18 +69,19 @@
m.metrics.BuildConfig = b
}
+func (m *Metrics) SystemResourceInfo(b *soong_metrics_proto.SystemResourceInfo) {
+ m.metrics.SystemResourceInfo = b
+}
+
func (m *Metrics) SetMetadataMetrics(metadata map[string]string) {
for k, v := range metadata {
switch k {
case "BUILD_ID":
m.metrics.BuildId = proto.String(v)
- break
case "PLATFORM_VERSION_CODENAME":
m.metrics.PlatformVersionCodename = proto.String(v)
- break
case "TARGET_PRODUCT":
m.metrics.TargetProduct = proto.String(v)
- break
case "TARGET_BUILD_VARIANT":
switch v {
case "user":
@@ -90,8 +90,6 @@
m.metrics.TargetBuildVariant = soong_metrics_proto.MetricsBase_USERDEBUG.Enum()
case "eng":
m.metrics.TargetBuildVariant = soong_metrics_proto.MetricsBase_ENG.Enum()
- default:
- // ignored
}
case "TARGET_ARCH":
m.metrics.TargetArch = m.getArch(v)
@@ -113,8 +111,6 @@
m.metrics.HostCross_2NdArch = proto.String(v)
case "OUT_DIR":
m.metrics.OutDir = proto.String(v)
- default:
- // ignored
}
}
}
@@ -138,8 +134,17 @@
m.metrics.BuildDateTimestamp = proto.Int64(buildTimestamp.UnixNano() / int64(time.Second))
}
+func (m *Metrics) SetBuildCommand(cmd []string) {
+ m.metrics.BuildCommand = proto.String(strings.Join(cmd, " "))
+}
+
// exports the output to the file at outputPath
-func (m *Metrics) Dump(outputPath string) (err error) {
+func (m *Metrics) Dump(outputPath string) error {
+ // ignore the error if the hostname could not be retrieved as it
+ // is not a critical metric to extract.
+ if hostname, err := os.Hostname(); err == nil {
+ m.metrics.Hostname = proto.String(hostname)
+ }
m.metrics.HostOs = proto.String(runtime.GOOS)
return writeMessageToFile(&m.metrics, outputPath)
}
diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go
index d7c53ec..fc2cfa4 100644
--- a/ui/metrics/metrics_proto/metrics.pb.go
+++ b/ui/metrics/metrics_proto/metrics.pb.go
@@ -152,7 +152,7 @@
}
func (ModuleTypeInfo_BuildSystem) EnumDescriptor() ([]byte, []int) {
- return fileDescriptor_6039342a2ba47b72, []int{3, 0}
+ return fileDescriptor_6039342a2ba47b72, []int{5, 0}
}
type MetricsBase struct {
@@ -197,12 +197,20 @@
// The metrics for calling Ninja.
NinjaRuns []*PerfInfo `protobuf:"bytes,20,rep,name=ninja_runs,json=ninjaRuns" json:"ninja_runs,omitempty"`
// The metrics for the whole build
- Total *PerfInfo `protobuf:"bytes,21,opt,name=total" json:"total,omitempty"`
- SoongBuildMetrics *SoongBuildMetrics `protobuf:"bytes,22,opt,name=soong_build_metrics,json=soongBuildMetrics" json:"soong_build_metrics,omitempty"`
- BuildConfig *BuildConfig `protobuf:"bytes,23,opt,name=build_config,json=buildConfig" json:"build_config,omitempty"`
- XXX_NoUnkeyedLiteral struct{} `json:"-"`
- XXX_unrecognized []byte `json:"-"`
- XXX_sizecache int32 `json:"-"`
+ Total *PerfInfo `protobuf:"bytes,21,opt,name=total" json:"total,omitempty"`
+ SoongBuildMetrics *SoongBuildMetrics `protobuf:"bytes,22,opt,name=soong_build_metrics,json=soongBuildMetrics" json:"soong_build_metrics,omitempty"`
+ BuildConfig *BuildConfig `protobuf:"bytes,23,opt,name=build_config,json=buildConfig" json:"build_config,omitempty"`
+ // The hostname of the machine.
+ Hostname *string `protobuf:"bytes,24,opt,name=hostname" json:"hostname,omitempty"`
+ // The system resource information such as total physical memory.
+ SystemResourceInfo *SystemResourceInfo `protobuf:"bytes,25,opt,name=system_resource_info,json=systemResourceInfo" json:"system_resource_info,omitempty"`
+ // The build command that the user entered to the build system.
+ BuildCommand *string `protobuf:"bytes,26,opt,name=build_command,json=buildCommand" json:"build_command,omitempty"`
+ // The metrics for calling Bazel.
+ BazelRuns []*PerfInfo `protobuf:"bytes,27,rep,name=bazel_runs,json=bazelRuns" json:"bazel_runs,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
func (m *MetricsBase) Reset() { *m = MetricsBase{} }
@@ -396,9 +404,38 @@
return nil
}
+func (m *MetricsBase) GetHostname() string {
+ if m != nil && m.Hostname != nil {
+ return *m.Hostname
+ }
+ return ""
+}
+
+func (m *MetricsBase) GetSystemResourceInfo() *SystemResourceInfo {
+ if m != nil {
+ return m.SystemResourceInfo
+ }
+ return nil
+}
+
+func (m *MetricsBase) GetBuildCommand() string {
+ if m != nil && m.BuildCommand != nil {
+ return *m.BuildCommand
+ }
+ return ""
+}
+
+func (m *MetricsBase) GetBazelRuns() []*PerfInfo {
+ if m != nil {
+ return m.BazelRuns
+ }
+ return nil
+}
+
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 +480,62 @@
return false
}
+func (m *BuildConfig) GetForceUseGoma() bool {
+ if m != nil && m.ForceUseGoma != nil {
+ return *m.ForceUseGoma
+ }
+ return false
+}
+
+type SystemResourceInfo struct {
+ // The total physical memory in bytes.
+ TotalPhysicalMemory *uint64 `protobuf:"varint,1,opt,name=total_physical_memory,json=totalPhysicalMemory" json:"total_physical_memory,omitempty"`
+ // The total of available cores for building
+ AvailableCpus *int32 `protobuf:"varint,2,opt,name=available_cpus,json=availableCpus" json:"available_cpus,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *SystemResourceInfo) Reset() { *m = SystemResourceInfo{} }
+func (m *SystemResourceInfo) String() string { return proto.CompactTextString(m) }
+func (*SystemResourceInfo) ProtoMessage() {}
+func (*SystemResourceInfo) Descriptor() ([]byte, []int) {
+ return fileDescriptor_6039342a2ba47b72, []int{2}
+}
+
+func (m *SystemResourceInfo) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_SystemResourceInfo.Unmarshal(m, b)
+}
+func (m *SystemResourceInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_SystemResourceInfo.Marshal(b, m, deterministic)
+}
+func (m *SystemResourceInfo) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_SystemResourceInfo.Merge(m, src)
+}
+func (m *SystemResourceInfo) XXX_Size() int {
+ return xxx_messageInfo_SystemResourceInfo.Size(m)
+}
+func (m *SystemResourceInfo) XXX_DiscardUnknown() {
+ xxx_messageInfo_SystemResourceInfo.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SystemResourceInfo proto.InternalMessageInfo
+
+func (m *SystemResourceInfo) GetTotalPhysicalMemory() uint64 {
+ if m != nil && m.TotalPhysicalMemory != nil {
+ return *m.TotalPhysicalMemory
+ }
+ return 0
+}
+
+func (m *SystemResourceInfo) GetAvailableCpus() int32 {
+ if m != nil && m.AvailableCpus != nil {
+ return *m.AvailableCpus
+ }
+ return 0
+}
+
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"`
@@ -454,18 +547,20 @@
// The real running time.
// The number of nanoseconds elapsed since start_time.
RealTime *uint64 `protobuf:"varint,4,opt,name=real_time,json=realTime" json:"real_time,omitempty"`
- // The number of MB for memory use.
- MemoryUse *uint64 `protobuf:"varint,5,opt,name=memory_use,json=memoryUse" json:"memory_use,omitempty"`
- XXX_NoUnkeyedLiteral struct{} `json:"-"`
- XXX_unrecognized []byte `json:"-"`
- XXX_sizecache int32 `json:"-"`
+ // The number of MB for memory use (deprecated as it is too generic).
+ MemoryUse *uint64 `protobuf:"varint,5,opt,name=memory_use,json=memoryUse" json:"memory_use,omitempty"` // Deprecated: Do not use.
+ // The resource information of each executed process.
+ ProcessesResourceInfo []*ProcessResourceInfo `protobuf:"bytes,6,rep,name=processes_resource_info,json=processesResourceInfo" json:"processes_resource_info,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
func (m *PerfInfo) Reset() { *m = PerfInfo{} }
func (m *PerfInfo) String() string { return proto.CompactTextString(m) }
func (*PerfInfo) ProtoMessage() {}
func (*PerfInfo) Descriptor() ([]byte, []int) {
- return fileDescriptor_6039342a2ba47b72, []int{2}
+ return fileDescriptor_6039342a2ba47b72, []int{3}
}
func (m *PerfInfo) XXX_Unmarshal(b []byte) error {
@@ -514,6 +609,7 @@
return 0
}
+// Deprecated: Do not use.
func (m *PerfInfo) GetMemoryUse() uint64 {
if m != nil && m.MemoryUse != nil {
return *m.MemoryUse
@@ -521,6 +617,134 @@
return 0
}
+func (m *PerfInfo) GetProcessesResourceInfo() []*ProcessResourceInfo {
+ if m != nil {
+ return m.ProcessesResourceInfo
+ }
+ return nil
+}
+
+type ProcessResourceInfo struct {
+ // The name of the process for identification.
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ // The amount of time spent executing in user space in microseconds.
+ UserTimeMicros *uint64 `protobuf:"varint,2,opt,name=user_time_micros,json=userTimeMicros" json:"user_time_micros,omitempty"`
+ // The amount of time spent executing in kernel mode in microseconds.
+ SystemTimeMicros *uint64 `protobuf:"varint,3,opt,name=system_time_micros,json=systemTimeMicros" json:"system_time_micros,omitempty"`
+ // The maximum resident set size memory used in kilobytes.
+ MaxRssKb *uint64 `protobuf:"varint,4,opt,name=max_rss_kb,json=maxRssKb" json:"max_rss_kb,omitempty"`
+ // The number of minor page faults serviced without any I/O activity.
+ MinorPageFaults *uint64 `protobuf:"varint,5,opt,name=minor_page_faults,json=minorPageFaults" json:"minor_page_faults,omitempty"`
+ // The number of major page faults serviced that required I/O activity.
+ MajorPageFaults *uint64 `protobuf:"varint,6,opt,name=major_page_faults,json=majorPageFaults" json:"major_page_faults,omitempty"`
+ // Total IO input in kilobytes.
+ IoInputKb *uint64 `protobuf:"varint,7,opt,name=io_input_kb,json=ioInputKb" json:"io_input_kb,omitempty"`
+ // Total IO output in kilobytes.
+ IoOutputKb *uint64 `protobuf:"varint,8,opt,name=io_output_kb,json=ioOutputKb" json:"io_output_kb,omitempty"`
+ // The number of voluntary context switches
+ VoluntaryContextSwitches *uint64 `protobuf:"varint,9,opt,name=voluntary_context_switches,json=voluntaryContextSwitches" json:"voluntary_context_switches,omitempty"`
+ // The number of involuntary context switches
+ InvoluntaryContextSwitches *uint64 `protobuf:"varint,10,opt,name=involuntary_context_switches,json=involuntaryContextSwitches" json:"involuntary_context_switches,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *ProcessResourceInfo) Reset() { *m = ProcessResourceInfo{} }
+func (m *ProcessResourceInfo) String() string { return proto.CompactTextString(m) }
+func (*ProcessResourceInfo) ProtoMessage() {}
+func (*ProcessResourceInfo) Descriptor() ([]byte, []int) {
+ return fileDescriptor_6039342a2ba47b72, []int{4}
+}
+
+func (m *ProcessResourceInfo) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_ProcessResourceInfo.Unmarshal(m, b)
+}
+func (m *ProcessResourceInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_ProcessResourceInfo.Marshal(b, m, deterministic)
+}
+func (m *ProcessResourceInfo) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ProcessResourceInfo.Merge(m, src)
+}
+func (m *ProcessResourceInfo) XXX_Size() int {
+ return xxx_messageInfo_ProcessResourceInfo.Size(m)
+}
+func (m *ProcessResourceInfo) XXX_DiscardUnknown() {
+ xxx_messageInfo_ProcessResourceInfo.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ProcessResourceInfo proto.InternalMessageInfo
+
+func (m *ProcessResourceInfo) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *ProcessResourceInfo) GetUserTimeMicros() uint64 {
+ if m != nil && m.UserTimeMicros != nil {
+ return *m.UserTimeMicros
+ }
+ return 0
+}
+
+func (m *ProcessResourceInfo) GetSystemTimeMicros() uint64 {
+ if m != nil && m.SystemTimeMicros != nil {
+ return *m.SystemTimeMicros
+ }
+ return 0
+}
+
+func (m *ProcessResourceInfo) GetMaxRssKb() uint64 {
+ if m != nil && m.MaxRssKb != nil {
+ return *m.MaxRssKb
+ }
+ return 0
+}
+
+func (m *ProcessResourceInfo) GetMinorPageFaults() uint64 {
+ if m != nil && m.MinorPageFaults != nil {
+ return *m.MinorPageFaults
+ }
+ return 0
+}
+
+func (m *ProcessResourceInfo) GetMajorPageFaults() uint64 {
+ if m != nil && m.MajorPageFaults != nil {
+ return *m.MajorPageFaults
+ }
+ return 0
+}
+
+func (m *ProcessResourceInfo) GetIoInputKb() uint64 {
+ if m != nil && m.IoInputKb != nil {
+ return *m.IoInputKb
+ }
+ return 0
+}
+
+func (m *ProcessResourceInfo) GetIoOutputKb() uint64 {
+ if m != nil && m.IoOutputKb != nil {
+ return *m.IoOutputKb
+ }
+ return 0
+}
+
+func (m *ProcessResourceInfo) GetVoluntaryContextSwitches() uint64 {
+ if m != nil && m.VoluntaryContextSwitches != nil {
+ return *m.VoluntaryContextSwitches
+ }
+ return 0
+}
+
+func (m *ProcessResourceInfo) GetInvoluntaryContextSwitches() uint64 {
+ if m != nil && m.InvoluntaryContextSwitches != nil {
+ return *m.InvoluntaryContextSwitches
+ }
+ return 0
+}
+
type ModuleTypeInfo struct {
// The build system, eg. Soong or Make.
BuildSystem *ModuleTypeInfo_BuildSystem `protobuf:"varint,1,opt,name=build_system,json=buildSystem,enum=soong_build_metrics.ModuleTypeInfo_BuildSystem,def=0" json:"build_system,omitempty"`
@@ -537,7 +761,7 @@
func (m *ModuleTypeInfo) String() string { return proto.CompactTextString(m) }
func (*ModuleTypeInfo) ProtoMessage() {}
func (*ModuleTypeInfo) Descriptor() ([]byte, []int) {
- return fileDescriptor_6039342a2ba47b72, []int{3}
+ return fileDescriptor_6039342a2ba47b72, []int{5}
}
func (m *ModuleTypeInfo) XXX_Unmarshal(b []byte) error {
@@ -595,7 +819,7 @@
func (m *CriticalUserJourneyMetrics) String() string { return proto.CompactTextString(m) }
func (*CriticalUserJourneyMetrics) ProtoMessage() {}
func (*CriticalUserJourneyMetrics) Descriptor() ([]byte, []int) {
- return fileDescriptor_6039342a2ba47b72, []int{4}
+ return fileDescriptor_6039342a2ba47b72, []int{6}
}
func (m *CriticalUserJourneyMetrics) XXX_Unmarshal(b []byte) error {
@@ -642,7 +866,7 @@
func (m *CriticalUserJourneysMetrics) String() string { return proto.CompactTextString(m) }
func (*CriticalUserJourneysMetrics) ProtoMessage() {}
func (*CriticalUserJourneysMetrics) Descriptor() ([]byte, []int) {
- return fileDescriptor_6039342a2ba47b72, []int{5}
+ return fileDescriptor_6039342a2ba47b72, []int{7}
}
func (m *CriticalUserJourneysMetrics) XXX_Unmarshal(b []byte) error {
@@ -690,7 +914,7 @@
func (m *SoongBuildMetrics) String() string { return proto.CompactTextString(m) }
func (*SoongBuildMetrics) ProtoMessage() {}
func (*SoongBuildMetrics) Descriptor() ([]byte, []int) {
- return fileDescriptor_6039342a2ba47b72, []int{6}
+ return fileDescriptor_6039342a2ba47b72, []int{8}
}
func (m *SoongBuildMetrics) XXX_Unmarshal(b []byte) error {
@@ -752,7 +976,9 @@
proto.RegisterEnum("soong_build_metrics.ModuleTypeInfo_BuildSystem", ModuleTypeInfo_BuildSystem_name, ModuleTypeInfo_BuildSystem_value)
proto.RegisterType((*MetricsBase)(nil), "soong_build_metrics.MetricsBase")
proto.RegisterType((*BuildConfig)(nil), "soong_build_metrics.BuildConfig")
+ proto.RegisterType((*SystemResourceInfo)(nil), "soong_build_metrics.SystemResourceInfo")
proto.RegisterType((*PerfInfo)(nil), "soong_build_metrics.PerfInfo")
+ proto.RegisterType((*ProcessResourceInfo)(nil), "soong_build_metrics.ProcessResourceInfo")
proto.RegisterType((*ModuleTypeInfo)(nil), "soong_build_metrics.ModuleTypeInfo")
proto.RegisterType((*CriticalUserJourneyMetrics)(nil), "soong_build_metrics.CriticalUserJourneyMetrics")
proto.RegisterType((*CriticalUserJourneysMetrics)(nil), "soong_build_metrics.CriticalUserJourneysMetrics")
@@ -764,69 +990,92 @@
}
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,
+ // 1380 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0xef, 0x52, 0x1b, 0x37,
+ 0x10, 0x8f, 0xc1, 0x60, 0x7b, 0xfd, 0x07, 0x23, 0xa0, 0x5c, 0x48, 0xd2, 0x52, 0xb7, 0x49, 0x99,
+ 0x4e, 0x43, 0x32, 0x34, 0xc3, 0x64, 0x98, 0x4c, 0xa7, 0xe0, 0xd0, 0x34, 0x65, 0xc0, 0x8c, 0x08,
+ 0x69, 0xda, 0x7e, 0x50, 0xe5, 0xb3, 0x0c, 0x97, 0xdc, 0x9d, 0x6e, 0x24, 0x1d, 0xc5, 0x79, 0xb3,
+ 0x7e, 0xee, 0x4b, 0xf4, 0x05, 0xfa, 0x04, 0x7d, 0x81, 0x8e, 0x56, 0x77, 0xe6, 0x20, 0x6e, 0xc2,
+ 0xe4, 0xdb, 0xe9, 0xb7, 0xbf, 0xdf, 0x6a, 0xb5, 0xd2, 0xee, 0xda, 0xd0, 0x8c, 0x84, 0x51, 0x81,
+ 0xaf, 0xd7, 0x13, 0x25, 0x8d, 0x24, 0x0b, 0x5a, 0xca, 0xf8, 0x84, 0xf5, 0xd3, 0x20, 0x1c, 0xb0,
+ 0xcc, 0xd4, 0xf9, 0xbb, 0x01, 0xf5, 0x7d, 0xf7, 0xbd, 0xc3, 0xb5, 0x20, 0x0f, 0x61, 0xd1, 0x11,
+ 0x06, 0xdc, 0x08, 0x66, 0x82, 0x48, 0x68, 0xc3, 0xa3, 0xc4, 0x2b, 0xad, 0x96, 0xd6, 0xa6, 0x29,
+ 0x41, 0xdb, 0x53, 0x6e, 0xc4, 0x8b, 0xdc, 0x42, 0x6e, 0x42, 0xd5, 0x29, 0x82, 0x81, 0x37, 0xb5,
+ 0x5a, 0x5a, 0xab, 0xd1, 0x0a, 0xae, 0x9f, 0x0f, 0xc8, 0x16, 0xdc, 0x4c, 0x42, 0x6e, 0x86, 0x52,
+ 0x45, 0xec, 0x4c, 0x28, 0x1d, 0xc8, 0x98, 0xf9, 0x72, 0x20, 0x62, 0x1e, 0x09, 0x6f, 0x1a, 0xb9,
+ 0xcb, 0x39, 0xe1, 0xa5, 0xb3, 0x77, 0x33, 0x33, 0xb9, 0x0b, 0x2d, 0xc3, 0xd5, 0x89, 0x30, 0x2c,
+ 0x51, 0x72, 0x90, 0xfa, 0xc6, 0x2b, 0xa3, 0xa0, 0xe9, 0xd0, 0x43, 0x07, 0x92, 0x01, 0x2c, 0x66,
+ 0x34, 0x17, 0xc4, 0x19, 0x57, 0x01, 0x8f, 0x8d, 0x37, 0xb3, 0x5a, 0x5a, 0x6b, 0x6d, 0xdc, 0x5f,
+ 0x9f, 0x70, 0xe6, 0xf5, 0xc2, 0x79, 0xd7, 0x77, 0xac, 0xe5, 0xa5, 0x13, 0x6d, 0x4d, 0xef, 0x1e,
+ 0x3c, 0xa3, 0xc4, 0xf9, 0x2b, 0x1a, 0x48, 0x0f, 0xea, 0xd9, 0x2e, 0x5c, 0xf9, 0xa7, 0xde, 0x2c,
+ 0x3a, 0xbf, 0xfb, 0x41, 0xe7, 0xdb, 0xca, 0x3f, 0xdd, 0xaa, 0x1c, 0x1f, 0xec, 0x1d, 0xf4, 0x7e,
+ 0x3e, 0xa0, 0xe0, 0x5c, 0x58, 0x90, 0xac, 0xc3, 0x42, 0xc1, 0xe1, 0x38, 0xea, 0x0a, 0x1e, 0x71,
+ 0xfe, 0x82, 0x98, 0x07, 0xf0, 0x0d, 0x64, 0x61, 0x31, 0x3f, 0x49, 0xc7, 0xf4, 0x2a, 0xd2, 0xdb,
+ 0xce, 0xd2, 0x4d, 0xd2, 0x9c, 0xbd, 0x07, 0xb5, 0x53, 0xa9, 0xb3, 0x60, 0x6b, 0x1f, 0x15, 0x6c,
+ 0xd5, 0x3a, 0xc0, 0x50, 0x29, 0x34, 0xd1, 0xd9, 0x46, 0x3c, 0x70, 0x0e, 0xe1, 0xa3, 0x1c, 0xd6,
+ 0xad, 0x93, 0x8d, 0x78, 0x80, 0x3e, 0x97, 0xa1, 0x82, 0x3e, 0xa5, 0xf6, 0xea, 0x78, 0x86, 0x59,
+ 0xbb, 0xec, 0x69, 0xd2, 0xc9, 0x36, 0x93, 0x9a, 0x89, 0x73, 0xa3, 0xb8, 0xd7, 0x40, 0x73, 0xdd,
+ 0x99, 0x77, 0x2d, 0x34, 0xe6, 0xf8, 0x4a, 0x6a, 0x6d, 0x5d, 0x34, 0x2f, 0x38, 0x5d, 0x8b, 0xf5,
+ 0x34, 0xb9, 0x07, 0x73, 0x05, 0x0e, 0x86, 0xdd, 0x72, 0xcf, 0x67, 0xcc, 0xc2, 0x40, 0xee, 0xc3,
+ 0x42, 0x81, 0x37, 0x3e, 0xe2, 0x9c, 0x4b, 0xec, 0x98, 0x5b, 0x88, 0x5b, 0xa6, 0x86, 0x0d, 0x02,
+ 0xe5, 0xb5, 0x5d, 0xdc, 0x32, 0x35, 0x4f, 0x03, 0x45, 0xbe, 0x83, 0xba, 0x16, 0x26, 0x4d, 0x98,
+ 0x91, 0x32, 0xd4, 0xde, 0xfc, 0xea, 0xf4, 0x5a, 0x7d, 0xe3, 0xce, 0xc4, 0x14, 0x1d, 0x0a, 0x35,
+ 0x7c, 0x1e, 0x0f, 0x25, 0x05, 0x54, 0xbc, 0xb0, 0x02, 0xb2, 0x05, 0xb5, 0x37, 0xdc, 0x04, 0x4c,
+ 0xa5, 0xb1, 0xf6, 0xc8, 0x75, 0xd4, 0x55, 0xcb, 0xa7, 0x69, 0xac, 0xc9, 0x13, 0x00, 0xc7, 0x44,
+ 0xf1, 0xc2, 0x75, 0xc4, 0x35, 0xb4, 0xe6, 0xea, 0x38, 0x88, 0x5f, 0x73, 0xa7, 0x5e, 0xbc, 0x96,
+ 0x1a, 0x05, 0xa8, 0xfe, 0x16, 0x66, 0x8c, 0x34, 0x3c, 0xf4, 0x96, 0x56, 0x4b, 0x1f, 0x16, 0x3a,
+ 0x2e, 0x79, 0x09, 0x93, 0x5a, 0x91, 0xf7, 0x09, 0xba, 0xb8, 0x37, 0xd1, 0xc5, 0x91, 0xc5, 0xb0,
+ 0x24, 0xb3, 0x17, 0x46, 0xe7, 0xf5, 0x55, 0x88, 0x74, 0xa1, 0xe1, 0x54, 0xbe, 0x8c, 0x87, 0xc1,
+ 0x89, 0xb7, 0x8c, 0x0e, 0x57, 0x27, 0x3a, 0x44, 0x61, 0x17, 0x79, 0xb4, 0xde, 0xbf, 0x58, 0x90,
+ 0x15, 0xc0, 0xa7, 0x8f, 0x2d, 0xca, 0xc3, 0x3b, 0x1e, 0xaf, 0xc9, 0x2f, 0xb0, 0xa8, 0x47, 0xda,
+ 0x88, 0x88, 0x29, 0xa1, 0x65, 0xaa, 0x7c, 0xc1, 0x82, 0x78, 0x28, 0xbd, 0x9b, 0xb8, 0xd1, 0x57,
+ 0x93, 0x23, 0x47, 0x01, 0xcd, 0xf8, 0x98, 0x06, 0xa2, 0xdf, 0xc1, 0xc8, 0x17, 0xd0, 0xcc, 0x63,
+ 0x8f, 0x22, 0x1e, 0x0f, 0xbc, 0x15, 0xdc, 0xbb, 0x91, 0x85, 0x86, 0x98, 0xbd, 0xab, 0x3e, 0x7f,
+ 0x2b, 0x42, 0x77, 0x57, 0xb7, 0xae, 0x75, 0x57, 0x28, 0xb0, 0x77, 0xd5, 0x79, 0x08, 0x8d, 0x4b,
+ 0x4d, 0xad, 0x0a, 0xe5, 0xe3, 0xa3, 0x5d, 0xda, 0xbe, 0x41, 0x9a, 0x50, 0xb3, 0x5f, 0x4f, 0x77,
+ 0x77, 0x8e, 0x9f, 0xb5, 0x4b, 0xa4, 0x02, 0xb6, 0x11, 0xb6, 0xa7, 0x3a, 0x4f, 0xa0, 0x8c, 0xcf,
+ 0xbe, 0x0e, 0x79, 0x19, 0xb7, 0x6f, 0x58, 0xeb, 0x36, 0xdd, 0x6f, 0x97, 0x48, 0x0d, 0x66, 0xb6,
+ 0xe9, 0xfe, 0xe6, 0xa3, 0xf6, 0x94, 0xc5, 0x5e, 0x3d, 0xde, 0x6c, 0x4f, 0x13, 0x80, 0xd9, 0x57,
+ 0x8f, 0x37, 0xd9, 0xe6, 0xa3, 0x76, 0xb9, 0x73, 0x02, 0xf5, 0x42, 0x96, 0xed, 0x9c, 0x48, 0xb5,
+ 0x60, 0x27, 0x32, 0xe2, 0x38, 0x4d, 0xaa, 0xb4, 0x92, 0x6a, 0xf1, 0x4c, 0x46, 0xdc, 0x96, 0x95,
+ 0x35, 0xa9, 0xbe, 0xc0, 0x09, 0x52, 0xa5, 0xb3, 0xa9, 0x16, 0xb4, 0x2f, 0xc8, 0x97, 0xd0, 0x1a,
+ 0x4a, 0x9b, 0xe6, 0xb1, 0x72, 0x1a, 0xed, 0x0d, 0x44, 0x8f, 0x9d, 0xbc, 0x23, 0x81, 0xbc, 0x9b,
+ 0x65, 0xb2, 0x01, 0x4b, 0xf8, 0xdc, 0x58, 0x72, 0x3a, 0xd2, 0x81, 0xcf, 0x43, 0x16, 0x89, 0x48,
+ 0xaa, 0x11, 0x6e, 0x5e, 0xa6, 0x0b, 0x68, 0x3c, 0xcc, 0x6c, 0xfb, 0x68, 0xb2, 0x43, 0x87, 0x9f,
+ 0xf1, 0x20, 0xe4, 0xfd, 0x50, 0xd8, 0x4e, 0xab, 0x31, 0x9e, 0x19, 0xda, 0x1c, 0xa3, 0xdd, 0x24,
+ 0xd5, 0x9d, 0x7f, 0x4b, 0x50, 0xcd, 0x33, 0x4c, 0x08, 0x94, 0x07, 0x42, 0xfb, 0xe8, 0xb6, 0x46,
+ 0xf1, 0xdb, 0x62, 0xf8, 0x80, 0xdc, 0x3c, 0xc4, 0x6f, 0x72, 0x07, 0x40, 0x1b, 0xae, 0x0c, 0x0e,
+ 0x55, 0x3c, 0x47, 0x99, 0xd6, 0x10, 0xb1, 0xb3, 0x94, 0xdc, 0x82, 0x9a, 0x12, 0x3c, 0x74, 0xd6,
+ 0x32, 0x5a, 0xab, 0x16, 0x40, 0xe3, 0xe7, 0x00, 0x2e, 0x78, 0x9b, 0x08, 0x9c, 0x6d, 0xe5, 0x9d,
+ 0x29, 0xaf, 0x44, 0x6b, 0x0e, 0x3d, 0xd6, 0x82, 0xfc, 0x0e, 0xcb, 0x89, 0x92, 0xbe, 0xd0, 0x5a,
+ 0xe8, 0x2b, 0xcf, 0x73, 0x16, 0x1f, 0xca, 0xda, 0xe4, 0x87, 0xe2, 0x34, 0x97, 0xde, 0xe7, 0xd2,
+ 0xd8, 0x51, 0x11, 0xee, 0xfc, 0x39, 0x0d, 0x0b, 0x13, 0xe8, 0xe3, 0xc3, 0x96, 0x0a, 0x87, 0x5d,
+ 0x83, 0x76, 0xaa, 0x85, 0xc2, 0xd3, 0xb0, 0x28, 0xb0, 0xed, 0x15, 0x93, 0x51, 0xa6, 0x2d, 0x8b,
+ 0xdb, 0x43, 0xed, 0x23, 0x6a, 0x27, 0x5b, 0x56, 0x53, 0x45, 0xae, 0x4b, 0x4f, 0xdb, 0x59, 0x0a,
+ 0xec, 0xdb, 0x00, 0x11, 0x3f, 0x67, 0x4a, 0x6b, 0xf6, 0xa6, 0x9f, 0xa7, 0x29, 0xe2, 0xe7, 0x54,
+ 0xeb, 0xbd, 0x3e, 0xf9, 0x1a, 0xe6, 0xa3, 0x20, 0x96, 0x8a, 0x25, 0xfc, 0x44, 0xb0, 0x21, 0x4f,
+ 0x43, 0xa3, 0x5d, 0xb6, 0xe8, 0x1c, 0x1a, 0x0e, 0xf9, 0x89, 0xf8, 0x01, 0x61, 0xe4, 0xf2, 0xd7,
+ 0x57, 0xb8, 0xb3, 0x19, 0xd7, 0x1a, 0x0a, 0xdc, 0x4f, 0xa1, 0x1e, 0x48, 0x16, 0xc4, 0x49, 0x6a,
+ 0xec, 0xb6, 0x15, 0x77, 0x77, 0x81, 0x7c, 0x6e, 0x91, 0xbd, 0x3e, 0x59, 0x85, 0x46, 0x20, 0x99,
+ 0x4c, 0x4d, 0x46, 0xa8, 0x22, 0x01, 0x02, 0xd9, 0x43, 0x68, 0xaf, 0x4f, 0x9e, 0xc0, 0xca, 0x99,
+ 0x0c, 0xd3, 0xd8, 0x70, 0x35, 0xb2, 0xed, 0xc9, 0x88, 0x73, 0xc3, 0xf4, 0x1f, 0x81, 0xf1, 0x4f,
+ 0x85, 0xc6, 0x11, 0x5d, 0xa6, 0xde, 0x98, 0xd1, 0x75, 0x84, 0xa3, 0xcc, 0x4e, 0xbe, 0x87, 0xdb,
+ 0x41, 0xfc, 0x1e, 0x3d, 0xa0, 0x7e, 0xa5, 0xc0, 0xb9, 0xe2, 0xa1, 0xf3, 0x4f, 0x09, 0x5a, 0xfb,
+ 0x72, 0x90, 0x86, 0xe2, 0xc5, 0x28, 0x71, 0xd7, 0xf6, 0x5b, 0xde, 0x2d, 0x5d, 0x92, 0xf1, 0xfa,
+ 0x5a, 0x1b, 0x0f, 0x26, 0x8f, 0xf5, 0x4b, 0x52, 0xd7, 0x3c, 0x5d, 0xc9, 0x15, 0x06, 0x7c, 0xff,
+ 0x02, 0x25, 0x9f, 0x41, 0x3d, 0x42, 0x0d, 0x33, 0xa3, 0x24, 0xaf, 0x03, 0x88, 0xc6, 0x6e, 0x6c,
+ 0x65, 0xc7, 0x69, 0xc4, 0xe4, 0x90, 0x39, 0xd0, 0x5d, 0x79, 0x93, 0x36, 0xe2, 0x34, 0xea, 0x0d,
+ 0xdd, 0x7e, 0xba, 0xf3, 0x20, 0x6b, 0x21, 0x99, 0xd7, 0x4b, 0x7d, 0xa8, 0x06, 0x33, 0x47, 0xbd,
+ 0xde, 0x81, 0x6d, 0x58, 0x55, 0x28, 0xef, 0x6f, 0xef, 0xed, 0xb6, 0xa7, 0x3a, 0x21, 0xac, 0x74,
+ 0x55, 0x60, 0x6c, 0x49, 0x1f, 0x6b, 0xa1, 0x7e, 0x92, 0xa9, 0x8a, 0xc5, 0x28, 0x1f, 0x10, 0x93,
+ 0x5e, 0xea, 0x16, 0x54, 0xf2, 0x01, 0x34, 0xf5, 0x9e, 0x79, 0x51, 0xf8, 0x61, 0x43, 0x73, 0x41,
+ 0xa7, 0x0f, 0xb7, 0x26, 0xec, 0xa6, 0x2f, 0xe6, 0x51, 0xd9, 0x4f, 0x5f, 0x6b, 0xaf, 0x84, 0xf5,
+ 0x37, 0x39, 0xb3, 0xff, 0x1f, 0x2d, 0x45, 0x71, 0xe7, 0xaf, 0x12, 0xcc, 0xbf, 0x33, 0xfd, 0x88,
+ 0x07, 0x95, 0x3c, 0x6f, 0x25, 0xcc, 0x5b, 0xbe, 0xb4, 0xf3, 0x2b, 0xfb, 0x79, 0xe8, 0x0e, 0xd4,
+ 0xa4, 0xe3, 0xb5, 0x7d, 0xf3, 0xae, 0x25, 0xf2, 0x30, 0x94, 0x3e, 0xf3, 0x65, 0x1a, 0x9b, 0xac,
+ 0xd4, 0xe6, 0xd0, 0xb0, 0x6d, 0xf1, 0xae, 0x85, 0x6d, 0x05, 0x17, 0xb9, 0x3a, 0x78, 0x9b, 0xb7,
+ 0xa5, 0xd6, 0x05, 0xf5, 0x28, 0x78, 0x2b, 0xec, 0xef, 0x31, 0x5b, 0x93, 0xa7, 0x82, 0x27, 0x8e,
+ 0xe6, 0x2a, 0xae, 0x1e, 0xf1, 0xf3, 0x1f, 0x05, 0x4f, 0x2c, 0x67, 0x67, 0xe9, 0xd7, 0x6c, 0xe4,
+ 0x67, 0xe7, 0x66, 0xf8, 0x97, 0xe4, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcb, 0xfb, 0x8e, 0xf5,
+ 0xa2, 0x0c, 0x00, 0x00,
}
diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto
index 6559ba3..91d8dd9 100644
--- a/ui/metrics/metrics_proto/metrics.proto
+++ b/ui/metrics/metrics_proto/metrics.proto
@@ -96,12 +96,34 @@
optional SoongBuildMetrics soong_build_metrics = 22;
optional BuildConfig build_config = 23;
+
+ // The hostname of the machine.
+ optional string hostname = 24;
+
+ // The system resource information such as total physical memory.
+ optional SystemResourceInfo system_resource_info = 25;
+
+ // The build command that the user entered to the build system.
+ optional string build_command = 26;
+
+ // The metrics for calling Bazel.
+ repeated PerfInfo bazel_runs = 27;
}
message BuildConfig {
optional bool use_goma = 1;
optional bool use_rbe = 2;
+
+ optional bool force_use_goma = 3;
+}
+
+message SystemResourceInfo {
+ // The total physical memory in bytes.
+ optional uint64 total_physical_memory = 1;
+
+ // The total of available cores for building
+ optional int32 available_cpus = 2;
}
message PerfInfo {
@@ -119,8 +141,43 @@
// The number of nanoseconds elapsed since start_time.
optional uint64 real_time = 4;
- // The number of MB for memory use.
- optional uint64 memory_use = 5;
+ // The number of MB for memory use (deprecated as it is too generic).
+ optional uint64 memory_use = 5 [deprecated=true];
+
+ // The resource information of each executed process.
+ repeated ProcessResourceInfo processes_resource_info = 6;
+}
+
+message ProcessResourceInfo {
+ // The name of the process for identification.
+ optional string name = 1;
+
+ // The amount of time spent executing in user space in microseconds.
+ optional uint64 user_time_micros = 2;
+
+ // The amount of time spent executing in kernel mode in microseconds.
+ optional uint64 system_time_micros = 3;
+
+ // The maximum resident set size memory used in kilobytes.
+ optional uint64 max_rss_kb = 4;
+
+ // The number of minor page faults serviced without any I/O activity.
+ optional uint64 minor_page_faults = 5;
+
+ // The number of major page faults serviced that required I/O activity.
+ optional uint64 major_page_faults = 6;
+
+ // Total IO input in kilobytes.
+ optional uint64 io_input_kb= 7;
+
+ // Total IO output in kilobytes.
+ optional uint64 io_output_kb = 8;
+
+ // The number of voluntary context switches
+ optional uint64 voluntary_context_switches = 9;
+
+ // The number of involuntary context switches
+ optional uint64 involuntary_context_switches = 10;
}
message ModuleTypeInfo {
diff --git a/ui/metrics/metrics_proto/regen.sh b/ui/metrics/metrics_proto/regen.sh
index 343c638..8eb2d74 100755
--- a/ui/metrics/metrics_proto/regen.sh
+++ b/ui/metrics/metrics_proto/regen.sh
@@ -1,3 +1,17 @@
#!/bin/bash
-aprotoc --go_out=paths=source_relative:. metrics.proto
+# Generates the golang source file of metrics.proto protobuf file.
+
+set -e
+
+function die() { echo "ERROR: $1" >&2; exit 1; }
+
+readonly error_msg="Maybe you need to run 'lunch aosp_arm-eng && m aprotoc blueprint_tools'?"
+
+if ! hash aprotoc &>/dev/null; then
+ die "could not find aprotoc. ${error_msg}"
+fi
+
+if ! aprotoc --go_out=paths=source_relative:. metrics.proto; then
+ die "build failed. ${error_msg}"
+fi
diff --git a/ui/metrics/time.go b/ui/metrics/time.go
deleted file mode 100644
index 4016563..0000000
--- a/ui/metrics/time.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2018 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 metrics
-
-import (
- "time"
-
- "android/soong/ui/metrics/metrics_proto"
- "android/soong/ui/tracer"
- "github.com/golang/protobuf/proto"
-)
-
-// for testing purpose only
-var _now = now
-
-type timeEvent struct {
- desc string
- name string
-
- // the time that the event started to occur.
- start time.Time
-}
-
-type TimeTracer interface {
- Begin(name, desc string, thread tracer.Thread)
- End(thread tracer.Thread) soong_metrics_proto.PerfInfo
-}
-
-type timeTracerImpl struct {
- activeEvents []timeEvent
-}
-
-var _ TimeTracer = &timeTracerImpl{}
-
-func now() time.Time {
- return time.Now()
-}
-
-func (t *timeTracerImpl) Begin(name, desc string, _ tracer.Thread) {
- t.activeEvents = append(t.activeEvents, timeEvent{name: name, desc: desc, start: _now()})
-}
-
-func (t *timeTracerImpl) End(tracer.Thread) soong_metrics_proto.PerfInfo {
- if len(t.activeEvents) < 1 {
- panic("Internal error: No pending events for endAt to end!")
- }
- lastEvent := t.activeEvents[len(t.activeEvents)-1]
- t.activeEvents = t.activeEvents[:len(t.activeEvents)-1]
- realTime := uint64(_now().Sub(lastEvent.start).Nanoseconds())
-
- return soong_metrics_proto.PerfInfo{
- Desc: proto.String(lastEvent.desc),
- Name: proto.String(lastEvent.name),
- StartTime: proto.Uint64(uint64(lastEvent.start.UnixNano())),
- RealTime: proto.Uint64(realTime),
- }
-}
diff --git a/ui/status/ninja.go b/ui/status/ninja.go
index a11774c..765679f 100644
--- a/ui/status/ninja.go
+++ b/ui/status/ninja.go
@@ -162,6 +162,17 @@
Action: started,
Output: msg.EdgeFinished.GetOutput(),
Error: err,
+ Stats: ActionResultStats{
+ UserTime: msg.EdgeFinished.GetUserTime(),
+ SystemTime: msg.EdgeFinished.GetSystemTime(),
+ MaxRssKB: msg.EdgeFinished.GetMaxRssKb(),
+ MinorPageFaults: msg.EdgeFinished.GetMinorPageFaults(),
+ MajorPageFaults: msg.EdgeFinished.GetMajorPageFaults(),
+ IOInputKB: msg.EdgeFinished.GetIoInputKb(),
+ IOOutputKB: msg.EdgeFinished.GetIoOutputKb(),
+ VoluntaryContextSwitches: msg.EdgeFinished.GetVoluntaryContextSwitches(),
+ InvoluntaryContextSwitches: msg.EdgeFinished.GetInvoluntaryContextSwitches(),
+ },
})
}
}
diff --git a/ui/status/ninja_frontend/frontend.pb.go b/ui/status/ninja_frontend/frontend.pb.go
index 7ba9de2..86e474b 100644
--- a/ui/status/ninja_frontend/frontend.pb.go
+++ b/ui/status/ninja_frontend/frontend.pb.go
@@ -371,10 +371,24 @@
// Number of milliseconds spent executing in user mode
UserTime *uint32 `protobuf:"varint,5,opt,name=user_time,json=userTime" json:"user_time,omitempty"`
// Number of milliseconds spent executing in kernel mode
- SystemTime *uint32 `protobuf:"varint,6,opt,name=system_time,json=systemTime" json:"system_time,omitempty"`
- XXX_NoUnkeyedLiteral struct{} `json:"-"`
- XXX_unrecognized []byte `json:"-"`
- XXX_sizecache int32 `json:"-"`
+ SystemTime *uint32 `protobuf:"varint,6,opt,name=system_time,json=systemTime" json:"system_time,omitempty"`
+ // Max resident set size in kB
+ MaxRssKb *uint64 `protobuf:"varint,7,opt,name=max_rss_kb,json=maxRssKb" json:"max_rss_kb,omitempty"`
+ // Minor page faults
+ MinorPageFaults *uint64 `protobuf:"varint,8,opt,name=minor_page_faults,json=minorPageFaults" json:"minor_page_faults,omitempty"`
+ // Major page faults
+ MajorPageFaults *uint64 `protobuf:"varint,9,opt,name=major_page_faults,json=majorPageFaults" json:"major_page_faults,omitempty"`
+ // IO input in kB
+ IoInputKb *uint64 `protobuf:"varint,10,opt,name=io_input_kb,json=ioInputKb" json:"io_input_kb,omitempty"`
+ // IO output in kB
+ IoOutputKb *uint64 `protobuf:"varint,11,opt,name=io_output_kb,json=ioOutputKb" json:"io_output_kb,omitempty"`
+ // Voluntary context switches
+ VoluntaryContextSwitches *uint64 `protobuf:"varint,12,opt,name=voluntary_context_switches,json=voluntaryContextSwitches" json:"voluntary_context_switches,omitempty"`
+ // Involuntary context switches
+ InvoluntaryContextSwitches *uint64 `protobuf:"varint,13,opt,name=involuntary_context_switches,json=involuntaryContextSwitches" json:"involuntary_context_switches,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
func (m *Status_EdgeFinished) Reset() { *m = Status_EdgeFinished{} }
@@ -444,6 +458,55 @@
return 0
}
+func (m *Status_EdgeFinished) GetMaxRssKb() uint64 {
+ if m != nil && m.MaxRssKb != nil {
+ return *m.MaxRssKb
+ }
+ return 0
+}
+
+func (m *Status_EdgeFinished) GetMinorPageFaults() uint64 {
+ if m != nil && m.MinorPageFaults != nil {
+ return *m.MinorPageFaults
+ }
+ return 0
+}
+
+func (m *Status_EdgeFinished) GetMajorPageFaults() uint64 {
+ if m != nil && m.MajorPageFaults != nil {
+ return *m.MajorPageFaults
+ }
+ return 0
+}
+
+func (m *Status_EdgeFinished) GetIoInputKb() uint64 {
+ if m != nil && m.IoInputKb != nil {
+ return *m.IoInputKb
+ }
+ return 0
+}
+
+func (m *Status_EdgeFinished) GetIoOutputKb() uint64 {
+ if m != nil && m.IoOutputKb != nil {
+ return *m.IoOutputKb
+ }
+ return 0
+}
+
+func (m *Status_EdgeFinished) GetVoluntaryContextSwitches() uint64 {
+ if m != nil && m.VoluntaryContextSwitches != nil {
+ return *m.VoluntaryContextSwitches
+ }
+ return 0
+}
+
+func (m *Status_EdgeFinished) GetInvoluntaryContextSwitches() uint64 {
+ if m != nil && m.InvoluntaryContextSwitches != nil {
+ return *m.InvoluntaryContextSwitches
+ }
+ return 0
+}
+
type Status_Message struct {
// Message priority level (DEBUG, INFO, WARNING, ERROR).
Level *Status_Message_Level `protobuf:"varint,1,opt,name=level,enum=ninja.Status_Message_Level,def=0" json:"level,omitempty"`
@@ -511,39 +574,48 @@
}
var fileDescriptor_eca3873955a29cfe = []byte{
- // 539 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x54, 0xd1, 0x6e, 0xd3, 0x4a,
- 0x10, 0xbd, 0x4e, 0xe2, 0x38, 0x1e, 0x27, 0xb9, 0x61, 0x25, 0x90, 0xeb, 0x0a, 0x35, 0xea, 0x53,
- 0x5f, 0x08, 0x12, 0x42, 0x42, 0x20, 0x24, 0x44, 0x44, 0x5a, 0x8a, 0x20, 0x95, 0xb6, 0x45, 0x48,
- 0xbc, 0x44, 0x4e, 0x77, 0x5a, 0x8c, 0xec, 0x75, 0xe4, 0xdd, 0x54, 0xe2, 0x37, 0xf8, 0x09, 0xfe,
- 0x80, 0xaf, 0xe3, 0x01, 0xed, 0xec, 0xda, 0x75, 0x68, 0xdf, 0x7c, 0x76, 0xce, 0x9c, 0x39, 0x7b,
- 0x76, 0x64, 0x18, 0x5f, 0x55, 0xa5, 0xd4, 0x28, 0xc5, 0x6c, 0x53, 0x95, 0xba, 0x64, 0xbe, 0xcc,
- 0xe4, 0xf7, 0xf4, 0xf0, 0x4f, 0x00, 0xfd, 0x73, 0x9d, 0xea, 0xad, 0x62, 0x2f, 0x21, 0xd2, 0xa5,
- 0x4e, 0xf3, 0x15, 0x8a, 0x6b, 0x54, 0xb1, 0x37, 0xf5, 0x8e, 0xa2, 0x67, 0xf1, 0x8c, 0x78, 0x33,
- 0xcb, 0x99, 0x5d, 0x18, 0xc2, 0xc2, 0xd4, 0x39, 0xe8, 0xe6, 0x9b, 0xbd, 0x81, 0xd1, 0x7a, 0x9b,
- 0xe5, 0x62, 0xa5, 0x74, 0x5a, 0x69, 0x14, 0x71, 0x87, 0x9a, 0x93, 0xdd, 0xe6, 0xb9, 0xa1, 0x9c,
- 0x5b, 0x06, 0x1f, 0xae, 0x5b, 0x88, 0xcd, 0x61, 0x6c, 0x05, 0xae, 0x32, 0x99, 0xa9, 0x6f, 0x28,
- 0xe2, 0x2e, 0x29, 0xec, 0xdf, 0xa3, 0x70, 0xec, 0x28, 0xdc, 0xce, 0xac, 0x21, 0x7b, 0x0d, 0x43,
- 0xe3, 0xbc, 0xf1, 0xd0, 0x23, 0x85, 0xbd, 0x5d, 0x05, 0xe3, 0xb7, 0xb6, 0x10, 0xe1, 0x2d, 0x30,
- 0x57, 0xa0, 0xee, 0xc6, 0x80, 0x7f, 0xdf, 0x15, 0x4c, 0x7b, 0x33, 0x9f, 0xc6, 0x35, 0xe3, 0x9f,
- 0x42, 0x50, 0xa0, 0x52, 0xe9, 0x35, 0xc6, 0x7d, 0x6a, 0x7d, 0xb8, 0xdb, 0xfa, 0xc9, 0x16, 0x79,
- 0xcd, 0x4a, 0x9e, 0x00, 0xdc, 0xc6, 0xc9, 0x0e, 0xee, 0xa6, 0x3f, 0x6a, 0x67, 0x9c, 0x7c, 0x80,
- 0x61, 0x3b, 0x40, 0x36, 0x85, 0x68, 0x93, 0x56, 0x69, 0x9e, 0x63, 0x9e, 0xa9, 0xc2, 0x35, 0xb4,
- 0x8f, 0x58, 0x0c, 0xc1, 0x0d, 0x56, 0xeb, 0x52, 0x21, 0xbd, 0xc7, 0x80, 0xd7, 0x30, 0xf9, 0x1f,
- 0x46, 0x3b, 0x51, 0x26, 0xbf, 0x3d, 0x88, 0x5a, 0xd1, 0xb0, 0x31, 0x74, 0x32, 0xe1, 0x34, 0x3b,
- 0x99, 0x60, 0x8f, 0x01, 0x28, 0xd6, 0x95, 0xce, 0x0a, 0xab, 0x36, 0xe2, 0x21, 0x9d, 0x5c, 0x64,
- 0x05, 0xb2, 0x47, 0xd0, 0xcf, 0xe4, 0x66, 0xab, 0x55, 0xdc, 0x9d, 0x76, 0x8f, 0x42, 0xee, 0x90,
- 0x71, 0x50, 0x6e, 0x35, 0x15, 0x7a, 0x54, 0xa8, 0x21, 0x63, 0xd0, 0x13, 0xa8, 0x2e, 0x29, 0xe5,
- 0x90, 0xd3, 0xb7, 0x61, 0x5f, 0x96, 0x45, 0x91, 0x4a, 0x41, 0x09, 0x86, 0xbc, 0x86, 0xb6, 0x22,
- 0x55, 0x99, 0x63, 0x1c, 0xd8, 0x9b, 0x38, 0x98, 0xfc, 0xf2, 0x60, 0xd8, 0x7e, 0x94, 0x3b, 0xce,
- 0xf7, 0x60, 0x80, 0x52, 0xb4, 0x7d, 0x07, 0x28, 0x45, 0xed, 0x5a, 0xd1, 0xdb, 0xd0, 0xb2, 0x3d,
- 0xe0, 0x0e, 0x99, 0x73, 0x6b, 0x93, 0x56, 0x28, 0xe4, 0x0e, 0xb1, 0x7d, 0x08, 0xb7, 0x0a, 0x2b,
- 0xab, 0xe5, 0x93, 0xd6, 0xc0, 0x1c, 0x90, 0xd8, 0x01, 0x44, 0xea, 0x87, 0xd2, 0x58, 0xd8, 0x72,
- 0xdf, 0xbe, 0x9f, 0x3d, 0x32, 0x84, 0xe4, 0xa7, 0x07, 0x81, 0xdb, 0x01, 0xf6, 0x02, 0xfc, 0x1c,
- 0x6f, 0x30, 0x27, 0x9f, 0xe3, 0x7f, 0xb7, 0xdc, 0xb1, 0x66, 0x1f, 0x0d, 0xe5, 0x55, 0xef, 0x74,
- 0x79, 0x7c, 0xc6, 0x2d, 0xdf, 0x04, 0x51, 0x2f, 0x59, 0xc7, 0x46, 0xe4, 0xe0, 0xe1, 0x73, 0xf0,
- 0x89, 0xcf, 0x06, 0x40, 0x1d, 0x93, 0xff, 0x58, 0x04, 0xc1, 0x97, 0xb7, 0x7c, 0x79, 0xba, 0x3c,
- 0x99, 0x78, 0x2c, 0x04, 0x7f, 0xc1, 0xf9, 0x19, 0x9f, 0x74, 0xcc, 0xe7, 0xbb, 0xc5, 0xfc, 0xf3,
- 0xc9, 0xa4, 0x3b, 0x67, 0xef, 0xbb, 0x5f, 0xc7, 0x34, 0x7c, 0x55, 0xff, 0x1f, 0xfe, 0x06, 0x00,
- 0x00, 0xff, 0xff, 0xaf, 0x93, 0x48, 0xcf, 0x2a, 0x04, 0x00, 0x00,
+ // 678 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x94, 0xff, 0x4e, 0xd4, 0x40,
+ 0x10, 0xc7, 0xbd, 0xdf, 0xd7, 0xe9, 0xdd, 0x71, 0x6c, 0xa2, 0x29, 0x05, 0xe5, 0xc2, 0x5f, 0xc4,
+ 0xc4, 0x33, 0x31, 0x26, 0x46, 0x43, 0xa2, 0x9e, 0x02, 0x22, 0x0a, 0x66, 0xc1, 0x98, 0xf8, 0x4f,
+ 0xb3, 0xbd, 0x2e, 0xb0, 0xd8, 0x76, 0x2f, 0xdd, 0x2d, 0xc2, 0x6b, 0xf8, 0x2c, 0xc6, 0xd7, 0xf1,
+ 0x55, 0xcc, 0xce, 0xb6, 0x47, 0x0f, 0x88, 0xff, 0x75, 0x66, 0x3e, 0xf3, 0x9d, 0xd9, 0x99, 0xed,
+ 0xc2, 0xe0, 0x24, 0x93, 0xa9, 0xe6, 0x69, 0x34, 0x9e, 0x65, 0x52, 0x4b, 0xd2, 0x4a, 0x45, 0x7a,
+ 0xce, 0x36, 0x7e, 0x03, 0xb4, 0x8f, 0x34, 0xd3, 0xb9, 0x22, 0x2f, 0xc1, 0xd5, 0x52, 0xb3, 0x38,
+ 0xe0, 0xd1, 0x29, 0x57, 0x5e, 0x6d, 0x54, 0xdb, 0x74, 0x9f, 0x79, 0x63, 0xe4, 0xc6, 0x96, 0x19,
+ 0x1f, 0x1b, 0x60, 0xdb, 0xc4, 0x29, 0xe8, 0xf9, 0x37, 0x79, 0x0d, 0xfd, 0x30, 0x17, 0x71, 0x14,
+ 0x28, 0xcd, 0x32, 0xcd, 0x23, 0xaf, 0x8e, 0xc9, 0xfe, 0x62, 0xf2, 0xc4, 0x20, 0x47, 0x96, 0xa0,
+ 0xbd, 0xb0, 0x62, 0x91, 0x09, 0x0c, 0xac, 0xc0, 0x89, 0x48, 0x85, 0x3a, 0xe3, 0x91, 0xd7, 0x40,
+ 0x85, 0xd5, 0x3b, 0x14, 0x76, 0x0a, 0x84, 0xda, 0x9a, 0xa5, 0x49, 0xb6, 0xa0, 0x67, 0x3a, 0x9f,
+ 0xf7, 0xd0, 0x44, 0x85, 0x95, 0x45, 0x05, 0xd3, 0x6f, 0xd9, 0x82, 0xcb, 0xaf, 0x0d, 0x73, 0x04,
+ 0xcc, 0x9e, 0x37, 0xd0, 0xba, 0xeb, 0x08, 0x26, 0x7d, 0x5e, 0x1f, 0xcb, 0xcd, 0xcb, 0x3f, 0x85,
+ 0x4e, 0xc2, 0x95, 0x62, 0xa7, 0xdc, 0x6b, 0x63, 0xea, 0xfd, 0xc5, 0xd4, 0xcf, 0x36, 0x48, 0x4b,
+ 0xca, 0x7f, 0x02, 0x70, 0x3d, 0x4e, 0xb2, 0x7e, 0x7b, 0xfa, 0xfd, 0xea, 0x8c, 0xfd, 0x8f, 0xd0,
+ 0xab, 0x0e, 0x90, 0x8c, 0xc0, 0x9d, 0xb1, 0x8c, 0xc5, 0x31, 0x8f, 0x85, 0x4a, 0x8a, 0x84, 0xaa,
+ 0x8b, 0x78, 0xd0, 0xb9, 0xe0, 0x59, 0x28, 0x15, 0xc7, 0x7d, 0x74, 0x69, 0x69, 0xfa, 0x4b, 0xd0,
+ 0x5f, 0x18, 0xa5, 0xff, 0xa7, 0x06, 0x6e, 0x65, 0x34, 0x64, 0x00, 0x75, 0x11, 0x15, 0x9a, 0x75,
+ 0x11, 0x91, 0x87, 0x00, 0x38, 0xd6, 0x40, 0x8b, 0xc4, 0xaa, 0xf5, 0xa9, 0x83, 0x9e, 0x63, 0x91,
+ 0x70, 0xf2, 0x00, 0xda, 0x22, 0x9d, 0xe5, 0x5a, 0x79, 0x8d, 0x51, 0x63, 0xd3, 0xa1, 0x85, 0x65,
+ 0x3a, 0x90, 0xb9, 0xc6, 0x40, 0x13, 0x03, 0xa5, 0x49, 0x08, 0x34, 0x23, 0xae, 0xa6, 0x38, 0x65,
+ 0x87, 0xe2, 0xb7, 0xa1, 0xa7, 0x32, 0x49, 0x58, 0x1a, 0xe1, 0x04, 0x1d, 0x5a, 0x9a, 0x36, 0x92,
+ 0x2a, 0x19, 0x73, 0xaf, 0x63, 0x4f, 0x52, 0x98, 0xfe, 0xdf, 0x06, 0xf4, 0xaa, 0x4b, 0xb9, 0xd5,
+ 0xf9, 0x0a, 0x74, 0x79, 0x1a, 0x55, 0xfb, 0xee, 0xf0, 0x34, 0x2a, 0xbb, 0x56, 0xb8, 0x1b, 0xbc,
+ 0x6c, 0xcb, 0xb4, 0xb0, 0x8c, 0xdf, 0xb6, 0x89, 0x57, 0xc8, 0xa1, 0x85, 0x45, 0x56, 0xc1, 0xc9,
+ 0x15, 0xcf, 0xac, 0x56, 0x0b, 0xb5, 0xba, 0xc6, 0x81, 0x62, 0xeb, 0xe0, 0xaa, 0x2b, 0xa5, 0x79,
+ 0x62, 0xc3, 0x6d, 0xbb, 0x3f, 0xeb, 0x42, 0x60, 0x0d, 0x20, 0x61, 0x97, 0x41, 0xa6, 0x54, 0xf0,
+ 0x23, 0xc4, 0x63, 0x34, 0x69, 0x37, 0x61, 0x97, 0x54, 0xa9, 0xfd, 0x90, 0x3c, 0x86, 0xe5, 0x44,
+ 0xa4, 0x32, 0x0b, 0x66, 0xcc, 0x5c, 0x42, 0x96, 0xc7, 0x5a, 0x79, 0x5d, 0x84, 0x96, 0x30, 0xf0,
+ 0x85, 0x9d, 0xf2, 0x1d, 0x74, 0x23, 0xcb, 0xce, 0x6f, 0xb0, 0x4e, 0xc1, 0x9a, 0x40, 0x85, 0x7d,
+ 0x04, 0xae, 0x90, 0x01, 0xae, 0xc3, 0x94, 0x05, 0xa4, 0x1c, 0x21, 0xf7, 0x8c, 0x67, 0x3f, 0x24,
+ 0x23, 0xe8, 0x09, 0x19, 0xd8, 0x03, 0x1a, 0xc0, 0x45, 0x00, 0x84, 0x3c, 0x44, 0xd7, 0x7e, 0x48,
+ 0xb6, 0xc0, 0xbf, 0x90, 0x71, 0x9e, 0x6a, 0x96, 0x5d, 0x05, 0x53, 0xf3, 0x86, 0x5c, 0xea, 0x40,
+ 0xfd, 0x14, 0x7a, 0x7a, 0xc6, 0x95, 0xd7, 0x43, 0xde, 0x9b, 0x13, 0xef, 0x2c, 0x70, 0x54, 0xc4,
+ 0xc9, 0x1b, 0x58, 0x13, 0xe9, 0x7f, 0xf2, 0xfb, 0x98, 0xef, 0x57, 0x98, 0x1b, 0x0a, 0xfe, 0xaf,
+ 0x1a, 0x74, 0x8a, 0x7f, 0x87, 0xbc, 0x80, 0x56, 0xcc, 0x2f, 0x78, 0x8c, 0xfb, 0x1d, 0xdc, 0x7c,
+ 0x1d, 0x0a, 0x6a, 0xfc, 0xc9, 0x20, 0xaf, 0x9a, 0x7b, 0x07, 0x3b, 0x87, 0xd4, 0xf2, 0xe6, 0x02,
+ 0x95, 0x3f, 0x67, 0xdd, 0x5e, 0xad, 0xc2, 0xdc, 0x78, 0x0e, 0x2d, 0xe4, 0x49, 0x17, 0x30, 0x63,
+ 0x78, 0x8f, 0xb8, 0xd0, 0xf9, 0xf6, 0x96, 0x1e, 0xec, 0x1d, 0xec, 0x0e, 0x6b, 0xc4, 0x81, 0xd6,
+ 0x36, 0xa5, 0x87, 0x74, 0x58, 0x37, 0x9f, 0xef, 0xb7, 0x27, 0x5f, 0x77, 0x87, 0x8d, 0x09, 0xf9,
+ 0xd0, 0xf8, 0x3e, 0xc0, 0xe2, 0x41, 0xf9, 0xae, 0xfe, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x2f, 0x7a,
+ 0x33, 0x13, 0x62, 0x05, 0x00, 0x00,
}
diff --git a/ui/status/ninja_frontend/frontend.proto b/ui/status/ninja_frontend/frontend.proto
index baa0046..e5e5d9f 100644
--- a/ui/status/ninja_frontend/frontend.proto
+++ b/ui/status/ninja_frontend/frontend.proto
@@ -65,6 +65,20 @@
optional uint32 user_time = 5;
// Number of milliseconds spent executing in kernel mode
optional uint32 system_time = 6;
+ // Max resident set size in kB
+ optional uint64 max_rss_kb = 7;
+ // Minor page faults
+ optional uint64 minor_page_faults = 8;
+ // Major page faults
+ optional uint64 major_page_faults = 9;
+ // IO input in kB
+ optional uint64 io_input_kb = 10;
+ // IO output in kB
+ optional uint64 io_output_kb = 11;
+ // Voluntary context switches
+ optional uint64 voluntary_context_switches = 12;
+ // Involuntary context switches
+ optional uint64 involuntary_context_switches = 13;
}
message Message {
diff --git a/ui/status/status.go b/ui/status/status.go
index df33baa..a5b4a28 100644
--- a/ui/status/status.go
+++ b/ui/status/status.go
@@ -54,6 +54,37 @@
// Error is nil if the Action succeeded, or set to an error if it
// failed.
Error error
+
+ Stats ActionResultStats
+}
+
+type ActionResultStats struct {
+ // Number of milliseconds spent executing in user mode
+ UserTime uint32
+
+ // Number of milliseconds spent executing in kernel mode
+ SystemTime uint32
+
+ // Max resident set size in kB
+ MaxRssKB uint64
+
+ // Minor page faults
+ MinorPageFaults uint64
+
+ // Major page faults
+ MajorPageFaults uint64
+
+ // IO input in kB
+ IOInputKB uint64
+
+ // IO output in kB
+ IOOutputKB uint64
+
+ // Voluntary context switches
+ VoluntaryContextSwitches uint64
+
+ // Involuntary context switches
+ InvoluntaryContextSwitches uint64
}
// Counts describes the number of actions in each state
diff --git a/ui/tracer/status.go b/ui/tracer/status.go
index c831255..a8b4e62 100644
--- a/ui/tracer/status.go
+++ b/ui/tracer/status.go
@@ -80,9 +80,32 @@
Dur: uint64(time.Since(start.start).Nanoseconds()) / 1000,
Pid: 1,
Tid: uint64(start.cpu),
+ Arg: &statsArg{
+ UserTime: result.Stats.UserTime,
+ SystemTime: result.Stats.SystemTime,
+ MaxRssKB: result.Stats.MaxRssKB,
+ MinorPageFaults: result.Stats.MinorPageFaults,
+ MajorPageFaults: result.Stats.MajorPageFaults,
+ IOInputKB: result.Stats.IOInputKB,
+ IOOutputKB: result.Stats.IOOutputKB,
+ VoluntaryContextSwitches: result.Stats.VoluntaryContextSwitches,
+ InvoluntaryContextSwitches: result.Stats.InvoluntaryContextSwitches,
+ },
})
}
+type statsArg struct {
+ UserTime uint32 `json:"user_time"`
+ SystemTime uint32 `json:"system_time_ms"`
+ MaxRssKB uint64 `json:"max_rss_kb"`
+ MinorPageFaults uint64 `json:"minor_page_faults"`
+ MajorPageFaults uint64 `json:"major_page_faults"`
+ IOInputKB uint64 `json:"io_input_kb"`
+ IOOutputKB uint64 `json:"io_output_kb"`
+ VoluntaryContextSwitches uint64 `json:"voluntary_context_switches"`
+ InvoluntaryContextSwitches uint64 `json:"involuntary_context_switches"`
+}
+
func (s *statusOutput) Flush() {}
func (s *statusOutput) Message(level status.MsgLevel, message string) {}
diff --git a/xml/xml_test.go b/xml/xml_test.go
index abcb108..138503c 100644
--- a/xml/xml_test.go
+++ b/xml/xml_test.go
@@ -57,10 +57,10 @@
"baz.xml": nil,
}
config := android.TestArchConfig(buildDir, nil, bp, fs)
- ctx := android.NewTestArchContext()
+ ctx := android.NewTestArchContext(config)
ctx.RegisterModuleType("prebuilt_etc", etc.PrebuiltEtcFactory)
ctx.RegisterModuleType("prebuilt_etc_xml", PrebuiltEtcXmlFactory)
- ctx.Register(config)
+ ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)