summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp18
-rw-r--r--OWNERS1
-rw-r--r--README.md12
-rw-r--r--android/apex.go25
-rw-r--r--android/api_levels.go2
-rw-r--r--android/config.go16
-rw-r--r--android/module.go20
-rw-r--r--android/mutator.go2
-rw-r--r--android/neverallow.go82
-rw-r--r--android/neverallow_test.go64
-rw-r--r--android/prebuilt.go6
-rw-r--r--android/sdk.go15
-rw-r--r--android/soong_config_modules.go24
-rw-r--r--android/soong_config_modules_test.go7
-rw-r--r--android/soongconfig/modules.go108
-rw-r--r--android/variable.go4
-rw-r--r--apex/apex.go79
-rw-r--r--apex/apex_test.go214
-rw-r--r--apex/vndk.go16
-rw-r--r--apex/vndk_test.go55
-rw-r--r--cc/androidmk.go30
-rw-r--r--cc/builder.go49
-rw-r--r--cc/cc.go64
-rw-r--r--cc/config/arm64_device.go2
-rw-r--r--cc/config/clang.go2
-rw-r--r--cc/config/global.go17
-rw-r--r--cc/config/x86_windows_host.go5
-rw-r--r--cc/genrule.go1
-rw-r--r--cc/installer.go4
-rw-r--r--cc/library.go18
-rw-r--r--cc/library_sdk_member.go8
-rw-r--r--cc/linkable.go2
-rw-r--r--cc/linker.go11
-rw-r--r--cc/llndk_library.go2
-rw-r--r--cc/ndk_library.go3
-rw-r--r--cc/ndk_prebuilt.go12
-rw-r--r--cc/prebuilt.go54
-rw-r--r--cc/prebuilt_test.go53
-rw-r--r--cc/sdk.go65
-rw-r--r--cc/sdk_test.go102
-rw-r--r--cc/stl.go6
-rw-r--r--cc/testing.go15
-rw-r--r--cc/tidy.go4
-rw-r--r--cc/toolchain_library.go1
-rw-r--r--cc/vndk.go13
-rw-r--r--cmd/zipsync/zipsync.go2
-rw-r--r--docs/map_files.md174
-rw-r--r--java/androidmk.go15
-rwxr-xr-xjava/app.go47
-rw-r--r--java/app_test.go152
-rw-r--r--java/dexpreopt_bootjars.go71
-rw-r--r--java/dexpreopt_bootjars_test.go2
-rw-r--r--java/dexpreopt_config.go2
-rw-r--r--java/droiddoc.go64
-rw-r--r--java/java.go36
-rw-r--r--java/prebuilt_apis.go28
-rw-r--r--java/sdk.go21
-rw-r--r--java/sdk_library.go325
-rw-r--r--remoteexec/remoteexec.go155
-rw-r--r--remoteexec/remoteexec_test.go83
-rw-r--r--rust/compiler.go5
-rw-r--r--rust/config/arm64_device.go1
-rw-r--r--rust/library.go2
-rw-r--r--rust/rust.go8
-rw-r--r--sdk/cc_sdk_test.go2
-rw-r--r--sdk/java_sdk_test.go156
-rw-r--r--sdk/sdk.go20
-rw-r--r--sdk/testing.go8
-rw-r--r--ui/build/dumpvars.go1
-rw-r--r--ui/build/sandbox_linux.go35
-rw-r--r--ui/metrics/Android.bp9
-rwxr-xr-xui/metrics/upload_proto/regen.sh17
-rw-r--r--ui/metrics/upload_proto/upload.pb.go122
-rw-r--r--ui/metrics/upload_proto/upload.proto35
74 files changed, 2587 insertions, 324 deletions
diff --git a/Android.bp b/Android.bp
index 9c2bb4366..97233f555 100644
--- a/Android.bp
+++ b/Android.bp
@@ -132,6 +132,7 @@ bootstrap_go_package {
pkgPath: "android/soong/cc/config",
deps: [
"soong-android",
+ "soong-remoteexec",
],
srcs: [
"cc/config/clang.go",
@@ -186,6 +187,7 @@ bootstrap_go_package {
"cc/rs.go",
"cc/sanitize.go",
"cc/sabi.go",
+ "cc/sdk.go",
"cc/snapshot_utils.go",
"cc/stl.go",
"cc/strip.go",
@@ -546,6 +548,22 @@ bootstrap_go_package {
pluginFor: ["soong_build"],
}
+bootstrap_go_package {
+ name: "soong-remoteexec",
+ pkgPath: "android/soong/remoteexec",
+ deps: [
+ "blueprint",
+ "soong-android",
+ ],
+ srcs: [
+ "remoteexec/remoteexec.go",
+ ],
+ testSrcs: [
+ "remoteexec/remoteexec_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
+
//
// Defaults to enable various configurations of host bionic
//
diff --git a/OWNERS b/OWNERS
index 4ae045d04..e1db45940 100644
--- a/OWNERS
+++ b/OWNERS
@@ -4,3 +4,4 @@ per-file ndk_*.go, *gen_stub_libs.py = danalbert@google.com
per-file clang.go,global.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
per-file tidy.go = srhines@google.com, chh@google.com
per-file lto.go,pgo.go = srhines@google.com, pirama@google.com, yikong@google.com
+per-file docs/map_files.md = danalbert@google.com, enh@google.com, jiyong@google.com
diff --git a/README.md b/README.md
index 3eac87b1f..8b028a81a 100644
--- a/README.md
+++ b/README.md
@@ -421,6 +421,7 @@ soong_config_module_type {
config_namespace: "acme",
variables: ["board"],
bool_variables: ["feature"],
+ value_variables: ["width"],
properties: ["cflags", "srcs"],
}
@@ -431,8 +432,9 @@ soong_config_string_variable {
```
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:
```
@@ -443,6 +445,7 @@ SOONG_CONFIG_acme += \
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
@@ -471,6 +474,9 @@ acme_cc_defaults {
feature: {
cflags: ["-DFEATURE"],
},
+ width: {
+ cflags: ["-DWIDTH=%s"],
+ },
},
}
@@ -482,7 +488,7 @@ cc_library {
```
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 cbaf1c71a..9bf6fc717 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -19,6 +19,8 @@ import (
"sort"
"strconv"
"sync"
+
+ "github.com/google/blueprint"
)
const (
@@ -32,6 +34,14 @@ type ApexInfo struct {
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 @@ type ApexInfo struct {
// respectively.
type ApexModule interface {
Module
+ DepIsInSameApex
+
apexModuleBase() *ApexModuleBase
// Marks that this module should be built for the specified APEXes.
@@ -88,10 +100,6 @@ type ApexModule interface {
// 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 <= maxSdkVersion.
// For example, with maxSdkVersion is 10 and versionList is [9,11]
// it returns 9 as string
@@ -111,6 +119,15 @@ type ApexProperties struct {
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 {
diff --git a/android/api_levels.go b/android/api_levels.go
index 4f6efee70..4b7a8fd9d 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -73,7 +73,7 @@ func getApiLevelsMap(config Config) map[string]int {
"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 558c828e0..c297b0597 100644
--- a/android/config.go
+++ b/android/config.go
@@ -652,22 +652,6 @@ func (c *config) PlatformVersionActiveCodenames() []string {
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/module.go b/android/module.go
index 80f477b04..02b2c8926 100644
--- a/android/module.go
+++ b/android/module.go
@@ -128,6 +128,13 @@ type BaseModuleContext interface {
// 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 @@ type Module interface {
InstallBypassMake() bool
InstallForceOS() *OsType
SkipInstall()
+ IsSkipInstall() bool
ExportedToMake() bool
InitRc() Paths
VintfFragments() Paths
@@ -943,6 +951,10 @@ func (m *ModuleBase) SkipInstall() {
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 @@ type baseModuleContext struct {
debug bool
walkPath []Module
+ tagPath []blueprint.DependencyTag
strictVisitDeps bool // If true, enforce that all dependencies are enabled
}
@@ -1696,6 +1709,7 @@ func (b *baseModuleContext) WalkDepsBlueprint(visit func(blueprint.Module, bluep
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)
@@ -1703,8 +1717,10 @@ func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
// 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
@@ -1716,6 +1732,10 @@ func (b *baseModuleContext) GetWalkPath() []Module {
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/mutator.go b/android/mutator.go
index a46d4beb1..10a815ae4 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -103,7 +103,7 @@ var postDeps = []RegisterMutatorFunc{
registerPathDepsMutator,
RegisterPrebuiltsPostDepsMutators,
RegisterVisibilityRuleEnforcer,
- registerNeverallowMutator,
+ RegisterNeverallowMutator,
RegisterOverridePostDepsMutators,
}
diff --git a/android/neverallow.go b/android/neverallow.go
index 8fcfb8a6e..cf09792e0 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -17,6 +17,7 @@ package android
import (
"path/filepath"
"reflect"
+ "regexp"
"strconv"
"strings"
@@ -41,7 +42,7 @@ import (
// counts as a match
// - it has none of the "Without" properties matched (same rules as above)
-func registerNeverallowMutator(ctx RegisterMutatorsContext) {
+func RegisterNeverallowMutator(ctx RegisterMutatorsContext) {
ctx.BottomUp("neverallow", neverallowMutator).Parallel()
}
@@ -53,6 +54,7 @@ func init() {
AddNeverAllowRules(createLibcoreRules()...)
AddNeverAllowRules(createMediaRules()...)
AddNeverAllowRules(createJavaDeviceForHostRules()...)
+ AddNeverAllowRules(createCcSdkVariantRules()...)
}
// Add a NeverAllow rule to the set of rules to apply.
@@ -146,7 +148,8 @@ func createLibcoreRules() []Rule {
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 createJavaDeviceForHostRules() []Rule {
}
}
+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 {
@@ -213,7 +247,7 @@ func neverallowMutator(ctx BottomUpMutatorContext) {
}
type ValueMatcher interface {
- test(string) bool
+ Test(string) bool
String() string
}
@@ -221,7 +255,7 @@ type equalMatcher struct {
expected string
}
-func (m *equalMatcher) test(value string) bool {
+func (m *equalMatcher) Test(value string) bool {
return m.expected == value
}
@@ -232,7 +266,7 @@ func (m *equalMatcher) String() string {
type anyMatcher struct {
}
-func (m *anyMatcher) test(value string) bool {
+func (m *anyMatcher) Test(value string) bool {
return true
}
@@ -246,7 +280,7 @@ type startsWithMatcher struct {
prefix string
}
-func (m *startsWithMatcher) test(value string) bool {
+func (m *startsWithMatcher) Test(value string) bool {
return strings.HasPrefix(value, m.prefix)
}
@@ -254,6 +288,30 @@ func (m *startsWithMatcher) String() string {
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 @@ func StartsWith(prefix string) ValueMatcher {
return &startsWithMatcher{prefix}
}
+func Regexp(re string) ValueMatcher {
+ r, err := regexp.Compile(re)
+ if err != nil {
+ panic(err)
+ }
+ return &regexMatcher{r}
+}
+
// assorted utils
func cleanPaths(paths []string) []string {
@@ -507,7 +573,7 @@ func hasProperty(properties []interface{}, prop ruleProperty) bool {
}
check := func(value string) bool {
- return prop.matcher.test(value)
+ return prop.matcher.Test(value)
}
if matchValue(propertiesValue, check) {
@@ -564,6 +630,6 @@ func neverallowRules(config Config) []Rule {
// Overrides the default neverallow rules for the supplied config.
//
// For testing only.
-func setTestNeverallowRules(config Config, testRules []Rule) {
+func SetTestNeverallowRules(config Config, testRules []Rule) {
config.Once(neverallowRulesKey, func() interface{} { return testRules })
}
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 6f07a4a73..2fc42e31f 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -227,6 +227,16 @@ var neverallowTests = []struct {
},
},
{
+ 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 @@ var neverallowTests = []struct {
}`),
},
},
+ // 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) {
@@ -259,7 +313,7 @@ func TestNeverallow(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
// If the test has its own rules then use them instead of the default ones.
if test.rules != nil {
- setTestNeverallowRules(config, test.rules)
+ SetTestNeverallowRules(config, test.rules)
}
_, errs := testNeverallow(config)
CheckErrorsAgainstExpectations(t, errs, test.expectedErrors)
@@ -273,7 +327,7 @@ func testNeverallow(config Config) (*TestContext, []error) {
ctx.RegisterModuleType("java_library", newMockJavaLibraryModule)
ctx.RegisterModuleType("java_library_host", newMockJavaLibraryModule)
ctx.RegisterModuleType("java_device_for_host", newMockJavaLibraryModule)
- ctx.PostDepsMutators(registerNeverallowMutator)
+ ctx.PostDepsMutators(RegisterNeverallowMutator)
ctx.Register(config)
_, errs := ctx.ParseBlueprintsFiles("Android.bp")
@@ -289,6 +343,8 @@ type mockCcLibraryProperties struct {
Include_dirs []string
Vendor_available *bool
Static_libs []string
+ Sdk_version *string
+ Sdk_variant_only *bool
Vndk struct {
Enabled *bool
@@ -305,6 +361,10 @@ type mockCcLibraryProperties struct {
Cflags []string
}
}
+
+ Platform struct {
+ Shared_libs []string
+ }
}
type mockCcLibraryModule struct {
diff --git a/android/prebuilt.go b/android/prebuilt.go
index c902ec826..82745a498 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -39,6 +39,12 @@ var PrebuiltDepTag prebuiltDependencyTag
// 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/sdk.go b/android/sdk.go
index 66094cda0..6f62f552c 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -22,17 +22,30 @@ import (
"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/soong_config_modules.go b/android/soong_config_modules.go
index fa1e20448..619cf8615 100644
--- a/android/soong_config_modules.go
+++ b/android/soong_config_modules.go
@@ -73,6 +73,9 @@ type soongConfigModuleTypeImportProperties struct {
// feature: {
// cflags: ["-DFEATURE"],
// },
+// width: {
+// cflags: ["-DWIDTH=%s"],
+// },
// },
// }
//
@@ -90,6 +93,7 @@ type soongConfigModuleTypeImportProperties struct {
// config_namespace: "acme",
// variables: ["board"],
// bool_variables: ["feature"],
+// value_variables: ["width"],
// properties: ["cflags", "srcs"],
// }
//
@@ -107,8 +111,9 @@ type soongConfigModuleTypeImportProperties struct {
//
// 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{}
@@ -122,7 +127,10 @@ func soongConfigModuleTypeImportFactory() Module {
}
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() {}
@@ -148,6 +156,7 @@ type soongConfigModuleTypeModule struct {
// config_namespace: "acme",
// variables: ["board"],
// bool_variables: ["feature"],
+// value_variables: ["width"],
// properties: ["cflags", "srcs"],
// }
//
@@ -171,6 +180,9 @@ type soongConfigModuleTypeModule struct {
// feature: {
// cflags: ["-DFEATURE"],
// },
+// width: {
+// cflags: ["-DWIDTH=%s"],
+// },
// },
// }
//
@@ -189,6 +201,7 @@ type soongConfigModuleTypeModule struct {
//
// 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 {
@@ -349,7 +362,12 @@ func soongConfigModuleFactory(factory blueprint.ModuleFactory,
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 1cf060dc0..f905b1ab2 100644
--- a/android/soong_config_modules_test.go
+++ b/android/soong_config_modules_test.go
@@ -45,6 +45,7 @@ func TestSoongConfigModule(t *testing.T) {
config_namespace: "acme",
variables: ["board", "feature1", "FEATURE3"],
bool_variables: ["feature2"],
+ value_variables: ["size"],
properties: ["cflags", "srcs"],
}
@@ -82,6 +83,9 @@ func TestSoongConfigModule(t *testing.T) {
cflags: ["-DSOC_B"],
},
},
+ size: {
+ cflags: ["-DSIZE=%s"],
+ },
feature1: {
cflags: ["-DFEATURE1"],
},
@@ -101,6 +105,7 @@ func TestSoongConfigModule(t *testing.T) {
config.TestProductVariables.VendorVars = map[string]map[string]string{
"acme": map[string]string{
"board": "soc_a",
+ "size": "42",
"feature1": "true",
"feature2": "false",
// FEATURE3 unset
@@ -121,7 +126,7 @@ func TestSoongConfigModule(t *testing.T) {
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 2d6063d79..142a81387 100644
--- a/android/soongconfig/modules.go
+++ b/android/soongconfig/modules.go
@@ -112,6 +112,10 @@ type ModuleTypeProperties struct {
// 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
}
@@ -161,6 +165,18 @@ func processModuleTypeDef(v *SoongConfigDefinition, def *parser.Module) (errs []
})
}
+ 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
}
@@ -404,15 +420,17 @@ func typeForPropertyFromPropertyStruct(ps interface{}, property string) reflect.
// 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 {
@@ -438,7 +456,7 @@ type soongConfigVariable interface {
// 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 {
@@ -473,14 +491,14 @@ func (s *stringVariable) initializeProperties(v reflect.Value, typ reflect.Type)
}
}
-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 {
@@ -495,11 +513,83 @@ func (b boolVariable) initializeProperties(v reflect.Value, typ reflect.Type) {
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 612d138c3..3b3916e2f 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -151,7 +151,6 @@ type productVariables struct {
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"`
@@ -255,7 +254,7 @@ type productVariables struct {
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"`
@@ -358,7 +357,6 @@ func (v *productVariables) SetDefaultConfig() {
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/apex/apex.go b/apex/apex.go
index f0eb1dec9..8463ac123 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -18,6 +18,7 @@ import (
"fmt"
"path"
"path/filepath"
+ "regexp"
"sort"
"strconv"
"strings"
@@ -123,7 +124,6 @@ func makeApexAvailableWhitelist() map[string][]string {
"crtbegin_dynamic1",
"crtbegin_so1",
"crtbrand",
- "conscrypt.module.intra.core.api.stubs",
"dex2oat_headers",
"dt_fd_forward_export",
"icu4c_extra_headers",
@@ -305,25 +305,13 @@ func makeApexAvailableWhitelist() map[string][]string {
"android.hidl.memory.token@1.0",
"android.hidl.memory@1.0",
"android.hidl.safe_union@1.0",
- "gemmlowp_headers",
"libarect",
"libbuildversion",
- "libeigen",
- "libfmq",
"libmath",
- "libneuralnetworks_common",
- "libneuralnetworks_headers",
"libprocessgroup",
"libprocessgroup_headers",
"libprocpartition",
"libsync",
- "libtextclassifier_hash",
- "libtextclassifier_hash_headers",
- "libtextclassifier_hash_static",
- "libtflite_kernel_utils",
- "philox_random",
- "philox_random_headers",
- "tensorflow_headers",
}
//
// Module separator
@@ -848,10 +836,13 @@ func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
// Mark the direct and transitive dependencies of apex bundles so that they
// can be built for the apex bundles.
func apexDepsMutator(mctx android.TopDownMutatorContext) {
+ if !mctx.Module().Enabled() {
+ return
+ }
var apexBundles []android.ApexInfo
var directDep bool
if a, ok := mctx.Module().(*apexBundle); ok && !a.vndkApex {
- apexBundles = []android.ApexInfo{android.ApexInfo{
+ apexBundles = []android.ApexInfo{{
ApexName: mctx.ModuleName(),
MinSdkVersion: a.minSdkVersion(mctx),
}}
@@ -865,22 +856,33 @@ func apexDepsMutator(mctx android.TopDownMutatorContext) {
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 !mctx.Module().Enabled() {
+ return
+ }
if am, ok := mctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
am.CreateApexVariations(mctx)
} else if a, ok := mctx.Module().(*apexBundle); ok && !a.vndkApex {
@@ -918,6 +920,9 @@ func addFlattenedFileContextsInfos(ctx android.BaseModuleContext, fileContextsIn
}
func apexFlattenedMutator(mctx android.BottomUpMutatorContext) {
+ if !mctx.Module().Enabled() {
+ return
+ }
if ab, ok := mctx.Module().(*apexBundle); ok {
var variants []string
switch proptools.StringDefault(ab.properties.Payload_type, "image") {
@@ -1811,6 +1816,24 @@ func (a *apexBundle) minSdkVersion(ctx android.BaseModuleContext) int {
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
@@ -1834,12 +1857,23 @@ func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) {
apexName := ctx.ModuleName()
fromName := ctx.OtherModuleName(from)
toName := ctx.OtherModuleName(to)
+
+ // 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.
@@ -1949,6 +1983,9 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// 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 {
@@ -2116,7 +2153,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
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 c5edc3b67..9f55728f2 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -27,6 +27,7 @@ import (
"android/soong/android"
"android/soong/cc"
+ "android/soong/dexpreopt"
"android/soong/java"
)
@@ -158,6 +159,7 @@ func testApexContext(t *testing.T, bp string, handlers ...testCustomizer) (*andr
"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 @@ func TestBasicApex(t *testing.T) {
apex_available: [ "myapex" ],
}
- cc_library {
+ cc_library_shared {
name: "mylib2",
srcs: ["mylib.cpp"],
system_shared_libs: [],
@@ -381,6 +383,16 @@ func TestBasicApex(t *testing.T) {
],
}
+ 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"],
@@ -3384,7 +3396,7 @@ func TestApexWithApps(t *testing.T) {
}
// 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
@@ -3581,12 +3593,12 @@ func TestApexAvailable_DirectDep(t *testing.T) {
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",
@@ -4180,6 +4192,27 @@ func TestApexWithJniLibs(t *testing.T) {
})
}
+func TestApexMutatorsDontRunIfDisabled(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ `, func(fs map[string][]byte, config android.Config) {
+ delete(config.Targets, android.Android)
+ config.AndroidCommonTarget = android.Target{}
+ })
+
+ if expected, got := []string{""}, ctx.ModuleVariantsForTests("myapex"); !reflect.DeepEqual(expected, got) {
+ t.Errorf("Expected variants: %v, but got: %v", expected, got)
+ }
+}
+
func TestApexWithJniLibs_Errors(t *testing.T) {
testApexError(t, `jni_libs: "xxx" is not a cc_library`, `
apex {
@@ -4233,6 +4266,175 @@ func TestAppBundle(t *testing.T) {
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/vndk.go b/apex/vndk.go
index f2e913eb3..f948d7608 100644
--- a/apex/vndk.go
+++ b/apex/vndk.go
@@ -16,6 +16,7 @@ package apex
import (
"path/filepath"
+ "strconv"
"strings"
"sync"
@@ -95,6 +96,10 @@ func apexVndkMutator(mctx android.TopDownMutatorContext) {
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)
@@ -117,10 +122,13 @@ func makeCompatSymlinks(name string, ctx android.ModuleContext) (symlinks []stri
// When all hard-coded references are fixed, remove symbolic links
// Note that we should keep following symlinks for older VNDKs (<=29)
// Since prebuilt vndk libs still depend on system/lib/vndk path
- if strings.HasPrefix(name, vndkApexName) {
- vndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
- if strings.HasPrefix(name, vndkApexNamePrefix) {
- vndkVersion = strings.TrimPrefix(name, vndkApexNamePrefix)
+ if strings.HasPrefix(name, vndkApexNamePrefix) {
+ vndkVersion := strings.TrimPrefix(name, vndkApexNamePrefix)
+ if numVer, err := strconv.Atoi(vndkVersion); err != nil {
+ ctx.ModuleErrorf("apex_vndk should be named as %v<ver:number>: %s", vndkApexNamePrefix, name)
+ return
+ } else if numVer > android.SdkVersion_Android10 {
+ return
}
// the name of vndk apex is formatted "com.android.vndk.v" + version
apexName := vndkApexNamePrefix + vndkVersion
diff --git a/apex/vndk_test.go b/apex/vndk_test.go
index a9e26adc8..523ac2630 100644
--- a/apex/vndk_test.go
+++ b/apex/vndk_test.go
@@ -8,6 +8,59 @@ import (
"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 @@ func TestVndkApexUsesVendorVariant(t *testing.T) {
system_shared_libs: [],
stl: "none",
notice: "custom_notice",
+ sdk_version: "current",
}
cc_library {
name: "libprofile-clang-extras_ndk",
@@ -98,6 +152,7 @@ func TestVndkApexUsesVendorVariant(t *testing.T) {
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/cc/androidmk.go b/cc/androidmk.go
index ef695b003..5438b149d 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -29,6 +29,7 @@ var (
vendorSuffix = ".vendor"
ramdiskSuffix = ".ramdisk"
recoverySuffix = ".recovery"
+ sdkSuffix = ".sdk"
)
type AndroidMkContext interface {
@@ -103,6 +104,28 @@ func (c *Module) AndroidMkEntries() []android.AndroidMkEntries {
}
}
}
+ 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))))")
+ }
},
},
}
@@ -248,6 +271,10 @@ func (library *libraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries
entries.SubName = "." + library.stubsVersion()
}
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ // Note library.skipInstall() has a special case to get here for static
+ // libraries that otherwise would have skipped installation and hence not
+ // have executed AndroidMkEntries at all. The reason is to ensure they get
+ // a NOTICE file make target which other libraries might depend on.
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
if library.buildStubs() {
entries.SetBool("LOCAL_NO_NOTICE_FILE", true)
@@ -393,6 +420,9 @@ func (library *toolchainLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext,
}
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/builder.go b/cc/builder.go
index 136263b41..b583586f3 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -29,6 +29,7 @@ import (
"android/soong/android"
"android/soong/cc/config"
+ "android/soong/remoteexec"
)
const (
@@ -62,7 +63,7 @@ var (
},
"ccCmd", "cFlags")
- ld = pctx.AndroidStaticRule("ld",
+ ld, ldRE = remoteexec.StaticRules(pctx, "ld",
blueprint.RuleParams{
Command: "$ldCmd ${crtBegin} @${out}.rsp " +
"${libFlags} ${crtEnd} -o ${out} ${ldFlags} ${extraLibFlags}",
@@ -72,16 +73,28 @@ var (
// clang -Wl,--out-implib doesn't update its output file if it hasn't changed.
Restat: true,
},
- "ldCmd", "crtBegin", "libFlags", "crtEnd", "ldFlags", "extraLibFlags")
-
- partialLd = pctx.AndroidStaticRule("partialLd",
+ &remoteexec.REParams{Labels: map[string]string{"type": "link", "tool": "clang"},
+ ExecStrategy: "${config.RECXXLinksExecStrategy}",
+ Inputs: []string{"${out}.rsp"},
+ RSPFile: "${out}.rsp",
+ OutputFiles: []string{"${out}"},
+ ToolchainInputs: []string{"$ldCmd"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.RECXXLinksPool}"},
+ }, []string{"ldCmd", "crtBegin", "libFlags", "crtEnd", "ldFlags", "extraLibFlags"}, nil)
+
+ partialLd, partialLdRE = remoteexec.StaticRules(pctx, "partialLd",
blueprint.RuleParams{
// Without -no-pie, clang 7.0 adds -pie to link Android files,
// but -r and -pie cannot be used together.
Command: "$ldCmd -fuse-ld=lld -nostdlib -no-pie -Wl,-r ${in} -o ${out} ${ldFlags}",
CommandDeps: []string{"$ldCmd"},
- },
- "ldCmd", "ldFlags")
+ }, &remoteexec.REParams{
+ Labels: map[string]string{"type": "link", "tool": "clang"},
+ ExecStrategy: "${config.RECXXLinksExecStrategy}", Inputs: []string{"$inCommaList"},
+ OutputFiles: []string{"${out}"},
+ ToolchainInputs: []string{"$ldCmd"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.RECXXLinksPool}"},
+ }, []string{"ldCmd", "ldFlags"}, []string{"inCommaList"})
ar = pctx.AndroidStaticRule("ar",
blueprint.RuleParams{
@@ -262,6 +275,7 @@ func init() {
}
pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
+ pctx.Import("android/soong/remoteexec")
}
type builderFlags struct {
@@ -657,8 +671,13 @@ func TransformObjToDynamicBinary(ctx android.ModuleContext,
deps = append(deps, crtBegin.Path(), crtEnd.Path())
}
+ rule := ld
+ if ctx.Config().IsEnvTrue("RBE_CXX_LINKS") {
+ rule = ldRE
+ }
+
ctx.Build(pctx, android.BuildParams{
- Rule: ld,
+ Rule: rule,
Description: "link " + outputFile.Base(),
Output: outputFile,
ImplicitOutputs: implicitOutputs,
@@ -798,16 +817,22 @@ func TransformObjsToObj(ctx android.ModuleContext, objFiles android.Paths,
ldCmd := "${config.ClangBin}/clang++"
+ rule := partialLd
+ args := map[string]string{
+ "ldCmd": ldCmd,
+ "ldFlags": flags.globalLdFlags + " " + flags.localLdFlags,
+ }
+ if ctx.Config().IsEnvTrue("RBE_CXX_LINKS") {
+ rule = partialLdRE
+ args["inCommaList"] = strings.Join(objFiles.Strings(), ",")
+ }
ctx.Build(pctx, android.BuildParams{
- Rule: partialLd,
+ Rule: rule,
Description: "link " + outputFile.Base(),
Output: outputFile,
Inputs: objFiles,
Implicits: deps,
- Args: map[string]string{
- "ldCmd": ldCmd,
- "ldFlags": flags.globalLdFlags + " " + flags.localLdFlags,
- },
+ Args: args,
})
}
diff --git a/cc/cc.go b/cc/cc.go
index c42914bd1..02014049b 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -42,6 +42,7 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) {
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 @@ type BaseProperties struct {
// 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 @@ type BaseProperties struct {
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 {
@@ -389,6 +404,7 @@ type installer interface {
inSanitizerDir() bool
hostToolPath() android.OptionalPath
relativeInstallPath() string
+ skipInstall(mod *Module)
}
type xref interface {
@@ -530,7 +546,10 @@ func (c *Module) Shared() bool {
}
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 {
@@ -558,6 +577,10 @@ func (c *Module) SdkVersion() string {
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 {
@@ -586,13 +609,6 @@ func (c *Module) GetDepsInLinkOrder() []android.Path {
return c.depsInLinkOrder
}
-func (c *Module) StubsSymbolFile() android.OptionalPath {
- if library, ok := c.linker.(*libraryDecorator); ok {
- return library.stubsSymbolFile
- }
- return android.OptionalPath{}
-}
-
func (c *Module) StubsVersions() []string {
if c.linker != nil {
if library, ok := c.linker.(*libraryDecorator); ok {
@@ -824,6 +840,17 @@ func (c *Module) UseVndk() bool {
return c.Properties.VndkVersion != ""
}
+func (c *Module) canUseSdk() bool {
+ return c.Os() == android.Android && !c.UseVndk() && !c.InRamdisk() && !c.InRecovery()
+}
+
+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
}
@@ -1081,21 +1108,18 @@ func (ctx *moduleContextImpl) header() bool {
}
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
@@ -1407,6 +1431,8 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
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{
@@ -2614,6 +2640,14 @@ func (c *Module) InstallInRecovery() bool {
return c.InRecovery()
}
+func (c *Module) SkipInstall() {
+ if c.installer == nil {
+ c.ModuleBase.SkipInstall()
+ return
+ }
+ c.installer.skipInstall(c)
+}
+
func (c *Module) HostToolPath() android.OptionalPath {
if c.installer == nil {
return android.OptionalPath{}
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 19aedd99d..5575baaab 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -37,10 +37,8 @@ var (
}
arm64Ldflags = []string{
- "-Wl,-m,aarch64_elf64_le_vec",
"-Wl,--hash-style=gnu",
"-Wl,-z,separate-code",
- "-fuse-ld=gold",
"-Wl,--icf=safe",
}
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 274ccd5d5..bdd9030f4 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -80,10 +80,8 @@ var ClangUnknownCflags = sorted([]string{
// Ldflags that should be filtered out when linking with clang lld
var ClangUnknownLldflags = sorted([]string{
- "-fuse-ld=gold",
"-Wl,--fix-cortex-a8",
"-Wl,--no-fix-cortex-a8",
- "-Wl,-m,aarch64_elf64_le_vec",
})
var ClangLibToolingUnknownCflags = sorted([]string{})
diff --git a/cc/config/global.go b/cc/config/global.go
index 29020ab24..d85ac5f6a 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -18,6 +18,7 @@ import (
"strings"
"android/soong/android"
+ "android/soong/remoteexec"
)
var (
@@ -127,8 +128,8 @@ var (
// 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{
@@ -255,6 +256,9 @@ func init() {
}
return ""
})
+
+ pctx.VariableFunc("RECXXLinksPool", envOverrideFunc("RBE_CXX_LINKS_POOL", remoteexec.DefaultPool))
+ pctx.VariableFunc("RECXXLinksExecStrategy", envOverrideFunc("RBE_CXX_LINKS_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
}
var HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
@@ -268,3 +272,12 @@ func bionicHeaders(kernelArch string) string {
"-isystem bionic/libc/kernel/android/uapi",
}, " ")
}
+
+func envOverrideFunc(envVar, defaultVal string) func(ctx android.PackageVarContext) string {
+ return func(ctx android.PackageVarContext) string {
+ if override := ctx.Config().Getenv(envVar); override != "" {
+ return override
+ }
+ return defaultVal
+ }
+}
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index 43e8c85e8..cd0a50837 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -58,8 +58,11 @@ var (
"-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 155e410dc..9331448b8 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -27,6 +27,7 @@ type GenruleExtraProperties struct {
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/installer.go b/cc/installer.go
index 200d59e9f..0b4a68cc8 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -106,3 +106,7 @@ func (installer *baseInstaller) hostToolPath() android.OptionalPath {
func (installer *baseInstaller) relativeInstallPath() string {
return String(installer.Properties.Relative_install_path)
}
+
+func (installer *baseInstaller) skipInstall(mod *Module) {
+ mod.ModuleBase.SkipInstall()
+}
diff --git a/cc/library.go b/cc/library.go
index 26e86f940..94fffb951 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -367,9 +367,6 @@ type libraryDecorator struct {
// Location of the file that should be copied to dist dir when requested
distFile android.OptionalPath
- // stubs.symbol_file
- stubsSymbolFile android.OptionalPath
-
versionScriptPath android.ModuleGenPath
post_install_cmds []string
@@ -606,7 +603,6 @@ func (library *libraryDecorator) shouldCreateSourceAbiDump(ctx ModuleContext) bo
func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
if library.buildStubs() {
- library.stubsSymbolFile = android.OptionalPathForModuleSrc(ctx, library.Properties.Stubs.Symbol_file)
objs, versionScript := compileStubLibrary(ctx, flags, String(library.Properties.Stubs.Symbol_file), library.MutatedProperties.StubsVersion, "--apex")
library.versionScriptPath = versionScript
return objs
@@ -1241,7 +1237,7 @@ func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) {
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())
@@ -1333,6 +1329,18 @@ func (library *libraryDecorator) availableFor(what string) bool {
return android.CheckAvailableForApex(what, list)
}
+func (library *libraryDecorator) skipInstall(mod *Module) {
+ if library.static() && library.buildStatic() && !library.buildStubs() {
+ // If we're asked to skip installation of a static library (in particular
+ // when it's not //apex_available:platform) we still want an AndroidMk entry
+ // for it to ensure we get the relevant NOTICE file targets (cf.
+ // notice_files.mk) that other libraries might depend on. AndroidMkEntries
+ // always sets LOCAL_UNINSTALLABLE_MODULE for these entries.
+ return
+ }
+ mod.ModuleBase.SkipInstall()
+}
+
var versioningMacroNamesListKey = android.NewOnceKey("versioningMacroNamesList")
func versioningMacroNamesList(config android.Config) *map[string]string {
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index 4e4df5b0e..754b96a98 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -271,10 +271,7 @@ func addPossiblyArchSpecificProperties(sdkModuleContext android.ModuleContext, b
}
if len(libInfo.StubsVersion) > 0 {
- symbolFilePath := filepath.Join(nativeEtcDir, libInfo.StubsSymbolFile.Path().Base())
- builder.CopyToSnapshot(libInfo.StubsSymbolFile.Path(), symbolFilePath)
stubsSet := outputProperties.AddPropertySet("stubs")
- stubsSet.AddProperty("symbol_file", symbolFilePath)
stubsSet.AddProperty("versions", []string{libInfo.StubsVersion})
}
}
@@ -283,7 +280,6 @@ const (
nativeIncludeDir = "include"
nativeGeneratedIncludeDir = "include_gen"
nativeStubDir = "lib"
- nativeEtcDir = "etc"
)
// path to the native library. Relative to <sdk_root>/<api_dir>
@@ -348,9 +344,6 @@ type nativeLibInfoProperties struct {
// are not in use.
StubsVersion string
- // The stubs symbol file.
- StubsSymbolFile android.OptionalPath
-
// outputFile is not exported as it is always arch specific.
outputFile android.Path
}
@@ -389,7 +382,6 @@ func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberConte
if ccModule.HasStubsVariants() {
p.StubsVersion = ccModule.StubsVersion()
- p.StubsSymbolFile = ccModule.StubsSymbolFile()
}
}
diff --git a/cc/linkable.go b/cc/linkable.go
index 80cd6b8a2..fbe61a4f4 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -45,12 +45,14 @@ type LinkableInterface interface {
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 f65d7c8d3..57a0c016a 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -158,6 +158,13 @@ type BaseLinkerProperties struct {
// 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 @@ func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
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 09050aa34..7ff20f472 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -83,7 +83,7 @@ func (stub *llndkStubDecorator) compilerFlags(ctx ModuleContext, flags Flags, de
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 2a86d3362..68d4ac067 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -381,6 +381,9 @@ func newStubLibrary() *Module {
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 3a630d2c0..c4d770837 100644
--- a/cc/ndk_prebuilt.go
+++ b/cc/ndk_prebuilt.go
@@ -76,6 +76,8 @@ func NdkPrebuiltObjectFactory() android.Module {
baseLinker: NewBaseLinker(nil),
},
}
+ module.Properties.AlwaysSdk = true
+ module.Properties.Sdk_version = StringPtr("current")
module.Properties.HideFromMake = true
return module.Init()
}
@@ -125,10 +127,9 @@ func NdkPrebuiltSharedStlFactory() android.Module {
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()
}
@@ -145,6 +146,9 @@ func NdkPrebuiltStaticStlFactory() android.Module {
}
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.go b/cc/prebuilt.go
index fc9cc17d3..ac990f35f 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -43,6 +43,11 @@ type prebuiltLinkerProperties struct {
// Check the prebuilt ELF files (e.g. DT_SONAME, DT_NEEDED, resolution of undefined
// symbols, etc), default true.
Check_elf_files *bool
+
+ // Optionally provide an import library if this is a Windows PE DLL prebuilt.
+ // This is needed only if this library is linked by other modules in build time.
+ // Only makes sense for the Windows target.
+ Windows_import_lib *string `android:"path,arch_variant"`
}
type prebuiltLinker struct {
@@ -109,9 +114,16 @@ func (p *prebuiltLibraryLinker) link(ctx ModuleContext,
in := android.PathForModuleSrc(ctx, srcs[0])
+ if p.static() {
+ return in
+ }
+
if p.shared() {
p.unstrippedOutputFile = in
libName := p.libraryDecorator.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
+ outputFile := android.PathForModuleOut(ctx, libName)
+ var implicits android.Paths
+
if p.needsStrip(ctx) {
stripped := android.PathForModuleOut(ctx, "stripped", libName)
p.stripExecutableOrSharedLib(ctx, in, stripped, builderFlags)
@@ -122,10 +134,41 @@ func (p *prebuiltLibraryLinker) link(ctx ModuleContext,
// depending on a table of contents file instead of the library itself.
tocFile := android.PathForModuleOut(ctx, libName+".toc")
p.tocFile = android.OptionalPathForPath(tocFile)
- TransformSharedObjectToToc(ctx, in, tocFile, builderFlags)
- }
+ TransformSharedObjectToToc(ctx, outputFile, tocFile, builderFlags)
+
+ if ctx.Windows() && p.properties.Windows_import_lib != nil {
+ // Consumers of this library actually links to the import library in build
+ // time and dynamically links to the DLL in run time. i.e.
+ // a.exe <-- static link --> foo.lib <-- dynamic link --> foo.dll
+ importLibSrc := android.PathForModuleSrc(ctx, String(p.properties.Windows_import_lib))
+ importLibName := p.libraryDecorator.getLibName(ctx) + ".lib"
+ importLibOutputFile := android.PathForModuleOut(ctx, importLibName)
+ implicits = append(implicits, importLibOutputFile)
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Description: "prebuilt import library",
+ Input: importLibSrc,
+ Output: importLibOutputFile,
+ Args: map[string]string{
+ "cpFlags": "-L",
+ },
+ })
+ }
- return in
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Description: "prebuilt shared library",
+ Implicits: implicits,
+ Input: in,
+ Output: outputFile,
+ Args: map[string]string{
+ "cpFlags": "-L",
+ },
+ })
+
+ return outputFile
+ }
}
return nil
@@ -155,6 +198,10 @@ func (p *prebuiltLibraryLinker) disablePrebuilt() {
p.properties.Srcs = nil
}
+func (p *prebuiltLibraryLinker) skipInstall(mod *Module) {
+ mod.ModuleBase.SkipInstall()
+}
+
func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
module, library := NewLibrary(hod)
module.compiler = nil
@@ -163,6 +210,7 @@ func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDec
libraryDecorator: library,
}
module.linker = prebuilt
+ module.installer = prebuilt
module.AddProperties(&prebuilt.properties)
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index 0b018c10d..adb44bd71 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -184,7 +184,7 @@ func TestPrebuiltLibraryShared(t *testing.T) {
})
shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
- assertString(t, shared.OutputFile().String(), "libf.so")
+ assertString(t, shared.OutputFile().Path().Base(), "libtest.so")
}
func TestPrebuiltLibraryStatic(t *testing.T) {
@@ -198,7 +198,7 @@ func TestPrebuiltLibraryStatic(t *testing.T) {
})
static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
- assertString(t, static.OutputFile().String(), "libf.a")
+ assertString(t, static.OutputFile().Path().Base(), "libf.a")
}
func TestPrebuiltLibrary(t *testing.T) {
@@ -221,8 +221,53 @@ func TestPrebuiltLibrary(t *testing.T) {
})
shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
- assertString(t, shared.OutputFile().String(), "libf.so")
+ assertString(t, shared.OutputFile().Path().Base(), "libtest.so")
static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
- assertString(t, static.OutputFile().String(), "libf.a")
+ assertString(t, static.OutputFile().Path().Base(), "libf.a")
+}
+
+func TestPrebuiltLibraryStem(t *testing.T) {
+ ctx := testPrebuilt(t, `
+ cc_prebuilt_library {
+ name: "libfoo",
+ stem: "libbar",
+ static: {
+ srcs: ["libfoo.a"],
+ },
+ shared: {
+ srcs: ["libfoo.so"],
+ },
+ strip: {
+ none: true,
+ },
+ }
+ `, map[string][]byte{
+ "libfoo.a": nil,
+ "libfoo.so": nil,
+ })
+
+ static := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Module().(*Module)
+ assertString(t, static.OutputFile().Path().Base(), "libfoo.a")
+
+ shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
+ assertString(t, shared.OutputFile().Path().Base(), "libbar.so")
+}
+
+func TestPrebuiltLibrarySharedStem(t *testing.T) {
+ ctx := testPrebuilt(t, `
+ cc_prebuilt_library_shared {
+ name: "libfoo",
+ stem: "libbar",
+ srcs: ["libfoo.so"],
+ strip: {
+ none: true,
+ },
+ }
+ `, map[string][]byte{
+ "libfoo.so": nil,
+ })
+
+ shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
+ assertString(t, shared.OutputFile().Path().Base(), "libbar.so")
}
diff --git a/cc/sdk.go b/cc/sdk.go
new file mode 100644
index 000000000..d05a04a12
--- /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 000000000..5a3c181dc
--- /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 8113f7258..4e74c7fb0 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -115,9 +115,13 @@ func (stl *stl) begin(ctx BaseModuleContext) {
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 f85795b33..53f09955a 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -152,6 +152,7 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string {
name: "libgcc_stripped",
vendor_available: true,
recovery_available: true,
+ sdk_version: "current",
src: "",
}
@@ -169,6 +170,7 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string {
llndk_library {
name: "libc",
symbol_file: "",
+ sdk_version: "current",
}
cc_library {
name: "libm",
@@ -188,6 +190,7 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string {
llndk_library {
name: "libm",
symbol_file: "",
+ sdk_version: "current",
}
cc_library {
name: "libdl",
@@ -207,6 +210,7 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string {
llndk_library {
name: "libdl",
symbol_file: "",
+ sdk_version: "current",
}
cc_library {
name: "libft2",
@@ -219,6 +223,7 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string {
name: "libft2",
symbol_file: "",
vendor_available: false,
+ sdk_version: "current",
}
cc_library {
name: "libc++_static",
@@ -375,6 +380,16 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string {
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 545539232..cfb5b6886 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -117,6 +117,10 @@ func (tidy *tidyFeature) flags(ctx ModuleContext, flags Flags) Flags {
// 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 dfc6f7679..042e012d9 100644
--- a/cc/toolchain_library.go
+++ b/cc/toolchain_library.go
@@ -67,6 +67,7 @@ func ToolchainLibraryFactory() android.Module {
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 4888dcf07..dbe1f3b5b 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -309,6 +309,10 @@ func processVndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {
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 @@ func IsForVndkApex(mctx android.BottomUpMutatorContext, m *Module) bool {
}
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 a6023d3bf..294e5ef0a 100644
--- a/cmd/zipsync/zipsync.go
+++ b/cmd/zipsync/zipsync.go
@@ -115,7 +115,7 @@ func main() {
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 000000000..9fc0d14d6
--- /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 136bb36ca..d37eac840 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -545,10 +545,21 @@ func (ddoc *Droiddoc) AndroidMkEntries() []android.AndroidMkEntries {
}
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/app.go b/java/app.go
index 449558033..7d509eea1 100755
--- a/java/app.go
+++ b/java/app.go
@@ -110,6 +110,10 @@ type appProperties struct {
PreventInstall bool `blueprint:"mutated"`
HideFromMake bool `blueprint:"mutated"`
IsCoverageVariant bool `blueprint:"mutated"`
+
+ // Whether this app is considered mainline updatable or not. When set to true, this will enforce
+ // additional rules for making sure that the APK is truly updatable. Default is false.
+ Updatable *bool
}
// android_app properties that can be overridden by override_android_app
@@ -214,6 +218,13 @@ func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
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...)
}
@@ -242,11 +253,21 @@ func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleCon
}
func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- a.checkPlatformAPI(ctx)
- a.checkSdkVersion(ctx)
+ a.checkAppSdkVersions(ctx)
a.generateAndroidBuildActions(ctx)
}
+func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) {
+ if Bool(a.appProperties.Updatable) {
+ if !a.sdkVersion().stable() {
+ ctx.PropertyErrorf("sdk_version", "Updatable apps must use stable SDKs, found %v", a.sdkVersion())
+ }
+ }
+
+ a.checkPlatformAPI(ctx)
+ a.checkSdkVersions(ctx)
+}
+
// Returns true if the native libraries should be stored in the APK uncompressed and the
// extractNativeLibs application flag should be set to false in the manifest.
func (a *AndroidApp) useEmbeddedNativeLibs(ctx android.ModuleContext) bool {
@@ -385,7 +406,18 @@ func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, ctx android.ModuleContext
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 {
@@ -1360,6 +1392,12 @@ type RuntimeResourceOverlayProperties struct {
// 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) {
@@ -1372,6 +1410,9 @@ func (r *RuntimeResourceOverlay) DepsMutator(ctx android.BottomUpMutatorContext)
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) {
diff --git a/java/app_test.go b/java/app_test.go
index f3cd07096..7b04e4629 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -264,6 +264,108 @@ func TestAndroidAppLinkType(t *testing.T) {
`)
}
+func TestUpdatableApps(t *testing.T) {
+ testCases := []struct {
+ name string
+ bp string
+ expectedError string
+ }{
+ {
+ name: "Stable public SDK",
+ bp: `android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "29",
+ updatable: true,
+ }`,
+ },
+ {
+ name: "Stable system SDK",
+ bp: `android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "system_29",
+ updatable: true,
+ }`,
+ },
+ {
+ name: "Current public SDK",
+ bp: `android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ updatable: true,
+ }`,
+ },
+ {
+ name: "Current system SDK",
+ bp: `android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "system_current",
+ updatable: true,
+ }`,
+ },
+ {
+ name: "Current module SDK",
+ bp: `android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "module_current",
+ updatable: true,
+ }`,
+ },
+ {
+ name: "Current core SDK",
+ bp: `android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "core_current",
+ updatable: true,
+ }`,
+ },
+ {
+ name: "No Platform APIs",
+ bp: `android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ platform_apis: true,
+ updatable: true,
+ }`,
+ expectedError: "Updatable apps must use stable SDKs",
+ },
+ {
+ name: "No Core Platform APIs",
+ bp: `android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "core_platform",
+ updatable: true,
+ }`,
+ expectedError: "Updatable apps must use stable SDKs",
+ },
+ {
+ name: "No unspecified APIs",
+ bp: `android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ updatable: true,
+ }`,
+ expectedError: "Updatable apps must use stable SDK",
+ },
+ }
+
+ for _, test := range testCases {
+ t.Run(test.name, func(t *testing.T) {
+ if test.expectedError == "" {
+ testJava(t, test.bp)
+ } else {
+ testJavaError(t, test.expectedError, test.bp)
+ }
+ })
+ }
+}
+
func TestResourceDirs(t *testing.T) {
testCases := []struct {
name string
@@ -791,6 +893,7 @@ func TestJNIABI(t *testing.T) {
cc_library {
name: "libjni",
system_shared_libs: [],
+ sdk_version: "current",
stl: "none",
}
@@ -928,26 +1031,26 @@ func TestJNIPackaging(t *testing.T) {
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 +1082,10 @@ func TestJNIPackaging(t *testing.T) {
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())
+ }
}
})
}
@@ -2344,11 +2451,17 @@ func checkAapt2LinkFlag(t *testing.T, aapt2Flags, flagName, expectedValue string
}
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"],
}
@@ -2358,7 +2471,21 @@ func TestRuntimeResourceOverlay(t *testing.T) {
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")
@@ -2370,6 +2497,19 @@ func TestRuntimeResourceOverlay(t *testing.T) {
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_bootjars.go b/java/dexpreopt_bootjars.go
index d00864d23..543b2333c 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -26,7 +26,7 @@ import (
)
func init() {
- android.RegisterSingletonType("dex_bootjars", dexpreoptBootJarsFactory)
+ RegisterDexpreoptBootJarsComponents(android.InitRegistrationContext)
}
// Target-independent description of pre-compiled boot image.
@@ -174,6 +174,10 @@ func dexpreoptBootJarsFactory() android.Singleton {
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
@@ -242,16 +246,66 @@ func (d *dexpreoptBootJars) GenerateBuildActions(ctx android.SingletonContext) {
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
}
})
@@ -263,7 +317,8 @@ func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootI
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])
}
}
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index 94ca8bb97..127c20159 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -53,7 +53,7 @@ func TestDexpreoptBootJars(t *testing.T) {
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 1315aba64..066694cc3 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -81,7 +81,7 @@ func stemOf(moduleName string) string {
func getDexLocation(ctx android.PathContext, target android.Target, subdir string, name string) string {
if target.Os.Class == android.Host {
- return filepath.Join("out", "host", ctx.Config().PrebuiltOS(), subdir, name)
+ return filepath.Join(ctx.Config().Getenv("OUT_DIR"), "host", ctx.Config().PrebuiltOS(), subdir, name)
} else {
return filepath.Join("/", subdir, name)
}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index b0efaa5bd..e4582f653 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -301,6 +301,11 @@ type DroidstubsProperties struct {
// 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 @@ func ignoreMissingModules(ctx android.BottomUpMutatorContext, apiToCheck *ApiToC
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 @@ func (d *Droidstubs) ApiFilePath() android.Path {
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) DepsMutator(ctx android.BottomUpMutatorContext) {
}
}
-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 @@ func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuil
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 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// 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 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
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 c81b781b5..61974f5af 100644
--- a/java/java.go
+++ b/java/java.go
@@ -86,7 +86,7 @@ func RegisterJavaBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory)
}
-func (j *Module) checkSdkVersion(ctx android.ModuleContext) {
+func (j *Module) checkSdkVersions(ctx android.ModuleContext) {
if j.SocSpecific() || j.DeviceSpecific() ||
(j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
if sc, ok := ctx.Module().(sdkContext); ok {
@@ -96,6 +96,18 @@ func (j *Module) checkSdkVersion(ctx android.ModuleContext) {
}
}
}
+
+ ctx.VisitDirectDeps(func(module android.Module) {
+ tag := ctx.OtherModuleDependencyTag(module)
+ switch module.(type) {
+ // TODO(satayev): cover other types as well, e.g. imports
+ case *Library, *AndroidLibrary:
+ switch tag {
+ case bootClasspathTag, libTag, staticLibTag, java9LibTag:
+ checkLinkType(ctx, j, module.(linkTypeContext), tag.(dependencyTag))
+ }
+ }
+ })
}
func (j *Module) checkPlatformAPI(ctx android.ModuleContext) {
@@ -898,15 +910,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
// Handled by AndroidApp.collectAppDeps
return
}
- switch module.(type) {
- case *Library, *AndroidLibrary:
- if to, ok := module.(linkTypeContext); ok {
- switch tag {
- case bootClasspathTag, libTag, staticLibTag:
- checkLinkType(ctx, j, to, tag.(dependencyTag))
- }
- }
- }
+
switch dep := module.(type) {
case SdkLibraryDependency:
switch tag {
@@ -1760,11 +1764,6 @@ func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu
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
}
@@ -1823,7 +1822,7 @@ func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bo
}
func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- j.checkSdkVersion(ctx)
+ j.checkSdkVersions(ctx)
j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")
j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary
j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter)
@@ -2513,11 +2512,6 @@ func (j *Import) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu
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 cb17feedd..86eddb172 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -28,10 +28,6 @@ func init() {
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 @@ func (module *prebuiltApis) GenerateAndroidBuildActions(ctx android.ModuleContex
// 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 @@ func parseJarPath(ctx android.BaseModuleContext, path string) (module string, ap
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 @@ func parseApiFilePath(ctx android.BaseModuleContext, path string) (module string
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 @@ func createImport(mctx android.TopDownMutatorContext, module string, scope strin
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 @@ func createFilegroup(mctx android.TopDownMutatorContext, module string, scope st
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 @@ func getPrebuiltFiles(mctx android.TopDownMutatorContext, name string) []string
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 @@ func prebuiltSdkStubs(mctx android.TopDownMutatorContext) {
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 prebuiltApiFiles(mctx android.TopDownMutatorContext) {
}
}
-func PrebuiltApisMutator(mctx android.TopDownMutatorContext) {
+func createPrebuiltApiModules(mctx android.LoadHookContext) {
if _, ok := mctx.Module().(*prebuiltApis); ok {
prebuiltApiFiles(mctx)
prebuiltSdkStubs(mctx)
@@ -191,9 +187,15 @@ func PrebuiltApisMutator(mctx android.TopDownMutatorContext) {
// 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.go b/java/sdk.go
index 0e132d399..92076f4b5 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -147,6 +147,10 @@ type sdkSpec struct {
raw string
}
+func (s sdkSpec) String() string {
+ return fmt.Sprintf("%s_%s", s.kind, s.version)
+}
+
// valid checks if this sdkSpec is well-formed. Note however that true doesn't mean that the
// specified SDK actually exists.
func (s sdkSpec) valid() bool {
@@ -158,6 +162,23 @@ func (s sdkSpec) specified() bool {
return s.valid() && s.kind != sdkPrivate
}
+// whether the API surface is managed and versioned, i.e. has .txt file that
+// get frozen on SDK freeze and changes get reviewed by API council.
+func (s sdkSpec) stable() bool {
+ if !s.specified() {
+ return false
+ }
+ switch s.kind {
+ case sdkCore, sdkPublic, sdkSystem, sdkModule, sdkSystemServer:
+ return true
+ case sdkNone, sdkCorePlatform, sdkTest, sdkPrivate:
+ return false
+ default:
+ panic(fmt.Errorf("unknown sdkKind=%v", s.kind))
+ }
+ return false
+}
+
// prebuiltSdkAvailableForUnbundledBuilt tells whether this sdkSpec can have a prebuilt SDK
// that can be used for unbundled builds.
func (s sdkSpec) prebuiltSdkAvailableForUnbundledBuild() bool {
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 52c900489..ff80d633b 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -15,17 +15,18 @@
package java
import (
- "android/soong/android"
-
"fmt"
"path"
"path/filepath"
+ "reflect"
"sort"
"strings"
"sync"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
+
+ "android/soong/android"
)
const (
@@ -66,6 +67,9 @@ type apiScope struct {
// 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
@@ -86,11 +90,14 @@ type apiScope struct {
// *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,
@@ -131,6 +138,7 @@ var (
moduleSuffix: sdkSystemApiSuffix,
apiFileMakeVariableSuffix: "_SYSTEM",
sdkVersion: "system_current",
+ droidstubsArgs: []string{"-showAnnotation android.annotation.SystemApi"},
})
apiScopeTest = initApiScope(&apiScope{
name: "test",
@@ -138,6 +146,7 @@ var (
moduleSuffix: sdkTestApiSuffix,
apiFileMakeVariableSuffix: "_TEST",
sdkVersion: "test_current",
+ droidstubsArgs: []string{"-showAnnotation android.annotation.TestApi"},
})
allApiScopes = apiScopes{
apiScopePublic,
@@ -162,6 +171,14 @@ func init() {
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) {
@@ -219,9 +236,11 @@ type sdkLibraryProperties struct {
}
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
@@ -308,11 +327,13 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
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)
}
@@ -458,7 +479,7 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.LoadHookContext, apiSc
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 {
@@ -516,15 +537,15 @@ func (module *SdkLibrary) createStubsSources(mctx android.LoadHookContext, apiSc
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",
@@ -536,16 +557,12 @@ func (module *SdkLibrary) createStubsSources(mctx android.LoadHookContext, apiSc
"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
@@ -813,42 +830,89 @@ type sdkLibraryScopeProperties struct {
// 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 @@ func (module *sdkLibraryImport) createInternalModules(mctx android.LoadHookConte
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
- }{}
-
- 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)
- }
+ module.createJavaImportForStubs(mctx, apiScope, scopeProperties)
- // 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 @@ func (module *sdkLibraryImport) createInternalModules(mctx android.LoadHookConte
*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 @@ func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries {
},
}}
}
+
+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/remoteexec/remoteexec.go b/remoteexec/remoteexec.go
new file mode 100644
index 000000000..d43dc6c01
--- /dev/null
+++ b/remoteexec/remoteexec.go
@@ -0,0 +1,155 @@
+// 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 remoteexec
+
+import (
+ "sort"
+ "strings"
+
+ "android/soong/android"
+
+ "github.com/google/blueprint"
+)
+
+const (
+ // ContainerImageKey is the key identifying the container image in the platform spec.
+ ContainerImageKey = "container-image"
+
+ // PoolKey is the key identifying the pool to use for remote execution.
+ PoolKey = "Pool"
+
+ // DefaultImage is the default container image used for Android remote execution. The
+ // image was built with the Dockerfile at
+ // https://android.googlesource.com/platform/prebuilts/remoteexecution-client/+/refs/heads/master/docker/Dockerfile
+ DefaultImage = "docker://gcr.io/androidbuild-re-dockerimage/android-build-remoteexec-image@sha256:582efb38f0c229ea39952fff9e132ccbe183e14869b39888010dacf56b360d62"
+
+ // DefaultWrapperPath is the default path to the remote execution wrapper.
+ DefaultWrapperPath = "prebuilts/remoteexecution-client/live/rewrapper"
+
+ // DefaultPool is the name of the pool to use for remote execution when none is specified.
+ DefaultPool = "default"
+
+ // LocalExecStrategy is the exec strategy to indicate that the action should be run locally.
+ LocalExecStrategy = "local"
+
+ // RemoteExecStrategy is the exec strategy to indicate that the action should be run
+ // remotely.
+ RemoteExecStrategy = "remote"
+
+ // RemoteLocalFallbackExecStrategy is the exec strategy to indicate that the action should
+ // be run remotely and fallback to local execution if remote fails.
+ RemoteLocalFallbackExecStrategy = "remote_local_fallback"
+)
+
+var (
+ defaultLabels = map[string]string{"type": "tool"}
+ defaultExecStrategy = LocalExecStrategy
+ pctx = android.NewPackageContext("android/soong/remoteexec")
+)
+
+// REParams holds information pertinent to the remote execution of a rule.
+type REParams struct {
+ // Platform is the key value pair used for remotely executing the action.
+ Platform map[string]string
+ // Labels is a map of labels that identify the rule.
+ Labels map[string]string
+ // ExecStrategy is the remote execution strategy: remote, local, or remote_local_fallback.
+ ExecStrategy string
+ // Inputs is a list of input paths or ninja variables.
+ Inputs []string
+ // RSPFile is the name of the ninja variable used by the rule as a placeholder for an rsp
+ // input.
+ RSPFile string
+ // OutputFiles is a list of output file paths or ninja variables as placeholders for rule
+ // outputs.
+ OutputFiles []string
+ // ToolchainInputs is a list of paths or ninja variables pointing to the location of
+ // toolchain binaries used by the rule.
+ ToolchainInputs []string
+}
+
+func init() {
+ pctx.VariableFunc("Wrapper", func(ctx android.PackageVarContext) string {
+ if override := ctx.Config().Getenv("RBE_WRAPPER"); override != "" {
+ return override
+ }
+ return DefaultWrapperPath
+ })
+}
+
+// Generate the remote execution wrapper template to be added as a prefix to the rule's command.
+func (r *REParams) Template() string {
+ template := "${remoteexec.Wrapper}"
+
+ var kvs []string
+ labels := r.Labels
+ if len(labels) == 0 {
+ labels = defaultLabels
+ }
+ for k, v := range labels {
+ kvs = append(kvs, k+"="+v)
+ }
+ sort.Strings(kvs)
+ template += " --labels=" + strings.Join(kvs, ",")
+
+ var platform []string
+ for k, v := range r.Platform {
+ if v == "" {
+ continue
+ }
+ platform = append(platform, k+"="+v)
+ }
+ if _, ok := r.Platform[ContainerImageKey]; !ok {
+ platform = append(platform, ContainerImageKey+"="+DefaultImage)
+ }
+ if platform != nil {
+ sort.Strings(platform)
+ template += " --platform=\"" + strings.Join(platform, ",") + "\""
+ }
+
+ strategy := r.ExecStrategy
+ if strategy == "" {
+ strategy = defaultExecStrategy
+ }
+ template += " --exec_strategy=" + strategy
+
+ if len(r.Inputs) > 0 {
+ template += " --inputs=" + strings.Join(r.Inputs, ",")
+ }
+
+ if r.RSPFile != "" {
+ template += " --input_list_paths=" + r.RSPFile
+ }
+
+ if len(r.OutputFiles) > 0 {
+ template += " --output_files=" + strings.Join(r.OutputFiles, ",")
+ }
+
+ if len(r.ToolchainInputs) > 0 {
+ template += " --toolchain_inputs=" + strings.Join(r.ToolchainInputs, ",")
+ }
+
+ return template + " -- "
+}
+
+// StaticRules returns a pair of rules based on the given RuleParams, where the first rule is a
+// locally executable rule and the second rule is a remotely executable rule.
+func StaticRules(ctx android.PackageContext, name string, ruleParams blueprint.RuleParams, reParams *REParams, commonArgs []string, reArgs []string) (blueprint.Rule, blueprint.Rule) {
+ ruleParamsRE := ruleParams
+ ruleParamsRE.Command = reParams.Template() + ruleParamsRE.Command
+
+ return ctx.AndroidStaticRule(name, ruleParams, commonArgs...),
+ ctx.AndroidRemoteStaticRule(name+"RE", android.RemoteRuleSupports{RBE: true}, ruleParamsRE, append(commonArgs, reArgs...)...)
+}
diff --git a/remoteexec/remoteexec_test.go b/remoteexec/remoteexec_test.go
new file mode 100644
index 000000000..30e891ced
--- /dev/null
+++ b/remoteexec/remoteexec_test.go
@@ -0,0 +1,83 @@
+// 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 remoteexec
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestTemplate(t *testing.T) {
+ tests := []struct {
+ name string
+ params *REParams
+ want string
+ }{
+ {
+ name: "basic",
+ params: &REParams{
+ Labels: map[string]string{"type": "compile", "lang": "cpp", "compiler": "clang"},
+ Inputs: []string{"$in"},
+ OutputFiles: []string{"$out"},
+ Platform: map[string]string{
+ ContainerImageKey: DefaultImage,
+ PoolKey: "default",
+ },
+ },
+ want: fmt.Sprintf("${remoteexec.Wrapper} --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=local --inputs=$in --output_files=$out -- ", DefaultImage),
+ },
+ {
+ name: "all params",
+ params: &REParams{
+ Labels: map[string]string{"type": "compile", "lang": "cpp", "compiler": "clang"},
+ Inputs: []string{"$in"},
+ OutputFiles: []string{"$out"},
+ ExecStrategy: "remote",
+ RSPFile: "$out.rsp",
+ ToolchainInputs: []string{"clang++"},
+ Platform: map[string]string{
+ ContainerImageKey: DefaultImage,
+ PoolKey: "default",
+ },
+ },
+ want: fmt.Sprintf("${remoteexec.Wrapper} --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=remote --inputs=$in --input_list_paths=$out.rsp --output_files=$out --toolchain_inputs=clang++ -- ", DefaultImage),
+ },
+ }
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ if got := test.params.Template(); got != test.want {
+ t.Errorf("Template() returned\n%s\nwant\n%s", got, test.want)
+ }
+ })
+ }
+}
+
+func TestTemplateDeterminism(t *testing.T) {
+ r := &REParams{
+ Labels: map[string]string{"type": "compile", "lang": "cpp", "compiler": "clang"},
+ Inputs: []string{"$in"},
+ OutputFiles: []string{"$out"},
+ Platform: map[string]string{
+ ContainerImageKey: DefaultImage,
+ PoolKey: "default",
+ },
+ }
+ want := fmt.Sprintf("${remoteexec.Wrapper} --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=local --inputs=$in --output_files=$out -- ", DefaultImage)
+ for i := 0; i < 1000; i++ {
+ if got := r.Template(); got != want {
+ t.Fatalf("Template() returned\n%s\nwant\n%s", got, want)
+ }
+ }
+}
diff --git a/rust/compiler.go b/rust/compiler.go
index 4593165f4..81b258c1e 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -222,7 +222,10 @@ func (compiler *baseCompiler) installDir(ctx ModuleContext) android.InstallPath
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 60796d8d8..180fd8ba0 100644
--- a/rust/config/arm64_device.go
+++ b/rust/config/arm64_device.go
@@ -27,7 +27,6 @@ var (
"-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 0cf2dd045..bf863bb67 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -318,6 +318,8 @@ func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
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 f446ef039..6fe887129 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -164,6 +164,10 @@ func (mod *Module) OnlyInRecovery() bool {
return false
}
+func (mod *Module) UseSdk() bool {
+ return false
+}
+
func (mod *Module) UseVndk() bool {
return false
}
@@ -184,6 +188,10 @@ func (mod *Module) SdkVersion() string {
return ""
}
+func (mod *Module) AlwaysSdk() bool {
+ return false
+}
+
func (mod *Module) ToolchainLibrary() bool {
return false
}
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 9e6086f15..780da9fc3 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -1766,7 +1766,6 @@ cc_prebuilt_library_shared {
sdk_member_name: "stubslib",
installable: false,
stubs: {
- symbol_file: "etc/stubslib.map.txt",
versions: ["3"],
},
arch: {
@@ -1783,7 +1782,6 @@ cc_prebuilt_library_shared {
name: "stubslib",
prefer: false,
stubs: {
- symbol_file: "etc/stubslib.map.txt",
versions: ["3"],
},
arch: {
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index cbffb501b..c0ad35c3f 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -24,7 +24,51 @@ func testSdkWithJava(t *testing.T, bp string) *testSdkResult {
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 @@ func TestBasicSdkWithJavaLibrary(t *testing.T) {
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 @@ module_exports_snapshot {
`),
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 @@ module_exports_snapshot {
}
`),
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 @@ module_exports_snapshot {
`),
)
}
+
+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 dabdf851e..cb5a6053d 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -312,7 +312,7 @@ func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
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 @@ func sdkDepsReplaceMutator(mctx android.BottomUpMutatorContext) {
}
}
-// 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 00245cef4..9e272019e 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -90,6 +90,7 @@ func testSdkContext(bp string, fs map[string][]byte) (*android.TestContext, andr
// from java package
java.RegisterJavaBuildComponents(ctx)
java.RegisterAppBuildComponents(ctx)
+ java.RegisterSdkLibraryBuildComponents(ctx)
java.RegisterStubsBuildComponents(ctx)
java.RegisterSystemModulesBuildComponents(ctx)
@@ -338,14 +339,15 @@ func checkAllOtherCopyRules(expected string) snapshotBuildInfoChecker {
}
}
-// 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/dumpvars.go b/ui/build/dumpvars.go
index ce8f968d7..a3234e339 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -190,6 +190,7 @@ func runMakeProductConfig(ctx Context, config Config) {
// compiler wrappers set up by make
"CC_WRAPPER",
"CXX_WRAPPER",
+ "RBE_WRAPPER",
"JAVAC_WRAPPER",
"R8_WRAPPER",
"D8_WRAPPER",
diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go
index 5ca83cce6..98eb028a8 100644
--- a/ui/build/sandbox_linux.go
+++ b/ui/build/sandbox_linux.go
@@ -19,6 +19,7 @@ import (
"os"
"os/exec"
"os/user"
+ "path/filepath"
"strings"
"sync"
)
@@ -75,11 +76,22 @@ func (c *Cmd) sandboxSupported() bool {
sandboxConfig.group = "nobody"
}
+ // These directories will be bind mounted
+ // so we need full non-symlink paths
sandboxConfig.srcDir = absPath(c.ctx, ".")
+ if derefPath, err := filepath.EvalSymlinks(sandboxConfig.srcDir); err == nil {
+ sandboxConfig.srcDir = absPath(c.ctx, derefPath)
+ }
sandboxConfig.outDir = absPath(c.ctx, c.config.OutDir())
+ if derefPath, err := filepath.EvalSymlinks(sandboxConfig.outDir); err == nil {
+ sandboxConfig.outDir = absPath(c.ctx, derefPath)
+ }
sandboxConfig.distDir = absPath(c.ctx, c.config.DistDir())
+ if derefPath, err := filepath.EvalSymlinks(sandboxConfig.distDir); err == nil {
+ sandboxConfig.distDir = absPath(c.ctx, derefPath)
+ }
- cmd := exec.CommandContext(c.ctx.Context, nsjailPath,
+ sandboxArgs := []string{
"-H", "android-build",
"-e",
"-u", "nobody",
@@ -88,10 +100,21 @@ func (c *Cmd) sandboxSupported() bool {
"-B", sandboxConfig.srcDir,
"-B", "/tmp",
"-B", sandboxConfig.outDir,
- "-B", sandboxConfig.distDir,
+ }
+
+ 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)
@@ -164,9 +187,6 @@ func (c *Cmd) wrapSandbox() {
//Mount out dir as read-write
"-B", sandboxConfig.outDir,
- //Mount dist dir as read-write
- "-B", sandboxConfig.distDir,
-
// Mount a writable tmp dir
"-B", "/tmp",
@@ -178,6 +198,11 @@ func (c *Cmd) wrapSandbox() {
"-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())
diff --git a/ui/metrics/Android.bp b/ui/metrics/Android.bp
index 529639de5..3596e1019 100644
--- a/ui/metrics/Android.bp
+++ b/ui/metrics/Android.bp
@@ -17,6 +17,7 @@ bootstrap_go_package {
pkgPath: "android/soong/ui/metrics",
deps: [
"golang-protobuf-proto",
+ "soong-ui-metrics_upload_proto",
"soong-ui-metrics_proto",
"soong-ui-tracer",
],
@@ -35,3 +36,11 @@ bootstrap_go_package {
],
}
+bootstrap_go_package {
+ name: "soong-ui-metrics_upload_proto",
+ pkgPath: "android/soong/ui/metrics/upload_proto",
+ deps: ["golang-protobuf-proto"],
+ srcs: [
+ "upload_proto/upload.pb.go",
+ ],
+}
diff --git a/ui/metrics/upload_proto/regen.sh b/ui/metrics/upload_proto/regen.sh
new file mode 100755
index 000000000..4521df7bd
--- /dev/null
+++ b/ui/metrics/upload_proto/regen.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# Generates the golang source file of upload.proto file.
+
+set -e
+
+function die() { echo "ERROR: $1" >&2; exit 1; }
+
+readonly error_msg="Maybe you need to run 'lunch aosp_arm-eng && m aprotoc blueprint_tools'?"
+
+if ! hash aprotoc &>/dev/null; then
+ die "could not find aprotoc. ${error_msg}"
+fi
+
+if ! aprotoc --go_out=paths=source_relative:. upload.proto; then
+ die "build failed. ${error_msg}"
+fi
diff --git a/ui/metrics/upload_proto/upload.pb.go b/ui/metrics/upload_proto/upload.pb.go
new file mode 100644
index 000000000..1b1e5e843
--- /dev/null
+++ b/ui/metrics/upload_proto/upload.pb.go
@@ -0,0 +1,122 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: upload.proto
+
+package soong_metrics_upload_proto
+
+import (
+ fmt "fmt"
+ proto "github.com/golang/protobuf/proto"
+ math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type Upload struct {
+ // The timestamp in milliseconds that the build was created.
+ CreationTimestampMs *uint64 `protobuf:"varint,1,opt,name=creation_timestamp_ms,json=creationTimestampMs" json:"creation_timestamp_ms,omitempty"`
+ // The timestamp in milliseconds when the build was completed.
+ CompletionTimestampMs *uint64 `protobuf:"varint,2,opt,name=completion_timestamp_ms,json=completionTimestampMs" json:"completion_timestamp_ms,omitempty"`
+ // The branch name.
+ BranchName *string `protobuf:"bytes,3,opt,name=branch_name,json=branchName" json:"branch_name,omitempty"`
+ // The target name.
+ TargetName *string `protobuf:"bytes,4,opt,name=target_name,json=targetName" json:"target_name,omitempty"`
+ // A list of metrics filepaths to upload.
+ MetricsFiles []string `protobuf:"bytes,5,rep,name=metrics_files,json=metricsFiles" json:"metrics_files,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Upload) Reset() { *m = Upload{} }
+func (m *Upload) String() string { return proto.CompactTextString(m) }
+func (*Upload) ProtoMessage() {}
+func (*Upload) Descriptor() ([]byte, []int) {
+ return fileDescriptor_91b94b655bd2a7e5, []int{0}
+}
+
+func (m *Upload) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Upload.Unmarshal(m, b)
+}
+func (m *Upload) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Upload.Marshal(b, m, deterministic)
+}
+func (m *Upload) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Upload.Merge(m, src)
+}
+func (m *Upload) XXX_Size() int {
+ return xxx_messageInfo_Upload.Size(m)
+}
+func (m *Upload) XXX_DiscardUnknown() {
+ xxx_messageInfo_Upload.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Upload proto.InternalMessageInfo
+
+func (m *Upload) GetCreationTimestampMs() uint64 {
+ if m != nil && m.CreationTimestampMs != nil {
+ return *m.CreationTimestampMs
+ }
+ return 0
+}
+
+func (m *Upload) GetCompletionTimestampMs() uint64 {
+ if m != nil && m.CompletionTimestampMs != nil {
+ return *m.CompletionTimestampMs
+ }
+ return 0
+}
+
+func (m *Upload) GetBranchName() string {
+ if m != nil && m.BranchName != nil {
+ return *m.BranchName
+ }
+ return ""
+}
+
+func (m *Upload) GetTargetName() string {
+ if m != nil && m.TargetName != nil {
+ return *m.TargetName
+ }
+ return ""
+}
+
+func (m *Upload) GetMetricsFiles() []string {
+ if m != nil {
+ return m.MetricsFiles
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*Upload)(nil), "soong_metrics_upload.Upload")
+}
+
+func init() {
+ proto.RegisterFile("upload.proto", fileDescriptor_91b94b655bd2a7e5)
+}
+
+var fileDescriptor_91b94b655bd2a7e5 = []byte{
+ // 201 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0x2d, 0xc8, 0xc9,
+ 0x4f, 0x4c, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x29, 0xce, 0xcf, 0xcf, 0x4b, 0x8f,
+ 0xcf, 0x4d, 0x2d, 0x29, 0xca, 0x4c, 0x2e, 0x8e, 0x87, 0xc8, 0x29, 0xdd, 0x66, 0xe4, 0x62, 0x0b,
+ 0x05, 0x33, 0x85, 0x8c, 0xb8, 0x44, 0x93, 0x8b, 0x52, 0x13, 0x4b, 0x32, 0xf3, 0xf3, 0xe2, 0x4b,
+ 0x32, 0x73, 0x53, 0x8b, 0x4b, 0x12, 0x73, 0x0b, 0xe2, 0x73, 0x8b, 0x25, 0x18, 0x15, 0x18, 0x35,
+ 0x58, 0x82, 0x84, 0x61, 0x92, 0x21, 0x30, 0x39, 0xdf, 0x62, 0x21, 0x33, 0x2e, 0xf1, 0xe4, 0xfc,
+ 0xdc, 0x82, 0x9c, 0x54, 0x4c, 0x5d, 0x4c, 0x60, 0x5d, 0xa2, 0x08, 0x69, 0x64, 0x7d, 0xf2, 0x5c,
+ 0xdc, 0x49, 0x45, 0x89, 0x79, 0xc9, 0x19, 0xf1, 0x79, 0x89, 0xb9, 0xa9, 0x12, 0xcc, 0x0a, 0x8c,
+ 0x1a, 0x9c, 0x41, 0x5c, 0x10, 0x21, 0xbf, 0xc4, 0xdc, 0x54, 0x90, 0x82, 0x92, 0xc4, 0xa2, 0xf4,
+ 0xd4, 0x12, 0x88, 0x02, 0x16, 0x88, 0x02, 0x88, 0x10, 0x58, 0x81, 0x32, 0x17, 0x2f, 0xcc, 0x2b,
+ 0x69, 0x99, 0x39, 0xa9, 0xc5, 0x12, 0xac, 0x0a, 0xcc, 0x1a, 0x9c, 0x41, 0x3c, 0x50, 0x41, 0x37,
+ 0x90, 0x98, 0x93, 0x4c, 0x94, 0x14, 0x36, 0x5f, 0xc7, 0x83, 0x43, 0x04, 0x10, 0x00, 0x00, 0xff,
+ 0xff, 0xe2, 0x01, 0x74, 0x65, 0x20, 0x01, 0x00, 0x00,
+}
diff --git a/ui/metrics/upload_proto/upload.proto b/ui/metrics/upload_proto/upload.proto
new file mode 100644
index 000000000..7a9f080e0
--- /dev/null
+++ b/ui/metrics/upload_proto/upload.proto
@@ -0,0 +1,35 @@
+// 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.
+
+syntax = "proto2";
+
+package soong_metrics_upload;
+option go_package = "soong_metrics_upload_proto";
+
+message Upload {
+ // The timestamp in milliseconds that the build was created.
+ optional uint64 creation_timestamp_ms = 1;
+
+ // The timestamp in milliseconds when the build was completed.
+ optional uint64 completion_timestamp_ms = 2;
+
+ // The branch name.
+ optional string branch_name = 3;
+
+ // The target name.
+ optional string target_name = 4;
+
+ // A list of metrics filepaths to upload.
+ repeated string metrics_files = 5;
+}