Bp2Build common properties auto-handling
Introduce `commonAttributes` & `fillCommonBp2BuildModuleAttrs used in
CreateBazelTargetModule
Adapt `bp2BuildInfo` to use `commonAttrs` instead of `Name`.
And thus also all downstream users of `CreateBazelTargetModule`.
As initial user, the Soong `required` property will be
translated to Bazel's `data`.
Bug: 198146582, 196091467
Test: build_converstion_test.go:TestCommonBp2BuildModuleAttrs
Test: go test
Test: mixed_{libc,droid}.sh
Change-Id: Ib500e40f7e2cb48c459f1ebe3188962fc41ec124
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 4a0eeea..c05a62b 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -411,7 +411,7 @@
TargetPackage() string
BazelRuleClass() string
BazelRuleLoadLocation() string
- BazelAttributes() interface{}
+ BazelAttributes() []interface{}
}
func generateBazelTarget(ctx bpToBuildContext, m bp2buildModule) BazelTarget {
@@ -419,7 +419,8 @@
bzlLoadLocation := m.BazelRuleLoadLocation()
// extract the bazel attributes from the module.
- props := extractModuleProperties([]interface{}{m.BazelAttributes()})
+ attrs := m.BazelAttributes()
+ props := extractModuleProperties(attrs, true)
delete(props.Attrs, "bp2build_available")
@@ -482,14 +483,14 @@
// TODO: this omits properties for blueprint modules (blueprint_go_binary,
// bootstrap_go_binary, bootstrap_go_package), which will have to be handled separately.
if aModule, ok := m.(android.Module); ok {
- return extractModuleProperties(aModule.GetProperties())
+ return extractModuleProperties(aModule.GetProperties(), false)
}
return BazelAttributes{}
}
// Generically extract module properties and types into a map, keyed by the module property name.
-func extractModuleProperties(props []interface{}) BazelAttributes {
+func extractModuleProperties(props []interface{}, checkForDuplicateProperties bool) BazelAttributes {
ret := map[string]string{}
// Iterate over this android.Module's property structs.
@@ -503,6 +504,11 @@
if isStructPtr(propertiesValue.Type()) {
structValue := propertiesValue.Elem()
for k, v := range extractStructProperties(structValue, 0) {
+ if existing, exists := ret[k]; checkForDuplicateProperties && exists {
+ panic(fmt.Errorf(
+ "%s (%v) is present in properties whereas it should be consolidated into a commonAttributes",
+ k, existing))
+ }
ret[k] = v
}
} else {
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index e904627..f14574c 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -15,10 +15,12 @@
package bp2build
import (
- "android/soong/android"
"fmt"
"strings"
"testing"
+
+ "android/soong/android"
+ "android/soong/python"
)
func TestGenerateSoongModuleTargets(t *testing.T) {
@@ -1215,3 +1217,133 @@
}
}
}
+
+func TestCommonBp2BuildModuleAttrs(t *testing.T) {
+ testCases := []bp2buildTestCase{
+ {
+ description: "Required into data test",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
+ moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ blueprint: `filegroup {
+ name: "reqd",
+}
+
+filegroup {
+ name: "fg_foo",
+ required: ["reqd"],
+ bazel_module: { bp2build_available: true },
+}`,
+ expectedBazelTargets: []string{`filegroup(
+ name = "fg_foo",
+ data = [":reqd"],
+)`,
+ `filegroup(
+ name = "reqd",
+)`,
+ },
+ },
+ {
+ description: "Required via arch into data test",
+ moduleTypeUnderTest: "python_library",
+ moduleTypeUnderTestFactory: python.PythonLibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: python.PythonLibraryBp2Build,
+ blueprint: `python_library {
+ name: "reqdx86",
+ bazel_module: { bp2build_available: false, },
+}
+
+python_library {
+ name: "reqdarm",
+ bazel_module: { bp2build_available: false, },
+}
+
+python_library {
+ name: "fg_foo",
+ arch: {
+ arm: {
+ required: ["reqdarm"],
+ },
+ x86: {
+ required: ["reqdx86"],
+ },
+ },
+ bazel_module: { bp2build_available: true },
+}`,
+ expectedBazelTargets: []string{`py_library(
+ name = "fg_foo",
+ data = select({
+ "//build/bazel/platforms/arch:arm": [":reqdarm"],
+ "//build/bazel/platforms/arch:x86": [":reqdx86"],
+ "//conditions:default": [],
+ }),
+ srcs_version = "PY3",
+)`,
+ },
+ },
+ {
+ description: "Required appended to data test",
+ moduleTypeUnderTest: "python_library",
+ moduleTypeUnderTestFactory: python.PythonLibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: python.PythonLibraryBp2Build,
+ blueprint: `python_library {
+ name: "reqd",
+ srcs: ["src.py"],
+}
+
+python_library {
+ name: "fg_foo",
+ data: ["data.bin"],
+ required: ["reqd"],
+ bazel_module: { bp2build_available: true },
+}`,
+ expectedBazelTargets: []string{
+ `py_library(
+ name = "fg_foo",
+ data = [
+ "data.bin",
+ ":reqd",
+ ],
+ srcs_version = "PY3",
+)`,
+ `py_library(
+ name = "reqd",
+ srcs = ["src.py"],
+ srcs_version = "PY3",
+)`,
+ },
+ filesystem: map[string]string{
+ "data.bin": "",
+ "src.py": "",
+ },
+ },
+ {
+ description: "All props-to-attrs at once together test",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
+ moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ blueprint: `filegroup {
+ name: "reqd"
+}
+filegroup {
+ name: "fg_foo",
+ required: ["reqd"],
+ bazel_module: { bp2build_available: true },
+}`,
+ expectedBazelTargets: []string{
+ `filegroup(
+ name = "fg_foo",
+ data = [":reqd"],
+)`,
+ `filegroup(
+ name = "reqd",
+)`,
+ },
+ filesystem: map[string]string{},
+ },
+ }
+
+ for _, test := range testCases {
+ runBp2BuildTestCaseSimple(t, test)
+ }
+}
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 0a86a79..d34a4ba 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -1,12 +1,13 @@
package bp2build
import (
- "android/soong/android"
- "android/soong/cc/config"
"fmt"
"reflect"
"strings"
+ "android/soong/android"
+ "android/soong/cc/config"
+
"github.com/google/blueprint/proptools"
)
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 1e7e53c..6c322ee 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -135,17 +135,14 @@
android.FailIfErrored(t, errs)
}
if actualCount, expectedCount := len(bazelTargets), len(tc.expectedBazelTargets); actualCount != expectedCount {
- t.Errorf("%s: Expected %d bazel target, got %d; %v",
- tc.description, expectedCount, actualCount, bazelTargets)
+ t.Errorf("%s: Expected %d bazel target, got `%d``",
+ tc.description, expectedCount, actualCount)
} else {
for i, target := range bazelTargets {
if w, g := tc.expectedBazelTargets[i], target.content; w != g {
t.Errorf(
- "%s: Expected generated Bazel target to be '%s', got '%s'",
- tc.description,
- w,
- g,
- )
+ "%s: Expected generated Bazel target to be `%s`, got `%s`",
+ tc.description, w, g)
}
}
}
@@ -312,7 +309,7 @@
Rule_class: "custom",
}
- ctx.CreateBazelTargetModule(m.Name(), props, attrs)
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
}
}
@@ -331,19 +328,19 @@
Rule_class: "my_library",
Bzl_load_location: "//build/bazel/rules:rules.bzl",
}
- ctx.CreateBazelTargetModule(baseName, myLibraryProps, attrs)
+ ctx.CreateBazelTargetModule(myLibraryProps, android.CommonAttributes{Name: baseName}, attrs)
protoLibraryProps := bazel.BazelTargetModuleProperties{
Rule_class: "proto_library",
Bzl_load_location: "//build/bazel/rules:proto.bzl",
}
- ctx.CreateBazelTargetModule(baseName+"_proto_library_deps", protoLibraryProps, attrs)
+ ctx.CreateBazelTargetModule(protoLibraryProps, android.CommonAttributes{Name: baseName + "_proto_library_deps"}, attrs)
myProtoLibraryProps := bazel.BazelTargetModuleProperties{
Rule_class: "my_proto_library",
Bzl_load_location: "//build/bazel/rules:proto.bzl",
}
- ctx.CreateBazelTargetModule(baseName+"_my_proto_library_deps", myProtoLibraryProps, attrs)
+ ctx.CreateBazelTargetModule(myProtoLibraryProps, android.CommonAttributes{Name: baseName + "_my_proto_library_deps"}, attrs)
}
}