Merge "Add SetProperties to json-module-graph" am: adf1b2a2cd
am: b6fdee8f0a
am: bbd97028b8
Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1937639 Change-Id: Ida7e56de037ef33121705423ae3c77251b1b4e98
This commit is contained in:
@@ -19,6 +19,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"text/scanner"
|
"text/scanner"
|
||||||
@@ -1326,7 +1327,64 @@ func (m *ModuleBase) GetUnconvertedBp2buildDeps() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *ModuleBase) AddJSONData(d *map[string]interface{}) {
|
func (m *ModuleBase) AddJSONData(d *map[string]interface{}) {
|
||||||
(*d)["Android"] = map[string]interface{}{}
|
(*d)["Android"] = map[string]interface{}{
|
||||||
|
// Properties set in Blueprint or in blueprint of a defaults modules
|
||||||
|
"SetProperties": m.propertiesWithValues(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type propInfo struct {
|
||||||
|
Name string
|
||||||
|
Type string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ModuleBase) propertiesWithValues() []propInfo {
|
||||||
|
var info []propInfo
|
||||||
|
props := m.GetProperties()
|
||||||
|
|
||||||
|
var propsWithValues func(name string, v reflect.Value)
|
||||||
|
propsWithValues = func(name string, v reflect.Value) {
|
||||||
|
kind := v.Kind()
|
||||||
|
switch kind {
|
||||||
|
case reflect.Ptr, reflect.Interface:
|
||||||
|
if v.IsNil() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
propsWithValues(name, v.Elem())
|
||||||
|
case reflect.Struct:
|
||||||
|
if v.IsZero() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
namePrefix := name
|
||||||
|
sTyp := v.Type().Field(i)
|
||||||
|
if proptools.ShouldSkipProperty(sTyp) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if name != "" && !strings.HasSuffix(namePrefix, ".") {
|
||||||
|
namePrefix += "."
|
||||||
|
}
|
||||||
|
if !proptools.IsEmbedded(sTyp) {
|
||||||
|
namePrefix += sTyp.Name
|
||||||
|
}
|
||||||
|
sVal := v.Field(i)
|
||||||
|
propsWithValues(namePrefix, sVal)
|
||||||
|
}
|
||||||
|
case reflect.Array, reflect.Slice:
|
||||||
|
if v.IsNil() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
elKind := v.Type().Elem().Kind()
|
||||||
|
info = append(info, propInfo{name, elKind.String() + " " + kind.String()})
|
||||||
|
default:
|
||||||
|
info = append(info, propInfo{name, kind.String()})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range props {
|
||||||
|
propsWithValues("", reflect.ValueOf(p).Elem())
|
||||||
|
}
|
||||||
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ModuleBase) ComponentDepsMutator(BottomUpMutatorContext) {}
|
func (m *ModuleBase) ComponentDepsMutator(BottomUpMutatorContext) {}
|
||||||
|
@@ -615,3 +615,204 @@ func parseMkRules(t *testing.T, config Config, nodes []mkparser.Node) []installM
|
|||||||
|
|
||||||
return rules
|
return rules
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PropsTestModuleEmbedded struct {
|
||||||
|
Embedded_prop *string
|
||||||
|
}
|
||||||
|
|
||||||
|
type propsTestModule struct {
|
||||||
|
ModuleBase
|
||||||
|
DefaultableModuleBase
|
||||||
|
props struct {
|
||||||
|
A string `android:"arch_variant"`
|
||||||
|
B *bool
|
||||||
|
C []string
|
||||||
|
}
|
||||||
|
otherProps struct {
|
||||||
|
PropsTestModuleEmbedded
|
||||||
|
|
||||||
|
D *int64
|
||||||
|
Nested struct {
|
||||||
|
E *string
|
||||||
|
}
|
||||||
|
F *string `blueprint:"mutated"`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func propsTestModuleFactory() Module {
|
||||||
|
module := &propsTestModule{}
|
||||||
|
module.AddProperties(&module.props, &module.otherProps)
|
||||||
|
InitAndroidArchModule(module, HostAndDeviceSupported, MultilibBoth)
|
||||||
|
InitDefaultableModule(module)
|
||||||
|
return module
|
||||||
|
}
|
||||||
|
|
||||||
|
type propsTestModuleDefaults struct {
|
||||||
|
ModuleBase
|
||||||
|
DefaultsModuleBase
|
||||||
|
}
|
||||||
|
|
||||||
|
func propsTestModuleDefaultsFactory() Module {
|
||||||
|
defaults := &propsTestModuleDefaults{}
|
||||||
|
module := propsTestModule{}
|
||||||
|
defaults.AddProperties(&module.props, &module.otherProps)
|
||||||
|
InitDefaultsModule(defaults)
|
||||||
|
return defaults
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *propsTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
|
||||||
|
str := "abc"
|
||||||
|
p.otherProps.F = &str
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUsedProperties(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
desc string
|
||||||
|
bp string
|
||||||
|
expectedProps []propInfo
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "only name",
|
||||||
|
bp: `test {
|
||||||
|
name: "foo",
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
expectedProps: []propInfo{
|
||||||
|
propInfo{"Name", "string"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "some props",
|
||||||
|
bp: `test {
|
||||||
|
name: "foo",
|
||||||
|
a: "abc",
|
||||||
|
b: true,
|
||||||
|
d: 123,
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
expectedProps: []propInfo{
|
||||||
|
propInfo{"A", "string"},
|
||||||
|
propInfo{"B", "bool"},
|
||||||
|
propInfo{"D", "int64"},
|
||||||
|
propInfo{"Name", "string"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "unused non-pointer prop",
|
||||||
|
bp: `test {
|
||||||
|
name: "foo",
|
||||||
|
b: true,
|
||||||
|
d: 123,
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
expectedProps: []propInfo{
|
||||||
|
// for non-pointer cannot distinguish between unused and intentionally set to empty
|
||||||
|
propInfo{"A", "string"},
|
||||||
|
propInfo{"B", "bool"},
|
||||||
|
propInfo{"D", "int64"},
|
||||||
|
propInfo{"Name", "string"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "nested props",
|
||||||
|
bp: `test {
|
||||||
|
name: "foo",
|
||||||
|
nested: {
|
||||||
|
e: "abc",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
expectedProps: []propInfo{
|
||||||
|
propInfo{"Nested.E", "string"},
|
||||||
|
propInfo{"Name", "string"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "arch props",
|
||||||
|
bp: `test {
|
||||||
|
name: "foo",
|
||||||
|
arch: {
|
||||||
|
x86_64: {
|
||||||
|
a: "abc",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
expectedProps: []propInfo{
|
||||||
|
propInfo{"Name", "string"},
|
||||||
|
propInfo{"Arch.X86_64.A", "string"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "embedded props",
|
||||||
|
bp: `test {
|
||||||
|
name: "foo",
|
||||||
|
embedded_prop: "a",
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
expectedProps: []propInfo{
|
||||||
|
propInfo{"Embedded_prop", "string"},
|
||||||
|
propInfo{"Name", "string"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "defaults",
|
||||||
|
bp: `
|
||||||
|
test_defaults {
|
||||||
|
name: "foo_defaults",
|
||||||
|
a: "a",
|
||||||
|
b: true,
|
||||||
|
embedded_prop:"a",
|
||||||
|
arch: {
|
||||||
|
x86_64: {
|
||||||
|
a: "a",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
test {
|
||||||
|
name: "foo",
|
||||||
|
defaults: ["foo_defaults"],
|
||||||
|
c: ["a"],
|
||||||
|
nested: {
|
||||||
|
e: "d",
|
||||||
|
},
|
||||||
|
target: {
|
||||||
|
linux: {
|
||||||
|
a: "a",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
expectedProps: []propInfo{
|
||||||
|
propInfo{"A", "string"},
|
||||||
|
propInfo{"B", "bool"},
|
||||||
|
propInfo{"C", "string slice"},
|
||||||
|
propInfo{"Embedded_prop", "string"},
|
||||||
|
propInfo{"Nested.E", "string"},
|
||||||
|
propInfo{"Name", "string"},
|
||||||
|
propInfo{"Arch.X86_64.A", "string"},
|
||||||
|
propInfo{"Target.Linux.A", "string"},
|
||||||
|
propInfo{"Defaults", "string slice"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.desc, func(t *testing.T) {
|
||||||
|
result := GroupFixturePreparers(
|
||||||
|
PrepareForTestWithAllowMissingDependencies,
|
||||||
|
PrepareForTestWithDefaults,
|
||||||
|
FixtureRegisterWithContext(func(ctx RegistrationContext) {
|
||||||
|
ctx.RegisterModuleType("test", propsTestModuleFactory)
|
||||||
|
ctx.RegisterModuleType("test_defaults", propsTestModuleDefaultsFactory)
|
||||||
|
}),
|
||||||
|
FixtureWithRootAndroidBp(tc.bp),
|
||||||
|
).RunTest(t)
|
||||||
|
|
||||||
|
foo := result.ModuleForTests("foo", "").Module().base()
|
||||||
|
|
||||||
|
AssertDeepEquals(t, "foo ", tc.expectedProps, foo.propertiesWithValues())
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -244,17 +244,14 @@ func TestAddJSONData(t *testing.T) {
|
|||||||
}
|
}
|
||||||
jsonData := map[string]interface{}{}
|
jsonData := map[string]interface{}{}
|
||||||
prebuiltStubsSources.AddJSONData(&jsonData)
|
prebuiltStubsSources.AddJSONData(&jsonData)
|
||||||
if fmt.Sprint(jsonData) != fmt.Sprint(
|
expectedOut := []map[string]interface{}{
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"Android": map[string]interface{}{},
|
"Inputs": []string{},
|
||||||
"Actions": []map[string]interface{}{
|
"Outputs": []string{},
|
||||||
map[string]interface{}{
|
},
|
||||||
"Inputs": []string{},
|
}
|
||||||
"Outputs": []string{},
|
if !reflect.DeepEqual(jsonData["Actions"], expectedOut) {
|
||||||
},
|
t.Errorf("The JSON action data %#v isn't as expected %#v.", jsonData["Actions"], expectedOut)
|
||||||
},
|
|
||||||
}) {
|
|
||||||
t.Errorf("The JSON data map isn't as expected %s.", jsonData)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user