Initial androidbp translator.

Translates Android.bp files back to Android.mk

Change-Id: Ib4bd1e0abc58ab514a7dd4a01008af645d6a3d13
This commit is contained in:
Andres Morales 2015-04-29 12:46:49 -07:00
parent 3d7678f9d6
commit da8706fed8
4 changed files with 315 additions and 4 deletions

View File

@ -182,6 +182,17 @@ bootstrap_go_package {
],
}
bootstrap_go_binary {
name: "androidbp",
srcs: [
"androidbp/cmd/androidbp.go",
"androidbp/cmd/soong.go",
],
deps: [
"blueprint-parser",
],
}
//
// C static libraries extracted from the gcc toolchain
//

195
androidbp/cmd/androidbp.go Normal file
View File

@ -0,0 +1,195 @@
package main
import (
"bufio"
"fmt"
"os"
"path"
"strings"
bpparser "github.com/google/blueprint/parser"
)
type androidMkWriter struct {
*bufio.Writer
file *bpparser.File
path string
}
func (w *androidMkWriter) valueToString(value bpparser.Value) string {
if value.Variable != "" {
return fmt.Sprintf("$(%s)", value.Variable)
} else {
switch value.Type {
case bpparser.Bool:
return fmt.Sprintf(`"%t"`, value.BoolValue)
case bpparser.String:
return fmt.Sprintf(`"%s"`, value.StringValue)
case bpparser.List:
return fmt.Sprintf("\\\n%s\n", w.listToMkString(value.ListValue))
case bpparser.Map:
w.errorf("maps not supported in assignment")
return "ERROR: unsupported type map in assignment"
}
}
return ""
}
func (w *androidMkWriter) listToMkString(list []bpparser.Value) string {
lines := make([]string, 0, len(list))
for _, tok := range list {
lines = append(lines, fmt.Sprintf("\t\"%s\"", tok.StringValue))
}
return strings.Join(lines, " \\\n")
}
func (w *androidMkWriter) errorf(format string, values ...interface{}) {
s := fmt.Sprintf(format, values)
w.WriteString("# ANDROIDBP ERROR:\n")
for _, line := range strings.Split(s, "\n") {
fmt.Fprintf(w, "# %s\n", line)
}
}
func (w *androidMkWriter) handleComment(comment *bpparser.Comment) {
for _, c := range comment.Comment {
mkComment := strings.Replace(c, "//", "#", 1)
// TODO: handle /* comments?
fmt.Fprintf(w, "%s\n", mkComment)
}
}
func (w *androidMkWriter) handleModule(module *bpparser.Module) {
if moduleName, ok := moduleTypes[module.Type.Name]; ok {
w.WriteString("include $(CLEAR_VARS)\n")
standardProps := make([]string, 0, len(module.Properties))
//condProps := make([]string, len(module.Properties))
for _, prop := range module.Properties {
if mkProp, ok := standardProperties[prop.Name.Name]; ok {
standardProps = append(standardProps, fmt.Sprintf("%s := %s", mkProp.string,
w.valueToString(prop.Value)))
}
}
mkModule := strings.Join(standardProps, "\n")
w.WriteString(mkModule)
fmt.Fprintf(w, "include $(%s)\n\n", moduleName)
} else {
w.errorf("Unsupported module %s", module.Type.Name)
}
}
func (w *androidMkWriter) handleAssignment(assignment *bpparser.Assignment) {
assigner := ":="
if assignment.Assigner != "=" {
assigner = assignment.Assigner
}
fmt.Fprintf(w, "%s %s %s\n", assignment.Name.Name, assigner,
w.valueToString(assignment.OrigValue))
}
func (w *androidMkWriter) iter() <-chan interface{} {
ch := make(chan interface{}, len(w.file.Comments)+len(w.file.Defs))
go func() {
commIdx := 0
defsIdx := 0
for defsIdx < len(w.file.Defs) || commIdx < len(w.file.Comments) {
if defsIdx == len(w.file.Defs) {
ch <- w.file.Comments[commIdx]
commIdx++
} else if commIdx == len(w.file.Comments) {
ch <- w.file.Defs[defsIdx]
defsIdx++
} else {
commentsPos := 0
defsPos := 0
def := w.file.Defs[defsIdx]
switch def := def.(type) {
case *bpparser.Module:
defsPos = def.LbracePos.Line
case *bpparser.Assignment:
defsPos = def.Pos.Line
}
comment := w.file.Comments[commIdx]
commentsPos = comment.Pos.Line
if commentsPos < defsPos {
commIdx++
ch <- comment
} else {
defsIdx++
ch <- def
}
}
}
close(ch)
}()
return ch
}
func (w *androidMkWriter) write() {
outFilePath := fmt.Sprintf("%s/Android.mk.out", w.path)
fmt.Printf("Writing %s\n", outFilePath)
f, err := os.Create(outFilePath)
if err != nil {
panic(err)
}
defer func() {
if err := f.Close(); err != nil {
panic(err)
}
}()
w.Writer = bufio.NewWriter(f)
for block := range w.iter() {
switch block := block.(type) {
case *bpparser.Module:
w.handleModule(block)
case *bpparser.Assignment:
w.handleAssignment(block)
case bpparser.Comment:
w.handleComment(&block)
}
}
if err = w.Flush(); err != nil {
panic(err)
}
}
func main() {
if len(os.Args) < 2 {
fmt.Println("No filename supplied")
return
}
reader, err := os.Open(os.Args[1])
if err != nil {
fmt.Println(err.Error())
return
}
scope := bpparser.NewScope(nil)
file, errs := bpparser.Parse(os.Args[1], reader, scope)
if len(errs) > 0 {
fmt.Println("%d errors parsing %s", len(errs), os.Args[1])
fmt.Println(errs)
return
}
writer := &androidMkWriter{
file: file,
path: path.Dir(os.Args[1]),
}
writer.write()
}

