Merge "Don't use metalava for "check-current""
diff --git a/Android.bp b/Android.bp
index fe776df..7cdd928 100644
--- a/Android.bp
+++ b/Android.bp
@@ -132,6 +132,7 @@
pkgPath: "android/soong/cc/config",
deps: [
"soong-android",
+ "soong-remoteexec",
],
srcs: [
"cc/config/clang.go",
@@ -547,6 +548,22 @@
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
//
@@ -627,7 +644,8 @@
arch: {
arm: {
src: "prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a",
- repack_objects_to_keep: ["unwind-arm.o", "libunwind.o", "pr-support.o"],
+ repack_objects_to_keep: [],
+ enabled: false,
},
arm64: {
src: "prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/lib/gcc/aarch64-linux-android/4.9.x/libgcc.a",
diff --git a/android/androidmk.go b/android/androidmk.go
index b5f4b2b..d579e30 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -198,6 +198,10 @@
a.AddStrings("LOCAL_HOST_REQUIRED_MODULES", a.Host_required...)
a.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", a.Target_required...)
+ if am, ok := mod.(ApexModule); ok {
+ a.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", am.NotAvailableForPlatform())
+ }
+
archStr := amod.Arch().ArchType.String()
host := false
switch amod.Os().Class {
diff --git a/android/apex.go b/android/apex.go
index 9bf6fc7..f9350d1 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -32,6 +32,7 @@
ApexName string
MinSdkVersion int
+ Updatable bool
}
// Extracted from ApexModule to make it easier to define custom subsets of the
@@ -100,10 +101,28 @@
// Tests if this module is available for the specified APEX or ":platform"
AvailableFor(what string) bool
+ // Return true if this module is not available to platform (i.e. apex_available
+ // property doesn't have "//apex_available:platform"), or shouldn't be available
+ // to platform, which is the case when this module depends on other module that
+ // isn't available to platform.
+ NotAvailableForPlatform() bool
+
+ // Mark that this module is not available to platform. Set by the
+ // check-platform-availability mutator in the apex package.
+ SetNotAvailableForPlatform()
+
// Returns the highest version which is <= maxSdkVersion.
// For example, with maxSdkVersion is 10 and versionList is [9,11]
// it returns 9 as string
ChooseSdkVersion(versionList []string, maxSdkVersion int) (string, error)
+
+ // Tests if the module comes from an updatable APEX.
+ Updatable() bool
+
+ // List of APEXes that this module tests. The module has access to
+ // the private part of the listed APEXes even when it is not included in the
+ // APEXes.
+ TestFor() []string
}
type ApexProperties struct {
@@ -117,6 +136,8 @@
Apex_available []string
Info ApexInfo `blueprint:"mutated"`
+
+ NotAvailableForPlatform bool `blueprint:"mutated"`
}
// Marker interface that identifies dependencies that are excluded from APEX
@@ -147,6 +168,11 @@
return m.ApexProperties.Apex_available
}
+func (m *ApexModuleBase) TestFor() []string {
+ // To be implemented by concrete types inheriting ApexModuleBase
+ return nil
+}
+
func (m *ApexModuleBase) BuildForApexes(apexes []ApexInfo) {
m.apexVariationsLock.Lock()
defer m.apexVariationsLock.Unlock()
@@ -201,6 +227,14 @@
return CheckAvailableForApex(what, m.ApexProperties.Apex_available)
}
+func (m *ApexModuleBase) NotAvailableForPlatform() bool {
+ return m.ApexProperties.NotAvailableForPlatform
+}
+
+func (m *ApexModuleBase) SetNotAvailableForPlatform() {
+ m.ApexProperties.NotAvailableForPlatform = true
+}
+
func (m *ApexModuleBase) DepIsInSameApex(ctx BaseModuleContext, dep Module) bool {
// By default, if there is a dependency from A to B, we try to include both in the same APEX,
// unless B is explicitly from outside of the APEX (i.e. a stubs lib). Thus, returning true.
@@ -229,6 +263,10 @@
}
}
+func (m *ApexModuleBase) Updatable() bool {
+ return m.ApexProperties.Info.Updatable
+}
+
type byApexName []ApexInfo
func (a byApexName) Len() int { return len(a) }
diff --git a/android/api_levels.go b/android/api_levels.go
index 4f6efee..b6296d8 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -16,6 +16,7 @@
import (
"encoding/json"
+ "fmt"
"strconv"
)
@@ -73,7 +74,7 @@
"P": 28,
"Q": 29,
}
- for i, codename := range config.PlatformVersionCombinedCodenames() {
+ for i, codename := range config.PlatformVersionActiveCodenames() {
apiLevelsMap[codename] = baseApiLevel + i
}
@@ -84,14 +85,19 @@
// Converts an API level string into its numeric form.
// * Codenames are decoded.
// * Numeric API levels are simply converted.
-// * "minimum" and "current" are not currently handled since the former is
-// NDK specific and the latter has inconsistent meaning.
+// * "current" is mapped to FutureApiLevel(10000)
+// * "minimum" is NDK specific and not handled with this. (refer normalizeNdkApiLevel in cc.go)
func ApiStrToNum(ctx BaseModuleContext, apiLevel string) (int, error) {
- num, ok := getApiLevelsMap(ctx.Config())[apiLevel]
- if ok {
+ if apiLevel == "current" {
+ return FutureApiLevel, nil
+ }
+ if num, ok := getApiLevelsMap(ctx.Config())[apiLevel]; ok {
return num, nil
}
- return strconv.Atoi(apiLevel)
+ if num, err := strconv.Atoi(apiLevel); err == nil {
+ return num, nil
+ }
+ return 0, fmt.Errorf("SDK version should be one of \"current\", <number> or <codename>: %q", apiLevel)
}
func (a *apiLevelsSingleton) GenerateBuildActions(ctx SingletonContext) {
diff --git a/android/config.go b/android/config.go
index 558c828..c297b05 100644
--- a/android/config.go
+++ b/android/config.go
@@ -652,22 +652,6 @@
return c.productVariables.Platform_version_active_codenames
}
-// Codenames that are available in the branch but not included in the current
-// lunch target.
-func (c *config) PlatformVersionFutureCodenames() []string {
- return c.productVariables.Platform_version_future_codenames
-}
-
-// All possible codenames in the current branch. NB: Not named AllCodenames
-// because "all" has historically meant "active" in make, and still does in
-// build.prop.
-func (c *config) PlatformVersionCombinedCodenames() []string {
- combined := []string{}
- combined = append(combined, c.PlatformVersionActiveCodenames()...)
- combined = append(combined, c.PlatformVersionFutureCodenames()...)
- return combined
-}
-
func (c *config) ProductAAPTConfig() []string {
return c.productVariables.AAPTConfig
}
diff --git a/android/mutator.go b/android/mutator.go
index a46d4be..10a815a 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -103,7 +103,7 @@
registerPathDepsMutator,
RegisterPrebuiltsPostDepsMutators,
RegisterVisibilityRuleEnforcer,
- registerNeverallowMutator,
+ RegisterNeverallowMutator,
RegisterOverridePostDepsMutators,
}
diff --git a/android/neverallow.go b/android/neverallow.go
index 04ec27d..cf09792 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -42,7 +42,7 @@
// 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()
}
@@ -247,7 +247,7 @@
}
type ValueMatcher interface {
- test(string) bool
+ Test(string) bool
String() string
}
@@ -255,7 +255,7 @@
expected string
}
-func (m *equalMatcher) test(value string) bool {
+func (m *equalMatcher) Test(value string) bool {
return m.expected == value
}
@@ -266,7 +266,7 @@
type anyMatcher struct {
}
-func (m *anyMatcher) test(value string) bool {
+func (m *anyMatcher) Test(value string) bool {
return true
}
@@ -280,7 +280,7 @@
prefix string
}
-func (m *startsWithMatcher) test(value string) bool {
+func (m *startsWithMatcher) Test(value string) bool {
return strings.HasPrefix(value, m.prefix)
}
@@ -292,7 +292,7 @@
re *regexp.Regexp
}
-func (m *regexMatcher) test(value string) bool {
+func (m *regexMatcher) Test(value string) bool {
return m.re.MatchString(value)
}
@@ -302,7 +302,7 @@
type isSetMatcher struct{}
-func (m *isSetMatcher) test(value string) bool {
+func (m *isSetMatcher) Test(value string) bool {
return value != ""
}
@@ -573,7 +573,7 @@
}
check := func(value string) bool {
- return prop.matcher.test(value)
+ return prop.matcher.Test(value)
}
if matchValue(propertiesValue, check) {
@@ -630,6 +630,6 @@
// 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 0373b79..2fc42e3 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -313,7 +313,7 @@
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)
@@ -327,7 +327,7 @@
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")
diff --git a/android/variable.go b/android/variable.go
index 612d138..3b3916e 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -151,7 +151,6 @@
Platform_sdk_codename *string `json:",omitempty"`
Platform_sdk_final *bool `json:",omitempty"`
Platform_version_active_codenames []string `json:",omitempty"`
- Platform_version_future_codenames []string `json:",omitempty"`
Platform_vndk_version *string `json:",omitempty"`
Platform_systemsdk_versions []string `json:",omitempty"`
Platform_security_patch *string `json:",omitempty"`
@@ -255,7 +254,7 @@
ClangTidy *bool `json:",omitempty"`
TidyChecks *string `json:",omitempty"`
- SamplingPGO *bool `json:",omitempty"`
+ SamplingPGO *bool `json:",omitempty"`
NativeLineCoverage *bool `json:",omitempty"`
Native_coverage *bool `json:",omitempty"`
@@ -358,7 +357,6 @@
Platform_sdk_codename: stringPtr("Q"),
Platform_sdk_final: boolPtr(false),
Platform_version_active_codenames: []string{"Q"},
- Platform_version_future_codenames: []string{"Q"},
Platform_vndk_version: stringPtr("Q"),
HostArch: stringPtr("x86_64"),
diff --git a/apex/apex.go b/apex/apex.go
index fd3fb2b..39968ab 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -20,7 +20,6 @@
"path/filepath"
"regexp"
"sort"
- "strconv"
"strings"
"sync"
@@ -94,24 +93,6 @@
//
// Module separator
//
- m["com.android.adbd"] = []string{
- "libadbd_auth",
- "libbuildversion",
- "libcap",
- "libmdnssd",
- "libminijail",
- "libminijail_gen_constants",
- "libminijail_gen_constants_obj",
- "libminijail_gen_syscall",
- "libminijail_gen_syscall_obj",
- "libminijail_generated",
- "libpackagelistparser",
- "libpcre2",
- "libprocessgroup_headers",
- }
- //
- // Module separator
- //
artApexContents := []string{
"art_cmdlineparser_headers",
"art_disassembler_headers",
@@ -135,14 +116,12 @@
"libandroidicuinit",
"libart_runtime_headers_ndk",
"libartd-disassembler",
- "libasync_safe",
"libdexfile_all_headers",
"libdexfile_external_headers",
"libdexfile_support",
"libdmabufinfo",
"libexpat",
"libfdlibm",
- "libgtest_prod",
"libicui18n_headers",
"libicuuc",
"libicuuc_headers",
@@ -232,13 +211,10 @@
"libevent",
"libfmq",
"libg722codec",
- "libgtest_prod",
"libgui_headers",
"libmedia_headers",
"libmodpb64",
"libosi",
- "libprocessgroup",
- "libprocessgroup_headers",
"libstagefright_foundation_headers",
"libstagefright_headers",
"libstatslog",
@@ -264,9 +240,7 @@
// Module separator
//
m["com.android.conscrypt"] = []string{
- "boringssl_self_test",
"libnativehelper_header_only",
- "unsupportedappusage",
}
//
// Module separator
@@ -284,18 +258,6 @@
//
// Module separator
//
- m["com.android.cronet"] = []string{
- "cronet_impl_common_java",
- "cronet_impl_native_java",
- "cronet_impl_platform_java",
- "libcronet.80.0.3986.0",
- "org.chromium.net.cronet",
- "org.chromium.net.cronet.xml",
- "prebuilt_libcronet.80.0.3986.0",
- }
- //
- // Module separator
- //
m["com.android.neuralnetworks"] = []string{
"android.hardware.neuralnetworks@1.0",
"android.hardware.neuralnetworks@1.1",
@@ -308,8 +270,6 @@
"libarect",
"libbuildversion",
"libmath",
- "libprocessgroup",
- "libprocessgroup_headers",
"libprocpartition",
"libsync",
}
@@ -352,7 +312,6 @@
"libaacextractor",
"libamrextractor",
"libarect",
- "libasync_safe",
"libaudio_system_headers",
"libaudioclient",
"libaudioclient_headers",
@@ -406,13 +365,10 @@
"libnblog",
"liboggextractor",
"libpackagelistparser",
- "libpcre2",
"libpdx",
"libpdx_default_transport",
"libpdx_headers",
"libpdx_uds",
- "libprocessgroup",
- "libprocessgroup_headers",
"libprocinfo",
"libsonivox",
"libspeexresampler",
@@ -478,7 +434,6 @@
"libFraunhoferAAC",
"libLibGuiProperties",
"libarect",
- "libasync_safe",
"libaudio_system_headers",
"libaudioutils",
"libaudioutils",
@@ -492,7 +447,6 @@
"libbluetooth-types-header",
"libbufferhub_headers",
"libc_scudo",
- "libcap",
"libcodec2",
"libcodec2_headers",
"libcodec2_hidl@1.0",
@@ -551,21 +505,12 @@
"libmath",
"libmedia_codecserviceregistrant",
"libmedia_headers",
- "libminijail",
- "libminijail_gen_constants",
- "libminijail_gen_constants_obj",
- "libminijail_gen_syscall",
- "libminijail_gen_syscall_obj",
- "libminijail_generated",
"libmpeg2dec",
"libnativebase_headers",
"libnativebridge_lazy",
"libnativeloader_lazy",
"libnativewindow_headers",
- "libopus",
"libpdx_headers",
- "libprocessgroup",
- "libprocessgroup_headers",
"libscudo_wrapper",
"libsfplugin_ccodec_utils",
"libstagefright_amrnb_common",
@@ -633,8 +578,6 @@
m["com.android.runtime"] = []string{
"bionic_libc_platform_headers",
"libarm-optimized-routines-math",
- "libasync_safe",
- "libasync_safe_headers",
"libc_aeabi",
"libc_bionic",
"libc_bionic_ndk",
@@ -670,13 +613,11 @@
"libdexfile_support",
"libdexfile_support_static",
"libdl_static",
- "libgtest_prod",
"libjemalloc5",
"liblinker_main",
"liblinker_malloc",
"liblz4",
"liblzma",
- "libprocessgroup_headers",
"libprocinfo",
"libpropertyinfoparser",
"libscudo",
@@ -690,34 +631,11 @@
//
// Module separator
//
- m["com.android.resolv"] = []string{
- "dnsresolver_aidl_interface-unstable-ndk_platform",
- "libgtest_prod",
- "libnativehelper_header_only",
- "libnetd_client_headers",
- "libnetd_resolv",
- "libnetdutils",
- "libprocessgroup",
- "libprocessgroup_headers",
- "libstatslog_resolv",
- "libstatspush_compat",
- "libstatssocket",
- "libstatssocket_headers",
- "libsysutils",
- "netd_event_listener_interface-ndk_platform",
- "server_configurable_flags",
- "stats_proto",
- }
- //
- // Module separator
- //
m["com.android.tethering"] = []string{
"libnativehelper_compat_libc++",
"android.hardware.tetheroffload.config@1.0",
"libcgrouprc",
"libcgrouprc_format",
- "libprocessgroup",
- "libprocessgroup_headers",
"libtetherutilsjni",
"libvndksupport",
"tethering-aidl-interfaces-java",
@@ -755,8 +673,6 @@
"ipmemorystore-aidl-interfaces-java",
"ksoap2",
"libnanohttpd",
- "libprocessgroup",
- "libprocessgroup_headers",
"libwifi-jni",
"net-utils-services-common",
"netd_aidl_interface-V2-java",
@@ -784,7 +700,6 @@
// Module separator
//
m["com.android.os.statsd"] = []string{
- "libprocessgroup_headers",
"libstatssocket",
}
//
@@ -831,17 +746,22 @@
ctx.BottomUp("apex", apexMutator).Parallel()
ctx.BottomUp("apex_flattened", apexFlattenedMutator).Parallel()
ctx.BottomUp("apex_uses", apexUsesMutator).Parallel()
+ ctx.BottomUp("mark_platform_availability", markPlatformAvailability).Parallel()
}
// 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),
+ Updatable: proptools.Bool(a.properties.Updatable),
}}
directDep = true
} else if am, ok := mctx.Module().(android.ApexModule); ok {
@@ -865,6 +785,60 @@
})
}
+// mark if a module cannot be available to platform. A module cannot be available
+// to platform if 1) it is explicitly marked as not available (i.e. "//apex_available:platform"
+// is absent) or 2) it depends on another module that isn't (or can't be) available to platform
+func markPlatformAvailability(mctx android.BottomUpMutatorContext) {
+ // Host and recovery are not considered as platform
+ if mctx.Host() || mctx.Module().InstallInRecovery() {
+ return
+ }
+
+ if am, ok := mctx.Module().(android.ApexModule); ok {
+ availableToPlatform := am.AvailableFor(android.AvailableToPlatform)
+
+ // In a rare case when a lib is marked as available only to an apex
+ // but the apex doesn't exist. This can happen in a partial manifest branch
+ // like master-art. Currently, libstatssocket in the stats APEX is causing
+ // this problem.
+ // Include the lib in platform because the module SDK that ought to provide
+ // it doesn't exist, so it would otherwise be left out completely.
+ // TODO(b/154888298) remove this by adding those libraries in module SDKS and skipping
+ // this check for libraries provided by SDKs.
+ if !availableToPlatform && !android.InAnyApex(am.Name()) {
+ availableToPlatform = true
+ }
+
+ // If any of the dep is not available to platform, this module is also considered
+ // as being not available to platform even if it has "//apex_available:platform"
+ mctx.VisitDirectDeps(func(child android.Module) {
+ if !am.DepIsInSameApex(mctx, child) {
+ // if the dependency crosses apex boundary, don't consider it
+ return
+ }
+ if dep, ok := child.(android.ApexModule); ok && dep.NotAvailableForPlatform() {
+ availableToPlatform = false
+ // TODO(b/154889534) trigger an error when 'am' has "//apex_available:platform"
+ }
+ })
+
+ // Exception 1: stub libraries and native bridge libraries are always available to platform
+ if cc, ok := mctx.Module().(*cc.Module); ok &&
+ (cc.IsStubs() || cc.Target().NativeBridge == android.NativeBridgeEnabled) {
+ availableToPlatform = true
+ }
+
+ // Exception 2: bootstrap bionic libraries are also always available to platform
+ if cc.InstallToBootstrap(mctx.ModuleName(), mctx.Config()) {
+ availableToPlatform = true
+ }
+
+ if !availableToPlatform {
+ am.SetNotAvailableForPlatform()
+ }
+ }
+}
+
// 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 {
@@ -877,6 +851,9 @@
// 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 {
@@ -914,6 +891,9 @@
}
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") {
@@ -1096,8 +1076,10 @@
IsCoverageVariant bool `blueprint:"mutated"`
// Whether this APEX is considered updatable or not. When set to true, this will enforce additional
- // rules for making sure that the APEX is truely updatable. This will also disable the size optimizations
- // like symlinking to the system libs. Default is false.
+ // rules for making sure that the APEX is truly updatable.
+ // - To be updatable, min_sdk_version should be set as well
+ // This will also disable the size optimizations like symlinking to the system libs.
+ // Default is false.
Updatable *bool
// The minimum SDK version that this apex must be compatibile with.
@@ -1732,15 +1714,16 @@
func apexFileForAndroidApp(ctx android.BaseModuleContext, aapp interface {
android.Module
Privileged() bool
+ InstallApkName() string
OutputFile() android.Path
JacocoReportClassesFile() android.Path
Certificate() java.Certificate
-}, pkgName string) apexFile {
+}) apexFile {
appDir := "app"
if aapp.Privileged() {
appDir = "priv-app"
}
- dirInApex := filepath.Join(appDir, pkgName)
+ dirInApex := filepath.Join(appDir, aapp.InstallApkName())
fileToCopy := aapp.OutputFile()
af := newApexFile(ctx, fileToCopy, aapp.Name(), dirInApex, app, aapp)
af.jacocoReportClassesFile = aapp.JacocoReportClassesFile()
@@ -1796,14 +1779,11 @@
func (a *apexBundle) minSdkVersion(ctx android.BaseModuleContext) int {
ver := proptools.StringDefault(a.properties.Min_sdk_version, "current")
- if ver != "current" {
- minSdkVersion, err := strconv.Atoi(ver)
- if err != nil {
- ctx.PropertyErrorf("min_sdk_version", "should be \"current\" or <number>, but %q", ver)
- }
- return minSdkVersion
+ intVer, err := android.ApiStrToNum(ctx, ver)
+ if err != nil {
+ ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
}
- return android.FutureApiLevel
+ return intVer
}
// A regexp for removing boilerplate from BaseDependencyTag from the string representation of
@@ -1871,6 +1851,14 @@
})
}
+func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) {
+ if proptools.Bool(a.properties.Updatable) {
+ if String(a.properties.Min_sdk_version) == "" {
+ ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well")
+ }
+ }
+}
+
// Collects the list of module names that directly or indirectly contributes to the payload of this APEX
func (a *apexBundle) collectDepsInfo(ctx android.ModuleContext) {
a.depInfos = make(map[string]depInfo)
@@ -1936,6 +1924,7 @@
}
a.checkApexAvailability(ctx)
+ a.checkUpdatable(ctx)
a.collectDepsInfo(ctx)
@@ -2031,14 +2020,13 @@
ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child))
}
case androidAppTag:
- pkgName := ctx.DeviceConfig().OverridePackageNameFor(depName)
if ap, ok := child.(*java.AndroidApp); ok {
- filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap, pkgName))
+ filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap))
return true // track transitive dependencies
} else if ap, ok := child.(*java.AndroidAppImport); ok {
- filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap, pkgName))
+ filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap))
} else if ap, ok := child.(*java.AndroidTestHelperApp); ok {
- filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap, pkgName))
+ filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap))
} else {
ctx.PropertyErrorf("apps", "%q is not an android_app module", depName)
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 0c8937e..c4ab0be 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -1144,6 +1144,60 @@
expectNoLink("liba", "shared_otherapex", "libz", "shared")
}
+func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libx"],
+ min_sdk_version: "R",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libx",
+ shared_libs: ["libz"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ }
+
+ cc_library {
+ name: "libz",
+ system_shared_libs: [],
+ stl: "none",
+ stubs: {
+ versions: ["29", "R"],
+ },
+ }
+ `, func(fs map[string][]byte, config android.Config) {
+ config.TestProductVariables.Platform_version_active_codenames = []string{"R"}
+ })
+
+ expectLink := func(from, from_variant, to, to_variant string) {
+ ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
+ ensureContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
+ }
+ expectNoLink := func(from, from_variant, to, to_variant string) {
+ ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
+ ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
+ }
+ // 9000 is quite a magic number.
+ // Finalized SDK codenames are mapped as P(28), Q(29), ...
+ // And, codenames which are not finalized yet(active_codenames + future_codenames) are numbered from 9000, 9001, ...
+ // to distinguish them from finalized and future_api(10000)
+ // In this test, "R" is assumed not finalized yet( listed in Platform_version_active_codenames) and translated into 9000
+ // (refer android/api_levels.go)
+ expectLink("libx", "shared_myapex", "libz", "shared_9000")
+ expectNoLink("libx", "shared_myapex", "libz", "shared_29")
+ expectNoLink("libx", "shared_myapex", "libz", "shared")
+}
+
func TestApexMinSdkVersionDefaultsToLatest(t *testing.T) {
ctx, _ := testApex(t, `
apex {
@@ -1334,11 +1388,11 @@
}
`)
- testApexError(t, `"myapex" .*: min_sdk_version: should be "current" or <number>`, `
+ testApexError(t, `"myapex" .*: min_sdk_version: SDK version should be .*`, `
apex {
name: "myapex",
key: "myapex.key",
- min_sdk_version: "R",
+ min_sdk_version: "abc",
}
apex_key {
@@ -3428,6 +3482,7 @@
dex_preopt: {
enabled: false,
},
+ apex_available: ["myapex"],
}
android_app_import {
@@ -3438,6 +3493,8 @@
dex_preopt: {
enabled: false,
},
+ filename: "AwesomePrebuiltAppFooPriv.apk",
+ apex_available: ["myapex"],
}
`)
@@ -3446,7 +3503,48 @@
copyCmds := apexRule.Args["copy_commands"]
ensureContains(t, copyCmds, "image.apex/app/AppFooPrebuilt/AppFooPrebuilt.apk")
- ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPrivPrebuilt/AppFooPrivPrebuilt.apk")
+ ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPrivPrebuilt/AwesomePrebuiltAppFooPriv.apk")
+}
+
+func TestApexWithAppImportsPrefer(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ apps: [
+ "AppFoo",
+ ],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ android_app {
+ name: "AppFoo",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ apex_available: [ "myapex" ],
+ }
+
+ android_app_import {
+ name: "AppFoo",
+ apk: "AppFooPrebuilt.apk",
+ filename: "AppFooPrebuilt.apk",
+ presigned: true,
+ prefer: true,
+ apex_available: ["myapex"],
+ }
+ `, withFiles(map[string][]byte{
+ "AppFooPrebuilt.apk": nil,
+ }))
+
+ ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
+ "app/AppFoo/AppFooPrebuilt.apk",
+ })
}
func TestApexWithTestHelperApp(t *testing.T) {
@@ -3652,22 +3750,12 @@
}`)
}
-func TestApexAvailable_CreatedForPlatform(t *testing.T) {
- // check that libfoo and libbar are created only for myapex, but not for the platform
- // TODO(jiyong) the checks for the platform variant are removed because we now create
- // the platform variant regardless of the apex_availability. Instead, we will make sure that
- // the platform variants are not used from other platform modules. When that is done,
- // these checks will be replaced by expecting a specific error message that will be
- // emitted when the platform variant is used.
- // ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared_myapex")
- // ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared")
- // ensureListContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared_myapex")
- // ensureListNotContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared")
-
+func TestApexAvailable_CheckForPlatform(t *testing.T) {
ctx, _ := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
+ native_shared_libs: ["libbar", "libbaz"],
}
apex_key {
@@ -3680,16 +3768,52 @@
name: "libfoo",
stl: "none",
system_shared_libs: [],
+ shared_libs: ["libbar"],
apex_available: ["//apex_available:platform"],
+ }
+
+ cc_library {
+ name: "libfoo2",
+ stl: "none",
+ system_shared_libs: [],
+ shared_libs: ["libbaz"],
+ apex_available: ["//apex_available:platform"],
+ }
+
+ cc_library {
+ name: "libbar",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: ["myapex"],
+ }
+
+ cc_library {
+ name: "libbaz",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: ["myapex"],
+ stubs: {
+ versions: ["1"],
+ },
}`)
- // check that libfoo is created only for the platform
- ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared_myapex")
- ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared")
+ // libfoo shouldn't be available to platform even though it has "//apex_available:platform",
+ // because it depends on libbar which isn't available to platform
+ libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+ if libfoo.NotAvailableForPlatform() != true {
+ t.Errorf("%q shouldn't be available to platform", libfoo.String())
+ }
+
+ // libfoo2 however can be available to platform because it depends on libbaz which provides
+ // stubs
+ libfoo2 := ctx.ModuleForTests("libfoo2", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+ if libfoo2.NotAvailableForPlatform() == true {
+ t.Errorf("%q should be available to platform", libfoo2.String())
+ }
}
func TestApexAvailable_CreatedForApex(t *testing.T) {
- testApex(t, `
+ ctx, _ := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -3712,17 +3836,14 @@
},
}`)
- // shared variant of libfoo is only available to myapex
- // TODO(jiyong) the checks for the platform variant are removed because we now create
- // the platform variant regardless of the apex_availability. Instead, we will make sure that
- // the platform variants are not used from other platform modules. When that is done,
- // these checks will be replaced by expecting a specific error message that will be
- // emitted when the platform variant is used.
- // ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared_myapex")
- // ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared")
- // // but the static variant is available to both myapex and the platform
- // ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_static_myapex")
- // ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_static")
+ libfooShared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+ if libfooShared.NotAvailableForPlatform() != true {
+ t.Errorf("%q shouldn't be available to platform", libfooShared.String())
+ }
+ libfooStatic := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Module().(*cc.Module)
+ if libfooStatic.NotAvailableForPlatform() != false {
+ t.Errorf("%q should be available to platform", libfooStatic.String())
+ }
}
func TestOverrideApex(t *testing.T) {
@@ -3779,7 +3900,7 @@
copyCmds := apexRule.Args["copy_commands"]
ensureNotContains(t, copyCmds, "image.apex/app/app/app.apk")
- ensureContains(t, copyCmds, "image.apex/app/app/override_app.apk")
+ ensureContains(t, copyCmds, "image.apex/app/override_app/override_app.apk")
apexBundle := module.Module().(*apexBundle)
name := apexBundle.Name()
@@ -4001,6 +4122,7 @@
native_shared_libs: ["mylib"],
java_libs: ["myjar"],
updatable: true,
+ min_sdk_version: "current",
}
apex_key {
@@ -4151,6 +4273,27 @@
})
}
+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 {
@@ -4214,6 +4357,13 @@
"system/sepolicy/apex/some-updatable-apex-file_contexts",
],
}
+
+ filegroup {
+ name: "some-non-updatable-apex-file_contexts",
+ srcs: [
+ "system/sepolicy/apex/some-non-updatable-apex-file_contexts",
+ ],
+ }
`
bp += cc.GatherRequiredDepsForTest(android.Android)
bp += java.GatherRequiredDepsForTest()
@@ -4226,6 +4376,7 @@
"apex_manifest.json": nil,
"AndroidManifest.xml": nil,
"system/sepolicy/apex/some-updatable-apex-file_contexts": nil,
+ "system/sepolicy/apex/some-non-updatable-apex-file_contexts": nil,
"system/sepolicy/apex/com.android.art.something-file_contexts": nil,
"framework/aidl/a.aidl": nil,
}
@@ -4269,6 +4420,22 @@
}
}
+func TestUpdatable_should_set_min_sdk_version(t *testing.T) {
+ testApexError(t, `"myapex" .*: updatable: updatable APEXes should set min_sdk_version`, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ updatable: true,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ `)
+}
+
func TestNoUpdatableJarsInBootImage(t *testing.T) {
bp := `
java_library {
@@ -4280,6 +4447,14 @@
}
java_library {
+ name: "some-non-updatable-apex-lib",
+ srcs: ["a.java"],
+ apex_available: [
+ "some-non-updatable-apex",
+ ],
+ }
+
+ java_library {
name: "some-platform-lib",
srcs: ["a.java"],
installable: true,
@@ -4298,16 +4473,30 @@
name: "some-updatable-apex",
key: "some-updatable-apex.key",
java_libs: ["some-updatable-apex-lib"],
+ updatable: true,
+ min_sdk_version: "current",
+ }
+
+ apex {
+ name: "some-non-updatable-apex",
+ key: "some-non-updatable-apex.key",
+ java_libs: ["some-non-updatable-apex-lib"],
}
apex_key {
name: "some-updatable-apex.key",
}
+ apex_key {
+ name: "some-non-updatable-apex.key",
+ }
+
apex {
name: "com.android.art.something",
key: "com.android.art.something.key",
java_libs: ["some-art-lib"],
+ updatable: true,
+ min_sdk_version: "current",
}
apex_key {
@@ -4338,6 +4527,13 @@
}
testNoUpdatableJarsInBootImage(t, error, bp, transform)
+ // non-updatable jar from some other apex in the ART boot image => error
+ error = "module 'some-non-updatable-apex-lib' is not allowed in the ART boot image"
+ transform = func(config *dexpreopt.GlobalConfig) {
+ config.ArtApexJars = []string{"some-non-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) {
@@ -4345,6 +4541,12 @@
}
testNoUpdatableJarsInBootImage(t, error, bp, transform)
+ // non-updatable jar from some other apex in the framework boot image => ok
+ transform = func(config *dexpreopt.GlobalConfig) {
+ config.BootJars = []string{"some-non-updatable-apex-lib"}
+ }
+ testNoUpdatableJarsInBootImage(t, "", 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) {
@@ -4360,7 +4562,7 @@
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"
+ error = "module 'some-platform-lib' is not allowed in the ART boot image"
transform = func(config *dexpreopt.GlobalConfig) {
config.ArtApexJars = []string{"some-platform-lib"}
}
@@ -4373,6 +4575,58 @@
testNoUpdatableJarsInBootImage(t, "", bp, transform)
}
+func TestTestFor(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib", "myprivlib"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ stubs: {
+ versions: ["1"],
+ },
+ apex_available: ["myapex"],
+ }
+
+ cc_library {
+ name: "myprivlib",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: ["myapex"],
+ }
+
+
+ cc_test {
+ name: "mytest",
+ gtest: false,
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ shared_libs: ["mylib", "myprivlib"],
+ test_for: ["myapex"]
+ }
+ `)
+
+ // the test 'mytest' is a test for the apex, therefore is linked to the
+ // actual implementation of mylib instead of its stub.
+ ldFlags := ctx.ModuleForTests("mytest", "android_arm64_armv8-a").Rule("ld").Args["libFlags"]
+ ensureContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared/mylib.so")
+ ensureNotContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared_1/mylib.so")
+}
+
func TestMain(m *testing.M) {
run := func() int {
setUp()
diff --git a/apex/vndk.go b/apex/vndk.go
index 2a0d5b0..f948d76 100644
--- a/apex/vndk.go
+++ b/apex/vndk.go
@@ -16,6 +16,7 @@
import (
"path/filepath"
+ "strconv"
"strings"
"sync"
@@ -121,10 +122,13 @@
// 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/cc/androidmk.go b/cc/androidmk.go
index 19c7182..5438b14 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -271,6 +271,10 @@
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)
diff --git a/cc/builder.go b/cc/builder.go
index 136263b..990069d 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -29,6 +29,7 @@
"android/soong/android"
"android/soong/cc/config"
+ "android/soong/remoteexec"
)
const (
@@ -37,13 +38,6 @@
)
var (
- abiCheckAllowFlags = []string{
- "-allow-unreferenced-changes",
- "-allow-unreferenced-elf-symbol-changes",
- }
-)
-
-var (
pctx = android.NewPackageContext("android/soong/cc")
cc = pctx.AndroidRemoteStaticRule("cc", android.RemoteRuleSupports{Goma: true, RBE: true},
@@ -62,7 +56,7 @@
},
"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 +66,28 @@
// clang -Wl,--out-implib doesn't update its output file if it hasn't changed.
Restat: true,
},
- "ldCmd", "crtBegin", "libFlags", "crtEnd", "ldFlags", "extraLibFlags")
+ &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 = pctx.AndroidStaticRule("partialLd",
+ 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{
@@ -208,8 +214,7 @@
sAbiDiff = pctx.RuleFunc("sAbiDiff",
func(ctx android.PackageRuleContext) blueprint.RuleParams {
- // TODO(b/78139997): Add -check-all-apis back
- commandStr := "($sAbiDiffer ${allowFlags} -lib ${libName} -arch ${arch} -o ${out} -new ${in} -old ${referenceDump})"
+ commandStr := "($sAbiDiffer ${extraFlags} -lib ${libName} -arch ${arch} -o ${out} -new ${in} -old ${referenceDump})"
commandStr += "|| (echo 'error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py ${createReferenceDumpFlags} -l ${libName}'"
commandStr += " && (mkdir -p $$DIST_DIR/abidiffs && cp ${out} $$DIST_DIR/abidiffs/)"
commandStr += " && exit 1)"
@@ -218,7 +223,7 @@
CommandDeps: []string{"$sAbiDiffer"},
}
},
- "allowFlags", "referenceDump", "libName", "arch", "createReferenceDumpFlags")
+ "extraFlags", "referenceDump", "libName", "arch", "createReferenceDumpFlags")
unzipRefSAbiDump = pctx.AndroidStaticRule("unzipRefSAbiDump",
blueprint.RuleParams{
@@ -262,6 +267,7 @@
}
pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
+ pctx.Import("android/soong/remoteexec")
}
type builderFlags struct {
@@ -293,7 +299,7 @@
rsFlags string
toolchain config.Toolchain
tidy bool
- coverage bool
+ gcovCoverage bool
sAbiDump bool
emitXrefs bool
@@ -355,7 +361,7 @@
tidyFiles = make(android.Paths, 0, len(srcFiles))
}
var coverageFiles android.Paths
- if flags.coverage {
+ if flags.gcovCoverage {
coverageFiles = make(android.Paths, 0, len(srcFiles))
}
var kytheFiles android.Paths
@@ -456,7 +462,7 @@
var ccCmd string
tidy := flags.tidy
- coverage := flags.coverage
+ coverage := flags.gcovCoverage
dump := flags.sAbiDump
rule := cc
emitXref := flags.emitXrefs
@@ -657,8 +663,13 @@
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,
@@ -723,27 +734,36 @@
}
func SourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceDump android.Path,
- baseName, exportedHeaderFlags string, isLlndk, isNdk, isVndkExt bool) android.OptionalPath {
+ baseName, exportedHeaderFlags string, checkAllApis, isLlndk, isNdk, isVndkExt bool) android.OptionalPath {
outputFile := android.PathForModuleOut(ctx, baseName+".abidiff")
libName := strings.TrimSuffix(baseName, filepath.Ext(baseName))
createReferenceDumpFlags := ""
- localAbiCheckAllowFlags := append([]string(nil), abiCheckAllowFlags...)
- if exportedHeaderFlags == "" {
- localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-advice-only")
+ var extraFlags []string
+ if checkAllApis {
+ extraFlags = append(extraFlags, "-check-all-apis")
+ } else {
+ extraFlags = append(extraFlags,
+ "-allow-unreferenced-changes",
+ "-allow-unreferenced-elf-symbol-changes")
}
+
+ if exportedHeaderFlags == "" {
+ extraFlags = append(extraFlags, "-advice-only")
+ }
+
if isLlndk || isNdk {
createReferenceDumpFlags = "--llndk"
if isLlndk {
// TODO(b/130324828): "-consider-opaque-types-different" should apply to
// both LLNDK and NDK shared libs. However, a known issue in header-abi-diff
// breaks libaaudio. Remove the if-guard after the issue is fixed.
- localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-consider-opaque-types-different")
+ extraFlags = append(extraFlags, "-consider-opaque-types-different")
}
}
if isVndkExt {
- localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-allow-extensions")
+ extraFlags = append(extraFlags, "-allow-extensions")
}
ctx.Build(pctx, android.BuildParams{
@@ -756,7 +776,7 @@
"referenceDump": referenceDump.String(),
"libName": libName,
"arch": ctx.Arch().ArchType.Name,
- "allowFlags": strings.Join(localAbiCheckAllowFlags, " "),
+ "extraFlags": strings.Join(extraFlags, " "),
"createReferenceDumpFlags": createReferenceDumpFlags,
},
})
@@ -798,16 +818,22 @@
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 4667a3d..66425c7 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -182,11 +182,11 @@
// These must be after any module include flags, which will be in CommonFlags.
SystemIncludeFlags []string
- Toolchain config.Toolchain
- Tidy bool
- Coverage bool
- SAbiDump bool
- EmitXrefs bool // If true, generate Ninja rules to generate emitXrefs input files for Kythe
+ Toolchain config.Toolchain
+ Tidy bool
+ GcovCoverage bool
+ SAbiDump bool
+ EmitXrefs bool // If true, generate Ninja rules to generate emitXrefs input files for Kythe
RequiredInstructionSet string
DynamicLinker string
@@ -213,6 +213,9 @@
// two variants to be built, one for the platform and one for apps.
Sdk_version *string
+ // Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
+ Min_sdk_version *string
+
// If true, always create an sdk variant and don't create a platform variant.
Sdk_variant_only *bool
@@ -404,6 +407,7 @@
inSanitizerDir() bool
hostToolPath() android.OptionalPath
relativeInstallPath() string
+ skipInstall(mod *Module)
}
type xref interface {
@@ -1118,7 +1122,7 @@
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
@@ -1194,6 +1198,11 @@
return false
}
+ // Coverage builds have extra symbols.
+ if ctx.mod.isCoverageVariant() {
+ return false
+ }
+
if ctx.ctx.Fuchsia() {
return false
}
@@ -1900,8 +1909,7 @@
addSharedLibDependencies := func(depTag DependencyTag, name string, version string) {
var variations []blueprint.Variation
variations = append(variations, blueprint.Variation{Mutator: "link", Variation: "shared"})
- versionVariantAvail := !c.InRecovery() && !c.InRamdisk()
- if version != "" && versionVariantAvail {
+ if version != "" && VersionVariantAvailable(c) {
// Version is explicitly specified. i.e. libFoo#30
variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version})
depTag.ExplicitlyVersioned = true
@@ -1911,7 +1919,7 @@
// If the version is not specified, add dependency to all stubs libraries.
// The stubs library will be used when the depending module is built for APEX and
// the dependent module is not in the same APEX.
- if version == "" && versionVariantAvail {
+ if version == "" && VersionVariantAvailable(c) {
for _, ver := range stubsVersionsFor(actx.Config())[name] {
// Note that depTag.ExplicitlyVersioned is false in this case.
actx.AddVariationDependencies([]blueprint.Variation{
@@ -2309,7 +2317,7 @@
}
if ccDep.CcLibrary() && !depIsStatic {
depIsStubs := ccDep.BuildStubs()
- depHasStubs := ccDep.HasStubsVariants()
+ depHasStubs := VersionVariantAvailable(c) && ccDep.HasStubsVariants()
depInSameApex := android.DirectlyInApex(c.ApexName(), depName)
depInPlatform := !android.DirectlyInAnyApex(ctx, depName)
@@ -2325,11 +2333,20 @@
// If not building for APEX, use stubs only when it is from
// an APEX (and not from platform)
useThisDep = (depInPlatform != depIsStubs)
- if c.InRamdisk() || c.InRecovery() || c.bootstrap() {
- // However, for ramdisk, recovery or bootstrap modules,
+ if c.bootstrap() {
+ // However, for host, ramdisk, recovery or bootstrap modules,
// always link to non-stub variant
useThisDep = !depIsStubs
}
+ for _, testFor := range c.TestFor() {
+ // Another exception: if this module is bundled with an APEX, then
+ // it is linked with the non-stub variant of a module in the APEX
+ // as if this is part of the APEX.
+ if android.DirectlyInApex(testFor, depName) {
+ useThisDep = !depIsStubs
+ break
+ }
+ }
} else {
// If building for APEX, use stubs only when it is not from
// the same APEX
@@ -2639,6 +2656,14 @@
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{}
@@ -2748,6 +2773,16 @@
}
}
+func (c *Module) TestFor() []string {
+ if test, ok := c.linker.(interface {
+ testFor() []string
+ }); ok {
+ return test.testFor()
+ } else {
+ return c.ApexModuleBase.TestFor()
+ }
+}
+
// Return true if the module is ever installable.
func (c *Module) EverInstallable() bool {
return c.installer != nil &&
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 19aedd9..5575baa 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -37,10 +37,8 @@
}
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 274ccd5..bdd9030 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -80,10 +80,8 @@
// 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 5611a96..d85ac5f 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -18,6 +18,7 @@
"strings"
"android/soong/android"
+ "android/soong/remoteexec"
)
var (
@@ -255,6 +256,9 @@
}
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 @@
"-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/coverage.go b/cc/coverage.go
index b94b628..bde07fd 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -82,10 +82,10 @@
}
if cov.Properties.CoverageEnabled {
- flags.Coverage = true
cov.linkCoverage = true
if gcovCoverage {
+ flags.GcovCoverage = true
flags.Local.CommonFlags = append(flags.Local.CommonFlags, "--coverage", "-O0")
// Override -Wframe-larger-than and non-default optimization
diff --git a/cc/installer.go b/cc/installer.go
index 200d59e..0b4a68c 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -106,3 +106,7 @@
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/libbuildversion/Android.bp b/cc/libbuildversion/Android.bp
index 825b920..b63338d 100644
--- a/cc/libbuildversion/Android.bp
+++ b/cc/libbuildversion/Android.bp
@@ -10,4 +10,8 @@
enabled: true,
},
},
+ apex_available: [
+ "//apex_available:platform",
+ "//apex_available:anyapex",
+ ],
}
diff --git a/cc/library.go b/cc/library.go
index 140f87a..ecea2ea 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -102,6 +102,10 @@
// Symbol tags that should be ignored from the symbol file
Exclude_symbol_tags []string
+
+ // Run checks on all APIs (in addition to the ones referred by
+ // one of exported ELF symbols.)
+ Check_all_apis *bool
}
// Order symbols in .bss section by their sizes. Only useful for shared libraries.
@@ -1072,7 +1076,9 @@
refAbiDumpFile := getRefAbiDumpFile(ctx, vndkVersion, fileName)
if refAbiDumpFile != nil {
library.sAbiDiff = SourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
- refAbiDumpFile, fileName, exportedHeaderFlags, ctx.isLlndk(ctx.Config()), ctx.isNdk(), ctx.isVndkExt())
+ refAbiDumpFile, fileName, exportedHeaderFlags,
+ Bool(library.Properties.Header_abi_checker.Check_all_apis),
+ ctx.isLlndk(ctx.Config()), ctx.isNdk(), ctx.isVndkExt())
}
}
}
@@ -1329,6 +1335,18 @@
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 {
@@ -1489,18 +1507,22 @@
return ""
}
-func checkVersions(ctx android.BaseModuleContext, versions []string) {
+func normalizeVersions(ctx android.BaseModuleContext, versions []string) {
numVersions := make([]int, len(versions))
for i, v := range versions {
- numVer, err := strconv.Atoi(v)
+ numVer, err := android.ApiStrToNum(ctx, v)
if err != nil {
- ctx.PropertyErrorf("versions", "%q is not a number", v)
+ ctx.PropertyErrorf("versions", "%s", err.Error())
+ return
}
numVersions[i] = numVer
}
if !sort.IsSorted(sort.IntSlice(numVersions)) {
ctx.PropertyErrorf("versions", "not sorted: %v", versions)
}
+ for i, v := range numVersions {
+ versions[i] = strconv.Itoa(v)
+ }
}
func createVersionVariations(mctx android.BottomUpMutatorContext, versions []string) {
@@ -1516,13 +1538,21 @@
}
}
-// Version mutator splits a module into the mandatory non-stubs variant
+func VersionVariantAvailable(module interface {
+ Host() bool
+ InRamdisk() bool
+ InRecovery() bool
+}) bool {
+ return !module.Host() && !module.InRamdisk() && !module.InRecovery()
+}
+
+// VersionMutator splits a module into the mandatory non-stubs variant
// (which is unnamed) and zero or more stubs variants.
func VersionMutator(mctx android.BottomUpMutatorContext) {
- if library, ok := mctx.Module().(LinkableInterface); ok && !library.InRecovery() {
+ if library, ok := mctx.Module().(LinkableInterface); ok && VersionVariantAvailable(library) {
if library.CcLibrary() && library.BuildSharedVariant() && len(library.StubsVersions()) > 0 {
versions := library.StubsVersions()
- checkVersions(mctx, versions)
+ normalizeVersions(mctx, versions)
if mctx.Failed() {
return
}
@@ -1555,7 +1585,7 @@
}
if genrule, ok := mctx.Module().(*genrule.Module); ok {
if _, ok := genrule.Extra.(*GenruleExtraProperties); ok {
- if !genrule.InRecovery() {
+ if VersionVariantAvailable(genrule) {
mctx.CreateVariations("")
return
}
diff --git a/cc/library_test.go b/cc/library_test.go
index b8d8895..cb16725 100644
--- a/cc/library_test.go
+++ b/cc/library_test.go
@@ -17,6 +17,8 @@
import (
"reflect"
"testing"
+
+ "android/soong/android"
)
func TestLibraryReuse(t *testing.T) {
@@ -186,3 +188,55 @@
}
})
}
+
+func TestStubsVersions(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "libfoo",
+ srcs: ["foo.c"],
+ stubs: {
+ versions: ["29", "R", "10000"],
+ },
+ }
+ `
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.Platform_version_active_codenames = []string{"R"}
+ ctx := testCcWithConfig(t, config)
+
+ variants := ctx.ModuleVariantsForTests("libfoo")
+ for _, expectedVer := range []string{"29", "9000", "10000"} {
+ expectedVariant := "android_arm_armv7-a-neon_shared_" + expectedVer
+ if !inList(expectedVariant, variants) {
+ t.Errorf("missing expected variant: %q", expectedVariant)
+ }
+ }
+}
+
+func TestStubsVersions_NotSorted(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "libfoo",
+ srcs: ["foo.c"],
+ stubs: {
+ versions: ["29", "10000", "R"],
+ },
+ }
+ `
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.Platform_version_active_codenames = []string{"R"}
+ testCcErrorWithConfig(t, `"libfoo" .*: versions: not sorted`, config)
+}
+
+func TestStubsVersions_ParseError(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "libfoo",
+ srcs: ["foo.c"],
+ stubs: {
+ versions: ["29", "10000", "X"],
+ },
+ }
+ `
+
+ testCcError(t, `"libfoo" .*: versions: SDK version should be`, bp)
+}
diff --git a/cc/linkable.go b/cc/linkable.go
index fbe61a4..4a70d48 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -39,6 +39,8 @@
Shared() bool
Toc() android.OptionalPath
+ Host() bool
+
InRamdisk() bool
OnlyInRamdisk() bool
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 09050aa..7ff20f4 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -83,7 +83,7 @@
func (stub *llndkStubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
vndkVer := ctx.Module().(*Module).VndkVersion()
- if !inList(vndkVer, ctx.Config().PlatformVersionCombinedCodenames()) || vndkVer == "" {
+ if !inList(vndkVer, ctx.Config().PlatformVersionActiveCodenames()) || vndkVer == "" {
// For non-enforcing devices, vndkVer is empty. Use "current" in that case, too.
vndkVer = "current"
}
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 68d4ac0..1597b88 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -96,6 +96,8 @@
Unversioned_until *string
// Private property for use by the mutator that splits per-API level.
+ // can be one of <number:sdk_version> or <codename> or "current"
+ // passed to "gen_stub_libs.py" as it is
ApiLevel string `blueprint:"mutated"`
// True if this API is not yet ready to be shipped in the NDK. It will be
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index fc9cc17..ac990f3 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -43,6 +43,11 @@
// 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 @@
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 @@
// 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)
- return in
+ 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",
+ },
+ })
+ }
+
+ 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 @@
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 @@
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 0b018c1..adb44bd 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -184,7 +184,7 @@
})
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 @@
})
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 @@
})
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/test.go b/cc/test.go
index 1085d3a..f51cf01 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -29,6 +29,11 @@
// if set, use the isolated gtest runner. Defaults to false.
Isolated *bool
+
+ // List of APEXes that this module tests. The module has access to
+ // the private part of the listed APEXes even when it is not included in the
+ // APEXes.
+ Test_for []string
}
// Test option struct.
@@ -215,6 +220,10 @@
return BoolDefault(test.Properties.Gtest, true)
}
+func (test *testDecorator) testFor() []string {
+ return test.Properties.Test_for
+}
+
func (test *testDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
if !test.gtest() {
return flags
diff --git a/cc/util.go b/cc/util.go
index 60070bb..af26268 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -82,7 +82,7 @@
tidyFlags: strings.Join(in.TidyFlags, " "),
sAbiFlags: strings.Join(in.SAbiFlags, " "),
toolchain: in.Toolchain,
- coverage: in.Coverage,
+ gcovCoverage: in.GcovCoverage,
tidy: in.Tidy,
sAbiDump: in.SAbiDump,
emitXrefs: in.EmitXrefs,
diff --git a/java/androidmk.go b/java/androidmk.go
index d37eac8..68da23e 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -472,34 +472,6 @@
if ddoc.Javadoc.stubsSrcJar != nil {
entries.SetPath("LOCAL_DROIDDOC_STUBS_SRCJAR", ddoc.Javadoc.stubsSrcJar)
}
- apiFilePrefix := "INTERNAL_PLATFORM_"
- if String(ddoc.properties.Api_tag_name) != "" {
- apiFilePrefix += String(ddoc.properties.Api_tag_name) + "_"
- }
- if ddoc.apiFile != nil {
- entries.SetPath(apiFilePrefix+"API_FILE", ddoc.apiFile)
- }
- if ddoc.dexApiFile != nil {
- entries.SetPath(apiFilePrefix+"DEX_API_FILE", ddoc.dexApiFile)
- }
- if ddoc.privateApiFile != nil {
- entries.SetPath(apiFilePrefix+"PRIVATE_API_FILE", ddoc.privateApiFile)
- }
- if ddoc.privateDexApiFile != nil {
- entries.SetPath(apiFilePrefix+"PRIVATE_DEX_API_FILE", ddoc.privateDexApiFile)
- }
- if ddoc.removedApiFile != nil {
- entries.SetPath(apiFilePrefix+"REMOVED_API_FILE", ddoc.removedApiFile)
- }
- if ddoc.removedDexApiFile != nil {
- entries.SetPath(apiFilePrefix+"REMOVED_DEX_API_FILE", ddoc.removedDexApiFile)
- }
- if ddoc.exactApiFile != nil {
- entries.SetPath(apiFilePrefix+"EXACT_API_FILE", ddoc.exactApiFile)
- }
- if ddoc.proguardFile != nil {
- entries.SetPath(apiFilePrefix+"PROGUARD_FILE", ddoc.proguardFile)
- }
},
},
ExtraFooters: []android.AndroidMkExtraFootersFunc{
@@ -578,35 +550,18 @@
if dstubs.metadataZip != nil {
entries.SetPath("LOCAL_DROIDDOC_METADATA_ZIP", dstubs.metadataZip)
}
- apiFilePrefix := "INTERNAL_PLATFORM_"
- if String(dstubs.properties.Api_tag_name) != "" {
- apiFilePrefix += String(dstubs.properties.Api_tag_name) + "_"
- }
- if dstubs.apiFile != nil {
- entries.SetPath(apiFilePrefix+"API_FILE", dstubs.apiFile)
- }
- if dstubs.dexApiFile != nil {
- entries.SetPath(apiFilePrefix+"DEX_API_FILE", dstubs.dexApiFile)
- }
- if dstubs.privateApiFile != nil {
- entries.SetPath(apiFilePrefix+"PRIVATE_API_FILE", dstubs.privateApiFile)
- }
- if dstubs.privateDexApiFile != nil {
- entries.SetPath(apiFilePrefix+"PRIVATE_DEX_API_FILE", dstubs.privateDexApiFile)
- }
- if dstubs.removedApiFile != nil {
- entries.SetPath(apiFilePrefix+"REMOVED_API_FILE", dstubs.removedApiFile)
- }
- if dstubs.removedDexApiFile != nil {
- entries.SetPath(apiFilePrefix+"REMOVED_DEX_API_FILE", dstubs.removedDexApiFile)
- }
- if dstubs.exactApiFile != nil {
- entries.SetPath(apiFilePrefix+"EXACT_API_FILE", dstubs.exactApiFile)
- }
},
},
ExtraFooters: []android.AndroidMkExtraFootersFunc{
func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
+ if dstubs.apiFile != nil {
+ fmt.Fprintf(w, ".PHONY: %s %s.txt\n", dstubs.Name(), dstubs.Name())
+ fmt.Fprintf(w, "%s %s.txt: %s\n", dstubs.Name(), dstubs.Name(), dstubs.apiFile)
+ }
+ if dstubs.removedApiFile != nil {
+ fmt.Fprintf(w, ".PHONY: %s %s.txt\n", dstubs.Name(), dstubs.Name())
+ fmt.Fprintf(w, "%s %s.txt: %s\n", dstubs.Name(), dstubs.Name(), dstubs.removedApiFile)
+ }
if dstubs.checkCurrentApiTimestamp != nil {
fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-check-current-api")
fmt.Fprintln(w, dstubs.Name()+"-check-current-api:",
@@ -633,14 +588,12 @@
fmt.Fprintln(w, dstubs.Name()+"-check-last-released-api:",
dstubs.checkLastReleasedApiTimestamp.String())
- if dstubs.Name() != "android.car-system-stubs-docs" {
- fmt.Fprintln(w, ".PHONY: checkapi")
- fmt.Fprintln(w, "checkapi:",
- dstubs.checkLastReleasedApiTimestamp.String())
+ fmt.Fprintln(w, ".PHONY: checkapi")
+ fmt.Fprintln(w, "checkapi:",
+ dstubs.checkLastReleasedApiTimestamp.String())
- fmt.Fprintln(w, ".PHONY: droidcore")
- fmt.Fprintln(w, "droidcore: checkapi")
- }
+ fmt.Fprintln(w, ".PHONY: droidcore")
+ fmt.Fprintln(w, "droidcore: checkapi")
}
if dstubs.apiLintTimestamp != nil {
fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-api-lint")
@@ -673,6 +626,11 @@
}
func (a *AndroidAppImport) AndroidMkEntries() []android.AndroidMkEntries {
+ if !a.IsForPlatform() {
+ // The non-platform variant is placed inside APEX. No reason to
+ // make it available to Make.
+ return nil
+ }
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "APPS",
OutputFile: android.OptionalPathForPath(a.outputFile),
diff --git a/java/app.go b/java/app.go
index ae9cd5f..276ab9c 100755
--- a/java/app.go
+++ b/java/app.go
@@ -110,6 +110,12 @@
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 to make sure an app can safely be updated. Default is false.
+ // Prefer using other specific properties if build behaviour must be changed; avoid using this
+ // flag for anything but neverallow rules (unless the behaviour change is invisible to owners).
+ Updatable *bool
}
// android_app properties that can be overridden by override_android_app
@@ -249,11 +255,24 @@
}
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())
+ }
+ if String(a.deviceProperties.Min_sdk_version) == "" {
+ ctx.PropertyErrorf("updatable", "updatable apps must set min_sdk_version.")
+ }
+ }
+
+ 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 {
@@ -497,6 +516,10 @@
return certificates
}
+func (a *AndroidApp) InstallApkName() string {
+ return a.installApkName
+}
+
func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
var apkDeps android.Paths
@@ -968,6 +991,7 @@
type AndroidAppImport struct {
android.ModuleBase
android.DefaultableModuleBase
+ android.ApexModuleBase
prebuilt android.Prebuilt
properties AndroidAppImportProperties
@@ -1120,6 +1144,10 @@
a.generateAndroidBuildActions(ctx)
}
+func (a *AndroidAppImport) InstallApkName() string {
+ return a.BaseModuleName()
+}
+
func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext) {
numCertPropsSet := 0
if String(a.properties.Certificate) != "" {
@@ -1177,6 +1205,8 @@
dexOutput = dexUncompressed
}
+ apkFilename := proptools.StringDefault(a.properties.Filename, a.BaseModuleName()+".apk")
+
// Sign or align the package
// TODO: Handle EXTERNAL
if !Bool(a.properties.Presigned) {
@@ -1187,11 +1217,11 @@
ctx.ModuleErrorf("Unexpected number of certificates were extracted: %q", certificates)
}
a.certificate = certificates[0]
- signed := android.PathForModuleOut(ctx, "signed", ctx.ModuleName()+".apk")
+ signed := android.PathForModuleOut(ctx, "signed", apkFilename)
SignAppPackage(ctx, signed, dexOutput, certificates, nil)
a.outputFile = signed
} else {
- alignedApk := android.PathForModuleOut(ctx, "zip-aligned", ctx.ModuleName()+".apk")
+ alignedApk := android.PathForModuleOut(ctx, "zip-aligned", apkFilename)
TransformZipAlign(ctx, alignedApk, dexOutput)
a.outputFile = alignedApk
a.certificate = presignedCertificate
@@ -1199,8 +1229,9 @@
// TODO: Optionally compress the output apk.
- a.installPath = ctx.InstallFile(installDir,
- proptools.StringDefault(a.properties.Filename, a.BaseModuleName()+".apk"), a.outputFile)
+ if a.IsForPlatform() {
+ a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile)
+ }
// TODO: androidmk converter jni libs
}
@@ -1251,6 +1282,13 @@
return Bool(a.properties.Privileged)
}
+func (a *AndroidAppImport) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+ // android_app_import might have extra dependencies via uses_libs property.
+ // Don't track the dependency as we don't automatically add those libraries
+ // to the classpath. It should be explicitly added to java_libs property of APEX
+ return false
+}
+
func createVariantGroupType(variants []string, variantGroupName string) reflect.Type {
props := reflect.TypeOf((*AndroidAppImportProperties)(nil))
@@ -1297,6 +1335,7 @@
module.processVariants(ctx)
})
+ android.InitApexModule(module)
InitJavaModule(module, android.DeviceSupported)
android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk")
@@ -1334,6 +1373,7 @@
module.processVariants(ctx)
})
+ android.InitApexModule(module)
InitJavaModule(module, android.DeviceSupported)
android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk")
diff --git a/java/app_test.go b/java/app_test.go
index 43696db..4178d5e 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -264,6 +264,127 @@
`)
}
+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",
+ min_sdk_version: "29",
+ updatable: true,
+ }`,
+ },
+ {
+ name: "Stable system SDK",
+ bp: `android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "system_29",
+ min_sdk_version: "29",
+ updatable: true,
+ }`,
+ },
+ {
+ name: "Current public SDK",
+ bp: `android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ min_sdk_version: "29",
+ updatable: true,
+ }`,
+ },
+ {
+ name: "Current system SDK",
+ bp: `android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "system_current",
+ min_sdk_version: "29",
+ updatable: true,
+ }`,
+ },
+ {
+ name: "Current module SDK",
+ bp: `android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "module_current",
+ min_sdk_version: "29",
+ updatable: true,
+ }`,
+ },
+ {
+ name: "Current core SDK",
+ bp: `android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "core_current",
+ min_sdk_version: "29",
+ updatable: true,
+ }`,
+ },
+ {
+ name: "No Platform APIs",
+ bp: `android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ platform_apis: true,
+ min_sdk_version: "29",
+ 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",
+ min_sdk_version: "29",
+ updatable: true,
+ }`,
+ expectedError: "Updatable apps must use stable SDKs",
+ },
+ {
+ name: "No unspecified APIs",
+ bp: `android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ updatable: true,
+ min_sdk_version: "29",
+ }`,
+ expectedError: "Updatable apps must use stable SDK",
+ },
+ {
+ name: "Must specify min_sdk_version",
+ bp: `android_app {
+ name: "app_without_min_sdk_version",
+ srcs: ["a.java"],
+ sdk_version: "29",
+ updatable: true,
+ }`,
+ expectedError: "updatable apps must set min_sdk_version.",
+ },
+ }
+
+ 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
diff --git a/java/builder.go b/java/builder.go
index 3a0247d..6844809 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -147,7 +147,12 @@
jarjar = pctx.AndroidStaticRule("jarjar",
blueprint.RuleParams{
- Command: "${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.JarjarCmd} process $rulesFile $in $out",
+ Command: "${config.JavaCmd} ${config.JavaVmFlags}" +
+ // b/146418363 Enable Android specific jarjar transformer to drop compat annotations
+ // for newly repackaged classes. Dropping @UnsupportedAppUsage on repackaged classes
+ // avoids adding new hiddenapis after jarjar'ing.
+ " -DremoveAndroidCompatAnnotations=true" +
+ " -jar ${config.JarjarCmd} process $rulesFile $in $out",
CommandDeps: []string{"${config.JavaCmd}", "${config.JarjarCmd}", "$rulesFile"},
},
"rulesFile")
@@ -191,7 +196,7 @@
classpath classpath
java9Classpath classpath
processorPath classpath
- processor string
+ processors []string
systemModules *systemModules
aidlFlags string
aidlDeps android.Paths
@@ -265,8 +270,8 @@
deps = append(deps, flags.processorPath...)
processor := "-proc:none"
- if flags.processor != "" {
- processor = "-processor " + flags.processor
+ if len(flags.processors) > 0 {
+ processor = "-processor " + strings.Join(flags.processors, ",")
}
intermediatesDir := "xref"
@@ -380,8 +385,8 @@
deps = append(deps, flags.processorPath...)
processor := "-proc:none"
- if flags.processor != "" {
- processor = "-processor " + flags.processor
+ if len(flags.processors) > 0 {
+ processor = "-processor " + strings.Join(flags.processors, ",")
}
srcJarDir := "srcjars"
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 543b233..c3825cb 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -268,27 +268,28 @@
// Check that this module satisfies constraints for a particular boot image.
apex, isApexModule := module.(android.ApexModule)
+ fromUpdatableApex := isApexModule && apex.Updatable()
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())
+ // ok: found the jar in the ART apex
} else if isApexModule && apex.IsForPlatform() && Bool(module.(*Library).deviceProperties.Hostdex) {
- // this is a special "hostdex" variant, skip it and resume search
+ // exception (skip and continue): special "hostdex" platform variant
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
+ // exception (skip and continue): Jacoco platform variant for a coverage build
return -1, nil
+ } else if fromUpdatableApex {
+ // error: this jar is part of an updatable apex other than ART
+ ctx.Errorf("module '%s' from updatable apex '%s' is not allowed in the ART boot image", name, apex.ApexName())
} 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)
+ // error: this jar is part of the platform or a non-updatable apex
+ ctx.Errorf("module '%s' is 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
+ if !fromUpdatableApex {
+ // ok: this jar is part of the platform or a non-updatable apex
} else {
- // this jar is part of an updatable apex, fail immediately
+ // error: this jar is part of an updatable apex
ctx.Errorf("module '%s' from updatable apex '%s' is not allowed in the framework boot image", name, apex.ApexName())
}
} else {
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 8e7797a..a9b5d5f 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -177,37 +177,15 @@
// filegroup or genrule can be included within this property.
Knowntags []string `android:"path"`
- // the tag name used to distinguish if the API files belong to public/system/test.
- Api_tag_name *string
-
// the generated public API filename by Doclava.
Api_filename *string
- // the generated public Dex API filename by Doclava.
- Dex_api_filename *string
-
- // the generated private API filename by Doclava.
- Private_api_filename *string
-
- // the generated private Dex API filename by Doclava.
- Private_dex_api_filename *string
-
// the generated removed API filename by Doclava.
Removed_api_filename *string
// the generated removed Dex API filename by Doclava.
Removed_dex_api_filename *string
- // mapping of dex signatures to source file and line number. This is a temporary property and
- // will be deleted; you probably shouldn't be using it.
- Dex_mapping_filename *string
-
- // the generated exact API filename by Doclava.
- Exact_api_filename *string
-
- // the generated proguard filename by Doclava.
- Proguard_filename *string
-
// if set to false, don't allow droiddoc to generate stubs source files. Defaults to true.
Create_stubs *bool
@@ -229,37 +207,15 @@
}
type DroidstubsProperties struct {
- // the tag name used to distinguish if the API files belong to public/system/test.
- Api_tag_name *string
-
// the generated public API filename by Metalava.
Api_filename *string
- // the generated public Dex API filename by Metalava.
- Dex_api_filename *string
-
- // the generated private API filename by Metalava.
- Private_api_filename *string
-
- // the generated private Dex API filename by Metalava.
- Private_dex_api_filename *string
-
// the generated removed API filename by Metalava.
Removed_api_filename *string
// the generated removed Dex API filename by Metalava.
Removed_dex_api_filename *string
- // mapping of dex signatures to source file and line number. This is a temporary property and
- // will be deleted; you probably shouldn't be using it.
- Dex_mapping_filename *string
-
- // the generated exact API filename by Metalava.
- Exact_api_filename *string
-
- // the generated proguard filename by Metalava.
- Proguard_filename *string
-
Check_api struct {
Last_released ApiToCheck
@@ -731,14 +687,9 @@
properties DroiddocProperties
apiFile android.WritablePath
- dexApiFile android.WritablePath
privateApiFile android.WritablePath
- privateDexApiFile android.WritablePath
removedApiFile android.WritablePath
removedDexApiFile android.WritablePath
- exactApiFile android.WritablePath
- apiMappingFile android.WritablePath
- proguardFile android.WritablePath
checkCurrentApiTimestamp android.WritablePath
updateCurrentApiTimestamp android.WritablePath
@@ -876,41 +827,11 @@
cmd.FlagWithOutput("-removedApi ", d.removedApiFile)
}
- if String(d.properties.Private_api_filename) != "" {
- d.privateApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_api_filename))
- cmd.FlagWithOutput("-privateApi ", d.privateApiFile)
- }
-
- if String(d.properties.Dex_api_filename) != "" {
- d.dexApiFile = android.PathForModuleOut(ctx, String(d.properties.Dex_api_filename))
- cmd.FlagWithOutput("-dexApi ", d.dexApiFile)
- }
-
- if String(d.properties.Private_dex_api_filename) != "" {
- d.privateDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_dex_api_filename))
- cmd.FlagWithOutput("-privateDexApi ", d.privateDexApiFile)
- }
-
if String(d.properties.Removed_dex_api_filename) != "" {
d.removedDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Removed_dex_api_filename))
cmd.FlagWithOutput("-removedDexApi ", d.removedDexApiFile)
}
- if String(d.properties.Exact_api_filename) != "" {
- d.exactApiFile = android.PathForModuleOut(ctx, String(d.properties.Exact_api_filename))
- cmd.FlagWithOutput("-exactApi ", d.exactApiFile)
- }
-
- if String(d.properties.Dex_mapping_filename) != "" {
- d.apiMappingFile = android.PathForModuleOut(ctx, String(d.properties.Dex_mapping_filename))
- cmd.FlagWithOutput("-apiMapping ", d.apiMappingFile)
- }
-
- if String(d.properties.Proguard_filename) != "" {
- d.proguardFile = android.PathForModuleOut(ctx, String(d.properties.Proguard_filename))
- cmd.FlagWithOutput("-proguard ", d.proguardFile)
- }
-
if BoolDefault(d.properties.Create_stubs, true) {
cmd.FlagWithArg("-stubs ", stubsDir.String())
}
@@ -1210,14 +1131,9 @@
apiFile android.WritablePath
apiXmlFile android.WritablePath
lastReleasedApiXmlFile android.WritablePath
- dexApiFile android.WritablePath
privateApiFile android.WritablePath
- privateDexApiFile android.WritablePath
removedApiFile android.WritablePath
removedDexApiFile android.WritablePath
- apiMappingFile android.WritablePath
- exactApiFile android.WritablePath
- proguardFile android.WritablePath
nullabilityWarningsFile android.WritablePath
checkCurrentApiTimestamp android.WritablePath
@@ -1322,41 +1238,11 @@
cmd.FlagWithOutput("--removed-api ", d.removedApiFile)
}
- if String(d.properties.Private_api_filename) != "" {
- d.privateApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_api_filename))
- cmd.FlagWithOutput("--private-api ", d.privateApiFile)
- }
-
- if String(d.properties.Dex_api_filename) != "" {
- d.dexApiFile = android.PathForModuleOut(ctx, String(d.properties.Dex_api_filename))
- cmd.FlagWithOutput("--dex-api ", d.dexApiFile)
- }
-
- if String(d.properties.Private_dex_api_filename) != "" {
- d.privateDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_dex_api_filename))
- cmd.FlagWithOutput("--private-dex-api ", d.privateDexApiFile)
- }
-
if String(d.properties.Removed_dex_api_filename) != "" {
d.removedDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Removed_dex_api_filename))
cmd.FlagWithOutput("--removed-dex-api ", d.removedDexApiFile)
}
- if String(d.properties.Exact_api_filename) != "" {
- d.exactApiFile = android.PathForModuleOut(ctx, String(d.properties.Exact_api_filename))
- cmd.FlagWithOutput("--exact-api ", d.exactApiFile)
- }
-
- if String(d.properties.Dex_mapping_filename) != "" {
- d.apiMappingFile = android.PathForModuleOut(ctx, String(d.properties.Dex_mapping_filename))
- cmd.FlagWithOutput("--dex-api-mapping ", d.apiMappingFile)
- }
-
- if String(d.properties.Proguard_filename) != "" {
- d.proguardFile = android.PathForModuleOut(ctx, String(d.properties.Proguard_filename))
- cmd.FlagWithOutput("--proguard ", d.proguardFile)
- }
-
if Bool(d.properties.Write_sdk_values) {
d.metadataDir = android.PathForModuleOut(ctx, "metadata")
cmd.FlagWithArg("--sdk-values ", d.metadataDir.String())
diff --git a/java/java.go b/java/java.go
index a8ca3ff..38f485e 100644
--- a/java/java.go
+++ b/java/java.go
@@ -86,7 +86,7 @@
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 @@
}
}
}
+
+ 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 @@
// 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 {
@@ -1130,7 +1134,8 @@
flags.java9Classpath = append(flags.java9Classpath, deps.java9Classpath...)
flags.processorPath = append(flags.processorPath, deps.processorPath...)
- flags.processor = strings.Join(deps.processorClasses, ",")
+ flags.processors = append(flags.processors, deps.processorClasses...)
+ flags.processors = android.FirstUniqueStrings(flags.processors)
if len(flags.bootClasspath) == 0 && ctx.Host() && !flags.javaVersion.usesJavaModules() &&
decodeSdkDep(ctx, sdkContext(j)).hasStandardLibs() {
@@ -1265,7 +1270,7 @@
srcJars = append(srcJars, kaptSrcJar)
// Disable annotation processing in javac, it's already been handled by kapt
flags.processorPath = nil
- flags.processor = ""
+ flags.processors = nil
}
kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName)
@@ -1818,7 +1823,7 @@
}
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)
diff --git a/java/kotlin.go b/java/kotlin.go
index cb7da20..9b160a0 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -136,8 +136,11 @@
kaptProcessorPath := flags.processorPath.FormRepeatedClassPath("-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=")
kaptProcessor := ""
- if flags.processor != "" {
- kaptProcessor = "-P plugin:org.jetbrains.kotlin.kapt3:processors=" + flags.processor
+ for i, p := range flags.processors {
+ if i > 0 {
+ kaptProcessor += " "
+ }
+ kaptProcessor += "-P plugin:org.jetbrains.kotlin.kapt3:processors=" + p
}
encodedJavacFlags := kaptEncodeFlags([][2]string{
diff --git a/java/kotlin_test.go b/java/kotlin_test.go
index 5c6d45f..60ca1c4 100644
--- a/java/kotlin_test.go
+++ b/java/kotlin_test.go
@@ -88,7 +88,7 @@
java_library {
name: "foo",
srcs: ["a.java", "b.kt"],
- plugins: ["bar"],
+ plugins: ["bar", "baz"],
}
java_plugin {
@@ -96,6 +96,12 @@
processor_class: "com.bar",
srcs: ["b.java"],
}
+
+ java_plugin {
+ name: "baz",
+ processor_class: "com.baz",
+ srcs: ["b.java"],
+ }
`)
buildOS := android.BuildOs.String()
@@ -105,6 +111,7 @@
javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
bar := ctx.ModuleForTests("bar", buildOS+"_common").Rule("javac").Output.String()
+ baz := ctx.ModuleForTests("baz", buildOS+"_common").Rule("javac").Output.String()
// Test that the kotlin and java sources are passed to kapt and kotlinc
if len(kapt.Inputs) != 2 || kapt.Inputs[0].String() != "a.java" || kapt.Inputs[1].String() != "b.kt" {
@@ -136,11 +143,12 @@
}
// Test that the processors are passed to kapt
- expectedProcessorPath := "-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + bar
+ expectedProcessorPath := "-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + bar +
+ " -P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + baz
if kapt.Args["kaptProcessorPath"] != expectedProcessorPath {
t.Errorf("expected kaptProcessorPath %q, got %q", expectedProcessorPath, kapt.Args["kaptProcessorPath"])
}
- expectedProcessor := "-P plugin:org.jetbrains.kotlin.kapt3:processors=com.bar"
+ expectedProcessor := "-P plugin:org.jetbrains.kotlin.kapt3:processors=com.bar -P plugin:org.jetbrains.kotlin.kapt3:processors=com.baz"
if kapt.Args["kaptProcessor"] != expectedProcessor {
t.Errorf("expected kaptProcessor %q, got %q", expectedProcessor, kapt.Args["kaptProcessor"])
}
diff --git a/java/sdk.go b/java/sdk.go
index 0e132d3..92076f4 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -147,6 +147,10 @@
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 @@
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 ff80d63..51e680b 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -394,13 +394,6 @@
}
}
-// $(INTERNAL_PLATFORM_<apiTagName>_API_FILE) points to the generated
-// api file for the current source
-// TODO: remove this when apicheck is done in soong
-func (module *SdkLibrary) apiTagName(apiScope *apiScope) string {
- return strings.Replace(strings.ToUpper(module.BaseModuleName()), ".", "_", -1) + apiScope.apiFileMakeVariableSuffix
-}
-
func (module *SdkLibrary) latestApiFilegroupName(apiScope *apiScope) string {
return ":" + module.BaseModuleName() + ".api." + apiScope.name + ".latest"
}
@@ -491,9 +484,6 @@
Libs []string
Arg_files []string
Args *string
- Api_tag_name *string
- Api_filename *string
- Removed_api_filename *string
Java_version *string
Merge_annotations_dirs []string
Merge_inclusion_annotations_dirs []string
@@ -572,10 +562,6 @@
apiDir := module.getApiDir()
currentApiFileName = path.Join(apiDir, currentApiFileName)
removedApiFileName = path.Join(apiDir, removedApiFileName)
- // TODO(jiyong): remove these three props
- props.Api_tag_name = proptools.StringPtr(module.apiTagName(apiScope))
- props.Api_filename = proptools.StringPtr(currentApiFileName)
- props.Removed_api_filename = proptools.StringPtr(removedApiFileName)
// check against the not-yet-release API
props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName)
diff --git a/remoteexec/remoteexec.go b/remoteexec/remoteexec.go
new file mode 100644
index 0000000..d43dc6c
--- /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 0000000..30e891c
--- /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/config/global.go b/rust/config/global.go
index 690d83e..c0bd0f2 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
var pctx = android.NewPackageContext("android/soong/rust/config")
var (
- RustDefaultVersion = "1.40.0"
+ RustDefaultVersion = "1.42.0"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2018"
Stdlibs = []string{
diff --git a/rust/rust.go b/rust/rust.go
index 6fe8871..5cc8845 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -735,13 +735,14 @@
deps := mod.deps(ctx)
commonDepVariations := []blueprint.Variation{}
- commonDepVariations = append(commonDepVariations,
- blueprint.Variation{Mutator: "version", Variation: ""})
+ if cc.VersionVariantAvailable(mod) {
+ commonDepVariations = append(commonDepVariations,
+ blueprint.Variation{Mutator: "version", Variation: ""})
+ }
if !mod.Host() {
commonDepVariations = append(commonDepVariations,
blueprint.Variation{Mutator: "image", Variation: android.CoreVariation})
}
-
actx.AddVariationDependencies(
append(commonDepVariations, []blueprint.Variation{
{Mutator: "rust_libraries", Variation: "rlib"},
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 020581d..02b190f 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -215,25 +215,6 @@
srcs: ["foo.rs"],
crate_name: "bar",
}
- // Make a dummy libstd to let resolution go through
- rust_library_dylib {
- name: "libstd",
- crate_name: "std",
- srcs: ["foo.rs"],
- no_stdlibs: true,
- }
- rust_library_dylib {
- name: "libterm",
- crate_name: "term",
- srcs: ["foo.rs"],
- no_stdlibs: true,
- }
- rust_library_dylib {
- name: "libtest",
- crate_name: "test",
- srcs: ["foo.rs"],
- no_stdlibs: true,
- }
rust_proc_macro {
name: "libpm",
rlibs: ["libbar"],
diff --git a/rust/testing.go b/rust/testing.go
index f9adec8..c3a4625 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -22,51 +22,11 @@
func GatherRequiredDepsForTest() string {
bp := `
rust_prebuilt_dylib {
- name: "libarena_x86_64-unknown-linux-gnu",
- srcs: [""],
- host_supported: true,
- }
- rust_prebuilt_dylib {
- name: "libfmt_macros_x86_64-unknown-linux-gnu",
- srcs: [""],
- host_supported: true,
- }
- rust_prebuilt_dylib {
- name: "libgraphviz_x86_64-unknown-linux-gnu",
- srcs: [""],
- host_supported: true,
- }
- rust_prebuilt_dylib {
- name: "libserialize_x86_64-unknown-linux-gnu",
- srcs: [""],
- host_supported: true,
- }
- rust_prebuilt_dylib {
name: "libstd_x86_64-unknown-linux-gnu",
srcs: [""],
host_supported: true,
}
rust_prebuilt_dylib {
- name: "libsyntax_x86_64-unknown-linux-gnu",
- srcs: [""],
- host_supported: true,
- }
- rust_prebuilt_dylib {
- name: "libsyntax_ext_x86_64-unknown-linux-gnu",
- srcs: [""],
- host_supported: true,
- }
- rust_prebuilt_dylib {
- name: "libsyntax_pos_x86_64-unknown-linux-gnu",
- srcs: [""],
- host_supported: true,
- }
- rust_prebuilt_dylib {
- name: "libterm_x86_64-unknown-linux-gnu",
- srcs: [""],
- host_supported: true,
- }
- rust_prebuilt_dylib {
name: "libtest_x86_64-unknown-linux-gnu",
srcs: [""],
host_supported: true,
@@ -81,6 +41,31 @@
nocrt: true,
system_shared_libs: [],
}
+ rust_library_dylib {
+ name: "libstd",
+ crate_name: "std",
+ srcs: ["foo.rs"],
+ no_stdlibs: true,
+ }
+ rust_library_rlib {
+ name: "libstd.static",
+ crate_name: "std",
+ srcs: ["foo.rs"],
+ no_stdlibs: true,
+ }
+ rust_library_dylib {
+ name: "libtest",
+ crate_name: "test",
+ srcs: ["foo.rs"],
+ no_stdlibs: true,
+ }
+ rust_library_rlib {
+ name: "libtest.static",
+ crate_name: "test",
+ srcs: ["foo.rs"],
+ no_stdlibs: true,
+ }
+
` + cc.GatherRequiredDepsForTest(android.NoOsType)
return bp
}
diff --git a/scripts/build-aml-prebuilts.sh b/scripts/build-aml-prebuilts.sh
index 35a6ff3..7408349 100755
--- a/scripts/build-aml-prebuilts.sh
+++ b/scripts/build-aml-prebuilts.sh
@@ -50,15 +50,20 @@
mkdir -p ${SOONG_OUT}
SOONG_VARS=${SOONG_OUT}/soong.variables
+# We enable bionic linux builds as ART also needs prebuilts for it.
+# Enabling bionic linux requires setting allow_missing_dependencies.
cat > ${SOONG_VARS}.new << EOF
{
"Platform_sdk_version": ${PLATFORM_SDK_VERSION},
"Platform_sdk_codename": "${PLATFORM_VERSION}",
"Platform_version_active_codenames": ${PLATFORM_VERSION_ALL_CODENAMES},
+ "Allow_missing_dependencies": true,
"DeviceName": "generic_arm64",
"HostArch": "x86_64",
"HostSecondaryArch": "x86",
+ "CrossHost": "linux_bionic",
+ "CrossHostArch": "x86_64",
"Aml_abis": true,
"UseGoma": ${USE_GOMA}
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index 79e40dd..fc91c3d 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -18,6 +18,7 @@
art-module-test-exports
conscrypt-module-sdk
conscrypt-module-test-exports
+ conscrypt-module-host-exports
)
# We want to create apex modules for all supported architectures.
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index a2e35d9..0932873 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -151,6 +151,12 @@
// Whether public stub exists or not.
Public_stub *bool `blueprint:"mutated"`
+
+ Cpp struct {
+ // Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
+ // Forwarded to cc_library.min_sdk_version
+ Min_sdk_version *string
+ }
}
var (
@@ -344,6 +350,7 @@
Vendor_available *bool
Host_supported *bool
Apex_available []string
+ Min_sdk_version *string
}
type javaLibraryProperties struct {
@@ -433,6 +440,7 @@
ccProps.Vendor_available = m.properties.Vendor_available
ccProps.Host_supported = m.properties.Host_supported
ccProps.Apex_available = m.ApexProperties.Apex_available
+ ccProps.Min_sdk_version = m.properties.Cpp.Min_sdk_version
ctx.CreateModule(cc.LibraryFactory, &ccProps)
scope := "internal"
diff --git a/ui/build/build.go b/ui/build/build.go
index f3feac2..1122733 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -53,7 +53,6 @@
{{end -}}
pool highmem_pool
depth = {{.HighmemParallel}}
-build _kati_always_build_: phony
{{if .HasKatiSuffix}}subninja {{.KatiBuildNinjaFile}}
subninja {{.KatiPackageNinjaFile}}
{{end -}}
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index ce8f968..a559330 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -190,6 +190,7 @@
// compiler wrappers set up by make
"CC_WRAPPER",
"CXX_WRAPPER",
+ "RBE_WRAPPER",
"JAVAC_WRAPPER",
"R8_WRAPPER",
"D8_WRAPPER",
@@ -228,8 +229,6 @@
"DEFAULT_ERROR_BUILD_MODULE_TYPES",
"BUILD_BROKEN_PREBUILT_ELF_FILES",
"BUILD_BROKEN_TREBLE_SYSPROP_NEVERALLOW",
- "BUILD_BROKEN_USES_BUILD_AUX_EXECUTABLE",
- "BUILD_BROKEN_USES_BUILD_AUX_STATIC_LIBRARY",
"BUILD_BROKEN_USES_BUILD_COPY_HEADERS",
"BUILD_BROKEN_USES_BUILD_EXECUTABLE",
"BUILD_BROKEN_USES_BUILD_FUZZ_TEST",
@@ -237,17 +236,12 @@
"BUILD_BROKEN_USES_BUILD_HOST_DALVIK_JAVA_LIBRARY",
"BUILD_BROKEN_USES_BUILD_HOST_DALVIK_STATIC_JAVA_LIBRARY",
"BUILD_BROKEN_USES_BUILD_HOST_EXECUTABLE",
- "BUILD_BROKEN_USES_BUILD_HOST_FUZZ_TEST",
"BUILD_BROKEN_USES_BUILD_HOST_JAVA_LIBRARY",
- "BUILD_BROKEN_USES_BUILD_HOST_NATIVE_TEST",
"BUILD_BROKEN_USES_BUILD_HOST_PREBUILT",
"BUILD_BROKEN_USES_BUILD_HOST_SHARED_LIBRARY",
"BUILD_BROKEN_USES_BUILD_HOST_STATIC_LIBRARY",
- "BUILD_BROKEN_USES_BUILD_HOST_STATIC_TEST_LIBRARY",
- "BUILD_BROKEN_USES_BUILD_HOST_TEST_CONFIG",
"BUILD_BROKEN_USES_BUILD_JAVA_LIBRARY",
"BUILD_BROKEN_USES_BUILD_MULTI_PREBUILT",
- "BUILD_BROKEN_USES_BUILD_NATIVE_BENCHMARK",
"BUILD_BROKEN_USES_BUILD_NATIVE_TEST",
"BUILD_BROKEN_USES_BUILD_NOTICE_FILE",
"BUILD_BROKEN_USES_BUILD_PACKAGE",
@@ -257,8 +251,6 @@
"BUILD_BROKEN_USES_BUILD_SHARED_LIBRARY",
"BUILD_BROKEN_USES_BUILD_STATIC_JAVA_LIBRARY",
"BUILD_BROKEN_USES_BUILD_STATIC_LIBRARY",
- "BUILD_BROKEN_USES_BUILD_STATIC_TEST_LIBRARY",
- "BUILD_BROKEN_USES_BUILD_TARGET_TEST_CONFIG",
}, exportEnvVars...), BannerVars...)
make_vars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true)
diff --git a/ui/build/exec.go b/ui/build/exec.go
index e435c53..053bbae 100644
--- a/ui/build/exec.go
+++ b/ui/build/exec.go
@@ -19,6 +19,8 @@
"io"
"os/exec"
"strings"
+ "syscall"
+ "time"
)
// Cmd is a wrapper of os/exec.Cmd that integrates with the build context for
@@ -33,6 +35,8 @@
ctx Context
config Config
name string
+
+ started time.Time
}
func Command(ctx Context, config Config, name string, executable string, args ...string) *Cmd {
@@ -57,7 +61,20 @@
c.wrapSandbox()
}
- c.ctx.Verboseln(c.Path, c.Args)
+ c.ctx.Verbosef("%q executing %q %v\n", c.name, c.Path, c.Args)
+ c.started = time.Now()
+}
+
+func (c *Cmd) report() {
+ if c.Cmd.ProcessState != nil {
+ rusage := c.Cmd.ProcessState.SysUsage().(*syscall.Rusage)
+ c.ctx.Verbosef("%q finished with exit code %d (%s real, %s user, %s system, %dMB maxrss)",
+ c.name, c.Cmd.ProcessState.ExitCode(),
+ time.Since(c.started).Round(time.Millisecond),
+ c.Cmd.ProcessState.UserTime().Round(time.Millisecond),
+ c.Cmd.ProcessState.SystemTime().Round(time.Millisecond),
+ rusage.Maxrss/1024)
+ }
}
func (c *Cmd) Start() error {
@@ -68,21 +85,30 @@
func (c *Cmd) Run() error {
c.prepare()
err := c.Cmd.Run()
+ c.report()
return err
}
func (c *Cmd) Output() ([]byte, error) {
c.prepare()
bytes, err := c.Cmd.Output()
+ c.report()
return bytes, err
}
func (c *Cmd) CombinedOutput() ([]byte, error) {
c.prepare()
bytes, err := c.Cmd.CombinedOutput()
+ c.report()
return bytes, err
}
+func (c *Cmd) Wait() error {
+ err := c.Cmd.Wait()
+ c.report()
+ return err
+}
+
// StartOrFatal is equivalent to Start, but handles the error with a call to ctx.Fatal
func (c *Cmd) StartOrFatal() {
if err := c.Start(); err != nil {
diff --git a/ui/build/kati.go b/ui/build/kati.go
index 8796a4f..2eb7850 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -67,6 +67,7 @@
"--ninja_dir=" + config.OutDir(),
"--ninja_suffix=" + config.KatiSuffix() + extraSuffix,
"--no_ninja_prelude",
+ "--use_ninja_phony_output",
"--regen",
"--ignore_optional_include=" + filepath.Join(config.OutDir(), "%.P"),
"--detect_android_echo",
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index dfc3be1..1b13e5d 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -58,6 +58,7 @@
args = append(args, "-f", config.CombinedNinjaFile())
args = append(args,
+ "-o", "usesphonyoutputs=yes",
"-w", "dupbuild=err",
"-w", "missingdepfile=err")
diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go
index 4c3bac3..98eb028 100644
--- a/ui/build/sandbox_linux.go
+++ b/ui/build/sandbox_linux.go
@@ -19,6 +19,7 @@
"os"
"os/exec"
"os/user"
+ "path/filepath"
"strings"
"sync"
)
@@ -75,9 +76,20 @@
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)
+ }
sandboxArgs := []string{
"-H", "android-build",
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 9b8d648..2fbf381 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -119,7 +119,11 @@
cmd := Command(ctx, config, "soong "+name,
config.PrebuiltBuildTool("ninja"),
"-d", "keepdepfile",
+ "-o", "usesphonyoutputs=yes",
+ "-o", "preremoveoutputs=yes",
"-w", "dupbuild=err",
+ "-w", "outputdir=err",
+ "-w", "missingoutfile=err",
"-j", strconv.Itoa(config.Parallel()),
"--frontend_file", fifo,
"-f", filepath.Join(config.SoongOutDir(), file))
diff --git a/ui/build/test_build.go b/ui/build/test_build.go
index 5109465..4ff9483 100644
--- a/ui/build/test_build.go
+++ b/ui/build/test_build.go
@@ -50,10 +50,10 @@
// Get a list of leaf nodes in the dependency graph from ninja
executable := config.PrebuiltBuildTool("ninja")
- args := []string{}
- args = append(args, config.NinjaArgs()...)
- args = append(args, "-f", config.CombinedNinjaFile())
- args = append(args, "-t", "targets", "rule")
+ common_args := []string{}
+ common_args = append(common_args, config.NinjaArgs()...)
+ common_args = append(common_args, "-f", config.CombinedNinjaFile())
+ args := append(common_args, "-t", "targets", "rule")
cmd := Command(ctx, config, "ninja", executable, args...)
stdout, err := cmd.StdoutPipe()
@@ -96,9 +96,31 @@
sb := &strings.Builder{}
title := "Dependencies in out found with no rule to create them:"
fmt.Fprintln(sb, title)
- for _, dep := range danglingRulesList {
- fmt.Fprintln(sb, " ", dep)
+
+ report_lines := 1
+ for i, dep := range danglingRulesList {
+ if report_lines > 20 {
+ fmt.Fprintf(sb, " ... and %d more\n", len(danglingRulesList)-i)
+ break
+ }
+ // It's helpful to see the reverse dependencies. ninja -t query is the
+ // best tool we got for that. Its output starts with the dependency
+ // itself.
+ query_cmd := Command(ctx, config, "ninja", executable,
+ append(common_args, "-t", "query", dep)...)
+ query_stdout, err := query_cmd.StdoutPipe()
+ if err != nil {
+ ctx.Fatal(err)
+ }
+ query_cmd.StartOrFatal()
+ scanner := bufio.NewScanner(query_stdout)
+ for scanner.Scan() {
+ report_lines++
+ fmt.Fprintln(sb, " ", scanner.Text())
+ }
+ query_cmd.WaitOrFatal()
}
+
ts.FinishAction(status.ActionResult{
Action: action,
Error: fmt.Errorf(title),
diff --git a/ui/metrics/Android.bp b/ui/metrics/Android.bp
index 529639d..3596e10 100644
--- a/ui/metrics/Android.bp
+++ b/ui/metrics/Android.bp
@@ -17,6 +17,7 @@
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 {
+ 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 0000000..4521df7
--- /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 0000000..1b1e5e8
--- /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 0000000..7a9f080
--- /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;
+}