Merge "Make copyBootJarsToPredefinedLocations simpler and less fragile"
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index f906c8a..e4bbe64 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -756,6 +756,10 @@
cmd.ImplicitDepFile(PathForBazelOut(ctx, *depfile))
}
+ for _, symlinkPath := range buildStatement.SymlinkPaths {
+ cmd.ImplicitSymlinkOutput(PathForBazelOut(ctx, symlinkPath))
+ }
+
// This is required to silence warnings pertaining to unexpected timestamps. Particularly,
// some Bazel builtins (such as files in the bazel_tools directory) have far-future
// timestamps. Without restat, Ninja would emit warnings that the input files of a
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index f93fe2b..f74fed1 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -83,6 +83,36 @@
// or ":<module>") and returns a Bazel-compatible label which corresponds to dependencies on the
// module within the given ctx.
func BazelLabelForModuleDeps(ctx BazelConversionPathContext, modules []string) bazel.LabelList {
+ return bazelLabelForModuleDeps(ctx, modules, false)
+}
+
+// BazelLabelForModuleWholeDeps expects a list of references to other modules, ("<module>"
+// or ":<module>") and returns a Bazel-compatible label which corresponds to dependencies on the
+// module within the given ctx, where prebuilt dependencies will be appended with _alwayslink so
+// they can be handled as whole static libraries.
+func BazelLabelForModuleWholeDeps(ctx BazelConversionPathContext, modules []string) bazel.LabelList {
+ return bazelLabelForModuleDeps(ctx, modules, true)
+}
+
+// BazelLabelForModuleDepsExcludes expects two lists: modules (containing modules to include in the
+// list), and excludes (modules to exclude from the list). Both of these should contain references
+// to other modules, ("<module>" or ":<module>"). It returns a Bazel-compatible label list which
+// corresponds to dependencies on the module within the given ctx, and the excluded dependencies.
+func BazelLabelForModuleDepsExcludes(ctx BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
+ return bazelLabelForModuleDepsExcludes(ctx, modules, excludes, false)
+}
+
+// BazelLabelForModuleWholeDepsExcludes expects two lists: modules (containing modules to include in
+// the list), and excludes (modules to exclude from the list). Both of these should contain
+// references to other modules, ("<module>" or ":<module>"). It returns a Bazel-compatible label
+// list which corresponds to dependencies on the module within the given ctx, and the excluded
+// dependencies. Prebuilt dependencies will be appended with _alwayslink so they can be handled as
+// whole static libraries.
+func BazelLabelForModuleWholeDepsExcludes(ctx BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
+ return bazelLabelForModuleDepsExcludes(ctx, modules, excludes, true)
+}
+
+func bazelLabelForModuleDeps(ctx BazelConversionPathContext, modules []string, isWholeLibs bool) bazel.LabelList {
var labels bazel.LabelList
for _, module := range modules {
bpText := module
@@ -90,7 +120,7 @@
module = ":" + module
}
if m, t := SrcIsModuleWithTag(module); m != "" {
- l := getOtherModuleLabel(ctx, m, t)
+ l := getOtherModuleLabel(ctx, m, t, isWholeLibs)
l.OriginalModuleName = bpText
labels.Includes = append(labels.Includes, l)
} else {
@@ -100,16 +130,12 @@
return labels
}
-// BazelLabelForModuleDeps expects two lists: modules (containing modules to include in the list),
-// and excludes (modules to exclude from the list). Both of these should contain references to other
-// modules, ("<module>" or ":<module>"). It returns a Bazel-compatible label list which corresponds
-// to dependencies on the module within the given ctx, and the excluded dependencies.
-func BazelLabelForModuleDepsExcludes(ctx BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
- moduleLabels := BazelLabelForModuleDeps(ctx, RemoveListFromList(modules, excludes))
+func bazelLabelForModuleDepsExcludes(ctx BazelConversionPathContext, modules, excludes []string, isWholeLibs bool) bazel.LabelList {
+ moduleLabels := bazelLabelForModuleDeps(ctx, RemoveListFromList(modules, excludes), isWholeLibs)
if len(excludes) == 0 {
return moduleLabels
}
- excludeLabels := BazelLabelForModuleDeps(ctx, excludes)
+ excludeLabels := bazelLabelForModuleDeps(ctx, excludes, isWholeLibs)
return bazel.LabelList{
Includes: moduleLabels.Includes,
Excludes: excludeLabels.Includes,
@@ -273,7 +299,7 @@
for _, p := range paths {
if m, tag := SrcIsModuleWithTag(p); m != "" {
- l := getOtherModuleLabel(ctx, m, tag)
+ l := getOtherModuleLabel(ctx, m, tag, false)
if !InList(l.Label, expandedExcludes) {
l.OriginalModuleName = fmt.Sprintf(":%s", m)
labels.Includes = append(labels.Includes, l)
@@ -304,7 +330,7 @@
// getOtherModuleLabel returns a bazel.Label for the given dependency/tag combination for the
// module. The label will be relative to the current directory if appropriate. The dependency must
// already be resolved by either deps mutator or path deps mutator.
-func getOtherModuleLabel(ctx BazelConversionPathContext, dep, tag string) bazel.Label {
+func getOtherModuleLabel(ctx BazelConversionPathContext, dep, tag string, isWholeLibs bool) bazel.Label {
m, _ := ctx.GetDirectDep(dep)
if m == nil {
panic(fmt.Errorf(`Cannot get direct dep %q of %q.
@@ -313,6 +339,11 @@
}
otherLabel := bazelModuleLabel(ctx, m, tag)
label := bazelModuleLabel(ctx, ctx.Module(), "")
+ if isWholeLibs {
+ if m, ok := m.(Module); ok && IsModulePrebuilt(m) {
+ otherLabel += "_alwayslink"
+ }
+ }
if samePackage(label, otherLabel) {
otherLabel = bazelShortLabel(otherLabel)
}
diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go
index 5316d7b..08616a9 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -104,6 +104,7 @@
"LOCAL_NDK_STL_VARIANT": "stl",
"LOCAL_JAR_MANIFEST": "manifest",
"LOCAL_CERTIFICATE": "certificate",
+ "LOCAL_CERTIFICATE_LINEAGE": "lineage",
"LOCAL_PACKAGE_NAME": "name",
"LOCAL_MODULE_RELATIVE_PATH": "relative_install_path",
"LOCAL_PROTOC_OPTIMIZE_TYPE": "proto.type",
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index 439f45d..067dcba 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -1463,6 +1463,22 @@
}
`,
},
+ {
+ desc: "LOCAL_CERTIFICATE_LINEAGE",
+ in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := foo
+LOCAL_MODULE_TAGS := tests
+LOCAL_CERTIFICATE_LINEAGE := lineage
+include $(BUILD_PACKAGE)
+`,
+ expected: `
+android_test {
+ name: "foo",
+ lineage: "lineage",
+}
+`,
+ },
}
func TestEndToEnd(t *testing.T) {
diff --git a/bazel/aquery.go b/bazel/aquery.go
index d1119cb..8741afb 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -73,12 +73,13 @@
// BuildStatement contains information to register a build statement corresponding (one to one)
// with a Bazel action from Bazel's action graph.
type BuildStatement struct {
- Command string
- Depfile *string
- OutputPaths []string
- InputPaths []string
- Env []KeyValuePair
- Mnemonic string
+ Command string
+ Depfile *string
+ OutputPaths []string
+ InputPaths []string
+ SymlinkPaths []string
+ Env []KeyValuePair
+ Mnemonic string
}
// A helper type for aquery processing which facilitates retrieval of path IDs from their
@@ -234,10 +235,21 @@
OutputPaths: outputPaths,
InputPaths: inputPaths,
Env: actionEntry.EnvironmentVariables,
- Mnemonic: actionEntry.Mnemonic}
- if len(actionEntry.Arguments) < 1 {
+ Mnemonic: actionEntry.Mnemonic,
+ }
+
+ if isSymlinkAction(actionEntry) {
+ if len(inputPaths) != 1 || len(outputPaths) != 1 {
+ return nil, fmt.Errorf("Expect 1 input and 1 output to symlink action, got: input %q, output %q", inputPaths, outputPaths)
+ }
+ out := outputPaths[0]
+ outDir := proptools.ShellEscapeIncludingSpaces(filepath.Dir(out))
+ out = proptools.ShellEscapeIncludingSpaces(out)
+ in := proptools.ShellEscapeIncludingSpaces(inputPaths[0])
+ buildStatement.Command = fmt.Sprintf("mkdir -p %[1]s && rm -f %[2]s && ln -rsf %[3]s %[2]s", outDir, out, in)
+ buildStatement.SymlinkPaths = outputPaths[:]
+ } else if len(actionEntry.Arguments) < 1 {
return nil, fmt.Errorf("received action with no command: [%v]", buildStatement)
- continue
}
buildStatements = append(buildStatements, buildStatement)
}
@@ -245,9 +257,13 @@
return buildStatements, nil
}
+func isSymlinkAction(a action) bool {
+ return a.Mnemonic == "Symlink" || a.Mnemonic == "SolibSymlink"
+}
+
func shouldSkipAction(a action) bool {
- // TODO(b/180945121): Handle symlink actions.
- if a.Mnemonic == "Symlink" || a.Mnemonic == "SourceSymlinkManifest" || a.Mnemonic == "SymlinkTree" || a.Mnemonic == "SolibSymlink" {
+ // TODO(b/180945121): Handle complex symlink actions.
+ if a.Mnemonic == "SymlinkTree" || a.Mnemonic == "SourceSymlinkManifest" {
return true
}
// Middleman actions are not handled like other actions; they are handled separately as a
@@ -278,6 +294,9 @@
return "", fmt.Errorf("undefined path fragment id %d", currId)
}
labels = append([]string{currFragment.Label}, labels...)
+ if currId == currFragment.ParentId {
+ return "", fmt.Errorf("Fragment cannot refer to itself as parent %#v", currFragment)
+ }
currId = currFragment.ParentId
}
return filepath.Join(labels...), nil
diff --git a/bazel/aquery_test.go b/bazel/aquery_test.go
index 7b40dcd..43e4155 100644
--- a/bazel/aquery_test.go
+++ b/bazel/aquery_test.go
@@ -805,17 +805,229 @@
}
}
+func TestSimpleSymlink(t *testing.T) {
+ const inputString = `
+{
+ "artifacts": [{
+ "id": 1,
+ "pathFragmentId": 3
+ }, {
+ "id": 2,
+ "pathFragmentId": 5
+ }],
+ "actions": [{
+ "targetId": 1,
+ "actionKey": "x",
+ "mnemonic": "Symlink",
+ "inputDepSetIds": [1],
+ "outputIds": [2],
+ "primaryOutputId": 2
+ }],
+ "depSetOfFiles": [{
+ "id": 1,
+ "directArtifactIds": [1]
+ }],
+ "pathFragments": [{
+ "id": 1,
+ "label": "one"
+ }, {
+ "id": 2,
+ "label": "file_subdir",
+ "parentId": 1
+ }, {
+ "id": 3,
+ "label": "file",
+ "parentId": 2
+ }, {
+ "id": 4,
+ "label": "symlink_subdir",
+ "parentId": 1
+ }, {
+ "id": 5,
+ "label": "symlink",
+ "parentId": 4
+ }]
+}`
+
+ actual, err := AqueryBuildStatements([]byte(inputString))
+
+ if err != nil {
+ t.Errorf("Unexpected error %q", err)
+ }
+
+ expectedBuildStatements := []BuildStatement{
+ BuildStatement{
+ Command: "mkdir -p one/symlink_subdir && " +
+ "rm -f one/symlink_subdir/symlink && " +
+ "ln -rsf one/file_subdir/file one/symlink_subdir/symlink",
+ InputPaths: []string{"one/file_subdir/file"},
+ OutputPaths: []string{"one/symlink_subdir/symlink"},
+ SymlinkPaths: []string{"one/symlink_subdir/symlink"},
+ Mnemonic: "Symlink",
+ },
+ }
+ assertBuildStatements(t, actual, expectedBuildStatements)
+}
+
+func TestSymlinkQuotesPaths(t *testing.T) {
+ const inputString = `
+{
+ "artifacts": [{
+ "id": 1,
+ "pathFragmentId": 3
+ }, {
+ "id": 2,
+ "pathFragmentId": 5
+ }],
+ "actions": [{
+ "targetId": 1,
+ "actionKey": "x",
+ "mnemonic": "SolibSymlink",
+ "inputDepSetIds": [1],
+ "outputIds": [2],
+ "primaryOutputId": 2
+ }],
+ "depSetOfFiles": [{
+ "id": 1,
+ "directArtifactIds": [1]
+ }],
+ "pathFragments": [{
+ "id": 1,
+ "label": "one"
+ }, {
+ "id": 2,
+ "label": "file subdir",
+ "parentId": 1
+ }, {
+ "id": 3,
+ "label": "file",
+ "parentId": 2
+ }, {
+ "id": 4,
+ "label": "symlink subdir",
+ "parentId": 1
+ }, {
+ "id": 5,
+ "label": "symlink",
+ "parentId": 4
+ }]
+}`
+
+ actual, err := AqueryBuildStatements([]byte(inputString))
+
+ if err != nil {
+ t.Errorf("Unexpected error %q", err)
+ }
+
+ expectedBuildStatements := []BuildStatement{
+ BuildStatement{
+ Command: "mkdir -p 'one/symlink subdir' && " +
+ "rm -f 'one/symlink subdir/symlink' && " +
+ "ln -rsf 'one/file subdir/file' 'one/symlink subdir/symlink'",
+ InputPaths: []string{"one/file subdir/file"},
+ OutputPaths: []string{"one/symlink subdir/symlink"},
+ SymlinkPaths: []string{"one/symlink subdir/symlink"},
+ Mnemonic: "SolibSymlink",
+ },
+ }
+ assertBuildStatements(t, actual, expectedBuildStatements)
+}
+
+func TestSymlinkMultipleInputs(t *testing.T) {
+ const inputString = `
+{
+ "artifacts": [{
+ "id": 1,
+ "pathFragmentId": 1
+ }, {
+ "id": 2,
+ "pathFragmentId": 2
+ }, {
+ "id": 3,
+ "pathFragmentId": 3
+ }],
+ "actions": [{
+ "targetId": 1,
+ "actionKey": "x",
+ "mnemonic": "Symlink",
+ "inputDepSetIds": [1],
+ "outputIds": [3],
+ "primaryOutputId": 3
+ }],
+ "depSetOfFiles": [{
+ "id": 1,
+ "directArtifactIds": [1,2]
+ }],
+ "pathFragments": [{
+ "id": 1,
+ "label": "file"
+ }, {
+ "id": 2,
+ "label": "other_file"
+ }, {
+ "id": 3,
+ "label": "symlink"
+ }]
+}`
+
+ _, err := AqueryBuildStatements([]byte(inputString))
+ assertError(t, err, `Expect 1 input and 1 output to symlink action, got: input ["file" "other_file"], output ["symlink"]`)
+}
+
+func TestSymlinkMultipleOutputs(t *testing.T) {
+ const inputString = `
+{
+ "artifacts": [{
+ "id": 1,
+ "pathFragmentId": 1
+ }, {
+ "id": 2,
+ "pathFragmentId": 2
+ }, {
+ "id": 3,
+ "pathFragmentId": 3
+ }],
+ "actions": [{
+ "targetId": 1,
+ "actionKey": "x",
+ "mnemonic": "Symlink",
+ "inputDepSetIds": [1],
+ "outputIds": [2,3],
+ "primaryOutputId": 2
+ }],
+ "depSetOfFiles": [{
+ "id": 1,
+ "directArtifactIds": [1]
+ }],
+ "pathFragments": [{
+ "id": 1,
+ "label": "file"
+ }, {
+ "id": 2,
+ "label": "symlink"
+ }, {
+ "id": 3,
+ "label": "other_symlink"
+ }]
+}`
+
+ _, err := AqueryBuildStatements([]byte(inputString))
+ assertError(t, err, `Expect 1 input and 1 output to symlink action, got: input ["file"], output ["symlink" "other_symlink"]`)
+}
+
func assertError(t *testing.T, err error, expected string) {
+ t.Helper()
if err == nil {
t.Errorf("expected error '%s', but got no error", expected)
} else if err.Error() != expected {
- t.Errorf("expected error '%s', but got: %s", expected, err.Error())
+ t.Errorf("expected error:\n\t'%s', but got:\n\t'%s'", expected, err.Error())
}
}
// Asserts that the given actual build statements match the given expected build statements.
// Build statement equivalence is determined using buildStatementEquals.
func assertBuildStatements(t *testing.T, expected []BuildStatement, actual []BuildStatement) {
+ t.Helper()
if len(expected) != len(actual) {
t.Errorf("expected %d build statements, but got %d,\n expected: %v,\n actual: %v",
len(expected), len(actual), expected, actual)
@@ -852,6 +1064,12 @@
if !reflect.DeepEqual(stringSet(first.OutputPaths), stringSet(second.OutputPaths)) {
return false
}
+ if !reflect.DeepEqual(stringSet(first.SymlinkPaths), stringSet(second.SymlinkPaths)) {
+ return false
+ }
+ if first.Depfile != second.Depfile {
+ return false
+ }
return true
}
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 4de5aae..a1e0424 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -488,6 +488,9 @@
ret = "{\n"
// Sort and print the struct props by the key.
structProps := extractStructProperties(propertyValue, indent)
+ if len(structProps) == 0 {
+ return "", nil
+ }
for _, k := range android.SortedStringKeys(structProps) {
ret += makeIndent(indent + 1)
ret += fmt.Sprintf("%q: %s,\n", k, structProps[k])
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index c464cec..7f6982c 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -49,6 +49,7 @@
cc.RegisterCCBuildComponents(ctx)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
+ ctx.RegisterModuleType("cc_prebuilt_library_static", cc.PrebuiltStaticLibraryFactory)
ctx.RegisterModuleType("toolchain_library", cc.ToolchainLibraryFactory)
ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
}
@@ -401,6 +402,48 @@
})
}
+func TestCcLibraryWholeStaticLibsAlwaysLink(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ depsMutators: []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+ dir: "foo/bar",
+ filesystem: map[string]string{
+ "foo/bar/Android.bp": `
+cc_library {
+ name: "a",
+ whole_static_libs: ["whole_static_lib_for_both"],
+ static: {
+ whole_static_libs: ["whole_static_lib_for_static"],
+ },
+ shared: {
+ whole_static_libs: ["whole_static_lib_for_shared"],
+ },
+ bazel_module: { bp2build_available: true },
+}
+
+cc_prebuilt_library_static { name: "whole_static_lib_for_shared" }
+
+cc_prebuilt_library_static { name: "whole_static_lib_for_static" }
+
+cc_prebuilt_library_static { name: "whole_static_lib_for_both" }
+`,
+ },
+ blueprint: soongCcLibraryPreamble,
+ expectedBazelTargets: []string{`cc_library(
+ name = "a",
+ copts = [
+ "-Ifoo/bar",
+ "-I$(BINDIR)/foo/bar",
+ ],
+ whole_archive_deps = [":whole_static_lib_for_both_alwayslink"],
+ whole_archive_deps_for_shared = [":whole_static_lib_for_shared_alwayslink"],
+ whole_archive_deps_for_static = [":whole_static_lib_for_static_alwayslink"],
+)`},
+ })
+}
+
func TestCcLibrarySharedStaticPropsInArch(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
description: "cc_library shared/static props in arch",
@@ -1231,3 +1274,173 @@
}),
)`}})
}
+
+func TestCcLibraryStrip(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ description: "cc_library strip args",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ depsMutators: []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+ dir: "foo/bar",
+ filesystem: map[string]string{
+ "foo/bar/Android.bp": `
+cc_library {
+ name: "nothing",
+ bazel_module: { bp2build_available: true },
+}
+cc_library {
+ name: "keep_symbols",
+ bazel_module: { bp2build_available: true },
+ strip: {
+ keep_symbols: true,
+ }
+}
+cc_library {
+ name: "keep_symbols_and_debug_frame",
+ bazel_module: { bp2build_available: true },
+ strip: {
+ keep_symbols_and_debug_frame: true,
+ }
+}
+cc_library {
+ name: "none",
+ bazel_module: { bp2build_available: true },
+ strip: {
+ none: true,
+ }
+}
+cc_library {
+ name: "keep_symbols_list",
+ bazel_module: { bp2build_available: true },
+ strip: {
+ keep_symbols_list: ["symbol"],
+ }
+}
+cc_library {
+ name: "all",
+ bazel_module: { bp2build_available: true },
+ strip: {
+ all: true,
+ }
+}
+`,
+ },
+ blueprint: soongCcLibraryPreamble,
+ expectedBazelTargets: []string{`cc_library(
+ name = "all",
+ copts = [
+ "-Ifoo/bar",
+ "-I$(BINDIR)/foo/bar",
+ ],
+ strip = {
+ "all": True,
+ },
+)`, `cc_library(
+ name = "keep_symbols",
+ copts = [
+ "-Ifoo/bar",
+ "-I$(BINDIR)/foo/bar",
+ ],
+ strip = {
+ "keep_symbols": True,
+ },
+)`, `cc_library(
+ name = "keep_symbols_and_debug_frame",
+ copts = [
+ "-Ifoo/bar",
+ "-I$(BINDIR)/foo/bar",
+ ],
+ strip = {
+ "keep_symbols_and_debug_frame": True,
+ },
+)`, `cc_library(
+ name = "keep_symbols_list",
+ copts = [
+ "-Ifoo/bar",
+ "-I$(BINDIR)/foo/bar",
+ ],
+ strip = {
+ "keep_symbols_list": ["symbol"],
+ },
+)`, `cc_library(
+ name = "none",
+ copts = [
+ "-Ifoo/bar",
+ "-I$(BINDIR)/foo/bar",
+ ],
+ strip = {
+ "none": True,
+ },
+)`, `cc_library(
+ name = "nothing",
+ copts = [
+ "-Ifoo/bar",
+ "-I$(BINDIR)/foo/bar",
+ ],
+)`},
+ })
+}
+
+func TestCcLibraryStripWithArch(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ description: "cc_library strip args",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ depsMutators: []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+ dir: "foo/bar",
+ filesystem: map[string]string{
+ "foo/bar/Android.bp": `
+cc_library {
+ name: "multi-arch",
+ bazel_module: { bp2build_available: true },
+ target: {
+ darwin: {
+ strip: {
+ keep_symbols_list: ["foo", "bar"]
+ }
+ },
+ },
+ arch: {
+ arm: {
+ strip: {
+ keep_symbols_and_debug_frame: true,
+ },
+ },
+ arm64: {
+ strip: {
+ keep_symbols: true,
+ },
+ },
+ }
+}
+`,
+ },
+ blueprint: soongCcLibraryPreamble,
+ expectedBazelTargets: []string{`cc_library(
+ name = "multi-arch",
+ copts = [
+ "-Ifoo/bar",
+ "-I$(BINDIR)/foo/bar",
+ ],
+ strip = {
+ "keep_symbols": select({
+ "//build/bazel/platforms/arch:arm64": True,
+ "//conditions:default": None,
+ }),
+ "keep_symbols_and_debug_frame": select({
+ "//build/bazel/platforms/arch:arm": True,
+ "//conditions:default": None,
+ }),
+ "keep_symbols_list": select({
+ "//build/bazel/platforms/os:darwin": [
+ "foo",
+ "bar",
+ ],
+ "//conditions:default": [],
+ }),
+ },
+)`},
+ })
+}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 211fe5e..7c6ee0a 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -255,7 +255,7 @@
srcs: bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, props.Srcs)),
staticDeps: bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, props.Static_libs)),
dynamicDeps: bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, props.Shared_libs)),
- wholeArchiveDeps: bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, props.Whole_static_libs)),
+ wholeArchiveDeps: bazel.MakeLabelListAttribute(android.BazelLabelForModuleWholeDeps(ctx, props.Whole_static_libs)),
}
setAttrs := func(axis bazel.ConfigurationAxis, config string, props StaticOrSharedProperties) {
@@ -263,7 +263,7 @@
attrs.srcs.SetSelectValue(axis, config, android.BazelLabelForModuleSrc(ctx, props.Srcs))
attrs.staticDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, props.Static_libs))
attrs.dynamicDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, props.Shared_libs))
- attrs.wholeArchiveDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, props.Whole_static_libs))
+ attrs.wholeArchiveDeps.SetSelectValue(axis, config, android.BazelLabelForModuleWholeDeps(ctx, props.Whole_static_libs))
}
if isStatic {
@@ -485,13 +485,18 @@
// Convenience struct to hold all attributes parsed from linker properties.
type linkerAttributes struct {
- deps bazel.LabelListAttribute
- dynamicDeps bazel.LabelListAttribute
- wholeArchiveDeps bazel.LabelListAttribute
- exportedDeps bazel.LabelListAttribute
- useLibcrt bazel.BoolAttribute
- linkopts bazel.StringListAttribute
- versionScript bazel.LabelAttribute
+ deps bazel.LabelListAttribute
+ dynamicDeps bazel.LabelListAttribute
+ wholeArchiveDeps bazel.LabelListAttribute
+ exportedDeps bazel.LabelListAttribute
+ useLibcrt bazel.BoolAttribute
+ linkopts bazel.StringListAttribute
+ versionScript bazel.LabelAttribute
+ stripKeepSymbols bazel.BoolAttribute
+ stripKeepSymbolsAndDebugFrame bazel.BoolAttribute
+ stripKeepSymbolsList bazel.StringListAttribute
+ stripAll bazel.BoolAttribute
+ stripNone bazel.BoolAttribute
}
// FIXME(b/187655838): Use the existing linkerFlags() function instead of duplicating logic here
@@ -515,6 +520,33 @@
var versionScript bazel.LabelAttribute
var useLibcrt bazel.BoolAttribute
+ var stripKeepSymbols bazel.BoolAttribute
+ var stripKeepSymbolsAndDebugFrame bazel.BoolAttribute
+ var stripKeepSymbolsList bazel.StringListAttribute
+ var stripAll bazel.BoolAttribute
+ var stripNone bazel.BoolAttribute
+
+ if libraryDecorator, ok := module.linker.(*libraryDecorator); ok {
+ stripProperties := libraryDecorator.stripper.StripProperties
+ stripKeepSymbols.Value = stripProperties.Strip.Keep_symbols
+ stripKeepSymbolsList.Value = stripProperties.Strip.Keep_symbols_list
+ stripKeepSymbolsAndDebugFrame.Value = stripProperties.Strip.Keep_symbols_and_debug_frame
+ stripAll.Value = stripProperties.Strip.All
+ stripNone.Value = stripProperties.Strip.None
+ }
+
+ for axis, configToProps := range module.GetArchVariantProperties(ctx, &StripProperties{}) {
+ for config, props := range configToProps {
+ if stripProperties, ok := props.(*StripProperties); ok {
+ stripKeepSymbols.SetSelectValue(axis, config, stripProperties.Strip.Keep_symbols)
+ stripKeepSymbolsList.SetSelectValue(axis, config, stripProperties.Strip.Keep_symbols_list)
+ stripKeepSymbolsAndDebugFrame.SetSelectValue(axis, config, stripProperties.Strip.Keep_symbols_and_debug_frame)
+ stripAll.SetSelectValue(axis, config, stripProperties.Strip.All)
+ stripNone.SetSelectValue(axis, config, stripProperties.Strip.None)
+ }
+ }
+ }
+
for _, linkerProps := range module.linker.linkerProps() {
if baseLinkerProps, ok := linkerProps.(*BaseLinkerProperties); ok {
// Excludes to parallel Soong:
@@ -522,7 +554,7 @@
staticLibs := android.FirstUniqueStrings(baseLinkerProps.Static_libs)
staticDeps.Value = android.BazelLabelForModuleDepsExcludes(ctx, staticLibs, baseLinkerProps.Exclude_static_libs)
wholeArchiveLibs := android.FirstUniqueStrings(baseLinkerProps.Whole_static_libs)
- wholeArchiveDeps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDepsExcludes(ctx, wholeArchiveLibs, baseLinkerProps.Exclude_static_libs))
+ wholeArchiveDeps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleWholeDepsExcludes(ctx, wholeArchiveLibs, baseLinkerProps.Exclude_static_libs))
sharedLibs := android.FirstUniqueStrings(baseLinkerProps.Shared_libs)
dynamicDeps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDepsExcludes(ctx, sharedLibs, baseLinkerProps.Exclude_shared_libs))
@@ -549,7 +581,7 @@
staticLibs := android.FirstUniqueStrings(baseLinkerProps.Static_libs)
staticDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDepsExcludes(ctx, staticLibs, baseLinkerProps.Exclude_static_libs))
wholeArchiveLibs := android.FirstUniqueStrings(baseLinkerProps.Whole_static_libs)
- wholeArchiveDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDepsExcludes(ctx, wholeArchiveLibs, baseLinkerProps.Exclude_static_libs))
+ wholeArchiveDeps.SetSelectValue(axis, config, android.BazelLabelForModuleWholeDepsExcludes(ctx, wholeArchiveLibs, baseLinkerProps.Exclude_static_libs))
sharedLibs := android.FirstUniqueStrings(baseLinkerProps.Shared_libs)
dynamicDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDepsExcludes(ctx, sharedLibs, baseLinkerProps.Exclude_shared_libs))
@@ -572,13 +604,15 @@
excludesField string
// reference to the bazel attribute that should be set for the given product variable config
attribute *bazel.LabelListAttribute
+
+ depResolutionFunc func(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList
}
productVarToDepFields := map[string]productVarDep{
// product variables do not support exclude_shared_libs
- "Shared_libs": productVarDep{attribute: &dynamicDeps},
- "Static_libs": productVarDep{"Exclude_static_libs", &staticDeps},
- "Whole_static_libs": productVarDep{"Exclude_static_libs", &wholeArchiveDeps},
+ "Shared_libs": productVarDep{attribute: &dynamicDeps, depResolutionFunc: android.BazelLabelForModuleDepsExcludes},
+ "Static_libs": productVarDep{"Exclude_static_libs", &staticDeps, android.BazelLabelForModuleDepsExcludes},
+ "Whole_static_libs": productVarDep{"Exclude_static_libs", &wholeArchiveDeps, android.BazelLabelForModuleWholeDepsExcludes},
}
productVariableProps := android.ProductVariableProperties(ctx)
@@ -612,7 +646,8 @@
if excludes, ok = excludesProp.Property.([]string); excludesExists && !ok {
ctx.ModuleErrorf("Could not convert product variable %s property", dep.excludesField)
}
- dep.attribute.SetSelectValue(bazel.ProductVariableConfigurationAxis(config), config, android.BazelLabelForModuleDepsExcludes(ctx, android.FirstUniqueStrings(includes), excludes))
+
+ dep.attribute.SetSelectValue(bazel.ProductVariableConfigurationAxis(config), config, dep.depResolutionFunc(ctx, android.FirstUniqueStrings(includes), excludes))
}
}
@@ -630,6 +665,13 @@
linkopts: linkopts,
useLibcrt: useLibcrt,
versionScript: versionScript,
+
+ // Strip properties
+ stripKeepSymbols: stripKeepSymbols,
+ stripKeepSymbolsAndDebugFrame: stripKeepSymbolsAndDebugFrame,
+ stripKeepSymbolsList: stripKeepSymbolsList,
+ stripAll: stripAll,
+ stripNone: stripNone,
}
}
diff --git a/cc/library.go b/cc/library.go
index 93bd56c..28605f5 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -259,6 +259,16 @@
Static_deps_for_static bazel.LabelListAttribute
Dynamic_deps_for_static bazel.LabelListAttribute
Whole_archive_deps_for_static bazel.LabelListAttribute
+
+ Strip stripAttributes
+}
+
+type stripAttributes struct {
+ Keep_symbols bazel.BoolAttribute
+ Keep_symbols_and_debug_frame bazel.BoolAttribute
+ Keep_symbols_list bazel.StringListAttribute
+ All bazel.BoolAttribute
+ None bazel.BoolAttribute
}
type bazelCcLibrary struct {
@@ -323,6 +333,14 @@
Linkopts: linkerAttrs.linkopts,
Use_libcrt: linkerAttrs.useLibcrt,
+ Strip: stripAttributes{
+ Keep_symbols: linkerAttrs.stripKeepSymbols,
+ Keep_symbols_and_debug_frame: linkerAttrs.stripKeepSymbolsAndDebugFrame,
+ Keep_symbols_list: linkerAttrs.stripKeepSymbolsList,
+ All: linkerAttrs.stripAll,
+ None: linkerAttrs.stripNone,
+ },
+
Shared_srcs: sharedAttrs.srcs,
Shared_srcs_c: sharedAttrs.srcs_c,
Shared_srcs_as: sharedAttrs.srcs_as,
diff --git a/cc/strip.go b/cc/strip.go
index b1f34bb..c60e135 100644
--- a/cc/strip.go
+++ b/cc/strip.go
@@ -59,6 +59,7 @@
return !forceDisable && (forceEnable || defaultEnable)
}
+// Keep this consistent with //build/bazel/rules/stripped_shared_library.bzl.
func (stripper *Stripper) strip(actx android.ModuleContext, in android.Path, out android.ModuleOutPath,
flags StripFlags, isStaticLib bool) {
if actx.Darwin() {
diff --git a/java/lint.go b/java/lint.go
index 9f769df..1511cfe 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -361,10 +361,7 @@
Labels: map[string]string{"type": "tool", "name": "lint"},
ExecStrategy: lintRBEExecStrategy(ctx),
ToolchainInputs: []string{config.JavaCmd(ctx).String()},
- EnvironmentVariables: []string{
- "LANG",
- },
- Platform: map[string]string{remoteexec.PoolKey: pool},
+ Platform: map[string]string{remoteexec.PoolKey: pool},
})
}
diff --git a/remoteexec/remoteexec.go b/remoteexec/remoteexec.go
index ef4672a..9e7a0f1 100644
--- a/remoteexec/remoteexec.go
+++ b/remoteexec/remoteexec.go
@@ -50,8 +50,14 @@
)
var (
- defaultLabels = map[string]string{"type": "tool"}
- defaultExecStrategy = LocalExecStrategy
+ defaultLabels = map[string]string{"type": "tool"}
+ defaultExecStrategy = LocalExecStrategy
+ defaultEnvironmentVariables = []string{
+ // This is a subset of the allowlist in ui/build/ninja.go that makes sense remotely.
+ "LANG",
+ "LC_MESSAGES",
+ "PYTHONDONTWRITEBYTECODE",
+ }
)
// REParams holds information pertinent to the remote execution of a rule.
@@ -149,8 +155,10 @@
args += " --toolchain_inputs=" + strings.Join(r.ToolchainInputs, ",")
}
- if len(r.EnvironmentVariables) > 0 {
- args += " --env_var_allowlist=" + strings.Join(r.EnvironmentVariables, ",")
+ envVarAllowlist := append(r.EnvironmentVariables, defaultEnvironmentVariables...)
+
+ if len(envVarAllowlist) > 0 {
+ args += " --env_var_allowlist=" + strings.Join(envVarAllowlist, ",")
}
return args + " -- "
diff --git a/remoteexec/remoteexec_test.go b/remoteexec/remoteexec_test.go
index b117b89..3686316 100644
--- a/remoteexec/remoteexec_test.go
+++ b/remoteexec/remoteexec_test.go
@@ -36,7 +36,7 @@
PoolKey: "default",
},
},
- want: fmt.Sprintf("${android.RBEWrapper} --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=local --inputs=$in --output_files=$out -- ", DefaultImage),
+ want: fmt.Sprintf("${android.RBEWrapper} --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=local --inputs=$in --output_files=$out --env_var_allowlist=LANG,LC_MESSAGES,PYTHONDONTWRITEBYTECODE -- ", DefaultImage),
},
{
name: "all params",
@@ -52,7 +52,7 @@
PoolKey: "default",
},
},
- want: fmt.Sprintf("${android.RBEWrapper} --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=remote --inputs=$in --input_list_paths=$out.rsp,out2.rsp --output_files=$out --toolchain_inputs=clang++ -- ", DefaultImage),
+ want: fmt.Sprintf("${android.RBEWrapper} --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=remote --inputs=$in --input_list_paths=$out.rsp,out2.rsp --output_files=$out --toolchain_inputs=clang++ --env_var_allowlist=LANG,LC_MESSAGES,PYTHONDONTWRITEBYTECODE -- ", DefaultImage),
},
}
for _, test := range tests {
@@ -74,7 +74,7 @@
PoolKey: "default",
},
}
- want := fmt.Sprintf("prebuilts/remoteexecution-client/live/rewrapper --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=local --inputs=$in --output_files=$out -- ", DefaultImage)
+ want := fmt.Sprintf("prebuilts/remoteexecution-client/live/rewrapper --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=local --inputs=$in --output_files=$out --env_var_allowlist=LANG,LC_MESSAGES,PYTHONDONTWRITEBYTECODE -- ", DefaultImage)
if got := params.NoVarTemplate(DefaultWrapperPath); got != want {
t.Errorf("NoVarTemplate() returned\n%s\nwant\n%s", got, want)
}
@@ -90,7 +90,7 @@
PoolKey: "default",
},
}
- want := fmt.Sprintf("${android.RBEWrapper} --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=local --inputs=$in --output_files=$out -- ", DefaultImage)
+ want := fmt.Sprintf("${android.RBEWrapper} --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=local --inputs=$in --output_files=$out --env_var_allowlist=LANG,LC_MESSAGES,PYTHONDONTWRITEBYTECODE -- ", DefaultImage)
for i := 0; i < 1000; i++ {
if got := r.Template(); got != want {
t.Fatalf("Template() returned\n%s\nwant\n%s", got, want)