Merge "Allow stripping host modules"
diff --git a/apex/apex.go b/apex/apex.go
index 72f3db1..7ab7454 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1666,7 +1666,7 @@
// system libraries.
if !am.DirectlyInAnyApex() {
// we need a module name for Make
- name := cc.ImplementationModuleName(ctx)
+ name := cc.ImplementationModuleNameForMake(ctx)
if !proptools.Bool(a.properties.Use_vendor) {
// we don't use subName(.vendor) for a "use_vendor: true" apex
diff --git a/apex/apex_test.go b/apex/apex_test.go
index cc05fd4..0b67ef5 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -6186,6 +6186,57 @@
`)
}
+func TestPreferredPrebuiltSharedLibDep(t *testing.T) {
+ ctx, config := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ apex_available: ["myapex"],
+ shared_libs: ["otherlib"],
+ system_shared_libs: [],
+ }
+
+ cc_library {
+ name: "otherlib",
+ srcs: ["mylib.cpp"],
+ stubs: {
+ versions: ["current"],
+ },
+ }
+
+ cc_prebuilt_library_shared {
+ name: "otherlib",
+ prefer: true,
+ srcs: ["prebuilt.so"],
+ stubs: {
+ versions: ["current"],
+ },
+ }
+ `)
+
+ ab := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
+ data := android.AndroidMkDataForTest(t, config, "", ab)
+ var builder strings.Builder
+ data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
+ androidMk := builder.String()
+
+ // The make level dependency needs to be on otherlib - prebuilt_otherlib isn't
+ // a thing there.
+ ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES += otherlib\n")
+}
+
func TestMain(m *testing.M) {
run := func() int {
setUp()
diff --git a/cc/builder.go b/cc/builder.go
index 439e372..5545a5b 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -568,8 +568,11 @@
ccCmd = "clang++"
moduleFlags = cppflags
moduleToolingFlags = toolingCppflags
+ case ".h", ".hpp":
+ ctx.PropertyErrorf("srcs", "Header file %s is not supported, instead use export_include_dirs or local_include_dirs.", srcFile)
+ continue
default:
- ctx.ModuleErrorf("File %s has unknown extension", srcFile)
+ ctx.PropertyErrorf("srcs", "File %s has unknown extension. Supported extensions: .s, .S, .c, .cpp, .cc, .cxx, .mm", srcFile)
continue
}
diff --git a/cc/cc.go b/cc/cc.go
index f62df3c..b1c1264 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1099,6 +1099,19 @@
return name
}
+// Similar to ImplementationModuleName, but uses the Make variant of the module
+// name as base name, for use in AndroidMk output. E.g. for a prebuilt module
+// where the Soong name is prebuilt_foo, this returns foo (which works in Make
+// under the premise that the prebuilt module overrides its source counterpart
+// if it is exposed to Make).
+func (c *Module) ImplementationModuleNameForMake(ctx android.BaseModuleContext) string {
+ name := c.BaseModuleName()
+ if versioned, ok := c.linker.(versionedInterface); ok {
+ name = versioned.implementationModuleName(name)
+ }
+ return name
+}
+
func (c *Module) bootstrap() bool {
return Bool(c.Properties.Bootstrap)
}
diff --git a/rust/project_json.go b/rust/project_json.go
index 8d9e50c..c4d60ad 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -75,12 +75,16 @@
android.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton)
}
-// librarySource finds the main source file (.rs) for a crate.
-func librarySource(ctx android.SingletonContext, rModule *Module, rustLib *libraryDecorator) (string, bool) {
- srcs := rustLib.baseCompiler.Properties.Srcs
+// crateSource finds the main source file (.rs) for a crate.
+func crateSource(ctx android.SingletonContext, rModule *Module, comp *baseCompiler) (string, bool) {
+ srcs := comp.Properties.Srcs
if len(srcs) != 0 {
return path.Join(ctx.ModuleDir(rModule), srcs[0]), true
}
+ rustLib, ok := rModule.compiler.(*libraryDecorator)
+ if !ok {
+ return "", false
+ }
if !rustLib.source() {
return "", false
}
@@ -132,8 +136,15 @@
if rModule.compiler == nil {
return 0, "", false
}
- rustLib, ok := rModule.compiler.(*libraryDecorator)
- if !ok {
+ var comp *baseCompiler
+ switch c := rModule.compiler.(type) {
+ case *libraryDecorator:
+ comp = c.baseCompiler
+ case *binaryDecorator:
+ comp = c.baseCompiler
+ case *testDecorator:
+ comp = c.binaryDecorator.baseCompiler
+ default:
return 0, "", false
}
moduleName := ctx.ModuleName(module)
@@ -146,12 +157,12 @@
return cInfo.ID, crateName, true
}
crate := rustProjectCrate{Deps: make([]rustProjectDep, 0), Cfgs: make([]string, 0)}
- rootModule, ok := librarySource(ctx, rModule, rustLib)
+ rootModule, ok := crateSource(ctx, rModule, comp)
if !ok {
return 0, "", false
}
crate.RootModule = rootModule
- crate.Edition = rustLib.baseCompiler.edition()
+ crate.Edition = comp.edition()
deps := make(map[string]int)
singleton.mergeDependencies(ctx, module, &crate, deps)
diff --git a/rust/project_json_test.go b/rust/project_json_test.go
index 16699c1..aff1697 100644
--- a/rust/project_json_test.go
+++ b/rust/project_json_test.go
@@ -67,6 +67,37 @@
return crates
}
+// validateCrate ensures that a crate can be parsed as a map.
+func validateCrate(t *testing.T, crate interface{}) map[string]interface{} {
+ c, ok := crate.(map[string]interface{})
+ if !ok {
+ t.Fatalf("Unexpected type for crate: %v", c)
+ }
+ return c
+}
+
+// validateDependencies parses the dependencies for a crate. It returns a list
+// of the dependencies name.
+func validateDependencies(t *testing.T, crate map[string]interface{}) []string {
+ var dependencies []string
+ deps, ok := crate["deps"].([]interface{})
+ if !ok {
+ t.Errorf("Unexpected format for deps: %v", crate["deps"])
+ }
+ for _, dep := range deps {
+ d, ok := dep.(map[string]interface{})
+ if !ok {
+ t.Errorf("Unexpected format for dependency: %v", dep)
+ }
+ name, ok := d["name"].(string)
+ if !ok {
+ t.Errorf("Dependency is missing the name key: %v", d)
+ }
+ dependencies = append(dependencies, name)
+ }
+ return dependencies
+}
+
func TestProjectJsonDep(t *testing.T) {
bp := `
rust_library {
@@ -85,6 +116,29 @@
validateJsonCrates(t, jsonContent)
}
+func TestProjectJsonBinary(t *testing.T) {
+ bp := `
+ rust_binary {
+ name: "liba",
+ srcs: ["a/src/lib.rs"],
+ crate_name: "a"
+ }
+ `
+ jsonContent := testProjectJson(t, bp)
+ crates := validateJsonCrates(t, jsonContent)
+ for _, c := range crates {
+ crate := validateCrate(t, c)
+ rootModule, ok := crate["root_module"].(string)
+ if !ok {
+ t.Fatalf("Unexpected type for root_module: %v", crate["root_module"])
+ }
+ if rootModule == "a/src/lib.rs" {
+ return
+ }
+ }
+ t.Errorf("Entry for binary %q not found: %s", "a", jsonContent)
+}
+
func TestProjectJsonBindGen(t *testing.T) {
bp := `
rust_library {
@@ -116,10 +170,7 @@
jsonContent := testProjectJson(t, bp)
crates := validateJsonCrates(t, jsonContent)
for _, c := range crates {
- crate, ok := c.(map[string]interface{})
- if !ok {
- t.Fatalf("Unexpected type for crate: %v", c)
- }
+ crate := validateCrate(t, c)
rootModule, ok := crate["root_module"].(string)
if !ok {
t.Fatalf("Unexpected type for root_module: %v", crate["root_module"])
@@ -133,16 +184,8 @@
}
// Check that libbindings1 does not depend on itself.
if strings.Contains(rootModule, "libbindings1") {
- deps, ok := crate["deps"].([]interface{})
- if !ok {
- t.Errorf("Unexpected format for deps: %v", crate["deps"])
- }
- for _, dep := range deps {
- d, ok := dep.(map[string]interface{})
- if !ok {
- t.Errorf("Unexpected format for dep: %v", dep)
- }
- if d["name"] == "bindings1" {
+ for _, depName := range validateDependencies(t, crate) {
+ if depName == "bindings1" {
t.Errorf("libbindings1 depends on itself")
}
}
@@ -171,20 +214,18 @@
`
jsonContent := testProjectJson(t, bp)
crates := validateJsonCrates(t, jsonContent)
- for _, crate := range crates {
- c := crate.(map[string]interface{})
- if c["root_module"] == "b/src/lib.rs" {
- deps, ok := c["deps"].([]interface{})
- if !ok {
- t.Errorf("Unexpected format for deps: %v", c["deps"])
- }
+ for _, c := range crates {
+ crate := validateCrate(t, c)
+ rootModule, ok := crate["root_module"].(string)
+ if !ok {
+ t.Fatalf("Unexpected type for root_module: %v", crate["root_module"])
+ }
+ // Make sure that b has 2 different dependencies.
+ if rootModule == "b/src/lib.rs" {
aCount := 0
- for _, dep := range deps {
- d, ok := dep.(map[string]interface{})
- if !ok {
- t.Errorf("Unexpected format for dep: %v", dep)
- }
- if d["name"] == "a" {
+ deps := validateDependencies(t, crate)
+ for _, depName := range deps {
+ if depName == "a" {
aCount++
}
}
diff --git a/ui/build/bazel.go b/ui/build/bazel.go
index 2d36f67..fac0461 100644
--- a/ui/build/bazel.go
+++ b/ui/build/bazel.go
@@ -24,6 +24,28 @@
"android/soong/ui/metrics"
)
+func getBazelInfo(ctx Context, config Config, bazelExecutable string, query string) string {
+ infoCmd := Command(ctx, config, "bazel", bazelExecutable)
+
+ if extraStartupArgs, ok := infoCmd.Environment.Get("BAZEL_STARTUP_ARGS"); ok {
+ infoCmd.Args = append(infoCmd.Args, strings.Fields(extraStartupArgs)...)
+ }
+
+ // Obtain the output directory path in the execution root.
+ infoCmd.Args = append(infoCmd.Args,
+ "info",
+ query,
+ )
+
+ infoCmd.Environment.Set("DIST_DIR", config.DistDir())
+ infoCmd.Environment.Set("SHELL", "/bin/bash")
+
+ infoCmd.Dir = filepath.Join(config.OutDir(), "..")
+
+ queryResult := strings.TrimSpace(string(infoCmd.OutputOrFatal()))
+ return queryResult
+}
+
// Main entry point to construct the Bazel build command line, environment
// variables and post-processing steps (e.g. converge output directories)
func runBazel(ctx Context, config Config) {
@@ -76,16 +98,36 @@
"--slim_profile=true",
)
- // Append custom build flags to the Bazel command. Changes to these flags
- // may invalidate Bazel's analysis cache.
- if extraBuildArgs, ok := cmd.Environment.Get("BAZEL_BUILD_ARGS"); ok {
- cmd.Args = append(cmd.Args, strings.Fields(extraBuildArgs)...)
- }
+ if config.UseRBE() {
+ for _, envVar := range []string{
+ // RBE client
+ "RBE_compare",
+ "RBE_exec_strategy",
+ "RBE_invocation_id",
+ "RBE_log_dir",
+ "RBE_platform",
+ "RBE_remote_accept_cache",
+ "RBE_remote_update_cache",
+ "RBE_server_address",
+ // TODO: remove old FLAG_ variables.
+ "FLAG_compare",
+ "FLAG_exec_root",
+ "FLAG_exec_strategy",
+ "FLAG_invocation_id",
+ "FLAG_log_dir",
+ "FLAG_platform",
+ "FLAG_remote_accept_cache",
+ "FLAG_remote_update_cache",
+ "FLAG_server_address",
+ } {
+ cmd.Args = append(cmd.Args,
+ "--action_env="+envVar)
+ }
- // Append the label of the default ninja_build target.
- cmd.Args = append(cmd.Args,
- "//:"+config.TargetProduct()+"-"+config.TargetBuildVariant(),
- )
+ // 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"))
+ }
// Ensure that the PATH environment variable value used in the action
// environment is the restricted set computed from soong_ui, and not a
@@ -95,6 +137,18 @@
cmd.Args = append(cmd.Args, "--action_env=PATH="+pathEnvValue)
}
+ // Append custom build flags to the Bazel command. Changes to these flags
+ // may invalidate Bazel's analysis cache.
+ // These should be appended as the final args, so that they take precedence.
+ if extraBuildArgs, ok := cmd.Environment.Get("BAZEL_BUILD_ARGS"); ok {
+ cmd.Args = append(cmd.Args, strings.Fields(extraBuildArgs)...)
+ }
+
+ // Append the label of the default ninja_build target.
+ cmd.Args = append(cmd.Args,
+ "//:"+config.TargetProduct()+"-"+config.TargetBuildVariant(),
+ )
+
cmd.Environment.Set("DIST_DIR", config.DistDir())
cmd.Environment.Set("SHELL", "/bin/bash")
@@ -113,24 +167,8 @@
// Ensure that the $OUT_DIR contains the expected set of files by symlinking
// the files from the execution root's output direction into $OUT_DIR.
- // Obtain the Bazel output directory for ninja_build.
- infoCmd := Command(ctx, config, "bazel", bazelExecutable)
-
- if extraStartupArgs, ok := infoCmd.Environment.Get("BAZEL_STARTUP_ARGS"); ok {
- infoCmd.Args = append(infoCmd.Args, strings.Fields(extraStartupArgs)...)
- }
-
- // Obtain the output directory path in the execution root.
- infoCmd.Args = append(infoCmd.Args,
- "info",
- "output_path",
- )
-
- infoCmd.Environment.Set("DIST_DIR", config.DistDir())
- infoCmd.Environment.Set("SHELL", "/bin/bash")
- infoCmd.Dir = filepath.Join(config.OutDir(), "..")
- ctx.Status.Status("Getting Bazel Info..")
- outputBasePath := string(infoCmd.OutputOrFatal())
+ ctx.Println("Getting Bazel output_path...")
+ outputBasePath := getBazelInfo(ctx, config, bazelExecutable, "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")