80
androidbp/cmd/soong.go Normal file
View File

@ -0,0 +1,80 @@
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},
"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},
"include_dirs": {"LOCAL_C_INCLUDES", bpparser.List},
"export_include_dirs": {"LOCAL_EXPORT_C_INCLUDE_DIRS", 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": {"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},
}
var moduleTypes = 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",
"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",
}

View File

@ -48,6 +48,30 @@ rule g.bootstrap.link
command = GOROOT='${g.bootstrap.goRoot}' ${g.bootstrap.linkCmd} -o ${out} ${libDirFlags} ${in}
description = ${g.bootstrap.goChar}l ${out}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Module: androidbp
# Variant:
# Type: bootstrap_go_binary
# Factory: github.com/google/blueprint/bootstrap.newGoBinaryModule
# Defined: build/soong/Blueprints:183:1
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.gcCmd} $
.bootstrap/blueprint-parser/pkg/github.com/google/blueprint/parser.a
incFlags = -I .bootstrap/blueprint-parser/pkg
pkgPath = androidbp
default .bootstrap/androidbp/obj/androidbp.a
build .bootstrap/androidbp/obj/a.out: g.bootstrap.link $
.bootstrap/androidbp/obj/androidbp.a | ${g.bootstrap.linkCmd}
libDirFlags = -L .bootstrap/blueprint-parser/pkg
default .bootstrap/androidbp/obj/a.out
build .bootstrap/bin/androidbp: g.bootstrap.cp .bootstrap/androidbp/obj/a.out
default .bootstrap/bin/androidbp
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Module: androidmk
# Variant:
@ -565,10 +589,11 @@ rule s.bootstrap.minibp
generator = true
build .bootstrap/main.ninja.in: s.bootstrap.bigbp $
${g.bootstrap.srcDir}/Blueprints | .bootstrap/bin/androidmk $
.bootstrap/bin/bpfmt .bootstrap/bin/bpmodify .bootstrap/bin/minibp $
.bootstrap/bin/soong_build .bootstrap/bin/soong_env $
.bootstrap/bin/soong_glob .bootstrap/bin/soong_jar
${g.bootstrap.srcDir}/Blueprints | .bootstrap/bin/androidbp $
.bootstrap/bin/androidmk .bootstrap/bin/bpfmt .bootstrap/bin/bpmodify $
.bootstrap/bin/minibp .bootstrap/bin/soong_build $
.bootstrap/bin/soong_env .bootstrap/bin/soong_glob $
.bootstrap/bin/soong_jar
default .bootstrap/main.ninja.in
build .bootstrap/notAFile: phony
default .bootstrap/notAFile