From 2701212d054a89286b9da482f92e79a262e25aee Mon Sep 17 00:00:00 2001 From: Dan Willemsen Date: Fri, 26 Jun 2015 17:40:54 -0700 Subject: [PATCH] androidbp: Implement static/shared property copying During mutation, make deep copies of the blueprint modules, then start modifying the property lists to apply the static/shared properties. Change-Id: Idc7063f4d1cf7d173ae10418e3437f3e2b914f59 --- Android.bp | 1 + androidbp/cmd/androidbp.go | 97 ++++++++++++------------- androidbp/cmd/androidbp_test.go | 27 +++++++ androidbp/cmd/module.go | 121 ++++++++++++++++++++++++++++++++ build.ninja.in | 4 +- 5 files changed, 202 insertions(+), 48 deletions(-) create mode 100644 androidbp/cmd/module.go diff --git a/Android.bp b/Android.bp index 8185a2c23..09acaf98e 100644 --- a/Android.bp +++ b/Android.bp @@ -193,6 +193,7 @@ bootstrap_go_binary { srcs: [ "androidbp/cmd/androidbp.go", "androidbp/cmd/soong.go", + "androidbp/cmd/module.go", ], testSrcs: [ "androidbp/cmd/androidbp_test.go", diff --git a/androidbp/cmd/androidbp.go b/androidbp/cmd/androidbp.go index ef7a364eb..ca33cb807 100644 --- a/androidbp/cmd/androidbp.go +++ b/androidbp/cmd/androidbp.go @@ -18,43 +18,6 @@ import ( var recursiveSubdirRegex *regexp.Regexp = regexp.MustCompile("(.+)/\\*\\*/(.+)") -type Module struct { - bpmod *bpparser.Module - bpname string - mkname string - isHostRule bool -} - -func newModule(mod *bpparser.Module) *Module { - return &Module{ - bpmod: mod, - bpname: mod.Type.Name, - } -} - -func (m *Module) translateRuleName() error { - var name string - if translation, ok := moduleTypeToRule[m.bpname]; ok { - name = translation - } else { - return fmt.Errorf("Unknown module type %q", m.bpname) - } - - if m.isHostRule { - if trans, ok := targetToHostModuleRule[name]; ok { - name = trans - } else { - return fmt.Errorf("No corresponding host rule for %q", name) - } - } else { - m.isHostRule = strings.Contains(name, "HOST") - } - - m.mkname = name - - return nil -} - type androidMkWriter struct { io.Writer @@ -85,6 +48,22 @@ func valueToString(value bpparser.Value) (string, error) { } } +func appendValueToValue(dest bpparser.Value, src bpparser.Value) (bpparser.Value, error) { + if src.Type != dest.Type { + return bpparser.Value{}, fmt.Errorf("ERROR: source and destination types don't match") + } + switch dest.Type { + case bpparser.List: + dest.ListValue = append(dest.ListValue, src.ListValue...) + return dest, nil + case bpparser.String: + dest.StringValue += src.StringValue + return dest, nil + default: + return bpparser.Value{}, fmt.Errorf("ERROR: unsupported append with type %s", dest.Type.String()) + } +} + func getTopOfAndroidTree(wd string) (string, error) { if !filepath.IsAbs(wd) { return "", errors.New("path must be absolute: " + wd) @@ -257,15 +236,6 @@ func prependLocalModule(name string, prop *bpparser.Property, suffix *string) ([ }, nil } -func modulePropBool(module *bpparser.Module, name string) bool { - for _, prop := range module.Properties { - if name == prop.Name.Name { - return prop.Value.BoolValue - } - } - return false -} - func (w *androidMkWriter) writeModule(moduleRule string, props []string, disabledBuilds map[string]bool, isHostRule bool) { disabledConditionals := disabledTargetConditionals @@ -331,8 +301,41 @@ func (w *androidMkWriter) mutateModule(module *Module) (modules []*Module, err e newModule(module.bpmod), newModule(module.bpmod), } + + ccLinkageCopy := func(props Properties, prop *bpparser.Property) error { + for _, p := range prop.Value.MapValue { + err := props.AppendToProp(p.Name.Name, p) + if err != nil { + return err + } + } + props.DeleteProp(prop.Name.Name) + return nil + } + ccLinkageDelete := func(props Properties, prop *bpparser.Property) error { + props.DeleteProp(prop.Name.Name) + return nil + } + modules[0].bpname = "cc_library_shared" + err := modules[0].IterateArchPropertiesWithName("shared", ccLinkageCopy) + if err != nil { + return nil, err + } + err = modules[0].IterateArchPropertiesWithName("static", ccLinkageDelete) + if err != nil { + return nil, err + } + modules[1].bpname = "cc_library_static" + err = modules[1].IterateArchPropertiesWithName("shared", ccLinkageDelete) + if err != nil { + return nil, err + } + err = modules[1].IterateArchPropertiesWithName("static", ccLinkageCopy) + if err != nil { + return nil, err + } } for _, mod := range modules { @@ -340,7 +343,7 @@ func (w *androidMkWriter) mutateModule(module *Module) (modules []*Module, err e if err != nil { return nil, err } - if mod.isHostRule || !modulePropBool(mod.bpmod, "host_supported") { + if mod.isHostRule || !mod.PropBool("host_supported") { continue } diff --git a/androidbp/cmd/androidbp_test.go b/androidbp/cmd/androidbp_test.go index 87170ed58..cf5be7a2d 100644 --- a/androidbp/cmd/androidbp_test.go +++ b/androidbp/cmd/androidbp_test.go @@ -104,6 +104,33 @@ var moduleTestCases = []struct { LOCAL_MODULE := test include $(BUILD_HOST_STATIC_LIBRARY)`, }, + // Static and Shared properties + { + blueprint: `cc_library { + name: "test", + srcs: ["a"], + static: { srcs: ["c"], static_libs: ["l"], }, + shared: { srcs: ["b"], }, + multilib: { lib32: { shared: { cflags: ["f"], }, }, }, + }`, + androidmk: `include $(CLEAR_VARS) + LOCAL_MODULE := test + LOCAL_SRC_FILES := \ + a \ + b + LOCAL_CFLAGS_32 := \ + f + include $(BUILD_SHARED_LIBRARY) + + include $(CLEAR_VARS) + LOCAL_MODULE := test + LOCAL_SRC_FILES := \ + a \ + c + LOCAL_STATIC_LIBRARIES := \ + l + include $(BUILD_STATIC_LIBRARY)`, + }, // Manual translation { blueprint: `/* Android.mk:start diff --git a/androidbp/cmd/module.go b/androidbp/cmd/module.go new file mode 100644 index 000000000..648ff88d0 --- /dev/null +++ b/androidbp/cmd/module.go @@ -0,0 +1,121 @@ +package main + +import ( + "fmt" + "strings" + + bpparser "github.com/google/blueprint/parser" +) + +type Module struct { + bpmod *bpparser.Module + bpname string + mkname string + isHostRule bool +} + +func newModule(mod *bpparser.Module) *Module { + return &Module{ + bpmod: mod.Copy(), + bpname: mod.Type.Name, + } +} + +func (m *Module) translateRuleName() error { + var name string + if translation, ok := moduleTypeToRule[m.bpname]; ok { + name = translation + } else { + return fmt.Errorf("Unknown module type %q", m.bpname) + } + + if m.isHostRule { + if trans, ok := targetToHostModuleRule[name]; ok { + name = trans + } else { + return fmt.Errorf("No corresponding host rule for %q", name) + } + } else { + m.isHostRule = strings.Contains(name, "HOST") + } + + m.mkname = name + + return nil +} + +func (m *Module) Properties() Properties { + return Properties{&m.bpmod.Properties} +} + +func (m *Module) PropBool(name string) bool { + if prop, ok := m.Properties().Prop(name); ok { + return prop.Value.BoolValue + } + return false +} + +func (m *Module) IterateArchPropertiesWithName(name string, f func(Properties, *bpparser.Property) error) error { + if p, ok := m.Properties().Prop(name); ok { + err := f(m.Properties(), p) + if err != nil { + return err + } + } + + for _, prop := range m.bpmod.Properties { + switch prop.Name.Name { + case "arch", "multilib", "target": + for _, sub := range prop.Value.MapValue { + props := Properties{&sub.Value.MapValue} + if p, ok := props.Prop(name); ok { + err := f(props, p) + if err != nil { + return err + } + } + } + } + } + + return nil +} + +type Properties struct { + props *[]*bpparser.Property +} + +func (p Properties) Prop(name string) (*bpparser.Property, bool) { + for _, prop := range *p.props { + if name == prop.Name.Name { + return prop, true + } + } + return nil, false +} + +func (p Properties) AppendToProp(name string, src *bpparser.Property) error { + if d, ok := p.Prop(name); ok { + val, err := appendValueToValue(d.Value, src.Value) + if err != nil { + return err + } + + d.Value = val + } else { + prop := src.Copy() + prop.Name.Name = name + *p.props = append(*p.props, prop) + } + + return nil +} + +func (p Properties) DeleteProp(name string) { + for i, prop := range *p.props { + if prop.Name.Name == name { + *p.props = append((*p.props)[0:i], (*p.props)[i+1:]...) + return + } + } +} diff --git a/build.ninja.in b/build.ninja.in index c015c641c..2e62364a9 100644 --- a/build.ninja.in +++ b/build.ninja.in @@ -68,6 +68,7 @@ rule g.bootstrap.test build .bootstrap/androidbp/test/androidbp.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/androidbp/cmd/androidbp.go $ ${g.bootstrap.srcDir}/build/soong/androidbp/cmd/soong.go $ + ${g.bootstrap.srcDir}/build/soong/androidbp/cmd/module.go $ ${g.bootstrap.srcDir}/build/soong/androidbp/cmd/androidbp_test.go | $ ${g.bootstrap.gcCmd} $ .bootstrap/blueprint-parser/pkg/github.com/google/blueprint/parser.a $ @@ -104,7 +105,8 @@ default .bootstrap/androidbp/test/test.passed build .bootstrap/androidbp/obj/androidbp.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/androidbp/cmd/androidbp.go $ - ${g.bootstrap.srcDir}/build/soong/androidbp/cmd/soong.go | $ + ${g.bootstrap.srcDir}/build/soong/androidbp/cmd/soong.go $ + ${g.bootstrap.srcDir}/build/soong/androidbp/cmd/module.go | $ ${g.bootstrap.gcCmd} $ .bootstrap/blueprint-parser/pkg/github.com/google/blueprint/parser.a $ .bootstrap/blueprint-pathtools/pkg/github.com/google/blueprint/pathtools.a $