Merge "Fix missing NOTICE targets for static libs that aren't available to platform."
diff --git a/Android.bp b/Android.bp
index 9c2bb43..fe776df 100644
--- a/Android.bp
+++ b/Android.bp
@@ -186,6 +186,7 @@
"cc/rs.go",
"cc/sanitize.go",
"cc/sabi.go",
+ "cc/sdk.go",
"cc/snapshot_utils.go",
"cc/stl.go",
"cc/strip.go",
diff --git a/OWNERS b/OWNERS
index 4ae045d..e1db459 100644
--- a/OWNERS
+++ b/OWNERS
@@ -4,3 +4,4 @@
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
diff --git a/README.md b/README.md
index b1bb425..8b028a8 100644
--- a/README.md
+++ b/README.md
@@ -419,7 +419,9 @@
name: "acme_cc_defaults",
module_type: "cc_defaults",
config_namespace: "acme",
- variables: ["board", "feature"],
+ variables: ["board"],
+ bool_variables: ["feature"],
+ value_variables: ["width"],
properties: ["cflags", "srcs"],
}
@@ -427,15 +429,12 @@
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
-`cc_defaults` module type, with two additional conditionals based on variables
-`board` and `feature`, which can affect properties `cflags` and `srcs`.
+`cc_defaults` module type, with three additional conditionals based on
+variables `board`, `feature` and `width`, which can affect properties `cflags`
+and `srcs`.
The values of the variables can be set from a product's `BoardConfig.mk` file:
```
@@ -446,6 +445,7 @@
SOONG_CONFIG_acme_board := soc_a
SOONG_CONFIG_acme_feature := true
+SOONG_CONFIG_acme_width := 200
```
The `acme_cc_defaults` module type can be used anywhere after the definition in
@@ -474,6 +474,9 @@
feature: {
cflags: ["-DFEATURE"],
},
+ width: {
+ cflags: ["-DWIDTH=%s"],
+ },
},
}
@@ -485,7 +488,7 @@
```
With the `BoardConfig.mk` snippet above, libacme_foo would build with
-cflags "-DGENERIC -DSOC_A -DFEATURE".
+cflags "-DGENERIC -DSOC_A -DFEATURE -DWIDTH=200".
`soong_config_module_type` modules will work best when used to wrap defaults
modules (`cc_defaults`, `java_defaults`, etc.), which can then be referenced
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/api_levels.go b/android/api_levels.go
index 4f6efee..4b7a8fd 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -73,7 +73,7 @@
"P": 28,
"Q": 29,
}
- for i, codename := range config.PlatformVersionCombinedCodenames() {
+ for i, codename := range config.PlatformVersionActiveCodenames() {
apiLevelsMap[codename] = baseApiLevel + i
}
diff --git a/android/config.go b/android/config.go
index 558c828..c297b05 100644
--- a/android/config.go
+++ b/android/config.go
@@ -652,22 +652,6 @@
return c.productVariables.Platform_version_active_codenames
}
-// Codenames that are available in the branch but not included in the current
-// lunch target.
-func (c *config) PlatformVersionFutureCodenames() []string {
- return c.productVariables.Platform_version_future_codenames
-}
-
-// All possible codenames in the current branch. NB: Not named AllCodenames
-// because "all" has historically meant "active" in make, and still does in
-// build.prop.
-func (c *config) PlatformVersionCombinedCodenames() []string {
- combined := []string{}
- combined = append(combined, c.PlatformVersionActiveCodenames()...)
- combined = append(combined, c.PlatformVersionFutureCodenames()...)
- return combined
-}
-
func (c *config) ProductAAPTConfig() []string {
return c.productVariables.AAPTConfig
}
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/neverallow.go b/android/neverallow.go
index 8fcfb8a..04ec27d 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -17,6 +17,7 @@
import (
"path/filepath"
"reflect"
+ "regexp"
"strconv"
"strings"
@@ -53,6 +54,7 @@
AddNeverAllowRules(createLibcoreRules()...)
AddNeverAllowRules(createMediaRules()...)
AddNeverAllowRules(createJavaDeviceForHostRules()...)
+ AddNeverAllowRules(createCcSdkVariantRules()...)
}
// Add a NeverAllow rule to the set of rules to apply.
@@ -146,7 +148,8 @@
rules := []Rule{
NeverAllow().
NotIn(coreLibraryProjects...).
- With("sdk_version", "none"),
+ With("sdk_version", "none").
+ WithoutMatcher("name", Regexp("^android_.*stubs_current$")),
}
return rules
@@ -175,6 +178,37 @@
}
}
+func createCcSdkVariantRules() []Rule {
+ sdkVersionOnlyWhitelist := []string{
+ // derive_sdk_prefer32 has stem: "derive_sdk" which conflicts with the derive_sdk.
+ // This sometimes works because the APEX modules that contain derive_sdk and
+ // derive_sdk_prefer32 suppress the platform installation rules, but fails when
+ // the APEX modules contain the SDK variant and the platform variant still exists.
+ "frameworks/base/apex/sdkextensions/derive_sdk",
+ }
+
+ platformVariantPropertiesWhitelist := []string{
+ // android_native_app_glue and libRSSupport use native_window.h but target old
+ // sdk versions (minimum and 9 respectively) where libnativewindow didn't exist,
+ // so they can't add libnativewindow to shared_libs to get the header directory
+ // for the platform variant. Allow them to use the platform variant
+ // property to set shared_libs.
+ "prebuilts/ndk",
+ "frameworks/rs",
+ }
+
+ return []Rule{
+ NeverAllow().
+ NotIn(sdkVersionOnlyWhitelist...).
+ WithMatcher("sdk_variant_only", isSetMatcherInstance).
+ Because("sdk_variant_only can only be used in whitelisted projects"),
+ NeverAllow().
+ NotIn(platformVariantPropertiesWhitelist...).
+ WithMatcher("platform.shared_libs", isSetMatcherInstance).
+ Because("platform variant properties can only be used in whitelisted projects"),
+ }
+}
+
func neverallowMutator(ctx BottomUpMutatorContext) {
m, ok := ctx.Module().(Module)
if !ok {
@@ -254,6 +288,30 @@
return ".starts-with(" + m.prefix + ")"
}
+type regexMatcher struct {
+ re *regexp.Regexp
+}
+
+func (m *regexMatcher) test(value string) bool {
+ return m.re.MatchString(value)
+}
+
+func (m *regexMatcher) String() string {
+ return ".regexp(" + m.re.String() + ")"
+}
+
+type isSetMatcher struct{}
+
+func (m *isSetMatcher) test(value string) bool {
+ return value != ""
+}
+
+func (m *isSetMatcher) String() string {
+ return ".is-set"
+}
+
+var isSetMatcherInstance = &isSetMatcher{}
+
type ruleProperty struct {
fields []string // e.x.: Vndk.Enabled
matcher ValueMatcher
@@ -457,6 +515,14 @@
return &startsWithMatcher{prefix}
}
+func Regexp(re string) ValueMatcher {
+ r, err := regexp.Compile(re)
+ if err != nil {
+ panic(err)
+ }
+ return ®exMatcher{r}
+}
+
// assorted utils
func cleanPaths(paths []string) []string {
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 6f07a4a..0373b79 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -227,6 +227,16 @@
},
},
{
+ name: "sdk_version: \"none\" on android_*stubs_current stub",
+ fs: map[string][]byte{
+ "frameworks/base/Android.bp": []byte(`
+ java_library {
+ name: "android_stubs_current",
+ sdk_version: "none",
+ }`),
+ },
+ },
+ {
name: "sdk_version: \"none\" outside core libraries",
fs: map[string][]byte{
"Android.bp": []byte(`
@@ -249,6 +259,50 @@
}`),
},
},
+ // CC sdk rule tests
+ {
+ name: `"sdk_variant_only" outside whitelist`,
+ fs: map[string][]byte{
+ "Android.bp": []byte(`
+ cc_library {
+ name: "outside_whitelist",
+ sdk_version: "current",
+ sdk_variant_only: true,
+ }`),
+ },
+ expectedErrors: []string{
+ `module "outside_whitelist": violates neverallow`,
+ },
+ },
+ {
+ name: `"sdk_variant_only: false" outside whitelist`,
+ fs: map[string][]byte{
+ "Android.bp": []byte(`
+ cc_library {
+ name: "outside_whitelist",
+ sdk_version: "current",
+ sdk_variant_only: false,
+ }`),
+ },
+ expectedErrors: []string{
+ `module "outside_whitelist": violates neverallow`,
+ },
+ },
+ {
+ name: `"platform" outside whitelist`,
+ fs: map[string][]byte{
+ "Android.bp": []byte(`
+ cc_library {
+ name: "outside_whitelist",
+ platform: {
+ shared_libs: ["libfoo"],
+ },
+ }`),
+ },
+ expectedErrors: []string{
+ `module "outside_whitelist": violates neverallow`,
+ },
+ },
}
func TestNeverallow(t *testing.T) {
@@ -289,6 +343,8 @@
Include_dirs []string
Vendor_available *bool
Static_libs []string
+ Sdk_version *string
+ Sdk_variant_only *bool
Vndk struct {
Enabled *bool
@@ -305,6 +361,10 @@
Cflags []string
}
}
+
+ Platform struct {
+ Shared_libs []string
+ }
}
type mockCcLibraryModule struct {
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 198108d..619cf86 100644
--- a/android/soong_config_modules.go
+++ b/android/soong_config_modules.go
@@ -73,6 +73,9 @@
// feature: {
// cflags: ["-DFEATURE"],
// },
+// width: {
+// cflags: ["-DWIDTH=%s"],
+// },
// },
// }
//
@@ -88,7 +91,9 @@
// name: "acme_cc_defaults",
// module_type: "cc_defaults",
// config_namespace: "acme",
-// variables: ["board", "feature"],
+// variables: ["board"],
+// bool_variables: ["feature"],
+// value_variables: ["width"],
// properties: ["cflags", "srcs"],
// }
//
@@ -97,10 +102,6 @@
// values: ["soc_a", "soc_b"],
// }
//
-// soong_config_bool_variable {
-// name: "feature",
-// }
-//
// If an acme BoardConfig.mk file contained:
//
// SOONG_CONFIG_NAMESPACES += acme
@@ -110,8 +111,9 @@
//
// SOONG_CONFIG_acme_board := soc_a
// SOONG_CONFIG_acme_feature := true
+// SOONG_CONFIG_acme_width := 200
//
-// Then libacme_foo would build with cflags "-DGENERIC -DSOC_A -DFEATURE".
+// Then libacme_foo would build with cflags "-DGENERIC -DSOC_A -DFEATURE -DWIDTH=200".
func soongConfigModuleTypeImportFactory() Module {
module := &soongConfigModuleTypeImport{}
@@ -125,7 +127,10 @@
}
func (m *soongConfigModuleTypeImport) Name() string {
- return "soong_config_module_type_import_" + soongconfig.CanonicalizeToProperty(m.properties.From)
+ // The generated name is non-deterministic, but it does not
+ // matter because this module does not emit any rules.
+ return soongconfig.CanonicalizeToProperty(m.properties.From) +
+ "soong_config_module_type_import_" + fmt.Sprintf("%p", m)
}
func (*soongConfigModuleTypeImport) Nameless() {}
@@ -149,7 +154,9 @@
// name: "acme_cc_defaults",
// module_type: "cc_defaults",
// config_namespace: "acme",
-// variables: ["board", "feature"],
+// variables: ["board"],
+// bool_variables: ["feature"],
+// value_variables: ["width"],
// properties: ["cflags", "srcs"],
// }
//
@@ -158,10 +165,6 @@
// values: ["soc_a", "soc_b"],
// }
//
-// soong_config_bool_variable {
-// name: "feature",
-// }
-//
// acme_cc_defaults {
// name: "acme_defaults",
// cflags: ["-DGENERIC"],
@@ -177,6 +180,9 @@
// feature: {
// cflags: ["-DFEATURE"],
// },
+// width: {
+// cflags: ["-DWIDTH=%s"],
+// },
// },
// }
//
@@ -195,6 +201,7 @@
//
// SOONG_CONFIG_acme_board := soc_a
// SOONG_CONFIG_acme_feature := true
+// SOONG_CONFIG_acme_width := 200
//
// Then libacme_foo would build with cflags "-DGENERIC -DSOC_A -DFEATURE".
func soongConfigModuleTypeFactory() Module {
@@ -355,7 +362,12 @@
AddLoadHook(module, func(ctx LoadHookContext) {
config := ctx.Config().VendorConfig(moduleType.ConfigNamespace)
- for _, ps := range soongconfig.PropertiesToApply(moduleType, conditionalProps, config) {
+ newProps, err := soongconfig.PropertiesToApply(moduleType, conditionalProps, config)
+ if err != nil {
+ ctx.ModuleErrorf("%s", err)
+ return
+ }
+ for _, ps := range newProps {
ctx.AppendProperties(ps)
}
})
diff --git a/android/soong_config_modules_test.go b/android/soong_config_modules_test.go
index 6ad88a2..f905b1a 100644
--- a/android/soong_config_modules_test.go
+++ b/android/soong_config_modules_test.go
@@ -43,7 +43,9 @@
name: "acme_test_defaults",
module_type: "test_defaults",
config_namespace: "acme",
- variables: ["board", "feature1", "feature2", "FEATURE3"],
+ variables: ["board", "feature1", "FEATURE3"],
+ bool_variables: ["feature2"],
+ value_variables: ["size"],
properties: ["cflags", "srcs"],
}
@@ -57,10 +59,6 @@
}
soong_config_bool_variable {
- name: "feature2",
- }
-
- soong_config_bool_variable {
name: "FEATURE3",
}
`
@@ -85,6 +83,9 @@
cflags: ["-DSOC_B"],
},
},
+ size: {
+ cflags: ["-DSIZE=%s"],
+ },
feature1: {
cflags: ["-DFEATURE1"],
},
@@ -104,6 +105,7 @@
config.TestProductVariables.VendorVars = map[string]map[string]string{
"acme": map[string]string{
"board": "soc_a",
+ "size": "42",
"feature1": "true",
"feature2": "false",
// FEATURE3 unset
@@ -124,7 +126,7 @@
FailIfErrored(t, errs)
foo := ctx.ModuleForTests("foo", "").Module().(*soongConfigTestModule)
- if g, w := foo.props.Cflags, []string{"-DGENERIC", "-DSOC_A", "-DFEATURE1"}; !reflect.DeepEqual(g, w) {
+ if g, w := foo.props.Cflags, []string{"-DGENERIC", "-DSIZE=42", "-DSOC_A", "-DFEATURE1"}; !reflect.DeepEqual(g, w) {
t.Errorf("wanted foo cflags %q, got %q", w, g)
}
}
diff --git a/android/soongconfig/modules.go b/android/soongconfig/modules.go
index aa4f5c5..142a813 100644
--- a/android/soongconfig/modules.go
+++ b/android/soongconfig/modules.go
@@ -109,6 +109,13 @@
// 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 SOONG_CONFIG variables that this module type will read. The value will be
+ // inserted into the properties with %s substitution.
+ Value_variables []string
+
// the list of properties that this module type will extend.
Properties []string
}
@@ -146,6 +153,30 @@
}
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,
+ },
+ })
+ }
+
+ for _, name := range props.Value_variables {
+ if name == "" {
+ return []error{fmt.Errorf("value_variables entry must not be blank")}
+ }
+
+ mt.Variables = append(mt.Variables, &valueVariable{
+ baseVariable: baseVariable{
+ variable: name,
+ },
+ })
+ }
+
return nil
}
@@ -389,15 +420,17 @@
// PropertiesToApply returns the applicable properties from a ModuleType that should be applied
// based on SoongConfig values.
-func PropertiesToApply(moduleType *ModuleType, props reflect.Value, config SoongConfig) []interface{} {
+func PropertiesToApply(moduleType *ModuleType, props reflect.Value, config SoongConfig) ([]interface{}, error) {
var ret []interface{}
props = props.Elem().FieldByName(soongConfigProperty)
for i, c := range moduleType.Variables {
- if ps := c.PropertiesToApply(config, props.Field(i)); ps != nil {
+ if ps, err := c.PropertiesToApply(config, props.Field(i)); err != nil {
+ return nil, err
+ } else if ps != nil {
ret = append(ret, ps)
}
}
- return ret
+ return ret, nil
}
type ModuleType struct {
@@ -423,7 +456,7 @@
// PropertiesToApply should return one of the interface{} values set by initializeProperties to be applied
// to the module.
- PropertiesToApply(config SoongConfig, values reflect.Value) interface{}
+ PropertiesToApply(config SoongConfig, values reflect.Value) (interface{}, error)
}
type baseVariable struct {
@@ -458,14 +491,14 @@
}
}
-func (s *stringVariable) PropertiesToApply(config SoongConfig, values reflect.Value) interface{} {
+func (s *stringVariable) PropertiesToApply(config SoongConfig, values reflect.Value) (interface{}, error) {
for j, v := range s.values {
if config.String(s.variable) == v {
- return values.Field(j).Interface()
+ return values.Field(j).Interface(), nil
}
}
- return nil
+ return nil, nil
}
type boolVariable struct {
@@ -480,11 +513,83 @@
v.Set(reflect.Zero(typ))
}
-func (b boolVariable) PropertiesToApply(config SoongConfig, values reflect.Value) interface{} {
+func (b boolVariable) PropertiesToApply(config SoongConfig, values reflect.Value) (interface{}, error) {
if config.Bool(b.variable) {
- return values.Interface()
+ return values.Interface(), nil
}
+ return nil, nil
+}
+
+type valueVariable struct {
+ baseVariable
+}
+
+func (s *valueVariable) variableValuesType() reflect.Type {
+ return emptyInterfaceType
+}
+
+func (s *valueVariable) initializeProperties(v reflect.Value, typ reflect.Type) {
+ v.Set(reflect.Zero(typ))
+}
+
+func (s *valueVariable) PropertiesToApply(config SoongConfig, values reflect.Value) (interface{}, error) {
+ if !config.IsSet(s.variable) {
+ return nil, nil
+ }
+ configValue := config.String(s.variable)
+
+ propStruct := values.Elem().Elem()
+ for i := 0; i < propStruct.NumField(); i++ {
+ field := propStruct.Field(i)
+ kind := field.Kind()
+ if kind == reflect.Ptr {
+ if field.IsNil() {
+ continue
+ }
+ field = field.Elem()
+ }
+ switch kind {
+ case reflect.String:
+ err := printfIntoProperty(field, configValue)
+ if err != nil {
+ return nil, fmt.Errorf("soong_config_variables.%s.%s: %s", s.variable, propStruct.Type().Field(i).Name, err)
+ }
+ case reflect.Slice:
+ for j := 0; j < field.Len(); j++ {
+ err := printfIntoProperty(field.Index(j), configValue)
+ if err != nil {
+ return nil, fmt.Errorf("soong_config_variables.%s.%s: %s", s.variable, propStruct.Type().Field(i).Name, err)
+ }
+ }
+ case reflect.Bool:
+ // Nothing to do
+ default:
+ return nil, fmt.Errorf("soong_config_variables.%s.%s: unsupported property type %q", s.variable, propStruct.Type().Field(i).Name, kind)
+ }
+ }
+
+ return values.Interface(), nil
+}
+
+func printfIntoProperty(propertyValue reflect.Value, configValue string) error {
+ s := propertyValue.String()
+
+ count := strings.Count(s, "%")
+ if count == 0 {
+ return nil
+ }
+
+ if count > 1 {
+ return fmt.Errorf("value variable properties only support a single '%%'")
+ }
+
+ if !strings.Contains(s, "%s") {
+ return fmt.Errorf("unsupported %% in value variable property")
+ }
+
+ propertyValue.Set(reflect.ValueOf(fmt.Sprintf(s, configValue)))
+
return nil
}
diff --git a/android/variable.go b/android/variable.go
index 8357d2f..3b3916e 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -95,6 +95,9 @@
Sanitize struct {
Address *bool
}
+ Optimize struct {
+ Enabled *bool
+ }
}
Pdk struct {
@@ -148,7 +151,6 @@
Platform_sdk_codename *string `json:",omitempty"`
Platform_sdk_final *bool `json:",omitempty"`
Platform_version_active_codenames []string `json:",omitempty"`
- Platform_version_future_codenames []string `json:",omitempty"`
Platform_vndk_version *string `json:",omitempty"`
Platform_systemsdk_versions []string `json:",omitempty"`
Platform_security_patch *string `json:",omitempty"`
@@ -252,7 +254,7 @@
ClangTidy *bool `json:",omitempty"`
TidyChecks *string `json:",omitempty"`
- SamplingPGO *bool `json:",omitempty"`
+ SamplingPGO *bool `json:",omitempty"`
NativeLineCoverage *bool `json:",omitempty"`
Native_coverage *bool `json:",omitempty"`
@@ -355,7 +357,6 @@
Platform_sdk_codename: stringPtr("Q"),
Platform_sdk_final: boolPtr(false),
Platform_version_active_codenames: []string{"Q"},
- Platform_version_future_codenames: []string{"Q"},
Platform_vndk_version: stringPtr("Q"),
HostArch: stringPtr("x86_64"),
diff --git a/android/vts_config.go b/android/vts_config.go
index 9a1df7c..77fb9fe 100644
--- a/android/vts_config.go
+++ b/android/vts_config.go
@@ -53,7 +53,7 @@
fmt.Fprintf(w, "LOCAL_TEST_CONFIG := %s\n",
*me.properties.Test_config)
}
- fmt.Fprintf(w, "LOCAL_COMPATIBILITY_SUITE := vts %s\n",
+ fmt.Fprintf(w, "LOCAL_COMPATIBILITY_SUITE := vts10 %s\n",
strings.Join(me.properties.Test_suites, " "))
},
}
@@ -64,7 +64,7 @@
me.AddProperties(&me.properties)
}
-// vts_config generates a Vendor Test Suite (VTS) configuration file from the
+// 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{}
diff --git a/apex/apex.go b/apex/apex.go
index bc992f0..fd3fb2b 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -18,6 +18,7 @@
"fmt"
"path"
"path/filepath"
+ "regexp"
"sort"
"strconv"
"strings"
@@ -94,27 +95,9 @@
// Module separator
//
m["com.android.adbd"] = []string{
- "adbd",
- "bcm_object",
- "fmtlib",
- "libadbconnection_server",
- "libadbd",
"libadbd_auth",
- "libadbd_core",
- "libadbd_services",
- "libasyncio",
- "libbacktrace_headers",
- "libbase",
- "libbase_headers",
"libbuildversion",
- "libc++",
"libcap",
- "libcrypto",
- "libcrypto_utils",
- "libcutils",
- "libcutils_headers",
- "libdiagnose_usb",
- "liblog_headers",
"libmdnssd",
"libminijail",
"libminijail_gen_constants",
@@ -125,9 +108,6 @@
"libpackagelistparser",
"libpcre2",
"libprocessgroup_headers",
- "libqemu_pipe",
- "libsystem_headers",
- "libutils_headers",
}
//
// Module separator
@@ -136,7 +116,6 @@
"art_cmdlineparser_headers",
"art_disassembler_headers",
"art_libartbase_headers",
- "bcm_object",
"bionic_libc_platform_headers",
"core-repackaged-icu4j",
"cpp-define-generator-asm-support",
@@ -145,12 +124,9 @@
"crtbegin_dynamic1",
"crtbegin_so1",
"crtbrand",
- "conscrypt.module.intra.core.api.stubs",
"dex2oat_headers",
"dt_fd_forward_export",
- "fmtlib",
"icu4c_extra_headers",
- "jacocoagent",
"javavm_headers",
"jni_platform_headers",
"libPlatformProperties",
@@ -160,15 +136,6 @@
"libart_runtime_headers_ndk",
"libartd-disassembler",
"libasync_safe",
- "libbacktrace",
- "libbase",
- "libbase_headers",
- "libc++",
- "libc++_static",
- "libc++abi",
- "libc++demangle",
- "libc_headers",
- "libcrypto",
"libdexfile_all_headers",
"libdexfile_external_headers",
"libdexfile_support",
@@ -181,7 +148,6 @@
"libicuuc_headers",
"libicuuc_stubdata",
"libjdwp_headers",
- "liblog_headers",
"liblz4",
"liblzma",
"libmeminfo",
@@ -192,7 +158,6 @@
"libopenjdkjvmti_headers",
"libperfetto_client_experimental",
"libprocinfo",
- "libprotobuf-cpp-lite",
"libunwind_llvm",
"libunwindstack",
"libv8",
@@ -229,13 +194,10 @@
"android.hidl.token@1.0-utils",
"avrcp-target-service",
"avrcp_headers",
- "bcm_object",
"bluetooth-protos-lite",
"bluetooth.mapsapi",
"com.android.vcard",
"dnsresolver_aidl_interface-V2-java",
- "fmtlib",
- "guava",
"ipmemorystore-aidl-interfaces-V5-java",
"ipmemorystore-aidl-interfaces-java",
"internal_include_headers",
@@ -245,9 +207,6 @@
"libFraunhoferAAC",
"libaudio-a2dp-hw-utils",
"libaudio-hearing-aid-hw-utils",
- "libbacktrace_headers",
- "libbase",
- "libbase_headers",
"libbinder_headers",
"libbluetooth",
"libbluetooth-types",
@@ -269,38 +228,23 @@
"libbtdevice",
"libbte",
"libbtif",
- "libc++",
"libchrome",
- "libcrypto",
- "libcutils",
- "libcutils_headers",
"libevent",
"libfmq",
"libg722codec",
"libgtest_prod",
"libgui_headers",
- "libhidlbase",
- "libhidlbase-impl-internal",
- "libhidltransport-impl-internal",
- "libhwbinder-impl-internal",
- "libjsoncpp",
- "liblog_headers",
"libmedia_headers",
"libmodpb64",
"libosi",
"libprocessgroup",
"libprocessgroup_headers",
- "libprotobuf-cpp-lite",
- "libprotobuf-java-lite",
- "libprotobuf-java-micro",
"libstagefright_foundation_headers",
"libstagefright_headers",
"libstatslog",
"libstatssocket",
- "libsystem_headers",
"libtinyxml2",
"libudrv-uipc",
- "libutils_headers",
"libz",
"media_plugin_headers",
"net-utils-services-common",
@@ -320,12 +264,8 @@
// Module separator
//
m["com.android.conscrypt"] = []string{
- "bcm_object",
"boringssl_self_test",
- "libc++",
- "libcrypto",
"libnativehelper_header_only",
- "libssl",
"unsupportedappusage",
}
//
@@ -365,44 +305,13 @@
"android.hidl.memory.token@1.0",
"android.hidl.memory@1.0",
"android.hidl.safe_union@1.0",
- "bcm_object",
- "fmtlib",
- "gemmlowp_headers",
"libarect",
- "libbacktrace_headers",
- "libbase",
- "libbase_headers",
"libbuildversion",
- "libc++",
- "libcrypto",
- "libcrypto_static",
- "libcutils",
- "libcutils_headers",
- "libeigen",
- "libfmq",
- "libhidlbase",
- "libhidlbase-impl-internal",
- "libhidlmemory",
- "libhidltransport-impl-internal",
- "libhwbinder-impl-internal",
- "libjsoncpp",
- "liblog_headers",
"libmath",
- "libneuralnetworks_common",
- "libneuralnetworks_headers",
"libprocessgroup",
"libprocessgroup_headers",
"libprocpartition",
"libsync",
- "libsystem_headers",
- "libtextclassifier_hash",
- "libtextclassifier_hash_headers",
- "libtextclassifier_hash_static",
- "libtflite_kernel_utils",
- "libutils_headers",
- "philox_random",
- "philox_random_headers",
- "tensorflow_headers",
}
//
// Module separator
@@ -431,9 +340,7 @@
"android.hidl.memory@1.0",
"android.hidl.token@1.0",
"android.hidl.token@1.0-utils",
- "bcm_object",
"bionic_libc_platform_headers",
- "fmtlib",
"gl_headers",
"libEGL",
"libEGL_blobCache",
@@ -455,23 +362,14 @@
"libaudiopolicy",
"libaudioutils",
"libaudioutils_fixedfft",
- "libbacktrace",
- "libbacktrace_headers",
- "libbase",
- "libbase_headers",
"libbinder_headers",
"libbluetooth-types-header",
"libbufferhub",
"libbufferhub_headers",
"libbufferhubqueue",
- "libc++",
- "libc_headers",
"libc_malloc_debug_backtrace",
"libcamera_client",
"libcamera_metadata",
- "libcrypto",
- "libcutils",
- "libcutils_headers",
"libdexfile_external_headers",
"libdexfile_support",
"libdvr_headers",
@@ -483,14 +381,7 @@
"libgui",
"libgui_headers",
"libhardware_headers",
- "libhidlbase",
- "libhidlbase-impl-internal",
- "libhidlmemory",
- "libhidltransport-impl-internal",
- "libhwbinder-impl-internal",
"libinput",
- "libjsoncpp",
- "liblog_headers",
"liblzma",
"libmath",
"libmedia",
@@ -538,11 +429,9 @@
"libstagefright_mpeg2extractor",
"libstagefright_mpeg2support",
"libsync",
- "libsystem_headers",
"libui",
"libui_headers",
"libunwindstack",
- "libutils_headers",
"libvibrator",
"libvorbisidec",
"libwavextractor",
@@ -582,7 +471,6 @@
"android.hidl.safe_union@1.0",
"android.hidl.token@1.0",
"android.hidl.token@1.0-utils",
- "fmtlib",
"libEGL",
"libFLAC",
"libFLAC-config",
@@ -599,15 +487,10 @@
"libavcenc",
"libavservices_minijail",
"libavservices_minijail",
- "libbacktrace",
- "libbacktrace_headers",
- "libbase",
- "libbase_headers",
"libbinder_headers",
"libbinderthreadstateutils",
"libbluetooth-types-header",
"libbufferhub_headers",
- "libc++",
"libc_scudo",
"libcap",
"libcodec2",
@@ -647,8 +530,6 @@
"libcodec2_soft_vp9dec",
"libcodec2_soft_vp9enc",
"libcodec2_vndk",
- "libcutils",
- "libcutils_headers",
"libdexfile_support",
"libdvr_headers",
"libfmq",
@@ -664,15 +545,8 @@
"libhardware_headers",
"libhevcdec",
"libhevcenc",
- "libhidlbase",
- "libhidlbase-impl-internal",
- "libhidlmemory",
- "libhidltransport-impl-internal",
- "libhwbinder-impl-internal",
"libion",
"libjpeg",
- "libjsoncpp",
- "liblog_headers",
"liblzma",
"libmath",
"libmedia_codecserviceregistrant",
@@ -710,11 +584,9 @@
"libstagefright_m4vh263enc",
"libstagefright_mp3dec",
"libsync",
- "libsystem_headers",
"libui",
"libui_headers",
"libunwindstack",
- "libutils_headers",
"libvorbisidec",
"libvpx",
"libyuv",
@@ -730,7 +602,6 @@
"MediaProvider",
"MediaProviderGoogle",
"fmtlib_ndk",
- "guava",
"libbase_ndk",
"libfuse",
"libfuse_jni",
@@ -754,7 +625,6 @@
"kotlinx-coroutines-android-nodeps",
"kotlinx-coroutines-core",
"kotlinx-coroutines-core-nodeps",
- "libprotobuf-java-lite",
"permissioncontroller-statsd",
}
//
@@ -762,14 +632,9 @@
//
m["com.android.runtime"] = []string{
"bionic_libc_platform_headers",
- "fmtlib",
"libarm-optimized-routines-math",
"libasync_safe",
"libasync_safe_headers",
- "libbacktrace_headers",
- "libbase",
- "libbase_headers",
- "libc++",
"libc_aeabi",
"libc_bionic",
"libc_bionic_ndk",
@@ -783,7 +648,6 @@
"libc_freebsd",
"libc_freebsd_large_stack",
"libc_gdtoa",
- "libc_headers",
"libc_init_dynamic",
"libc_init_static",
"libc_jemalloc_wrapper",
@@ -798,8 +662,6 @@
"libc_syscalls",
"libc_tzcode",
"libc_unwind_static",
- "libcutils",
- "libcutils_headers",
"libdebuggerd",
"libdebuggerd_common_headers",
"libdebuggerd_handler_core",
@@ -812,7 +674,6 @@
"libjemalloc5",
"liblinker_main",
"liblinker_malloc",
- "liblog_headers",
"liblz4",
"liblzma",
"libprocessgroup_headers",
@@ -820,11 +681,9 @@
"libpropertyinfoparser",
"libscudo",
"libstdc++",
- "libsystem_headers",
"libsystemproperties",
"libtombstoned_client_static",
"libunwindstack",
- "libutils_headers",
"libz",
"libziparchive",
}
@@ -832,34 +691,19 @@
// Module separator
//
m["com.android.resolv"] = []string{
- "bcm_object",
"dnsresolver_aidl_interface-unstable-ndk_platform",
- "fmtlib",
- "libbacktrace_headers",
- "libbase",
- "libbase_headers",
- "libc++",
- "libcrypto",
- "libcutils",
- "libcutils_headers",
"libgtest_prod",
- "libjsoncpp",
- "liblog_headers",
"libnativehelper_header_only",
"libnetd_client_headers",
"libnetd_resolv",
"libnetdutils",
"libprocessgroup",
"libprocessgroup_headers",
- "libprotobuf-cpp-lite",
- "libssl",
"libstatslog_resolv",
"libstatspush_compat",
"libstatssocket",
"libstatssocket_headers",
- "libsystem_headers",
"libsysutils",
- "libutils_headers",
"netd_event_listener_interface-ndk_platform",
"server_configurable_flags",
"stats_proto",
@@ -868,28 +712,13 @@
// Module separator
//
m["com.android.tethering"] = []string{
- "libbase",
- "libc++",
"libnativehelper_compat_libc++",
"android.hardware.tetheroffload.config@1.0",
- "fmtlib",
- "libbacktrace_headers",
- "libbase_headers",
"libcgrouprc",
"libcgrouprc_format",
- "libcutils",
- "libcutils_headers",
- "libhidlbase",
- "libhidlbase-impl-internal",
- "libhidltransport-impl-internal",
- "libhwbinder-impl-internal",
- "libjsoncpp",
- "liblog_headers",
"libprocessgroup",
"libprocessgroup_headers",
- "libsystem_headers",
"libtetherutilsjni",
- "libutils_headers",
"libvndksupport",
"tethering-aidl-interfaces-java",
}
@@ -925,20 +754,9 @@
"ipmemorystore-aidl-interfaces-V3-java",
"ipmemorystore-aidl-interfaces-java",
"ksoap2",
- "libbacktrace_headers",
- "libbase",
- "libbase_headers",
- "libc++",
- "libcutils",
- "libcutils_headers",
- "liblog_headers",
"libnanohttpd",
"libprocessgroup",
"libprocessgroup_headers",
- "libprotobuf-java-lite",
- "libprotobuf-java-nano",
- "libsystem_headers",
- "libutils_headers",
"libwifi-jni",
"net-utils-services-common",
"netd_aidl_interface-V2-java",
@@ -966,34 +784,14 @@
// Module separator
//
m["com.android.os.statsd"] = []string{
- "libbacktrace_headers",
- "libbase_headers",
- "libc++",
- "libcutils",
- "libcutils_headers",
- "liblog_headers",
"libprocessgroup_headers",
"libstatssocket",
- "libsystem_headers",
- "libutils_headers",
}
//
// Module separator
//
m[android.AvailableToAnyApex] = []string{
- "crtbegin_dynamic",
- "crtbegin_dynamic1",
- "crtbegin_so",
- "crtbegin_so1",
- "crtbegin_static",
- "crtbrand",
- "crtend_android",
- "crtend_so",
"libatomic",
- "libc++_static",
- "libc++abi",
- "libc++demangle",
- "libc_headers",
"libclang_rt",
"libgcc_stripped",
"libprofile-clang-extras",
@@ -1001,22 +799,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
}
@@ -1071,20 +853,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() {
@@ -1973,9 +1763,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() {
@@ -1985,22 +1779,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 */)
})
}
@@ -2016,6 +1806,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
@@ -2030,28 +1838,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 {
@@ -2067,6 +1894,9 @@
isExternal: externalDep,
}
}
+
+ // As soon as the dependency graph crosses the APEX boundary, don't go further.
+ return !externalDep
})
}
@@ -2143,6 +1973,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 {
@@ -2311,7 +2144,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..0c8937e 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"]
@@ -3383,7 +3396,7 @@
}
// JNI libraries including transitive deps are
for _, jni := range []string{"libjni", "libfoo"} {
- jniOutput := ctx.ModuleForTests(jni, "android_arm64_armv8-a_shared_myapex").Module().(*cc.Module).OutputFile()
+ jniOutput := ctx.ModuleForTests(jni, "android_arm64_armv8-a_sdk_shared_myapex").Module().(*cc.Module).OutputFile()
// ... embedded inside APK (jnilibs.zip)
ensureListContains(t, appZipRule.Implicits.Strings(), jniOutput.String())
// ... and not directly inside the APEX
@@ -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/apex/vndk.go b/apex/vndk.go
index f2e913e..2a0d5b0 100644
--- a/apex/vndk.go
+++ b/apex/vndk.go
@@ -95,6 +95,10 @@
func apexVndkDepsMutator(mctx android.BottomUpMutatorContext) {
if m, ok := mctx.Module().(*cc.Module); ok && cc.IsForVndkApex(mctx, m) {
vndkVersion := m.VndkVersion()
+ // For VNDK-Lite device, we gather core-variants of VNDK-Sp libraries, which doesn't have VNDK version defined
+ if vndkVersion == "" {
+ vndkVersion = mctx.DeviceConfig().PlatformVndkVersion()
+ }
vndkApexList := vndkApexList(mctx.Config())
if vndkApex, ok := vndkApexList[vndkVersion]; ok {
mctx.AddReverseDependency(mctx.Module(), sharedLibTag, vndkApex)
diff --git a/apex/vndk_test.go b/apex/vndk_test.go
index a9e26ad..523ac26 100644
--- a/apex/vndk_test.go
+++ b/apex/vndk_test.go
@@ -8,6 +8,59 @@
"android/soong/android"
)
+func TestVndkApexForVndkLite(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex_vndk {
+ name: "myapex",
+ key: "myapex.key",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libvndk",
+ srcs: ["mylib.cpp"],
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ }
+
+ cc_library {
+ name: "libvndksp",
+ srcs: ["mylib.cpp"],
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ }
+ `+vndkLibrariesTxtFiles("current"), func(fs map[string][]byte, config android.Config) {
+ config.TestProductVariables.DeviceVndkVersion = proptools.StringPtr("")
+ })
+ // VNDK-Lite contains only core variants of VNDK-Sp libraries
+ ensureExactContents(t, ctx, "myapex", "android_common_image", []string{
+ "lib/libvndksp.so",
+ "lib/libc++.so",
+ "lib64/libvndksp.so",
+ "lib64/libc++.so",
+ "etc/llndk.libraries.VER.txt",
+ "etc/vndkcore.libraries.VER.txt",
+ "etc/vndksp.libraries.VER.txt",
+ "etc/vndkprivate.libraries.VER.txt",
+ })
+}
+
func TestVndkApexUsesVendorVariant(t *testing.T) {
bp := `
apex_vndk {
@@ -90,6 +143,7 @@
system_shared_libs: [],
stl: "none",
notice: "custom_notice",
+ sdk_version: "current",
}
cc_library {
name: "libprofile-clang-extras_ndk",
@@ -98,6 +152,7 @@
system_shared_libs: [],
stl: "none",
notice: "custom_notice",
+ sdk_version: "current",
}
`, func(fs map[string][]byte, config android.Config) {
config.TestProductVariables.Native_coverage = proptools.BoolPtr(true)
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/androidmk.go b/cc/androidmk.go
index 1c90aaf..5438b14 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -29,6 +29,7 @@
vendorSuffix = ".vendor"
ramdiskSuffix = ".ramdisk"
recoverySuffix = ".recovery"
+ sdkSuffix = ".sdk"
)
type AndroidMkContext interface {
@@ -103,6 +104,28 @@
}
}
}
+ if c.Properties.IsSdkVariant && c.Properties.SdkAndPlatformVariantVisibleToMake {
+ // Make the SDK variant uninstallable so that there are not two rules to install
+ // to the same location.
+ entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
+ // Add the unsuffixed name to SOONG_SDK_VARIANT_MODULES so that Make can rewrite
+ // dependencies to the .sdk suffix when building a module that uses the SDK.
+ entries.SetString("SOONG_SDK_VARIANT_MODULES",
+ "$(SOONG_SDK_VARIANT_MODULES) $(patsubst %.sdk,%,$(LOCAL_MODULE))")
+ }
+ },
+ },
+ ExtraFooters: []android.AndroidMkExtraFootersFunc{
+ func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
+ if c.Properties.IsSdkVariant && c.Properties.SdkAndPlatformVariantVisibleToMake &&
+ c.CcLibraryInterface() && c.Shared() {
+ // Using the SDK variant as a JNI library needs a copy of the .so that
+ // is not named .sdk.so so that it can be packaged into the APK with
+ // the right name.
+ fmt.Fprintln(w, "$(eval $(call copy-one-file,",
+ "$(LOCAL_BUILT_MODULE),",
+ "$(patsubst %.sdk.so,%.so,$(LOCAL_BUILT_MODULE))))")
+ }
},
},
}
@@ -397,6 +420,9 @@
}
func (installer *baseInstaller) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ if installer.path == (android.InstallPath{}) {
+ return
+ }
// Soong installation is only supported for host modules. Have Make
// installation trigger Soong installation.
if ctx.Target().Os.Class == android.Host {
diff --git a/cc/cc.go b/cc/cc.go
index aea9b51..0201404 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -42,6 +42,7 @@
ctx.RegisterModuleType("cc_defaults", defaultsFactory)
ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("sdk", sdkMutator).Parallel()
ctx.BottomUp("vndk", VndkMutator).Parallel()
ctx.BottomUp("link", LinkageMutator).Parallel()
ctx.BottomUp("ndk_api", NdkApiMutator).Parallel()
@@ -208,9 +209,13 @@
// Deprecated. true is the default, false is invalid.
Clang *bool `android:"arch_variant"`
- // Minimum sdk version supported when compiling against the ndk
+ // Minimum sdk version supported when compiling against the ndk. Setting this property causes
+ // two variants to be built, one for the platform and one for apps.
Sdk_version *string
+ // If true, always create an sdk variant and don't create a platform variant.
+ Sdk_variant_only *bool
+
AndroidMkSharedLibs []string `blueprint:"mutated"`
AndroidMkStaticLibs []string `blueprint:"mutated"`
AndroidMkRuntimeLibs []string `blueprint:"mutated"`
@@ -252,6 +257,16 @@
SnapshotRuntimeLibs []string `blueprint:"mutated"`
Installable *bool
+
+ // Set by factories of module types that can only be referenced from variants compiled against
+ // the SDK.
+ AlwaysSdk bool `blueprint:"mutated"`
+
+ // Variant is an SDK variant created by sdkMutator
+ IsSdkVariant bool `blueprint:"mutated"`
+ // Set when both SDK and platform variants are exported to Make to trigger renaming the SDK
+ // variant to have a ".sdk" suffix.
+ SdkAndPlatformVariantVisibleToMake bool `blueprint:"mutated"`
}
type VendorProperties struct {
@@ -489,6 +504,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 {
@@ -528,7 +546,10 @@
}
func (c *Module) SelectedStl() string {
- return c.stl.Properties.SelectedStl
+ if c.stl != nil {
+ return c.stl.Properties.SelectedStl
+ }
+ return ""
}
func (c *Module) ToolchainLibrary() bool {
@@ -556,6 +577,10 @@
return String(c.Properties.Sdk_version)
}
+func (c *Module) AlwaysSdk() bool {
+ return c.Properties.AlwaysSdk || Bool(c.Properties.Sdk_variant_only)
+}
+
func (c *Module) IncludeDirs() android.Paths {
if c.linker != nil {
if library, ok := c.linker.(exportedFlagsProducer); ok {
@@ -815,6 +840,17 @@
return c.Properties.VndkVersion != ""
}
+func (c *Module) canUseSdk() bool {
+ return c.Os() == android.Android && !c.UseVndk() && !c.InRamdisk() && !c.InRecovery()
+}
+
+func (c *Module) UseSdk() bool {
+ if c.canUseSdk() {
+ return String(c.Properties.Sdk_version) != ""
+ }
+ return false
+}
+
func (c *Module) isCoverageVariant() bool {
return c.coverage.Properties.IsCoverageVariant
}
@@ -1072,21 +1108,18 @@
}
func (ctx *moduleContextImpl) canUseSdk() bool {
- return ctx.ctx.Device() && !ctx.useVndk() && !ctx.inRamdisk() && !ctx.inRecovery() && !ctx.ctx.Fuchsia()
+ return ctx.mod.canUseSdk()
}
func (ctx *moduleContextImpl) useSdk() bool {
- if ctx.canUseSdk() {
- return String(ctx.mod.Properties.Sdk_version) != ""
- }
- return false
+ return ctx.mod.UseSdk()
}
func (ctx *moduleContextImpl) sdkVersion() string {
if ctx.ctx.Device() {
if ctx.useVndk() {
vndkVer := ctx.mod.VndkVersion()
- if inList(vndkVer, ctx.ctx.Config().PlatformVersionCombinedCodenames()) {
+ if inList(vndkVer, ctx.ctx.Config().PlatformVersionActiveCodenames()) {
return "current"
}
return vndkVer
@@ -1210,7 +1243,7 @@
}
func (ctx *moduleContextImpl) apexSdkVersion() int {
- return ctx.mod.ApexProperties.Info.MinSdkVersion
+ return ctx.mod.apexSdkVersion
}
func (ctx *moduleContextImpl) hasStubsVariants() bool {
@@ -1398,6 +1431,8 @@
c.Properties.SubName += ramdiskSuffix
} else if c.InRecovery() && !c.OnlyInRecovery() {
c.Properties.SubName += recoverySuffix
+ } else if c.Properties.IsSdkVariant && c.Properties.SdkAndPlatformVariantVisibleToMake {
+ c.Properties.SubName += sdkSuffix
}
ctx := &moduleContext{
@@ -1848,7 +1883,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))
@@ -2232,9 +2270,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
@@ -2288,8 +2339,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
@@ -2312,8 +2362,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/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index 43e8c85..cd0a508 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -58,8 +58,11 @@
"-Wl,--dynamicbase",
"-Wl,--nxcompat",
}
+ windowsLldflags = []string{
+ "-Wl,--Xlink=-Brepro", // Enable deterministic build
+ }
windowsClangLdflags = append(ClangFilterUnknownCflags(windowsLdflags), []string{}...)
- windowsClangLldflags = ClangFilterUnknownLldflags(windowsClangLdflags)
+ windowsClangLldflags = append(ClangFilterUnknownLldflags(windowsClangLdflags), windowsLldflags...)
windowsX86Cflags = []string{
"-m32",
diff --git a/cc/genrule.go b/cc/genrule.go
index 155e410..9331448 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -27,6 +27,7 @@
Vendor_available *bool
Ramdisk_available *bool
Recovery_available *bool
+ Sdk_version *string
}
// cc_genrule is a genrule that can depend on other cc_* objects.
diff --git a/cc/library.go b/cc/library.go
index ec6fc25..94fffb9 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -376,7 +376,7 @@
useCoreVariant bool
checkSameCoreVariant bool
- // Decorated interafaces
+ // Decorated interfaces
*baseCompiler
*baseLinker
*baseInstaller
@@ -1237,7 +1237,7 @@
if Bool(library.Properties.Static_ndk_lib) && library.static() &&
!ctx.useVndk() && !ctx.inRamdisk() && !ctx.inRecovery() && ctx.Device() &&
library.baseLinker.sanitize.isUnsanitizedVariant() &&
- !library.buildStubs() {
+ !library.buildStubs() && ctx.sdkVersion() == "" {
installPath := getNdkSysrootBase(ctx).Join(
ctx, "usr/lib", config.NDKTriple(ctx.toolchain()), file.Base())
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/linkable.go b/cc/linkable.go
index 80cd6b8..fbe61a4 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -45,12 +45,14 @@
InRecovery() bool
OnlyInRecovery() bool
+ UseSdk() bool
UseVndk() bool
MustUseVendorVariant() bool
IsVndk() bool
HasVendorVariant() bool
SdkVersion() string
+ AlwaysSdk() bool
ToolchainLibrary() bool
NdkPrebuiltStl() bool
diff --git a/cc/linker.go b/cc/linker.go
index f65d7c8..57a0c01 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -158,6 +158,13 @@
// the ramdisk variant of the C/C++ module.
Exclude_static_libs []string
}
+ Platform struct {
+ // list of shared libs that should be use to build the platform variant
+ // of a module that sets sdk_version. This should rarely be necessary,
+ // in most cases the same libraries are available for the SDK and platform
+ // variants.
+ Shared_libs []string
+ }
}
// make android::build:GetBuildNumber() available containing the build ID.
@@ -255,6 +262,10 @@
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs)
}
+ if !ctx.useSdk() {
+ deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Target.Platform.Shared_libs...)
+ }
+
if ctx.toolchain().Bionic() {
// libclang_rt.builtins and libatomic have to be last on the command line
if !Bool(linker.Properties.No_libcrt) {
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 09050aa..7ff20f4 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -83,7 +83,7 @@
func (stub *llndkStubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
vndkVer := ctx.Module().(*Module).VndkVersion()
- if !inList(vndkVer, ctx.Config().PlatformVersionCombinedCodenames()) || vndkVer == "" {
+ if !inList(vndkVer, ctx.Config().PlatformVersionActiveCodenames()) || vndkVer == "" {
// For non-enforcing devices, vndkVer is empty. Use "current" in that case, too.
vndkVer = "current"
}
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 2a86d33..68d4ac0 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -381,6 +381,9 @@
module.linker = stub
module.installer = stub
+ module.Properties.AlwaysSdk = true
+ module.Properties.Sdk_version = StringPtr("current")
+
module.AddProperties(&stub.properties, &library.MutatedProperties)
return module
diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go
index e849aee..c4d7708 100644
--- a/cc/ndk_prebuilt.go
+++ b/cc/ndk_prebuilt.go
@@ -76,6 +76,8 @@
baseLinker: NewBaseLinker(nil),
},
}
+ module.Properties.AlwaysSdk = true
+ module.Properties.Sdk_version = StringPtr("current")
module.Properties.HideFromMake = true
return module.Init()
}
@@ -90,6 +92,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 +110,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
@@ -115,10 +127,9 @@
libraryDecorator: library,
}
module.installer = nil
- minVersionString := "minimum"
- noStlString := "none"
- module.Properties.Sdk_version = &minVersionString
- module.stl.Properties.Stl = &noStlString
+ module.Properties.Sdk_version = StringPtr("minimum")
+ module.Properties.AlwaysSdk = true
+ module.stl.Properties.Stl = StringPtr("none")
return module.Init()
}
@@ -135,6 +146,9 @@
}
module.installer = nil
module.Properties.HideFromMake = true
+ module.Properties.AlwaysSdk = true
+ module.Properties.Sdk_version = StringPtr("current")
+ module.stl.Properties.Stl = StringPtr("none")
module.ModuleBase.EnableNativeBridgeSupportByDefault()
return module.Init()
}
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/sdk.go b/cc/sdk.go
new file mode 100644
index 0000000..d05a04a
--- /dev/null
+++ b/cc/sdk.go
@@ -0,0 +1,65 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cc
+
+import (
+ "android/soong/android"
+ "android/soong/genrule"
+)
+
+// sdkMutator sets a creates a platform and an SDK variant for modules
+// that set sdk_version, and ignores sdk_version for the platform
+// variant. The SDK variant will be used for embedding in APKs
+// that may be installed on older platforms. Apexes use their own
+// variants that enforce backwards compatibility.
+func sdkMutator(ctx android.BottomUpMutatorContext) {
+ if ctx.Os() != android.Android {
+ return
+ }
+
+ switch m := ctx.Module().(type) {
+ case LinkableInterface:
+ if m.AlwaysSdk() {
+ if !m.UseSdk() {
+ ctx.ModuleErrorf("UseSdk() must return true when AlwaysSdk is set, did the factory forget to set Sdk_version?")
+ }
+ ctx.CreateVariations("sdk")
+ } else if m.UseSdk() {
+ modules := ctx.CreateVariations("", "sdk")
+ modules[0].(*Module).Properties.Sdk_version = nil
+ modules[1].(*Module).Properties.IsSdkVariant = true
+
+ if ctx.Config().UnbundledBuild() {
+ modules[0].(*Module).Properties.HideFromMake = true
+ } else {
+ modules[1].(*Module).Properties.SdkAndPlatformVariantVisibleToMake = true
+ modules[1].(*Module).Properties.PreventInstall = true
+ }
+ ctx.AliasVariation("")
+ } else {
+ ctx.CreateVariations("")
+ ctx.AliasVariation("")
+ }
+ case *genrule.Module:
+ if p, ok := m.Extra.(*GenruleExtraProperties); ok {
+ if String(p.Sdk_version) != "" {
+ ctx.CreateVariations("", "sdk")
+ } else {
+ ctx.CreateVariations("")
+ }
+ ctx.AliasVariation("")
+ }
+ }
+}
diff --git a/cc/sdk_test.go b/cc/sdk_test.go
new file mode 100644
index 0000000..5a3c181
--- /dev/null
+++ b/cc/sdk_test.go
@@ -0,0 +1,102 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cc
+
+import (
+ "testing"
+
+ "android/soong/android"
+)
+
+func TestSdkMutator(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "libsdk",
+ shared_libs: ["libsdkdep"],
+ sdk_version: "current",
+ stl: "c++_shared",
+ }
+
+ cc_library {
+ name: "libsdkdep",
+ sdk_version: "current",
+ stl: "c++_shared",
+ }
+
+ cc_library {
+ name: "libplatform",
+ shared_libs: ["libsdk"],
+ stl: "libc++",
+ }
+
+ cc_binary {
+ name: "platformbinary",
+ shared_libs: ["libplatform"],
+ stl: "libc++",
+ }
+
+ cc_binary {
+ name: "sdkbinary",
+ shared_libs: ["libsdk"],
+ sdk_version: "current",
+ stl: "libc++",
+ }
+ `
+
+ assertDep := func(t *testing.T, from, to android.TestingModule) {
+ t.Helper()
+ found := false
+
+ var toFile android.Path
+ m := to.Module().(*Module)
+ if toc := m.Toc(); toc.Valid() {
+ toFile = toc.Path()
+ } else {
+ toFile = m.outputFile.Path()
+ }
+
+ rule := from.Description("link")
+ for _, dep := range rule.Implicits {
+ if dep.String() == toFile.String() {
+ found = true
+ }
+ }
+ if !found {
+ t.Errorf("expected %q in %q", toFile.String(), rule.Implicits.Strings())
+ }
+ }
+
+ ctx := testCc(t, bp)
+
+ libsdkNDK := ctx.ModuleForTests("libsdk", "android_arm64_armv8-a_sdk_shared")
+ libsdkPlatform := ctx.ModuleForTests("libsdk", "android_arm64_armv8-a_shared")
+ libsdkdepNDK := ctx.ModuleForTests("libsdkdep", "android_arm64_armv8-a_sdk_shared")
+ libsdkdepPlatform := ctx.ModuleForTests("libsdkdep", "android_arm64_armv8-a_shared")
+ libplatform := ctx.ModuleForTests("libplatform", "android_arm64_armv8-a_shared")
+ platformbinary := ctx.ModuleForTests("platformbinary", "android_arm64_armv8-a")
+ sdkbinary := ctx.ModuleForTests("sdkbinary", "android_arm64_armv8-a_sdk")
+
+ libcxxNDK := ctx.ModuleForTests("ndk_libc++_shared", "android_arm64_armv8-a_sdk_shared")
+ libcxxPlatform := ctx.ModuleForTests("libc++", "android_arm64_armv8-a_shared")
+
+ assertDep(t, libsdkNDK, libsdkdepNDK)
+ assertDep(t, libsdkPlatform, libsdkdepPlatform)
+ assertDep(t, libplatform, libsdkPlatform)
+ assertDep(t, platformbinary, libplatform)
+ assertDep(t, sdkbinary, libsdkNDK)
+
+ assertDep(t, libsdkNDK, libcxxNDK)
+ assertDep(t, libsdkPlatform, libcxxPlatform)
+}
diff --git a/cc/stl.go b/cc/stl.go
index 8113f72..4e74c7f 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -115,9 +115,13 @@
switch s {
case "libc++", "libc++_static":
return s
+ case "c++_shared":
+ return "libc++"
+ case "c++_static":
+ return "libc++_static"
case "none":
return ""
- case "":
+ case "", "system":
if ctx.static() {
return "libc++_static"
} else {
diff --git a/cc/testing.go b/cc/testing.go
index b8a7eab..53f0995 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,
@@ -138,6 +152,7 @@
name: "libgcc_stripped",
vendor_available: true,
recovery_available: true,
+ sdk_version: "current",
src: "",
}
@@ -155,6 +170,7 @@
llndk_library {
name: "libc",
symbol_file: "",
+ sdk_version: "current",
}
cc_library {
name: "libm",
@@ -174,6 +190,7 @@
llndk_library {
name: "libm",
symbol_file: "",
+ sdk_version: "current",
}
cc_library {
name: "libdl",
@@ -193,6 +210,7 @@
llndk_library {
name: "libdl",
symbol_file: "",
+ sdk_version: "current",
}
cc_library {
name: "libft2",
@@ -205,6 +223,7 @@
name: "libft2",
symbol_file: "",
vendor_available: false,
+ sdk_version: "current",
}
cc_library {
name: "libc++_static",
@@ -215,6 +234,10 @@
vendor_available: true,
recovery_available: true,
host_supported: true,
+ apex_available: [
+ "//apex_available:platform",
+ "//apex_available:anyapex",
+ ],
}
cc_library {
name: "libc++",
@@ -243,6 +266,10 @@
host_supported: false,
vendor_available: true,
recovery_available: true,
+ apex_available: [
+ "//apex_available:platform",
+ "//apex_available:anyapex",
+ ],
}
cc_library {
name: "libunwind_llvm",
@@ -254,8 +281,21 @@
recovery_available: true,
}
+ cc_defaults {
+ name: "crt_defaults",
+ recovery_available: true,
+ vendor_available: true,
+ native_bridge_supported: true,
+ stl: "none",
+ apex_available: [
+ "//apex_available:platform",
+ "//apex_available:anyapex",
+ ],
+ }
+
cc_object {
name: "crtbegin_so",
+ defaults: ["crt_defaults"],
recovery_available: true,
vendor_available: true,
native_bridge_supported: true,
@@ -264,6 +304,7 @@
cc_object {
name: "crtbegin_dynamic",
+ defaults: ["crt_defaults"],
recovery_available: true,
vendor_available: true,
native_bridge_supported: true,
@@ -272,6 +313,7 @@
cc_object {
name: "crtbegin_static",
+ defaults: ["crt_defaults"],
recovery_available: true,
vendor_available: true,
native_bridge_supported: true,
@@ -280,6 +322,7 @@
cc_object {
name: "crtend_so",
+ defaults: ["crt_defaults"],
recovery_available: true,
vendor_available: true,
native_bridge_supported: true,
@@ -288,6 +331,7 @@
cc_object {
name: "crtend_android",
+ defaults: ["crt_defaults"],
recovery_available: true,
vendor_available: true,
native_bridge_supported: true,
@@ -336,6 +380,16 @@
sdk_version: "27",
}
+ ndk_prebuilt_object {
+ name: "ndk_crtbegin_dynamic.27",
+ sdk_version: "27",
+ }
+
+ ndk_prebuilt_object {
+ name: "ndk_crtend_android.27",
+ sdk_version: "27",
+ }
+
ndk_prebuilt_shared_stl {
name: "ndk_libc++_shared",
}
diff --git a/cc/tidy.go b/cc/tidy.go
index 5455392..cfb5b68 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -117,6 +117,10 @@
// which is used in many Android files.
tidyChecks = tidyChecks + ",-cert-dcl16-c"
}
+ // https://b.corp.google.com/issues/153464409
+ // many local projects enable cert-* checks, which
+ // trigger bugprone-reserved-identifier.
+ tidyChecks = tidyChecks + ",-bugprone-reserved-identifier*,-cert-dcl51-cpp,-cert-dcl37-c"
flags.TidyFlags = append(flags.TidyFlags, tidyChecks)
if len(tidy.Properties.Tidy_checks_as_errors) > 0 {
diff --git a/cc/toolchain_library.go b/cc/toolchain_library.go
index dfc6f76..042e012 100644
--- a/cc/toolchain_library.go
+++ b/cc/toolchain_library.go
@@ -67,6 +67,7 @@
module.stl = nil
module.sanitize = nil
module.installer = nil
+ module.Properties.Sdk_version = StringPtr("current")
return module.Init()
}
diff --git a/cc/vndk.go b/cc/vndk.go
index 4888dcf..dbe1f3b 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -309,6 +309,10 @@
panic(err)
}
+ if m.HasStubsVariants() {
+ mctx.PropertyErrorf("vndk.enabled", "This library provides stubs. Shouldn't be VNDK. Consider making it as LLNDK")
+ }
+
vndkLibrariesLock.Lock()
defer vndkLibrariesLock.Unlock()
@@ -350,6 +354,15 @@
}
if lib, ok := m.linker.(libraryInterface); ok {
+ // VNDK APEX for VNDK-Lite devices will have VNDK-SP libraries from core variants
+ if mctx.DeviceConfig().VndkVersion() == "" {
+ // b/73296261: filter out libz.so because it is considered as LLNDK for VNDK-lite devices
+ if mctx.ModuleName() == "libz" {
+ return false
+ }
+ return m.ImageVariation().Variation == android.CoreVariation && lib.shared() && m.isVndkSp()
+ }
+
useCoreVariant := m.VndkVersion() == mctx.DeviceConfig().PlatformVndkVersion() &&
mctx.DeviceConfig().VndkUseCoreVariant() && !m.MustUseVendorVariant()
return lib.shared() && m.inVendor() && m.IsVndk() && !m.isVndkExt() && !useCoreVariant
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/docs/map_files.md b/docs/map_files.md
new file mode 100644
index 0000000..9fc0d14
--- /dev/null
+++ b/docs/map_files.md
@@ -0,0 +1,174 @@
+# Native API Map Files
+
+Native APIs such as those exposed by the NDK, LL-NDK, or APEX are described by
+map.txt files. These files are [linker version scripts] with comments that are
+semantically meaningful to [gen_stub_libs.py]. For an example of a map file, see
+[libc.map.txt].
+
+[gen_stub_libs.py]: https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/gen_stub_libs.py
+[libc.map.txt]: https://cs.android.com/android/platform/superproject/+/master:bionic/libc/libc.map.txt
+[linker version scripts]: https://www.gnu.org/software/gnulib/manual/html_node/LD-Version-Scripts.html
+
+## Basic format
+
+A linker version script defines at least one alphanumeric "version" definition,
+each of which contain a list of symbols. For example:
+
+```txt
+MY_API_R { # introduced=R
+ global:
+ api_foo;
+ api_bar;
+ local:
+ *;
+};
+
+MY_API_S { # introduced=S
+ global:
+ api_baz;
+} MY_API_R;
+```
+
+Comments on the same line as either a version definition or a symbol name have
+meaning. If you need to add any comments that should not be interpreted by the
+stub generator, keep them on their own line. For a list of supported comments,
+see the "Tags" section.
+
+Here, `api_foo` and `api_bar` are exposed in the generated stubs with the
+`MY_API_R` version and `api_baz` is exposed with the `MY_API_S` version. No
+other symbols are defined as public by this API. `MY_API_S` inherits all symbols
+defined by `MY_API_R`.
+
+When generating NDK API stubs from this version script, the stub library for R
+will define `api_foo` and `api_bar`. The stub library for S will define all
+three APIs.
+
+Note that, with few exceptions (see "Special version names" below), the name of
+the version has no inherent meaning.
+
+These map files can (and should) also be used as version scripts for building
+the implementation library rather than just defining the stub interface by using
+the `version_script` property of `cc_library`. This has the effect of limiting
+symbol visibility of the library to expose only the interface named by the map
+file. Without this, APIs that you have not explicitly exposed will still be
+available to users via `dlsym`. Note: All comments are ignored in this case. Any
+symbol named in any `global:` group will be visible.
+
+## Special version names
+
+Version names that end with `_PRIVATE` or `_PLATFORM` will not be exposed in any
+stubs, but will be exposed in the implementation library. Using either of these
+naming schemes is equivalent to marking the version with the `platform-only`
+tag. See the docs for `platform-only` for more information.
+
+## Tags
+
+Comments on the same line as a version definition or a symbol name are
+interpreted by the stub generator. Multiple space-delimited tags may be used on
+the same line. The supported tags are:
+
+### apex
+
+Indicates that the version or symbol is to be exposed in the APEX stubs rather
+than the NDK. May be used in combination with `llndk` if the symbol is exposed
+to both APEX and the LL-NDK.
+
+### future
+
+Indicates that the version or symbol is first introduced in the "future" API
+level. This is an abitrarily high API level used to define APIs that have not
+yet been added to a specific release.
+
+### introduced
+
+Indicates the version in which an API was first introduced. For example,
+`introduced=21` specifies that the API was first added (or first made public) in
+API level 21. This tag can be applied to either a version definition or an
+individual symbol. If applied to a version, all symbols contained in the version
+will have the tag applied. An `introduced` tag on a symbol overrides the value
+set for the version, if both are defined.
+
+Note: The map file alone does not contain all the information needed to
+determine which API level an API was added in. The `first_version` property of
+`ndk_library` will dictate which API levels stubs are generated for. If the
+module sets `first_version: "21"`, no symbols were introduced before API 21.
+
+Codenames can (and typically should) be used when defining new APIs. This allows
+the actual number of the API level to remain vague during development of that
+release. For example, `introduced=S` can be used to define APIs added in S. Any
+code name known to the build system can be used. For a list of versions known to
+the build system, see `out/soong/api_levels.json` (if not present, run `m
+out/soong/api_levels.json` to generate it).
+
+Architecture-specific variants of this tag exist:
+
+* `introduced-arm=VERSION`
+* `introduced-arm64=VERSION`
+* `introduced-x86=VERSION`
+* `introduced-x86_64=VERSION`
+
+The architecture-specific tag will take precedence over the architecture-generic
+tag when generating stubs for that architecture if both are present. If the
+symbol is defined with only architecture-specific tags, it will not be present
+for architectures that are not named.
+
+Note: The architecture-specific tags should, in general, not be used. These are
+primarily needed for APIs that were wrongly inconsistently exposed by libc/libm
+in old versions of Android before the stubs were well maintained. Think hard
+before using an architecture-specific tag for a new API.
+
+### llndk
+
+Indicates that the version or symbol is to be exposed in the LL-NDK stubs rather
+than the NDK. May be used in combination with `apex` if the symbol is exposed to
+both APEX and the LL-NDK.
+
+### platform-only
+
+Indicates that the version or symbol is public in the implementation library but
+should not be exposed in the stub library. Developers can still access them via
+`dlsym`, but they will not be exposed in the stubs so it should at least be
+clear to the developer that they are up to no good.
+
+The typical use for this tag is for exposing an API to the platform that is not
+for use by the NDK, LL-NDK, or APEX. It is preferable to keep such APIs in an
+entirely separate library to protect them from access via `dlsym`, but this is
+not always possible.
+
+### var
+
+Used to define a public global variable. By default all symbols are exposed as
+functions. In the uncommon situation of exposing a global variable, the `var`
+tag may be used.
+
+### versioned=VERSION
+
+Behaves similarly to `introduced` but defines the first version that the stub
+library should apply symbol versioning. For example:
+
+```txt
+R { # introduced=R
+ global:
+ foo;
+ bar; # versioned=S
+ local:
+ *;
+};
+```
+
+The stub library for R will contain symbols for both `foo` and `bar`, but only
+`foo` will include a versioned symbol `foo@R`. The stub library for S will
+contain both symbols, as well as the versioned symbols `foo@R` and `bar@R`.
+
+This tag is not commonly needed and is only used to hide symbol versioning
+mistakes that shipped as part of the platform.
+
+Note: Like `introduced`, the map file does not tell the whole story. The
+`ndk_library` Soong module may define a `unversioned_until` property that sets
+the default for the entire map file.
+
+### weak
+
+Indicates that the symbol should be [weak] in the stub library.
+
+[weak]: https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html
diff --git a/java/androidmk.go b/java/androidmk.go
index ee2437a..d37eac8 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{
@@ -544,10 +545,21 @@
}
func (dstubs *Droidstubs) AndroidMkEntries() []android.AndroidMkEntries {
+ // If the stubsSrcJar is not generated (because generate_stubs is false) then
+ // use the api file as the output file to ensure the relevant phony targets
+ // are created in make if only the api txt file is being generated. This is
+ // needed because an invalid output file would prevent the make entries from
+ // being written.
+ // TODO(b/146727827): Revert when we do not need to generate stubs and API separately.
+ distFile := android.OptionalPathForPath(dstubs.apiFile)
+ outputFile := android.OptionalPathForPath(dstubs.stubsSrcJar)
+ if !outputFile.Valid() {
+ outputFile = distFile
+ }
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
- DistFile: android.OptionalPathForPath(dstubs.apiFile),
- OutputFile: android.OptionalPathForPath(dstubs.stubsSrcJar),
+ DistFile: distFile,
+ OutputFile: outputFile,
Include: "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(entries *android.AndroidMkEntries) {
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..ae9cd5f 100755
--- a/java/app.go
+++ b/java/app.go
@@ -214,6 +214,13 @@
for _, jniTarget := range ctx.MultiTargets() {
variation := append(jniTarget.Variations(),
blueprint.Variation{Mutator: "link", Variation: "shared"})
+
+ // If the app builds against an Android SDK use the SDK variant of JNI dependencies
+ // unless jni_uses_platform_apis is set.
+ if a.sdkVersion().specified() && a.sdkVersion().kind != sdkCorePlatform &&
+ !Bool(a.appProperties.Jni_uses_platform_apis) {
+ variation = append(variation, blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
+ }
ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs...)
}
@@ -385,7 +392,18 @@
TransformJniLibsToJar(ctx, jniJarFile, jniLibs, a.useEmbeddedNativeLibs(ctx))
for _, jni := range jniLibs {
if jni.coverageFile.Valid() {
- a.jniCoverageOutputs = append(a.jniCoverageOutputs, jni.coverageFile.Path())
+ // Only collect coverage for the first target arch if this is a multilib target.
+ // TODO(jungjw): Ideally, we want to collect both reports, but that would cause coverage
+ // data file path collisions since the current coverage file path format doesn't contain
+ // arch-related strings. This is fine for now though; the code coverage team doesn't use
+ // multi-arch targets such as test_suite_* for coverage collections yet.
+ //
+ // 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 {
+ a.jniCoverageOutputs = append(a.jniCoverageOutputs, jni.coverageFile.Path())
+ }
}
}
} else {
@@ -529,14 +547,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 +1188,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")
@@ -1337,6 +1369,12 @@
// if not blank, set the minimum version of the sdk that the compiled artifacts will run against.
// Defaults to sdk_version if not set.
Min_sdk_version *string
+
+ // list of android_library modules whose resources are extracted and linked against statically
+ Static_libs []string
+
+ // list of android_app modules whose resources are extracted and linked against
+ Resource_libs []string
}
func (r *RuntimeResourceOverlay) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -1349,6 +1387,9 @@
if cert != "" {
ctx.AddDependency(ctx.Module(), certificateTag, cert)
}
+
+ ctx.AddVariationDependencies(nil, staticLibTag, r.properties.Static_libs...)
+ ctx.AddVariationDependencies(nil, libTag, r.properties.Resource_libs...)
}
func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -1361,7 +1402,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..43696db 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -791,6 +791,7 @@
cc_library {
name: "libjni",
system_shared_libs: [],
+ sdk_version: "current",
stl: "none",
}
@@ -928,26 +929,26 @@
android_test {
name: "test",
- sdk_version: "core_platform",
+ sdk_version: "current",
jni_libs: ["libjni"],
}
android_test {
name: "test_noembed",
- sdk_version: "core_platform",
+ sdk_version: "current",
jni_libs: ["libjni"],
use_embedded_native_libs: false,
}
android_test_helper_app {
name: "test_helper",
- sdk_version: "core_platform",
+ sdk_version: "current",
jni_libs: ["libjni"],
}
android_test_helper_app {
name: "test_helper_noembed",
- sdk_version: "core_platform",
+ sdk_version: "current",
jni_libs: ["libjni"],
use_embedded_native_libs: false,
}
@@ -979,6 +980,10 @@
if g, w := !strings.Contains(jniLibZip.Args["jarArgs"], "-L 0"), test.compressed; g != w {
t.Errorf("expected jni compressed %v, got %v", w, g)
}
+
+ if !strings.Contains(jniLibZip.Implicits[0].String(), "_sdk_") {
+ t.Errorf("expected input %q to use sdk variant", jniLibZip.Implicits[0].String())
+ }
}
})
}
@@ -1074,6 +1079,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
@@ -2284,11 +2349,17 @@
}
func TestRuntimeResourceOverlay(t *testing.T) {
- ctx, config := testJava(t, `
+ fs := map[string][]byte{
+ "baz/res/res/values/strings.xml": nil,
+ "bar/res/res/values/strings.xml": nil,
+ }
+ bp := `
runtime_resource_overlay {
name: "foo",
certificate: "platform",
product_specific: true,
+ static_libs: ["bar"],
+ resource_libs: ["baz"],
aaptflags: ["--keep-raw-values"],
}
@@ -2298,7 +2369,21 @@
product_specific: true,
theme: "faza",
}
- `)
+
+ android_library {
+ name: "bar",
+ resource_dirs: ["bar/res"],
+ }
+
+ android_app {
+ name: "baz",
+ sdk_version: "current",
+ resource_dirs: ["baz/res"],
+ }
+ `
+ config := testAppConfig(nil, bp, fs)
+ ctx := testContext()
+ run(t, ctx, config)
m := ctx.ModuleForTests("foo", "android_common")
@@ -2310,6 +2395,19 @@
t.Errorf("expected values, %q are missing in aapt2 link flags, %q", absentFlags, aapt2Flags)
}
+ // Check overlay.list output for static_libs dependency.
+ overlayList := m.Output("aapt2/overlay.list").Inputs.Strings()
+ staticLibPackage := buildDir + "/.intermediates/bar/android_common/package-res.apk"
+ if !inList(staticLibPackage, overlayList) {
+ t.Errorf("Stactic lib res package %q missing in overlay list: %q", staticLibPackage, overlayList)
+ }
+
+ // Check AAPT2 link flags for resource_libs dependency.
+ resourceLibFlag := "-I " + buildDir + "/.intermediates/baz/android_common/package-res.apk"
+ if !strings.Contains(aapt2Flags, resourceLibFlag) {
+ t.Errorf("Resource lib flag %q missing in aapt2 link flags: %q", resourceLibFlag, aapt2Flags)
+ }
+
// Check cert signing flag.
signedApk := m.Output("signed/foo.apk")
signingFlag := signedApk.Args["certificates"]
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index bf64ae8..fba0b97 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -127,7 +127,8 @@
global := dexpreopt.GetGlobalConfig(ctx)
bootImage := defaultBootImageConfig(ctx)
dexFiles := bootImage.dexPathsDeps.Paths()
- dexLocations := bootImage.dexLocationsDeps
+ // The dex locations for all Android variants are identical.
+ dexLocations := bootImage.getAnyAndroidVariant().dexLocationsDeps
if global.UseArtImage {
bootImage = artBootImageConfig(ctx)
}
@@ -155,8 +156,8 @@
images = append(images, variant.images)
imagesDeps = append(imagesDeps, variant.imagesDeps)
}
- // The locations for all Android targets are identical. Pick the first one.
- imageLocations := bootImage.getVariant(targets[0]).imageLocations()
+ // The image locations for all Android variants are identical.
+ imageLocations := bootImage.getAnyAndroidVariant().imageLocations()
dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index ae3cd06..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.
@@ -51,10 +52,6 @@
// The names of jars that constitute this image.
modules []string
- // The "locations" of jars.
- dexLocations []string // for this image
- dexLocationsDeps []string // for the dependency images and in this image
-
// File paths to jars.
dexPaths android.WritablePaths // for this image
dexPathsDeps android.WritablePaths // for the dependency images and in this image
@@ -76,6 +73,10 @@
// Target for which the image is generated.
target android.Target
+ // The "locations" of jars.
+ dexLocations []string // for this image
+ dexLocationsDeps []string // for the dependency images and in this image
+
// Paths to image files.
images android.OutputPath // first image file
imagesDeps android.OutputPaths // all files
@@ -98,6 +99,16 @@
return nil
}
+// Return any (the first) variant which is for the device (as opposed to for the host)
+func (image bootImageConfig) getAnyAndroidVariant() *bootImageVariant {
+ for _, variant := range image.variants {
+ if variant.target.Os == android.Android {
+ return variant
+ }
+ }
+ return nil
+}
+
func (image bootImageConfig) moduleName(idx int) string {
// Dexpreopt on the boot class path produces multiple files. The first dex file
// is converted into 'name'.art (to match the legacy assumption that 'name'.art
@@ -163,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
@@ -231,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
}
})
@@ -252,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])
}
}
@@ -271,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 {
@@ -475,7 +542,7 @@
Tool(globalSoong.Profman).
FlagWithInput("--create-profile-from=", bootImageProfile).
FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
- FlagForEachArg("--dex-location=", image.dexLocationsDeps).
+ FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps).
FlagWithOutput("--reference-profile-file=", profile)
rule.Install(profile, "/system/etc/boot-image.prof")
@@ -526,7 +593,7 @@
Flag("--generate-boot-profile").
FlagWithInput("--create-profile-from=", bootFrameworkProfile).
FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
- FlagForEachArg("--dex-location=", image.dexLocationsDeps).
+ FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps).
FlagWithOutput("--reference-profile-file=", profile)
rule.Install(profile, "/system/etc/boot-image.bprof")
@@ -539,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 {
@@ -606,12 +728,11 @@
if image != nil {
ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String())
ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(image.dexPathsDeps.Strings(), " "))
- ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(image.dexLocationsDeps, " "))
+ ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(image.getAnyAndroidVariant().dexLocationsDeps, " "))
var imageNames []string
for _, current := range append(d.otherImages, image) {
imageNames = append(imageNames, current.name)
- imageLocations := []string{}
for _, variant := range current.variants {
suffix := ""
if variant.target.Os.Class == android.Host {
@@ -623,11 +744,8 @@
ctx.Strict("DEXPREOPT_IMAGE_DEPS_"+sfx, strings.Join(variant.imagesDeps.Strings(), " "))
ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+sfx, variant.installs.String())
ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+sfx, variant.unstrippedInstalls.String())
- if variant.target.Os == android.Android {
- // The locations for all Android targets are identical. Pick one.
- imageLocations = variant.imageLocations()
- }
}
+ imageLocations := current.getAnyAndroidVariant().imageLocations()
ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_"+current.name, strings.Join(imageLocations, ":"))
ctx.Strict("DEXPREOPT_IMAGE_ZIP_"+current.name, current.zip.String())
}
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 01a26ba..066694c 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -79,6 +79,14 @@
return moduleName
}
+func getDexLocation(ctx android.PathContext, target android.Target, subdir string, name string) string {
+ if target.Os.Class == android.Host {
+ return filepath.Join(ctx.Config().Getenv("OUT_DIR"), "host", ctx.Config().PrebuiltOS(), subdir, name)
+ } else {
+ return filepath.Join("/", subdir, name)
+ }
+}
+
var (
bootImageConfigKey = android.NewOnceKey("bootImageConfig")
artBootImageName = "art"
@@ -104,35 +112,23 @@
artSubdir := "apex/com.android.art/javalib"
frameworkSubdir := "system/framework"
- var artLocations, frameworkLocations []string
- for _, m := range artModules {
- artLocations = append(artLocations, filepath.Join("/"+artSubdir, stemOf(m)+".jar"))
- }
- for _, m := range frameworkModules {
- frameworkLocations = append(frameworkLocations, filepath.Join("/"+frameworkSubdir, stemOf(m)+".jar"))
- }
-
// ART config for the primary boot image in the ART apex.
// It includes the Core Libraries.
artCfg := bootImageConfig{
- name: artBootImageName,
- stem: "boot",
- installSubdir: artSubdir,
- modules: artModules,
- dexLocations: artLocations,
- dexLocationsDeps: artLocations,
+ name: artBootImageName,
+ stem: "boot",
+ installSubdir: artSubdir,
+ modules: artModules,
}
// Framework config for the boot image extension.
// It includes framework libraries and depends on the ART config.
frameworkCfg := bootImageConfig{
- extends: &artCfg,
- name: frameworkBootImageName,
- stem: "boot",
- installSubdir: frameworkSubdir,
- modules: frameworkModules,
- dexLocations: frameworkLocations,
- dexLocationsDeps: append(artLocations, frameworkLocations...),
+ extends: &artCfg,
+ name: frameworkBootImageName,
+ stem: "boot",
+ installSubdir: frameworkSubdir,
+ modules: frameworkModules,
}
configs := map[string]*bootImageConfig{
@@ -168,6 +164,10 @@
images: imageDir.Join(ctx, imageName),
imagesDeps: c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"),
}
+ for _, m := range c.modules {
+ variant.dexLocations = append(variant.dexLocations, getDexLocation(ctx, target, c.installSubdir, stemOf(m)+".jar"))
+ }
+ variant.dexLocationsDeps = variant.dexLocations
c.variants = append(c.variants, variant)
}
@@ -178,6 +178,7 @@
frameworkCfg.dexPathsDeps = append(artCfg.dexPathsDeps, frameworkCfg.dexPathsDeps...)
for i := range targets {
frameworkCfg.variants[i].primaryImages = artCfg.variants[i].images
+ frameworkCfg.variants[i].dexLocationsDeps = append(artCfg.variants[i].dexLocations, frameworkCfg.variants[i].dexLocationsDeps...)
}
return configs
@@ -202,7 +203,7 @@
updatableBootclasspath[i] = dexpreopt.GetJarLocationFromApexJarPair(p)
}
- bootclasspath := append(copyOf(image.dexLocationsDeps), updatableBootclasspath...)
+ bootclasspath := append(copyOf(image.getAnyAndroidVariant().dexLocationsDeps), updatableBootclasspath...)
return bootclasspath
})
}
@@ -217,7 +218,7 @@
func dexpreoptConfigMakevars(ctx android.MakeVarsContext) {
ctx.Strict("PRODUCT_BOOTCLASSPATH", strings.Join(defaultBootclasspath(ctx), ":"))
- ctx.Strict("PRODUCT_DEX2OAT_BOOTCLASSPATH", strings.Join(defaultBootImageConfig(ctx).dexLocationsDeps, ":"))
+ ctx.Strict("PRODUCT_DEX2OAT_BOOTCLASSPATH", strings.Join(defaultBootImageConfig(ctx).getAnyAndroidVariant().dexLocationsDeps, ":"))
ctx.Strict("PRODUCT_SYSTEM_SERVER_CLASSPATH", strings.Join(systemServerClasspath(ctx), ":"))
ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules, ":"))
diff --git a/java/droiddoc.go b/java/droiddoc.go
index b0efaa5..e4582f6 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -301,6 +301,11 @@
// if set to true, allow Metalava to generate doc_stubs source files. Defaults to false.
Create_doc_stubs *bool
+ // if set to false then do not write out stubs. Defaults to true.
+ //
+ // TODO(b/146727827): Remove capability when we do not need to generate stubs and API separately.
+ Generate_stubs *bool
+
// is set to true, Metalava will allow framework SDK to contain API levels annotations.
Api_levels_annotations_enabled *bool
@@ -370,10 +375,18 @@
apiToCheck.Removed_api_file = nil
}
+// Used by xsd_config
type ApiFilePath interface {
ApiFilePath() android.Path
}
+// Provider of information about API stubs, used by java_sdk_library.
+type ApiStubsProvider interface {
+ ApiFilePath
+ RemovedApiFilePath() android.Path
+ StubsSrcJar() android.Path
+}
+
//
// Javadoc
//
@@ -1259,6 +1272,14 @@
return d.apiFilePath
}
+func (d *Droidstubs) RemovedApiFilePath() android.Path {
+ return d.removedApiFile
+}
+
+func (d *Droidstubs) StubsSrcJar() android.Path {
+ return d.stubsSrcJar
+}
+
func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
d.Javadoc.addDeps(ctx)
@@ -1285,7 +1306,7 @@
}
}
-func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.WritablePath) {
+func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath) {
if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") ||
String(d.properties.Api_filename) != "" {
@@ -1341,11 +1362,13 @@
cmd.FlagWithArg("--sdk-values ", d.metadataDir.String())
}
- if Bool(d.properties.Create_doc_stubs) {
- cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
- } else {
- cmd.FlagWithArg("--stubs ", stubsDir.String())
- cmd.Flag("--exclude-documentation-from-stubs")
+ if stubsDir.Valid() {
+ if Bool(d.properties.Create_doc_stubs) {
+ cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
+ } else {
+ cmd.FlagWithArg("--stubs ", stubsDir.String())
+ cmd.Flag("--exclude-documentation-from-stubs")
+ }
}
}
@@ -1502,15 +1525,18 @@
// Create rule for metalava
- d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
-
srcJarDir := android.PathForModuleOut(ctx, "srcjars")
- stubsDir := android.PathForModuleOut(ctx, "stubsDir")
rule := android.NewRuleBuilder()
- rule.Command().Text("rm -rf").Text(stubsDir.String())
- rule.Command().Text("mkdir -p").Text(stubsDir.String())
+ generateStubs := BoolDefault(d.properties.Generate_stubs, true)
+ var stubsDir android.OptionalPath
+ if generateStubs {
+ d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
+ stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, "stubsDir"))
+ rule.Command().Text("rm -rf").Text(stubsDir.String())
+ rule.Command().Text("mkdir -p").Text(stubsDir.String())
+ }
srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars)
@@ -1536,13 +1562,15 @@
cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
}
- rule.Command().
- BuiltTool(ctx, "soong_zip").
- Flag("-write_if_changed").
- Flag("-jar").
- FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
- FlagWithArg("-C ", stubsDir.String()).
- FlagWithArg("-D ", stubsDir.String())
+ if generateStubs {
+ rule.Command().
+ BuiltTool(ctx, "soong_zip").
+ Flag("-write_if_changed").
+ Flag("-jar").
+ FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
+ FlagWithArg("-C ", stubsDir.String()).
+ FlagWithArg("-D ", stubsDir.String())
+ }
if Bool(d.properties.Write_sdk_values) {
d.metadataZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-metadata.zip")
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/prebuilt_apis.go b/java/prebuilt_apis.go
index cb17fee..86eddb1 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -28,10 +28,6 @@
func RegisterPrebuiltApisBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("prebuilt_apis", PrebuiltApisFactory)
-
- ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("prebuilt_apis", PrebuiltApisMutator).Parallel()
- })
}
type prebuiltApisProperties struct {
@@ -48,7 +44,7 @@
// no need to implement
}
-func parseJarPath(ctx android.BaseModuleContext, path string) (module string, apiver string, scope string) {
+func parseJarPath(path string) (module string, apiver string, scope string) {
elements := strings.Split(path, "/")
apiver = elements[0]
@@ -58,7 +54,7 @@
return
}
-func parseApiFilePath(ctx android.BaseModuleContext, path string) (module string, apiver string, scope string) {
+func parseApiFilePath(ctx android.LoadHookContext, path string) (module string, apiver string, scope string) {
elements := strings.Split(path, "/")
apiver = elements[0]
@@ -73,7 +69,7 @@
return
}
-func createImport(mctx android.TopDownMutatorContext, module string, scope string, apiver string, path string) {
+func createImport(mctx android.LoadHookContext, module string, scope string, apiver string, path string) {
props := struct {
Name *string
Jars []string
@@ -89,7 +85,7 @@
mctx.CreateModule(ImportFactory, &props)
}
-func createFilegroup(mctx android.TopDownMutatorContext, module string, scope string, apiver string, path string) {
+func createFilegroup(mctx android.LoadHookContext, module string, scope string, apiver string, path string) {
fgName := module + ".api." + scope + "." + apiver
filegroupProps := struct {
Name *string
@@ -100,7 +96,7 @@
mctx.CreateModule(android.FileGroupFactory, &filegroupProps)
}
-func getPrebuiltFiles(mctx android.TopDownMutatorContext, name string) []string {
+func getPrebuiltFiles(mctx android.LoadHookContext, name string) []string {
mydir := mctx.ModuleDir() + "/"
var files []string
for _, apiver := range mctx.Module().(*prebuiltApis).properties.Api_dirs {
@@ -115,7 +111,7 @@
return files
}
-func prebuiltSdkStubs(mctx android.TopDownMutatorContext) {
+func prebuiltSdkStubs(mctx android.LoadHookContext) {
mydir := mctx.ModuleDir() + "/"
// <apiver>/<scope>/<module>.jar
files := getPrebuiltFiles(mctx, "*.jar")
@@ -123,12 +119,12 @@
for _, f := range files {
// create a Import module for each jar file
localPath := strings.TrimPrefix(f, mydir)
- module, apiver, scope := parseJarPath(mctx, localPath)
+ module, apiver, scope := parseJarPath(localPath)
createImport(mctx, module, scope, apiver, localPath)
}
}
-func prebuiltApiFiles(mctx android.TopDownMutatorContext) {
+func prebuiltApiFiles(mctx android.LoadHookContext) {
mydir := mctx.ModuleDir() + "/"
// <apiver>/<scope>/api/<module>.txt
files := getPrebuiltFiles(mctx, "api/*.txt")
@@ -178,7 +174,7 @@
}
}
-func PrebuiltApisMutator(mctx android.TopDownMutatorContext) {
+func createPrebuiltApiModules(mctx android.LoadHookContext) {
if _, ok := mctx.Module().(*prebuiltApis); ok {
prebuiltApiFiles(mctx)
prebuiltSdkStubs(mctx)
@@ -191,9 +187,15 @@
// generates a filegroup module named <module>-api.<scope>.<ver>.
//
// It also creates <module>-api.<scope>.latest for the latest <ver>.
+//
+// Similarly, it generates a java_import for all API .jar files found under the
+// directory where the Android.bp is located. Specifically, an API file located
+// at ./<ver>/<scope>/api/<module>.jar generates a java_import module named
+// <prebuilt-api-module>.<scope>.<ver>.<module>.
func PrebuiltApisFactory() android.Module {
module := &prebuiltApis{}
module.AddProperties(&module.properties)
android.InitAndroidModule(module)
+ android.AddLoadHook(module, createPrebuiltApiModules)
return module
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 6921114..ff80d63 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -15,18 +15,18 @@
package java
import (
- "android/soong/android"
-
"fmt"
- "io"
"path"
"path/filepath"
+ "reflect"
"sort"
"strings"
"sync"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
+
+ "android/soong/android"
)
const (
@@ -67,6 +67,9 @@
// The name of the api scope, e.g. public, system, test
name string
+ // The name of the field in the dynamically created structure.
+ fieldName string
+
// The tag to use to depend on the stubs library module.
stubsTag scopeDependencyTag
@@ -87,11 +90,14 @@
// *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
func initApiScope(scope *apiScope) *apiScope {
- //apiScope := &scope
+ scope.fieldName = proptools.FieldNameForProperty(scope.name)
scope.stubsTag = scopeDependencyTag{
name: scope.name + "-stubs",
apiScope: scope,
@@ -132,6 +138,7 @@
moduleSuffix: sdkSystemApiSuffix,
apiFileMakeVariableSuffix: "_SYSTEM",
sdkVersion: "system_current",
+ droidstubsArgs: []string{"-showAnnotation android.annotation.SystemApi"},
})
apiScopeTest = initApiScope(&apiScope{
name: "test",
@@ -139,6 +146,7 @@
moduleSuffix: sdkTestApiSuffix,
apiFileMakeVariableSuffix: "_TEST",
sdkVersion: "test_current",
+ droidstubsArgs: []string{"-showAnnotation android.annotation.TestApi"},
})
allApiScopes = apiScopes{
apiScopePublic,
@@ -163,6 +171,14 @@
sort.Strings(*javaSdkLibraries)
ctx.Strict("JAVA_SDK_LIBRARIES", strings.Join(*javaSdkLibraries, " "))
})
+
+ // Register sdk member types.
+ android.RegisterSdkMemberType(&sdkLibrarySdkMemberType{
+ android.SdkMemberTypeBase{
+ PropertyName: "java_sdk_libs",
+ SupportsSdk: true,
+ },
+ })
}
func RegisterSdkLibraryBuildComponents(ctx android.RegistrationContext) {
@@ -220,9 +236,11 @@
}
type scopePaths struct {
- stubsHeaderPath android.Paths
- stubsImplPath android.Paths
- apiFilePath android.Path
+ stubsHeaderPath android.Paths
+ stubsImplPath android.Paths
+ currentApiFilePath android.Path
+ removedApiFilePath android.Path
+ stubsSrcJar android.Path
}
// Common code between sdk library and sdk library import
@@ -309,11 +327,13 @@
scopePaths.stubsImplPath = lib.ImplementationJars()
}
}
- if doc, ok := to.(ApiFilePath); ok {
+ if doc, ok := to.(ApiStubsProvider); ok {
if scopeTag, ok := tag.(scopeDependencyTag); ok {
apiScope := scopeTag.apiScope
scopePaths := module.getScopePaths(apiScope)
- scopePaths.apiFilePath = doc.ApiFilePath()
+ scopePaths.currentApiFilePath = doc.ApiFilePath()
+ scopePaths.removedApiFilePath = doc.RemovedApiFilePath()
+ scopePaths.stubsSrcJar = doc.StubsSrcJar()
} else {
ctx.ModuleErrorf("depends on module %q of unknown tag %q", otherName, tag)
}
@@ -328,41 +348,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 +371,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 +434,12 @@
Srcs []string
Javacflags []string
}
+ Dist struct {
+ Targets []string
+ Dest *string
+ Dir *string
+ Tag *string
+ }
}{}
props.Name = proptools.StringPtr(module.stubsName(apiScope))
@@ -466,11 +468,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 +506,11 @@
Include_dirs []string
Local_include_dirs []string
}
+ Dist struct {
+ Targets []string
+ Dest *string
+ Dir *string
+ }
}{}
sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
@@ -523,15 +537,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 +557,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 +588,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)
}
@@ -813,42 +830,89 @@
// List of shared java libs that this module has dependencies to
Libs []string
+
+ // The stub sources.
+ Stub_srcs []string `android:"path"`
+
+ // The current.txt
+ Current_api string `android:"path"`
+
+ // The removed.txt
+ Removed_api string `android:"path"`
}
type sdkLibraryImportProperties struct {
// List of shared java libs, common to all scopes, that this module has
// dependencies to
Libs []string
-
- // Properties associated with the public api scope.
- Public sdkLibraryScopeProperties
-
- // Properties associated with the system api scope.
- System sdkLibraryScopeProperties
-
- // Properties associated with the test api scope.
- Test sdkLibraryScopeProperties
}
type sdkLibraryImport struct {
android.ModuleBase
android.DefaultableModuleBase
prebuilt android.Prebuilt
+ android.ApexModuleBase
+ android.SdkBase
properties sdkLibraryImportProperties
+ // Map from api scope to the scope specific property structure.
+ scopeProperties map[*apiScope]*sdkLibraryScopeProperties
+
commonToSdkLibraryAndImport
}
var _ SdkLibraryDependency = (*sdkLibraryImport)(nil)
+// The type of a structure that contains a field of type sdkLibraryScopeProperties
+// for each apiscope in allApiScopes, e.g. something like:
+// struct {
+// Public sdkLibraryScopeProperties
+// System sdkLibraryScopeProperties
+// ...
+// }
+var allScopeStructType = createAllScopePropertiesStructType()
+
+// Dynamically create a structure type for each apiscope in allApiScopes.
+func createAllScopePropertiesStructType() reflect.Type {
+ var fields []reflect.StructField
+ for _, apiScope := range allApiScopes {
+ field := reflect.StructField{
+ Name: apiScope.fieldName,
+ Type: reflect.TypeOf(sdkLibraryScopeProperties{}),
+ }
+ fields = append(fields, field)
+ }
+
+ return reflect.StructOf(fields)
+}
+
+// Create an instance of the scope specific structure type and return a map
+// from apiscope to a pointer to each scope specific field.
+func createPropertiesInstance() (interface{}, map[*apiScope]*sdkLibraryScopeProperties) {
+ allScopePropertiesPtr := reflect.New(allScopeStructType)
+ allScopePropertiesStruct := allScopePropertiesPtr.Elem()
+ scopeProperties := make(map[*apiScope]*sdkLibraryScopeProperties)
+
+ for _, apiScope := range allApiScopes {
+ field := allScopePropertiesStruct.FieldByName(apiScope.fieldName)
+ scopeProperties[apiScope] = field.Addr().Interface().(*sdkLibraryScopeProperties)
+ }
+
+ return allScopePropertiesPtr.Interface(), scopeProperties
+}
+
// java_sdk_library_import imports a prebuilt java_sdk_library.
func sdkLibraryImportFactory() android.Module {
module := &sdkLibraryImport{}
- module.AddProperties(&module.properties)
+ allScopeProperties, scopeToProperties := createPropertiesInstance()
+ module.scopeProperties = scopeToProperties
+ module.AddProperties(&module.properties, allScopeProperties)
android.InitPrebuiltModule(module, &[]string{""})
+ android.InitApexModule(module)
+ android.InitSdkAwareModule(module)
InitJavaModule(module, android.HostAndDeviceSupported)
android.AddLoadHook(module, func(mctx android.LoadHookContext) { module.createInternalModules(mctx) })
@@ -870,48 +934,14 @@
module.prebuilt.ForcePrefer()
}
- for apiScope, scopeProperties := range module.scopeProperties() {
+ for apiScope, scopeProperties := range module.scopeProperties {
if len(scopeProperties.Jars) == 0 {
continue
}
- // Creates a java import for the jar with ".stubs" suffix
- props := struct {
- Name *string
- Soc_specific *bool
- Device_specific *bool
- Product_specific *bool
- System_ext_specific *bool
- Sdk_version *string
- Libs []string
- Jars []string
- Prefer *bool
- }{}
+ module.createJavaImportForStubs(mctx, apiScope, scopeProperties)
- props.Name = proptools.StringPtr(apiScope.stubsModuleName(module.BaseModuleName()))
- props.Sdk_version = scopeProperties.Sdk_version
- // Prepend any of the libs from the legacy public properties to the libs for each of the
- // scopes to avoid having to duplicate them in each scope.
- props.Libs = append(module.properties.Libs, scopeProperties.Libs...)
- props.Jars = scopeProperties.Jars
-
- if module.SocSpecific() {
- props.Soc_specific = proptools.BoolPtr(true)
- } else if module.DeviceSpecific() {
- props.Device_specific = proptools.BoolPtr(true)
- } else if module.ProductSpecific() {
- props.Product_specific = proptools.BoolPtr(true)
- } else if module.SystemExtSpecific() {
- props.System_ext_specific = proptools.BoolPtr(true)
- }
-
- // If the build should use prebuilt sdks then set prefer to true on the stubs library.
- // That will cause the prebuilt version of the stubs to override the source version.
- if mctx.Config().UnbundledBuildUsePrebuiltSdks() {
- props.Prefer = proptools.BoolPtr(true)
- }
-
- mctx.CreateModule(ImportFactory, &props)
+ module.createPrebuiltStubsSources(mctx, apiScope, scopeProperties)
}
javaSdkLibraries := javaSdkLibraries(mctx.Config())
@@ -920,16 +950,54 @@
*javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
}
-func (module *sdkLibraryImport) scopeProperties() map[*apiScope]*sdkLibraryScopeProperties {
- p := make(map[*apiScope]*sdkLibraryScopeProperties)
- p[apiScopePublic] = &module.properties.Public
- p[apiScopeSystem] = &module.properties.System
- p[apiScopeTest] = &module.properties.Test
- return p
+func (module *sdkLibraryImport) createJavaImportForStubs(mctx android.LoadHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
+ // Creates a java import for the jar with ".stubs" suffix
+ props := struct {
+ Name *string
+ Soc_specific *bool
+ Device_specific *bool
+ Product_specific *bool
+ System_ext_specific *bool
+ Sdk_version *string
+ Libs []string
+ Jars []string
+ Prefer *bool
+ }{}
+ props.Name = proptools.StringPtr(apiScope.stubsModuleName(module.BaseModuleName()))
+ props.Sdk_version = scopeProperties.Sdk_version
+ // Prepend any of the libs from the legacy public properties to the libs for each of the
+ // scopes to avoid having to duplicate them in each scope.
+ props.Libs = append(module.properties.Libs, scopeProperties.Libs...)
+ props.Jars = scopeProperties.Jars
+ if module.SocSpecific() {
+ props.Soc_specific = proptools.BoolPtr(true)
+ } else if module.DeviceSpecific() {
+ props.Device_specific = proptools.BoolPtr(true)
+ } else if module.ProductSpecific() {
+ props.Product_specific = proptools.BoolPtr(true)
+ } else if module.SystemExtSpecific() {
+ props.System_ext_specific = proptools.BoolPtr(true)
+ }
+ // If the build should use prebuilt sdks then set prefer to true on the stubs library.
+ // That will cause the prebuilt version of the stubs to override the source version.
+ if mctx.Config().UnbundledBuildUsePrebuiltSdks() {
+ props.Prefer = proptools.BoolPtr(true)
+ }
+ mctx.CreateModule(ImportFactory, &props)
+}
+
+func (module *sdkLibraryImport) createPrebuiltStubsSources(mctx android.LoadHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
+ props := struct {
+ Name *string
+ Srcs []string
+ }{}
+ props.Name = proptools.StringPtr(apiScope.docsModuleName(module.BaseModuleName()))
+ props.Srcs = scopeProperties.Stub_srcs
+ mctx.CreateModule(PrebuiltStubsSourcesFactory, &props)
}
func (module *sdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) {
- for apiScope, scopeProperties := range module.scopeProperties() {
+ for apiScope, scopeProperties := range module.scopeProperties {
if len(scopeProperties.Jars) == 0 {
continue
}
@@ -1096,3 +1164,110 @@
},
}}
}
+
+type sdkLibrarySdkMemberType struct {
+ android.SdkMemberTypeBase
+}
+
+func (s *sdkLibrarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
+ mctx.AddVariationDependencies(nil, dependencyTag, names...)
+}
+
+func (s *sdkLibrarySdkMemberType) IsInstance(module android.Module) bool {
+ _, ok := module.(*SdkLibrary)
+ return ok
+}
+
+func (s *sdkLibrarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
+ return ctx.SnapshotBuilder().AddPrebuiltModule(member, "java_sdk_library_import")
+}
+
+func (s *sdkLibrarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
+ return &sdkLibrarySdkMemberProperties{}
+}
+
+type sdkLibrarySdkMemberProperties struct {
+ android.SdkMemberPropertiesBase
+
+ // Scope to per scope properties.
+ Scopes map[*apiScope]scopeProperties
+
+ // Additional libraries that the exported stubs libraries depend upon.
+ Libs []string
+
+ // The Java stubs source files.
+ Stub_srcs []string
+}
+
+type scopeProperties struct {
+ Jars android.Paths
+ StubsSrcJar android.Path
+ CurrentApiFile android.Path
+ RemovedApiFile android.Path
+ SdkVersion string
+}
+
+func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
+ sdk := variant.(*SdkLibrary)
+
+ s.Scopes = make(map[*apiScope]scopeProperties)
+ for _, apiScope := range allApiScopes {
+ paths := sdk.getScopePaths(apiScope)
+ jars := paths.stubsImplPath
+ if len(jars) > 0 {
+ properties := scopeProperties{}
+ properties.Jars = jars
+ properties.SdkVersion = apiScope.sdkVersion
+ properties.StubsSrcJar = paths.stubsSrcJar
+ properties.CurrentApiFile = paths.currentApiFilePath
+ properties.RemovedApiFile = paths.removedApiFilePath
+ s.Scopes[apiScope] = properties
+ }
+ }
+
+ s.Libs = sdk.properties.Libs
+}
+
+func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
+ for _, apiScope := range allApiScopes {
+ if properties, ok := s.Scopes[apiScope]; ok {
+ scopeSet := propertySet.AddPropertySet(apiScope.name)
+
+ scopeDir := filepath.Join("sdk_library", s.OsPrefix(), apiScope.name)
+
+ var jars []string
+ for _, p := range properties.Jars {
+ dest := filepath.Join(scopeDir, ctx.Name()+"-stubs.jar")
+ ctx.SnapshotBuilder().CopyToSnapshot(p, dest)
+ jars = append(jars, dest)
+ }
+ scopeSet.AddProperty("jars", jars)
+
+ // Merge the stubs source jar into the snapshot zip so that when it is unpacked
+ // the source files are also unpacked.
+ snapshotRelativeDir := filepath.Join(scopeDir, ctx.Name()+"_stub_sources")
+ ctx.SnapshotBuilder().UnzipToSnapshot(properties.StubsSrcJar, snapshotRelativeDir)
+ scopeSet.AddProperty("stub_srcs", []string{snapshotRelativeDir})
+
+ if properties.CurrentApiFile != nil {
+ currentApiSnapshotPath := filepath.Join(scopeDir, ctx.Name()+".txt")
+ ctx.SnapshotBuilder().CopyToSnapshot(properties.CurrentApiFile, currentApiSnapshotPath)
+ scopeSet.AddProperty("current_api", currentApiSnapshotPath)
+ }
+
+ if properties.RemovedApiFile != nil {
+ removedApiSnapshotPath := filepath.Join(scopeDir, ctx.Name()+"-removed.txt")
+ ctx.SnapshotBuilder().CopyToSnapshot(properties.CurrentApiFile, removedApiSnapshotPath)
+ scopeSet.AddProperty("removed_api", removedApiSnapshotPath)
+ }
+
+ if properties.SdkVersion != "" {
+ scopeSet.AddProperty("sdk_version", properties.SdkVersion)
+ }
+ }
+ }
+
+ if len(s.Libs) > 0 {
+ propertySet.AddPropertyWithTag("libs", s.Libs, ctx.SnapshotBuilder().SdkMemberReferencePropertyTag(false))
+ }
+}
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/config/arm64_device.go b/rust/config/arm64_device.go
index 60796d8..180fd8b 100644
--- a/rust/config/arm64_device.go
+++ b/rust/config/arm64_device.go
@@ -27,7 +27,6 @@
"-Wl,--icf=safe",
"-Wl,-z,max-page-size=4096",
- "-Wl,--execute-only",
"-Wl,-z,separate-code",
}
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/rust/rust.go b/rust/rust.go
index f446ef0..6fe8871 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -164,6 +164,10 @@
return false
}
+func (mod *Module) UseSdk() bool {
+ return false
+}
+
func (mod *Module) UseVndk() bool {
return false
}
@@ -184,6 +188,10 @@
return ""
}
+func (mod *Module) AlwaysSdk() bool {
+ return false
+}
+
func (mod *Module) ToolchainLibrary() bool {
return false
}
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..c0ad35c 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -24,7 +24,51 @@
fs := map[string][]byte{
"Test.java": nil,
"aidl/foo/bar/Test.aidl": nil,
+
+ // For java_sdk_library
+ "api/current.txt": nil,
+ "api/removed.txt": nil,
+ "api/system-current.txt": nil,
+ "api/system-removed.txt": nil,
+ "api/test-current.txt": nil,
+ "api/test-removed.txt": nil,
+ "build/soong/scripts/gen-java-current-api-files.sh": nil,
}
+
+ // for java_sdk_library tests
+ bp = `
+java_system_modules_import {
+ name: "core-current-stubs-system-modules",
+}
+java_system_modules_import {
+ name: "core-platform-api-stubs-system-modules",
+}
+java_import {
+ name: "core.platform.api.stubs",
+}
+java_sdk_library_import {
+ name: "android_stubs_current",
+}
+java_sdk_library_import {
+ name: "android_system_stubs_current",
+}
+java_sdk_library_import {
+ name: "android_test_stubs_current",
+}
+java_import {
+ name: "core-lambda-stubs",
+ sdk_version: "none",
+}
+java_import {
+ name: "ext",
+ sdk_version: "none",
+}
+java_import {
+ name: "framework",
+ sdk_version: "none",
+}
+` + bp
+
return testSdkWithFs(t, bp, fs)
}
@@ -53,30 +97,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 {
@@ -592,7 +624,7 @@
`),
checkAllCopyRules(""),
- checkMergeZip(".intermediates/myexports/common_os/tmp/java/myjavaapistubs_stubs_sources.zip"),
+ checkMergeZips(".intermediates/myexports/common_os/tmp/java/myjavaapistubs_stubs_sources.zip"),
)
}
@@ -646,7 +678,7 @@
}
`),
checkAllCopyRules(""),
- checkMergeZip(".intermediates/myexports/common_os/tmp/java/myjavaapistubs_stubs_sources.zip"),
+ checkMergeZips(".intermediates/myexports/common_os/tmp/java/myjavaapistubs_stubs_sources.zip"),
)
}
@@ -939,3 +971,99 @@
`),
)
}
+
+func TestSnapshotWithJavaSdkLibrary(t *testing.T) {
+ result := testSdkWithJava(t, `
+ sdk {
+ name: "mysdk",
+ java_sdk_libs: ["myjavalib"],
+ }
+
+ java_sdk_library {
+ name: "myjavalib",
+ apex_available: ["//apex_available:anyapex"],
+ srcs: ["Test.java"],
+ sdk_version: "current",
+ }
+ `)
+
+ result.CheckSnapshot("mysdk", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_sdk_library_import {
+ name: "mysdk_myjavalib@current",
+ sdk_member_name: "myjavalib",
+ apex_available: ["//apex_available:anyapex"],
+ public: {
+ jars: ["sdk_library/public/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ current_api: "sdk_library/public/myjavalib.txt",
+ removed_api: "sdk_library/public/myjavalib-removed.txt",
+ sdk_version: "current",
+ },
+ system: {
+ jars: ["sdk_library/system/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
+ current_api: "sdk_library/system/myjavalib.txt",
+ removed_api: "sdk_library/system/myjavalib-removed.txt",
+ sdk_version: "system_current",
+ },
+ test: {
+ jars: ["sdk_library/test/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/test/myjavalib_stub_sources"],
+ current_api: "sdk_library/test/myjavalib.txt",
+ removed_api: "sdk_library/test/myjavalib-removed.txt",
+ sdk_version: "test_current",
+ },
+}
+
+java_sdk_library_import {
+ name: "myjavalib",
+ prefer: false,
+ apex_available: ["//apex_available:anyapex"],
+ public: {
+ jars: ["sdk_library/public/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ current_api: "sdk_library/public/myjavalib.txt",
+ removed_api: "sdk_library/public/myjavalib-removed.txt",
+ sdk_version: "current",
+ },
+ system: {
+ jars: ["sdk_library/system/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
+ current_api: "sdk_library/system/myjavalib.txt",
+ removed_api: "sdk_library/system/myjavalib-removed.txt",
+ sdk_version: "system_current",
+ },
+ test: {
+ jars: ["sdk_library/test/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/test/myjavalib_stub_sources"],
+ current_api: "sdk_library/test/myjavalib.txt",
+ removed_api: "sdk_library/test/myjavalib-removed.txt",
+ sdk_version: "test_current",
+ },
+}
+
+sdk_snapshot {
+ name: "mysdk@current",
+ java_sdk_libs: ["mysdk_myjavalib@current"],
+}
+`),
+ checkAllCopyRules(`
+.intermediates/myjavalib.stubs/android_common/javac/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.system/android_common/javac/myjavalib.stubs.system.jar -> sdk_library/system/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib.txt
+.intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.test/android_common/javac/myjavalib.stubs.test.jar -> sdk_library/test/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source.test/android_common/myjavalib.stubs.source.test_api.txt -> sdk_library/test/myjavalib.txt
+.intermediates/myjavalib.stubs.source.test/android_common/myjavalib.stubs.source.test_api.txt -> sdk_library/test/myjavalib-removed.txt
+`),
+ checkMergeZips(
+ ".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
+ ".intermediates/mysdk/common_os/tmp/sdk_library/system/myjavalib_stub_sources.zip",
+ ".intermediates/mysdk/common_os/tmp/sdk_library/test/myjavalib_stub_sources.zip"),
+ )
+}
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/sdk/testing.go b/sdk/testing.go
index 00245ce..9e27201 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -90,6 +90,7 @@
// from java package
java.RegisterJavaBuildComponents(ctx)
java.RegisterAppBuildComponents(ctx)
+ java.RegisterSdkLibraryBuildComponents(ctx)
java.RegisterStubsBuildComponents(ctx)
java.RegisterSystemModulesBuildComponents(ctx)
@@ -338,14 +339,15 @@
}
}
-// Check that the specified path is in the list of zips to merge with the intermediate zip.
-func checkMergeZip(expected string) snapshotBuildInfoChecker {
+// Check that the specified paths match the list of zips to merge with the intermediate zip.
+func checkMergeZips(expected ...string) snapshotBuildInfoChecker {
return func(info *snapshotBuildInfo) {
info.r.t.Helper()
if info.intermediateZip == "" {
info.r.t.Errorf("No intermediate zip file was created")
}
- ensureListContains(info.r.t, info.mergeZips, expected)
+
+ info.r.AssertDeepEquals("mismatching merge zip files", expected, info.mergeZips)
}
}
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index 95d049a..0bcdccb 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -99,6 +99,7 @@
hostOut("sdk_addon"),
hostOut("testcases"),
hostOut("vts"),
+ hostOut("vts10"),
hostOut("vts-core"),
productOut("*.img"),
productOut("*.zip"),
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())