Delete androidbp
androidbp is gone, replaced with combining kati ninja output for makefiles with blueprint ninja output for soong. Change-Id: I00b9e28877abf2ceb2223d3ccf0637bc1b7571bb
This commit is contained in:
16
Android.bp
16
Android.bp
@@ -207,22 +207,6 @@ bootstrap_go_package {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
bootstrap_go_binary {
|
|
||||||
name: "androidbp",
|
|
||||||
srcs: [
|
|
||||||
"androidbp/cmd/androidbp.go",
|
|
||||||
"androidbp/cmd/soong.go",
|
|
||||||
"androidbp/cmd/module.go",
|
|
||||||
],
|
|
||||||
testSrcs: [
|
|
||||||
"androidbp/cmd/androidbp_test.go",
|
|
||||||
],
|
|
||||||
deps: [
|
|
||||||
"blueprint",
|
|
||||||
"blueprint-parser",
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// C static libraries extracted from the gcc toolchain
|
// C static libraries extracted from the gcc toolchain
|
||||||
//
|
//
|
||||||
|
@@ -1,699 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
"text/scanner"
|
|
||||||
|
|
||||||
"github.com/google/blueprint"
|
|
||||||
bpparser "github.com/google/blueprint/parser"
|
|
||||||
)
|
|
||||||
|
|
||||||
var recursiveSubdirRegex *regexp.Regexp = regexp.MustCompile("(.+)/\\*\\*/(.+)")
|
|
||||||
|
|
||||||
type androidMkWriter struct {
|
|
||||||
io.Writer
|
|
||||||
|
|
||||||
blueprint *bpparser.File
|
|
||||||
path string
|
|
||||||
}
|
|
||||||
|
|
||||||
type propAssignment struct {
|
|
||||||
name, assigner, value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a propAssignment) assignmentWithSuffix(suffix string) string {
|
|
||||||
if suffix != "" {
|
|
||||||
a.name = a.name + "_" + suffix
|
|
||||||
}
|
|
||||||
return a.name + " " + a.assigner + " " + a.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a propAssignment) assignment() string {
|
|
||||||
return a.assignmentWithSuffix("")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *androidMkWriter) WriteString(s string) (int, error) {
|
|
||||||
return io.WriteString(w.Writer, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func valueToString(value bpparser.Value) (string, error) {
|
|
||||||
switch value.Type {
|
|
||||||
case bpparser.Bool:
|
|
||||||
return fmt.Sprintf("%t", value.BoolValue), nil
|
|
||||||
case bpparser.String:
|
|
||||||
return fmt.Sprintf("%s", processWildcards(value.StringValue)), nil
|
|
||||||
case bpparser.List:
|
|
||||||
val, err := listToMkString(value.ListValue)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("\\\n%s", val), nil
|
|
||||||
case bpparser.Map:
|
|
||||||
return "", fmt.Errorf("Can't convert map to string")
|
|
||||||
default:
|
|
||||||
return "", fmt.Errorf("ERROR: unsupported type %d", value.Type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
topfile := "build/soong/bootstrap.bash"
|
|
||||||
|
|
||||||
for "/" != wd {
|
|
||||||
expected := filepath.Join(wd, topfile)
|
|
||||||
|
|
||||||
if _, err := os.Stat(expected); err == nil {
|
|
||||||
// Found the top
|
|
||||||
return wd, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
wd = filepath.Join(wd, "..")
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", errors.New("couldn't find top of tree from " + wd)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: handle non-recursive wildcards?
|
|
||||||
func processWildcards(s string) string {
|
|
||||||
submatches := recursiveSubdirRegex.FindStringSubmatch(s)
|
|
||||||
if len(submatches) > 2 {
|
|
||||||
// Found a wildcard rule
|
|
||||||
return fmt.Sprintf("$(call find-files-in-subdirs, $(LOCAL_PATH), %s, %s)",
|
|
||||||
submatches[2], submatches[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func listToMkString(list []bpparser.Value) (string, error) {
|
|
||||||
lines := make([]string, 0, len(list))
|
|
||||||
for _, tok := range list {
|
|
||||||
val, err := valueToString(tok)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
lines = append(lines, fmt.Sprintf(" %s", val))
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings.Join(lines, " \\\n"), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func translateTargetConditionals(props []*bpparser.Property,
|
|
||||||
disabledBuilds map[string]bool, isHostRule bool) (computedProps []string, err error) {
|
|
||||||
for _, target := range props {
|
|
||||||
conditionals := targetScopedPropertyConditionals
|
|
||||||
altConditionals := hostScopedPropertyConditionals
|
|
||||||
if isHostRule {
|
|
||||||
conditionals, altConditionals = altConditionals, conditionals
|
|
||||||
}
|
|
||||||
|
|
||||||
conditional, ok := conditionals[target.Name.Name]
|
|
||||||
if !ok {
|
|
||||||
if _, ok := altConditionals[target.Name.Name]; ok {
|
|
||||||
// This is only for the other build type
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("Unsupported conditional %q", target.Name.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var scopedProps []string
|
|
||||||
for _, targetScopedProp := range target.Value.MapValue {
|
|
||||||
if assignment, ok, err := translateSingleProperty(targetScopedProp); err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if ok {
|
|
||||||
scopedProps = append(scopedProps, assignment.assignment())
|
|
||||||
} else if "disabled" == targetScopedProp.Name.Name {
|
|
||||||
if targetScopedProp.Value.BoolValue {
|
|
||||||
disabledBuilds[target.Name.Name] = true
|
|
||||||
} else {
|
|
||||||
delete(disabledBuilds, target.Name.Name)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("Unsupported target property %q", targetScopedProp.Name.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(scopedProps) > 0 {
|
|
||||||
if conditional != "" {
|
|
||||||
computedProps = append(computedProps, conditional)
|
|
||||||
computedProps = append(computedProps, scopedProps...)
|
|
||||||
computedProps = append(computedProps, "endif")
|
|
||||||
} else {
|
|
||||||
computedProps = append(computedProps, scopedProps...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func translateProductVariableConditionals(props []*bpparser.Property) (computedProps []string, err error) {
|
|
||||||
for _, productVariable := range props {
|
|
||||||
v, ok := productVariableConditionals[productVariable.Name.Name]
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("Unsupported product variable %q", productVariable.Name.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
var scopedProps []string
|
|
||||||
for _, conditionalScopedProp := range productVariable.Value.MapValue {
|
|
||||||
if assignment, ok, err := translateSingleProperty(conditionalScopedProp); err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if ok {
|
|
||||||
assignment.assigner = "+="
|
|
||||||
a := assignment.assignment()
|
|
||||||
if v.value != "" && strings.Contains(a, "%d") {
|
|
||||||
a = strings.Replace(a, "%d", v.value, 1)
|
|
||||||
}
|
|
||||||
scopedProps = append(scopedProps, a)
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("Unsupported product variable property %q",
|
|
||||||
conditionalScopedProp.Name.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(scopedProps) > 0 {
|
|
||||||
if v.conditional != "" {
|
|
||||||
computedProps = append(computedProps, v.conditional)
|
|
||||||
computedProps = append(computedProps, scopedProps...)
|
|
||||||
computedProps = append(computedProps, "endif")
|
|
||||||
} else {
|
|
||||||
computedProps = append(computedProps, scopedProps...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return computedProps, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var secondTargetReplacer = strings.NewReplacer("TARGET_", "TARGET_2ND_")
|
|
||||||
|
|
||||||
func translateSuffixProperties(suffixProps []*bpparser.Property,
|
|
||||||
suffixMap map[string]string) (computedProps []string, err error) {
|
|
||||||
for _, suffixProp := range suffixProps {
|
|
||||||
if suffix, ok := suffixMap[suffixProp.Name.Name]; ok {
|
|
||||||
for _, stdProp := range suffixProp.Value.MapValue {
|
|
||||||
if assignment, ok, err := translateSingleProperty(stdProp); err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if ok {
|
|
||||||
computedProps = append(computedProps, assignment.assignmentWithSuffix(suffix))
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("Unsupported property %q", stdProp.Name.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if variant, ok := cpuVariantConditionals[suffixProp.Name.Name]; ok {
|
|
||||||
var conditionalProps []propAssignment
|
|
||||||
for _, stdProp := range suffixProp.Value.MapValue {
|
|
||||||
if assignment, ok, err := translateSingleProperty(stdProp); err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if ok {
|
|
||||||
conditionalProps = append(conditionalProps, assignment)
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("Unsupported property %q", stdProp.Name.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
appendComputedProps := func() {
|
|
||||||
computedProps = append(computedProps, variant.conditional)
|
|
||||||
for _, prop := range conditionalProps {
|
|
||||||
prop.assigner = "+="
|
|
||||||
computedProps = append(computedProps, prop.assignmentWithSuffix(variant.suffix))
|
|
||||||
}
|
|
||||||
computedProps = append(computedProps, "endif")
|
|
||||||
}
|
|
||||||
|
|
||||||
appendComputedProps()
|
|
||||||
if variant.secondArch {
|
|
||||||
variant.conditional = secondTargetReplacer.Replace(variant.conditional)
|
|
||||||
variant.suffix = secondTargetReplacer.Replace(variant.suffix)
|
|
||||||
appendComputedProps()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("Unsupported suffix property %q", suffixProp.Name.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func translateSingleProperty(prop *bpparser.Property) (propAssignment, bool, error) {
|
|
||||||
var assignment propAssignment
|
|
||||||
if mkProp, ok := standardProperties[prop.Name.Name]; ok {
|
|
||||||
name := mkProp.string
|
|
||||||
val, err := valueToString(prop.Value)
|
|
||||||
if err != nil {
|
|
||||||
return propAssignment{}, false, err
|
|
||||||
}
|
|
||||||
assignment = propAssignment{name, ":=", val}
|
|
||||||
} else if rwProp, ok := rewriteProperties[prop.Name.Name]; ok {
|
|
||||||
val, err := valueToString(prop.Value)
|
|
||||||
if err != nil {
|
|
||||||
return propAssignment{}, false, err
|
|
||||||
}
|
|
||||||
assignment, err = rwProp.f(rwProp.string, prop, val)
|
|
||||||
if err != nil {
|
|
||||||
return propAssignment{}, false, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Unhandled, return false with no error to tell the caller to handle it
|
|
||||||
return propAssignment{}, false, nil
|
|
||||||
}
|
|
||||||
return assignment, true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func appendAssign(name string, prop *bpparser.Property, val string) (propAssignment, error) {
|
|
||||||
return propAssignment{name, "+=", val}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func prependLocalPath(name string, prop *bpparser.Property, val string) (propAssignment, error) {
|
|
||||||
return propAssignment{name, "+=", fmt.Sprintf("$(addprefix $(LOCAL_PATH)/,%s)", val)}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func prependLocalModule(name string, prop *bpparser.Property, val string) (propAssignment, error) {
|
|
||||||
return propAssignment{name, ":=", "$(LOCAL_MODULE)" + val}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func versionScript(name string, prop *bpparser.Property, val string) (propAssignment, error) {
|
|
||||||
return propAssignment{name, "+=", "-Wl,--version-script,$(LOCAL_PATH)/" + val}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *androidMkWriter) writeModule(moduleRule string, props []string,
|
|
||||||
disabledBuilds map[string]bool, isHostRule bool) {
|
|
||||||
disabledConditionals := disabledTargetConditionals
|
|
||||||
if isHostRule {
|
|
||||||
disabledConditionals = disabledHostConditionals
|
|
||||||
}
|
|
||||||
for build, _ := range disabledBuilds {
|
|
||||||
if conditional, ok := disabledConditionals[build]; ok {
|
|
||||||
fmt.Fprintf(w, "%s\n", conditional)
|
|
||||||
defer fmt.Fprintf(w, "endif\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(w, "include $(CLEAR_VARS)\n")
|
|
||||||
fmt.Fprintf(w, "%s\n", strings.Join(props, "\n"))
|
|
||||||
fmt.Fprintf(w, "include $(%s)\n\n", moduleRule)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *androidMkWriter) parsePropsAndWriteModule(module *Module) error {
|
|
||||||
standardProps := make([]string, 0, len(module.bpmod.Properties))
|
|
||||||
disabledBuilds := make(map[string]bool)
|
|
||||||
for _, prop := range module.bpmod.Properties {
|
|
||||||
if assignment, ok, err := translateSingleProperty(prop); err != nil {
|
|
||||||
return err
|
|
||||||
} else if ok {
|
|
||||||
standardProps = append(standardProps, assignment.assignment())
|
|
||||||
} else if suffixMap, ok := suffixProperties[prop.Name.Name]; ok {
|
|
||||||
props, err := translateSuffixProperties(prop.Value.MapValue, suffixMap)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
standardProps = append(standardProps, props...)
|
|
||||||
} else if "target" == prop.Name.Name {
|
|
||||||
props, err := translateTargetConditionals(prop.Value.MapValue, disabledBuilds, module.isHostRule)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
standardProps = append(standardProps, props...)
|
|
||||||
} else if "product_variables" == prop.Name.Name {
|
|
||||||
props, err := translateProductVariableConditionals(prop.Value.MapValue)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
standardProps = append(standardProps, props...)
|
|
||||||
} else if _, ok := ignoredProperties[prop.Name.Name]; ok {
|
|
||||||
} else {
|
|
||||||
return fmt.Errorf("Unsupported property %q", prop.Name.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
w.writeModule(module.mkname, standardProps, disabledBuilds, module.isHostRule)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func canUseWholeStaticLibrary(m *Module) (bool, error) {
|
|
||||||
ret := true
|
|
||||||
|
|
||||||
isCompatible := func(props Properties, prop *bpparser.Property) error {
|
|
||||||
for _, p := range prop.Value.MapValue {
|
|
||||||
if p.Name.Name == "cflags" {
|
|
||||||
ret = false
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if prop.Name.Name == "static" {
|
|
||||||
if p.Name.Name == "srcs" {
|
|
||||||
ret = false
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
err := m.IterateArchPropertiesWithName("shared", isCompatible)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
err = m.IterateArchPropertiesWithName("static", isCompatible)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *androidMkWriter) mutateModule(module *Module) (modules []*Module, err error) {
|
|
||||||
modules = []*Module{module}
|
|
||||||
|
|
||||||
if module.bpname == "cc_library" {
|
|
||||||
modules = []*Module{
|
|
||||||
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
|
|
||||||
}
|
|
||||||
deleteProp := func(props Properties, prop *bpparser.Property) error {
|
|
||||||
props.DeleteProp(prop.Name.Name)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok, err := canUseWholeStaticLibrary(module); err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if ok {
|
|
||||||
err = modules[0].IterateArchPropertiesWithName("srcs", deleteProp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if nameProp, ok := modules[0].Properties().Prop("name"); !ok {
|
|
||||||
return nil, fmt.Errorf("Can't find name property")
|
|
||||||
} else {
|
|
||||||
modules[0].Properties().AppendToProp("whole_static_libs", &bpparser.Property{
|
|
||||||
Value: bpparser.Value{
|
|
||||||
Type: bpparser.List,
|
|
||||||
ListValue: []bpparser.Value{
|
|
||||||
nameProp.Value.Copy(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
modules[0].bpname = "cc_library_shared"
|
|
||||||
err := modules[0].IterateArchPropertiesWithName("shared", ccLinkageCopy)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = modules[0].IterateArchPropertiesWithName("static", deleteProp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
modules[1].bpname = "cc_library_static"
|
|
||||||
err = modules[1].IterateArchPropertiesWithName("shared", deleteProp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = modules[1].IterateArchPropertiesWithName("static", ccLinkageCopy)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, mod := range modules {
|
|
||||||
err := mod.translateRuleName()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if mod.isHostRule || !mod.PropBool("host_supported") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
m := &Module{
|
|
||||||
bpmod: mod.bpmod,
|
|
||||||
bpname: mod.bpname,
|
|
||||||
isHostRule: true,
|
|
||||||
}
|
|
||||||
err = m.translateRuleName()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
modules = append(modules, m)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *androidMkWriter) handleModule(inputModule *bpparser.Module) error {
|
|
||||||
comment := w.getCommentBlock(inputModule.Type.Pos)
|
|
||||||
if translation, translated, err := getCommentTranslation(comment); err != nil {
|
|
||||||
return err
|
|
||||||
} else if translated {
|
|
||||||
w.WriteString(translation)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if ignoredModuleType[inputModule.Type.Name] {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
modules, err := w.mutateModule(newModule(inputModule))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, module := range modules {
|
|
||||||
err := w.parsePropsAndWriteModule(module)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *androidMkWriter) handleSubdirs(value bpparser.Value) {
|
|
||||||
subdirs := make([]string, 0, len(value.ListValue))
|
|
||||||
for _, tok := range value.ListValue {
|
|
||||||
subdirs = append(subdirs, tok.StringValue)
|
|
||||||
}
|
|
||||||
// The current makefile may be generated to outside the source tree (such as the out directory), with a different structure.
|
|
||||||
fmt.Fprintf(w, "# Uncomment the following line if you really want to include subdir Android.mks.\n")
|
|
||||||
fmt.Fprintf(w, "# include $(wildcard $(addsuffix $(LOCAL_PATH)/%s/, Android.mk))\n", strings.Join(subdirs, " "))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *androidMkWriter) handleLocalPath() error {
|
|
||||||
w.WriteString("LOCAL_PATH := " + w.path + "\n")
|
|
||||||
w.WriteString("LOCAL_MODULE_MAKEFILE := $(lastword $(MAKEFILE_LIST))\n\n")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns any block comment on the line preceding pos as a string
|
|
||||||
func (w *androidMkWriter) getCommentBlock(pos scanner.Position) string {
|
|
||||||
var buf []byte
|
|
||||||
|
|
||||||
comments := w.blueprint.Comments
|
|
||||||
for i, c := range comments {
|
|
||||||
if c.EndLine() == pos.Line-1 {
|
|
||||||
line := pos.Line
|
|
||||||
for j := i; j >= 0; j-- {
|
|
||||||
c = comments[j]
|
|
||||||
if c.EndLine() == line-1 {
|
|
||||||
buf = append([]byte(c.Text()), buf...)
|
|
||||||
line = c.Pos.Line
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCommentTranslation(comment string) (string, bool, error) {
|
|
||||||
lines := strings.Split(comment, "\n")
|
|
||||||
|
|
||||||
if directive, i, err := getCommentDirective(lines); err != nil {
|
|
||||||
return "", false, err
|
|
||||||
} else if directive != "" {
|
|
||||||
switch directive {
|
|
||||||
case "ignore":
|
|
||||||
return "", true, nil
|
|
||||||
case "start":
|
|
||||||
return getCommentTranslationBlock(lines[i+1:])
|
|
||||||
case "end":
|
|
||||||
return "", false, fmt.Errorf("Unexpected Android.mk:end translation directive")
|
|
||||||
default:
|
|
||||||
return "", false, fmt.Errorf("Unknown Android.mk module translation directive %q", directive)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCommentTranslationBlock(lines []string) (string, bool, error) {
|
|
||||||
var buf []byte
|
|
||||||
|
|
||||||
for _, line := range lines {
|
|
||||||
if directive := getLineCommentDirective(line); directive != "" {
|
|
||||||
switch directive {
|
|
||||||
case "end":
|
|
||||||
return string(buf), true, nil
|
|
||||||
default:
|
|
||||||
return "", false, fmt.Errorf("Unexpected Android.mk translation directive %q inside start", directive)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
buf = append(buf, line...)
|
|
||||||
buf = append(buf, '\n')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", false, fmt.Errorf("Missing Android.mk:end translation directive")
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCommentDirective(lines []string) (directive string, n int, err error) {
|
|
||||||
for i, line := range lines {
|
|
||||||
if directive := getLineCommentDirective(line); directive != "" {
|
|
||||||
return strings.ToLower(directive), i, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", -1, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getLineCommentDirective(line string) string {
|
|
||||||
line = strings.TrimSpace(line)
|
|
||||||
if strings.HasPrefix(line, "Android.mk:") {
|
|
||||||
line = strings.TrimPrefix(line, "Android.mk:")
|
|
||||||
line = strings.TrimSpace(line)
|
|
||||||
return line
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *androidMkWriter) write(writer io.Writer) (err error) {
|
|
||||||
w.Writer = writer
|
|
||||||
|
|
||||||
if err = w.handleLocalPath(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, block := range w.blueprint.Defs {
|
|
||||||
switch block := block.(type) {
|
|
||||||
case *bpparser.Module:
|
|
||||||
err = w.handleModule(block)
|
|
||||||
case *bpparser.Assignment:
|
|
||||||
// Nothing
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Unhandled def %v", block)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func translate(rootFile, androidBp, androidMk string) error {
|
|
||||||
|
|
||||||
ctx := blueprint.NewContext()
|
|
||||||
|
|
||||||
var blueprintFile *bpparser.File
|
|
||||||
|
|
||||||
_, errs := ctx.WalkBlueprintsFiles(rootFile, func(file *bpparser.File) {
|
|
||||||
if file.Name == androidBp {
|
|
||||||
blueprintFile = file
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if len(errs) > 0 {
|
|
||||||
return errs[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
if blueprintFile == nil {
|
|
||||||
return fmt.Errorf("File %q wasn't parsed from %q", androidBp, rootFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
writer := &androidMkWriter{
|
|
||||||
blueprint: blueprintFile,
|
|
||||||
path: path.Dir(androidBp),
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
|
|
||||||
err := writer.write(buf)
|
|
||||||
if err != nil {
|
|
||||||
os.Remove(androidMk)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.Create(androidMk)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
_, err = f.Write(buf.Bytes())
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if len(os.Args) < 4 {
|
|
||||||
fmt.Fprintln(os.Stderr, "Expected root Android.bp, input and output filename arguments")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
rootFile := os.Args[1]
|
|
||||||
androidBp, err := filepath.Rel(filepath.Dir(rootFile), os.Args[2])
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Android.bp file %q is not relative to %q: %s\n",
|
|
||||||
os.Args[2], rootFile, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
androidMk := os.Args[3]
|
|
||||||
|
|
||||||
err = translate(rootFile, androidBp, androidMk)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Error translating %s: %s\n", androidBp, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,227 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"unicode"
|
|
||||||
|
|
||||||
bpparser "github.com/google/blueprint/parser"
|
|
||||||
)
|
|
||||||
|
|
||||||
var valueTestCases = []struct {
|
|
||||||
blueprint string
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
blueprint: `test = false`,
|
|
||||||
expected: `false`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
blueprint: `test = "string"`,
|
|
||||||
expected: `string`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
blueprint: `test = ["a", "b"]`,
|
|
||||||
expected: `\
|
|
||||||
a \
|
|
||||||
b
|
|
||||||
`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestValueToString(t *testing.T) {
|
|
||||||
for _, testCase := range valueTestCases {
|
|
||||||
blueprint, errs := bpparser.Parse("", strings.NewReader(testCase.blueprint), nil)
|
|
||||||
if len(errs) > 0 {
|
|
||||||
t.Errorf("Failed to read blueprint: %q", errs)
|
|
||||||
}
|
|
||||||
|
|
||||||
str, err := valueToString(blueprint.Defs[0].(*bpparser.Assignment).Value)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err.Error())
|
|
||||||
}
|
|
||||||
expect(t, testCase.blueprint, testCase.expected, str)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var moduleTestCases = []struct {
|
|
||||||
blueprint string
|
|
||||||
androidmk string
|
|
||||||
}{
|
|
||||||
// Target-only
|
|
||||||
{
|
|
||||||
blueprint: `cc_library_shared { name: "test", }`,
|
|
||||||
androidmk: `include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := test
|
|
||||||
include $(BUILD_SHARED_LIBRARY)`,
|
|
||||||
},
|
|
||||||
// Host-only
|
|
||||||
{
|
|
||||||
blueprint: `cc_library_host_shared { name: "test", }`,
|
|
||||||
androidmk: `include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := test
|
|
||||||
include $(BUILD_HOST_SHARED_LIBRARY)`,
|
|
||||||
},
|
|
||||||
// Target and Host
|
|
||||||
{
|
|
||||||
blueprint: `cc_library_shared { name: "test", host_supported: true, }`,
|
|
||||||
androidmk: `include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := test
|
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := test
|
|
||||||
include $(BUILD_HOST_SHARED_LIBRARY)`,
|
|
||||||
},
|
|
||||||
// Static and Shared
|
|
||||||
{
|
|
||||||
blueprint: `cc_library { name: "test", srcs: ["a"], }`,
|
|
||||||
androidmk: `include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := test
|
|
||||||
LOCAL_WHOLE_STATIC_LIBRARIES := \
|
|
||||||
test
|
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := test
|
|
||||||
LOCAL_SRC_FILES := \
|
|
||||||
a
|
|
||||||
include $(BUILD_STATIC_LIBRARY)`,
|
|
||||||
},
|
|
||||||
// Static and Shared / Target and Host
|
|
||||||
{
|
|
||||||
blueprint: `cc_library { name: "test", host_supported: true, }`,
|
|
||||||
androidmk: `include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := test
|
|
||||||
LOCAL_WHOLE_STATIC_LIBRARIES := \
|
|
||||||
test
|
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := test
|
|
||||||
include $(BUILD_STATIC_LIBRARY)
|
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := test
|
|
||||||
LOCAL_WHOLE_STATIC_LIBRARIES := \
|
|
||||||
test
|
|
||||||
include $(BUILD_HOST_SHARED_LIBRARY)
|
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
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)`,
|
|
||||||
},
|
|
||||||
// Static and Shared properties, use whole static lib, but add extra shared srcs
|
|
||||||
{
|
|
||||||
blueprint: `cc_library {
|
|
||||||
name: "test",
|
|
||||||
srcs: ["a"],
|
|
||||||
shared: { srcs: ["b"], },
|
|
||||||
}`,
|
|
||||||
androidmk: `include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := test
|
|
||||||
LOCAL_WHOLE_STATIC_LIBRARIES := \
|
|
||||||
test
|
|
||||||
LOCAL_SRC_FILES := \
|
|
||||||
b
|
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := test
|
|
||||||
LOCAL_SRC_FILES := \
|
|
||||||
a
|
|
||||||
include $(BUILD_STATIC_LIBRARY)`,
|
|
||||||
},
|
|
||||||
// Manual translation
|
|
||||||
{
|
|
||||||
blueprint: `/* Android.mk:start
|
|
||||||
# Manual translation
|
|
||||||
Android.mk:end */
|
|
||||||
cc_library { name: "test", host_supported: true, }`,
|
|
||||||
androidmk: `# Manual translation`,
|
|
||||||
},
|
|
||||||
// Ignored translation
|
|
||||||
{
|
|
||||||
blueprint: `/* Android.mk:ignore */
|
|
||||||
cc_library { name: "test", host_supported: true, }`,
|
|
||||||
androidmk: ``,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestModules(t *testing.T) {
|
|
||||||
for _, testCase := range moduleTestCases {
|
|
||||||
blueprint, errs := bpparser.Parse("", strings.NewReader(testCase.blueprint), nil)
|
|
||||||
if len(errs) > 0 {
|
|
||||||
t.Errorf("Failed to read blueprint: %q", errs)
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
writer := &androidMkWriter{
|
|
||||||
blueprint: blueprint,
|
|
||||||
path: "",
|
|
||||||
Writer: buf,
|
|
||||||
}
|
|
||||||
|
|
||||||
module := blueprint.Defs[0].(*bpparser.Module)
|
|
||||||
err := writer.handleModule(module)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error %s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(t, testCase.blueprint, testCase.androidmk, buf.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trim left whitespace, and any trailing newlines. Leave inner blank lines and
|
|
||||||
// right whitespace so that we can still check line continuations are correct
|
|
||||||
func trim(str string) string {
|
|
||||||
var list []string
|
|
||||||
for _, s := range strings.Split(str, "\n") {
|
|
||||||
list = append(list, strings.TrimLeftFunc(s, unicode.IsSpace))
|
|
||||||
}
|
|
||||||
return strings.TrimRight(strings.Join(list, "\n"), "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func expect(t *testing.T, testCase string, expected string, out string) {
|
|
||||||
expected = trim(expected)
|
|
||||||
out = trim(out)
|
|
||||||
if expected != out {
|
|
||||||
sep := " "
|
|
||||||
if strings.Index(expected, "\n") != -1 || strings.Index(out, "\n") != -1 {
|
|
||||||
sep = "\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Errorf("test case: %s", testCase)
|
|
||||||
t.Errorf("unexpected difference:")
|
|
||||||
t.Errorf(" expected:%s%s", sep, expected)
|
|
||||||
t.Errorf(" got:%s%s", sep, out)
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,121 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,181 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import bpparser "github.com/google/blueprint/parser"
|
|
||||||
|
|
||||||
var standardProperties = map[string]struct {
|
|
||||||
string
|
|
||||||
bpparser.ValueType
|
|
||||||
}{
|
|
||||||
// ==== STRING PROPERTIES ====
|
|
||||||
"name": {"LOCAL_MODULE", bpparser.String},
|
|
||||||
"stem": {"LOCAL_MODULE_STEM", bpparser.String},
|
|
||||||
"class": {"LOCAL_MODULE_CLASS", bpparser.String},
|
|
||||||
"stl": {"LOCAL_CXX_STL", bpparser.String},
|
|
||||||
"strip": {"LOCAL_STRIP_MODULE", bpparser.String},
|
|
||||||
"compile_multilib": {"LOCAL_MULTILIB", bpparser.String},
|
|
||||||
"instruction_set": {"LOCAL_ARM_MODE_HACK", bpparser.String},
|
|
||||||
"sdk_version": {"LOCAL_SDK_VERSION", bpparser.String},
|
|
||||||
//"stl": "LOCAL_NDK_STL_VARIANT", TODO
|
|
||||||
"manifest": {"LOCAL_JAR_MANIFEST", bpparser.String},
|
|
||||||
"jarjar_rules": {"LOCAL_JARJAR_RULES", bpparser.String},
|
|
||||||
"certificate": {"LOCAL_CERTIFICATE", bpparser.String},
|
|
||||||
//"name": "LOCAL_PACKAGE_NAME", TODO
|
|
||||||
|
|
||||||
// ==== LIST PROPERTIES ====
|
|
||||||
"srcs": {"LOCAL_SRC_FILES", bpparser.List},
|
|
||||||
"exclude_srcs": {"LOCAL_SRC_FILES_EXCLUDE", bpparser.List},
|
|
||||||
"shared_libs": {"LOCAL_SHARED_LIBRARIES", bpparser.List},
|
|
||||||
"static_libs": {"LOCAL_STATIC_LIBRARIES", bpparser.List},
|
|
||||||
"whole_static_libs": {"LOCAL_WHOLE_STATIC_LIBRARIES", bpparser.List},
|
|
||||||
"system_shared_libs": {"LOCAL_SYSTEM_SHARED_LIBRARIES", bpparser.List},
|
|
||||||
"asflags": {"LOCAL_ASFLAGS", bpparser.List},
|
|
||||||
"clang_asflags": {"LOCAL_CLANG_ASFLAGS", bpparser.List},
|
|
||||||
"cflags": {"LOCAL_CFLAGS", bpparser.List},
|
|
||||||
"conlyflags": {"LOCAL_CONLYFLAGS", bpparser.List},
|
|
||||||
"cppflags": {"LOCAL_CPPFLAGS", bpparser.List},
|
|
||||||
"ldflags": {"LOCAL_LDFLAGS", bpparser.List},
|
|
||||||
"required": {"LOCAL_REQUIRED_MODULES", bpparser.List},
|
|
||||||
"tags": {"LOCAL_MODULE_TAGS", bpparser.List},
|
|
||||||
"host_ldlibs": {"LOCAL_LDLIBS", bpparser.List},
|
|
||||||
"clang_cflags": {"LOCAL_CLANG_CFLAGS", bpparser.List},
|
|
||||||
"yaccflags": {"LOCAL_YACCFLAGS", bpparser.List},
|
|
||||||
"java_resource_dirs": {"LOCAL_JAVA_RESOURCE_DIRS", bpparser.List},
|
|
||||||
"javacflags": {"LOCAL_JAVACFLAGS", bpparser.List},
|
|
||||||
"dxflags": {"LOCAL_DX_FLAGS", bpparser.List},
|
|
||||||
"java_libs": {"LOCAL_JAVA_LIBRARIES", bpparser.List},
|
|
||||||
"java_static_libs": {"LOCAL_STATIC_JAVA_LIBRARIES", bpparser.List},
|
|
||||||
"aidl_includes": {"LOCAL_AIDL_INCLUDES", bpparser.List},
|
|
||||||
"aaptflags": {"LOCAL_AAPT_FLAGS", bpparser.List},
|
|
||||||
"package_splits": {"LOCAL_PACKAGE_SPLITS", bpparser.List},
|
|
||||||
|
|
||||||
// ==== BOOL PROPERTIES ====
|
|
||||||
"host": {"LOCAL_IS_HOST_MODULE", bpparser.Bool},
|
|
||||||
"clang": {"LOCAL_CLANG", bpparser.Bool},
|
|
||||||
"static_executable": {"LOCAL_FORCE_STATIC_EXECUTABLE", bpparser.Bool},
|
|
||||||
"asan": {"LOCAL_ADDRESS_SANITIZER", bpparser.Bool},
|
|
||||||
"native_coverage": {"LOCAL_NATIVE_COVERAGE", bpparser.Bool},
|
|
||||||
"nocrt": {"LOCAL_NO_CRT", bpparser.Bool},
|
|
||||||
"allow_undefined_symbols": {"LOCAL_ALLOW_UNDEFINED_SYMBOLS", bpparser.Bool},
|
|
||||||
"rtti": {"LOCAL_RTTI_FLAG", bpparser.Bool},
|
|
||||||
"no_standard_libraries": {"LOCAL_NO_STANDARD_LIBRARIES", bpparser.Bool},
|
|
||||||
"export_package_resources": {"LOCAL_EXPORT_PACKAGE_RESOURCES", bpparser.Bool},
|
|
||||||
"no_default_compiler_flags": {"LOCAL_NO_DEFAULT_COMPILER_FLAGS", bpparser.Bool},
|
|
||||||
}
|
|
||||||
|
|
||||||
var rewriteProperties = map[string]struct {
|
|
||||||
string
|
|
||||||
f func(name string, prop *bpparser.Property, val string) (propAssignment, error)
|
|
||||||
}{
|
|
||||||
"include_dirs": {"LOCAL_C_INCLUDES", appendAssign},
|
|
||||||
"local_include_dirs": {"LOCAL_C_INCLUDES", prependLocalPath},
|
|
||||||
"export_include_dirs": {"LOCAL_EXPORT_C_INCLUDE_DIRS", prependLocalPath},
|
|
||||||
"suffix": {"LOCAL_MODULE_STEM", prependLocalModule},
|
|
||||||
"version_script": {"LOCAL_LDFLAGS", versionScript},
|
|
||||||
}
|
|
||||||
|
|
||||||
var ignoredProperties = map[string]bool{
|
|
||||||
"host_supported": true,
|
|
||||||
}
|
|
||||||
|
|
||||||
var moduleTypeToRule = map[string]string{
|
|
||||||
"cc_library_shared": "BUILD_SHARED_LIBRARY",
|
|
||||||
"cc_library_static": "BUILD_STATIC_LIBRARY",
|
|
||||||
"cc_library_host_shared": "BUILD_HOST_SHARED_LIBRARY",
|
|
||||||
"cc_library_host_static": "BUILD_HOST_STATIC_LIBRARY",
|
|
||||||
"cc_binary": "BUILD_EXECUTABLE",
|
|
||||||
"cc_binary_host": "BUILD_HOST_EXECUTABLE",
|
|
||||||
"cc_test": "BUILD_NATIVE_TEST",
|
|
||||||
"cc_test_host": "BUILD_HOST_NATIVE_TEST",
|
|
||||||
"cc_benchmark": "BUILD_NATIVE_BENCHMARK",
|
|
||||||
"cc_benchmark_host": "BUILD_HOST_NATIVE_BENCHMARK",
|
|
||||||
"java_library": "BUILD_JAVA_LIBRARY",
|
|
||||||
"java_library_static": "BUILD_STATIC_JAVA_LIBRARY",
|
|
||||||
"java_library_host": "BUILD_HOST_JAVA_LIBRARY",
|
|
||||||
"java_library_host_dalvik": "BUILD_HOST_DALVIK_JAVA_LIBRARY",
|
|
||||||
"android_app": "BUILD_PACKAGE",
|
|
||||||
"prebuilt": "BUILD_PREBUILT",
|
|
||||||
}
|
|
||||||
|
|
||||||
var ignoredModuleType = map[string]bool{
|
|
||||||
"bootstrap_go_binary": true,
|
|
||||||
"bootstrap_go_package": true,
|
|
||||||
"toolchain_library": true,
|
|
||||||
}
|
|
||||||
|
|
||||||
var suffixProperties = map[string]map[string]string{
|
|
||||||
"multilib": {"lib32": "32", "lib64": "64"},
|
|
||||||
"arch": {"arm": "arm", "arm64": "arm64", "mips": "mips", "mips64": "mips64",
|
|
||||||
"x86": "x86", "x86_64": "x86_64"},
|
|
||||||
}
|
|
||||||
|
|
||||||
var cpuVariantConditionals = map[string]struct {
|
|
||||||
conditional string
|
|
||||||
suffix string
|
|
||||||
secondArch bool
|
|
||||||
}{
|
|
||||||
"armv5te": {"ifeq ($(TARGET_ARCH_VARIANT),armv5te)", "$(TARGET_ARCH)", true},
|
|
||||||
"armv7_a": {"ifeq ($(TARGET_ARCH_VARIANT),armv7-a)", "$(TARGET_ARCH)", true},
|
|
||||||
"armv7_a_neon": {"ifeq ($(TARGET_ARCH_VARIANT),armv7-a-neon)", "$(TARGET_ARCH)", true},
|
|
||||||
"cortex_a7": {"ifeq ($(TARGET_CPU_VARIANT),cortex-a7)", "$(TARGET_ARCH)", true},
|
|
||||||
"cortex_a8": {"ifeq ($(TARGET_CPU_VARIANT),cortex-a8)", "$(TARGET_ARCH)", true},
|
|
||||||
"cortex_a9": {"ifeq ($(TARGET_CPU_VARIANT),cortex-a9)", "$(TARGET_ARCH)", true},
|
|
||||||
"cortex_a15": {"ifeq ($(TARGET_CPU_VARIANT),cortex-a15)", "$(TARGET_ARCH)", true},
|
|
||||||
"krait": {"ifeq ($(TARGET_CPU_VARIANT),krait)", "$(TARGET_ARCH)", true},
|
|
||||||
"denver": {"ifeq ($(TARGET_CPU_VARIANT),denver)", "$(TARGET_ARCH)", true},
|
|
||||||
"denver64": {"ifeq ($(TARGET_CPU_VARIANT),denver64)", "$(TARGET_ARCH)", true},
|
|
||||||
"mips_rev6": {"ifdef ARCH_MIPS_REV6", "mips", false},
|
|
||||||
"atom": {"ifeq ($(TARGET_ARCH_VARIANT),atom)", "$(TARGET_ARCH)", true},
|
|
||||||
"silvermont": {"ifeq ($(TARGET_ARCH_VARIANT),silvermont)", "$(TARGET_ARCH)", true},
|
|
||||||
"x86_ssse3": {"ifeq ($(ARCH_X86_HAVE_SSSE3),true)", "x86", false},
|
|
||||||
"x86_sse4": {"ifeq ($(ARCH_X86_HAVE_SSE4),true)", "x86", false},
|
|
||||||
}
|
|
||||||
|
|
||||||
var hostScopedPropertyConditionals = map[string]string{
|
|
||||||
"host": "",
|
|
||||||
"darwin": "ifeq ($(HOST_OS), darwin)",
|
|
||||||
"not_darwin": "ifneq ($(HOST_OS), darwin)",
|
|
||||||
"windows": "ifeq ($(HOST_OS), windows)",
|
|
||||||
"not_windows": "ifneq ($(HOST_OS), windows)",
|
|
||||||
"linux": "ifeq ($(HOST_OS), linux)",
|
|
||||||
"not_linux": "ifneq ($(HOST_OS), linux)",
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: host target?
|
|
||||||
var targetScopedPropertyConditionals = map[string]string{
|
|
||||||
"android": "",
|
|
||||||
"android32": "ifneq ($(TARGET_IS_64_BIT), true)",
|
|
||||||
"not_android32": "ifeq ($(TARGET_IS_64_BIT), true)",
|
|
||||||
"android64": "ifeq ($(TARGET_IS_64_BIT), true)",
|
|
||||||
"not_android64": "ifneq ($(TARGET_IS_64_BIT), true)",
|
|
||||||
}
|
|
||||||
|
|
||||||
var disabledHostConditionals = map[string]string{
|
|
||||||
"darwin": "ifneq ($(HOST_OS), darwin)",
|
|
||||||
"not_darwin": "ifeq ($(HOST_OS), darwin)",
|
|
||||||
"windows": "ifneq ($(HOST_OS), windows)",
|
|
||||||
"not_windows": "ifeq ($(HOST_OS), windows)",
|
|
||||||
"linux": "ifneq ($(HOST_OS), linux)",
|
|
||||||
"not_linux": "ifeq ($(HOST_OS), linux)",
|
|
||||||
}
|
|
||||||
|
|
||||||
var disabledTargetConditionals = map[string]string{
|
|
||||||
"android32": "ifeq ($(TARGET_IS_64_BIT), true)",
|
|
||||||
"not_android32": "ifeq ($(TARGET_IS_64_BIT), false)",
|
|
||||||
"android64": "ifeq ($(TARGET_IS_64_BIT), false)",
|
|
||||||
"not_android64": "ifeq ($(TARGET_IS_64_BIT), true)",
|
|
||||||
}
|
|
||||||
|
|
||||||
var targetToHostModuleRule = map[string]string{
|
|
||||||
"BUILD_SHARED_LIBRARY": "BUILD_HOST_SHARED_LIBRARY",
|
|
||||||
"BUILD_STATIC_LIBRARY": "BUILD_HOST_STATIC_LIBRARY",
|
|
||||||
"BUILD_EXECUTABLE": "BUILD_HOST_EXECUTABLE",
|
|
||||||
"BUILD_NATIVE_TEST": "BUILD_HOST_NATIVE_TEST",
|
|
||||||
"BUILD_JAVA_LIBRARY": "BUILD_HOST_JAVA_LIBRARY",
|
|
||||||
}
|
|
||||||
|
|
||||||
var productVariableConditionals = map[string]struct{ conditional, value string }{
|
|
||||||
"device_uses_jemalloc": {"ifneq ($(MALLOC_IMPL),dlmalloc)", ""},
|
|
||||||
"device_uses_dlmalloc": {"ifeq ($(MALLOC_IMPL),dlmalloc)", ""},
|
|
||||||
"device_uses_logd": {"ifneq ($(TARGET_USES_LOGD),false)", ""},
|
|
||||||
"dlmalloc_alignment": {"ifdef DLMALLOC_ALIGNMENT", "$(DLMALLOC_ALIGNMENT)"},
|
|
||||||
}
|
|
@@ -15,8 +15,6 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/google/blueprint"
|
"github.com/google/blueprint"
|
||||||
_ "github.com/google/blueprint/bootstrap"
|
_ "github.com/google/blueprint/bootstrap"
|
||||||
)
|
)
|
||||||
@@ -29,14 +27,6 @@ var (
|
|||||||
|
|
||||||
srcDir = pctx.VariableConfigMethod("srcDir", Config.SrcDir)
|
srcDir = pctx.VariableConfigMethod("srcDir", Config.SrcDir)
|
||||||
|
|
||||||
androidbpCmd = filepath.Join("${bootstrap.BinDir}", "androidbp")
|
|
||||||
androidbp = pctx.StaticRule("androidbp",
|
|
||||||
blueprint.RuleParams{
|
|
||||||
Command: androidbpCmd + " ${srcDir}/Android.bp $in $out",
|
|
||||||
CommandDeps: []string{androidbpCmd},
|
|
||||||
Description: "androidbp $out",
|
|
||||||
})
|
|
||||||
|
|
||||||
// A phony rule that is not the built-in Ninja phony rule. The built-in
|
// A phony rule that is not the built-in Ninja phony rule. The built-in
|
||||||
// phony rule has special behavior that is sometimes not desired. See the
|
// phony rule has special behavior that is sometimes not desired. See the
|
||||||
// Ninja docs for more details.
|
// Ninja docs for more details.
|
||||||
|
@@ -18,8 +18,6 @@ import (
|
|||||||
"android/soong"
|
"android/soong"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"android/soong/glob"
|
"android/soong/glob"
|
||||||
|
|
||||||
@@ -544,45 +542,4 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx blueprint.SingletonConte
|
|||||||
Optional: true,
|
Optional: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create Android.bp->mk translation rules
|
|
||||||
androidMks := []string{}
|
|
||||||
srcDir := ctx.Config().(Config).SrcDir()
|
|
||||||
intermediatesDir := filepath.Join(ctx.Config().(Config).IntermediatesDir(), "androidmk")
|
|
||||||
sort.Strings(bpFiles)
|
|
||||||
for _, origBp := range bpFiles {
|
|
||||||
bpFile := filepath.Join(srcDir, origBp)
|
|
||||||
mkFile := filepath.Join(srcDir, filepath.Dir(origBp), "Android.mk")
|
|
||||||
|
|
||||||
files, err := Glob(ctx, intermediatesDir, mkFile, nil)
|
|
||||||
if err != nil {
|
|
||||||
ctx.Errorf("glob: %s", err.Error())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Existing Android.mk file, use that instead
|
|
||||||
if len(files) > 0 {
|
|
||||||
for _, file := range files {
|
|
||||||
ctx.AddNinjaFileDeps(file)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
transMk := filepath.Join("androidmk", "Android_"+strings.Replace(filepath.Dir(origBp), "/", "_", -1)+".mk")
|
|
||||||
ctx.Build(pctx, blueprint.BuildParams{
|
|
||||||
Rule: androidbp,
|
|
||||||
Outputs: []string{transMk},
|
|
||||||
Inputs: []string{bpFile},
|
|
||||||
Optional: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
androidMks = append(androidMks, transMk)
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.Build(pctx, blueprint.BuildParams{
|
|
||||||
Rule: blueprint.Phony,
|
|
||||||
Outputs: []string{"androidmk"},
|
|
||||||
Implicits: androidMks,
|
|
||||||
Optional: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user