Merge "Fix empty item handling in Split function, rewrite Words function"
diff --git a/android/mutator.go b/android/mutator.go
index 7a10477..31edea3 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -44,6 +44,11 @@
}
}
+func registerMutatorsForBazelConversion(ctx *blueprint.Context) {
+ // FIXME(b/171263886): Start bringing in mutators to make the Bionic
+ // module subgraph suitable for automated conversion.
+}
+
func registerMutators(ctx *blueprint.Context, preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc) {
mctx := ®isterMutatorsContext{}
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 294a6e0..98cb572 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -178,6 +178,9 @@
srcPropertyName := proptools.PropertyNameForField(srcField)
srcsSupplier := func(ctx BaseModuleContext) []string {
+ if !ctx.Module().Enabled() {
+ return nil
+ }
value := srcPropsValue.FieldByIndex(srcFieldIndex)
if value.Kind() == reflect.Ptr {
value = value.Elem()
diff --git a/android/queryview.go b/android/queryview.go
index 970ae01..1b7e77d 100644
--- a/android/queryview.go
+++ b/android/queryview.go
@@ -26,15 +26,40 @@
// for calling the soong_build primary builder in the main build.ninja file.
func init() {
RegisterSingletonType("bazel_queryview", BazelQueryViewSingleton)
+ RegisterSingletonType("bazel_converter", BazelConverterSingleton)
}
+// BazelQueryViewSingleton is the singleton responsible for registering the
+// soong_build build statement that will convert the Soong module graph after
+// applying *all* mutators, enabing the feature to query the final state of the
+// Soong graph. This mode is meant for querying the build graph state, and not meant
+// for generating BUILD files to be checked in.
func BazelQueryViewSingleton() Singleton {
return &bazelQueryViewSingleton{}
}
-type bazelQueryViewSingleton struct{}
+// BazelConverterSingleton is the singleton responsible for registering the soong_build
+// build statement that will convert the Soong module graph by applying an alternate
+// pipeline of mutators, with the goal of reaching semantic equivalence between the original
+// Blueprint and final BUILD files. Using this mode, the goal is to be able to
+// build with these BUILD files directly in the source tree.
+func BazelConverterSingleton() Singleton {
+ return &bazelConverterSingleton{}
+}
-func (c *bazelQueryViewSingleton) GenerateBuildActions(ctx SingletonContext) {
+type bazelQueryViewSingleton struct{}
+type bazelConverterSingleton struct{}
+
+func generateBuildActionsForBazelConversion(ctx SingletonContext, converterMode bool) {
+ name := "queryview"
+ additionalEnvVars := ""
+ descriptionTemplate := "[EXPERIMENTAL, PRE-PRODUCTION] Creating the Bazel QueryView workspace with %s at $outDir"
+ if converterMode {
+ name = "bp2build"
+ additionalEnvVars = "CONVERT_TO_BAZEL=true"
+ descriptionTemplate = "[EXPERIMENTAL, PRE-PRODUCTION] Converting all Android.bp to Bazel BUILD files with %s at $outDir"
+ }
+
// Create a build and rule statement, using the Bazel QueryView's WORKSPACE
// file as the output file marker.
var deps Paths
@@ -42,22 +67,23 @@
deps = append(deps, moduleListFilePath)
deps = append(deps, pathForBuildToolDep(ctx, ctx.Config().ProductVariablesFileName))
- bazelQueryViewDirectory := PathForOutput(ctx, "queryview")
+ bazelQueryViewDirectory := PathForOutput(ctx, name)
bazelQueryViewWorkspaceFile := bazelQueryViewDirectory.Join(ctx, "WORKSPACE")
primaryBuilder := primaryBuilderPath(ctx)
bazelQueryView := ctx.Rule(pctx, "bazelQueryView",
blueprint.RuleParams{
Command: fmt.Sprintf(
"rm -rf ${outDir}/* && "+
- "%s --bazel_queryview_dir ${outDir} %s && "+
+ "%s %s --bazel_queryview_dir ${outDir} %s && "+
"echo WORKSPACE: `cat %s` > ${outDir}/.queryview-depfile.d",
+ additionalEnvVars,
primaryBuilder.String(),
strings.Join(os.Args[1:], " "),
moduleListFilePath.String(), // Use the contents of Android.bp.list as the depfile.
),
CommandDeps: []string{primaryBuilder.String()},
Description: fmt.Sprintf(
- "[EXPERIMENTAL, PRE-PRODUCTION] Creating the Bazel QueryView workspace with %s at $outDir",
+ descriptionTemplate,
primaryBuilder.Base()),
Deps: blueprint.DepsGCC,
Depfile: "${outDir}/.queryview-depfile.d",
@@ -73,6 +99,14 @@
},
})
- // Add a phony target for building the Bazel QueryView
- ctx.Phony("queryview", bazelQueryViewWorkspaceFile)
+ // Add a phony target for generating the workspace
+ ctx.Phony(name, bazelQueryViewWorkspaceFile)
+}
+
+func (c *bazelQueryViewSingleton) GenerateBuildActions(ctx SingletonContext) {
+ generateBuildActionsForBazelConversion(ctx, false)
+}
+
+func (c *bazelConverterSingleton) GenerateBuildActions(ctx SingletonContext) {
+ generateBuildActionsForBazelConversion(ctx, true)
}
diff --git a/android/register.go b/android/register.go
index 08e47b3..b26f9b9 100644
--- a/android/register.go
+++ b/android/register.go
@@ -90,6 +90,21 @@
return ctx
}
+// RegisterForBazelConversion registers an alternate shadow pipeline of
+// singletons, module types and mutators to register for converting Blueprint
+// files to semantically equivalent BUILD files.
+func (ctx *Context) RegisterForBazelConversion() {
+ for _, t := range moduleTypes {
+ ctx.RegisterModuleType(t.name, ModuleFactoryAdaptor(t.factory))
+ }
+
+ bazelConverterSingleton := singleton{"bp2build", BazelConverterSingleton}
+ ctx.RegisterSingletonType(bazelConverterSingleton.name,
+ SingletonFactoryAdaptor(ctx, bazelConverterSingleton.factory))
+
+ registerMutatorsForBazelConversion(ctx.Context)
+}
+
func (ctx *Context) Register() {
for _, t := range preSingletons {
ctx.RegisterPreSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index d758de2..907bed3 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -51,10 +51,22 @@
return android.NewNameResolver(exportFilter)
}
+// bazelConversionRequested checks that the user is intending to convert
+// Blueprint to Bazel BUILD files.
+func bazelConversionRequested(configuration android.Config) bool {
+ return configuration.IsEnvTrue("CONVERT_TO_BAZEL")
+}
+
func newContext(srcDir string, configuration android.Config) *android.Context {
ctx := android.NewContext(configuration)
- ctx.Register()
- if !shouldPrepareBuildActions() {
+ if bazelConversionRequested(configuration) {
+ // Register an alternate set of singletons and mutators for bazel
+ // conversion for Bazel conversion.
+ ctx.RegisterForBazelConversion()
+ } else {
+ ctx.Register()
+ }
+ if !shouldPrepareBuildActions(configuration) {
configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions)
}
ctx.SetNameInterface(newNameResolver(configuration))
@@ -114,6 +126,8 @@
ctx = newContext(srcDir, configuration)
bootstrap.Main(ctx.Context, configuration, extraNinjaDeps...)
}
+
+ // Convert the Soong module graph into Bazel BUILD files.
if bazelQueryViewDir != "" {
if err := createBazelQueryView(ctx, bazelQueryViewDir); err != nil {
fmt.Fprintf(os.Stderr, "%s", err)
@@ -130,7 +144,7 @@
// TODO(ccross): make this a command line argument. Requires plumbing through blueprint
// to affect the command line of the primary builder.
- if shouldPrepareBuildActions() {
+ if shouldPrepareBuildActions(configuration) {
metricsFile := filepath.Join(bootstrap.BuildDir, "soong_build_metrics.pb")
err := android.WriteMetrics(configuration, metricsFile)
if err != nil {
@@ -140,8 +154,19 @@
}
}
-func shouldPrepareBuildActions() bool {
- // If we're writing soong_docs or queryview, don't write build.ninja or
- // collect metrics.
- return docFile == "" && bazelQueryViewDir == ""
+// shouldPrepareBuildActions reads configuration and flags if build actions
+// should be generated.
+func shouldPrepareBuildActions(configuration android.Config) bool {
+ // Generating Soong docs
+ if docFile != "" {
+ return false
+ }
+
+ // Generating a directory for Soong query (queryview)
+ if bazelQueryViewDir != "" {
+ return false
+ }
+
+ // Generating a directory for converted Bazel BUILD files
+ return !bazelConversionRequested(configuration)
}
diff --git a/cmd/soong_build/writedocs.go b/cmd/soong_build/writedocs.go
index 5fb6e6b..253979e 100644
--- a/cmd/soong_build/writedocs.go
+++ b/cmd/soong_build/writedocs.go
@@ -44,9 +44,10 @@
"name": 0,
"src": 1,
"srcs": 2,
- "defaults": 3,
- "host_supported": 4,
- "device_supported": 5,
+ "exclude_srcs": 3,
+ "defaults": 4,
+ "host_supported": 5,
+ "device_supported": 6,
}
// For each module type, extract its documentation and convert it to the template data.
diff --git a/dexpreopt/class_loader_context.go b/dexpreopt/class_loader_context.go
index 3759217..deaf77f 100644
--- a/dexpreopt/class_loader_context.go
+++ b/dexpreopt/class_loader_context.go
@@ -437,7 +437,11 @@
if sdkVer == AnySdkVersion {
// Return error if dexpreopt doesn't know paths to one of the <uses-library>
// dependencies. In the future we may need to relax this and just disable dexpreopt.
- return false, fmt.Errorf("invalid path for <uses-library> \"%s\"", clc.Name)
+ if clc.Host == nil {
+ return false, fmt.Errorf("invalid build path for <uses-library> \"%s\"", clc.Name)
+ } else {
+ return false, fmt.Errorf("invalid install path for <uses-library> \"%s\"", clc.Name)
+ }
} else {
// No error for compatibility libraries, as Soong doesn't know if they are needed
// (this depends on the targetSdkVersion in the manifest), but the CLC is invalid.
diff --git a/dexpreopt/class_loader_context_test.go b/dexpreopt/class_loader_context_test.go
index df68563..be7d4c6 100644
--- a/dexpreopt/class_loader_context_test.go
+++ b/dexpreopt/class_loader_context_test.go
@@ -195,7 +195,7 @@
// But class loader context in such cases should raise an error on validation.
t.Run("validate", func(t *testing.T) {
_, err := validateClassLoaderContext(m)
- checkError(t, err, "invalid path for <uses-library> \"a\"")
+ checkError(t, err, "invalid build path for <uses-library> \"a\"")
})
}
diff --git a/java/aar.go b/java/aar.go
index 1940d7f..3b6b34e 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -407,6 +407,7 @@
ctx.VisitDirectDeps(func(module android.Module) {
depName := ctx.OtherModuleName(module)
+ depTag := ctx.OtherModuleDependencyTag(module)
var exportPackage android.Path
aarDep, _ := module.(AndroidLibraryDependency)
@@ -414,7 +415,7 @@
exportPackage = aarDep.ExportPackage()
}
- switch ctx.OtherModuleDependencyTag(module) {
+ switch depTag {
case instrumentationForTag:
// Nothing, instrumentationForTag is treated as libTag for javac but not for aapt2.
case libTag:
@@ -439,7 +440,6 @@
transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...)
transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...)
- classLoaderContexts.AddContextMap(aarDep.ClassLoaderContexts(), depName)
if aarDep.ExportedAssets().Valid() {
assets = append(assets, aarDep.ExportedAssets().Path())
}
@@ -458,11 +458,8 @@
}
}
- // Add nested dependencies after processing the direct dependency: if it is a <uses-library>,
- // nested context is added as its subcontext, and should not be re-added at the top-level.
- if dep, ok := module.(Dependency); ok {
- classLoaderContexts.AddContextMap(dep.ClassLoaderContexts(), depName)
- }
+ // Merge dep's CLC after processing the dep itself (which may add its own <uses-library>).
+ maybeAddCLCFromDep(module, depTag, depName, classLoaderContexts)
})
deps = append(deps, sharedLibs...)
diff --git a/java/app.go b/java/app.go
index 4bf9d33..e6d9550 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1400,6 +1400,13 @@
archProps := reflect.ValueOf(a.archVariants).Elem().FieldByName("Arch")
archType := ctx.Config().AndroidFirstDeviceTarget.Arch.ArchType
MergePropertiesFromVariant(ctx, &a.properties, archProps, archType.Name)
+
+ if String(a.properties.Apk) == "" {
+ // Disable this module since the apk property is still empty after processing all matching
+ // variants. This likely means there is no matching variant, and the default variant doesn't
+ // have an apk property value either.
+ a.Disable()
+ }
}
func MergePropertiesFromVariant(ctx android.EarlyModuleContext,
diff --git a/java/app_test.go b/java/app_test.go
index 6efb0dc..ef5e84d 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -2524,6 +2524,24 @@
`,
expected: "prebuilts/apk/app.apk",
},
+ {
+ name: "no matching arch without default",
+ bp: `
+ android_app_import {
+ name: "foo",
+ arch: {
+ arm: {
+ apk: "prebuilts/apk/app_arm.apk",
+ },
+ },
+ presigned: true,
+ dex_preopt: {
+ enabled: true,
+ },
+ }
+ `,
+ expected: "",
+ },
}
jniRuleRe := regexp.MustCompile("^if \\(zipinfo (\\S+)")
@@ -2531,6 +2549,12 @@
ctx, _ := testJava(t, test.bp)
variant := ctx.ModuleForTests("foo", "android_common")
+ if test.expected == "" {
+ if variant.Module().Enabled() {
+ t.Error("module should have been disabled, but wasn't")
+ }
+ continue
+ }
jniRuleCommand := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command
matches := jniRuleRe.FindStringSubmatch(jniRuleCommand)
if len(matches) != 2 {
@@ -2730,6 +2754,13 @@
}
java_sdk_library {
+ name: "fred",
+ srcs: ["a.java"],
+ api_packages: ["fred"],
+ sdk_version: "current",
+ }
+
+ java_sdk_library {
name: "bar",
srcs: ["a.java"],
api_packages: ["bar"],
@@ -2753,7 +2784,12 @@
name: "app",
srcs: ["a.java"],
libs: ["qux", "quuz.stubs"],
- static_libs: ["static-runtime-helper"],
+ static_libs: [
+ "static-runtime-helper",
+ // statically linked component libraries should not pull their SDK libraries,
+ // so "fred" should not be added to class loader context
+ "fred.stubs",
+ ],
uses_libs: ["foo"],
sdk_version: "current",
optional_uses_libs: [
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index f16ddf1..da7f291 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -506,7 +506,7 @@
m := image.modules.Jar(i)
if ctx.Config().AllowMissingDependencies() {
missingDeps = append(missingDeps, m)
- bootDexJars[i] = android.PathForOutput(ctx, "missing")
+ bootDexJars[i] = android.PathForOutput(ctx, "missing/module", m, "from/apex", image.modules.Apex(i))
} else {
ctx.Errorf("failed to find a dex jar path for module '%s'"+
", note that some jars may be filtered out by module constraints", m)
@@ -779,7 +779,7 @@
bootFrameworkProfile = path.Path()
} else {
missingDeps = append(missingDeps, defaultProfile)
- bootFrameworkProfile = android.PathForOutput(ctx, "missing")
+ bootFrameworkProfile = android.PathForOutput(ctx, "missing", defaultProfile)
}
profile := image.dir.Join(ctx, "boot.bprof")
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index ce8410e..419dc34 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -177,12 +177,13 @@
for moduleList, pathList := range moduleListToPathList {
for i := range pathList {
if pathList[i] == nil {
- pathList[i] = android.PathForOutput(ctx, "missing")
+ moduleName := (*moduleList)[i]
+ pathList[i] = android.PathForOutput(ctx, "missing/module", moduleName)
if ctx.Config().AllowMissingDependencies() {
- missingDeps = append(missingDeps, (*moduleList)[i])
+ missingDeps = append(missingDeps, moduleName)
} else {
ctx.Errorf("failed to find dex jar path for module %q",
- (*moduleList)[i])
+ moduleName)
}
}
}
diff --git a/java/java.go b/java/java.go
index 3d121cc..d44719e 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1081,7 +1081,6 @@
switch tag {
case libTag:
deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
- // names of sdk libs that are directly depended are exported
j.classLoaderContexts.MaybeAddContext(ctx, dep.OptionalImplicitSdkLibrary(),
dep.DexJarBuildPath(), dep.DexJarInstallPath())
case staticLibTag:
@@ -1093,7 +1092,6 @@
deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars()...)
case libTag, instrumentationForTag:
deps.classpath = append(deps.classpath, dep.HeaderJars()...)
- // sdk lib names from dependencies are re-exported
j.classLoaderContexts.AddContextMap(dep.ClassLoaderContexts(), otherName)
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
pluginJars, pluginClasses, disableTurbine := dep.ExportedPlugins()
@@ -1106,8 +1104,6 @@
deps.staticJars = append(deps.staticJars, dep.ImplementationJars()...)
deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars()...)
deps.staticResourceJars = append(deps.staticResourceJars, dep.ResourceJars()...)
- // sdk lib names from dependencies are re-exported
- j.classLoaderContexts.AddContextMap(dep.ClassLoaderContexts(), otherName)
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
pluginJars, pluginClasses, disableTurbine := dep.ExportedPlugins()
addPlugins(&deps, pluginJars, pluginClasses...)
@@ -1182,6 +1178,9 @@
deps.systemModules = &systemModules{outputDir, outputDeps}
}
}
+
+ // Merge dep's CLC after processing the dep itself (which may add its own <uses-library>).
+ maybeAddCLCFromDep(module, tag, otherName, j.classLoaderContexts)
})
return deps
@@ -2815,8 +2814,6 @@
switch tag {
case libTag, staticLibTag:
flags.classpath = append(flags.classpath, dep.HeaderJars()...)
- // sdk lib names from dependencies are re-exported
- j.classLoaderContexts.AddContextMap(dep.ClassLoaderContexts(), otherName)
case bootClasspathTag:
flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars()...)
}
@@ -2824,10 +2821,12 @@
switch tag {
case libTag:
flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
- // names of sdk libs that are directly depended are exported
j.classLoaderContexts.AddContext(ctx, otherName, dep.DexJarBuildPath(), dep.DexJarInstallPath())
}
}
+
+ // Merge dep's CLC after processing the dep itself (which may add its own <uses-library>).
+ maybeAddCLCFromDep(module, tag, otherName, j.classLoaderContexts)
})
var installFile android.Path
@@ -3248,3 +3247,31 @@
var BoolDefault = proptools.BoolDefault
var String = proptools.String
var inList = android.InList
+
+// Add class loader context of a given dependency to the given class loader context, provided that
+// all the necessary conditions are met.
+func maybeAddCLCFromDep(depModule android.Module, depTag blueprint.DependencyTag,
+ depName string, clcMap dexpreopt.ClassLoaderContextMap) {
+
+ if dep, ok := depModule.(Dependency); ok {
+ if depTag == libTag {
+ // Ok, propagate <uses-library> through non-static library dependencies.
+ } else if depTag == staticLibTag {
+ // Propagate <uses-library> through static library dependencies, unless it is a
+ // component library (such as stubs). Component libraries have a dependency on their
+ // SDK library, which should not be pulled just because of a static component library.
+ if comp, isComp := depModule.(SdkLibraryComponentDependency); isComp {
+ if compName := comp.OptionalImplicitSdkLibrary(); compName != nil {
+ dep = nil
+ }
+ }
+ } else {
+ // Don't propagate <uses-library> for other dependency tags.
+ dep = nil
+ }
+
+ if dep != nil {
+ clcMap.AddContextMap(dep.ClassLoaderContexts(), depName)
+ }
+ }
+}
diff --git a/ui/build/bazel.go b/ui/build/bazel.go
index fac0461..23b14ee 100644
--- a/ui/build/bazel.go
+++ b/ui/build/bazel.go
@@ -15,6 +15,8 @@
package build
import (
+ "bytes"
+ "fmt"
"io/ioutil"
"os"
"path/filepath"
@@ -24,7 +26,7 @@
"android/soong/ui/metrics"
)
-func getBazelInfo(ctx Context, config Config, bazelExecutable string, query string) string {
+func getBazelInfo(ctx Context, config Config, bazelExecutable string, bazelEnv map[string]string, query string) string {
infoCmd := Command(ctx, config, "bazel", bazelExecutable)
if extraStartupArgs, ok := infoCmd.Environment.Get("BAZEL_STARTUP_ARGS"); ok {
@@ -37,8 +39,9 @@
query,
)
- infoCmd.Environment.Set("DIST_DIR", config.DistDir())
- infoCmd.Environment.Set("SHELL", "/bin/bash")
+ for k, v := range bazelEnv {
+ infoCmd.Environment.Set(k, v)
+ }
infoCmd.Dir = filepath.Join(config.OutDir(), "..")
@@ -65,14 +68,18 @@
// Environment variables are the primary mechanism to pass information from
// soong_ui configuration or context to Bazel.
- //
+ bazelEnv := make(map[string]string)
+
// Use *_NINJA variables to pass the root-relative path of the combined,
// kati-generated, soong-generated, and packaging Ninja files to Bazel.
// Bazel reads these from the lunch() repository rule.
- config.environ.Set("COMBINED_NINJA", config.CombinedNinjaFile())
- config.environ.Set("KATI_NINJA", config.KatiBuildNinjaFile())
- config.environ.Set("PACKAGE_NINJA", config.KatiPackageNinjaFile())
- config.environ.Set("SOONG_NINJA", config.SoongNinjaFile())
+ bazelEnv["COMBINED_NINJA"] = config.CombinedNinjaFile()
+ bazelEnv["KATI_NINJA"] = config.KatiBuildNinjaFile()
+ bazelEnv["PACKAGE_NINJA"] = config.KatiPackageNinjaFile()
+ bazelEnv["SOONG_NINJA"] = config.SoongNinjaFile()
+
+ bazelEnv["DIST_DIR"] = config.DistDir()
+ bazelEnv["SHELL"] = "/bin/bash"
// `tools/bazel` is the default entry point for executing Bazel in the AOSP
// source tree.
@@ -126,7 +133,7 @@
// We need to calculate --RBE_exec_root ourselves
ctx.Println("Getting Bazel execution_root...")
- cmd.Args = append(cmd.Args, "--action_env=RBE_exec_root="+getBazelInfo(ctx, config, bazelExecutable, "execution_root"))
+ cmd.Args = append(cmd.Args, "--action_env=RBE_exec_root="+getBazelInfo(ctx, config, bazelExecutable, bazelEnv, "execution_root"))
}
// Ensure that the PATH environment variable value used in the action
@@ -149,15 +156,21 @@
"//:"+config.TargetProduct()+"-"+config.TargetBuildVariant(),
)
- cmd.Environment.Set("DIST_DIR", config.DistDir())
- cmd.Environment.Set("SHELL", "/bin/bash")
-
- // Print the full command line for debugging purposes.
- ctx.Println(cmd.Cmd)
-
// Execute the command at the root of the directory.
cmd.Dir = filepath.Join(config.OutDir(), "..")
- ctx.Status.Status("Starting Bazel..")
+
+ for k, v := range bazelEnv {
+ cmd.Environment.Set(k, v)
+ }
+
+ // Make a human-readable version of the bazelEnv map
+ bazelEnvStringBuffer := new(bytes.Buffer)
+ for k, v := range bazelEnv {
+ fmt.Fprintf(bazelEnvStringBuffer, "%s=%s ", k, v)
+ }
+
+ // Print the full command line (including environment variables) for debugging purposes.
+ ctx.Println("Bazel command line: " + bazelEnvStringBuffer.String() + cmd.Cmd.String() + "\n")
// Execute the build command.
cmd.RunAndStreamOrFatal()
@@ -168,11 +181,12 @@
// the files from the execution root's output direction into $OUT_DIR.
ctx.Println("Getting Bazel output_path...")
- outputBasePath := getBazelInfo(ctx, config, bazelExecutable, "output_path")
+ outputBasePath := getBazelInfo(ctx, config, bazelExecutable, bazelEnv, "output_path")
// TODO: Don't hardcode out/ as the bazel output directory. This is
// currently hardcoded as ninja_build.output_root.
bazelNinjaBuildOutputRoot := filepath.Join(outputBasePath, "..", "out")
+ ctx.Println("Creating output symlinks..")
symlinkOutdir(ctx, config, bazelNinjaBuildOutputRoot, ".")
}
@@ -185,27 +199,39 @@
if err != nil {
ctx.Fatal(err)
}
+
for _, f := range files {
+ // The original Bazel file path
destPath := filepath.Join(destDir, f.Name())
+
+ // The desired Soong file path
srcPath := filepath.Join(config.OutDir(), relativePath, f.Name())
- if statResult, err := os.Stat(srcPath); err == nil {
- if statResult.Mode().IsDir() && f.IsDir() {
- // Directory under OutDir already exists, so recurse on its contents.
+
+ destLstatResult, destLstatErr := os.Lstat(destPath)
+ if destLstatErr != nil {
+ ctx.Fatalf("Unable to Lstat dest %s: %s", destPath, destLstatErr)
+ }
+
+ srcLstatResult, srcLstatErr := os.Lstat(srcPath)
+
+ if srcLstatErr == nil {
+ if srcLstatResult.IsDir() && destLstatResult.IsDir() {
+ // src and dest are both existing dirs - recurse on the dest dir contents...
symlinkOutdir(ctx, config, rootPath, filepath.Join(relativePath, f.Name()))
- } else if !statResult.Mode().IsDir() && !f.IsDir() {
- // File exists both in source and destination, and it's not a directory
- // in either location. Do nothing.
- // This can arise for files which are generated under OutDir outside of
- // soong_build, such as .bootstrap files.
} else {
- // File is a directory in one location but not the other. Raise an error.
- ctx.Fatalf("Could not link %s to %s due to conflict", srcPath, destPath)
+ // Ignore other pre-existing src files (could be pre-existing files, directories, symlinks, ...)
+ // This can arise for files which are generated under OutDir outside of soong_build, such as .bootstrap files.
+ // FIXME: This might cause a problem later e.g. if a symlink in the build graph changes...
}
- } else if os.IsNotExist(err) {
- // Create symlink srcPath -> fullDestPath.
- os.Symlink(destPath, srcPath)
} else {
- ctx.Fatalf("Unable to stat %s: %s", srcPath, err)
+ if !os.IsNotExist(srcLstatErr) {
+ ctx.Fatalf("Unable to Lstat src %s: %s", srcPath, srcLstatErr)
+ }
+
+ // src does not exist, so try to create a src -> dest symlink (i.e. a Soong path -> Bazel path symlink)
+ if symlinkErr := os.Symlink(destPath, srcPath); symlinkErr != nil {
+ ctx.Fatalf("Unable to create symlink %s -> %s due to error %s", srcPath, destPath, symlinkErr)
+ }
}
}
}
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index ffd1ab9..7799766 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -139,15 +139,6 @@
// b/147197813 - used by art-check-debug-apex-gen
"EMMA_INSTRUMENT_FRAMEWORK",
- // Goma -- gomacc may not need all of these
- "GOMA_DIR",
- "GOMA_DISABLED",
- "GOMA_FAIL_FAST",
- "GOMA_FALLBACK",
- "GOMA_GCE_SERVICE_ACCOUNT",
- "GOMA_TMP_DIR",
- "GOMA_USE_LOCAL",
-
// RBE client
"RBE_compare",
"RBE_exec_root",