Add bp2build arch-specific paths mutator
Adds deps for properties tagged `android:"path"` within arch, multilib, and target properties. Test: build/bazel/ci/bp2build.sh Test: m nothing Bug: 185217298 Change-Id: I0230da399d2c4e984b837f69523fa09eadba3ff1
This commit is contained in:
@@ -412,6 +412,54 @@ func (target Target) Variations() []blueprint.Variation {
|
||||
}
|
||||
}
|
||||
|
||||
func registerBp2buildArchPathDepsMutator(ctx RegisterMutatorsContext) {
|
||||
ctx.BottomUp("bp2build-arch-pathdeps", bp2buildArchPathDepsMutator).Parallel()
|
||||
}
|
||||
|
||||
// add dependencies for architecture specific properties tagged with `android:"path"`
|
||||
func bp2buildArchPathDepsMutator(ctx BottomUpMutatorContext) {
|
||||
var module Module
|
||||
module = ctx.Module()
|
||||
|
||||
m := module.base()
|
||||
if !m.ArchSpecific() {
|
||||
return
|
||||
}
|
||||
|
||||
// addPathDepsForProps does not descend into sub structs, so we need to descend into the
|
||||
// arch-specific properties ourselves
|
||||
properties := []interface{}{}
|
||||
for _, archProperties := range m.archProperties {
|
||||
for _, archProps := range archProperties {
|
||||
archPropValues := reflect.ValueOf(archProps).Elem()
|
||||
// there are three "arch" variations, descend into each
|
||||
for _, variant := range []string{"Arch", "Multilib", "Target"} {
|
||||
// The properties are an interface, get the value (a pointer) that it points to
|
||||
archProps := archPropValues.FieldByName(variant).Elem()
|
||||
if archProps.IsNil() {
|
||||
continue
|
||||
}
|
||||
// And then a pointer to a struct
|
||||
archProps = archProps.Elem()
|
||||
for i := 0; i < archProps.NumField(); i += 1 {
|
||||
f := archProps.Field(i)
|
||||
// If the value of the field is a struct (as opposed to a pointer to a struct) then step
|
||||
// into the BlueprintEmbed field.
|
||||
if f.Kind() == reflect.Struct {
|
||||
f = f.FieldByName("BlueprintEmbed")
|
||||
}
|
||||
if f.IsZero() {
|
||||
continue
|
||||
}
|
||||
props := f.Interface().(interface{})
|
||||
properties = append(properties, props)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
addPathDepsForProps(ctx, properties)
|
||||
}
|
||||
|
||||
// osMutator splits an arch-specific module into a variant for each OS that is enabled for the
|
||||
// module. It uses the HostOrDevice value passed to InitAndroidArchModule and the
|
||||
// device_supported and host_supported properties to determine which OsTypes are enabled for this
|
||||
@@ -899,13 +947,17 @@ func filterArchStruct(field reflect.StructField, prefix string) (bool, reflect.S
|
||||
if string(field.Tag) != `android:"`+strings.Join(values, ",")+`"` {
|
||||
panic(fmt.Errorf("unexpected tag format %q", field.Tag))
|
||||
}
|
||||
// don't delete path tag as it is needed for bp2build
|
||||
// these tags don't need to be present in the runtime generated struct type.
|
||||
values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend", "path"})
|
||||
if len(values) > 0 {
|
||||
values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend"})
|
||||
if len(values) > 0 && values[0] != "path" {
|
||||
panic(fmt.Errorf("unknown tags %q in field %q", values, prefix+field.Name))
|
||||
} else if len(values) == 1 {
|
||||
field.Tag = reflect.StructTag(`android:"` + strings.Join(values, ",") + `"`)
|
||||
} else {
|
||||
field.Tag = ``
|
||||
}
|
||||
|
||||
field.Tag = ""
|
||||
return true, field
|
||||
}
|
||||
return false, field
|
||||
|
@@ -66,9 +66,9 @@ func TestFilterArchStruct(t *testing.T) {
|
||||
}{},
|
||||
out: &struct {
|
||||
A *string
|
||||
B *string
|
||||
C *string
|
||||
D *string
|
||||
B *string `android:"path"`
|
||||
C *string `android:"path"`
|
||||
D *string `android:"path"`
|
||||
}{},
|
||||
filtered: true,
|
||||
},
|
||||
|
@@ -151,7 +151,7 @@ var (
|
||||
"libc_bionic_ndk", // ruperts@, cc_library_static, depends on //bionic/libc/system_properties
|
||||
"libc_bionic_systrace", // ruperts@, cc_library_static, 'private/bionic_systrace.h' file not found
|
||||
"libc_pthread", // ruperts@, cc_library_static, 'private/bionic_defs.h' file not found
|
||||
"libc_syscalls", // ruperts@, cc_library_static, mutator panic cannot get direct dep syscalls-arm64.S of libc_syscalls
|
||||
"libc_syscalls", // eakammer@, cc_library_static, 'private/bionic_asm.h' file not found
|
||||
"libc_ndk", // ruperts@, cc_library_static, depends on //bionic/libm:libm
|
||||
"libc_nopthread", // ruperts@, cc_library_static, depends on //external/arm-optimized-routines
|
||||
"libc_common", // ruperts@, cc_library_static, depends on //bionic/libc:libc_nopthread
|
||||
|
@@ -55,6 +55,7 @@ func RegisterMutatorsForBazelConversion(ctx *Context, preArchMutators, depsMutat
|
||||
bp2buildDepsMutators = append([]RegisterMutatorFunc{
|
||||
registerDepsMutatorBp2Build,
|
||||
registerPathDepsMutator,
|
||||
registerBp2buildArchPathDepsMutator,
|
||||
}, depsMutators...)
|
||||
|
||||
for _, f := range bp2buildDepsMutators {
|
||||
|
@@ -34,7 +34,10 @@ func registerPathDepsMutator(ctx RegisterMutatorsContext) {
|
||||
// ":module" module reference syntax in a property that is tagged with `android:"path"`.
|
||||
func pathDepsMutator(ctx BottomUpMutatorContext) {
|
||||
props := ctx.Module().base().generalProperties
|
||||
addPathDepsForProps(ctx, props)
|
||||
}
|
||||
|
||||
func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) {
|
||||
// Iterate through each property struct of the module extracting the contents of all properties
|
||||
// tagged with `android:"path"`.
|
||||
var pathProperties []string
|
||||
|
@@ -204,8 +204,9 @@ func TestGenerateSoongModuleTargets(t *testing.T) {
|
||||
|
||||
func TestGenerateBazelTargetModules(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
bp string
|
||||
expectedBazelTarget string
|
||||
expectedBazelTargets []string
|
||||
}{
|
||||
{
|
||||
bp: `custom {
|
||||
@@ -214,7 +215,7 @@ func TestGenerateBazelTargetModules(t *testing.T) {
|
||||
string_prop: "a",
|
||||
bazel_module: { bp2build_available: true },
|
||||
}`,
|
||||
expectedBazelTarget: `custom(
|
||||
expectedBazelTargets: []string{`custom(
|
||||
name = "foo",
|
||||
string_list_prop = [
|
||||
"a",
|
||||
@@ -223,6 +224,7 @@ func TestGenerateBazelTargetModules(t *testing.T) {
|
||||
string_prop = "a",
|
||||
)`,
|
||||
},
|
||||
},
|
||||
{
|
||||
bp: `custom {
|
||||
name: "control_characters",
|
||||
@@ -230,7 +232,7 @@ func TestGenerateBazelTargetModules(t *testing.T) {
|
||||
string_prop: "a\t\n\r",
|
||||
bazel_module: { bp2build_available: true },
|
||||
}`,
|
||||
expectedBazelTarget: `custom(
|
||||
expectedBazelTargets: []string{`custom(
|
||||
name = "control_characters",
|
||||
string_list_prop = [
|
||||
"\t",
|
||||
@@ -239,6 +241,77 @@ func TestGenerateBazelTargetModules(t *testing.T) {
|
||||
string_prop = "a\t\n\r",
|
||||
)`,
|
||||
},
|
||||
},
|
||||
{
|
||||
bp: `custom {
|
||||
name: "has_dep",
|
||||
arch_paths: [":dep"],
|
||||
bazel_module: { bp2build_available: true },
|
||||
}
|
||||
|
||||
custom {
|
||||
name: "dep",
|
||||
arch_paths: ["abc"],
|
||||
bazel_module: { bp2build_available: true },
|
||||
}`,
|
||||
expectedBazelTargets: []string{`custom(
|
||||
name = "dep",
|
||||
arch_paths = ["abc"],
|
||||
)`,
|
||||
`custom(
|
||||
name = "has_dep",
|
||||
arch_paths = [":dep"],
|
||||
)`,
|
||||
},
|
||||
},
|
||||
{
|
||||
bp: `custom {
|
||||
name: "arch_paths",
|
||||
arch: {
|
||||
x86: {
|
||||
arch_paths: ["abc"],
|
||||
},
|
||||
},
|
||||
bazel_module: { bp2build_available: true },
|
||||
}`,
|
||||
expectedBazelTargets: []string{`custom(
|
||||
name = "arch_paths",
|
||||
arch_paths = select({
|
||||
"//build/bazel/platforms/arch:x86": ["abc"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)`,
|
||||
},
|
||||
},
|
||||
{
|
||||
bp: `custom {
|
||||
name: "has_dep",
|
||||
arch: {
|
||||
x86: {
|
||||
arch_paths: [":dep"],
|
||||
},
|
||||
},
|
||||
bazel_module: { bp2build_available: true },
|
||||
}
|
||||
|
||||
custom {
|
||||
name: "dep",
|
||||
arch_paths: ["abc"],
|
||||
bazel_module: { bp2build_available: true },
|
||||
}`,
|
||||
expectedBazelTargets: []string{`custom(
|
||||
name = "dep",
|
||||
arch_paths = ["abc"],
|
||||
)`,
|
||||
`custom(
|
||||
name = "has_dep",
|
||||
arch_paths = select({
|
||||
"//build/bazel/platforms/arch:x86": [":dep"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
dir := "."
|
||||
@@ -262,20 +335,22 @@ func TestGenerateBazelTargetModules(t *testing.T) {
|
||||
codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
|
||||
bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
|
||||
|
||||
if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
|
||||
if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
|
||||
t.Errorf("Expected %d bazel target, got %d", expectedCount, actualCount)
|
||||
} else {
|
||||
actualBazelTarget := bazelTargets[0]
|
||||
if actualBazelTarget.content != testCase.expectedBazelTarget {
|
||||
for i, expectedBazelTarget := range testCase.expectedBazelTargets {
|
||||
actualBazelTarget := bazelTargets[i]
|
||||
if actualBazelTarget.content != expectedBazelTarget {
|
||||
t.Errorf(
|
||||
"Expected generated Bazel target to be '%s', got '%s'",
|
||||
testCase.expectedBazelTarget,
|
||||
expectedBazelTarget,
|
||||
actualBazelTarget.content,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadStatements(t *testing.T) {
|
||||
testCases := []struct {
|
||||
|
@@ -86,6 +86,7 @@ custom = rule(
|
||||
"soong_module_name": attr.string(mandatory = True),
|
||||
"soong_module_variant": attr.string(),
|
||||
"soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
|
||||
"arch_paths": attr.string_list(),
|
||||
# bazel_module start
|
||||
# "label": attr.string(),
|
||||
# "bp2build_available": attr.bool(),
|
||||
@@ -114,6 +115,7 @@ custom_defaults = rule(
|
||||
"soong_module_name": attr.string(mandatory = True),
|
||||
"soong_module_variant": attr.string(),
|
||||
"soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
|
||||
"arch_paths": attr.string_list(),
|
||||
"bool_prop": attr.bool(),
|
||||
"bool_ptr_prop": attr.bool(),
|
||||
"int64_ptr_prop": attr.int(),
|
||||
@@ -138,6 +140,7 @@ custom_test_ = rule(
|
||||
"soong_module_name": attr.string(mandatory = True),
|
||||
"soong_module_variant": attr.string(),
|
||||
"soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
|
||||
"arch_paths": attr.string_list(),
|
||||
"bool_prop": attr.bool(),
|
||||
"bool_ptr_prop": attr.bool(),
|
||||
"int64_ptr_prop": attr.int(),
|
||||
|
@@ -28,6 +28,8 @@ type customProps struct {
|
||||
|
||||
Nested_props nestedProps
|
||||
Nested_props_ptr *nestedProps
|
||||
|
||||
Arch_paths []string `android:"path,arch_variant"`
|
||||
}
|
||||
|
||||
type customModule struct {
|
||||
@@ -56,7 +58,7 @@ func customModuleFactoryBase() android.Module {
|
||||
|
||||
func customModuleFactory() android.Module {
|
||||
m := customModuleFactoryBase()
|
||||
android.InitAndroidModule(m)
|
||||
android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibBoth)
|
||||
return m
|
||||
}
|
||||
|
||||
@@ -114,6 +116,7 @@ func customDefaultsModuleFactory() android.Module {
|
||||
type customBazelModuleAttributes struct {
|
||||
String_prop string
|
||||
String_list_prop []string
|
||||
Arch_paths bazel.LabelListAttribute
|
||||
}
|
||||
|
||||
type customBazelModule struct {
|
||||
@@ -137,9 +140,18 @@ func customBp2BuildMutator(ctx android.TopDownMutatorContext) {
|
||||
return
|
||||
}
|
||||
|
||||
paths := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.props.Arch_paths))
|
||||
|
||||
for arch, props := range m.GetArchProperties(&customProps{}) {
|
||||
if archProps, ok := props.(*customProps); ok && archProps.Arch_paths != nil {
|
||||
paths.SetValueForArch(arch.Name, android.BazelLabelForModuleSrc(ctx, archProps.Arch_paths))
|
||||
}
|
||||
}
|
||||
|
||||
attrs := &customBazelModuleAttributes{
|
||||
String_prop: m.props.String_prop,
|
||||
String_list_prop: m.props.String_list_prop,
|
||||
Arch_paths: paths,
|
||||
}
|
||||
|
||||
props := bazel.BazelTargetModuleProperties{
|
||||
|
Reference in New Issue
Block a user