Merge "Correct fmt printf error in bazel_handler"
diff --git a/android/apex.go b/android/apex.go
index 81f8c86..a014592 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -849,8 +849,12 @@
if err := to.ShouldSupportSdkVersion(ctx, minSdkVersion); err != nil {
toName := ctx.OtherModuleName(to)
if ver, ok := minSdkVersionAllowlist[toName]; !ok || ver.GreaterThan(minSdkVersion) {
- ctx.OtherModuleErrorf(to, "should support min_sdk_version(%v) for %q: %v. Dependency path: %s",
- minSdkVersion, ctx.ModuleName(), err.Error(), ctx.GetPathString(false))
+ ctx.OtherModuleErrorf(to, "should support min_sdk_version(%v) for %q: %v."+
+ "\n\nDependency path: %s\n\n"+
+ "Consider adding 'min_sdk_version: %q' to %q",
+ minSdkVersion, ctx.ModuleName(), err.Error(),
+ ctx.GetPathString(false),
+ minSdkVersion, ctx.ModuleName())
return false
}
}
diff --git a/android/config.go b/android/config.go
index ef5eadf..c10ad09 100644
--- a/android/config.go
+++ b/android/config.go
@@ -232,7 +232,7 @@
// Copy the real PATH value to the test environment, it's needed by
// NonHermeticHostSystemTool() used in x86_darwin_host.go
- envCopy["PATH"] = originalEnv["PATH"]
+ envCopy["PATH"] = os.Getenv("PATH")
config := &config{
productVariables: productVariables{
diff --git a/android/env.go b/android/env.go
index a8c7777..58ad0b6 100644
--- a/android/env.go
+++ b/android/env.go
@@ -17,7 +17,6 @@
import (
"fmt"
"os"
- "os/exec"
"strings"
"syscall"
@@ -34,37 +33,27 @@
var originalEnv map[string]string
var soongDelveListen string
var soongDelvePath string
-var soongDelveEnv []string
+var isDebugging bool
-func init() {
- // Delve support needs to read this environment variable very early, before NewConfig has created a way to
- // access originalEnv with dependencies. Store the value where soong_build can find it, it will manually
- // ensure the dependencies are created.
- soongDelveListen = os.Getenv("SOONG_DELVE")
- soongDelvePath = os.Getenv("SOONG_DELVE_PATH")
- if soongDelvePath == "" {
- soongDelvePath, _ = exec.LookPath("dlv")
+func InitEnvironment(envFile string) {
+ var err error
+ originalEnv, err = shared.EnvFromFile(envFile)
+ if err != nil {
+ panic(err)
}
- originalEnv = make(map[string]string)
- soongDelveEnv = []string{}
- for _, env := range os.Environ() {
- idx := strings.IndexRune(env, '=')
- if idx != -1 {
- originalEnv[env[:idx]] = env[idx+1:]
- if env[:idx] != "SOONG_DELVE" && env[:idx] != "SOONG_DELVE_PATH" {
- soongDelveEnv = append(soongDelveEnv, env)
- }
- }
- }
-
- // Clear the environment to prevent use of os.Getenv(), which would not provide dependencies on environment
- // variable values. The environment is available through ctx.Config().Getenv, ctx.Config().IsEnvTrue, etc.
- os.Clearenv()
+ soongDelveListen = originalEnv["SOONG_DELVE"]
+ soongDelvePath = originalEnv["SOONG_DELVE_PATH"]
}
+// Returns whether the current process is running under Delve due to
+// ReexecWithDelveMaybe().
+func IsDebugging() bool {
+ return isDebugging
+}
func ReexecWithDelveMaybe() {
- if soongDelveListen == "" {
+ isDebugging = os.Getenv("SOONG_DELVE_REEXECUTED") == "true"
+ if isDebugging || soongDelveListen == "" {
return
}
@@ -72,6 +61,17 @@
fmt.Fprintln(os.Stderr, "SOONG_DELVE is set but failed to find dlv")
os.Exit(1)
}
+
+ soongDelveEnv := []string{}
+ for _, env := range os.Environ() {
+ idx := strings.IndexRune(env, '=')
+ if idx != -1 {
+ soongDelveEnv = append(soongDelveEnv, env)
+ }
+ }
+
+ soongDelveEnv = append(soongDelveEnv, "SOONG_DELVE_REEXECUTED=true")
+
dlvArgv := []string{
soongDelvePath,
"--listen=:" + soongDelveListen,
@@ -88,17 +88,6 @@
os.Exit(1)
}
-// getenv checks either os.Getenv or originalEnv so that it works before or after the init()
-// function above. It doesn't add any dependencies on the environment variable, so it should
-// only be used for values that won't change. For values that might change use ctx.Config().Getenv.
-func getenv(key string) string {
- if originalEnv == nil {
- return os.Getenv(key)
- } else {
- return originalEnv[key]
- }
-}
-
func EnvSingleton() Singleton {
return &envSingleton{}
}
@@ -108,7 +97,7 @@
func (c *envSingleton) GenerateBuildActions(ctx SingletonContext) {
envDeps := ctx.Config().EnvDeps()
- envFile := PathForOutput(ctx, ".soong.environment")
+ envFile := PathForOutput(ctx, "soong.environment.used")
if ctx.Failed() {
return
}
diff --git a/android/license.go b/android/license.go
index b140b55..3bc6199 100644
--- a/android/license.go
+++ b/android/license.go
@@ -19,7 +19,7 @@
)
type licenseKindDependencyTag struct {
- blueprint.BaseDependencyTag
+ blueprint.BaseDependencyTag
}
var (
diff --git a/android/license_test.go b/android/license_test.go
index 552bbae..9f68713 100644
--- a/android/license_test.go
+++ b/android/license_test.go
@@ -49,9 +49,9 @@
}`),
},
expectedErrors: []string{
- `other/Blueprints:2:5: module "arule": depends on //top:top_allowed_as_notice `+
+ `other/Blueprints:2:5: module "arule": depends on //top:top_allowed_as_notice ` +
`which is not visible to this module`,
- `yetmore/Blueprints:2:5: module "//yetmore": depends on //top:top_allowed_as_notice `+
+ `yetmore/Blueprints:2:5: module "//yetmore": depends on //top:top_allowed_as_notice ` +
`which is not visible to this module`,
},
},
@@ -70,7 +70,7 @@
}`),
},
expectedErrors: []string{
- `top/Blueprints:6:5: module "top_proprietary": license_kinds property `+
+ `top/Blueprints:6:5: module "top_proprietary": license_kinds property ` +
`"top_by_exception_only" is not a license_kind module`,
},
},
diff --git a/android/licenses.go b/android/licenses.go
index 1000429..2838f5d 100644
--- a/android/licenses.go
+++ b/android/licenses.go
@@ -51,7 +51,7 @@
func newApplicableLicensesProperty(name string, licensesProperty *[]string) applicableLicensesProperty {
return applicableLicensesPropertyImpl{
- name: name,
+ name: name,
licensesProperty: licensesProperty,
}
}
diff --git a/android/licenses_test.go b/android/licenses_test.go
index b94add7..c043791 100644
--- a/android/licenses_test.go
+++ b/android/licenses_test.go
@@ -7,15 +7,15 @@
)
var licensesTests = []struct {
- name string
- fs map[string][]byte
- expectedErrors []string
- effectiveLicenses map[string][]string
- effectiveInheritedLicenses map[string][]string
- effectivePackage map[string]string
- effectiveNotices map[string][]string
- effectiveKinds map[string][]string
- effectiveConditions map[string][]string
+ name string
+ fs map[string][]byte
+ expectedErrors []string
+ effectiveLicenses map[string][]string
+ effectiveInheritedLicenses map[string][]string
+ effectivePackage map[string]string
+ effectiveNotices map[string][]string
+ effectiveKinds map[string][]string
+ effectiveConditions map[string][]string
}{
{
name: "invalid module type without licenses property",
@@ -71,28 +71,28 @@
},
effectiveLicenses: map[string][]string{
"libexample1": []string{"top_Apache2"},
- "libnested": []string{"top_Apache2"},
- "libother": []string{"top_Apache2"},
+ "libnested": []string{"top_Apache2"},
+ "libother": []string{"top_Apache2"},
},
effectiveKinds: map[string][]string{
"libexample1": []string{"notice"},
- "libnested": []string{"notice"},
- "libother": []string{"notice"},
+ "libnested": []string{"notice"},
+ "libother": []string{"notice"},
},
effectivePackage: map[string]string{
"libexample1": "topDog",
- "libnested": "topDog",
- "libother": "topDog",
+ "libnested": "topDog",
+ "libother": "topDog",
},
effectiveConditions: map[string][]string{
"libexample1": []string{"shownotice"},
- "libnested": []string{"shownotice"},
- "libother": []string{"shownotice"},
+ "libnested": []string{"shownotice"},
+ "libother": []string{"shownotice"},
},
effectiveNotices: map[string][]string{
"libexample1": []string{"top/LICENSE", "top/NOTICE"},
- "libnested": []string{"top/LICENSE", "top/NOTICE"},
- "libother": []string{"top/LICENSE", "top/NOTICE"},
+ "libnested": []string{"top/LICENSE", "top/NOTICE"},
+ "libother": []string{"top/LICENSE", "top/NOTICE"},
},
},
@@ -147,28 +147,28 @@
}`),
},
effectiveLicenses: map[string][]string{
- "libexample": []string{"nested_other", "top_other"},
+ "libexample": []string{"nested_other", "top_other"},
"libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
+ "libnested": []string{},
+ "libother": []string{},
},
effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"nested_other", "top_other"},
+ "libexample": []string{"nested_other", "top_other"},
"libsamepackage": []string{"nested_other", "top_other"},
- "libnested": []string{"nested_other", "top_other"},
- "libother": []string{"nested_other", "top_other"},
+ "libnested": []string{"nested_other", "top_other"},
+ "libother": []string{"nested_other", "top_other"},
},
effectiveKinds: map[string][]string{
- "libexample": []string{"nested_notice", "top_notice"},
+ "libexample": []string{"nested_notice", "top_notice"},
"libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
+ "libnested": []string{},
+ "libother": []string{},
},
effectiveConditions: map[string][]string{
- "libexample": []string{"notice"},
+ "libexample": []string{"notice"},
"libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
+ "libnested": []string{},
+ "libother": []string{},
},
},
{
@@ -218,32 +218,32 @@
}`),
},
effectiveLicenses: map[string][]string{
- "libexample": []string{"other", "top_nested"},
+ "libexample": []string{"other", "top_nested"},
"libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
- "liboutsider": []string{},
+ "libnested": []string{},
+ "libother": []string{},
+ "liboutsider": []string{},
},
effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"other", "top_nested"},
+ "libexample": []string{"other", "top_nested"},
"libsamepackage": []string{"other", "top_nested"},
- "libnested": []string{"other", "top_nested"},
- "libother": []string{"other", "top_nested"},
- "liboutsider": []string{"other", "top_nested"},
+ "libnested": []string{"other", "top_nested"},
+ "libother": []string{"other", "top_nested"},
+ "liboutsider": []string{"other", "top_nested"},
},
effectiveKinds: map[string][]string{
- "libexample": []string{},
+ "libexample": []string{},
"libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
- "liboutsider": []string{},
+ "libnested": []string{},
+ "libother": []string{},
+ "liboutsider": []string{},
},
effectiveNotices: map[string][]string{
- "libexample": []string{"top/nested/LICENSE.txt"},
+ "libexample": []string{"top/nested/LICENSE.txt"},
"libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
- "liboutsider": []string{},
+ "libnested": []string{},
+ "libother": []string{},
+ "liboutsider": []string{},
},
},
@@ -285,11 +285,11 @@
}`),
},
effectiveLicenses: map[string][]string{
- "libexample": []string{"by_exception_only"},
+ "libexample": []string{"by_exception_only"},
"libdefaults": []string{"notice"},
},
effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"by_exception_only"},
+ "libexample": []string{"by_exception_only"},
"libdefaults": []string{"notice"},
},
},
@@ -327,11 +327,11 @@
}`),
},
effectiveLicenses: map[string][]string{
- "libexample": []string{"top_notice"},
+ "libexample": []string{"top_notice"},
"liboutsider": []string{},
},
effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"top_notice"},
+ "libexample": []string{"top_notice"},
"liboutsider": []string{"top_notice"},
},
},
@@ -370,15 +370,15 @@
}`),
},
effectiveLicenses: map[string][]string{
- "libexample": []string{"top_notice"},
- "libnested": []string{"outsider"},
- "libother": []string{},
+ "libexample": []string{"top_notice"},
+ "libnested": []string{"outsider"},
+ "libother": []string{},
"liboutsider": []string{},
},
effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"top_notice"},
- "libnested": []string{"outsider"},
- "libother": []string{},
+ "libexample": []string{"top_notice"},
+ "libnested": []string{"outsider"},
+ "libother": []string{},
"liboutsider": []string{"top_notice", "outsider"},
},
},
@@ -449,7 +449,7 @@
},
effectiveInheritedLicenses: map[string][]string{
"module": []string{"prebuilt", "top_sources"},
- "other": []string{"prebuilt", "top_sources"},
+ "other": []string{"prebuilt", "top_sources"},
},
},
}
diff --git a/android/module.go b/android/module.go
index e8fb749..9f923e2 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1832,6 +1832,18 @@
return
}
+ m.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc)
+ rcDir := PathForModuleInstall(ctx, "etc", "init")
+ for _, src := range m.initRcPaths {
+ ctx.PackageFile(rcDir, filepath.Base(src.String()), src)
+ }
+
+ m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments)
+ vintfDir := PathForModuleInstall(ctx, "etc", "vintf", "manifest")
+ for _, src := range m.vintfFragmentsPaths {
+ ctx.PackageFile(vintfDir, filepath.Base(src.String()), src)
+ }
+
// Create the set of tagged dist files after calling GenerateAndroidBuildActions
// as GenerateTaggedDistFiles() calls OutputFiles(tag) and so relies on the
// output paths being set which must be done before or during
@@ -1844,8 +1856,6 @@
m.installFiles = append(m.installFiles, ctx.installFiles...)
m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...)
m.packagingSpecs = append(m.packagingSpecs, ctx.packagingSpecs...)
- m.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc)
- m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments)
for k, v := range ctx.phonies {
m.phonies[k] = append(m.phonies[k], v...)
}
diff --git a/android/paths.go b/android/paths.go
index ada4da6..3f4d3f2 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1662,9 +1662,9 @@
// on a device without a dedicated recovery partition, install the
// recovery variant.
if ctx.DeviceConfig().BoardMoveRecoveryResourcesToVendorBoot() {
- partition = "vendor-ramdisk/first_stage_ramdisk"
+ partition = "vendor_ramdisk/first_stage_ramdisk"
} else {
- partition = "vendor-ramdisk"
+ partition = "vendor_ramdisk"
}
if !ctx.InstallInRoot() {
partition += "/system"
diff --git a/android/sandbox.go b/android/sandbox.go
index ed022fb..28e903a 100644
--- a/android/sandbox.go
+++ b/android/sandbox.go
@@ -14,29 +14,8 @@
package android
-import (
- "fmt"
- "os"
-)
-
-func init() {
- // Stash the working directory in a private variable and then change the working directory
- // to "/", which will prevent untracked accesses to files by Go Soong plugins. The
- // SOONG_SANDBOX_SOONG_BUILD environment variable is set by soong_ui, and is not
- // overrideable on the command line.
-
- orig, err := os.Getwd()
- if err != nil {
- panic(fmt.Errorf("failed to get working directory: %s", err))
- }
- absSrcDir = orig
-
- if getenv("SOONG_SANDBOX_SOONG_BUILD") == "true" {
- err = os.Chdir("/")
- if err != nil {
- panic(fmt.Errorf("failed to change working directory to '/': %s", err))
- }
- }
+func InitSandbox(topDir string) {
+ absSrcDir = topDir
}
// DO NOT USE THIS FUNCTION IN NEW CODE.
diff --git a/android/writedocs.go b/android/writedocs.go
index 91c2318..6417690 100644
--- a/android/writedocs.go
+++ b/android/writedocs.go
@@ -34,7 +34,8 @@
type docsSingleton struct{}
func primaryBuilderPath(ctx SingletonContext) Path {
- primaryBuilder, err := filepath.Rel(ctx.Config().BuildDir(), os.Args[0])
+ buildDir := absolutePath(ctx.Config().BuildDir())
+ primaryBuilder, err := filepath.Rel(buildDir, os.Args[0])
if err != nil {
ctx.Errorf("path to primary builder %q is not in build dir %q",
os.Args[0], ctx.Config().BuildDir())
diff --git a/apex/OWNERS b/apex/OWNERS
index 793f3ed..fee739b 100644
--- a/apex/OWNERS
+++ b/apex/OWNERS
@@ -1,4 +1,4 @@
per-file * = jiyong@google.com
per-file allowed_deps.txt = set noparent
-per-file allowed_deps.txt = dariofreni@google.com,hansson@google.com,harpin@google.com,jiyong@google.com,narayan@google.com,omakoto@google.com,jham@google.com
+per-file allowed_deps.txt = dariofreni@google.com,hansson@google.com,harpin@google.com,jiyong@google.com,narayan@google.com,jham@google.com
diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt
index 78b84f0..476ac4a 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -361,6 +361,7 @@
libmedia_headers(minSdkVersion:29)
libmedia_helper_headers(minSdkVersion:29)
libmedia_midiiowrapper(minSdkVersion:29)
+libmediaparser-jni(minSdkVersion:29)
libmidiextractor(minSdkVersion:29)
libminijail(minSdkVersion:29)
libminijail_gen_constants(minSdkVersion:(no version))
@@ -635,6 +636,7 @@
Tethering(minSdkVersion:current)
TetheringApiCurrentLib(minSdkVersion:30)
TetheringApiCurrentLib(minSdkVersion:current)
+TetheringGoogle(minSdkVersion:30)
TetheringGoogle(minSdkVersion:current)
textclassifier-statsd(minSdkVersion:current)
TextClassifierNotificationLibNoManifest(minSdkVersion:29)
diff --git a/apex/apex.go b/apex/apex.go
index 8f388c4..efd1736 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -2244,8 +2244,10 @@
if to.AvailableFor(apexName) || baselineApexAvailable(apexName, toName) {
return true
}
- ctx.ModuleErrorf("%q requires %q that doesn't list the APEX under 'apex_available'. Dependency path:%s",
- fromName, toName, ctx.GetPathString(true))
+ ctx.ModuleErrorf("%q requires %q that doesn't list the APEX under 'apex_available'."+
+ "\n\nDependency path:%s\n\n"+
+ "Consider adding %q to 'apex_available' property of %q",
+ fromName, toName, ctx.GetPathString(true), apexName, toName)
// Visit this module's dependencies to check and report any issues with their availability.
return true
})
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 8ae6634..fcf2343 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -2534,7 +2534,8 @@
var builder strings.Builder
data.Custom(&builder, name, prefix, "", data)
androidMk := builder.String()
- ensureContains(t, androidMk, `LOCAL_MODULE_PATH := /tmp/target/product/test_device/vendor/apex`)
+ installPath := path.Join(buildDir, "../target/product/test_device/vendor/apex")
+ ensureContains(t, androidMk, "LOCAL_MODULE_PATH := "+installPath)
apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule")
requireNativeLibs := names(apexManifestRule.Args["requireNativeLibs"])
@@ -5314,7 +5315,7 @@
func TestApexAvailable_IndirectDep(t *testing.T) {
// libbbaz is an indirect dep
- testApexError(t, `requires "libbaz" that doesn't list the APEX under 'apex_available'. Dependency path:
+ testApexError(t, `requires "libbaz" that doesn't list the APEX under 'apex_available'.\n\nDependency path:
.*via tag apex\.dependencyTag.*name:sharedLib.*
.*-> libfoo.*link:shared.*
.*via tag cc\.libraryDependencyTag.*Kind:sharedLibraryDependency.*
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 3a6feca..e7f995f 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -21,6 +21,7 @@
"path/filepath"
"strings"
+ "android/soong/shared"
"github.com/google/blueprint/bootstrap"
"android/soong/android"
@@ -28,11 +29,15 @@
)
var (
+ topDir string
+ outDir string
docFile string
bazelQueryViewDir string
)
func init() {
+ flag.StringVar(&topDir, "top", "", "Top directory of the Android source tree")
+ flag.StringVar(&outDir, "out", "", "Soong output directory (usually $TOP/out/soong)")
flag.StringVar(&docFile, "soong_docs", "", "build documentation file to output")
flag.StringVar(&bazelQueryViewDir, "bazel_queryview_dir", "", "path to the bazel queryview directory")
}
@@ -80,15 +85,22 @@
}
func main() {
- android.ReexecWithDelveMaybe()
flag.Parse()
+ android.InitSandbox(topDir)
+ android.InitEnvironment(shared.JoinPath(topDir, outDir, "soong.environment.available"))
+ android.ReexecWithDelveMaybe()
+
// The top-level Blueprints file is passed as the first argument.
srcDir := filepath.Dir(flag.Arg(0))
var ctx *android.Context
configuration := newConfig(srcDir)
extraNinjaDeps := []string{configuration.ProductVariablesFileName}
+ // These two are here so that we restart a non-debugged soong_build when the
+ // user sets SOONG_DELVE the first time.
+ configuration.Getenv("SOONG_DELVE")
+ configuration.Getenv("SOONG_DELVE_PATH")
// Read the SOONG_DELVE again through configuration so that there is a dependency on the environment variable
// and soong_build will rerun when it is set for the first time.
if listen := configuration.Getenv("SOONG_DELVE"); listen != "" {
diff --git a/java/rro_test.go b/java/rro_test.go
index edbf170..061d9d3 100644
--- a/java/rro_test.go
+++ b/java/rro_test.go
@@ -20,6 +20,7 @@
"testing"
"android/soong/android"
+ "android/soong/shared"
)
func TestRuntimeResourceOverlay(t *testing.T) {
@@ -105,7 +106,7 @@
// Check device location.
path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"]
- expectedPath = []string{"/tmp/target/product/test_device/product/overlay"}
+ expectedPath = []string{shared.JoinPath(buildDir, "../target/product/test_device/product/overlay")}
if !reflect.DeepEqual(path, expectedPath) {
t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath)
}
@@ -114,7 +115,7 @@
m = ctx.ModuleForTests("foo_themed", "android_common")
androidMkEntries = android.AndroidMkEntriesForTest(t, ctx, m.Module())[0]
path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"]
- expectedPath = []string{"/tmp/target/product/test_device/product/overlay/faza"}
+ expectedPath = []string{shared.JoinPath(buildDir, "../target/product/test_device/product/overlay/faza")}
if !reflect.DeepEqual(path, expectedPath) {
t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath)
}
@@ -160,7 +161,7 @@
// Check device location.
path := android.AndroidMkEntriesForTest(t, ctx, m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
- expectedPath := []string{"/tmp/target/product/test_device/product/overlay/default_theme"}
+ expectedPath := []string{shared.JoinPath(buildDir, "../target/product/test_device/product/overlay/default_theme")}
if !reflect.DeepEqual(path, expectedPath) {
t.Errorf("Unexpected LOCAL_MODULE_PATH value: %q, expected: %q", path, expectedPath)
}
@@ -179,7 +180,7 @@
// Check device location.
path = android.AndroidMkEntriesForTest(t, ctx, m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
- expectedPath = []string{"/tmp/target/product/test_device/system/overlay"}
+ expectedPath = []string{shared.JoinPath(buildDir, "../target/product/test_device/system/overlay")}
if !reflect.DeepEqual(path, expectedPath) {
t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath)
}
diff --git a/sh/sh_binary_test.go b/sh/sh_binary_test.go
index fb7ab13..f48f7fb 100644
--- a/sh/sh_binary_test.go
+++ b/sh/sh_binary_test.go
@@ -3,6 +3,7 @@
import (
"io/ioutil"
"os"
+ "path"
"path/filepath"
"reflect"
"testing"
@@ -73,7 +74,8 @@
entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
- expectedPath := "/tmp/target/product/test_device/data/nativetest64/foo_test"
+ expectedPath := path.Join(buildDir,
+ "../target/product/test_device/data/nativetest64/foo_test")
actualPath := entries.EntryMap["LOCAL_MODULE_PATH"][0]
if expectedPath != actualPath {
t.Errorf("Unexpected LOCAL_MODULE_PATH expected: %q, actual: %q", expectedPath, actualPath)
@@ -97,7 +99,8 @@
entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
- expectedPath := "/tmp/target/product/test_device/data/nativetest64/foo"
+ expectedPath := path.Join(buildDir,
+ "../target/product/test_device/data/nativetest64/foo")
actualPath := entries.EntryMap["LOCAL_MODULE_PATH"][0]
if expectedPath != actualPath {
t.Errorf("Unexpected LOCAL_MODULE_PATH expected: %q, actual: %q", expectedPath, actualPath)
diff --git a/shared/Android.bp b/shared/Android.bp
index c79bc2b..deb17f8 100644
--- a/shared/Android.bp
+++ b/shared/Android.bp
@@ -8,6 +8,10 @@
srcs: [
"env.go",
"paths.go",
+ "debug.go",
+ ],
+ testSrcs: [
+ "paths_test.go",
],
deps: [
"soong-bazel",
diff --git a/shared/debug.go b/shared/debug.go
new file mode 100644
index 0000000..0c9ba4f
--- /dev/null
+++ b/shared/debug.go
@@ -0,0 +1,17 @@
+package shared
+
+import (
+ "os"
+ "os/exec"
+)
+
+// Finds the Delve binary to use. Either uses the SOONG_DELVE_PATH environment
+// variable or if that is unset, looks at $PATH.
+func ResolveDelveBinary() string {
+ result := os.Getenv("SOONG_DELVE_PATH")
+ if result == "" {
+ result, _ = exec.LookPath("dlv")
+ }
+
+ return result
+}
diff --git a/shared/env.go b/shared/env.go
index 7900daa..152729b 100644
--- a/shared/env.go
+++ b/shared/env.go
@@ -91,6 +91,28 @@
return false, nil
}
+// Deserializes and environment serialized by EnvFileContents() and returns it
+// as a map[string]string.
+func EnvFromFile(envFile string) (map[string]string, error) {
+ result := make(map[string]string)
+ data, err := ioutil.ReadFile(envFile)
+ if err != nil {
+ return result, err
+ }
+
+ var contents envFileData
+ err = json.Unmarshal(data, &contents)
+ if err != nil {
+ return result, err
+ }
+
+ for _, entry := range contents {
+ result[entry.Key] = entry.Value
+ }
+
+ return result, nil
+}
+
// Implements sort.Interface so that we can use sort.Sort on envFileData arrays.
func (e envFileData) Len() int {
return len(e)
diff --git a/shared/paths.go b/shared/paths.go
index 1b9ff60..fca8b4c 100644
--- a/shared/paths.go
+++ b/shared/paths.go
@@ -30,6 +30,21 @@
BazelMetricsDir() string
}
+// Joins the path strings in the argument list, taking absolute paths into
+// account. That is, if one of the strings is an absolute path, the ones before
+// are ignored.
+func JoinPath(base string, rest ...string) string {
+ result := base
+ for _, next := range rest {
+ if filepath.IsAbs(next) {
+ result = next
+ } else {
+ result = filepath.Join(result, next)
+ }
+ }
+ return result
+}
+
// Given the out directory, returns the root of the temp directory (to be cleared at the start of each execution of Soong)
func TempDirForOutDir(outDir string) (tempPath string) {
return filepath.Join(outDir, ".temp")
diff --git a/shared/paths_test.go b/shared/paths_test.go
new file mode 100644
index 0000000..018d55f
--- /dev/null
+++ b/shared/paths_test.go
@@ -0,0 +1,32 @@
+// Copyright 2021 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 shared
+
+import (
+ "testing"
+)
+
+func assertEqual(t *testing.T, expected, actual string) {
+ t.Helper()
+ if expected != actual {
+ t.Errorf("expected %q != got %q", expected, actual)
+ }
+}
+
+func TestJoinPath(t *testing.T) {
+ assertEqual(t, "/a/b", JoinPath("c/d", "/a/b"))
+ assertEqual(t, "a/b", JoinPath("a", "b"))
+ assertEqual(t, "/a/b", JoinPath("x", "/a", "b"))
+}
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index b1f8551..6ba497c 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -124,7 +124,7 @@
productOut("obj/PACKAGING"),
productOut("ramdisk"),
productOut("debug_ramdisk"),
- productOut("vendor-ramdisk"),
+ productOut("vendor_ramdisk"),
productOut("vendor_debug_ramdisk"),
productOut("test_harness_ramdisk"),
productOut("recovery"),
diff --git a/ui/build/environment.go b/ui/build/environment.go
index 6d8a28f..50d059f 100644
--- a/ui/build/environment.go
+++ b/ui/build/environment.go
@@ -33,6 +33,19 @@
return &env
}
+// Returns a copy of the environment as a map[string]string.
+func (e *Environment) AsMap() map[string]string {
+ result := make(map[string]string)
+
+ for _, envVar := range *e {
+ if k, v, ok := decodeKeyValue(envVar); ok {
+ result[k] = v
+ }
+ }
+
+ return result
+}
+
// Get returns the value associated with the key, and whether it exists.
// It's equivalent to the os.LookupEnv function, but with this copy of the
// Environment.
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 125dbcc..fc43663 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -21,6 +21,7 @@
"strconv"
"android/soong/shared"
+
soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
"github.com/golang/protobuf/proto"
@@ -30,6 +31,15 @@
"android/soong/ui/status"
)
+func writeEnvironmentFile(ctx Context, envFile string, envDeps map[string]string) error {
+ data, err := shared.EnvFileContents(envDeps)
+ if err != nil {
+ return err
+ }
+
+ return ioutil.WriteFile(envFile, data, 0644)
+}
+
// This uses Android.bp files and various tools to generate <builddir>/build.ninja.
//
// However, the execution of <builddir>/build.ninja happens later in build/soong/ui/build/build.go#Build()
@@ -47,6 +57,12 @@
ctx.BeginTrace(metrics.RunSoong, "soong")
defer ctx.EndTrace()
+ // We have two environment files: .available is the one with every variable,
+ // .used with the ones that were actually used. The latter is used to
+ // determine whether Soong needs to be re-run since why re-run it if only
+ // unused variables were changed?
+ envFile := filepath.Join(config.SoongOutDir(), "soong.environment.available")
+
// Use an anonymous inline function for tracing purposes (this pattern is used several times below).
func() {
ctx.BeginTrace(metrics.RunSoong, "blueprint bootstrap")
@@ -61,6 +77,7 @@
}
cmd := Command(ctx, config, "blueprint bootstrap", "build/blueprint/bootstrap.bash", args...)
+
cmd.Environment.Set("BLUEPRINTDIR", "./build/blueprint")
cmd.Environment.Set("BOOTSTRAP", "./build/blueprint/bootstrap.bash")
cmd.Environment.Set("BUILDDIR", config.SoongOutDir())
@@ -74,11 +91,32 @@
cmd.RunAndPrintOrFatal()
}()
+ soongBuildEnv := config.Environment().Copy()
+ soongBuildEnv.Set("TOP", os.Getenv("TOP"))
+ // These two dependencies are read from bootstrap.go, but also need to be here
+ // so that soong_build can declare a dependency on them
+ soongBuildEnv.Set("SOONG_DELVE", os.Getenv("SOONG_DELVE"))
+ soongBuildEnv.Set("SOONG_DELVE_PATH", os.Getenv("SOONG_DELVE_PATH"))
+ soongBuildEnv.Set("SOONG_OUTDIR", config.SoongOutDir())
+ // For Bazel mixed builds.
+ soongBuildEnv.Set("BAZEL_PATH", "./tools/bazel")
+ soongBuildEnv.Set("BAZEL_HOME", filepath.Join(config.BazelOutDir(), "bazelhome"))
+ soongBuildEnv.Set("BAZEL_OUTPUT_BASE", filepath.Join(config.BazelOutDir(), "output"))
+ soongBuildEnv.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
+ soongBuildEnv.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())
+
+ if os.Getenv("SOONG_DELVE") != "" {
+ // SOONG_DELVE is already in cmd.Environment
+ soongBuildEnv.Set("SOONG_DELVE_PATH", shared.ResolveDelveBinary())
+ }
+
+ writeEnvironmentFile(ctx, envFile, soongBuildEnv.AsMap())
+
func() {
ctx.BeginTrace(metrics.RunSoong, "environment check")
defer ctx.EndTrace()
- envFile := filepath.Join(config.SoongOutDir(), ".soong.environment")
+ envFile := filepath.Join(config.SoongOutDir(), "soong.environment.used")
getenv := func(k string) string {
v, _ := config.Environment().Get(k)
return v
@@ -134,14 +172,7 @@
"--frontend_file", fifo,
"-f", filepath.Join(config.SoongOutDir(), file))
- // For Bazel mixed builds.
- cmd.Environment.Set("BAZEL_PATH", "./tools/bazel")
- cmd.Environment.Set("BAZEL_HOME", filepath.Join(config.BazelOutDir(), "bazelhome"))
- cmd.Environment.Set("BAZEL_OUTPUT_BASE", filepath.Join(config.BazelOutDir(), "output"))
- cmd.Environment.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
- cmd.Environment.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())
-
- cmd.Environment.Set("SOONG_SANDBOX_SOONG_BUILD", "true")
+ cmd.Environment.Set("SOONG_OUTDIR", config.SoongOutDir())
cmd.Sandbox = soongSandbox
cmd.RunAndStreamOrFatal()
}