Merge "Add support for LINE_COVERAGE (1/2)"
diff --git a/android/arch.go b/android/arch.go
index 65833a8..3657e6d 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1622,7 +1622,7 @@
func getNdkAbisConfig() []archConfig {
return []archConfig{
- {"arm", "armv7-a", "", []string{"armeabi"}},
+ {"arm", "armv7-a", "", []string{"armeabi-v7a"}},
{"arm64", "armv8-a", "", []string{"arm64-v8a"}},
{"x86", "", "", []string{"x86"}},
{"x86_64", "", "", []string{"x86_64"}},
diff --git a/cc/ccdeps.go b/cc/ccdeps.go
index 4e23a7b..225405c 100644
--- a/cc/ccdeps.go
+++ b/cc/ccdeps.go
@@ -17,7 +17,6 @@
import (
"encoding/json"
"fmt"
- "os"
"path"
"sort"
"strings"
@@ -106,7 +105,7 @@
moduleDeps.Modules = moduleInfos
- ccfpath := android.PathForOutput(ctx, ccdepsJsonFileName).String()
+ ccfpath := android.PathForOutput(ctx, ccdepsJsonFileName)
err := createJsonFile(moduleDeps, ccfpath)
if err != nil {
ctx.Errorf(err.Error())
@@ -236,17 +235,14 @@
return m
}
-func createJsonFile(moduleDeps ccDeps, ccfpath string) error {
- file, err := os.Create(ccfpath)
- if err != nil {
- return fmt.Errorf("Failed to create file: %s, relative: %v", ccdepsJsonFileName, err)
- }
- defer file.Close()
- moduleDeps.Modules = sortMap(moduleDeps.Modules)
+func createJsonFile(moduleDeps ccDeps, ccfpath android.WritablePath) error {
buf, err := json.MarshalIndent(moduleDeps, "", "\t")
if err != nil {
- return fmt.Errorf("Write file failed: %s, relative: %v", ccdepsJsonFileName, err)
+ return fmt.Errorf("JSON marshal of cc deps failed: %s", err)
}
- fmt.Fprintf(file, string(buf))
+ err = android.WriteFileToOutputDir(ccfpath, buf, 0666)
+ if err != nil {
+ return fmt.Errorf("Writing cc deps to %s failed: %s", ccfpath.String(), err)
+ }
return nil
}
diff --git a/cc/config/global.go b/cc/config/global.go
index 44de4d5..333885f 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -127,8 +127,8 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r370808"
- ClangDefaultShortVersion = "10.0.1"
+ ClangDefaultVersion = "clang-r370808b"
+ ClangDefaultShortVersion = "10.0.2"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
@@ -168,6 +168,9 @@
flags = append(flags, "-ftrivial-auto-var-init=pattern")
} else if ctx.Config().IsEnvTrue("AUTO_UNINITIALIZE") {
flags = append(flags, "-ftrivial-auto-var-init=uninitialized")
+ } else {
+ // Default to pattern initialization.
+ flags = append(flags, "-ftrivial-auto-var-init=pattern")
}
return strings.Join(flags, " ")
diff --git a/cc/library.go b/cc/library.go
index 6c8f5bf..0bddab5 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1104,7 +1104,21 @@
if ctx.isVndkSp() {
library.baseInstaller.subDir = "vndk-sp"
} else if ctx.isVndk() {
- if !ctx.mustUseVendorVariant() && !ctx.isVndkExt() {
+ mayUseCoreVariant := true
+
+ if ctx.mustUseVendorVariant() {
+ mayUseCoreVariant = false
+ }
+
+ if ctx.isVndkExt() {
+ mayUseCoreVariant = false
+ }
+
+ if ctx.Config().CFIEnabledForPath(ctx.ModuleDir()) && ctx.Arch().ArchType == android.Arm64 {
+ mayUseCoreVariant = false
+ }
+
+ if mayUseCoreVariant {
library.checkSameCoreVariant = true
if ctx.DeviceConfig().VndkUseCoreVariant() {
library.useCoreVariant = true
diff --git a/java/androidmk.go b/java/androidmk.go
index 6d4d40b..d76e29b 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -341,7 +341,7 @@
entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", app.Privileged())
- entries.SetPath("LOCAL_CERTIFICATE", app.certificate.Pem)
+ entries.SetString("LOCAL_CERTIFICATE", app.certificate.AndroidMkString())
entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", app.getOverriddenPackages()...)
for _, jniLib := range app.installJniLibs {
@@ -699,6 +699,7 @@
Include: "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(entries *android.AndroidMkEntries) {
+ entries.SetString("LOCAL_CERTIFICATE", r.certificate.AndroidMkString())
entries.SetPath("LOCAL_MODULE_PATH", r.installDir.ToMakePath())
},
},
diff --git a/java/app.go b/java/app.go
index a27996c..6e0ffeb 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1243,6 +1243,8 @@
properties RuntimeResourceOverlayProperties
+ certificate Certificate
+
outputFile android.Path
installDir android.InstallPath
}
@@ -1288,6 +1290,7 @@
certificates = processMainCert(r.ModuleBase, String(r.properties.Certificate), certificates, ctx)
signed := android.PathForModuleOut(ctx, "signed", r.Name()+".apk")
SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates)
+ r.certificate = certificates[0]
r.outputFile = signed
r.installDir = android.PathForModuleInstall(ctx, "overlay", String(r.properties.Theme))
diff --git a/java/app_test.go b/java/app_test.go
index 2682682..c20a8e7 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -2242,10 +2242,15 @@
if expected != signingFlag {
t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
}
+ path := android.AndroidMkEntriesForTest(t, config, "", m.Module())[0].EntryMap["LOCAL_CERTIFICATE"]
+ expectedPath := []string{"build/make/target/product/security/platform.x509.pem"}
+ if !reflect.DeepEqual(path, expectedPath) {
+ t.Errorf("Unexpected LOCAL_CERTIFICATE value: %v, expected: %v", path, expectedPath)
+ }
// Check device location.
- path := android.AndroidMkEntriesForTest(t, config, "", m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
- expectedPath := []string{"/tmp/target/product/test_device/product/overlay"}
+ path = android.AndroidMkEntriesForTest(t, config, "", m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
+ expectedPath = []string{"/tmp/target/product/test_device/product/overlay"}
if !reflect.DeepEqual(path, expectedPath) {
t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath)
}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index abdceba..098400b 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -223,6 +223,9 @@
// if set to true, generate docs through Dokka instead of Doclava.
Dokka_enabled *bool
+
+ // Compat config XML. Generates compat change documentation if set.
+ Compat_config *string `android:"path"`
}
type DroidstubsProperties struct {
@@ -1037,6 +1040,11 @@
cmd.Flag(d.Javadoc.args).Implicits(d.Javadoc.argFiles)
+ if d.properties.Compat_config != nil {
+ compatConfig := android.PathForModuleSrc(ctx, String(d.properties.Compat_config))
+ cmd.FlagWithInput("-compatconfig ", compatConfig)
+ }
+
var desc string
if Bool(d.properties.Dokka_enabled) {
desc = "dokka"
diff --git a/java/java_test.go b/java/java_test.go
index a2788cb..0e987a6 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -479,7 +479,9 @@
java_sdk_library_import {
name: "sdklib",
- jars: ["b.jar"],
+ public: {
+ jars: ["c.jar"],
+ },
}
prebuilt_stubs_sources {
@@ -531,6 +533,54 @@
}
}
+func TestJavaSdkLibraryImport(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ libs: ["sdklib"],
+ sdk_version: "current",
+ }
+
+ java_library {
+ name: "foo.system",
+ srcs: ["a.java"],
+ libs: ["sdklib"],
+ sdk_version: "system_current",
+ }
+
+ java_library {
+ name: "foo.test",
+ srcs: ["a.java"],
+ libs: ["sdklib"],
+ sdk_version: "test_current",
+ }
+
+ java_sdk_library_import {
+ name: "sdklib",
+ public: {
+ jars: ["a.jar"],
+ },
+ system: {
+ jars: ["b.jar"],
+ },
+ test: {
+ jars: ["c.jar"],
+ },
+ }
+ `)
+
+ for _, scope := range []string{"", ".system", ".test"} {
+ fooModule := ctx.ModuleForTests("foo"+scope, "android_common")
+ javac := fooModule.Rule("javac")
+
+ sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs"+scope, "android_common").Rule("combineJar").Output
+ if !strings.Contains(javac.Args["classpath"], sdklibStubsJar.String()) {
+ t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], sdklibStubsJar.String())
+ }
+ }
+}
+
func TestDefaults(t *testing.T) {
ctx, _ := testJava(t, `
java_defaults {
@@ -1043,6 +1093,12 @@
libs: ["baz"],
sdk_version: "system_current",
}
+ java_library {
+ name: "baz-test",
+ srcs: ["c.java"],
+ libs: ["foo"],
+ sdk_version: "test_current",
+ }
`)
// check the existence of the internal modules
@@ -1075,6 +1131,13 @@
"foo.stubs.jar")
}
+ bazTestJavac := ctx.ModuleForTests("baz-test", "android_common").Rule("javac")
+ // tests if baz-test is actually linked to the test stubs lib
+ if !strings.Contains(bazTestJavac.Args["classpath"], "foo.stubs.test.jar") {
+ t.Errorf("baz-test javac classpath %v does not contain %q", bazTestJavac.Args["classpath"],
+ "foo.stubs.test.jar")
+ }
+
// test if baz has exported SDK lib names foo and bar to qux
qux := ctx.ModuleForTests("qux", "android_common")
if quxLib, ok := qux.Module().(*Library); ok {
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index d5c7579..95c0574 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -16,11 +16,17 @@
import (
"android/soong/android"
+ "fmt"
)
func init() {
android.RegisterSingletonType("platform_compat_config_singleton", platformCompatConfigSingletonFactory)
android.RegisterModuleType("platform_compat_config", platformCompatConfigFactory)
+ android.RegisterModuleType("global_compat_config", globalCompatConfigFactory)
+}
+
+func platformCompatConfigPath(ctx android.PathContext) android.OutputPath {
+ return android.PathForOutput(ctx, "compat_config", "merged_compat_config.xml")
}
type platformCompatConfigSingleton struct {
@@ -68,7 +74,7 @@
}
rule := android.NewRuleBuilder()
- outputPath := android.PathForOutput(ctx, "compat_config", "merged_compat_config.xml")
+ outputPath := platformCompatConfigPath(ctx)
rule.Command().
BuiltTool(ctx, "process-compat-config").
@@ -130,3 +136,49 @@
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
return module
}
+
+//============== merged_compat_config =================
+type globalCompatConfigProperties struct {
+ // name of the file into which the metadata will be copied.
+ Filename *string
+}
+
+type globalCompatConfig struct {
+ android.ModuleBase
+
+ properties globalCompatConfigProperties
+
+ outputFilePath android.OutputPath
+}
+
+func (c *globalCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ filename := String(c.properties.Filename)
+
+ inputPath := platformCompatConfigPath(ctx)
+ c.outputFilePath = android.PathForModuleOut(ctx, filename).OutputPath
+
+ // This ensures that outputFilePath has the correct name for others to
+ // use, as the source file may have a different name.
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Output: c.outputFilePath,
+ Input: inputPath,
+ })
+}
+
+func (h *globalCompatConfig) OutputFiles(tag string) (android.Paths, error) {
+ switch tag {
+ case "":
+ return android.Paths{h.outputFilePath}, nil
+ default:
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+ }
+}
+
+// global_compat_config provides access to the merged compat config xml file generated by the build.
+func globalCompatConfigFactory() android.Module {
+ module := &globalCompatConfig{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
+ return module
+}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 0ef0f23..cd22e6e 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -225,12 +225,30 @@
apiFilePath android.Path
}
+// Common code between sdk library and sdk library import
+type commonToSdkLibraryAndImport struct {
+ scopePaths map[*apiScope]*scopePaths
+}
+
+func (c *commonToSdkLibraryAndImport) getScopePaths(scope *apiScope) *scopePaths {
+ if c.scopePaths == nil {
+ c.scopePaths = make(map[*apiScope]*scopePaths)
+ }
+ paths := c.scopePaths[scope]
+ if paths == nil {
+ paths = &scopePaths{}
+ c.scopePaths[scope] = paths
+ }
+
+ return paths
+}
+
type SdkLibrary struct {
Library
sdkLibraryProperties sdkLibraryProperties
- scopePaths map[*apiScope]*scopePaths
+ commonToSdkLibraryAndImport
permissionsFile android.Path
}
@@ -246,19 +264,6 @@
}
}
-func (module *SdkLibrary) getScopePaths(scope *apiScope) *scopePaths {
- if module.scopePaths == nil {
- module.scopePaths = make(map[*apiScope]*scopePaths)
- }
- paths := module.scopePaths[scope]
- if paths == nil {
- paths = &scopePaths{}
- module.scopePaths[scope] = paths
- }
-
- return paths
-}
-
func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
useBuiltStubs := !ctx.Config().UnbundledBuildUsePrebuiltSdks()
for _, apiScope := range module.getActiveApiScopes() {
@@ -689,16 +694,19 @@
return module.Library.ImplementationJars()
}
}
- var paths *scopePaths
+ var apiScope *apiScope
switch sdkVersion.kind {
case sdkSystem:
- paths = module.getScopePaths(apiScopeSystem)
+ apiScope = apiScopeSystem
+ case sdkTest:
+ apiScope = apiScopeTest
case sdkPrivate:
return module.Library.HeaderJars()
default:
- paths = module.getScopePaths(apiScopePublic)
+ apiScope = apiScopePublic
}
+ paths := module.getScopePaths(apiScope)
if headerJars {
return paths.stubsHeaderPath
} else {
@@ -830,7 +838,8 @@
// SDK library prebuilts
//
-type sdkLibraryImportProperties struct {
+// Properties associated with each api scope.
+type sdkLibraryScopeProperties struct {
Jars []string `android:"path"`
Sdk_version *string
@@ -839,6 +848,21 @@
Libs []string
}
+type sdkLibraryImportProperties struct {
+ // List of shared java libs, common to all scopes, that this module has
+ // dependencies to
+ Libs []string
+
+ // Properties associated with the public api scope.
+ Public sdkLibraryScopeProperties
+
+ // Properties associated with the system api scope.
+ System sdkLibraryScopeProperties
+
+ // Properties associated with the test api scope.
+ Test sdkLibraryScopeProperties
+}
+
type sdkLibraryImport struct {
android.ModuleBase
android.DefaultableModuleBase
@@ -846,7 +870,7 @@
properties sdkLibraryImportProperties
- stubsPath android.Paths
+ commonToSdkLibraryAndImport
}
var _ SdkLibraryDependency = (*sdkLibraryImport)(nil)
@@ -857,7 +881,7 @@
module.AddProperties(&module.properties)
- android.InitPrebuiltModule(module, &module.properties.Jars)
+ android.InitPrebuiltModule(module, &[]string{})
InitJavaModule(module, android.HostAndDeviceSupported)
android.AddLoadHook(module, func(mctx android.LoadHookContext) { module.createInternalModules(mctx) })
@@ -873,38 +897,67 @@
}
func (module *sdkLibraryImport) createInternalModules(mctx android.LoadHookContext) {
- // Creates a java import for the jar with ".stubs" suffix
- props := struct {
- Name *string
- Soc_specific *bool
- Device_specific *bool
- Product_specific *bool
- System_ext_specific *bool
- }{}
- props.Name = proptools.StringPtr(module.BaseModuleName() + sdkStubsLibrarySuffix)
+ for apiScope, scopeProperties := range module.scopeProperties() {
+ if len(scopeProperties.Jars) == 0 {
+ continue
+ }
- if module.SocSpecific() {
- props.Soc_specific = proptools.BoolPtr(true)
- } else if module.DeviceSpecific() {
- props.Device_specific = proptools.BoolPtr(true)
- } else if module.ProductSpecific() {
- props.Product_specific = proptools.BoolPtr(true)
- } else if module.SystemExtSpecific() {
- props.System_ext_specific = proptools.BoolPtr(true)
+ // Creates a java import for the jar with ".stubs" suffix
+ props := struct {
+ Name *string
+ Soc_specific *bool
+ Device_specific *bool
+ Product_specific *bool
+ System_ext_specific *bool
+ Sdk_version *string
+ Libs []string
+ Jars []string
+ }{}
+
+ props.Name = proptools.StringPtr(apiScope.stubsModuleName(module.BaseModuleName()))
+ props.Sdk_version = scopeProperties.Sdk_version
+ // Prepend any of the libs from the legacy public properties to the libs for each of the
+ // scopes to avoid having to duplicate them in each scope.
+ props.Libs = append(module.properties.Libs, scopeProperties.Libs...)
+ props.Jars = scopeProperties.Jars
+
+ if module.SocSpecific() {
+ props.Soc_specific = proptools.BoolPtr(true)
+ } else if module.DeviceSpecific() {
+ props.Device_specific = proptools.BoolPtr(true)
+ } else if module.ProductSpecific() {
+ props.Product_specific = proptools.BoolPtr(true)
+ } else if module.SystemExtSpecific() {
+ props.System_ext_specific = proptools.BoolPtr(true)
+ }
+
+ mctx.CreateModule(ImportFactory, &props)
}
- mctx.CreateModule(ImportFactory, &props, &module.properties)
-
javaSdkLibraries := javaSdkLibraries(mctx.Config())
javaSdkLibrariesLock.Lock()
defer javaSdkLibrariesLock.Unlock()
*javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
}
+func (module *sdkLibraryImport) scopeProperties() map[*apiScope]*sdkLibraryScopeProperties {
+ p := make(map[*apiScope]*sdkLibraryScopeProperties)
+ p[apiScopePublic] = &module.properties.Public
+ p[apiScopeSystem] = &module.properties.System
+ p[apiScopeTest] = &module.properties.Test
+ return p
+}
+
func (module *sdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) {
- // Add dependencies to the prebuilt stubs library
- ctx.AddVariationDependencies(nil, apiScopePublic.stubsTag, module.BaseModuleName()+sdkStubsLibrarySuffix)
+ for apiScope, scopeProperties := range module.scopeProperties() {
+ if len(scopeProperties.Jars) == 0 {
+ continue
+ }
+
+ // Add dependencies to the prebuilt stubs library
+ ctx.AddVariationDependencies(nil, apiScope.stubsTag, apiScope.stubsModuleName(module.BaseModuleName()))
+ }
}
func (module *sdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -912,21 +965,42 @@
ctx.VisitDirectDeps(func(to android.Module) {
tag := ctx.OtherModuleDependencyTag(to)
- switch tag {
- case apiScopePublic.stubsTag:
- module.stubsPath = to.(Dependency).HeaderJars()
+ if lib, ok := to.(Dependency); ok {
+ if scopeTag, ok := tag.(scopeDependencyTag); ok {
+ apiScope := scopeTag.apiScope
+ scopePaths := module.getScopePaths(apiScope)
+ scopePaths.stubsHeaderPath = lib.HeaderJars()
+ }
}
})
}
+func (module *sdkLibraryImport) sdkJars(
+ ctx android.BaseModuleContext,
+ sdkVersion sdkSpec) android.Paths {
+
+ var apiScope *apiScope
+ switch sdkVersion.kind {
+ case sdkSystem:
+ apiScope = apiScopeSystem
+ case sdkTest:
+ apiScope = apiScopeTest
+ default:
+ apiScope = apiScopePublic
+ }
+
+ paths := module.getScopePaths(apiScope)
+ return paths.stubsHeaderPath
+}
+
// to satisfy SdkLibraryDependency interface
func (module *sdkLibraryImport) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
// This module is just a wrapper for the prebuilt stubs.
- return module.stubsPath
+ return module.sdkJars(ctx, sdkVersion)
}
// to satisfy SdkLibraryDependency interface
func (module *sdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
// This module is just a wrapper for the stubs.
- return module.stubsPath
+ return module.sdkJars(ctx, sdkVersion)
}
diff --git a/java/testing.go b/java/testing.go
index 08bae44..e746e2d 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -30,6 +30,7 @@
"b.kt": nil,
"a.jar": nil,
"b.jar": nil,
+ "c.jar": nil,
"APP_NOTICE": nil,
"GENRULE_NOTICE": nil,
"LIB_NOTICE": nil,
diff --git a/scripts/setup-android-build.sh b/scripts/setup-android-build.sh
new file mode 100755
index 0000000..dbb66c3
--- /dev/null
+++ b/scripts/setup-android-build.sh
@@ -0,0 +1,93 @@
+#! /bin/bash
+#
+# Sets the current directory as Android build output directory for a
+# given target by writing the "prefix script" to it. Commands prefixed
+# by this script are executed in the Android build environment. E.g.,
+# running
+# ./run <command>
+# runs <command> as if we issued
+# cd <source>
+# mount --bind <build dir> out
+# . build/envsetup.sh
+# lunch <config>
+# <command>
+# exit
+#
+# This arrangement eliminates the need to issue envsetup/lunch commands
+# manually, and allows to run multiple builds from the same shell.
+# Thus, if your source tree is in ~/aosp and you are building for
+# 'blueline' and 'cuttlefish', issuing
+# cd /sdx/blueline && \
+# ~/aosp/build/soong/scripts/setup-android-build.sh aosp_blueline-userdebug
+# cd /sdx/cuttlefish && \
+# ~/aosp/build/soong/scripts/setup-android-build.sh aosp_cf_arm64_phone-userdebug
+# sets up build directories in /sdx/blueline and /sdx/cuttlefish respectively.
+# After that, issue
+# /sdx/blueline/run m
+# to build blueline image, and issue
+# /sdx/cuttlefish atest CtsSecurityBulletinHostTestCases
+# to run CTS tests. Notice there is no need to change to a specific directory for that.
+#
+# Argument:
+# * configuration (one of those shown by `lunch` command).
+#
+set -e
+function die() { printf "$@"; exit 1; }
+
+# Find out where the source tree using the fact that we are in its
+# build/ subdirectory.
+[[ "$(uname)" == Linux ]] || die "This setup runs only on Linux\n"
+declare -r mydir="${0%/*}"
+declare -r source="${mydir%/build/soong/scripts}"
+[[ "/${mydir}/" =~ '/build/soong/scripts/' ]] || \
+ die "$0 should be in build/soong/scripts/ subdirectory of the source tree\n"
+[[ ! -e .repo && ! -e .git ]] || \
+ die "Current directory looks like source. You should be in the _target_ directory.\n"
+# Do not override old run script.
+if [[ -x ./run ]]; then
+ # Set variables from config=xxx and source=xxx comments in the existing script.
+ . <(sed -nr 's/^# *source=(.*)/oldsource=\1/p;s/^# *config=(.*)/oldconfig=\1/p' run)
+ die "This directory has been already set up to build Android for %s from %s.\n\
+Remove 'run' file if you want to set it up afresh\n" "$oldconfig" "$oldsource"
+fi
+
+(($#<2)) || die "usage: %s [<config>]\n" $0
+
+if (($#==1)); then
+ # Configuration is provided, emit run script.
+ declare -r config="$1"
+ declare -r target="$PWD"
+ cat >./run <<EOF
+#! /bin/bash
+# source=$source
+# config=$config
+declare -r cmd=\$(printf ' %q' "\$@")
+"$source/prebuilts/build-tools/linux-x86/bin/nsjail"\
+ -Mo -q -e -t 0\
+ -EANDROID_QUIET_BUILD=true \
+ -B / -B "$target:$source/out"\
+ --cwd "$source"\
+ --skip_setsid \
+ --keep_caps\
+ --disable_clone_newcgroup\
+ --disable_clone_newnet\
+ --rlimit_as soft\
+ --rlimit_core soft\
+ --rlimit_cpu soft\
+ --rlimit_fsize soft\
+ --rlimit_nofile soft\
+ --proc_rw\
+ --hostname $(hostname) \
+ --\
+ /bin/bash -i -c ". build/envsetup.sh && lunch "$config" &&\$cmd"
+EOF
+ chmod +x ./run
+else
+ # No configuration, show available ones.
+ printf "Please specify build target. Common values:\n"
+ (cd "$source"
+ . build/envsetup.sh
+ get_build_var COMMON_LUNCH_CHOICES | tr ' ' '\n' | pr -c4 -tT -W"$(tput cols)"
+ )
+ exit 1
+fi