Merge "soong: Add support for override_runtime_resource_overlay" into rvc-dev
diff --git a/Android.bp b/Android.bp
index 0621475..352cf80 100644
--- a/Android.bp
+++ b/Android.bp
@@ -130,6 +130,7 @@
pkgPath: "android/soong/cc/config",
deps: [
"soong-android",
+ "soong-remoteexec",
],
srcs: [
"cc/config/clang.go",
@@ -546,6 +547,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
//
diff --git a/android/apex.go b/android/apex.go
index 1a43ce4..c7410a1 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -114,6 +114,11 @@
// For example, with maxSdkVersion is 10 and versionList is [9,11]
// it returns 9 as string
ChooseSdkVersion(versionList []string, maxSdkVersion int) (string, error)
+
+ // 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 {
@@ -159,6 +164,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()
diff --git a/android/defs.go b/android/defs.go
index 5c815e6..4552224 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -100,6 +100,9 @@
// Used only when USE_GOMA=true is set, to restrict non-goma jobs to the local parallelism value
localPool = blueprint.NewBuiltinPool("local_pool")
+ // Used only by RuleBuilder to identify remoteable rules. Does not actually get created in ninja.
+ remotePool = blueprint.NewBuiltinPool("remote_pool")
+
// Used for processes that need significant RAM to ensure there are not too many running in parallel.
highmemPool = blueprint.NewBuiltinPool("highmem_pool")
)
diff --git a/android/module.go b/android/module.go
index f300e05..d9e655a 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1500,10 +1500,17 @@
func (m *moduleContext) Rule(pctx PackageContext, name string, params blueprint.RuleParams,
argNames ...string) blueprint.Rule {
- if m.config.UseRemoteBuild() && params.Pool == nil {
- // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict
- // jobs to the local parallelism value
- params.Pool = localPool
+ if m.config.UseRemoteBuild() {
+ if params.Pool == nil {
+ // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict
+ // jobs to the local parallelism value
+ params.Pool = localPool
+ } else if params.Pool == remotePool {
+ // remotePool is a fake pool used to identify rule that are supported for remoting. If the rule's
+ // pool is the remotePool, replace with nil so that ninja runs it at NINJA_REMOTE_NUM_JOBS
+ // parallelism.
+ params.Pool = nil
+ }
}
rule := m.bp.Rule(pctx.PackageContext, name, params, argNames...)
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 9005f07..6226548 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -446,7 +446,8 @@
if ctx.Config().UseGoma() && r.remoteable.Goma {
// When USE_GOMA=true is set and the rule is supported by goma, allow jobs to run outside the local pool.
} else if ctx.Config().UseRBE() && r.remoteable.RBE {
- // When USE_RBE=true is set and the rule is supported by RBE, allow jobs to run outside the local pool.
+ // When USE_RBE=true is set and the rule is supported by RBE, use the remotePool.
+ pool = remotePool
} else if r.highmem {
pool = highmemPool
} else if ctx.Config().UseRemoteBuild() {
diff --git a/android/singleton.go b/android/singleton.go
index 45a9b82..568398c 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -128,10 +128,17 @@
}
func (s *singletonContextAdaptor) Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule {
- if s.Config().UseRemoteBuild() && params.Pool == nil {
- // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict
- // jobs to the local parallelism value
- params.Pool = localPool
+ if s.Config().UseRemoteBuild() {
+ if params.Pool == nil {
+ // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict
+ // jobs to the local parallelism value
+ params.Pool = localPool
+ } else if params.Pool == remotePool {
+ // remotePool is a fake pool used to identify rule that are supported for remoting. If the rule's
+ // pool is the remotePool, replace with nil so that ninja runs it at NINJA_REMOTE_NUM_JOBS
+ // parallelism.
+ params.Pool = nil
+ }
}
rule := s.SingletonContext.Rule(pctx.PackageContext, name, params, argNames...)
if s.Config().captureBuild {
diff --git a/apex/apex.go b/apex/apex.go
index ec87f5b..6a0c4c1 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -92,24 +92,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",
@@ -133,14 +115,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",
@@ -230,13 +210,10 @@
"libevent",
"libfmq",
"libg722codec",
- "libgtest_prod",
"libgui_headers",
"libmedia_headers",
"libmodpb64",
"libosi",
- "libprocessgroup",
- "libprocessgroup_headers",
"libstagefright_foundation_headers",
"libstagefright_headers",
"libstatslog",
@@ -262,9 +239,7 @@
// Module separator
//
m["com.android.conscrypt"] = []string{
- "boringssl_self_test",
"libnativehelper_header_only",
- "unsupportedappusage",
}
//
// Module separator
@@ -282,18 +257,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",
@@ -306,8 +269,6 @@
"libarect",
"libbuildversion",
"libmath",
- "libprocessgroup",
- "libprocessgroup_headers",
"libprocpartition",
"libsync",
}
@@ -350,7 +311,6 @@
"libaacextractor",
"libamrextractor",
"libarect",
- "libasync_safe",
"libaudio_system_headers",
"libaudioclient",
"libaudioclient_headers",
@@ -404,13 +364,10 @@
"libnblog",
"liboggextractor",
"libpackagelistparser",
- "libpcre2",
"libpdx",
"libpdx_default_transport",
"libpdx_headers",
"libpdx_uds",
- "libprocessgroup",
- "libprocessgroup_headers",
"libprocinfo",
"libspeexresampler",
"libspeexresampler",
@@ -477,7 +434,6 @@
"libFraunhoferAAC",
"libLibGuiProperties",
"libarect",
- "libasync_safe",
"libaudio_system_headers",
"libaudioutils",
"libaudioutils",
@@ -491,7 +447,6 @@
"libbluetooth-types-header",
"libbufferhub_headers",
"libc_scudo",
- "libcap",
"libcodec2",
"libcodec2_headers",
"libcodec2_hidl@1.0",
@@ -550,20 +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",
"libpdx_headers",
- "libprocessgroup",
- "libprocessgroup_headers",
"libscudo_wrapper",
"libsfplugin_ccodec_utils",
"libspeexresampler",
@@ -634,8 +581,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",
@@ -671,13 +616,11 @@
"libdexfile_support",
"libdexfile_support_static",
"libdl_static",
- "libgtest_prod",
"libjemalloc5",
"liblinker_main",
"liblinker_malloc",
"liblz4",
"liblzma",
- "libprocessgroup_headers",
"libprocinfo",
"libpropertyinfoparser",
"libscudo",
@@ -691,34 +634,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",
@@ -756,8 +676,6 @@
"ipmemorystore-aidl-interfaces-java",
"ksoap2",
"libnanohttpd",
- "libprocessgroup",
- "libprocessgroup_headers",
"libwifi-jni",
"net-utils-services-common",
"netd_aidl_interface-V2-java",
@@ -785,7 +703,6 @@
// Module separator
//
m["com.android.os.statsd"] = []string{
- "libprocessgroup_headers",
"libstatssocket",
}
//
@@ -1162,6 +1079,10 @@
// Should be only used in tests#.
Test_only_no_hashtree *bool
+ // Whenever apex_payload.img of the APEX should not be dm-verity signed.
+ // Should be only used in tests#.
+ Test_only_unsigned_payload *bool
+
IsCoverageVariant bool `blueprint:"mutated"`
// Whether this APEX is considered updatable or not. When set to true, this will enforce additional
@@ -1653,6 +1574,10 @@
return proptools.Bool(a.properties.Test_only_no_hashtree)
}
+func (a *apexBundle) testOnlyShouldSkipPayloadSign() bool {
+ return proptools.Bool(a.properties.Test_only_unsigned_payload)
+}
+
func (a *apexBundle) getImageVariation(config android.DeviceConfig) string {
if a.vndkApex {
return cc.VendorVariationPrefix + a.vndkVersion(config)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 91ad6e8..5451fa2 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -4386,6 +4386,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/builder.go b/apex/builder.go
index 84cbff8..0d7e801 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -484,6 +484,10 @@
optFlags = append(optFlags, "--no_hashtree")
}
+ if a.testOnlyShouldSkipPayloadSign() {
+ optFlags = append(optFlags, "--unsigned_payload")
+ }
+
if a.properties.Apex_name != nil {
// If apex_name is set, apexer can skip checking if key name matches with apex name.
// Note that apex_manifest is also mended.
diff --git a/cc/builder.go b/cc/builder.go
index e09dc55..d8e90b6 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -29,6 +29,7 @@
"android/soong/android"
"android/soong/cc/config"
+ "android/soong/remoteexec"
)
const (
@@ -62,7 +63,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 +73,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{
@@ -262,6 +275,7 @@
}
pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
+ pctx.Import("android/soong/remoteexec")
}
type builderFlags struct {
@@ -657,8 +671,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,
@@ -798,16 +817,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 9baeceb..a92495c 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -2301,6 +2301,15 @@
// 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
@@ -2727,6 +2736,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/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/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/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/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 0e1bfc6..f984966 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -47,6 +47,8 @@
const SystemPartition = "/system/"
const SystemOtherPartition = "/system_other/"
+var DexpreoptRunningInSoong = false
+
// GenerateDexpreoptRule generates a set of commands that will preopt a module based on a GlobalConfig and a
// ModuleConfig. The produced files and their install locations will be available through rule.Installs().
func GenerateDexpreoptRule(ctx android.PathContext, globalSoong *GlobalSoongConfig,
@@ -589,7 +591,14 @@
// at that time (Soong processes the jars in dependency order, which may be different from the
// the system server classpath order).
func SystemServerDexJarHostPath(ctx android.PathContext, jar string) android.OutputPath {
- return android.PathForOutput(ctx, "system_server_dexjars", jar+".jar")
+ if DexpreoptRunningInSoong {
+ // Soong module, just use the default output directory $OUT/soong.
+ return android.PathForOutput(ctx, "system_server_dexjars", jar+".jar")
+ } else {
+ // Make module, default output directory is $OUT (passed via the "null config" created
+ // by dexpreopt_gen). Append Soong subdirectory to match Soong module paths.
+ return android.PathForOutput(ctx, "soong", "system_server_dexjars", jar+".jar")
+ }
}
func contains(l []string, s string) bool {
diff --git a/java/app.go b/java/app.go
index 4468dc5..951ce16 100755
--- a/java/app.go
+++ b/java/app.go
@@ -113,7 +113,9 @@
IsCoverageVariant bool `blueprint:"mutated"`
// Whether this app is considered mainline updatable or not. When set to true, this will enforce
- // additional rules for making sure that the APK is truly updatable. Default is false.
+ // 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
}
@@ -265,6 +267,9 @@
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)
diff --git a/java/app_test.go b/java/app_test.go
index 5b1e370..8ec8a7f 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -276,6 +276,7 @@
name: "foo",
srcs: ["a.java"],
sdk_version: "29",
+ min_sdk_version: "29",
updatable: true,
}`,
},
@@ -285,6 +286,7 @@
name: "foo",
srcs: ["a.java"],
sdk_version: "system_29",
+ min_sdk_version: "29",
updatable: true,
}`,
},
@@ -294,6 +296,7 @@
name: "foo",
srcs: ["a.java"],
sdk_version: "current",
+ min_sdk_version: "29",
updatable: true,
}`,
},
@@ -303,6 +306,7 @@
name: "foo",
srcs: ["a.java"],
sdk_version: "system_current",
+ min_sdk_version: "29",
updatable: true,
}`,
},
@@ -312,6 +316,7 @@
name: "foo",
srcs: ["a.java"],
sdk_version: "module_current",
+ min_sdk_version: "29",
updatable: true,
}`,
},
@@ -321,6 +326,7 @@
name: "foo",
srcs: ["a.java"],
sdk_version: "core_current",
+ min_sdk_version: "29",
updatable: true,
}`,
},
@@ -330,6 +336,7 @@
name: "foo",
srcs: ["a.java"],
platform_apis: true,
+ min_sdk_version: "29",
updatable: true,
}`,
expectedError: "Updatable apps must use stable SDKs",
@@ -340,6 +347,7 @@
name: "foo",
srcs: ["a.java"],
sdk_version: "core_platform",
+ min_sdk_version: "29",
updatable: true,
}`,
expectedError: "Updatable apps must use stable SDKs",
@@ -350,9 +358,20 @@
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 {
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 40cfe4f..28a2c8a 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -62,6 +62,10 @@
}
}
+func init() {
+ dexpreopt.DexpreoptRunningInSoong = true
+}
+
func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool {
global := dexpreopt.GetGlobalConfig(ctx)
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/ui/build/dumpvars.go b/ui/build/dumpvars.go
index ce8f968..a3234e3 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",