Merge "Make the names of 'soong_config_module_type_import' modules unique."
diff --git a/README.md b/README.md
index b1bb425..3eac87b 100644
--- a/README.md
+++ b/README.md
@@ -419,7 +419,8 @@
name: "acme_cc_defaults",
module_type: "cc_defaults",
config_namespace: "acme",
- variables: ["board", "feature"],
+ variables: ["board"],
+ bool_variables: ["feature"],
properties: ["cflags", "srcs"],
}
@@ -427,10 +428,6 @@
name: "board",
values: ["soc_a", "soc_b"],
}
-
-soong_config_bool_variable {
- name: "feature",
-}
```
This example describes a new `acme_cc_defaults` module type that extends the
diff --git a/android/apex.go b/android/apex.go
index eabe059..9bf6fc7 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -19,6 +19,8 @@
"sort"
"strconv"
"sync"
+
+ "github.com/google/blueprint"
)
const (
@@ -32,6 +34,14 @@
MinSdkVersion int
}
+// 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 {
+ // DepIsInSameApex tests if the other module 'dep' is installed to the same
+ // APEX as this module
+ DepIsInSameApex(ctx BaseModuleContext, dep Module) bool
+}
+
// ApexModule is the interface that a module type is expected to implement if
// the module has to be built differently depending on whether the module
// is destined for an apex or not (installed to one of the regular partitions).
@@ -49,6 +59,8 @@
// respectively.
type ApexModule interface {
Module
+ DepIsInSameApex
+
apexModuleBase() *ApexModuleBase
// Marks that this module should be built for the specified APEXes.
@@ -88,16 +100,10 @@
// Tests if this module is available for the specified APEX or ":platform"
AvailableFor(what string) bool
- // DepIsInSameApex tests if the other module 'dep' is installed to the same
- // APEX as this module
- DepIsInSameApex(ctx BaseModuleContext, dep Module) bool
-
- // Returns the highest version which is <= min_sdk_version.
- // For example, with min_sdk_version is 10 and versionList is [9,11]
- // it returns 9.
- ChooseSdkVersion(versionList []string, useLatest bool) (string, error)
-
- ShouldSupportAndroid10() bool
+ // Returns the highest version which is <= maxSdkVersion.
+ // For example, with maxSdkVersion is 10 and versionList is [9,11]
+ // it returns 9 as string
+ ChooseSdkVersion(versionList []string, maxSdkVersion int) (string, error)
}
type ApexProperties struct {
@@ -113,6 +119,15 @@
Info ApexInfo `blueprint:"mutated"`
}
+// Marker interface that identifies dependencies that are excluded from APEX
+// contents.
+type ExcludeFromApexContentsTag interface {
+ blueprint.DependencyTag
+
+ // Method that differentiates this interface from others.
+ ExcludeFromApexContents()
+}
+
// Provides default implementation for the ApexModule interface. APEX-aware
// modules are expected to include this struct and call InitApexModule().
type ApexModuleBase struct {
@@ -193,22 +208,14 @@
return true
}
-func (m *ApexModuleBase) ChooseSdkVersion(versionList []string, useLatest bool) (string, error) {
- if useLatest {
- return versionList[len(versionList)-1], nil
- }
- minSdkVersion := m.ApexProperties.Info.MinSdkVersion
+func (m *ApexModuleBase) ChooseSdkVersion(versionList []string, maxSdkVersion int) (string, error) {
for i := range versionList {
ver, _ := strconv.Atoi(versionList[len(versionList)-i-1])
- if ver <= minSdkVersion {
+ if ver <= maxSdkVersion {
return versionList[len(versionList)-i-1], nil
}
}
- return "", fmt.Errorf("min_sdk_version is set %v, but not found in %v", minSdkVersion, versionList)
-}
-
-func (m *ApexModuleBase) ShouldSupportAndroid10() bool {
- return !m.IsForPlatform() && (m.ApexProperties.Info.MinSdkVersion <= SdkVersion_Android10)
+ return "", fmt.Errorf("not found a version(<=%d) in versionList: %v", maxSdkVersion, versionList)
}
func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
diff --git a/android/defs.go b/android/defs.go
index 5c815e6..4552224 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -100,6 +100,9 @@
// Used only when USE_GOMA=true is set, to restrict non-goma jobs to the local parallelism value
localPool = blueprint.NewBuiltinPool("local_pool")
+ // Used only by RuleBuilder to identify remoteable rules. Does not actually get created in ninja.
+ remotePool = blueprint.NewBuiltinPool("remote_pool")
+
// Used for processes that need significant RAM to ensure there are not too many running in parallel.
highmemPool = blueprint.NewBuiltinPool("highmem_pool")
)
diff --git a/android/module.go b/android/module.go
index d57abd1..02b2c89 100644
--- a/android/module.go
+++ b/android/module.go
@@ -128,6 +128,13 @@
// and returns a top-down dependency path from a start module to current child module.
GetWalkPath() []Module
+ // GetTagPath is supposed to be called in visit function passed in WalkDeps()
+ // and returns a top-down dependency tags path from a start module to current child module.
+ // It has one less entry than GetWalkPath() as it contains the dependency tags that
+ // exist between each adjacent pair of modules in the GetWalkPath().
+ // GetTagPath()[i] is the tag between GetWalkPath()[i] and GetWalkPath()[i+1]
+ GetTagPath() []blueprint.DependencyTag
+
AddMissingDependencies(missingDeps []string)
Target() Target
@@ -220,6 +227,7 @@
InstallBypassMake() bool
InstallForceOS() *OsType
SkipInstall()
+ IsSkipInstall() bool
ExportedToMake() bool
InitRc() Paths
VintfFragments() Paths
@@ -908,7 +916,7 @@
// partition at "system/vendor/odm".
if config.OdmPath() == "odm" {
partition = "odm"
- } else if strings.HasPrefix(config.OdmPath (), "vendor/") {
+ } else if strings.HasPrefix(config.OdmPath(), "vendor/") {
partition = "vendor"
}
} else if m.ProductSpecific() {
@@ -943,6 +951,10 @@
m.commonProperties.SkipInstall = true
}
+func (m *ModuleBase) IsSkipInstall() bool {
+ return m.commonProperties.SkipInstall == true
+}
+
func (m *ModuleBase) ExportedToMake() bool {
return m.commonProperties.NamespaceExportedToMake
}
@@ -1400,6 +1412,7 @@
debug bool
walkPath []Module
+ tagPath []blueprint.DependencyTag
strictVisitDeps bool // If true, enforce that all dependencies are enabled
}
@@ -1506,10 +1519,17 @@
func (m *moduleContext) Rule(pctx PackageContext, name string, params blueprint.RuleParams,
argNames ...string) blueprint.Rule {
- if m.config.UseRemoteBuild() && params.Pool == nil {
- // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict
- // jobs to the local parallelism value
- params.Pool = localPool
+ if m.config.UseRemoteBuild() {
+ if params.Pool == nil {
+ // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict
+ // jobs to the local parallelism value
+ params.Pool = localPool
+ } else if params.Pool == remotePool {
+ // remotePool is a fake pool used to identify rule that are supported for remoting. If the rule's
+ // pool is the remotePool, replace with nil so that ninja runs it at NINJA_REMOTE_NUM_JOBS
+ // parallelism.
+ params.Pool = nil
+ }
}
rule := m.bp.Rule(pctx.PackageContext, name, params, argNames...)
@@ -1689,6 +1709,7 @@
func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
b.walkPath = []Module{b.Module()}
+ b.tagPath = []blueprint.DependencyTag{}
b.bp.WalkDeps(func(child, parent blueprint.Module) bool {
childAndroidModule, _ := child.(Module)
parentAndroidModule, _ := parent.(Module)
@@ -1696,8 +1717,10 @@
// record walkPath before visit
for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
+ b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
}
b.walkPath = append(b.walkPath, childAndroidModule)
+ b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
return visit(childAndroidModule, parentAndroidModule)
} else {
return false
@@ -1709,6 +1732,10 @@
return b.walkPath
}
+func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag {
+ return b.tagPath
+}
+
func (m *moduleContext) VisitAllModuleVariants(visit func(Module)) {
m.bp.VisitAllModuleVariants(func(module blueprint.Module) {
visit(module.(Module))
diff --git a/android/prebuilt.go b/android/prebuilt.go
index c902ec8..82745a4 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -39,6 +39,12 @@
// Mark this tag so dependencies that use it are excluded from visibility enforcement.
func (t prebuiltDependencyTag) ExcludeFromVisibilityEnforcement() {}
+// Mark this tag so dependencies that use it are excluded from APEX contents.
+func (t prebuiltDependencyTag) ExcludeFromApexContents() {}
+
+var _ ExcludeFromVisibilityEnforcementTag = PrebuiltDepTag
+var _ ExcludeFromApexContentsTag = PrebuiltDepTag
+
type PrebuiltProperties struct {
// When prefer is set to true the prebuilt will be used instead of any source module with
// a matching name.
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 9005f07..6226548 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -446,7 +446,8 @@
if ctx.Config().UseGoma() && r.remoteable.Goma {
// When USE_GOMA=true is set and the rule is supported by goma, allow jobs to run outside the local pool.
} else if ctx.Config().UseRBE() && r.remoteable.RBE {
- // When USE_RBE=true is set and the rule is supported by RBE, allow jobs to run outside the local pool.
+ // When USE_RBE=true is set and the rule is supported by RBE, use the remotePool.
+ pool = remotePool
} else if r.highmem {
pool = highmemPool
} else if ctx.Config().UseRemoteBuild() {
diff --git a/android/sdk.go b/android/sdk.go
index 66094cd..6f62f55 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -22,17 +22,30 @@
"github.com/google/blueprint/proptools"
)
+// Extracted from SdkAware to make it easier to define custom subsets of the
+// SdkAware interface and improve code navigation within the IDE.
+//
+// In addition to its use in SdkAware this interface must also be implemented by
+// APEX to specify the SDKs required by that module and its contents. e.g. APEX
+// is expected to implement RequiredSdks() by reading its own properties like
+// `uses_sdks`.
+type RequiredSdks interface {
+ // The set of SDKs required by an APEX and its contents.
+ RequiredSdks() SdkRefs
+}
+
// SdkAware is the interface that must be supported by any module to become a member of SDK or to be
// built with SDK
type SdkAware interface {
Module
+ RequiredSdks
+
sdkBase() *SdkBase
MakeMemberOf(sdk SdkRef)
IsInAnySdk() bool
ContainingSdk() SdkRef
MemberName() string
BuildWithSdks(sdks SdkRefs)
- RequiredSdks() SdkRefs
}
// SdkRef refers to a version of an SDK
diff --git a/android/singleton.go b/android/singleton.go
index 45a9b82..568398c 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -128,10 +128,17 @@
}
func (s *singletonContextAdaptor) Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule {
- if s.Config().UseRemoteBuild() && params.Pool == nil {
- // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict
- // jobs to the local parallelism value
- params.Pool = localPool
+ if s.Config().UseRemoteBuild() {
+ if params.Pool == nil {
+ // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict
+ // jobs to the local parallelism value
+ params.Pool = localPool
+ } else if params.Pool == remotePool {
+ // remotePool is a fake pool used to identify rule that are supported for remoting. If the rule's
+ // pool is the remotePool, replace with nil so that ninja runs it at NINJA_REMOTE_NUM_JOBS
+ // parallelism.
+ params.Pool = nil
+ }
}
rule := s.SingletonContext.Rule(pctx.PackageContext, name, params, argNames...)
if s.Config().captureBuild {
diff --git a/android/soong_config_modules.go b/android/soong_config_modules.go
index 8fc08ad..6ce609a 100644
--- a/android/soong_config_modules.go
+++ b/android/soong_config_modules.go
@@ -88,7 +88,8 @@
// name: "acme_cc_defaults",
// module_type: "cc_defaults",
// config_namespace: "acme",
-// variables: ["board", "feature"],
+// variables: ["board"],
+// bool_variables: ["feature"],
// properties: ["cflags", "srcs"],
// }
//
@@ -97,10 +98,6 @@
// values: ["soc_a", "soc_b"],
// }
//
-// soong_config_bool_variable {
-// name: "feature",
-// }
-//
// If an acme BoardConfig.mk file contained:
//
// SOONG_CONFIG_NAMESPACES += acme
@@ -152,7 +149,8 @@
// name: "acme_cc_defaults",
// module_type: "cc_defaults",
// config_namespace: "acme",
-// variables: ["board", "feature"],
+// variables: ["board"],
+// bool_variables: ["feature"],
// properties: ["cflags", "srcs"],
// }
//
@@ -161,10 +159,6 @@
// values: ["soc_a", "soc_b"],
// }
//
-// soong_config_bool_variable {
-// name: "feature",
-// }
-//
// acme_cc_defaults {
// name: "acme_defaults",
// cflags: ["-DGENERIC"],
diff --git a/android/soong_config_modules_test.go b/android/soong_config_modules_test.go
index 6ad88a2..1cf060d 100644
--- a/android/soong_config_modules_test.go
+++ b/android/soong_config_modules_test.go
@@ -43,7 +43,8 @@
name: "acme_test_defaults",
module_type: "test_defaults",
config_namespace: "acme",
- variables: ["board", "feature1", "feature2", "FEATURE3"],
+ variables: ["board", "feature1", "FEATURE3"],
+ bool_variables: ["feature2"],
properties: ["cflags", "srcs"],
}
@@ -57,10 +58,6 @@
}
soong_config_bool_variable {
- name: "feature2",
- }
-
- soong_config_bool_variable {
name: "FEATURE3",
}
`
diff --git a/android/soongconfig/modules.go b/android/soongconfig/modules.go
index aa4f5c5..2d6063d 100644
--- a/android/soongconfig/modules.go
+++ b/android/soongconfig/modules.go
@@ -109,6 +109,9 @@
// the list of SOONG_CONFIG variables that this module type will read
Variables []string
+ // the list of boolean SOONG_CONFIG variables that this module type will read
+ Bool_variables []string
+
// the list of properties that this module type will extend.
Properties []string
}
@@ -146,6 +149,18 @@
}
v.ModuleTypes[props.Name] = mt
+ for _, name := range props.Bool_variables {
+ if name == "" {
+ return []error{fmt.Errorf("bool_variable name must not be blank")}
+ }
+
+ mt.Variables = append(mt.Variables, &boolVariable{
+ baseVariable: baseVariable{
+ variable: name,
+ },
+ })
+ }
+
return nil
}
diff --git a/android/variable.go b/android/variable.go
index 8357d2f..612d138 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -95,6 +95,9 @@
Sanitize struct {
Address *bool
}
+ Optimize struct {
+ Enabled *bool
+ }
}
Pdk struct {
diff --git a/apex/apex.go b/apex/apex.go
index 446cad8..5a56185 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -18,6 +18,7 @@
"fmt"
"path"
"path/filepath"
+ "regexp"
"sort"
"strconv"
"strings"
@@ -94,16 +95,9 @@
// Module separator
//
m["com.android.adbd"] = []string{
- "adbd",
- "libadbconnection_server",
- "libadbd",
"libadbd_auth",
- "libadbd_core",
- "libadbd_services",
- "libasyncio",
"libbuildversion",
"libcap",
- "libdiagnose_usb",
"libmdnssd",
"libminijail",
"libminijail_gen_constants",
@@ -114,7 +108,6 @@
"libpackagelistparser",
"libpcre2",
"libprocessgroup_headers",
- "libqemu_pipe",
}
//
// Module separator
@@ -819,22 +812,6 @@
"libprofile-extras",
"libprofile-extras_ndk",
"libunwind_llvm",
- "ndk_crtbegin_dynamic.27",
- "ndk_crtbegin_so.16",
- "ndk_crtbegin_so.19",
- "ndk_crtbegin_so.21",
- "ndk_crtbegin_so.24",
- "ndk_crtbegin_so.27",
- "ndk_crtend_android.27",
- "ndk_crtend_so.16",
- "ndk_crtend_so.19",
- "ndk_crtend_so.21",
- "ndk_crtend_so.24",
- "ndk_crtend_so.27",
- "ndk_libandroid_support",
- "ndk_libc++_static",
- "ndk_libc++abi",
- "ndk_libunwind",
}
return m
}
@@ -889,20 +866,28 @@
return
}
- cur := mctx.Module().(interface {
- DepIsInSameApex(android.BaseModuleContext, android.Module) bool
- })
+ cur := mctx.Module().(android.DepIsInSameApex)
mctx.VisitDirectDeps(func(child android.Module) {
depName := mctx.OtherModuleName(child)
if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() &&
- cur.DepIsInSameApex(mctx, child) {
+ (cur.DepIsInSameApex(mctx, child) || inAnySdk(child)) {
android.UpdateApexDependency(apexBundles, depName, directDep)
am.BuildForApexes(apexBundles)
}
})
}
+// If a module in an APEX depends on a module from an SDK then it needs an APEX
+// specific variant created for it. Refer to sdk.sdkDepsReplaceMutator.
+func inAnySdk(module android.Module) bool {
+ if sa, ok := module.(android.SdkAware); ok {
+ return sa.IsInAnySdk()
+ }
+
+ return false
+}
+
// Create apex variations if a module is included in APEX(s).
func apexMutator(mctx android.BottomUpMutatorContext) {
if am, ok := mctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
@@ -1791,9 +1776,13 @@
return true
}
+// Function called while walking an APEX's payload dependencies.
+//
+// Return true if the `to` module should be visited, false otherwise.
+type payloadDepsCallback func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool
+
// Visit dependencies that contributes to the payload of this APEX
-func (a *apexBundle) walkPayloadDeps(ctx android.ModuleContext,
- do func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool)) {
+func (a *apexBundle) walkPayloadDeps(ctx android.ModuleContext, do payloadDepsCallback) {
ctx.WalkDeps(func(child, parent android.Module) bool {
am, ok := child.(android.ApexModule)
if !ok || !am.CanHaveApexVariants() {
@@ -1803,22 +1792,18 @@
// Check for the direct dependencies that contribute to the payload
if dt, ok := ctx.OtherModuleDependencyTag(child).(dependencyTag); ok {
if dt.payload {
- do(ctx, parent, am, false /* externalDep */)
- return true
+ return do(ctx, parent, am, false /* externalDep */)
}
+ // As soon as the dependency graph crosses the APEX boundary, don't go further.
return false
}
// Check for the indirect dependencies if it is considered as part of the APEX
if am.ApexName() != "" {
- do(ctx, parent, am, false /* externalDep */)
- return true
+ return do(ctx, parent, am, false /* externalDep */)
}
- do(ctx, parent, am, true /* externalDep */)
-
- // As soon as the dependency graph crosses the APEX boundary, don't go further.
- return false
+ return do(ctx, parent, am, true /* externalDep */)
})
}
@@ -1834,6 +1819,24 @@
return android.FutureApiLevel
}
+// A regexp for removing boilerplate from BaseDependencyTag from the string representation of
+// a dependency tag.
+var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:blueprint.BaseDependencyTag{}\E(, )?`)
+
+func PrettyPrintTag(tag blueprint.DependencyTag) string {
+ // Use tag's custom String() method if available.
+ if stringer, ok := tag.(fmt.Stringer); ok {
+ return stringer.String()
+ }
+
+ // Otherwise, get a default string representation of the tag's struct.
+ tagString := fmt.Sprintf("%#v", tag)
+
+ // Remove the boilerplate from BaseDependencyTag as it adds no value.
+ tagString = tagCleaner.ReplaceAllString(tagString, "")
+ return tagString
+}
+
// Ensures that the dependencies are marked as available for this APEX
func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) {
// Let's be practical. Availability for test, host, and the VNDK apex isn't important
@@ -1848,28 +1851,47 @@
return
}
- a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) {
+ a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
+ if externalDep {
+ // As soon as the dependency graph crosses the APEX boundary, don't go further.
+ return false
+ }
+
apexName := ctx.ModuleName()
fromName := ctx.OtherModuleName(from)
toName := ctx.OtherModuleName(to)
- if externalDep || to.AvailableFor(apexName) || whitelistedApexAvailable(apexName, toName) {
- return
+
+ // If `to` is not actually in the same APEX as `from` then it does not need apex_available and neither
+ // do any of its dependencies.
+ if am, ok := from.(android.DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) {
+ // As soon as the dependency graph crosses the APEX boundary, don't go further.
+ return false
+ }
+
+ if to.AvailableFor(apexName) || whitelistedApexAvailable(apexName, toName) {
+ return true
}
message := ""
- for _, m := range ctx.GetWalkPath()[1:] {
- message = fmt.Sprintf("%s\n -> %s", message, m.String())
+ tagPath := ctx.GetTagPath()
+ // Skip the first module as that will be added at the start of the error message by ctx.ModuleErrorf().
+ walkPath := ctx.GetWalkPath()[1:]
+ for i, m := range walkPath {
+ message = fmt.Sprintf("%s\n via tag %s\n -> %s", message, PrettyPrintTag(tagPath[i]), m.String())
}
ctx.ModuleErrorf("%q requires %q that is not available for the APEX. Dependency path:%s", fromName, toName, message)
+ // Visit this module's dependencies to check and report any issues with their availability.
+ return true
})
}
// Collects the list of module names that directly or indirectly contributes to the payload of this APEX
func (a *apexBundle) collectDepsInfo(ctx android.ModuleContext) {
a.depInfos = make(map[string]depInfo)
- a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) {
+ a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
if from.Name() == to.Name() {
// This can happen for cc.reuseObjTag. We are not interested in tracking this.
- return
+ // As soon as the dependency graph crosses the APEX boundary, don't go further.
+ return !externalDep
}
if info, exists := a.depInfos[to.Name()]; exists {
@@ -1885,6 +1907,9 @@
isExternal: externalDep,
}
}
+
+ // As soon as the dependency graph crosses the APEX boundary, don't go further.
+ return !externalDep
})
}
@@ -1961,6 +1986,9 @@
// TODO(jiyong) do this using walkPayloadDeps
ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool {
depTag := ctx.OtherModuleDependencyTag(child)
+ if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
+ return false
+ }
depName := ctx.OtherModuleName(child)
if _, isDirectDep := parent.(*apexBundle); isDirectDep {
switch depTag {
@@ -2129,7 +2157,7 @@
filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
}
} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
- ctx.ModuleErrorf("unexpected tag %q for indirect dependency %q", depTag, depName)
+ ctx.ModuleErrorf("unexpected tag %s for indirect dependency %q", PrettyPrintTag(depTag), depName)
}
}
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index c01ba14..f942c82 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -27,6 +27,7 @@
"android/soong/android"
"android/soong/cc"
+ "android/soong/dexpreopt"
"android/soong/java"
)
@@ -158,6 +159,7 @@
"my_include": nil,
"foo/bar/MyClass.java": nil,
"prebuilt.jar": nil,
+ "prebuilt.so": nil,
"vendor/foo/devkeys/test.x509.pem": nil,
"vendor/foo/devkeys/test.pk8": nil,
"testkey.x509.pem": nil,
@@ -367,7 +369,7 @@
apex_available: [ "myapex" ],
}
- cc_library {
+ cc_library_shared {
name: "mylib2",
srcs: ["mylib.cpp"],
system_shared_libs: [],
@@ -381,6 +383,16 @@
],
}
+ cc_prebuilt_library_shared {
+ name: "mylib2",
+ srcs: ["prebuilt.so"],
+ // TODO: remove //apex_available:platform
+ apex_available: [
+ "//apex_available:platform",
+ "myapex",
+ ],
+ }
+
cc_library_static {
name: "libstatic",
srcs: ["mylib.cpp"],
@@ -882,7 +894,7 @@
shouldNotLink []string
}{
{
- name: "should link to test latest",
+ name: "should link to the latest",
minSdkVersion: "current",
shouldLink: "30",
shouldNotLink: []string{"29"},
@@ -1222,7 +1234,7 @@
expectNoLink("libz", "shared", "libz", "shared")
}
-func TestQApexesUseLatestStubsInBundledBuilds(t *testing.T) {
+func TestQApexesUseLatestStubsInBundledBuildsAndHWASAN(t *testing.T) {
ctx, _ := testApex(t, `
apex {
name: "myapex",
@@ -1249,16 +1261,18 @@
versions: ["29", "30"],
},
}
- `)
+ `, func(fs map[string][]byte, config android.Config) {
+ config.TestProductVariables.SanitizeDevice = []string{"hwaddress"}
+ })
expectLink := func(from, from_variant, to, to_variant string) {
ld := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld")
libFlags := ld.Args["libFlags"]
ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
- expectLink("libx", "shared_myapex", "libbar", "shared_30")
+ expectLink("libx", "shared_hwasan_myapex", "libbar", "shared_30")
}
-func TestQTargetApexUseStaticUnwinder(t *testing.T) {
+func TestQTargetApexUsesStaticUnwinder(t *testing.T) {
ctx, _ := testApex(t, `
apex {
name: "myapex",
@@ -1277,8 +1291,7 @@
name: "libx",
apex_available: [ "myapex" ],
}
-
- `, withUnbundledBuild)
+ `)
// ensure apex variant of c++ is linked with static unwinder
cm := ctx.ModuleForTests("libc++", "android_arm64_armv8-a_shared_myapex").Module().(*cc.Module)
@@ -1289,7 +1302,7 @@
}
func TestInvalidMinSdkVersion(t *testing.T) {
- testApexError(t, `"libz" .*: min_sdk_version is set 29.*`, `
+ testApexError(t, `"libz" .*: not found a version\(<=29\)`, `
apex {
name: "myapex",
key: "myapex.key",
@@ -1319,9 +1332,9 @@
versions: ["30"],
},
}
- `, withUnbundledBuild)
+ `)
- testApexError(t, `"myapex" .*: min_sdk_version: should be .*`, `
+ testApexError(t, `"myapex" .*: min_sdk_version: should be "current" or <number>`, `
apex {
name: "myapex",
key: "myapex.key",
@@ -1842,7 +1855,7 @@
// non-APEX variant does not have __ANDROID_APEX__ defined
mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
- ensureNotContains(t, mylibCFlags, "-D__ANDROID_SDK_VERSION__=10000")
+ ensureNotContains(t, mylibCFlags, "-D__ANDROID_SDK_VERSION__")
// APEX variant has __ANDROID_APEX__ and __ANDROID_APEX_SDK__ defined
mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
@@ -3539,12 +3552,12 @@
func TestApexAvailable_IndirectDep(t *testing.T) {
// libbbaz is an indirect dep
testApexError(t, `requires "libbaz" that is not available for the APEX. Dependency path:
+.*via tag apex\.dependencyTag.*"sharedLib".*
.*-> libfoo.*link:shared.*
-.*-> libfoo.*link:static.*
+.*via tag cc\.DependencyTag.*"shared".*
.*-> libbar.*link:shared.*
-.*-> libbar.*link:static.*
-.*-> libbaz.*link:shared.*
-.*-> libbaz.*link:static.*`, `
+.*via tag cc\.DependencyTag.*"shared".*
+.*-> libbaz.*link:shared.*`, `
apex {
name: "myapex",
key: "myapex.key",
@@ -4191,6 +4204,175 @@
ensureContains(t, content, `"apex_config":{"apex_embedded_apk_config":[{"package_name":"com.android.foo","path":"app/AppFoo/AppFoo.apk"}]}`)
}
+func testNoUpdatableJarsInBootImage(t *testing.T, errmsg, bp string, transformDexpreoptConfig func(*dexpreopt.GlobalConfig)) {
+ t.Helper()
+
+ bp = bp + `
+ filegroup {
+ name: "some-updatable-apex-file_contexts",
+ srcs: [
+ "system/sepolicy/apex/some-updatable-apex-file_contexts",
+ ],
+ }
+ `
+ bp += cc.GatherRequiredDepsForTest(android.Android)
+ bp += java.GatherRequiredDepsForTest()
+ bp += dexpreopt.BpToolModulesForTest()
+
+ fs := map[string][]byte{
+ "a.java": nil,
+ "a.jar": nil,
+ "build/make/target/product/security": nil,
+ "apex_manifest.json": nil,
+ "AndroidManifest.xml": nil,
+ "system/sepolicy/apex/some-updatable-apex-file_contexts": nil,
+ "system/sepolicy/apex/com.android.art.something-file_contexts": nil,
+ "framework/aidl/a.aidl": nil,
+ }
+ cc.GatherRequiredFilesForTest(fs)
+
+ ctx := android.NewTestArchContext()
+ ctx.RegisterModuleType("apex", BundleFactory)
+ ctx.RegisterModuleType("apex_key", ApexKeyFactory)
+ ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
+ cc.RegisterRequiredBuildComponentsForTest(ctx)
+ java.RegisterJavaBuildComponents(ctx)
+ java.RegisterSystemModulesBuildComponents(ctx)
+ java.RegisterAppBuildComponents(ctx)
+ java.RegisterDexpreoptBootJarsComponents(ctx)
+ ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+ ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
+ ctx.PreDepsMutators(RegisterPreDepsMutators)
+ ctx.PostDepsMutators(RegisterPostDepsMutators)
+
+ config := android.TestArchConfig(buildDir, nil, bp, fs)
+ ctx.Register(config)
+
+ _ = dexpreopt.GlobalSoongConfigForTests(config)
+ dexpreopt.RegisterToolModulesForTest(ctx)
+ pathCtx := android.PathContextForTesting(config)
+ dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx)
+ transformDexpreoptConfig(dexpreoptConfig)
+ dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig)
+
+ _, errs := ctx.ParseBlueprintsFiles("Android.bp")
+ android.FailIfErrored(t, errs)
+
+ _, errs = ctx.PrepareBuildActions(config)
+ if errmsg == "" {
+ android.FailIfErrored(t, errs)
+ } else if len(errs) > 0 {
+ android.FailIfNoMatchingErrors(t, errmsg, errs)
+ return
+ } else {
+ t.Fatalf("missing expected error %q (0 errors are returned)", errmsg)
+ }
+}
+
+func TestNoUpdatableJarsInBootImage(t *testing.T) {
+ bp := `
+ java_library {
+ name: "some-updatable-apex-lib",
+ srcs: ["a.java"],
+ apex_available: [
+ "some-updatable-apex",
+ ],
+ }
+
+ java_library {
+ name: "some-platform-lib",
+ srcs: ["a.java"],
+ installable: true,
+ }
+
+ java_library {
+ name: "some-art-lib",
+ srcs: ["a.java"],
+ apex_available: [
+ "com.android.art.something",
+ ],
+ hostdex: true,
+ }
+
+ apex {
+ name: "some-updatable-apex",
+ key: "some-updatable-apex.key",
+ java_libs: ["some-updatable-apex-lib"],
+ }
+
+ apex_key {
+ name: "some-updatable-apex.key",
+ }
+
+ apex {
+ name: "com.android.art.something",
+ key: "com.android.art.something.key",
+ java_libs: ["some-art-lib"],
+ }
+
+ apex_key {
+ name: "com.android.art.something.key",
+ }
+ `
+
+ var error string
+ var transform func(*dexpreopt.GlobalConfig)
+
+ // updatable jar from ART apex in the ART boot image => ok
+ transform = func(config *dexpreopt.GlobalConfig) {
+ config.ArtApexJars = []string{"some-art-lib"}
+ }
+ testNoUpdatableJarsInBootImage(t, "", bp, transform)
+
+ // updatable jar from ART apex in the framework boot image => error
+ error = "module 'some-art-lib' from updatable apex 'com.android.art.something' is not allowed in the framework boot image"
+ transform = func(config *dexpreopt.GlobalConfig) {
+ config.BootJars = []string{"some-art-lib"}
+ }
+ testNoUpdatableJarsInBootImage(t, error, bp, transform)
+
+ // updatable jar from some other apex in the ART boot image => error
+ error = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the ART boot image"
+ transform = func(config *dexpreopt.GlobalConfig) {
+ config.ArtApexJars = []string{"some-updatable-apex-lib"}
+ }
+ testNoUpdatableJarsInBootImage(t, error, bp, transform)
+
+ // updatable jar from some other apex in the framework boot image => error
+ error = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the framework boot image"
+ transform = func(config *dexpreopt.GlobalConfig) {
+ config.BootJars = []string{"some-updatable-apex-lib"}
+ }
+ testNoUpdatableJarsInBootImage(t, error, bp, transform)
+
+ // nonexistent jar in the ART boot image => error
+ error = "failed to find a dex jar path for module 'nonexistent'"
+ transform = func(config *dexpreopt.GlobalConfig) {
+ config.ArtApexJars = []string{"nonexistent"}
+ }
+ testNoUpdatableJarsInBootImage(t, error, bp, transform)
+
+ // nonexistent jar in the framework boot image => error
+ error = "failed to find a dex jar path for module 'nonexistent'"
+ transform = func(config *dexpreopt.GlobalConfig) {
+ config.BootJars = []string{"nonexistent"}
+ }
+ testNoUpdatableJarsInBootImage(t, error, bp, transform)
+
+ // platform jar in the ART boot image => error
+ error = "module 'some-platform-lib' is part of the platform and not allowed in the ART boot image"
+ transform = func(config *dexpreopt.GlobalConfig) {
+ config.ArtApexJars = []string{"some-platform-lib"}
+ }
+ testNoUpdatableJarsInBootImage(t, error, bp, transform)
+
+ // platform jar in the framework boot image => ok
+ transform = func(config *dexpreopt.GlobalConfig) {
+ config.BootJars = []string{"some-platform-lib"}
+ }
+ testNoUpdatableJarsInBootImage(t, "", bp, transform)
+}
+
func TestMain(m *testing.M) {
run := func() int {
setUp()
diff --git a/apex/builder.go b/apex/builder.go
index 67bc206..5a2134a 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -230,12 +230,16 @@
func (a *apexBundle) buildNoticeFiles(ctx android.ModuleContext, apexFileName string) android.NoticeOutputs {
var noticeFiles android.Paths
- a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) {
+ a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
if externalDep {
- return
+ // As soon as the dependency graph crosses the APEX boundary, don't go further.
+ return false
}
+
notices := to.NoticeFiles()
noticeFiles = append(noticeFiles, notices...)
+
+ return true
})
if len(noticeFiles) == 0 {
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index 0516279..a1c5de1 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -124,6 +124,10 @@
Name: "removeHidlInterfaceTypes",
Fix: removeHidlInterfaceTypes,
},
+ {
+ Name: "removeSoongConfigBoolVariable",
+ Fix: removeSoongConfigBoolVariable,
+ },
}
func NewFixRequest() FixRequest {
@@ -714,6 +718,78 @@
return nil
}
+func removeSoongConfigBoolVariable(f *Fixer) error {
+ found := map[string]bool{}
+ newDefs := make([]parser.Definition, 0, len(f.tree.Defs))
+ for _, def := range f.tree.Defs {
+ if mod, ok := def.(*parser.Module); ok && mod.Type == "soong_config_bool_variable" {
+ if name, ok := getLiteralStringPropertyValue(mod, "name"); ok {
+ found[name] = true
+ } else {
+ return fmt.Errorf("Found soong_config_bool_variable without a name")
+ }
+ } else {
+ newDefs = append(newDefs, def)
+ }
+ }
+ f.tree.Defs = newDefs
+
+ if len(found) == 0 {
+ return nil
+ }
+
+ return runPatchListMod(func(mod *parser.Module, buf []byte, patchList *parser.PatchList) error {
+ if mod.Type != "soong_config_module_type" {
+ return nil
+ }
+
+ variables, ok := getLiteralListProperty(mod, "variables")
+ if !ok {
+ return nil
+ }
+
+ boolValues := strings.Builder{}
+ empty := true
+ for _, item := range variables.Values {
+ nameValue, ok := item.(*parser.String)
+ if !ok {
+ empty = false
+ continue
+ }
+ if found[nameValue.Value] {
+ patchList.Add(item.Pos().Offset, item.End().Offset+2, "")
+
+ boolValues.WriteString(`"`)
+ boolValues.WriteString(nameValue.Value)
+ boolValues.WriteString(`",`)
+ } else {
+ empty = false
+ }
+ }
+ if empty {
+ *patchList = parser.PatchList{}
+
+ prop, _ := mod.GetProperty("variables")
+ patchList.Add(prop.Pos().Offset, prop.End().Offset+2, "")
+ }
+ if boolValues.Len() == 0 {
+ return nil
+ }
+
+ bool_variables, ok := getLiteralListProperty(mod, "bool_variables")
+ if ok {
+ patchList.Add(bool_variables.RBracePos.Offset, bool_variables.RBracePos.Offset, ","+boolValues.String())
+ } else {
+ patchList.Add(variables.RBracePos.Offset+2, variables.RBracePos.Offset+2,
+ fmt.Sprintf(`bool_variables: [%s],`, boolValues.String()))
+ }
+
+ return nil
+ })(f)
+
+ return nil
+}
+
// Converts the default source list property, 'srcs', to a single source property with a given name.
// "LOCAL_MODULE" reference is also resolved during the conversion process.
func convertToSingleSource(mod *parser.Module, srcPropertyName string) {
diff --git a/bpfix/bpfix/bpfix_test.go b/bpfix/bpfix/bpfix_test.go
index 38cefdd..64a7b93 100644
--- a/bpfix/bpfix/bpfix_test.go
+++ b/bpfix/bpfix/bpfix_test.go
@@ -918,3 +918,67 @@
})
}
}
+
+func TestRemoveSoongConfigBoolVariable(t *testing.T) {
+ tests := []struct {
+ name string
+ in string
+ out string
+ }{
+ {
+ name: "remove bool",
+ in: `
+ soong_config_module_type {
+ name: "foo",
+ variables: ["bar", "baz"],
+ }
+
+ soong_config_bool_variable {
+ name: "bar",
+ }
+
+ soong_config_string_variable {
+ name: "baz",
+ }
+ `,
+ out: `
+ soong_config_module_type {
+ name: "foo",
+ variables: [
+ "baz"
+ ],
+ bool_variables: ["bar"],
+ }
+
+ soong_config_string_variable {
+ name: "baz",
+ }
+ `,
+ },
+ {
+ name: "existing bool_variables",
+ in: `
+ soong_config_module_type {
+ name: "foo",
+ variables: ["baz"],
+ bool_variables: ["bar"],
+ }
+
+ soong_config_bool_variable {
+ name: "baz",
+ }
+ `,
+ out: `
+ soong_config_module_type {
+ name: "foo",
+ bool_variables: ["bar", "baz"],
+ }
+ `,
+ },
+ }
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ runPass(t, test.in, test.out, removeSoongConfigBoolVariable)
+ })
+ }
+}
diff --git a/cc/cc.go b/cc/cc.go
index de07229..88fede4 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -488,6 +488,9 @@
makeLinkType string
// Kythe (source file indexer) paths for this compilation module
kytheFiles android.Paths
+
+ // For apex variants, this is set as apex.min_sdk_version
+ apexSdkVersion int
}
func (c *Module) Toc() android.OptionalPath {
@@ -1209,7 +1212,7 @@
}
func (ctx *moduleContextImpl) apexSdkVersion() int {
- return ctx.mod.ApexProperties.Info.MinSdkVersion
+ return ctx.mod.apexSdkVersion
}
func (ctx *moduleContextImpl) hasStubsVariants() bool {
@@ -1847,7 +1850,10 @@
}, depTag, lib)
}
- if deps.StaticUnwinderIfLegacy && ctx.Config().UnbundledBuild() {
+ // staticUnwinderDep is treated as staticDep for Q apexes
+ // so that native libraries/binaries are linked with static unwinder
+ // because Q libc doesn't have unwinder APIs
+ if deps.StaticUnwinderIfLegacy {
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
}, staticUnwinderDepTag, staticUnwinder(actx))
@@ -2231,9 +2237,22 @@
}
}
+ // For the dependency from platform to apex, use the latest stubs
+ c.apexSdkVersion = android.FutureApiLevel
+ if !c.IsForPlatform() {
+ c.apexSdkVersion = c.ApexProperties.Info.MinSdkVersion
+ }
+
+ if android.InList("hwaddress", ctx.Config().SanitizeDevice()) {
+ // In hwasan build, we override apexSdkVersion to the FutureApiLevel(10000)
+ // so that even Q(29/Android10) apexes could use the dynamic unwinder by linking the newer stubs(e.g libc(R+)).
+ // (b/144430859)
+ c.apexSdkVersion = android.FutureApiLevel
+ }
+
if depTag == staticUnwinderDepTag {
- // Use static unwinder for legacy (min_sdk_version = 29) apexes (b/144430859)
- if c.ShouldSupportAndroid10() {
+ // Use static unwinder for legacy (min_sdk_version = 29) apexes (b/144430859)
+ if c.apexSdkVersion <= android.SdkVersion_Android10 {
depTag = StaticDepTag
} else {
return
@@ -2287,8 +2306,7 @@
// when to use (unspecified) stubs, check min_sdk_version and choose the right one
if useThisDep && depIsStubs && !explicitlyVersioned {
- useLatest := c.IsForPlatform() || (c.ShouldSupportAndroid10() && !ctx.Config().UnbundledBuild())
- versionToUse, err := c.ChooseSdkVersion(ccDep.StubsVersions(), useLatest)
+ versionToUse, err := c.ChooseSdkVersion(ccDep.StubsVersions(), c.apexSdkVersion)
if err != nil {
ctx.OtherModuleErrorf(dep, err.Error())
return
@@ -2311,8 +2329,7 @@
// 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
- useLatest := c.ShouldSupportAndroid10() && !ctx.Config().UnbundledBuild()
- versionToUse, err = c.ChooseSdkVersion(versions, useLatest)
+ versionToUse, err = c.ChooseSdkVersion(versions, c.apexSdkVersion)
if err != nil {
ctx.OtherModuleErrorf(dep, err.Error())
return
diff --git a/cc/config/global.go b/cc/config/global.go
index 29020ab..5611a96 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -127,8 +127,8 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r377782c"
- ClangDefaultShortVersion = "10.0.5"
+ ClangDefaultVersion = "clang-r377782d"
+ ClangDefaultShortVersion = "10.0.6"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
diff --git a/cc/config/x86_darwin_host.go b/cc/config/x86_darwin_host.go
index 25225b5..8eb79e3 100644
--- a/cc/config/x86_darwin_host.go
+++ b/cc/config/x86_darwin_host.go
@@ -15,9 +15,11 @@
package config
import (
+ "fmt"
"os/exec"
"path/filepath"
"strings"
+ "sync"
"android/soong/android"
)
@@ -89,28 +91,20 @@
)
func init() {
- pctx.VariableFunc("macSdkPath", func(ctx android.PackageVarContext) string {
- xcodeselect := ctx.Config().HostSystemTool("xcode-select")
- bytes, err := exec.Command(xcodeselect, "--print-path").Output()
- if err != nil {
- ctx.Errorf("xcode-select failed with: %q", err.Error())
- }
- return strings.TrimSpace(string(bytes))
- })
pctx.VariableFunc("macSdkRoot", func(ctx android.PackageVarContext) string {
- return xcrunSdk(ctx, "--show-sdk-path")
+ return getMacTools(ctx).sdkRoot
})
pctx.StaticVariable("macMinVersion", "10.10")
pctx.VariableFunc("MacArPath", func(ctx android.PackageVarContext) string {
- return xcrun(ctx, "--find", "ar")
+ return getMacTools(ctx).arPath
})
pctx.VariableFunc("MacStripPath", func(ctx android.PackageVarContext) string {
- return xcrun(ctx, "--find", "strip")
+ return getMacTools(ctx).stripPath
})
pctx.VariableFunc("MacToolPath", func(ctx android.PackageVarContext) string {
- return filepath.Dir(xcrun(ctx, "--find", "ld"))
+ return getMacTools(ctx).toolPath
})
pctx.StaticVariable("DarwinGccVersion", darwinGccVersion)
@@ -126,38 +120,66 @@
pctx.StaticVariable("DarwinYasmFlags", "-f macho -m amd64")
}
-func xcrun(ctx android.PackageVarContext, args ...string) string {
- xcrun := ctx.Config().HostSystemTool("xcrun")
- bytes, err := exec.Command(xcrun, args...).Output()
- if err != nil {
- ctx.Errorf("xcrun failed with: %q", err.Error())
- }
- return strings.TrimSpace(string(bytes))
+type macPlatformTools struct {
+ once sync.Once
+ err error
+
+ sdkRoot string
+ arPath string
+ stripPath string
+ toolPath string
}
-func xcrunSdk(ctx android.PackageVarContext, arg string) string {
- xcrun := ctx.Config().HostSystemTool("xcrun")
- if selected := ctx.Config().Getenv("MAC_SDK_VERSION"); selected != "" {
- if !inList(selected, darwinSupportedSdkVersions) {
- ctx.Errorf("MAC_SDK_VERSION %s isn't supported: %q", selected, darwinSupportedSdkVersions)
+var macTools = &macPlatformTools{}
+
+func getMacTools(ctx android.PackageVarContext) *macPlatformTools {
+ macTools.once.Do(func() {
+ xcrunTool := ctx.Config().HostSystemTool("xcrun")
+
+ xcrun := func(args ...string) string {
+ if macTools.err != nil {
+ return ""
+ }
+
+ bytes, err := exec.Command(xcrunTool, args...).Output()
+ if err != nil {
+ macTools.err = fmt.Errorf("xcrun %q failed with: %q", args, err)
+ return ""
+ }
+
+ return strings.TrimSpace(string(bytes))
+ }
+
+ xcrunSdk := func(arg string) string {
+ if selected := ctx.Config().Getenv("MAC_SDK_VERSION"); selected != "" {
+ if !inList(selected, darwinSupportedSdkVersions) {
+ macTools.err = fmt.Errorf("MAC_SDK_VERSION %s isn't supported: %q", selected, darwinSupportedSdkVersions)
+ return ""
+ }
+
+ return xcrun("--sdk", "macosx"+selected, arg)
+ }
+
+ for _, sdk := range darwinSupportedSdkVersions {
+ bytes, err := exec.Command(xcrunTool, "--sdk", "macosx"+sdk, arg).Output()
+ if err == nil {
+ return strings.TrimSpace(string(bytes))
+ }
+ }
+ macTools.err = fmt.Errorf("Could not find a supported mac sdk: %q", darwinSupportedSdkVersions)
return ""
}
- bytes, err := exec.Command(xcrun, "--sdk", "macosx"+selected, arg).Output()
- if err != nil {
- ctx.Errorf("MAC_SDK_VERSION %s is not installed", selected)
- }
- return strings.TrimSpace(string(bytes))
- }
+ macTools.sdkRoot = xcrunSdk("--show-sdk-path")
- for _, sdk := range darwinSupportedSdkVersions {
- bytes, err := exec.Command(xcrun, "--sdk", "macosx"+sdk, arg).Output()
- if err == nil {
- return strings.TrimSpace(string(bytes))
- }
+ macTools.arPath = xcrun("--find", "ar")
+ macTools.stripPath = xcrun("--find", "strip")
+ macTools.toolPath = filepath.Dir(xcrun("--find", "ld"))
+ })
+ if macTools.err != nil {
+ ctx.Errorf("%q", macTools.err)
}
- ctx.Errorf("Could not find a supported mac sdk: %q", darwinSupportedSdkVersions)
- return ""
+ return macTools
}
type toolchainDarwin struct {
diff --git a/cc/library.go b/cc/library.go
index b9f448b..439a2c0 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -376,7 +376,7 @@
useCoreVariant bool
checkSameCoreVariant bool
- // Decorated interafaces
+ // Decorated interfaces
*baseCompiler
*baseLinker
*baseInstaller
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index 0a11af1..754b96a 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -269,6 +269,11 @@
for property, dirs := range includeDirs {
outputProperties.AddProperty(property, dirs)
}
+
+ if len(libInfo.StubsVersion) > 0 {
+ stubsSet := outputProperties.AddPropertySet("stubs")
+ stubsSet.AddProperty("versions", []string{libInfo.StubsVersion})
+ }
}
const (
@@ -335,6 +340,10 @@
// This field is exported as its contents may not be arch specific.
SystemSharedLibs []string
+ // The specific stubs version for the lib variant, or empty string if stubs
+ // are not in use.
+ StubsVersion string
+
// outputFile is not exported as it is always arch specific.
outputFile android.Path
}
@@ -370,6 +379,10 @@
p.SystemSharedLibs = specifiedDeps.systemSharedLibs
}
p.exportedGeneratedHeaders = ccModule.ExportedGeneratedHeaders()
+
+ if ccModule.HasStubsVariants() {
+ p.StubsVersion = ccModule.StubsVersion()
+ }
}
func (p *nativeLibInfoProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go
index e849aee..3a630d2 100644
--- a/cc/ndk_prebuilt.go
+++ b/cc/ndk_prebuilt.go
@@ -90,6 +90,11 @@
return ndkPrebuiltModuleToPath(ctx, flags.Toolchain, objectExtension, ctx.sdkVersion())
}
+func (*ndkPrebuiltObjectLinker) availableFor(what string) bool {
+ // ndk prebuilt objects are available to everywhere
+ return true
+}
+
type ndkPrebuiltStlLinker struct {
*libraryDecorator
}
@@ -103,6 +108,11 @@
return deps
}
+func (*ndkPrebuiltStlLinker) availableFor(what string) bool {
+ // ndk prebuilt objects are available to everywhere
+ return true
+}
+
// ndk_prebuilt_shared_stl exports a precompiled ndk shared standard template
// library (stl) library for linking operation. The soong's module name format
// is ndk_<NAME>.so where the library is located under
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index 242d835..0b018c1 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -22,6 +22,25 @@
"github.com/google/blueprint"
)
+func testPrebuilt(t *testing.T, bp string, fs map[string][]byte) *android.TestContext {
+ config := TestConfig(buildDir, android.Android, nil, bp, fs)
+ ctx := CreateTestContext()
+
+ // Enable androidmk support.
+ // * Register the singleton
+ // * Configure that we are inside make
+ // * Add CommonOS to ensure that androidmk processing works.
+ android.RegisterAndroidMkBuildComponents(ctx)
+ android.SetInMakeForTests(config)
+
+ ctx.Register(config)
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
+ return ctx
+}
+
func TestPrebuilt(t *testing.T) {
bp := `
cc_library {
@@ -84,7 +103,15 @@
}
`
- ctx := testPrebuilt(t, bp)
+ ctx := testPrebuilt(t, bp, map[string][]byte{
+ "liba.so": nil,
+ "libb.a": nil,
+ "libd.so": nil,
+ "libe.a": nil,
+ "libf.a": nil,
+ "libf.so": nil,
+ "crtx.o": nil,
+ })
// Verify that all the modules exist and that their dependencies were connected correctly
liba := ctx.ModuleForTests("liba", "android_arm64_armv8-a_shared").Module()
@@ -143,35 +170,6 @@
}
}
-func testPrebuilt(t *testing.T, bp string) *android.TestContext {
-
- fs := map[string][]byte{
- "liba.so": nil,
- "libb.a": nil,
- "libd.so": nil,
- "libe.a": nil,
- "libf.a": nil,
- "libf.so": nil,
- "crtx.o": nil,
- }
- config := TestConfig(buildDir, android.Android, nil, bp, fs)
- ctx := CreateTestContext()
-
- // Enable androidmk support.
- // * Register the singleton
- // * Configure that we are inside make
- // * Add CommonOS to ensure that androidmk processing works.
- android.RegisterAndroidMkBuildComponents(ctx)
- android.SetInMakeForTests(config)
-
- ctx.Register(config)
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
- return ctx
-}
-
func TestPrebuiltLibraryShared(t *testing.T) {
ctx := testPrebuilt(t, `
cc_prebuilt_library_shared {
@@ -181,7 +179,9 @@
none: true,
},
}
- `)
+ `, map[string][]byte{
+ "libf.so": nil,
+ })
shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
assertString(t, shared.OutputFile().String(), "libf.so")
@@ -193,7 +193,9 @@
name: "libtest",
srcs: ["libf.a"],
}
- `)
+ `, map[string][]byte{
+ "libf.a": nil,
+ })
static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
assertString(t, static.OutputFile().String(), "libf.a")
@@ -213,7 +215,10 @@
none: true,
},
}
- `)
+ `, map[string][]byte{
+ "libf.a": nil,
+ "libf.so": nil,
+ })
shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
assertString(t, shared.OutputFile().String(), "libf.so")
diff --git a/cc/testing.go b/cc/testing.go
index e9739ff..f85795b 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -67,6 +67,20 @@
src: "",
}
+ cc_prebuilt_library_shared {
+ name: "libclang_rt.hwasan-aarch64-android",
+ nocrt: true,
+ vendor_available: true,
+ recovery_available: true,
+ system_shared_libs: [],
+ stl: "none",
+ srcs: [""],
+ check_elf_files: false,
+ sanitize: {
+ never: true,
+ },
+ }
+
toolchain_library {
name: "libclang_rt.builtins-i686-android",
vendor_available: true,
diff --git a/cmd/zipsync/zipsync.go b/cmd/zipsync/zipsync.go
index a6023d3..294e5ef 100644
--- a/cmd/zipsync/zipsync.go
+++ b/cmd/zipsync/zipsync.go
@@ -115,7 +115,7 @@
filename := filepath.Join(*outputDir, name)
if f.FileInfo().IsDir() {
- must(os.MkdirAll(filename, f.FileInfo().Mode()))
+ must(os.MkdirAll(filename, 0777))
} else {
must(os.MkdirAll(filepath.Dir(filename), 0777))
in, err := f.Open()
diff --git a/java/androidmk.go b/java/androidmk.go
index ee2437a..136bb36 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -72,6 +72,7 @@
if !hideFromMake {
mainEntries = android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
+ DistFile: android.OptionalPathForPath(library.distFile),
OutputFile: android.OptionalPathForPath(library.outputFile),
Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
diff --git a/java/androidmk_test.go b/java/androidmk_test.go
index acc6bf0..7daa624 100644
--- a/java/androidmk_test.go
+++ b/java/androidmk_test.go
@@ -16,6 +16,7 @@
import (
"reflect"
+ "strings"
"testing"
"android/soong/android"
@@ -133,3 +134,38 @@
t.Errorf("Unexpected required modules - expected: %q, actual: %q", expected, actual)
}
}
+
+func TestDistWithTag(t *testing.T) {
+ ctx, config := testJava(t, `
+ java_library {
+ name: "foo_without_tag",
+ srcs: ["a.java"],
+ compile_dex: true,
+ dist: {
+ targets: ["hi"],
+ },
+ }
+ java_library {
+ name: "foo_with_tag",
+ srcs: ["a.java"],
+ compile_dex: true,
+ dist: {
+ targets: ["hi"],
+ tag: ".jar",
+ },
+ }
+ `)
+
+ without_tag_entries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_without_tag", "android_common").Module())
+ with_tag_entries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_with_tag", "android_common").Module())
+
+ if len(without_tag_entries) != 2 || len(with_tag_entries) != 2 {
+ t.Errorf("two mk entries per module expected, got %d and %d", len(without_tag_entries), len(with_tag_entries))
+ }
+ if !with_tag_entries[0].DistFile.Valid() || !strings.Contains(with_tag_entries[0].DistFile.String(), "/javac/foo_with_tag.jar") {
+ t.Errorf("expected classes.jar DistFile, got %v", with_tag_entries[0].DistFile)
+ }
+ if without_tag_entries[0].DistFile.Valid() {
+ t.Errorf("did not expect explicit DistFile, got %v", without_tag_entries[0].DistFile)
+ }
+}
diff --git a/java/app.go b/java/app.go
index 3f6c1d9..0a4d9e4 100755
--- a/java/app.go
+++ b/java/app.go
@@ -529,14 +529,28 @@
// Build a final signed app package.
packageFile := android.PathForModuleOut(ctx, a.installApkName+".apk")
- CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps)
+ v4SigningRequested := Bool(a.Module.deviceProperties.V4_signature)
+ var v4SignatureFile android.WritablePath = nil
+ if v4SigningRequested {
+ v4SignatureFile = android.PathForModuleOut(ctx, a.installApkName+".apk.idsig")
+ }
+ CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps, v4SignatureFile)
a.outputFile = packageFile
+ if v4SigningRequested {
+ a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile)
+ }
for _, split := range a.aapt.splits {
// Sign the split APKs
packageFile := android.PathForModuleOut(ctx, a.installApkName+"_"+split.suffix+".apk")
- CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps)
+ if v4SigningRequested {
+ v4SignatureFile = android.PathForModuleOut(ctx, a.installApkName+"_"+split.suffix+".apk.idsig")
+ }
+ CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps, v4SignatureFile)
a.extraOutputFiles = append(a.extraOutputFiles, packageFile)
+ if v4SigningRequested {
+ a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile)
+ }
}
// Build an app bundle.
@@ -1156,7 +1170,7 @@
}
a.certificate = certificates[0]
signed := android.PathForModuleOut(ctx, "signed", ctx.ModuleName()+".apk")
- SignAppPackage(ctx, signed, dexOutput, certificates)
+ SignAppPackage(ctx, signed, dexOutput, certificates, nil)
a.outputFile = signed
} else {
alignedApk := android.PathForModuleOut(ctx, "zip-aligned", ctx.ModuleName()+".apk")
@@ -1361,7 +1375,7 @@
_, certificates := collectAppDeps(ctx, false, false)
certificates = processMainCert(r.ModuleBase, String(r.properties.Certificate), certificates, ctx)
signed := android.PathForModuleOut(ctx, "signed", r.Name()+".apk")
- SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates)
+ SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates, nil)
r.certificate = certificates[0]
r.outputFile = signed
diff --git a/java/app_builder.go b/java/app_builder.go
index 5e7fbe6..b2780bc 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -45,7 +45,7 @@
})
func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
- packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths) {
+ packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths, v4SignatureFile android.WritablePath) {
unsignedApkName := strings.TrimSuffix(outputFile.Base(), ".apk") + "-unsigned.apk"
unsignedApk := android.PathForModuleOut(ctx, unsignedApkName)
@@ -66,10 +66,10 @@
Implicits: deps,
})
- SignAppPackage(ctx, outputFile, unsignedApk, certificates)
+ SignAppPackage(ctx, outputFile, unsignedApk, certificates, v4SignatureFile)
}
-func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, unsignedApk android.Path, certificates []Certificate) {
+func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, unsignedApk android.Path, certificates []Certificate, v4SignatureFile android.WritablePath) {
var certificateArgs []string
var deps android.Paths
@@ -78,14 +78,22 @@
deps = append(deps, c.Pem, c.Key)
}
+ outputFiles := android.WritablePaths{signedApk}
+ var flag string = ""
+ if v4SignatureFile != nil {
+ outputFiles = append(outputFiles, v4SignatureFile)
+ flag = "--enable-v4"
+ }
+
ctx.Build(pctx, android.BuildParams{
Rule: Signapk,
Description: "signapk",
- Output: signedApk,
+ Outputs: outputFiles,
Input: unsignedApk,
Implicits: deps,
Args: map[string]string{
"certificates": strings.Join(certificateArgs, " "),
+ "flags": flag,
},
})
}
diff --git a/java/app_test.go b/java/app_test.go
index 0c6da7a..f3cd070 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1074,6 +1074,66 @@
}
}
+func TestRequestV4SigningFlag(t *testing.T) {
+ testCases := []struct {
+ name string
+ bp string
+ expected string
+ }{
+ {
+ name: "default",
+ bp: `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ }
+ `,
+ expected: "",
+ },
+ {
+ name: "default",
+ bp: `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ v4_signature: false,
+ }
+ `,
+ expected: "",
+ },
+ {
+ name: "module certificate property",
+ bp: `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ v4_signature: true,
+ }
+ `,
+ expected: "--enable-v4",
+ },
+ }
+
+ for _, test := range testCases {
+ t.Run(test.name, func(t *testing.T) {
+ config := testAppConfig(nil, test.bp, nil)
+ ctx := testContext()
+
+ run(t, ctx, config)
+ foo := ctx.ModuleForTests("foo", "android_common")
+
+ signapk := foo.Output("foo.apk")
+ signFlags := signapk.Args["flags"]
+ if test.expected != signFlags {
+ t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expected, signFlags)
+ }
+ })
+ }
+}
+
func TestPackageNameOverride(t *testing.T) {
testCases := []struct {
name string
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 4db62b3..543b233 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -16,6 +16,7 @@
import (
"path/filepath"
+ "sort"
"strings"
"android/soong/android"
@@ -25,7 +26,7 @@
)
func init() {
- android.RegisterSingletonType("dex_bootjars", dexpreoptBootJarsFactory)
+ RegisterDexpreoptBootJarsComponents(android.InitRegistrationContext)
}
// Target-independent description of pre-compiled boot image.
@@ -173,6 +174,10 @@
return &dexpreoptBootJars{}
}
+func RegisterDexpreoptBootJarsComponents(ctx android.RegistrationContext) {
+ ctx.RegisterSingletonType("dex_bootjars", dexpreoptBootJarsFactory)
+}
+
func skipDexpreoptBootJars(ctx android.PathContext) bool {
if dexpreopt.GetGlobalConfig(ctx).DisablePreopt {
return true
@@ -241,16 +246,66 @@
dumpOatRules(ctx, d.defaultBootImage)
}
+// Inspect this module to see if it contains a bootclasspath dex jar.
+// Note that the same jar may occur in multiple modules.
+// This logic is tested in the apex package to avoid import cycle apex <-> java.
+func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, module android.Module) (int, android.Path) {
+ // All apex Java libraries have non-installable platform variants, skip them.
+ if module.IsSkipInstall() {
+ return -1, nil
+ }
+
+ jar, hasJar := module.(interface{ DexJar() android.Path })
+ if !hasJar {
+ return -1, nil
+ }
+
+ name := ctx.ModuleName(module)
+ index := android.IndexList(name, image.modules)
+ if index == -1 {
+ return -1, nil
+ }
+
+ // Check that this module satisfies constraints for a particular boot image.
+ apex, isApexModule := module.(android.ApexModule)
+ if image.name == artBootImageName {
+ if isApexModule && strings.HasPrefix(apex.ApexName(), "com.android.art.") {
+ // ok, found the jar in the ART apex
+ } else if isApexModule && !apex.IsForPlatform() {
+ // this jar is part of an updatable apex other than ART, fail immediately
+ ctx.Errorf("module '%s' from updatable apex '%s' is not allowed in the ART boot image", name, apex.ApexName())
+ } else if isApexModule && apex.IsForPlatform() && Bool(module.(*Library).deviceProperties.Hostdex) {
+ // this is a special "hostdex" variant, skip it and resume search
+ return -1, nil
+ } else if name == "jacocoagent" && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
+ // this is Jacoco platform variant for a coverage build, skip it and resume search
+ return -1, nil
+ } else {
+ // this (installable) jar is part of the platform, fail immediately
+ ctx.Errorf("module '%s' is part of the platform and not allowed in the ART boot image", name)
+ }
+ } else if image.name == frameworkBootImageName {
+ if !isApexModule || apex.IsForPlatform() {
+ // ok, this jar is part of the platform
+ } else {
+ // this jar is part of an updatable apex, fail immediately
+ ctx.Errorf("module '%s' from updatable apex '%s' is not allowed in the framework boot image", name, apex.ApexName())
+ }
+ } else {
+ panic("unknown boot image: " + image.name)
+ }
+
+ return index, jar.DexJar()
+}
+
// buildBootImage takes a bootImageConfig, creates rules to build it, and returns the image.
func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootImageConfig {
+ // Collect dex jar paths for the boot image modules.
+ // This logic is tested in the apex package to avoid import cycle apex <-> java.
bootDexJars := make(android.Paths, len(image.modules))
ctx.VisitAllModules(func(module android.Module) {
- // Collect dex jar paths for the modules listed above.
- if j, ok := module.(interface{ DexJar() android.Path }); ok {
- name := ctx.ModuleName(module)
- if i := android.IndexList(name, image.modules); i != -1 {
- bootDexJars[i] = j.DexJar()
- }
+ if i, j := getBootImageJar(ctx, image, module); i != -1 {
+ bootDexJars[i] = j
}
})
@@ -262,7 +317,8 @@
missingDeps = append(missingDeps, image.modules[i])
bootDexJars[i] = android.PathForOutput(ctx, "missing")
} else {
- ctx.Errorf("failed to find dex jar path for module %q",
+ ctx.Errorf("failed to find a dex jar path for module '%s'"+
+ ", note that some jars may be filtered out by module constraints",
image.modules[i])
}
}
@@ -281,6 +337,7 @@
profile := bootImageProfileRule(ctx, image, missingDeps)
bootFrameworkProfileRule(ctx, image, missingDeps)
+ updatableBcpPackagesRule(ctx, image, missingDeps)
var allFiles android.Paths
for _, variant := range image.variants {
@@ -549,6 +606,61 @@
var bootFrameworkProfileRuleKey = android.NewOnceKey("bootFrameworkProfileRule")
+func updatableBcpPackagesRule(ctx android.SingletonContext, image *bootImageConfig, missingDeps []string) android.WritablePath {
+ if ctx.Config().IsPdkBuild() || ctx.Config().UnbundledBuild() {
+ return nil
+ }
+
+ return ctx.Config().Once(updatableBcpPackagesRuleKey, func() interface{} {
+ global := dexpreopt.GetGlobalConfig(ctx)
+ updatableModules := dexpreopt.GetJarsFromApexJarPairs(global.UpdatableBootJars)
+
+ // Collect `permitted_packages` for updatable boot jars.
+ var updatablePackages []string
+ ctx.VisitAllModules(func(module android.Module) {
+ if j, ok := module.(*Library); ok {
+ name := ctx.ModuleName(module)
+ if i := android.IndexList(name, updatableModules); i != -1 {
+ pp := j.properties.Permitted_packages
+ if len(pp) > 0 {
+ updatablePackages = append(updatablePackages, pp...)
+ } else {
+ ctx.Errorf("Missing permitted_packages for %s", name)
+ }
+ // Do not match the same library repeatedly.
+ updatableModules = append(updatableModules[:i], updatableModules[i+1:]...)
+ }
+ }
+ })
+
+ // Sort updatable packages to ensure deterministic ordering.
+ sort.Strings(updatablePackages)
+
+ updatableBcpPackagesName := "updatable-bcp-packages.txt"
+ updatableBcpPackages := image.dir.Join(ctx, updatableBcpPackagesName)
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.WriteFile,
+ Output: updatableBcpPackages,
+ Args: map[string]string{
+ // WriteFile automatically adds the last end-of-line.
+ "content": strings.Join(updatablePackages, "\\n"),
+ },
+ })
+
+ rule := android.NewRuleBuilder()
+ rule.MissingDeps(missingDeps)
+ rule.Install(updatableBcpPackages, "/system/etc/"+updatableBcpPackagesName)
+ // TODO: Rename `profileInstalls` to `extraInstalls`?
+ // Maybe even move the field out of the bootImageConfig into some higher level type?
+ image.profileInstalls = append(image.profileInstalls, rule.Installs()...)
+
+ return updatableBcpPackages
+ }).(android.WritablePath)
+}
+
+var updatableBcpPackagesRuleKey = android.NewOnceKey("updatableBcpPackagesRule")
+
func dumpOatRules(ctx android.SingletonContext, image *bootImageConfig) {
var allPhonies android.Paths
for _, image := range image.variants {
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index 94ca8bb..127c201 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -53,7 +53,7 @@
ctx := testContext()
- ctx.RegisterSingletonType("dex_bootjars", dexpreoptBootJarsFactory)
+ RegisterDexpreoptBootJarsComponents(ctx)
run(t, ctx, config)
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 1315aba..066694c 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -81,7 +81,7 @@
func getDexLocation(ctx android.PathContext, target android.Target, subdir string, name string) string {
if target.Os.Class == android.Host {
- return filepath.Join("out", "host", ctx.Config().PrebuiltOS(), subdir, name)
+ return filepath.Join(ctx.Config().Getenv("OUT_DIR"), "host", ctx.Config().PrebuiltOS(), subdir, name)
} else {
return filepath.Join("/", subdir, name)
}
diff --git a/java/java.go b/java/java.go
index 7645d85..a8ca3ff 100644
--- a/java/java.go
+++ b/java/java.go
@@ -325,6 +325,10 @@
UncompressDex bool `blueprint:"mutated"`
IsSDKLibrary bool `blueprint:"mutated"`
+
+ // If true, generate the signature file of APK Signing Scheme V4, along side the signed APK file.
+ // Defaults to false.
+ V4_signature *bool
}
func (me *CompilerDeviceProperties) EffectiveOptimizeEnabled() bool {
@@ -421,6 +425,8 @@
// list of the xref extraction files
kytheFiles android.Paths
+
+ distFile android.Path
}
func (j *Module) OutputFiles(tag string) (android.Paths, error) {
@@ -1754,11 +1760,6 @@
if staticLibTag == ctx.OtherModuleDependencyTag(dep) {
return true
}
- // Also, a dependency to an sdk member is also considered as such. This is required because
- // sdk members should be mutated into APEXes. Refer to sdk.sdkDepsReplaceMutator.
- if sa, ok := dep.(android.SdkAware); ok && sa.IsInAnySdk() {
- return true
- }
return false
}
@@ -1778,9 +1779,18 @@
// Java libraries (.jar file)
//
+type LibraryProperties struct {
+ Dist struct {
+ // The tag of the output of this module that should be output.
+ Tag *string `android:"arch_variant"`
+ } `android:"arch_variant"`
+}
+
type Library struct {
Module
+ libraryProperties LibraryProperties
+
InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.Paths)
}
@@ -1824,6 +1834,15 @@
j.installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
ctx.ModuleName()+".jar", j.outputFile, extraInstallDeps...)
}
+
+ // Verify Dist.Tag is set to a supported output
+ if j.libraryProperties.Dist.Tag != nil {
+ distFiles, err := j.OutputFiles(*j.libraryProperties.Dist.Tag)
+ if err != nil {
+ ctx.PropertyErrorf("dist.tag", "%s", err.Error())
+ }
+ j.distFile = distFiles[0]
+ }
}
func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -1944,7 +1963,8 @@
&module.Module.properties,
&module.Module.deviceProperties,
&module.Module.dexpreoptProperties,
- &module.Module.protoProperties)
+ &module.Module.protoProperties,
+ &module.libraryProperties)
android.InitApexModule(module)
android.InitSdkAwareModule(module)
@@ -2488,11 +2508,6 @@
if staticLibTag == ctx.OtherModuleDependencyTag(dep) {
return true
}
- // Also, a dependency to an sdk member is also considered as such. This is required because
- // sdk members should be mutated into APEXes. Refer to sdk.sdkDepsReplaceMutator.
- if sa, ok := dep.(android.SdkAware); ok && sa.IsInAnySdk() {
- return true
- }
return false
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 6921114..efee7da 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -18,7 +18,6 @@
"android/soong/android"
"fmt"
- "io"
"path"
"path/filepath"
"sort"
@@ -87,6 +86,9 @@
// *current. Older stubs library built with a numbered SDK version is created from
// the prebuilt jar.
sdkVersion string
+
+ // Extra arguments to pass to droidstubs for this scope.
+ droidstubsArgs []string
}
// Initialize a scope, creating and adding appropriate dependency tags
@@ -132,6 +134,7 @@
moduleSuffix: sdkSystemApiSuffix,
apiFileMakeVariableSuffix: "_SYSTEM",
sdkVersion: "system_current",
+ droidstubsArgs: []string{"-showAnnotation android.annotation.SystemApi"},
})
apiScopeTest = initApiScope(&apiScope{
name: "test",
@@ -139,6 +142,7 @@
moduleSuffix: sdkTestApiSuffix,
apiFileMakeVariableSuffix: "_TEST",
sdkVersion: "test_current",
+ droidstubsArgs: []string{"-showAnnotation android.annotation.TestApi"},
})
allApiScopes = apiScopes{
apiScopePublic,
@@ -328,41 +332,6 @@
entriesList := module.Library.AndroidMkEntries()
entries := &entriesList[0]
entries.Required = append(entries.Required, module.xmlFileName())
-
- entries.ExtraFooters = []android.AndroidMkExtraFootersFunc{
- func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
- if !Bool(module.sdkLibraryProperties.No_dist) {
- // Create a phony module that installs the impl library, for the case when this lib is
- // in PRODUCT_PACKAGES.
- owner := module.ModuleBase.Owner()
- if owner == "" {
- if Bool(module.sdkLibraryProperties.Core_lib) {
- owner = "core"
- } else {
- owner = "android"
- }
- }
-
- // Create dist rules to install the stubs libs and api files to the dist dir
- for _, apiScope := range module.getActiveApiScopes() {
- if scopePaths, ok := module.scopePaths[apiScope]; ok {
- if len(scopePaths.stubsHeaderPath) == 1 {
- fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
- scopePaths.stubsImplPath.Strings()[0]+
- ":"+path.Join("apistubs", owner, apiScope.name,
- module.BaseModuleName()+".jar")+")")
- }
- if scopePaths.apiFilePath != nil {
- fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
- scopePaths.apiFilePath.String()+
- ":"+path.Join("apistubs", owner, apiScope.name, "api",
- module.BaseModuleName()+".txt")+")")
- }
- }
- }
- }
- },
- }
return entriesList
}
@@ -386,6 +355,17 @@
return module.BaseModuleName() + sdkXmlFileSuffix
}
+// The dist path of the stub artifacts
+func (module *SdkLibrary) apiDistPath(apiScope *apiScope) string {
+ if module.ModuleBase.Owner() != "" {
+ return path.Join("apistubs", module.ModuleBase.Owner(), apiScope.name)
+ } else if Bool(module.sdkLibraryProperties.Core_lib) {
+ return path.Join("apistubs", "core", apiScope.name)
+ } else {
+ return path.Join("apistubs", "android", apiScope.name)
+ }
+}
+
// Get the sdk version for use when compiling the stubs library.
func (module *SdkLibrary) sdkVersionForStubsLibrary(mctx android.LoadHookContext, apiScope *apiScope) string {
sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
@@ -438,6 +418,12 @@
Srcs []string
Javacflags []string
}
+ Dist struct {
+ Targets []string
+ Dest *string
+ Dir *string
+ Tag *string
+ }
}{}
props.Name = proptools.StringPtr(module.stubsName(apiScope))
@@ -466,11 +452,18 @@
} else if module.SystemExtSpecific() {
props.System_ext_specific = proptools.BoolPtr(true)
}
+ // Dist the class jar artifact for sdk builds.
+ if !Bool(module.sdkLibraryProperties.No_dist) {
+ props.Dist.Targets = []string{"sdk", "win_sdk"}
+ props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.BaseModuleName()))
+ props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope))
+ props.Dist.Tag = proptools.StringPtr(".jar")
+ }
mctx.CreateModule(LibraryFactory, &props)
}
-// Creates a droiddoc module that creates stubs source files from the given full source
+// Creates a droidstubs module that creates stubs source files from the given full source
// files
func (module *SdkLibrary) createStubsSources(mctx android.LoadHookContext, apiScope *apiScope) {
props := struct {
@@ -497,6 +490,11 @@
Include_dirs []string
Local_include_dirs []string
}
+ Dist struct {
+ Targets []string
+ Dest *string
+ Dir *string
+ }
}{}
sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
@@ -523,15 +521,15 @@
props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs
props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs
- droiddocArgs := []string{}
+ droidstubsArgs := []string{}
if len(module.sdkLibraryProperties.Api_packages) != 0 {
- droiddocArgs = append(droiddocArgs, "--stub-packages "+strings.Join(module.sdkLibraryProperties.Api_packages, ":"))
+ droidstubsArgs = append(droidstubsArgs, "--stub-packages "+strings.Join(module.sdkLibraryProperties.Api_packages, ":"))
}
if len(module.sdkLibraryProperties.Hidden_api_packages) != 0 {
- droiddocArgs = append(droiddocArgs,
+ droidstubsArgs = append(droidstubsArgs,
android.JoinWithPrefix(module.sdkLibraryProperties.Hidden_api_packages, " --hide-package "))
}
- droiddocArgs = append(droiddocArgs, module.sdkLibraryProperties.Droiddoc_options...)
+ droidstubsArgs = append(droidstubsArgs, module.sdkLibraryProperties.Droiddoc_options...)
disabledWarnings := []string{
"MissingPermission",
"BroadcastBehavior",
@@ -543,16 +541,12 @@
"Todo",
"Typo",
}
- droiddocArgs = append(droiddocArgs, android.JoinWithPrefix(disabledWarnings, "--hide "))
+ droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide "))
- switch apiScope {
- case apiScopeSystem:
- droiddocArgs = append(droiddocArgs, "-showAnnotation android.annotation.SystemApi")
- case apiScopeTest:
- droiddocArgs = append(droiddocArgs, " -showAnnotation android.annotation.TestApi")
- }
+ // Add in scope specific arguments.
+ droidstubsArgs = append(droidstubsArgs, apiScope.droidstubsArgs...)
props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files
- props.Args = proptools.StringPtr(strings.Join(droiddocArgs, " "))
+ props.Args = proptools.StringPtr(strings.Join(droidstubsArgs, " "))
// List of APIs identified from the provided source files are created. They are later
// compared against to the not-yet-released (a.k.a current) list of APIs and to the
@@ -578,6 +572,13 @@
module.latestRemovedApiFilegroupName(apiScope))
props.Check_api.Ignore_missing_latest_api = proptools.BoolPtr(true)
+ // Dist the api txt artifact for sdk builds.
+ if !Bool(module.sdkLibraryProperties.No_dist) {
+ props.Dist.Targets = []string{"sdk", "win_sdk"}
+ props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.txt", module.BaseModuleName()))
+ props.Dist.Dir = proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api"))
+ }
+
mctx.CreateModule(DroidstubsFactory, &props)
}
diff --git a/rust/compiler.go b/rust/compiler.go
index 4593165..81b258c 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -222,7 +222,10 @@
if ctx.toolchain().Is64Bit() && compiler.dir64 != "" {
dir = compiler.dir64
}
- if !ctx.Host() || ctx.Target().NativeBridge == android.NativeBridgeEnabled {
+ if ctx.Target().NativeBridge == android.NativeBridgeEnabled {
+ dir = filepath.Join(dir, ctx.Target().NativeBridgeRelativePath)
+ }
+ if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
dir = filepath.Join(dir, ctx.Arch().ArchType.String())
}
return android.PathForModuleInstall(ctx, dir, compiler.subDir,
diff --git a/rust/library.go b/rust/library.go
index 0cf2dd0..bf863bb 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -318,6 +318,8 @@
if ctx.toolchain().Bionic() && (library.dylib() || library.shared()) {
deps = library.baseCompiler.bionicDeps(ctx, deps)
+ deps.CrtBegin = "crtbegin_so"
+ deps.CrtEnd = "crtend_so"
}
return deps
diff --git a/scripts/build-aml-prebuilts.sh b/scripts/build-aml-prebuilts.sh
index 7e3a82c..35a6ff3 100755
--- a/scripts/build-aml-prebuilts.sh
+++ b/scripts/build-aml-prebuilts.sh
@@ -58,6 +58,7 @@
"DeviceName": "generic_arm64",
"HostArch": "x86_64",
+ "HostSecondaryArch": "x86",
"Aml_abis": true,
"UseGoma": ${USE_GOMA}
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index eb64bcc..780da9f 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -32,6 +32,7 @@
"arm64/include/Arm64Test.h": nil,
"libfoo.so": nil,
"aidl/foo/bar/Test.aidl": nil,
+ "some/where/stubslib.map.txt": nil,
}
return testSdkWithFs(t, bp, fs)
}
@@ -1739,3 +1740,63 @@
}
`))
}
+
+func TestStubsLibrary(t *testing.T) {
+ result := testSdkWithCc(t, `
+ sdk {
+ name: "mysdk",
+ native_shared_libs: ["stubslib"],
+ }
+
+ cc_library {
+ name: "stubslib",
+ stubs: {
+ symbol_file: "some/where/stubslib.map.txt",
+ versions: ["1", "2", "3"],
+ },
+ }
+ `)
+
+ result.CheckSnapshot("mysdk", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_library_shared {
+ name: "mysdk_stubslib@current",
+ sdk_member_name: "stubslib",
+ installable: false,
+ stubs: {
+ versions: ["3"],
+ },
+ arch: {
+ arm64: {
+ srcs: ["arm64/lib/stubslib.so"],
+ },
+ arm: {
+ srcs: ["arm/lib/stubslib.so"],
+ },
+ },
+}
+
+cc_prebuilt_library_shared {
+ name: "stubslib",
+ prefer: false,
+ stubs: {
+ versions: ["3"],
+ },
+ arch: {
+ arm64: {
+ srcs: ["arm64/lib/stubslib.so"],
+ },
+ arm: {
+ srcs: ["arm/lib/stubslib.so"],
+ },
+ },
+}
+
+sdk_snapshot {
+ name: "mysdk@current",
+ native_shared_libs: ["mysdk_stubslib@current"],
+}
+`))
+}
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index cbffb50..4a2c053 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -53,30 +53,18 @@
system_modules: "none",
sdk_version: "none",
host_supported: true,
- apex_available: [
- "//apex_available:platform",
- "//apex_available:anyapex",
- ],
}
java_import {
name: "sdkmember_mysdk_1",
sdk_member_name: "sdkmember",
host_supported: true,
- apex_available: [
- "//apex_available:platform",
- "//apex_available:anyapex",
- ],
}
java_import {
name: "sdkmember_mysdk_2",
sdk_member_name: "sdkmember",
host_supported: true,
- apex_available: [
- "//apex_available:platform",
- "//apex_available:anyapex",
- ],
}
java_library {
diff --git a/sdk/sdk.go b/sdk/sdk.go
index dabdf85..cb5a605 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -312,7 +312,7 @@
ctx.BottomUp("SdkMemberInterVersion", memberInterVersionMutator).Parallel()
}
-// RegisterPostDepshMutators registers post-deps mutators to support modules implementing SdkAware
+// RegisterPostDepsMutators registers post-deps mutators to support modules implementing SdkAware
// interface and the sdk module type. This function has been made public to be called by tests
// outside of the sdk package
func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
@@ -431,23 +431,31 @@
}
}
-// Step 6: ensure that the dependencies from outside of the APEX are all from the required SDKs
+// Step 6: ensure that the dependencies outside of the APEX are all from the required SDKs
func sdkRequirementsMutator(mctx android.TopDownMutatorContext) {
if m, ok := mctx.Module().(interface {
- DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool
- RequiredSdks() android.SdkRefs
+ android.DepIsInSameApex
+ android.RequiredSdks
}); ok {
requiredSdks := m.RequiredSdks()
if len(requiredSdks) == 0 {
return
}
mctx.VisitDirectDeps(func(dep android.Module) {
- if mctx.OtherModuleDependencyTag(dep) == android.DefaultsDepTag {
+ tag := mctx.OtherModuleDependencyTag(dep)
+ if tag == android.DefaultsDepTag {
// dependency to defaults is always okay
return
}
- // If the dep is from outside of the APEX, but is not in any of the
+ // Ignore the dependency from the unversioned member to any versioned members as an
+ // apex that depends on the unversioned member will not also be depending on a versioned
+ // member.
+ if _, ok := tag.(sdkMemberVersionedDepTag); ok {
+ return
+ }
+
+ // If the dep is outside of the APEX, but is not in any of the
// required SDKs, we know that the dep is a violation.
if sa, ok := dep.(android.SdkAware); ok {
if !m.DepIsInSameApex(mctx, dep) && !requiredSdks.Contains(sa.ContainingSdk()) {
diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go
index 2de772b..4c3bac3 100644
--- a/ui/build/sandbox_linux.go
+++ b/ui/build/sandbox_linux.go
@@ -54,6 +54,9 @@
working bool
group string
+ srcDir string
+ outDir string
+ distDir string
}
func (c *Cmd) sandboxSupported() bool {
@@ -72,15 +75,34 @@
sandboxConfig.group = "nobody"
}
- cmd := exec.CommandContext(c.ctx.Context, nsjailPath,
+ sandboxConfig.srcDir = absPath(c.ctx, ".")
+ sandboxConfig.outDir = absPath(c.ctx, c.config.OutDir())
+ sandboxConfig.distDir = absPath(c.ctx, c.config.DistDir())
+
+ sandboxArgs := []string{
"-H", "android-build",
"-e",
"-u", "nobody",
"-g", sandboxConfig.group,
- "-B", "/",
+ "-R", "/",
+ "-B", sandboxConfig.srcDir,
+ "-B", "/tmp",
+ "-B", sandboxConfig.outDir,
+ }
+
+ if _, err := os.Stat(sandboxConfig.distDir); !os.IsNotExist(err) {
+ //Mount dist dir as read-write if it already exists
+ sandboxArgs = append(sandboxArgs, "-B",
+ sandboxConfig.distDir)
+ }
+
+ sandboxArgs = append(sandboxArgs,
"--disable_clone_newcgroup",
"--",
"/bin/bash", "-c", `if [ $(hostname) == "android-build" ]; then echo "Android" "Success"; else echo Failure; fi`)
+
+ cmd := exec.CommandContext(c.ctx.Context, nsjailPath, sandboxArgs...)
+
cmd.Env = c.config.Environment().Environ()
c.ctx.Verboseln(cmd.Args)
@@ -144,8 +166,17 @@
"--rlimit_fsize", "soft",
"--rlimit_nofile", "soft",
- // For now, just map everything. Eventually we should limit this, especially to make most things readonly.
- "-B", "/",
+ // For now, just map everything. Make most things readonly.
+ "-R", "/",
+
+ // Mount source are read-write
+ "-B", sandboxConfig.srcDir,
+
+ //Mount out dir as read-write
+ "-B", sandboxConfig.outDir,
+
+ // Mount a writable tmp dir
+ "-B", "/tmp",
// Disable newcgroup for now, since it may require newer kernels
// TODO: try out cgroups
@@ -155,6 +186,11 @@
"-q",
}
+ if _, err := os.Stat(sandboxConfig.distDir); !os.IsNotExist(err) {
+ //Mount dist dir as read-write if it already exists
+ sandboxArgs = append(sandboxArgs, "-B", sandboxConfig.distDir)
+ }
+
if c.Sandbox.AllowBuildBrokenUsesNetwork && c.config.BuildBrokenUsesNetwork() {
c.ctx.Printf("AllowBuildBrokenUsesNetwork: %v", c.Sandbox.AllowBuildBrokenUsesNetwork)
c.ctx.Printf("BuildBrokenUsesNetwork: %v", c.config.BuildBrokenUsesNetwork())