Merge "Apply PRODUCT_ENFORCE_RRO_TARGETS to dependencies."
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 4ba5241..2de0ca9 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -15,6 +15,7 @@
"apex.go",
"api_levels.go",
"arch.go",
+ "bazel_handler.go",
"bazel_overlay.go",
"config.go",
"csuite_config.go",
@@ -54,7 +55,6 @@
"util.go",
"variable.go",
"visibility.go",
- "vts_config.go",
"writedocs.go",
// Lock down environment access last
@@ -83,6 +83,5 @@
"util_test.go",
"variable_test.go",
"visibility_test.go",
- "vts_config_test.go",
],
}
diff --git a/android/apex.go b/android/apex.go
index 1589a17..c01b716 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -28,20 +28,29 @@
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
// Serialized ApiLevel. Use via MinSdkVersion() method. Cannot be stored in
// its struct form because this is cloned into properties structs, and
// ApiLevel has private members.
MinSdkVersionStr string
- Updatable bool
- RequiredSdks SdkRefs
- InApexes []string
+ // True if the module comes from an updatable APEX.
+ Updatable bool
+ RequiredSdks SdkRefs
+
+ InApexes []string
+ ApexContents []*ApexContents
}
+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 {
@@ -54,6 +63,18 @@
return ApiLevelOrPanic(ctx, this.MinSdkVersionStr)
}
+func (i ApexInfo) IsForPlatform() bool {
+ return i.ApexVariationName == ""
+}
+
+// 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 {
@@ -87,23 +108,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
@@ -116,10 +132,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
@@ -138,9 +150,6 @@
// it returns 9 as string
ChooseSdkVersion(ctx BaseModuleContext, versionList []string, maxSdkVersion ApiLevel) (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.
@@ -153,11 +162,6 @@
// 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 {
@@ -171,7 +175,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"`
@@ -187,6 +205,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 {
@@ -215,43 +242,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()
@@ -263,16 +253,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 {
@@ -345,10 +335,6 @@
}
}
-func (m *ApexModuleBase) Updatable() bool {
- return m.ApexProperties.Info.Updatable
-}
-
type byApexName []ApexInfo
func (a byApexName) Len() int { return len(a) }
@@ -366,11 +352,13 @@
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(ctx)
apexInfo.InApexes = CopyOf(apexInfo.InApexes)
+ apexInfo.ApexContents = append([]*ApexContents(nil), apexInfo.ApexContents...)
merged = append(merged, apexInfo)
}
aliases = append(aliases, [2]string{apexName, mergedName})
@@ -378,17 +366,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(mctx, 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{}
@@ -400,6 +394,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
@@ -410,7 +414,7 @@
mod.MakeUninstallable()
}
if !platformVariation {
- mod.(ApexModule).apexModuleBase().ApexProperties.Info = apexVariations[i-1]
+ mctx.SetVariationProvider(mod, ApexInfoProvider, apexVariations[i-1])
}
}
@@ -423,116 +427,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
diff --git a/android/apex_test.go b/android/apex_test.go
index dd372f7..512b50f 100644
--- a/android/apex_test.go
+++ b/android/apex_test.go
@@ -29,10 +29,10 @@
{
name: "single",
in: []ApexInfo{
- {"foo", "current", false, nil, []string{"foo"}},
+ {"foo", "current", false, nil, []string{"foo"}, nil},
},
wantMerged: []ApexInfo{
- {"apex10000", "current", 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", "current", false, SdkRefs{{"baz", "1"}}, []string{"foo"}},
- {"bar", "current", 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", "current", 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", "current", 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", "current", 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", "current", false, nil, []string{"foo"}},
- {"bar", "current", true, nil, []string{"bar"}},
+ {"foo", "current", false, nil, []string{"foo"}, nil},
+ {"bar", "current", true, nil, []string{"bar"}, nil},
},
wantMerged: []ApexInfo{
- {"apex10000", "current", 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", "current", false, SdkRefs{{"baz", "1"}}, []string{"foo"}},
- {"bar", "current", 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", "current", false, SdkRefs{{"baz", "2"}}, []string{"bar"}},
- {"apex10000_baz_1", "current", 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"},
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
new file mode 100644
index 0000000..b7cea4b
--- /dev/null
+++ b/android/bazel_handler.go
@@ -0,0 +1,239 @@
+// 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"
+ "os"
+ "os/exec"
+ "runtime"
+ "strings"
+ "sync"
+)
+
+// Map key to describe bazel cquery requests.
+type cqueryKey struct {
+ label string
+ starlarkExpr string
+}
+
+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
+
+ 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) {
+ starlarkExpr := "', '.join([f.path for f in target.files.to_list()])"
+ result, ok := bazelCtx.cquery(label, starlarkExpr)
+ 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) {
+ if c.Getenv("USE_BAZEL") != "1" {
+ return noopBazelContext{}, nil
+ }
+
+ bazelCtx := bazelContext{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, starlarkExpr string) (string, bool) {
+ key := cqueryKey{label, starlarkExpr}
+ 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{"--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
+ }
+}
+
+// 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 labels []string
+ var cqueryOutput string
+ var err error
+ for val, _ := range context.requests {
+ labels = append(labels, val.label)
+
+ // TODO(cparsons): Combine requests into a batch cquery request.
+ // TODO(cparsons): Use --query_file to avoid command line limits.
+ cqueryOutput, err = context.issueBazelCommand("cquery", []string{val.label},
+ "--output=starlark",
+ "--starlark:expr="+val.starlarkExpr)
+
+ if err != nil {
+ return err
+ } else {
+ context.results[val] = string(cqueryOutput)
+ }
+ }
+
+ // 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", labels)
+
+ if err != nil {
+ return err
+ }
+
+ // Clear requests.
+ context.requests = map[cqueryKey]bool{}
+ return nil
+}
diff --git a/android/config.go b/android/config.go
index 2675402..cf6d596 100644
--- a/android/config.go
+++ b/android/config.go
@@ -85,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.
@@ -248,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,
@@ -316,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")
@@ -324,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) {
@@ -411,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 {
@@ -425,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
}
@@ -1120,12 +1145,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 {
diff --git a/android/makevars.go b/android/makevars.go
index 374986e..3ca7792 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -128,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.
@@ -142,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.
@@ -171,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
@@ -219,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,
@@ -232,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 c4e43c2..056b0a5 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1499,8 +1499,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)
diff --git a/android/paths_test.go b/android/paths_test.go
index d099f65..108bd6c 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -1260,7 +1260,7 @@
// boot.art boot.oat
}
-func ExampleOutputPath_FileInSameDir() {
+func ExampleOutputPath_InSameDir() {
ctx := &configErrorWrapper{
config: TestConfig("out", nil, "", nil),
}
diff --git a/android/variable.go b/android/variable.go
index ce523ed..d752aec 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -304,8 +304,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"`
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/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/allowed_deps.txt b/apex/allowed_deps.txt
index 87e96ea..cd4b056 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -124,6 +124,7 @@
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)
@@ -138,12 +139,19 @@
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:current)
@@ -186,6 +194,7 @@
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))
@@ -273,6 +282,7 @@
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))
@@ -289,6 +299,7 @@
libhidlbase(minSdkVersion:29)
libhidlmemory(minSdkVersion:29)
libhwbinder-impl-internal(minSdkVersion:29)
+libhwbinder_headers(minSdkVersion:29)
libion(minSdkVersion:29)
libjavacrypto(minSdkVersion:29)
libjsoncpp(minSdkVersion:29)
diff --git a/apex/apex.go b/apex/apex.go
index a5b228c..a9a58a6 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -67,6 +67,7 @@
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()
@@ -769,7 +770,10 @@
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()
@@ -785,13 +789,6 @@
if !ok || a.vndkApex {
return
}
- apexInfo := android.ApexInfo{
- ApexVariationName: mctx.ModuleName(),
- MinSdkVersionStr: a.minSdkVersion(mctx).String(),
- 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)
@@ -800,7 +797,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
@@ -813,12 +812,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
})
}
@@ -830,7 +858,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,
+ })
}
}
@@ -891,8 +952,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.
@@ -909,6 +971,15 @@
}
+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) {
if !mctx.Module().Enabled() {
return
@@ -1118,6 +1189,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.
@@ -1908,6 +1985,8 @@
return false
}
+ childApexInfo := ctx.OtherModuleProvider(child, android.ApexInfoProvider).(android.ApexInfo)
+
dt := ctx.OtherModuleDependencyTag(child)
if _, ok := dt.(android.ExcludeFromApexContentsTag); ok {
@@ -1924,7 +2003,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 */)
}
@@ -2032,6 +2111,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()
@@ -2052,7 +2133,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))
@@ -2291,7 +2372,8 @@
}
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
@@ -2299,7 +2381,7 @@
//
// 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) {
@@ -2338,6 +2420,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)
}
diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go
index afb739c..803e0c5 100644
--- a/apex/apex_singleton.go
+++ b/apex/apex_singleton.go
@@ -72,8 +72,11 @@
updatableFlatLists := android.Paths{}
ctx.VisitAllModules(func(module android.Module) {
if binaryInfo, ok := module.(android.ApexBundleDepsInfoIntf); ok {
- if path := binaryInfo.FlatListPath(); path != nil && binaryInfo.Updatable() {
- updatableFlatLists = append(updatableFlatLists, path)
+ apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+ if path := binaryInfo.FlatListPath(); path != nil {
+ if binaryInfo.Updatable() || apexInfo.Updatable {
+ updatableFlatLists = append(updatableFlatLists, path)
+ }
}
}
})
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 71c4aa2..cf2c953 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",
@@ -1607,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")
}
@@ -3643,16 +3643,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",
@@ -5845,7 +5842,6 @@
func testApexPermittedPackagesRules(t *testing.T, errmsg, bp string, apexBootJars []string, rules []android.Rule) {
t.Helper()
- android.ClearApexDependency()
bp += `
apex_key {
name: "myapex.key",
diff --git a/bazel/bazelenv.sh b/bazel/bazelenv.sh
new file mode 100755
index 0000000..2ca8baf
--- /dev/null
+++ b/bazel/bazelenv.sh
@@ -0,0 +1,74 @@
+#!/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
+
+export USE_BAZEL=1
+export BAZEL_HOME="$BASE_DIR/bazelhome"
+export BAZEL_OUTPUT_BASE="$BASE_DIR/output"
+export BAZEL_WORKSPACE="$(gettop)"
+
+echo "USE_BAZEL=${USE_BAZEL}"
+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/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 d92fabc..a2549b8 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -33,7 +33,6 @@
)
type AndroidMkContext interface {
- BaseModuleName() string
Target() android.Target
subAndroidMk(*android.AndroidMkEntries, interface{})
Arch() android.Arch
@@ -44,6 +43,7 @@
static() bool
InRamdisk() bool
InRecovery() bool
+ AnyVariantDirectlyInAnyApex() bool
}
type subAndroidMkProvider interface {
@@ -63,7 +63,7 @@
}
func (c *Module) AndroidMkEntries() []android.AndroidMkEntries {
- if c.Properties.HideFromMake || !c.IsForPlatform() {
+ if c.hideApexVariantFromMake || c.Properties.HideFromMake {
return []android.AndroidMkEntries{{
Disabled: true,
}}
@@ -277,9 +277,8 @@
}
})
}
- if len(library.Properties.Stubs.Versions) > 0 &&
- android.DirectlyInAnyApex(ctx, ctx.BaseModuleName()) && !ctx.InRamdisk() && !ctx.InRecovery() && !ctx.UseVndk() &&
- !ctx.static() {
+ if len(library.Properties.Stubs.Versions) > 0 && !ctx.Host() && ctx.AnyVariantDirectlyInAnyApex() &&
+ !ctx.InRamdisk() && !ctx.InRecovery() && !ctx.UseVndk() && !ctx.static() {
if library.buildStubs() && library.isLatestStubVersion() {
// reference the latest version via its name without suffix when it is provided by apex
entries.SubName = ""
diff --git a/cc/binary.go b/cc/binary.go
index b3ce5ff..7f7b619 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -445,7 +445,9 @@
// 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() {
+
if ctx.Device() && isBionic(ctx.baseModuleName()) {
binary.installSymlinkToRuntimeApex(ctx, file)
}
diff --git a/cc/cc.go b/cc/cc.go
index 03290ad..8188550 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -366,6 +366,7 @@
bootstrap() bool
mustUseVendorVariant() bool
nativeCoverage() bool
+ directlyInAnyApex() bool
}
type ModuleContext interface {
@@ -545,8 +546,17 @@
dataLibDepTag = dependencyTag{name: "data lib"}
runtimeDepTag = dependencyTag{name: "runtime lib"}
testPerSrcDepTag = dependencyTag{name: "test_per_src"}
+ testForDepTag = dependencyTag{name: "test for apex"}
+
+ stubImplDepTag = copyDirectlyInAnyApexDependencyTag{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()
@@ -622,6 +632,8 @@
// For apex variants, this is set as apex.min_sdk_version
apexSdkVersion android.ApiLevel
+
+ hideApexVariantFromMake bool
}
func (c *Module) Toc() android.OptionalPath {
@@ -1363,11 +1375,11 @@
}
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() android.ApiLevel {
@@ -1390,6 +1402,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,
@@ -1545,6 +1561,11 @@
return
}
+ apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ if !apexInfo.IsForPlatform() {
+ c.hideApexVariantFromMake = true
+ }
+
c.makeLinkType = c.getMakeLinkType(actx)
c.Properties.SubName = ""
@@ -1676,8 +1697,7 @@
// 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.Properties.HideFromMake = false // unhide
@@ -1686,13 +1706,13 @@
// 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
@@ -2381,8 +2401,9 @@
// For the dependency from platform to apex, use the latest stubs
c.apexSdkVersion = android.FutureApiLevel
- if !c.IsForPlatform() {
- c.apexSdkVersion = c.ApexProperties.Info.MinSdkVersion(ctx)
+ apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ if !apexInfo.IsForPlatform() {
+ c.apexSdkVersion = apexInfo.MinSdkVersion(ctx)
}
if android.InList("hwaddress", ctx.Config().SanitizeDevice()) {
@@ -2493,8 +2514,8 @@
if ccDep.CcLibrary() && !libDepTag.static() {
depIsStubs := ccDep.BuildStubs()
depHasStubs := CanBeOrLinkAgainstVersionVariants(c) && ccDep.HasStubsVariants()
- depInSameApexes := android.DirectlyInAllApexes(c.InApexes(), depName)
- depInPlatform := !android.DirectlyInAnyApex(ctx, depName)
+ depInSameApexes := android.DirectlyInAllApexes(apexInfo, depName)
+ depInPlatform := !dep.(android.ApexModule).AnyVariantDirectlyInAnyApex()
var useThisDep bool
if depIsStubs && libDepTag.explicitlyVersioned {
@@ -2504,7 +2525,7 @@
// 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() {
+ } else if apexInfo.IsForPlatform() {
// If not building for APEX, use stubs only when it is from
// an APEX (and not from platform)
useThisDep = (depInPlatform != depIsStubs)
@@ -2513,11 +2534,12 @@
// 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) {
+ // 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) {
useThisDep = !depIsStubs
break
}
@@ -2549,7 +2571,7 @@
// by default, use current version of LLNDK
versionToUse := ""
versions := m.AllStubsVersions()
- if c.ApexVariationName() != "" && len(versions) > 0 {
+ if apexInfo.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
@@ -2711,10 +2733,11 @@
c.Properties.AndroidMkHeaderLibs, makeLibName)
case libDepTag.shared():
if ccDep.CcLibrary() {
- if ccDep.BuildStubs() && android.InAnyApex(depName) {
+ if ccDep.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)
}
@@ -3018,7 +3041,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) &&
@@ -3027,7 +3050,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
}
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/global.go b/cc/config/global.go
index d4c6266..97e423a 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -205,6 +205,7 @@
pctx.PrefixedExistentPathsForSourcesVariable("CommonGlobalIncludes", "-I",
[]string{
"system/core/include",
+ "system/core/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 6f2e807..d18ae25 100644
--- a/cc/config/vndk.go
+++ b/cc/config/vndk.go
@@ -25,6 +25,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/library.go b/cc/library.go
index b5bec95..35828aa 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1231,18 +1231,19 @@
library.baseInstaller.subDir += "-" + vndkVersion
}
}
- } 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.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()
}
@@ -1531,6 +1532,8 @@
if variants[i] != "" {
m.(LinkableInterface).SetBuildStubs()
m.(LinkableInterface).SetStubsVersion(variants[i])
+ // The stubs depend on the implementation
+ mctx.AddInterVariantDependency(stubImplDepTag, modules[i], modules[0])
}
}
mctx.AliasVariation("")
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index b3f9d61..a429063 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -74,6 +74,8 @@
exportHeadersTimestamp android.OptionalPath
versionScriptPath android.ModuleGenPath
+
+ movedToApex bool
}
func (stub *llndkStubDecorator) compilerFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags {
@@ -135,6 +137,11 @@
func (stub *llndkStubDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps,
objs Objects) android.Path {
+ impl := ctx.GetDirectDepWithTag(ctx.baseModuleName(), llndkImplDep)
+ if implApexModule, ok := impl.(android.ApexModule); ok {
+ stub.movedToApex = implApexModule.DirectlyInAnyApex()
+ }
+
if !Bool(stub.Properties.Unversioned) {
linkerScriptFlag := "-Wl,--version-script," + stub.versionScriptPath.String()
flags.Local.LdFlags = append(flags.Local.LdFlags, linkerScriptFlag)
diff --git a/cc/lto.go b/cc/lto.go
index abd8dfb..a3b28d9 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -71,7 +71,8 @@
} else if ctx.Config().IsEnvTrue("GLOBAL_THINLTO") {
staticLib := ctx.static() && !ctx.staticBinary()
hostBin := ctx.Host()
- if !staticLib && !hostBin {
+ vndk := ctx.isVndk() // b/169217596
+ if !staticLib && !hostBin && !vndk {
if !lto.Never() && !lto.FullLTO() {
lto.Properties.Lto.Thin = boolPtr(true)
}
diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go
index f27d166..b72af44 100644
--- a/cc/snapshot_utils.go
+++ b/cc/snapshot_utils.go
@@ -58,10 +58,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
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 2819f49..529ed60 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -537,7 +537,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 +562,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
@@ -825,6 +825,7 @@
moduleDir := ctx.ModuleDir(module)
inVendorProprietaryPath := isVendorProprietaryPath(moduleDir)
+ apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
if m.ExcludeFromVendorSnapshot() {
if inVendorProprietaryPath {
@@ -842,7 +843,7 @@
}
}
- if !isVendorSnapshotModule(m, inVendorProprietaryPath) {
+ if !isVendorSnapshotModule(m, inVendorProprietaryPath, apexInfo) {
return
}
diff --git a/cc/vndk.go b/cc/vndk.go
index 9a2fa09..4169e21 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -300,6 +300,7 @@
if !Bool(lib.Properties.Vendor_available) {
vndkPrivateLibraries(mctx.Config())[name] = filename
}
+
if mctx.OtherModuleExists(name) {
mctx.AddFarVariationDependencies(m.Target().Variations(), llndkImplDep, name)
}
@@ -533,11 +534,13 @@
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() {
+ if !m.inVendor() || !m.installable(apexInfo) || m.isSnapshotPrebuilt() {
return nil, "", false
}
l, ok := m.linker.(snapshotLibraryInterface)
@@ -659,7 +662,9 @@
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
}
@@ -823,14 +828,21 @@
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 := m.BaseModuleName()
+ if llndk.movedToApex && !isBionic(m.BaseModuleName()) {
+ 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/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 01a39a2..7ae1c37 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -51,30 +51,34 @@
return android.NewNameResolver(exportFilter)
}
+func newContext(srcDir string, configuration android.Config) *android.Context {
+ ctx := android.NewContext()
+ 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,9 +88,31 @@
// enabled even if it completed successfully.
extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.BuildDir(), "always_rerun_for_delve"))
}
-
- bootstrap.Main(ctx.Context, configuration, extraNinjaDeps...)
-
+ 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)
+ 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 bazelOverlayDir != "" {
if err := createBazelOverlay(ctx, bazelOverlayDir); err != nil {
fmt.Fprintf(os.Stderr, "%s", err)
@@ -105,7 +131,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)
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 69e4f69..5c06251 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -173,6 +173,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)
+ build.PrintOutDirWarning(buildCtx, config)
os.MkdirAll(logsDir, 0777)
log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 4dbda49..814b75d 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -218,13 +218,21 @@
return m[sdkVer]
}
-func (m classLoaderContextMap) addLibs(sdkVer int, module *ModuleConfig, libs ...string) bool {
+func (m classLoaderContextMap) addLibs(ctx android.PathContext, sdkVer int, module *ModuleConfig, libs ...string) bool {
clc := m.getValue(sdkVer)
for _, lib := range libs {
- if p := pathForLibrary(module, lib); p != nil {
+ if p, ok := module.LibraryPaths[lib]; ok && p.Host != nil && p.Device != UnknownInstallLibraryPath {
clc.Host = append(clc.Host, p.Host)
clc.Target = append(clc.Target, p.Device)
} else {
+ if sdkVer == anySdkVersion {
+ // Fail the build 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.
+ android.ReportPathErrorf(ctx, "dexpreopt cannot find path for <uses-library> '%s'", lib)
+ } else {
+ // No error for compatibility libraries, as Soong doesn't know if they are needed
+ // (this depends on the targetSdkVersion in the manifest).
+ }
return false
}
}
@@ -270,14 +278,14 @@
} else if module.EnforceUsesLibraries {
// Unconditional class loader context.
usesLibs := append(copyOf(module.UsesLibraries), module.OptionalUsesLibraries...)
- if !classLoaderContexts.addLibs(anySdkVersion, module, usesLibs...) {
+ if !classLoaderContexts.addLibs(ctx, 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) {
+ if !classLoaderContexts.addLibs(ctx, 28, module, httpLegacy) {
return nil
}
}
@@ -287,14 +295,14 @@
"android.hidl.base-V1.0-java",
"android.hidl.manager-V1.0-java",
}
- if !classLoaderContexts.addLibs(29, module, usesLibs29...) {
+ if !classLoaderContexts.addLibs(ctx, 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) {
+ if !classLoaderContexts.addLibs(ctx, 30, module, testBase) {
return nil
}
}
@@ -589,14 +597,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/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/genrule/genrule.go b/genrule/genrule.go
index 4a2f810..178587a 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -113,8 +113,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 string
+}
type Module struct {
android.ModuleBase
android.DefaultableModuleBase
@@ -186,6 +188,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 +472,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
+ 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 {
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 4b36600..c692019 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -721,6 +721,39 @@
}
}
+func TestGenruleWithBazel(t *testing.T) {
+ bp := `
+ genrule {
+ name: "foo",
+ out: ["one.txt", "two.txt"],
+ bazel_module: "//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/aar.go b/java/aar.go
index c31fc95..134357e 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -511,6 +511,8 @@
a.aapt.buildActions(ctx, sdkContext(a))
a.exportedSdkLibs = a.aapt.sdkLibraries
+ a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
+
ctx.CheckbuildFile(a.proguardOptionsFile)
ctx.CheckbuildFile(a.exportPackage)
ctx.CheckbuildFile(a.aaptSrcJar)
@@ -603,6 +605,8 @@
manifest android.WritablePath
exportedStaticPackages android.Paths
+
+ hideApexVariantFromMake bool
}
func (a *AARImport) sdkVersion() sdkSpec {
@@ -707,6 +711,8 @@
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])
diff --git a/java/androidmk.go b/java/androidmk.go
index 65c44a3..f72ee37 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),
@@ -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,
}}
@@ -239,7 +232,7 @@
}
func (prebuilt *AARImport) AndroidMkEntries() []android.AndroidMkEntries {
- if !prebuilt.IsForPlatform() {
+ if prebuilt.hideApexVariantFromMake {
return []android.AndroidMkEntries{{
Disabled: true,
}}
@@ -309,7 +302,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 +451,7 @@
}
func (a *AndroidLibrary) AndroidMkEntries() []android.AndroidMkEntries {
- if !a.IsForPlatform() {
+ if a.hideApexVariantFromMake {
return []android.AndroidMkEntries{{
Disabled: true,
}}
@@ -638,7 +631,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 13d08b9..e788ca9 100755
--- a/java/app.go
+++ b/java/app.go
@@ -480,8 +480,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 +505,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 {
@@ -641,7 +643,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())
}
}
@@ -756,6 +758,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)
@@ -850,8 +856,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 +987,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 +1343,8 @@
preprocessed bool
installPath android.InstallPath
+
+ hideApexVariantFromMake bool
}
type AndroidAppImportProperties struct {
@@ -1392,7 +1402,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 +1491,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++
@@ -1569,7 +1584,7 @@
// TODO: Optionally compress the output apk.
- if a.IsForPlatform() {
+ if apexInfo.IsForPlatform() {
a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile)
}
diff --git a/java/app_test.go b/java/app_test.go
index b7be189..49ed3aa 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -2752,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"],
@@ -2795,7 +2782,6 @@
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.
@@ -2826,7 +2812,7 @@
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` +
@@ -2838,11 +2824,6 @@
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")
- }
-
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) {
t.Errorf("wanted %q in %q", w, cmd)
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index f1b7178..20dbc66 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -94,7 +94,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
}
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 7877031..9f49786 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -266,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() && isHostdex(module) {
+ } 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") {
@@ -279,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)
@@ -289,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)
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 33f422d..b3bb5ab 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -1064,6 +1064,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.removedApiFile}, nil
case ".annotations.zip":
return android.Paths{d.annotationsZip}, nil
case ".api_versions.xml":
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 61a9b97..9d07e41 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -18,6 +18,7 @@
"fmt"
"android/soong/android"
+ "android/soong/genrule"
)
func init() {
@@ -161,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)
@@ -224,30 +224,26 @@
// 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()
diff --git a/java/java.go b/java/java.go
index 1d7eaa7..2553a30 100644
--- a/java/java.go
+++ b/java/java.go
@@ -451,6 +451,8 @@
// Collect the module directory for IDE info in java/jdeps.go.
modulePaths []string
+
+ hideApexVariantFromMake bool
}
func (j *Module) addHostProperties() {
@@ -638,8 +640,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 +738,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...)
@@ -1590,7 +1605,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)
}
@@ -1672,7 +1688,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)
@@ -1934,7 +1950,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
}
@@ -1956,6 +1972,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
@@ -1970,7 +1991,7 @@
// 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 {
@@ -2562,6 +2583,8 @@
combinedClasspathFile android.Path
exportedSdkLibs dexpreopt.LibraryPaths
exportAidlIncludeDirs android.Paths
+
+ hideApexVariantFromMake bool
}
func (j *Import) sdkVersion() sdkSpec {
@@ -2617,6 +2640,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"
@@ -2699,6 +2726,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 {
@@ -2849,6 +2887,8 @@
maybeStrippedDexJarFile android.Path
dexpreopter
+
+ hideApexVariantFromMake bool
}
func (j *DexImport) Prebuilt() *android.Prebuilt {
@@ -2884,6 +2924,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)
@@ -2928,7 +2973,7 @@
j.maybeStrippedDexJarFile = dexOutputFile
- if j.IsForPlatform() {
+ if apexInfo.IsForPlatform() {
ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
j.Stem()+".jar", dexOutputFile)
}
diff --git a/java/java_test.go b/java/java_test.go
index bb200d3..53053df 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1416,7 +1416,31 @@
name: "core",
sdk_version: "none",
system_modules: "none",
- }`),
+ }
+
+ filegroup {
+ name: "core-jar",
+ srcs: [":core{.jar}"],
+ }
+`),
+ })
+ ctx := testContext()
+ 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()
run(t, ctx, config)
@@ -1560,6 +1584,39 @@
}
}
+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 {
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/sdk_library.go b/java/sdk_library.go
index 60924a6..859dc8d 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -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"`
@@ -870,6 +873,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 {
@@ -880,6 +889,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
@@ -1128,12 +1140,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,
@@ -1410,22 +1426,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 {
@@ -1444,7 +1452,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 {
@@ -1564,6 +1572,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() {
@@ -1961,7 +1972,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 {
@@ -2057,6 +2068,8 @@
outputFilePath android.OutputPath
installDirPath android.InstallPath
+
+ hideApexVariantFromMake bool
}
type sdkLibraryXmlProperties struct {
@@ -2114,13 +2127,13 @@
}
// 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() {
@@ -2136,8 +2149,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()
@@ -2151,7 +2166,7 @@
}
func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries {
- if !module.IsForPlatform() {
+ if module.hideApexVariantFromMake {
return []android.AndroidMkEntries{android.AndroidMkEntries{
Disabled: true,
}}
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/project_json.go b/rust/project_json.go
index 8d161b2..5697408 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -93,7 +93,7 @@
return "", false
}
default:
- if rModule.Target().String() != ctx.Config().Targets[android.Android][0].String() {
+ if rModule.Target().String() != ctx.Config().AndroidFirstDeviceTarget.String() {
return "", false
}
}
diff --git a/rust/project_json_test.go b/rust/project_json_test.go
index 11964f3..69288fc 100644
--- a/rust/project_json_test.go
+++ b/rust/project_json_test.go
@@ -22,22 +22,15 @@
"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
@@ -87,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)
}
@@ -123,11 +112,8 @@
source_stem: "bindings2",
wrapper_src: "src/any.h",
}
- ` + GatherRequiredDepsForTest()
- fs := map[string][]byte{
- "src/lib.rs": nil,
- }
- jsonContent := testProjectJson(t, bp, fs)
+ `
+ jsonContent := testProjectJson(t, bp)
crates := validateJsonCrates(t, jsonContent)
for _, c := range crates {
crate, ok := c.(map[string]interface{})
@@ -166,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/rust_test.go b/rust/rust_test.go
index 4842a4c..9b2f023 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.Register(*tctx.config)
_, 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.Register(*tctx.config)
_, 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
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 7c3cdbd..e807877 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -261,7 +261,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...)
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index e1123e0..fc0329f 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"),
diff --git a/ui/build/rbe.go b/ui/build/rbe.go
index 182c544..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 {
@@ -151,3 +153,16 @@
ctx.Fatalf("failed to copy %q to %q: %v\n", metricsFile, filename, err)
}
}
+
+// 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, "\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, "")
+ }
+}