aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2018-05-06 07:24:19 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2018-05-06 07:24:19 +0000
commit5709ccd0251e4806cf826a1472c6292ebb3a9790 (patch)
treec1dea294b0305d7414dc5ea08f86bc34be9ac2cd
parent8ff139ee3ad0de6f109e8ed10da84756858dae87 (diff)
parent7f9b6fbeece0867c8f027fb5cafafab25cc4f5c6 (diff)
downloadbuild_soong-5709ccd0251e4806cf826a1472c6292ebb3a9790.tar.gz
build_soong-5709ccd0251e4806cf826a1472c6292ebb3a9790.tar.bz2
build_soong-5709ccd0251e4806cf826a1472c6292ebb3a9790.zip
Snap for 4765094 from 7f9b6fbeece0867c8f027fb5cafafab25cc4f5c6 to pi-release
Change-Id: I309dd62ddbb35e39810f36e4545a7eee6d384daa
-rw-r--r--Android.bp4
-rw-r--r--androidmk/cmd/androidmk/android.go15
-rw-r--r--androidmk/cmd/androidmk/androidmk.go3
-rw-r--r--androidmk/cmd/androidmk/androidmk_test.go74
-rw-r--r--bpfix/bpfix/bpfix.go263
-rw-r--r--bpfix/bpfix/bpfix_test.go134
-rw-r--r--bpfix/cmd/bpfix.go3
-rw-r--r--cc/cc_test.go2
-rw-r--r--cmd/extract_jar_packages/Android.bp25
-rw-r--r--cmd/extract_jar_packages/extract_jar_packages.go88
-rw-r--r--cmd/extract_linker/main.go8
-rw-r--r--cmd/pom2bp/Android.bp22
-rw-r--r--cmd/pom2bp/pom2bp.go495
-rw-r--r--cmd/pom2mk/pom2mk.go2
-rw-r--r--cmd/zipsync/zipsync.go4
-rw-r--r--java/aapt2.go16
-rw-r--r--java/aar.go379
-rw-r--r--java/android_resources.go127
-rw-r--r--java/androidmk.go27
-rw-r--r--java/app.go351
-rw-r--r--java/app_builder.go36
-rw-r--r--java/app_test.go117
-rw-r--r--java/config/config.go1
-rw-r--r--java/config/makevars.go2
-rw-r--r--java/java.go17
-rw-r--r--java/java_resources.go (renamed from java/resources.go)0
-rw-r--r--java/java_test.go1
-rw-r--r--java/support_libraries.go66
-rw-r--r--ui/logger/logger.go2
-rw-r--r--ui/logger/logger_test.go2
30 files changed, 1840 insertions, 446 deletions
diff --git a/Android.bp b/Android.bp
index 68370d84..e9b1ebe0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -219,6 +219,7 @@ bootstrap_go_package {
srcs: [
"java/aapt2.go",
"java/aar.go",
+ "java/android_resources.go",
"java/androidmk.go",
"java/app_builder.go",
"java/app.go",
@@ -229,8 +230,9 @@ bootstrap_go_package {
"java/genrule.go",
"java/jacoco.go",
"java/java.go",
+ "java/java_resources.go",
"java/proto.go",
- "java/resources.go",
+ "java/support_libraries.go",
"java/system_modules.go",
],
testSrcs: [
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index 5196754e..5cb4869c 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -64,6 +64,9 @@ var rewriteProperties = map[string](func(variableAssignmentContext) error){
"LOCAL_MODULE_SUFFIX": skip, // TODO
"LOCAL_PATH": skip, // Nothing to do, except maybe avoid the "./" in paths?
"LOCAL_PRELINK_MODULE": skip, // Already phased out
+ "LOCAL_BUILT_MODULE_STEM": skip,
+ "LOCAL_USE_AAPT2": skip, // Always enabled in Soong
+ "LOCAL_JAR_EXCLUDE_FILES": skip, // Soong never excludes files from jars
}
// adds a group of properties all having the same type
@@ -94,6 +97,7 @@ func init() {
"LOCAL_NOTICE_FILE": "notice",
"LOCAL_JAVA_LANGUAGE_VERSION": "java_version",
"LOCAL_INSTRUMENTATION_FOR": "instrumentation_for",
+ "LOCAL_MANIFEST_FILE": "manifest",
"LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING": "dex_preopt.profile",
})
@@ -128,6 +132,7 @@ func init() {
"LOCAL_RENDERSCRIPT_FLAGS": "renderscript.flags",
"LOCAL_JAVA_RESOURCE_DIRS": "java_resource_dirs",
+ "LOCAL_RESOURCE_DIR": "resource_dirs",
"LOCAL_JAVACFLAGS": "javacflags",
"LOCAL_ERROR_PRONE_FLAGS": "errorprone.javacflags",
"LOCAL_DX_FLAGS": "dxflags",
@@ -142,7 +147,13 @@ func init() {
"LOCAL_PROGUARD_FLAGS": "optimize.proguard_flags",
"LOCAL_PROGUARD_FLAG_FILES": "optimize.proguard_flag_files",
+
+ // These will be rewritten to libs/static_libs by bpfix, after their presence is used to convert
+ // java_library_static to android_library.
+ "LOCAL_SHARED_ANDROID_LIBRARIES": "android_libs",
+ "LOCAL_STATIC_ANDROID_LIBRARIES": "android_static_libs",
})
+
addStandardProperties(bpparser.BoolType,
map[string]string{
// Bool properties
@@ -259,7 +270,7 @@ func classifyLocalOrGlobalPath(value bpparser.Expression) (string, bpparser.Expr
}
case *bpparser.Operator:
if v.Type() != bpparser.StringType {
- return "", nil, fmt.Errorf("classifyLocalOrGlobalPath expected a string, got %s", value.Type)
+ return "", nil, fmt.Errorf("classifyLocalOrGlobalPath expected a string, got %s", v.Type())
}
if v.Operator != '+' {
@@ -290,7 +301,7 @@ func classifyLocalOrGlobalPath(value bpparser.Expression) (string, bpparser.Expr
case *bpparser.String:
return "global", value, nil
default:
- return "", nil, fmt.Errorf("classifyLocalOrGlobalPath expected a string, got %s", value.Type)
+ return "", nil, fmt.Errorf("classifyLocalOrGlobalPath expected a string, got %s", v.Type())
}
}
diff --git a/androidmk/cmd/androidmk/androidmk.go b/androidmk/cmd/androidmk/androidmk.go
index 6e0b474b..b6a973c0 100644
--- a/androidmk/cmd/androidmk/androidmk.go
+++ b/androidmk/cmd/androidmk/androidmk.go
@@ -239,7 +239,8 @@ func convertFile(filename string, buffer *bytes.Buffer) (string, []error) {
}
// check for common supported but undesirable structures and clean them up
- err := bpfix.FixTree(tree, bpfix.NewFixRequest().AddAll())
+ fixer := bpfix.NewFixer(tree)
+ tree, err := fixer.Fix(bpfix.NewFixRequest().AddAll())
if err != nil {
return "", []error{err}
}
diff --git a/androidmk/cmd/androidmk/androidmk_test.go b/androidmk/cmd/androidmk/androidmk_test.go
index 45df1a57..edf3d42f 100644
--- a/androidmk/cmd/androidmk/androidmk_test.go
+++ b/androidmk/cmd/androidmk/androidmk_test.go
@@ -17,11 +17,10 @@ package main
import (
"bytes"
"fmt"
- "os"
"strings"
"testing"
- bpparser "github.com/google/blueprint/parser"
+ "android/soong/bpfix/bpfix"
)
var testCases = []struct {
@@ -498,6 +497,7 @@ include $(call all-makefiles-under,$(LOCAL_PATH))
include $(CLEAR_VARS)
LOCAL_SRC_FILES := test.jar
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+ LOCAL_STATIC_ANDROID_LIBRARIES :=
include $(BUILD_PREBUILT)
`,
expected: `
@@ -522,28 +522,68 @@ include $(call all-makefiles-under,$(LOCAL_PATH))
}
`,
},
-}
-func reformatBlueprint(input string) string {
- file, errs := bpparser.Parse("<testcase>", bytes.NewBufferString(input), bpparser.NewScope(nil))
- if len(errs) > 0 {
- for _, err := range errs {
- fmt.Fprintln(os.Stderr, err)
- }
- panic(fmt.Sprintf("%d parsing errors in testcase:\n%s", len(errs), input))
- }
+ {
+ desc: "aar",
+ in: `
+ include $(CLEAR_VARS)
+ LOCAL_SRC_FILES := test.java
+ LOCAL_RESOURCE_DIR := res
+ include $(BUILD_STATIC_JAVA_LIBRARY)
- res, err := bpparser.Print(file)
- if err != nil {
- panic(fmt.Sprintf("Error printing testcase: %q", err))
- }
+ include $(CLEAR_VARS)
+ LOCAL_SRC_FILES := test.java
+ LOCAL_STATIC_LIBRARIES := foo
+ LOCAL_STATIC_ANDROID_LIBRARIES := bar
+ include $(BUILD_STATIC_JAVA_LIBRARY)
+
+ include $(CLEAR_VARS)
+ LOCAL_SRC_FILES := test.java
+ LOCAL_SHARED_LIBRARIES := foo
+ LOCAL_SHARED_ANDROID_LIBRARIES := bar
+ include $(BUILD_STATIC_JAVA_LIBRARY)
- return string(res)
+ include $(CLEAR_VARS)
+ LOCAL_SRC_FILES := test.java
+ LOCAL_STATIC_ANDROID_LIBRARIES :=
+ include $(BUILD_STATIC_JAVA_LIBRARY)
+ `,
+ expected: `
+ android_library {
+ srcs: ["test.java"],
+ resource_dirs: ["res"],
+ }
+
+ android_library {
+ srcs: ["test.java"],
+ static_libs: [
+ "foo",
+ "bar",
+ ],
+ }
+
+ android_library {
+ srcs: ["test.java"],
+ libs: [
+ "foo",
+ "bar",
+ ],
+ }
+
+ java_library_static {
+ srcs: ["test.java"],
+ static_libs: [],
+ }
+ `,
+ },
}
func TestEndToEnd(t *testing.T) {
for i, test := range testCases {
- expected := reformatBlueprint(test.expected)
+ expected, err := bpfix.Reformat(test.expected)
+ if err != nil {
+ t.Error(err)
+ }
got, errs := convertFile(fmt.Sprintf("<testcase %d>", i), bytes.NewBufferString(test.in))
if len(errs) > 0 {
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index 84454907..e4d4e34e 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -18,17 +18,36 @@ package bpfix
import (
"bytes"
+ "errors"
"fmt"
+ "io"
"path/filepath"
"github.com/google/blueprint/parser"
)
+// Reformat takes a blueprint file as a string and returns a formatted version
+func Reformat(input string) (string, error) {
+ tree, err := parse("<string>", bytes.NewBufferString(input))
+ if err != nil {
+ return "", err
+ }
+
+ res, err := parser.Print(tree)
+ if err != nil {
+ return "", err
+ }
+
+ return string(res), nil
+}
+
// A FixRequest specifies the details of which fixes to apply to an individual file
// A FixRequest doesn't specify whether to do a dry run or where to write the results; that's in cmd/bpfix.go
type FixRequest struct {
- simplifyKnownRedundantVariables bool
- rewriteIncorrectAndroidmkPrebuilts bool
+ simplifyKnownRedundantVariables bool
+ rewriteIncorrectAndroidmkPrebuilts bool
+ rewriteIncorrectAndroidmkAndroidLibraries bool
+ mergeMatchingModuleProperties bool
}
func NewFixRequest() FixRequest {
@@ -39,24 +58,39 @@ func (r FixRequest) AddAll() (result FixRequest) {
result = r
result.simplifyKnownRedundantVariables = true
result.rewriteIncorrectAndroidmkPrebuilts = true
+ result.rewriteIncorrectAndroidmkAndroidLibraries = true
+ result.mergeMatchingModuleProperties = true
return result
}
-// FixTree repeatedly applies the fixes listed in the given FixRequest to the given File
+type Fixer struct {
+ tree *parser.File
+}
+
+func NewFixer(tree *parser.File) *Fixer {
+ fixer := &Fixer{tree}
+
+ // make a copy of the tree
+ fixer.reparse()
+
+ return fixer
+}
+
+// Fix repeatedly applies the fixes listed in the given FixRequest to the given File
// until there is no fix that affects the tree
-func FixTree(tree *parser.File, config FixRequest) error {
- prevIdentifier, err := fingerprint(tree)
+func (f *Fixer) Fix(config FixRequest) (*parser.File, error) {
+ prevIdentifier, err := f.fingerprint()
if err != nil {
- return err
+ return nil, err
}
maxNumIterations := 20
i := 0
for {
- err = fixTreeOnce(tree, config)
- newIdentifier, err := fingerprint(tree)
+ err = f.fixTreeOnce(config)
+ newIdentifier, err := f.fingerprint()
if err != nil {
- return err
+ return nil, err
}
if bytes.Equal(newIdentifier, prevIdentifier) {
break
@@ -67,31 +101,70 @@ func FixTree(tree *parser.File, config FixRequest) error {
// detect infinite loop
i++
if i >= maxNumIterations {
- return fmt.Errorf("Applied fixes %s times and yet the tree continued to change. Is there an infinite loop?", i)
+ return nil, fmt.Errorf("Applied fixes %d times and yet the tree continued to change. Is there an infinite loop?", i)
break
}
}
- return err
+ return f.tree, err
}
// returns a unique identifier for the given tree that can be used to determine whether the tree changed
-func fingerprint(tree *parser.File) (fingerprint []byte, err error) {
- bytes, err := parser.Print(tree)
+func (f *Fixer) fingerprint() (fingerprint []byte, err error) {
+ bytes, err := parser.Print(f.tree)
if err != nil {
return nil, err
}
return bytes, nil
}
-func fixTreeOnce(tree *parser.File, config FixRequest) error {
+func (f *Fixer) reparse() ([]byte, error) {
+ buf, err := parser.Print(f.tree)
+ if err != nil {
+ return nil, err
+ }
+ newTree, err := parse(f.tree.Name, bytes.NewReader(buf))
+ if err != nil {
+ return nil, err
+ }
+ f.tree = newTree
+ return buf, nil
+}
+
+func parse(name string, r io.Reader) (*parser.File, error) {
+ tree, errs := parser.Parse(name, r, parser.NewScope(nil))
+ if errs != nil {
+ s := "parse error: "
+ for _, err := range errs {
+ s += "\n" + err.Error()
+ }
+ return nil, errors.New(s)
+ }
+ return tree, nil
+}
+
+func (f *Fixer) fixTreeOnce(config FixRequest) error {
if config.simplifyKnownRedundantVariables {
- err := simplifyKnownPropertiesDuplicatingEachOther(tree)
+ err := f.simplifyKnownPropertiesDuplicatingEachOther()
if err != nil {
return err
}
}
if config.rewriteIncorrectAndroidmkPrebuilts {
- err := rewriteIncorrectAndroidmkPrebuilts(tree)
+ err := f.rewriteIncorrectAndroidmkPrebuilts()
+ if err != nil {
+ return err
+ }
+ }
+
+ if config.rewriteIncorrectAndroidmkAndroidLibraries {
+ err := f.rewriteIncorrectAndroidmkAndroidLibraries()
+ if err != nil {
+ return err
+ }
+ }
+
+ if config.mergeMatchingModuleProperties {
+ err := f.mergeMatchingModuleProperties()
if err != nil {
return err
}
@@ -99,13 +172,13 @@ func fixTreeOnce(tree *parser.File, config FixRequest) error {
return nil
}
-func simplifyKnownPropertiesDuplicatingEachOther(tree *parser.File) error {
+func (f *Fixer) simplifyKnownPropertiesDuplicatingEachOther() error {
// remove from local_include_dirs anything in export_include_dirs
- return removeMatchingModuleListProperties(tree, "export_include_dirs", "local_include_dirs")
+ return f.removeMatchingModuleListProperties("export_include_dirs", "local_include_dirs")
}
-func rewriteIncorrectAndroidmkPrebuilts(tree *parser.File) error {
- for _, def := range tree.Defs {
+func (f *Fixer) rewriteIncorrectAndroidmkPrebuilts() error {
+ for _, def := range f.tree.Defs {
mod, ok := def.(*parser.Module)
if !ok {
continue
@@ -127,6 +200,7 @@ func rewriteIncorrectAndroidmkPrebuilts(tree *parser.File) error {
switch filepath.Ext(src.Value) {
case ".jar":
renameProperty(mod, "srcs", "jars")
+
case ".aar":
renameProperty(mod, "srcs", "aars")
mod.Type = "android_library_import"
@@ -139,6 +213,146 @@ func rewriteIncorrectAndroidmkPrebuilts(tree *parser.File) error {
return nil
}
+func (f *Fixer) rewriteIncorrectAndroidmkAndroidLibraries() error {
+ for _, def := range f.tree.Defs {
+ mod, ok := def.(*parser.Module)
+ if !ok {
+ continue
+ }
+
+ hasAndroidLibraries := hasNonEmptyLiteralListProperty(mod, "android_libs")
+ hasStaticAndroidLibraries := hasNonEmptyLiteralListProperty(mod, "android_static_libs")
+ hasResourceDirs := hasNonEmptyLiteralListProperty(mod, "resource_dirs")
+
+ if hasAndroidLibraries || hasStaticAndroidLibraries || hasResourceDirs {
+ if mod.Type == "java_library_static" {
+ mod.Type = "android_library"
+ }
+ }
+
+ if mod.Type == "java_import" && !hasStaticAndroidLibraries {
+ removeProperty(mod, "android_static_libs")
+ }
+
+ // These may conflict with existing libs and static_libs properties, but the
+ // mergeMatchingModuleProperties pass will fix it.
+ renameProperty(mod, "shared_libs", "libs")
+ renameProperty(mod, "android_libs", "libs")
+ renameProperty(mod, "android_static_libs", "static_libs")
+ }
+
+ return nil
+}
+
+func (f *Fixer) mergeMatchingModuleProperties() error {
+ // Make sure all the offsets are accurate
+ buf, err := f.reparse()
+ if err != nil {
+ return err
+ }
+
+ var patchlist parser.PatchList
+ for _, def := range f.tree.Defs {
+ mod, ok := def.(*parser.Module)
+ if !ok {
+ continue
+ }
+
+ err := mergeMatchingProperties(&mod.Properties, buf, &patchlist)
+ if err != nil {
+ return err
+ }
+ }
+
+ newBuf := new(bytes.Buffer)
+ err = patchlist.Apply(bytes.NewReader(buf), newBuf)
+ if err != nil {
+ return err
+ }
+
+ newTree, err := parse(f.tree.Name, newBuf)
+ if err != nil {
+ return err
+ }
+
+ f.tree = newTree
+
+ return nil
+}
+
+func mergeMatchingProperties(properties *[]*parser.Property, buf []byte, patchlist *parser.PatchList) error {
+ seen := make(map[string]*parser.Property)
+ for i := 0; i < len(*properties); i++ {
+ property := (*properties)[i]
+ if prev, exists := seen[property.Name]; exists {
+ err := mergeProperties(prev, property, buf, patchlist)
+ if err != nil {
+ return err
+ }
+ *properties = append((*properties)[:i], (*properties)[i+1:]...)
+ } else {
+ seen[property.Name] = property
+ if mapProperty, ok := property.Value.(*parser.Map); ok {
+ err := mergeMatchingProperties(&mapProperty.Properties, buf, patchlist)
+ if err != nil {
+ return err
+ }
+ }
+ }
+ }
+ return nil
+}
+
+func mergeProperties(a, b *parser.Property, buf []byte, patchlist *parser.PatchList) error {
+ if a.Value.Type() != b.Value.Type() {
+ return fmt.Errorf("type mismatch when merging properties %q: %s and %s", a.Name, a.Value.Type(), b.Value.Type())
+ }
+
+ switch a.Value.Type() {
+ case parser.StringType:
+ return fmt.Errorf("conflicting definitions of string property %q", a.Name)
+ case parser.ListType:
+ return mergeListProperties(a, b, buf, patchlist)
+ }
+
+ return nil
+}
+
+func mergeListProperties(a, b *parser.Property, buf []byte, patchlist *parser.PatchList) error {
+ aval, oka := a.Value.(*parser.List)
+ bval, okb := b.Value.(*parser.List)
+ if !oka || !okb {
+ // Merging expressions not supported yet
+ return nil
+ }
+
+ s := string(buf[bval.LBracePos.Offset+1 : bval.RBracePos.Offset])
+ if bval.LBracePos.Line != bval.RBracePos.Line {
+ if s[0] != '\n' {
+ panic("expected \n")
+ }
+ // If B is a multi line list, skip the first "\n" in case A already has a trailing "\n"
+ s = s[1:]
+ }
+ if aval.LBracePos.Line == aval.RBracePos.Line {
+ // A is a single line list with no trailing comma
+ if len(aval.Values) > 0 {
+ s = "," + s
+ }
+ }
+
+ err := patchlist.Add(aval.RBracePos.Offset, aval.RBracePos.Offset, s)
+ if err != nil {
+ return err
+ }
+ err = patchlist.Add(b.NamePos.Offset, b.End().Offset+2, "")
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
// removes from <items> every item present in <removals>
func filterExpressionList(items *parser.List, removals *parser.List) {
writeIndex := 0
@@ -163,8 +377,8 @@ func filterExpressionList(items *parser.List, removals *parser.List) {
}
// Remove each modules[i].Properties[<legacyName>][j] that matches a modules[i].Properties[<canonicalName>][k]
-func removeMatchingModuleListProperties(tree *parser.File, canonicalName string, legacyName string) error {
- for _, def := range tree.Defs {
+func (f *Fixer) removeMatchingModuleListProperties(canonicalName string, legacyName string) error {
+ for _, def := range f.tree.Defs {
mod, ok := def.(*parser.Module)
if !ok {
continue
@@ -182,6 +396,11 @@ func removeMatchingModuleListProperties(tree *parser.File, canonicalName string,
return nil
}
+func hasNonEmptyLiteralListProperty(mod *parser.Module, name string) bool {
+ list, found := getLiteralListProperty(mod, name)
+ return found && len(list.Values) > 0
+}
+
func getLiteralListProperty(mod *parser.Module, name string) (list *parser.List, found bool) {
prop, ok := mod.GetProperty(name)
if !ok {
diff --git a/bpfix/bpfix/bpfix_test.go b/bpfix/bpfix/bpfix_test.go
index e17e815a..51708eb6 100644
--- a/bpfix/bpfix/bpfix_test.go
+++ b/bpfix/bpfix/bpfix_test.go
@@ -17,6 +17,7 @@
package bpfix
import (
+ "bytes"
"fmt"
"strings"
"testing"
@@ -62,14 +63,16 @@ func implFilterListTest(t *testing.T, local_include_dirs []string, export_includ
t.Fatalf("%d parse errors", len(errs))
}
+ fixer := NewFixer(tree)
+
// apply simplifications
- err := simplifyKnownPropertiesDuplicatingEachOther(tree)
+ err := fixer.simplifyKnownPropertiesDuplicatingEachOther()
if len(errs) > 0 {
t.Fatal(err)
}
// lookup legacy property
- mod := tree.Defs[0].(*parser.Module)
+ mod := fixer.tree.Defs[0].(*parser.Module)
_, found := mod.GetProperty("local_include_dirs")
if !found {
t.Fatalf("failed to include key local_include_dirs in parse tree")
@@ -113,3 +116,130 @@ func TestSimplifyKnownVariablesDuplicatingEachOther(t *testing.T) {
implFilterListTest(t, []string{}, []string{"include"}, []string{})
implFilterListTest(t, []string{}, []string{}, []string{})
}
+
+func TestMergeMatchingProperties(t *testing.T) {
+ tests := []struct {
+ name string
+ in string
+ out string
+ }{
+ {
+ name: "empty",
+ in: `
+ java_library {
+ name: "foo",
+ static_libs: [],
+ static_libs: [],
+ }
+ `,
+ out: `
+ java_library {
+ name: "foo",
+ static_libs: [],
+ }
+ `,
+ },
+ {
+ name: "single line into multiline",
+ in: `
+ java_library {
+ name: "foo",
+ static_libs: [
+ "a",
+ "b",
+ ],
+ //c1
+ static_libs: ["c" /*c2*/],
+ }
+ `,
+ out: `
+ java_library {
+ name: "foo",
+ static_libs: [
+ "a",
+ "b",
+ "c", /*c2*/
+ ],
+ //c1
+ }
+ `,
+ },
+ {
+ name: "multiline into multiline",
+ in: `
+ java_library {
+ name: "foo",
+ static_libs: [
+ "a",
+ "b",
+ ],
+ //c1
+ static_libs: [
+ //c2
+ "c", //c3
+ "d",
+ ],
+ }
+ `,
+ out: `
+ java_library {
+ name: "foo",
+ static_libs: [
+ "a",
+ "b",
+ //c2
+ "c", //c3
+ "d",
+ ],
+ //c1
+ }
+ `,
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ expected, err := Reformat(test.out)
+ if err != nil {
+ t.Error(err)
+ }
+
+ in, err := Reformat(test.in)
+ if err != nil {
+ t.Error(err)
+ }
+
+ tree, errs := parser.Parse("<testcase>", bytes.NewBufferString(in), parser.NewScope(nil))
+ if errs != nil {
+ t.Fatal(errs)
+ }
+
+ fixer := NewFixer(tree)
+
+ got := ""
+ prev := "foo"
+ passes := 0
+ for got != prev && passes < 10 {
+ err := fixer.mergeMatchingModuleProperties()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ out, err := parser.Print(fixer.tree)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ prev = got
+ got = string(out)
+ passes++
+ }
+
+ if got != expected {
+ t.Errorf("failed testcase '%s'\ninput:\n%s\n\nexpected:\n%s\ngot:\n%s\n",
+ test.name, in, expected, got)
+ }
+
+ })
+ }
+}
diff --git a/bpfix/cmd/bpfix.go b/bpfix/cmd/bpfix.go
index 461f41dd..2fde3836 100644
--- a/bpfix/cmd/bpfix.go
+++ b/bpfix/cmd/bpfix.go
@@ -75,7 +75,8 @@ func processFile(filename string, in io.Reader, out io.Writer, fixRequest bpfix.
}
// compute and apply any requested fixes
- err = bpfix.FixTree(file, fixRequest)
+ fixer := bpfix.NewFixer(file)
+ file, err = fixer.Fix(fixRequest)
if err != nil {
return err
}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index a4e25349..10c1aba7 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -264,7 +264,7 @@ func checkVndkModule(t *testing.T, ctx *android.TestContext, name, subDir string
mod := ctx.ModuleForTests(name, vendorVariant).Module().(*Module)
if !mod.hasVendorVariant() {
- t.Error("%q must have vendor variant", name)
+ t.Errorf("%q must have vendor variant", name)
}
// Check library properties.
diff --git a/cmd/extract_jar_packages/Android.bp b/cmd/extract_jar_packages/Android.bp
new file mode 100644
index 00000000..ea0cbbf8
--- /dev/null
+++ b/cmd/extract_jar_packages/Android.bp
@@ -0,0 +1,25 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+blueprint_go_binary {
+ name: "extract_jar_packages",
+ deps: [
+ "android-archive-zip",
+ "blueprint-pathtools",
+ ],
+ srcs: [
+ "extract_jar_packages.go",
+ ],
+}
+
diff --git a/cmd/extract_jar_packages/extract_jar_packages.go b/cmd/extract_jar_packages/extract_jar_packages.go
new file mode 100644
index 00000000..fca308ff
--- /dev/null
+++ b/cmd/extract_jar_packages/extract_jar_packages.go
@@ -0,0 +1,88 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "archive/zip"
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+)
+
+var (
+ outputFile = flag.String("o", "", "output file")
+ prefix = flag.String("prefix", "", "prefix for each entry in the output file")
+ inputFile = flag.String("i", "", "input jar or srcjar")
+)
+
+func must(err error) {
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+func fileToPackage(file string) string {
+ dir := filepath.Dir(file)
+ return strings.Replace(dir, "/", ".", -1)
+}
+
+func main() {
+ flag.Usage = func() {
+ fmt.Fprintln(os.Stderr, "usage: extract_jar_packages -i <input file> -o <output -file> [-prefix <prefix>]")
+ flag.PrintDefaults()
+ }
+
+ flag.Parse()
+
+ if *outputFile == "" || *inputFile == "" {
+ flag.Usage()
+ os.Exit(1)
+ }
+
+ pkgSet := make(map[string]bool)
+
+ reader, err := zip.OpenReader(*inputFile)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer reader.Close()
+
+ for _, f := range reader.File {
+ ext := filepath.Ext(f.Name)
+ if ext == ".java" || ext == ".class" {
+ pkgSet[fileToPackage(f.Name)] = true
+ }
+ }
+
+ var pkgs []string
+ for k := range pkgSet {
+ pkgs = append(pkgs, k)
+ }
+ sort.Strings(pkgs)
+
+ var data []byte
+ for _, pkg := range pkgs {
+ data = append(data, *prefix...)
+ data = append(data, pkg...)
+ data = append(data, "\n"...)
+ }
+
+ must(ioutil.WriteFile(*outputFile, data, 0666))
+}
diff --git a/cmd/extract_linker/main.go b/cmd/extract_linker/main.go
index 8530b4aa..3f24ab2d 100644
--- a/cmd/extract_linker/main.go
+++ b/cmd/extract_linker/main.go
@@ -68,7 +68,7 @@ func main() {
ef, err := elf.NewFile(f)
if err != nil {
- log.Fatal("Unable to read elf file: %v", err)
+ log.Fatalf("Unable to read elf file: %v", err)
}
asm := &bytes.Buffer{}
@@ -123,17 +123,17 @@ func main() {
if asmPath != "" {
if err := ioutil.WriteFile(asmPath, asm.Bytes(), 0777); err != nil {
- log.Fatal("Unable to write %q: %v", asmPath, err)
+ log.Fatalf("Unable to write %q: %v", asmPath, err)
}
}
if scriptPath != "" {
buf := &bytes.Buffer{}
if err := linkerScriptTemplate.Execute(buf, sections); err != nil {
- log.Fatal("Failed to create linker script: %v", err)
+ log.Fatalf("Failed to create linker script: %v", err)
}
if err := ioutil.WriteFile(scriptPath, buf.Bytes(), 0777); err != nil {
- log.Fatal("Unable to write %q: %v", scriptPath, err)
+ log.Fatalf("Unable to write %q: %v", scriptPath, err)
}
}
}
diff --git a/cmd/pom2bp/Android.bp b/cmd/pom2bp/Android.bp
new file mode 100644
index 00000000..0b2b7b5d
--- /dev/null
+++ b/cmd/pom2bp/Android.bp
@@ -0,0 +1,22 @@
+// Copyright 2017 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+blueprint_go_binary {
+ name: "pom2bp",
+ deps: [
+ "blueprint-proptools",
+ "bpfix-lib",
+ ],
+ srcs: ["pom2bp.go"],
+}
diff --git a/cmd/pom2bp/pom2bp.go b/cmd/pom2bp/pom2bp.go
new file mode 100644
index 00000000..078a07dd
--- /dev/null
+++ b/cmd/pom2bp/pom2bp.go
@@ -0,0 +1,495 @@
+// Copyright 2017 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/xml"
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "regexp"
+ "sort"
+ "strings"
+ "text/template"
+
+ "github.com/google/blueprint/proptools"
+
+ "android/soong/bpfix/bpfix"
+)
+
+type RewriteNames []RewriteName
+type RewriteName struct {
+ regexp *regexp.Regexp
+ repl string
+}
+
+func (r *RewriteNames) String() string {
+ return ""
+}
+
+func (r *RewriteNames) Set(v string) error {
+ split := strings.SplitN(v, "=", 2)
+ if len(split) != 2 {
+ return fmt.Errorf("Must be in the form of <regex>=<replace>")
+ }
+ regex, err := regexp.Compile(split[0])
+ if err != nil {
+ return nil
+ }
+ *r = append(*r, RewriteName{
+ regexp: regex,
+ repl: split[1],
+ })
+ return nil
+}
+
+func (r *RewriteNames) MavenToBp(groupId string, artifactId string) string {
+ for _, r := range *r {
+ if r.regexp.MatchString(groupId + ":" + artifactId) {
+ return r.regexp.ReplaceAllString(groupId+":"+artifactId, r.repl)
+ } else if r.regexp.MatchString(artifactId) {
+ return r.regexp.ReplaceAllString(artifactId, r.repl)
+ }
+ }
+ return artifactId
+}
+
+var rewriteNames = RewriteNames{}
+
+type ExtraDeps map[string][]string
+
+func (d ExtraDeps) String() string {
+ return ""
+}
+
+func (d ExtraDeps) Set(v string) error {
+ split := strings.SplitN(v, "=", 2)
+ if len(split) != 2 {
+ return fmt.Errorf("Must be in the form of <module>=<module>[,<module>]")
+ }
+ d[split[0]] = strings.Split(split[1], ",")
+ return nil
+}
+
+var extraDeps = make(ExtraDeps)
+
+type Exclude map[string]bool
+
+func (e Exclude) String() string {
+ return ""
+}
+
+func (e Exclude) Set(v string) error {
+ e[v] = true
+ return nil
+}
+
+var excludes = make(Exclude)
+
+var sdkVersion string
+var useVersion string
+
+func InList(s string, list []string) bool {
+ for _, l := range list {
+ if l == s {
+ return true
+ }
+ }
+
+ return false
+}
+
+type Dependency struct {
+ XMLName xml.Name `xml:"dependency"`
+
+ BpTarget string `xml:"-"`
+
+ GroupId string `xml:"groupId"`
+ ArtifactId string `xml:"artifactId"`
+ Version string `xml:"version"`
+ Type string `xml:"type"`
+ Scope string `xml:"scope"`
+}
+
+func (d Dependency) BpName() string {
+ if d.BpTarget == "" {
+ d.BpTarget = rewriteNames.MavenToBp(d.GroupId, d.ArtifactId)
+ }
+ return d.BpTarget
+}
+
+type Pom struct {
+ XMLName xml.Name `xml:"http://maven.apache.org/POM/4.0.0 project"`
+
+ PomFile string `xml:"-"`
+ ArtifactFile string `xml:"-"`
+ BpTarget string `xml:"-"`
+
+ GroupId string `xml:"groupId"`
+ ArtifactId string `xml:"artifactId"`
+ Version string `xml:"version"`
+ Packaging string `xml:"packaging"`
+
+ Dependencies []*Dependency `xml:"dependencies>dependency"`
+}
+
+func (p Pom) IsAar() bool {
+ return p.Packaging == "aar"
+}
+
+func (p Pom) IsJar() bool {
+ return p.Packaging == "jar"
+}
+
+func (p Pom) BpName() string {
+ if p.BpTarget == "" {
+ p.BpTarget = rewriteNames.MavenToBp(p.GroupId, p.ArtifactId)
+ }
+ return p.BpTarget
+}
+
+func (p Pom) BpJarDeps() []string {
+ return p.BpDeps("jar", []string{"compile", "runtime"})
+}
+
+func (p Pom) BpAarDeps() []string {
+ return p.BpDeps("aar", []string{"compile", "runtime"})
+}
+
+func (p Pom) BpExtraDeps() []string {
+ return extraDeps[p.BpName()]
+}
+
+// BpDeps obtains dependencies filtered by type and scope. The results of this
+// method are formatted as Android.bp targets, e.g. run through MavenToBp rules.
+func (p Pom) BpDeps(typeExt string, scopes []string) []string {
+ var ret []string
+ for _, d := range p.Dependencies {
+ if d.Type != typeExt || !InList(d.Scope, scopes) {
+ continue
+ }
+ name := rewriteNames.MavenToBp(d.GroupId, d.ArtifactId)
+ ret = append(ret, name)
+ }
+ return ret
+}
+
+func (p Pom) SdkVersion() string {
+ return sdkVersion
+}
+
+func (p *Pom) FixDeps(modules map[string]*Pom) {
+ for _, d := range p.Dependencies {
+ if d.Type == "" {
+ if depPom, ok := modules[d.BpName()]; ok {
+ // We've seen the POM for this dependency, use its packaging
+ // as the dependency type rather than Maven spec default.
+ d.Type = depPom.Packaging
+ } else {
+ // Dependency type was not specified and we don't have the POM
+ // for this artifact, use the default from Maven spec.
+ d.Type = "jar"
+ }
+ }
+ if d.Scope == "" {
+ // Scope was not specified, use the default from Maven spec.
+ d.Scope = "compile"
+ }
+ }
+}
+
+var bpTemplate = template.Must(template.New("bp").Parse(`
+{{if .IsAar}}android_library_import{{else}}java_import{{end}} {
+ name: "{{.BpName}}-nodeps",
+ {{if .IsAar}}aars{{else}}jars{{end}}: ["{{.ArtifactFile}}"],
+ sdk_version: "{{.SdkVersion}}",{{if .IsAar}}
+ static_libs: [{{range .BpAarDeps}}
+ "{{.}}",{{end}}{{range .BpExtraDeps}}
+ "{{.}}",{{end}}
+ ],{{end}}
+}
+
+{{if .IsAar}}android_library{{else}}java_library_static{{end}} {
+ name: "{{.BpName}}",
+ sdk_version: "{{.SdkVersion}}",{{if .IsAar}}
+ manifest: "manifests/{{.BpName}}/AndroidManifest.xml",{{end}}
+ static_libs: [
+ "{{.BpName}}-nodeps",{{range .BpJarDeps}}
+ "{{.}}",{{end}}{{range .BpAarDeps}}
+ "{{.}}",{{end}}{{range .BpExtraDeps}}
+ "{{.}}",{{end}}
+ ],
+ java_version: "1.7",
+}
+`))
+
+func parse(filename string) (*Pom, error) {
+ data, err := ioutil.ReadFile(filename)
+ if err != nil {
+ return nil, err
+ }
+
+ var pom Pom
+ err = xml.Unmarshal(data, &pom)
+ if err != nil {
+ return nil, err
+ }
+
+ if useVersion != "" && pom.Version != useVersion {
+ return nil, nil
+ }
+
+ if pom.Packaging == "" {
+ pom.Packaging = "jar"
+ }
+
+ pom.PomFile = filename
+ pom.ArtifactFile = strings.TrimSuffix(filename, ".pom") + "." + pom.Packaging
+
+ return &pom, nil
+}
+
+func rerunForRegen(filename string) error {
+ buf, err := ioutil.ReadFile(filename)
+ if err != nil {
+ return err
+ }
+
+ scanner := bufio.NewScanner(bytes.NewBuffer(buf))
+
+ // Skip the first line in the file
+ for i := 0; i < 2; i++ {
+ if !scanner.Scan() {
+ if scanner.Err() != nil {
+ return scanner.Err()
+ } else {
+ return fmt.Errorf("unexpected EOF")
+ }
+ }
+ }
+
+ // Extract the old args from the file
+ line := scanner.Text()
+ if strings.HasPrefix(line, "// pom2bp ") {
+ line = strings.TrimPrefix(line, "// pom2bp ")
+ } else if strings.HasPrefix(line, "// pom2mk ") {
+ line = strings.TrimPrefix(line, "// pom2mk ")
+ } else if strings.HasPrefix(line, "# pom2mk ") {
+ line = strings.TrimPrefix(line, "# pom2mk ")
+ } else {
+ return fmt.Errorf("unexpected second line: %q", line)
+ }
+ args := strings.Split(line, " ")
+ lastArg := args[len(args)-1]
+ args = args[:len(args)-1]
+
+ // Append all current command line args except -regen <file> to the ones from the file
+ for i := 1; i < len(os.Args); i++ {
+ if os.Args[i] == "-regen" {
+ i++
+ } else {
+ args = append(args, os.Args[i])
+ }
+ }
+ args = append(args, lastArg)
+
+ cmd := os.Args[0] + " " + strings.Join(args, " ")
+ // Re-exec pom2bp with the new arguments
+ output, err := exec.Command("/bin/sh", "-c", cmd).Output()
+ if exitErr, _ := err.(*exec.ExitError); exitErr != nil {
+ return fmt.Errorf("failed to run %s\n%s", cmd, string(exitErr.Stderr))
+ } else if err != nil {
+ return err
+ }
+
+ // If the old file was a .mk file, replace it with a .bp file
+ if filepath.Ext(filename) == ".mk" {
+ os.Remove(filename)
+ filename = strings.TrimSuffix(filename, ".mk") + ".bp"
+ }
+
+ return ioutil.WriteFile(filename, output, 0666)
+}
+
+func main() {
+ flag.Usage = func() {
+ fmt.Fprintf(os.Stderr, `pom2bp, a tool to create Android.bp files from maven repos
+
+The tool will extract the necessary information from *.pom files to create an Android.bp whose
+aar libraries can be linked against when using AAPT2.
+
+Usage: %s [--rewrite <regex>=<replace>] [-exclude <module>] [--extra-deps <module>=<module>[,<module>]] [<dir>] [-regen <file>]
+
+ -rewrite <regex>=<replace>
+ rewrite can be used to specify mappings between Maven projects and Android.bp modules. The -rewrite
+ option can be specified multiple times. When determining the Android.bp module for a given Maven
+ project, mappings are searched in the order they were specified. The first <regex> matching
+ either the Maven project's <groupId>:<artifactId> or <artifactId> will be used to generate
+ the Android.bp module name using <replace>. If no matches are found, <artifactId> is used.
+ -exclude <module>
+ Don't put the specified module in the Android.bp file.
+ -extra-deps <module>=<module>[,<module>]
+ Some Android.bp modules have transitive dependencies that must be specified when they are
+ depended upon (like android-support-v7-mediarouter requires android-support-v7-appcompat).
+ This may be specified multiple times to declare these dependencies.
+ -sdk-version <version>
+ Sets LOCAL_SDK_VERSION := <version> for all modules.
+ -use-version <version>
+ If the maven directory contains multiple versions of artifacts and their pom files,
+ -use-version can be used to only write Android.bp files for a specific version of those artifacts.
+ <dir>
+ The directory to search for *.pom files under.
+ The contents are written to stdout, to be put in the current directory (often as Android.bp)
+ -regen <file>
+ Read arguments from <file> and overwrite it (if it ends with .bp) or move it to .bp (if it
+ ends with .mk).
+
+`, os.Args[0])
+ }
+
+ var regen string
+
+ flag.Var(&excludes, "exclude", "Exclude module")
+ flag.Var(&extraDeps, "extra-deps", "Extra dependencies needed when depending on a module")
+ flag.Var(&rewriteNames, "rewrite", "Regex(es) to rewrite artifact names")
+ flag.StringVar(&sdkVersion, "sdk-version", "", "What to write to LOCAL_SDK_VERSION")
+ flag.StringVar(&useVersion, "use-version", "", "Only read artifacts of a specific version")
+ flag.Bool("static-deps", false, "Ignored")
+ flag.StringVar(&regen, "regen", "", "Rewrite specified file")
+ flag.Parse()
+
+ if regen != "" {
+ err := rerunForRegen(regen)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ os.Exit(0)
+ }
+
+ if flag.NArg() == 0 {
+ fmt.Fprintln(os.Stderr, "Directory argument is required")
+ os.Exit(1)
+ } else if flag.NArg() > 1 {
+ fmt.Fprintln(os.Stderr, "Multiple directories provided:", strings.Join(flag.Args(), " "))
+ os.Exit(1)
+ }
+
+ dir := flag.Arg(0)
+ absDir, err := filepath.Abs(dir)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, "Failed to get absolute directory:", err)
+ os.Exit(1)
+ }
+
+ var filenames []string
+ err = filepath.Walk(absDir, func(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+
+ name := info.Name()
+ if info.IsDir() {
+ if strings.HasPrefix(name, ".") {
+ return filepath.SkipDir
+ }
+ return nil
+ }
+
+ if strings.HasPrefix(name, ".") {
+ return nil
+ }
+
+ if strings.HasSuffix(name, ".pom") {
+ path, err = filepath.Rel(absDir, path)
+ if err != nil {
+ return err
+ }
+ filenames = append(filenames, filepath.Join(dir, path))
+ }
+ return nil
+ })
+ if err != nil {
+ fmt.Fprintln(os.Stderr, "Error walking files:", err)
+ os.Exit(1)
+ }
+
+ if len(filenames) == 0 {
+ fmt.Fprintln(os.Stderr, "Error: no *.pom files found under", dir)
+ os.Exit(1)
+ }
+
+ sort.Strings(filenames)
+
+ poms := []*Pom{}
+ modules := make(map[string]*Pom)
+ duplicate := false
+ for _, filename := range filenames {
+ pom, err := parse(filename)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, "Error converting", filename, err)
+ os.Exit(1)
+ }
+
+ if pom != nil {
+ key := pom.BpName()
+ if excludes[key] {
+ continue
+ }
+
+ if old, ok := modules[key]; ok {
+ fmt.Fprintln(os.Stderr, "Module", key, "defined twice:", old.PomFile, pom.PomFile)
+ duplicate = true
+ }
+
+ poms = append(poms, pom)
+ modules[key] = pom
+ }
+ }
+ if duplicate {
+ os.Exit(1)
+ }
+
+ for _, pom := range poms {
+ pom.FixDeps(modules)
+ }
+
+ buf := &bytes.Buffer{}
+
+ fmt.Fprintln(buf, "// Automatically generated with:")
+ fmt.Fprintln(buf, "// pom2bp", strings.Join(proptools.ShellEscape(os.Args[1:]), " "))
+
+ for _, pom := range poms {
+ var err error
+ err = bpTemplate.Execute(buf, pom)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, "Error writing", pom.PomFile, pom.BpName(), err)
+ os.Exit(1)
+ }
+ }
+
+ out, err := bpfix.Reformat(buf.String())
+ if err != nil {
+ fmt.Fprintln(os.Stderr, "Error formatting output", err)
+ os.Exit(1)
+ }
+
+ os.Stdout.WriteString(out)
+}
diff --git a/cmd/pom2mk/pom2mk.go b/cmd/pom2mk/pom2mk.go
index 57416243..fc836411 100644
--- a/cmd/pom2mk/pom2mk.go
+++ b/cmd/pom2mk/pom2mk.go
@@ -406,7 +406,7 @@ Usage: %s [--rewrite <regex>=<replace>] [-exclude <module>] [--extra-deps <modul
dir := flag.Arg(0)
absDir, err := filepath.Abs(dir)
if err != nil {
- fmt.Println(os.Stderr, "Failed to get absolute directory:", err)
+ fmt.Fprintln(os.Stderr, "Failed to get absolute directory:", err)
os.Exit(1)
}
diff --git a/cmd/zipsync/zipsync.go b/cmd/zipsync/zipsync.go
index 035a1455..1b300161 100644
--- a/cmd/zipsync/zipsync.go
+++ b/cmd/zipsync/zipsync.go
@@ -93,11 +93,11 @@ func main() {
}
}
if filepath.IsAbs(f.Name) {
- log.Fatal("%q in %q is an absolute path", f.Name, input)
+ log.Fatalf("%q in %q is an absolute path", f.Name, input)
}
if prev, exists := seen[f.Name]; exists {
- log.Fatal("%q found in both %q and %q", f.Name, prev, input)
+ log.Fatalf("%q found in both %q and %q", f.Name, prev, input)
}
seen[f.Name] = input
diff --git a/java/aapt2.go b/java/aapt2.go
index fd7388e1..70c75071 100644
--- a/java/aapt2.go
+++ b/java/aapt2.go
@@ -111,15 +111,19 @@ func aapt2CompileDirs(ctx android.ModuleContext, flata android.WritablePath, dir
var aapt2LinkRule = pctx.AndroidStaticRule("aapt2Link",
blueprint.RuleParams{
- Command: `${config.Aapt2Cmd} link -o $out $flags --java $genDir --proguard $proguardOptions $inFlags && ` +
- `${config.SoongZipCmd} -write_if_changed -jar -o $genJar -C $genDir -D $genDir`,
+ Command: `${config.Aapt2Cmd} link -o $out $flags --java $genDir --proguard $proguardOptions ` +
+ `--output-text-symbols ${rTxt} $inFlags && ` +
+ `${config.SoongZipCmd} -write_if_changed -jar -o $genJar -C $genDir -D $genDir &&` +
+ `${config.ExtractJarPackagesCmd} -i $genJar -o $extraPackages --prefix '--extra-packages '`,
+
CommandDeps: []string{
"${config.Aapt2Cmd}",
"${config.SoongZipCmd}",
+ "${config.ExtractJarPackagesCmd}",
},
Restat: true,
},
- "flags", "inFlags", "proguardOptions", "genDir", "genJar")
+ "flags", "inFlags", "proguardOptions", "genDir", "genJar", "rTxt", "extraPackages")
var fileListToFileRule = pctx.AndroidStaticRule("fileListToFile",
blueprint.RuleParams{
@@ -129,7 +133,7 @@ var fileListToFileRule = pctx.AndroidStaticRule("fileListToFile",
})
func aapt2Link(ctx android.ModuleContext,
- packageRes, genJar, proguardOptions android.WritablePath,
+ packageRes, genJar, proguardOptions, rTxt, extraPackages android.WritablePath,
flags []string, deps android.Paths,
compiledRes, compiledOverlay android.Paths) {
@@ -171,13 +175,15 @@ func aapt2Link(ctx android.ModuleContext,
Description: "aapt2 link",
Implicits: deps,
Output: packageRes,
- ImplicitOutputs: android.WritablePaths{proguardOptions, genJar},
+ ImplicitOutputs: android.WritablePaths{proguardOptions, genJar, rTxt, extraPackages},
Args: map[string]string{
"flags": strings.Join(flags, " "),
"inFlags": strings.Join(inFlags, " "),
"proguardOptions": proguardOptions.String(),
"genDir": genDir.String(),
"genJar": genJar.String(),
+ "rTxt": rTxt.String(),
+ "extraPackages": extraPackages.String(),
},
})
}
diff --git a/java/aar.go b/java/aar.go
index 0df3632b..9e5cddb6 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -16,21 +16,332 @@ package java
import (
"android/soong/android"
+ "strings"
"github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
)
-//
-// AAR (android library) prebuilts
-//
+type AndroidLibraryDependency interface {
+ Dependency
+ ExportPackage() android.Path
+ ExportedProguardFlagFiles() android.Paths
+ ExportedStaticPackages() android.Paths
+}
+
func init() {
android.RegisterModuleType("android_library_import", AARImportFactory)
+ android.RegisterModuleType("android_library", AndroidLibraryFactory)
+}
+
+//
+// AAR (android library)
+//
+
+type androidLibraryProperties struct {
+ BuildAAR bool `blueprint:"mutated"`
+}
+
+type aaptProperties struct {
+ // flags passed to aapt when creating the apk
+ Aaptflags []string
+
+ // list of directories relative to the Blueprints file containing assets.
+ // Defaults to "assets"
+ Asset_dirs []string
+
+ // list of directories relative to the Blueprints file containing
+ // Android resources
+ Resource_dirs []string
+
+ // path to AndroidManifest.xml. If unset, defaults to "AndroidManifest.xml".
+ Manifest *string
+}
+
+type aapt struct {
+ aaptSrcJar android.Path
+ exportPackage android.Path
+ manifestPath android.Path
+ proguardOptionsFile android.Path
+ rroDirs android.Paths
+ rTxt android.Path
+ extraAaptPackagesFile android.Path
+
+ aaptProperties aaptProperties
+}
+
+func (a *aapt) ExportPackage() android.Path {
+ return a.exportPackage
+}
+
+func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkVersion string) (flags []string, deps android.Paths,
+ resDirs, overlayDirs []globbedResourceDir, overlayFiles, rroDirs android.Paths, manifestPath android.Path) {
+
+ hasVersionCode := false
+ hasVersionName := false
+ for _, f := range a.aaptProperties.Aaptflags {
+ if strings.HasPrefix(f, "--version-code") {
+ hasVersionCode = true
+ } else if strings.HasPrefix(f, "--version-name") {
+ hasVersionName = true
+ }
+ }
+
+ var linkFlags []string
+
+ // Flags specified in Android.bp
+ linkFlags = append(linkFlags, a.aaptProperties.Aaptflags...)
+
+ linkFlags = append(linkFlags, "--no-static-lib-packages")
+
+ // Find implicit or explicit asset and resource dirs
+ assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets")
+ resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs, "res")
+
+ var linkDeps android.Paths
+
+ // Glob directories into lists of paths
+ for _, dir := range resourceDirs {
+ resDirs = append(resDirs, globbedResourceDir{
+ dir: dir,
+ files: androidResourceGlob(ctx, dir),
+ })
+ resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, dir)
+ overlayDirs = append(overlayDirs, resOverlayDirs...)
+ rroDirs = append(rroDirs, resRRODirs...)
+ }
+
+ var assetFiles android.Paths
+ for _, dir := range assetDirs {
+ assetFiles = append(assetFiles, androidResourceGlob(ctx, dir)...)
+ }
+
+ // App manifest file
+ manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
+ manifestPath = android.PathForModuleSrc(ctx, manifestFile)
+ linkFlags = append(linkFlags, "--manifest "+manifestPath.String())
+ linkDeps = append(linkDeps, manifestPath)
+
+ linkFlags = append(linkFlags, android.JoinWithPrefix(assetDirs.Strings(), "-A "))
+ linkDeps = append(linkDeps, assetFiles...)
+
+ transitiveStaticLibs, libDeps, libFlags := aaptLibs(ctx, sdkVersion)
+
+ overlayFiles = append(overlayFiles, transitiveStaticLibs...)
+ linkDeps = append(linkDeps, libDeps...)
+ linkFlags = append(linkFlags, libFlags...)
+
+ // SDK version flags
+ switch sdkVersion {
+ case "", "current", "system_current", "test_current":
+ sdkVersion = proptools.NinjaEscape([]string{ctx.Config().DefaultAppTargetSdk()})[0]
+ }
+
+ linkFlags = append(linkFlags, "--min-sdk-version "+sdkVersion)
+ linkFlags = append(linkFlags, "--target-sdk-version "+sdkVersion)
+
+ // Version code
+ if !hasVersionCode {
+ linkFlags = append(linkFlags, "--version-code", ctx.Config().PlatformSdkVersion())
+ }
+
+ if !hasVersionName {
+ var versionName string
+ if ctx.ModuleName() == "framework-res" {
+ // Some builds set AppsDefaultVersionName() to include the build number ("O-123456"). aapt2 copies the
+ // version name of framework-res into app manifests as compileSdkVersionCodename, which confuses things
+ // if it contains the build number. Use the DefaultAppTargetSdk instead.
+ versionName = ctx.Config().DefaultAppTargetSdk()
+ } else {
+ versionName = ctx.Config().AppsDefaultVersionName()
+ }
+ versionName = proptools.NinjaEscape([]string{versionName})[0]
+ linkFlags = append(linkFlags, "--version-name ", versionName)
+ }
+
+ return linkFlags, linkDeps, resDirs, overlayDirs, overlayFiles, rroDirs, manifestPath
+}
+
+func (a *aapt) deps(ctx android.BottomUpMutatorContext, sdkVersion string) {
+ if !ctx.Config().UnbundledBuild() {
+ sdkDep := decodeSdkDep(ctx, sdkVersion)
+ if sdkDep.frameworkResModule != "" {
+ ctx.AddDependency(ctx.Module(), frameworkResTag, sdkDep.frameworkResModule)
+ }
+ }
}
+func (a *aapt) buildActions(ctx android.ModuleContext, sdkVersion string, extraLinkFlags ...string) {
+ linkFlags, linkDeps, resDirs, overlayDirs, overlayFiles, rroDirs, manifestPath := a.aapt2Flags(ctx, sdkVersion)
+
+ linkFlags = append(linkFlags, extraLinkFlags...)
+
+ packageRes := android.PathForModuleOut(ctx, "package-res.apk")
+ srcJar := android.PathForModuleGen(ctx, "R.jar")
+ proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
+ rTxt := android.PathForModuleOut(ctx, "R.txt")
+ // This file isn't used by Soong, but is generated for exporting
+ extraPackages := android.PathForModuleOut(ctx, "extra_packages")
+
+ var compiledRes, compiledOverlay android.Paths
+ for _, dir := range resDirs {
+ compiledRes = append(compiledRes, aapt2Compile(ctx, dir.dir, dir.files).Paths()...)
+ }
+ for _, dir := range overlayDirs {
+ compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files).Paths()...)
+ }
+
+ compiledOverlay = append(compiledOverlay, overlayFiles...)
+
+ aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt, extraPackages,
+ linkFlags, linkDeps, compiledRes, compiledOverlay)
+
+ a.aaptSrcJar = srcJar
+ a.exportPackage = packageRes
+ a.manifestPath = manifestPath
+ a.proguardOptionsFile = proguardOptionsFile
+ a.rroDirs = rroDirs
+ a.extraAaptPackagesFile = extraPackages
+ a.rTxt = rTxt
+}
+
+// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
+func aaptLibs(ctx android.ModuleContext, sdkVersion string) (transitiveStaticLibs, deps android.Paths,
+ flags []string) {
+
+ var sharedLibs android.Paths
+
+ sdkDep := decodeSdkDep(ctx, sdkVersion)
+ if sdkDep.useFiles {
+ sharedLibs = append(sharedLibs, sdkDep.jar)
+ }
+
+ ctx.VisitDirectDeps(func(module android.Module) {
+ var exportPackage android.Path
+ aarDep, _ := module.(AndroidLibraryDependency)
+ if aarDep != nil {
+ exportPackage = aarDep.ExportPackage()
+ }
+
+ switch ctx.OtherModuleDependencyTag(module) {
+ case libTag, frameworkResTag:
+ if exportPackage != nil {
+ sharedLibs = append(sharedLibs, exportPackage)
+ }
+ case staticLibTag:
+ if exportPackage != nil {
+ transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
+ transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...)
+ }
+ }
+ })
+
+ deps = append(deps, sharedLibs...)
+ deps = append(deps, transitiveStaticLibs...)
+
+ if len(transitiveStaticLibs) > 0 {
+ flags = append(flags, "--auto-add-overlay")
+ }
+
+ for _, sharedLib := range sharedLibs {
+ flags = append(flags, "-I "+sharedLib.String())
+ }
+
+ transitiveStaticLibs = android.FirstUniquePaths(transitiveStaticLibs)
+
+ return transitiveStaticLibs, deps, flags
+}
+
+type AndroidLibrary struct {
+ Library
+ aapt
+
+ androidLibraryProperties androidLibraryProperties
+
+ aarFile android.WritablePath
+
+ exportedProguardFlagFiles android.Paths
+ exportedStaticPackages android.Paths
+}
+
+func (a *AndroidLibrary) ExportedProguardFlagFiles() android.Paths {
+ return a.exportedProguardFlagFiles
+}
+
+func (a *AndroidLibrary) ExportedStaticPackages() android.Paths {
+ return a.exportedStaticPackages
+}
+
+var _ AndroidLibraryDependency = (*AndroidLibrary)(nil)
+
+func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
+ a.Module.deps(ctx)
+ if !Bool(a.properties.No_framework_libs) && !Bool(a.properties.No_standard_libs) {
+ a.aapt.deps(ctx, String(a.deviceProperties.Sdk_version))
+ }
+}
+
+func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ a.aapt.buildActions(ctx, String(a.deviceProperties.Sdk_version), "--static-lib")
+
+ ctx.CheckbuildFile(a.proguardOptionsFile)
+ ctx.CheckbuildFile(a.exportPackage)
+ ctx.CheckbuildFile(a.aaptSrcJar)
+
+ // apps manifests are handled by aapt, don't let Module see them
+ a.properties.Manifest = nil
+
+ a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles,
+ a.proguardOptionsFile)
+
+ a.Module.compile(ctx, a.aaptSrcJar)
+
+ a.aarFile = android.PathForOutput(ctx, ctx.ModuleName()+".aar")
+ var res android.Paths
+ if a.androidLibraryProperties.BuildAAR {
+ BuildAAR(ctx, a.aarFile, a.outputFile, a.manifestPath, a.rTxt, res)
+ ctx.CheckbuildFile(a.aarFile)
+ }
+
+ ctx.VisitDirectDeps(func(m android.Module) {
+ if lib, ok := m.(AndroidLibraryDependency); ok && ctx.OtherModuleDependencyTag(m) == staticLibTag {
+ a.exportedProguardFlagFiles = append(a.exportedProguardFlagFiles, lib.ExportedProguardFlagFiles()...)
+ a.exportedStaticPackages = append(a.exportedStaticPackages, lib.ExportPackage())
+ a.exportedStaticPackages = append(a.exportedStaticPackages, lib.ExportedStaticPackages()...)
+ }
+ })
+
+ a.exportedProguardFlagFiles = android.FirstUniquePaths(a.exportedProguardFlagFiles)
+ a.exportedStaticPackages = android.FirstUniquePaths(a.exportedStaticPackages)
+}
+
+func AndroidLibraryFactory() android.Module {
+ module := &AndroidLibrary{}
+
+ module.AddProperties(
+ &module.Module.properties,
+ &module.Module.deviceProperties,
+ &module.Module.protoProperties,
+ &module.aaptProperties,
+ &module.androidLibraryProperties)
+
+ module.androidLibraryProperties.BuildAAR = true
+
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ return module
+}
+
+//
+// AAR (android library) prebuilts
+//
+
type AARImportProperties struct {
Aars []string
Sdk_version *string
+
+ Static_libs []string
+ Libs []string
}
type AARImport struct {
@@ -39,9 +350,26 @@ type AARImport struct {
properties AARImportProperties
- classpathFile android.WritablePath
- proguardFlags android.WritablePath
- exportPackage android.WritablePath
+ classpathFile android.WritablePath
+ proguardFlags android.WritablePath
+ exportPackage android.WritablePath
+ extraAaptPackagesFile android.WritablePath
+
+ exportedStaticPackages android.Paths
+}
+
+var _ AndroidLibraryDependency = (*AARImport)(nil)
+
+func (a *AARImport) ExportPackage() android.Path {
+ return a.exportPackage
+}
+
+func (a *AARImport) ExportedProguardFlagFiles() android.Paths {
+ return android.Paths{a.proguardFlags}
+}
+
+func (a *AARImport) ExportedStaticPackages() android.Paths {
+ return a.exportedStaticPackages
}
func (a *AARImport) Prebuilt() *android.Prebuilt {
@@ -53,13 +381,15 @@ func (a *AARImport) Name() string {
}
func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) {
- // TODO: this should use decodeSdkDep once that knows about current
if !ctx.Config().UnbundledBuild() {
- switch String(a.properties.Sdk_version) { // TODO: Res_sdk_version?
- case "current", "system_current", "test_current", "":
- ctx.AddDependency(ctx.Module(), frameworkResTag, "framework-res")
+ sdkDep := decodeSdkDep(ctx, String(a.properties.Sdk_version))
+ if sdkDep.useModule && sdkDep.frameworkResModule != "" {
+ ctx.AddDependency(ctx.Module(), frameworkResTag, sdkDep.frameworkResModule)
}
}
+
+ ctx.AddDependency(ctx.Module(), libTag, a.properties.Libs...)
+ ctx.AddDependency(ctx.Module(), staticLibTag, a.properties.Static_libs...)
}
// Unzip an AAR into its constituent files and directories. Any files in Outputs that don't exist in the AAR will be
@@ -105,6 +435,8 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.exportPackage = android.PathForModuleOut(ctx, "package-res.apk")
srcJar := android.PathForModuleGen(ctx, "R.jar")
proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
+ rTxt := android.PathForModuleOut(ctx, "R.txt")
+ a.extraAaptPackagesFile = android.PathForModuleOut(ctx, "extra_packages")
var linkDeps android.Paths
@@ -117,30 +449,15 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
linkFlags = append(linkFlags, "--manifest "+manifest.String())
linkDeps = append(linkDeps, manifest)
- // Include dirs
- ctx.VisitDirectDeps(func(module android.Module) {
- var depFiles android.Paths
- if javaDep, ok := module.(Dependency); ok {
- // TODO: shared android libraries
- if ctx.OtherModuleName(module) == "framework-res" {
- depFiles = android.Paths{javaDep.(*AndroidApp).exportPackage}
- }
- }
+ transitiveStaticLibs, libDeps, libFlags := aaptLibs(ctx, String(a.properties.Sdk_version))
- for _, dep := range depFiles {
- linkFlags = append(linkFlags, "-I "+dep.String())
- }
- linkDeps = append(linkDeps, depFiles...)
- })
+ linkDeps = append(linkDeps, libDeps...)
+ linkFlags = append(linkFlags, libFlags...)
- sdkDep := decodeSdkDep(ctx, String(a.properties.Sdk_version))
- if sdkDep.useFiles {
- linkFlags = append(linkFlags, "-I "+sdkDep.jar.String())
- linkDeps = append(linkDeps, sdkDep.jar)
- }
+ overlayRes := append(android.Paths{flata}, transitiveStaticLibs...)
- aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile,
- linkFlags, linkDeps, nil, android.Paths{flata})
+ aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, rTxt, a.extraAaptPackagesFile,
+ linkFlags, linkDeps, nil, overlayRes)
}
var _ Dependency = (*AARImport)(nil)
diff --git a/java/android_resources.go b/java/android_resources.go
new file mode 100644
index 00000000..47535d29
--- /dev/null
+++ b/java/android_resources.go
@@ -0,0 +1,127 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+ "path/filepath"
+ "strings"
+
+ "android/soong/android"
+)
+
+func init() {
+ android.RegisterPreSingletonType("overlay", OverlaySingletonFactory)
+}
+
+var androidResourceIgnoreFilenames = []string{
+ ".svn",
+ ".git",
+ ".ds_store",
+ "*.scc",
+ ".*",
+ "CVS",
+ "thumbs.db",
+ "picasa.ini",
+ "*~",
+}
+
+func androidResourceGlob(ctx android.ModuleContext, dir android.Path) android.Paths {
+ return ctx.GlobFiles(filepath.Join(dir.String(), "**/*"), androidResourceIgnoreFilenames)
+}
+
+type overlayGlobResult struct {
+ dir string
+ paths android.DirectorySortedPaths
+
+ // Set to true of the product has selected that values in this overlay should not be moved to
+ // Runtime Resource Overlay (RRO) packages.
+ excludeFromRRO bool
+}
+
+const overlayDataKey = "overlayDataKey"
+
+type globbedResourceDir struct {
+ dir android.Path
+ files android.Paths
+}
+
+func overlayResourceGlob(ctx android.ModuleContext, dir android.Path) (res []globbedResourceDir,
+ rroDirs android.Paths) {
+
+ overlayData := ctx.Config().Get(overlayDataKey).([]overlayGlobResult)
+
+ // Runtime resource overlays (RRO) may be turned on by the product config for some modules
+ rroEnabled := ctx.Config().EnforceRROForModule(ctx.ModuleName())
+
+ for _, data := range overlayData {
+ files := data.paths.PathsInDirectory(filepath.Join(data.dir, dir.String()))
+ if len(files) > 0 {
+ overlayModuleDir := android.PathForSource(ctx, data.dir, dir.String())
+ // If enforce RRO is enabled for this module and this overlay is not in the
+ // exclusion list, ignore the overlay. The list of ignored overlays will be
+ // passed to Make to be turned into an RRO package.
+ if rroEnabled && !data.excludeFromRRO {
+ rroDirs = append(rroDirs, overlayModuleDir)
+ } else {
+ res = append(res, globbedResourceDir{
+ dir: overlayModuleDir,
+ files: files,
+ })
+ }
+ }
+ }
+
+ return res, rroDirs
+}
+
+func OverlaySingletonFactory() android.Singleton {
+ return overlaySingleton{}
+}
+
+type overlaySingleton struct{}
+
+func (overlaySingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ var overlayData []overlayGlobResult
+ overlayDirs := ctx.Config().ResourceOverlays()
+ for i := range overlayDirs {
+ // Iterate backwards through the list of overlay directories so that the later, lower-priority
+ // directories in the list show up earlier in the command line to aapt2.
+ overlay := overlayDirs[len(overlayDirs)-1-i]
+ var result overlayGlobResult
+ result.dir = overlay
+
+ // Mark overlays that will not have Runtime Resource Overlays enforced on them
+ // based on the product config
+ result.excludeFromRRO = ctx.Config().EnforceRROExcludedOverlay(overlay)
+
+ files, err := ctx.GlobWithDeps(filepath.Join(overlay, "**/*"), androidResourceIgnoreFilenames)
+ if err != nil {
+ ctx.Errorf("failed to glob resource dir %q: %s", overlay, err.Error())
+ continue
+ }
+ var paths android.Paths
+ for _, f := range files {
+ if !strings.HasSuffix(f, "/") {
+ paths = append(paths, android.PathForSource(ctx, f))
+ }
+ }
+ result.paths = android.PathsToDirectorySortedPaths(paths)
+ overlayData = append(overlayData, result)
+ }
+
+ ctx.Config().Once(overlayDataKey, func() interface{} {
+ return overlayData
+ })
+}
diff --git a/java/androidmk.go b/java/androidmk.go
index 13966ed7..b85ecb40 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -124,6 +124,7 @@ func (prebuilt *AARImport) AndroidMk() android.AndroidMkData {
fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", prebuilt.classpathFile.String())
fmt.Fprintln(w, "LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=", prebuilt.exportPackage.String())
fmt.Fprintln(w, "LOCAL_SOONG_EXPORT_PROGUARD_FLAGS :=", prebuilt.proguardFlags.String())
+ fmt.Fprintln(w, "LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES :=", prebuilt.extraAaptPackagesFile.String())
fmt.Fprintln(w, "LOCAL_SDK_VERSION :=", String(prebuilt.properties.Sdk_version))
},
},
@@ -214,7 +215,33 @@ func (app *AndroidApp) AndroidMk() android.AndroidMkData {
},
},
}
+}
+
+func (a *AndroidLibrary) AndroidMk() android.AndroidMkData {
+ data := a.Library.AndroidMk()
+
+ data.Extra = append(data.Extra, func(w io.Writer, outputFile android.Path) {
+ if a.proguardDictionary != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_PROGUARD_DICT :=", a.proguardDictionary.String())
+ }
+
+ if a.Name() == "framework-res" {
+ fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(TARGET_OUT_JAVA_LIBRARIES)")
+ // Make base_rules.mk not put framework-res in a subdirectory called
+ // framework_res.
+ fmt.Fprintln(w, "LOCAL_NO_STANDARD_LIBRARIES := true")
+ }
+
+ fmt.Fprintln(w, "LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=", a.exportPackage.String())
+ fmt.Fprintln(w, "LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES :=", a.extraAaptPackagesFile.String())
+ fmt.Fprintln(w, "LOCAL_FULL_MANIFEST_FILE :=", a.manifestPath.String())
+ fmt.Fprintln(w, "LOCAL_SOONG_EXPORT_PROGUARD_FLAGS :=",
+ strings.Join(a.exportedProguardFlagFiles.Strings(), " "))
+ fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
+ fmt.Fprintln(w, "LOCAL_DEX_PREOPT := false")
+ })
+ return data
}
func (jd *Javadoc) AndroidMk() android.AndroidMkData {
diff --git a/java/app.go b/java/app.go
index 9360cc56..ae0592a6 100644
--- a/java/app.go
+++ b/java/app.go
@@ -17,7 +17,6 @@ package java
// This file contains the module types for compiling Android apps.
import (
- "path/filepath"
"strings"
"github.com/google/blueprint/proptools"
@@ -26,11 +25,9 @@ import (
)
func init() {
- android.RegisterPreSingletonType("overlay", OverlaySingletonFactory)
android.RegisterModuleType("android_app", AndroidAppFactory)
}
-// AAR prebuilts
// AndroidManifest.xml merging
// package splits
@@ -46,91 +43,98 @@ type appProperties struct {
// use to get PRODUCT-agnostic resource data like IDs and type definitions.
Export_package_resources *bool
- // flags passed to aapt when creating the apk
- Aaptflags []string
+ // Specifies that this app should be installed to the priv-app directory,
+ // where the system will grant it additional privileges not available to
+ // normal apps.
+ Privileged *bool
// list of resource labels to generate individual resource packages
Package_splits []string
- // list of directories relative to the Blueprints file containing assets.
- // Defaults to "assets"
- Asset_dirs []string
-
- // list of directories relative to the Blueprints file containing
- // Android resources
- Resource_dirs []string
-
Instrumentation_for *string
-
- // Specifies that this app should be installed to the priv-app directory,
- // where the system will grant it additional privileges not available to
- // normal apps.
- Privileged *bool
}
type AndroidApp struct {
- Module
+ Library
+ aapt
+
+ certificate certificate
appProperties appProperties
+}
- aaptSrcJar android.Path
- exportPackage android.Path
- rroDirs android.Paths
- manifestPath android.Path
- certificate certificate
+func (a *AndroidApp) ExportedProguardFlagFiles() android.Paths {
+ return nil
}
+func (a *AndroidApp) ExportedStaticPackages() android.Paths {
+ return nil
+}
+
+var _ AndroidLibraryDependency = (*AndroidApp)(nil)
+
type certificate struct {
pem, key android.Path
}
func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
a.Module.deps(ctx)
-
if !Bool(a.properties.No_framework_libs) && !Bool(a.properties.No_standard_libs) {
- switch String(a.deviceProperties.Sdk_version) { // TODO: Res_sdk_version?
- case "current", "system_current", "test_current", "":
- ctx.AddDependency(ctx.Module(), frameworkResTag, "framework-res")
- default:
- // We'll already have a dependency on an sdk prebuilt android.jar
- }
+ a.aapt.deps(ctx, String(a.deviceProperties.Sdk_version))
}
}
func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, manifestPath := a.aapt2Flags(ctx)
+ var linkFlags []string
+ if String(a.appProperties.Instrumentation_for) != "" {
+ linkFlags = append(linkFlags,
+ "--rename-instrumentation-target-package",
+ String(a.appProperties.Instrumentation_for))
+ } else {
+ a.properties.Instrument = true
+ }
- packageRes := android.PathForModuleOut(ctx, "package-res.apk")
- srcJar := android.PathForModuleGen(ctx, "R.jar")
- proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
+ hasProduct := false
+ for _, f := range a.aaptProperties.Aaptflags {
+ if strings.HasPrefix(f, "--product") {
+ hasProduct = true
+ }
+ }
- var compiledRes, compiledOverlay android.Paths
- for _, dir := range resDirs {
- compiledRes = append(compiledRes, aapt2Compile(ctx, dir.dir, dir.files).Paths()...)
+ // Product characteristics
+ if !hasProduct && len(ctx.Config().ProductAAPTCharacteristics()) > 0 {
+ linkFlags = append(linkFlags, "--product", ctx.Config().ProductAAPTCharacteristics())
}
- for _, dir := range overlayDirs {
- compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files).Paths()...)
+
+ // Product AAPT config
+ for _, aaptConfig := range ctx.Config().ProductAAPTConfig() {
+ linkFlags = append(linkFlags, "-c", aaptConfig)
}
- aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile,
- linkFlags, linkDeps, compiledRes, compiledOverlay)
+ // Product AAPT preferred config
+ if len(ctx.Config().ProductAAPTPreferredConfig()) > 0 {
+ linkFlags = append(linkFlags, "--preferred-density", ctx.Config().ProductAAPTPreferredConfig())
+ }
- a.exportPackage = packageRes
- a.aaptSrcJar = srcJar
+ // TODO: LOCAL_PACKAGE_OVERRIDES
+ // $(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
- ctx.CheckbuildFile(proguardOptionsFile)
- ctx.CheckbuildFile(a.exportPackage)
- ctx.CheckbuildFile(a.aaptSrcJar)
+ a.aapt.buildActions(ctx, String(a.deviceProperties.Sdk_version), linkFlags...)
// apps manifests are handled by aapt, don't let Module see them
a.properties.Manifest = nil
- if String(a.appProperties.Instrumentation_for) == "" {
- a.properties.Instrument = true
- }
+ var staticLibProguardFlagFiles android.Paths
+ ctx.VisitDirectDeps(func(m android.Module) {
+ if lib, ok := m.(AndroidLibraryDependency); ok && ctx.OtherModuleDependencyTag(m) == staticLibTag {
+ staticLibProguardFlagFiles = append(staticLibProguardFlagFiles, lib.ExportedProguardFlagFiles()...)
+ }
+ })
+
+ staticLibProguardFlagFiles = android.FirstUniquePaths(staticLibProguardFlagFiles)
- a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles,
- proguardOptionsFile)
+ a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, staticLibProguardFlagFiles...)
+ a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, a.proguardOptionsFile)
if ctx.ModuleName() != "framework-res" {
a.Module.compile(ctx, a.aaptSrcJar)
@@ -167,8 +171,6 @@ func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
CreateAppPackage(ctx, packageFile, a.exportPackage, a.outputFile, certificates)
a.outputFile = packageFile
- a.rroDirs = rroDirs
- a.manifestPath = manifestPath
if ctx.ModuleName() == "framework-res" {
// framework-res.apk is installed as system/framework/framework-res.apk
@@ -180,161 +182,6 @@ func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
}
-var aaptIgnoreFilenames = []string{
- ".svn",
- ".git",
- ".ds_store",
- "*.scc",
- ".*",
- "CVS",
- "thumbs.db",
- "picasa.ini",
- "*~",
-}
-
-type globbedResourceDir struct {
- dir android.Path
- files android.Paths
-}
-
-func (a *AndroidApp) aapt2Flags(ctx android.ModuleContext) (flags []string, deps android.Paths,
- resDirs, overlayDirs []globbedResourceDir, rroDirs android.Paths, manifestPath android.Path) {
-
- hasVersionCode := false
- hasVersionName := false
- hasProduct := false
- for _, f := range a.appProperties.Aaptflags {
- if strings.HasPrefix(f, "--version-code") {
- hasVersionCode = true
- } else if strings.HasPrefix(f, "--version-name") {
- hasVersionName = true
- } else if strings.HasPrefix(f, "--product") {
- hasProduct = true
- }
- }
-
- var linkFlags []string
-
- // Flags specified in Android.bp
- linkFlags = append(linkFlags, a.appProperties.Aaptflags...)
-
- linkFlags = append(linkFlags, "--no-static-lib-packages")
-
- // Find implicit or explicit asset and resource dirs
- assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Asset_dirs, "assets")
- resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Resource_dirs, "res")
-
- var linkDeps android.Paths
-
- // Glob directories into lists of paths
- for _, dir := range resourceDirs {
- resDirs = append(resDirs, globbedResourceDir{
- dir: dir,
- files: resourceGlob(ctx, dir),
- })
- resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, dir)
- overlayDirs = append(overlayDirs, resOverlayDirs...)
- rroDirs = append(rroDirs, resRRODirs...)
- }
-
- var assetFiles android.Paths
- for _, dir := range assetDirs {
- assetFiles = append(assetFiles, resourceGlob(ctx, dir)...)
- }
-
- // App manifest file
- var manifestFile string
- if a.properties.Manifest == nil {
- manifestFile = "AndroidManifest.xml"
- } else {
- manifestFile = *a.properties.Manifest
- }
-
- manifestPath = android.PathForModuleSrc(ctx, manifestFile)
- linkFlags = append(linkFlags, "--manifest "+manifestPath.String())
- linkDeps = append(linkDeps, manifestPath)
-
- linkFlags = append(linkFlags, android.JoinWithPrefix(assetDirs.Strings(), "-A "))
- linkDeps = append(linkDeps, assetFiles...)
-
- // Include dirs
- ctx.VisitDirectDeps(func(module android.Module) {
- var depFiles android.Paths
- if javaDep, ok := module.(Dependency); ok {
- // TODO: shared android libraries
- if ctx.OtherModuleName(module) == "framework-res" {
- depFiles = android.Paths{javaDep.(*AndroidApp).exportPackage}
- }
- }
-
- for _, dep := range depFiles {
- linkFlags = append(linkFlags, "-I "+dep.String())
- }
- linkDeps = append(linkDeps, depFiles...)
- })
-
- sdkDep := decodeSdkDep(ctx, String(a.deviceProperties.Sdk_version))
- if sdkDep.useFiles {
- linkFlags = append(linkFlags, "-I "+sdkDep.jar.String())
- linkDeps = append(linkDeps, sdkDep.jar)
- }
-
- // SDK version flags
- sdkVersion := String(a.deviceProperties.Sdk_version)
- switch sdkVersion {
- case "", "current", "system_current", "test_current":
- sdkVersion = proptools.NinjaEscape([]string{ctx.Config().DefaultAppTargetSdk()})[0]
- }
-
- linkFlags = append(linkFlags, "--min-sdk-version "+sdkVersion)
- linkFlags = append(linkFlags, "--target-sdk-version "+sdkVersion)
-
- // Product characteristics
- if !hasProduct && len(ctx.Config().ProductAAPTCharacteristics()) > 0 {
- linkFlags = append(linkFlags, "--product", ctx.Config().ProductAAPTCharacteristics())
- }
-
- // Product AAPT config
- for _, aaptConfig := range ctx.Config().ProductAAPTConfig() {
- linkFlags = append(linkFlags, "-c", aaptConfig)
- }
-
- // Product AAPT preferred config
- if len(ctx.Config().ProductAAPTPreferredConfig()) > 0 {
- linkFlags = append(linkFlags, "--preferred-density", ctx.Config().ProductAAPTPreferredConfig())
- }
-
- // Version code
- if !hasVersionCode {
- linkFlags = append(linkFlags, "--version-code", ctx.Config().PlatformSdkVersion())
- }
-
- if !hasVersionName {
- var versionName string
- if ctx.ModuleName() == "framework-res" {
- // Some builds set AppsDefaultVersionName() to include the build number ("O-123456"). aapt2 copies the
- // version name of framework-res into app manifests as compileSdkVersionCodename, which confuses things
- // if it contains the build number. Use the DefaultAppTargetSdk instead.
- versionName = ctx.Config().DefaultAppTargetSdk()
- } else {
- versionName = ctx.Config().AppsDefaultVersionName()
- }
- versionName = proptools.NinjaEscape([]string{versionName})[0]
- linkFlags = append(linkFlags, "--version-name ", versionName)
- }
-
- if String(a.appProperties.Instrumentation_for) != "" {
- linkFlags = append(linkFlags,
- "--rename-instrumentation-target-package",
- String(a.appProperties.Instrumentation_for))
- }
-
- // TODO: LOCAL_PACKAGE_OVERRIDES
- // $(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
-
- return linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, manifestPath
-}
-
func AndroidAppFactory() android.Module {
module := &AndroidApp{}
@@ -344,92 +191,10 @@ func AndroidAppFactory() android.Module {
module.AddProperties(
&module.Module.properties,
&module.Module.deviceProperties,
+ &module.Module.protoProperties,
+ &module.aaptProperties,
&module.appProperties)
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
return module
}
-
-func resourceGlob(ctx android.ModuleContext, dir android.Path) android.Paths {
- return ctx.GlobFiles(filepath.Join(dir.String(), "**/*"), aaptIgnoreFilenames)
-}
-
-type overlayGlobResult struct {
- dir string
- paths android.DirectorySortedPaths
-
- // Set to true of the product has selected that values in this overlay should not be moved to
- // Runtime Resource Overlay (RRO) packages.
- excludeFromRRO bool
-}
-
-const overlayDataKey = "overlayDataKey"
-
-func overlayResourceGlob(ctx android.ModuleContext, dir android.Path) (res []globbedResourceDir,
- rroDirs android.Paths) {
-
- overlayData := ctx.Config().Get(overlayDataKey).([]overlayGlobResult)
-
- // Runtime resource overlays (RRO) may be turned on by the product config for some modules
- rroEnabled := ctx.Config().EnforceRROForModule(ctx.ModuleName())
-
- for _, data := range overlayData {
- files := data.paths.PathsInDirectory(filepath.Join(data.dir, dir.String()))
- if len(files) > 0 {
- overlayModuleDir := android.PathForSource(ctx, data.dir, dir.String())
- // If enforce RRO is enabled for this module and this overlay is not in the
- // exclusion list, ignore the overlay. The list of ignored overlays will be
- // passed to Make to be turned into an RRO package.
- if rroEnabled && !data.excludeFromRRO {
- rroDirs = append(rroDirs, overlayModuleDir)
- } else {
- res = append(res, globbedResourceDir{
- dir: overlayModuleDir,
- files: files,
- })
- }
- }
- }
-
- return res, rroDirs
-}
-
-func OverlaySingletonFactory() android.Singleton {
- return overlaySingleton{}
-}
-
-type overlaySingleton struct{}
-
-func (overlaySingleton) GenerateBuildActions(ctx android.SingletonContext) {
- var overlayData []overlayGlobResult
- overlayDirs := ctx.Config().ResourceOverlays()
- for i := range overlayDirs {
- // Iterate backwards through the list of overlay directories so that the later, lower-priority
- // directories in the list show up earlier in the command line to aapt2.
- overlay := overlayDirs[len(overlayDirs)-1-i]
- var result overlayGlobResult
- result.dir = overlay
-
- // Mark overlays that will not have Runtime Resource Overlays enforced on them
- // based on the product config
- result.excludeFromRRO = ctx.Config().EnforceRROExcludedOverlay(overlay)
-
- files, err := ctx.GlobWithDeps(filepath.Join(overlay, "**/*"), aaptIgnoreFilenames)
- if err != nil {
- ctx.Errorf("failed to glob resource dir %q: %s", overlay, err.Error())
- continue
- }
- var paths android.Paths
- for _, f := range files {
- if !strings.HasSuffix(f, "/") {
- paths = append(paths, android.PathForSource(ctx, f))
- }
- }
- result.paths = android.PathsToDirectorySortedPaths(paths)
- overlayData = append(overlayData, result)
- }
-
- ctx.Config().Once(overlayDataKey, func() interface{} {
- return overlayData
- })
-}
diff --git a/java/app_builder.go b/java/app_builder.go
index 945d7bdb..954ca446 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -96,3 +96,39 @@ func CreateAppPackage(ctx android.ModuleContext, outputFile android.WritablePath
},
})
}
+
+var buildAAR = pctx.AndroidStaticRule("buildAAR",
+ blueprint.RuleParams{
+ Command: `rm -rf ${outDir} && mkdir -p ${outDir} && ` +
+ `cp ${manifest} ${outDir}/AndroidManifest.xml && ` +
+ `cp ${classesJar} ${outDir}/classes.jar && ` +
+ `cp ${rTxt} ${outDir}/R.txt && ` +
+ `${config.SoongZipCmd} -jar -o $out -C ${outDir} -D ${outDir} ${resArgs}`,
+ CommandDeps: []string{"${config.SoongZipCmd}"},
+ },
+ "manifest", "classesJar", "rTxt", "resArgs", "outDir")
+
+func BuildAAR(ctx android.ModuleContext, outputFile android.WritablePath,
+ classesJar, manifest, rTxt android.Path, res android.Paths) {
+
+ // TODO(ccross): uniquify and copy resources with dependencies
+
+ deps := android.Paths{manifest, rTxt}
+ classesJarPath := ""
+ if classesJar != nil {
+ deps = append(deps, classesJar)
+ classesJarPath = classesJar.String()
+ }
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: buildAAR,
+ Implicits: deps,
+ Output: outputFile,
+ Args: map[string]string{
+ "manifest": manifest.String(),
+ "classesJar": classesJarPath,
+ "rTxt": rTxt.String(),
+ "outDir": android.PathForModuleOut(ctx, "aar").String(),
+ },
+ })
+}
diff --git a/java/app_test.go b/java/app_test.go
index 2e531303..6770119e 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -61,41 +61,44 @@ func testApp(t *testing.T, bp string) *android.TestContext {
}
func TestApp(t *testing.T) {
- ctx := testApp(t, `
- android_app {
- name: "foo",
- srcs: ["a.java"],
- }
- `)
+ for _, moduleType := range []string{"android_app", "android_library"} {
+ t.Run(moduleType, func(t *testing.T) {
+ ctx := testApp(t, moduleType+` {
+ name: "foo",
+ srcs: ["a.java"],
+ }
+ `)
- foo := ctx.ModuleForTests("foo", "android_common")
+ foo := ctx.ModuleForTests("foo", "android_common")
- expectedLinkImplicits := []string{"AndroidManifest.xml"}
+ expectedLinkImplicits := []string{"AndroidManifest.xml"}
- frameworkRes := ctx.ModuleForTests("framework-res", "android_common")
- expectedLinkImplicits = append(expectedLinkImplicits,
- frameworkRes.Output("package-res.apk").Output.String())
+ frameworkRes := ctx.ModuleForTests("framework-res", "android_common")
+ expectedLinkImplicits = append(expectedLinkImplicits,
+ frameworkRes.Output("package-res.apk").Output.String())
- // Test the mapping from input files to compiled output file names
- compile := foo.Output(compiledResourceFiles[0])
- if !reflect.DeepEqual(resourceFiles, compile.Inputs.Strings()) {
- t.Errorf("expected aapt2 compile inputs expected:\n %#v\n got:\n %#v",
- resourceFiles, compile.Inputs.Strings())
- }
+ // Test the mapping from input files to compiled output file names
+ compile := foo.Output(compiledResourceFiles[0])
+ if !reflect.DeepEqual(resourceFiles, compile.Inputs.Strings()) {
+ t.Errorf("expected aapt2 compile inputs expected:\n %#v\n got:\n %#v",
+ resourceFiles, compile.Inputs.Strings())
+ }
- compiledResourceOutputs := compile.Outputs.Strings()
- sort.Strings(compiledResourceOutputs)
+ compiledResourceOutputs := compile.Outputs.Strings()
+ sort.Strings(compiledResourceOutputs)
- expectedLinkImplicits = append(expectedLinkImplicits, compiledResourceOutputs...)
+ expectedLinkImplicits = append(expectedLinkImplicits, compiledResourceOutputs...)
- list := foo.Output("aapt2/res.list")
- expectedLinkImplicits = append(expectedLinkImplicits, list.Output.String())
+ list := foo.Output("aapt2/res.list")
+ expectedLinkImplicits = append(expectedLinkImplicits, list.Output.String())
- // Check that the link rule uses
- res := ctx.ModuleForTests("foo", "android_common").Output("package-res.apk")
- if !reflect.DeepEqual(expectedLinkImplicits, res.Implicits.Strings()) {
- t.Errorf("expected aapt2 link implicits expected:\n %#v\n got:\n %#v",
- expectedLinkImplicits, res.Implicits.Strings())
+ // Check that the link rule uses
+ res := ctx.ModuleForTests("foo", "android_common").Output("package-res.apk")
+ if !reflect.DeepEqual(expectedLinkImplicits, res.Implicits.Strings()) {
+ t.Errorf("expected aapt2 link implicits expected:\n %#v\n got:\n %#v",
+ expectedLinkImplicits, res.Implicits.Strings())
+ }
+ })
}
}
@@ -288,45 +291,47 @@ func TestAppSdkVersion(t *testing.T) {
},
}
- for _, test := range testCases {
- t.Run(test.name, func(t *testing.T) {
- bp := fmt.Sprintf(`android_app {
+ for _, moduleType := range []string{"android_app", "android_library"} {
+ for _, test := range testCases {
+ t.Run(moduleType+" "+test.name, func(t *testing.T) {
+ bp := fmt.Sprintf(`%s {
name: "foo",
srcs: ["a.java"],
sdk_version: "%s",
- }`, test.sdkVersion)
+ }`, moduleType, test.sdkVersion)
- config := testConfig(nil)
- config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt
- config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename
- config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal
+ config := testConfig(nil)
+ config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt
+ config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename
+ config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal
- ctx := testAppContext(config, bp, nil)
+ ctx := testAppContext(config, bp, nil)
- run(t, ctx, config)
+ run(t, ctx, config)
- foo := ctx.ModuleForTests("foo", "android_common")
- link := foo.Output("package-res.apk")
- linkFlags := strings.Split(link.Args["flags"], " ")
- min := android.IndexList("--min-sdk-version", linkFlags)
- target := android.IndexList("--target-sdk-version", linkFlags)
+ foo := ctx.ModuleForTests("foo", "android_common")
+ link := foo.Output("package-res.apk")
+ linkFlags := strings.Split(link.Args["flags"], " ")
+ min := android.IndexList("--min-sdk-version", linkFlags)
+ target := android.IndexList("--target-sdk-version", linkFlags)
- if min == -1 || target == -1 || min == len(linkFlags)-1 || target == len(linkFlags)-1 {
- t.Fatalf("missing --min-sdk-version or --target-sdk-version in link flags: %q", linkFlags)
- }
+ if min == -1 || target == -1 || min == len(linkFlags)-1 || target == len(linkFlags)-1 {
+ t.Fatalf("missing --min-sdk-version or --target-sdk-version in link flags: %q", linkFlags)
+ }
- gotMinSdkVersion := linkFlags[min+1]
- gotTargetSdkVersion := linkFlags[target+1]
+ gotMinSdkVersion := linkFlags[min+1]
+ gotTargetSdkVersion := linkFlags[target+1]
- if gotMinSdkVersion != test.expectedMinSdkVersion {
- t.Errorf("incorrect --min-sdk-version, expected %q got %q",
- test.expectedMinSdkVersion, gotMinSdkVersion)
- }
+ if gotMinSdkVersion != test.expectedMinSdkVersion {
+ t.Errorf("incorrect --min-sdk-version, expected %q got %q",
+ test.expectedMinSdkVersion, gotMinSdkVersion)
+ }
- if gotTargetSdkVersion != test.expectedMinSdkVersion {
- t.Errorf("incorrect --target-sdk-version, expected %q got %q",
- test.expectedMinSdkVersion, gotTargetSdkVersion)
- }
- })
+ if gotTargetSdkVersion != test.expectedMinSdkVersion {
+ t.Errorf("incorrect --target-sdk-version, expected %q got %q",
+ test.expectedMinSdkVersion, gotTargetSdkVersion)
+ }
+ })
+ }
}
}
diff --git a/java/config/config.go b/java/config/config.go
index 5587a16d..980db3b0 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -87,6 +87,7 @@ func init() {
pctx.SourcePathVariable("GenKotlinBuildFileCmd", "build/soong/scripts/gen-kotlin-build-file.sh")
pctx.SourcePathVariable("JarArgsCmd", "build/soong/scripts/jar-args.sh")
+ pctx.HostBinToolVariable("ExtractJarPackagesCmd", "extract_jar_packages")
pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
pctx.HostBinToolVariable("MergeZipsCmd", "merge_zips")
pctx.HostBinToolVariable("Zip2ZipCmd", "zip2zip")
diff --git a/java/config/makevars.go b/java/config/makevars.go
index 5210f202..27c7daaa 100644
--- a/java/config/makevars.go
+++ b/java/config/makevars.go
@@ -77,4 +77,6 @@ func makeVarsProvider(ctx android.MakeVarsContext) {
ctx.Strict("JACOCO_CLI_JAR", "${JacocoCLIJar}")
ctx.Strict("DEFAULT_JACOCO_EXCLUDE_FILTER", strings.Join(DefaultJacocoExcludeFilter, ","))
+
+ ctx.Strict("EXTRACT_JAR_PACKAGES", "${ExtractJarPackagesCmd}")
}
diff --git a/java/java.go b/java/java.go
index d4db7157..619ae754 100644
--- a/java/java.go
+++ b/java/java.go
@@ -312,6 +312,8 @@ type sdkDep struct {
module string
systemModules string
+ frameworkResModule string
+
jar android.Path
aidl android.Path
}
@@ -406,6 +408,7 @@ func decodeSdkDep(ctx android.BaseContext, v string) sdkDep {
// useModule: true,
// module: m,
// systemModules: m + "_system_modules",
+ // frameworkResModule: r,
// }
//}
@@ -416,16 +419,17 @@ func decodeSdkDep(ctx android.BaseContext, v string) sdkDep {
switch v {
case "":
return sdkDep{
- useDefaultLibs: true,
+ useDefaultLibs: true,
+ frameworkResModule: "framework-res",
}
// TODO(ccross): re-enable these once we generate stubs, until then
// use the stubs in prebuilts/sdk/*current
//case "current":
- // return toModule("android_stubs_current")
+ // return toModule("android_stubs_current", "framework-res")
//case "system_current":
- // return toModule("android_system_stubs_current")
+ // return toModule("android_system_stubs_current", "framework-res")
//case "test_current":
- // return toModule("android_test_stubs_current")
+ // return toModule("android_test_stubs_current", "framework-res")
default:
return toFile(v)
}
@@ -592,7 +596,10 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
tag := ctx.OtherModuleDependencyTag(module)
if to, ok := module.(*Library); ok {
- checkLinkType(ctx, j, to, tag.(dependencyTag))
+ switch tag {
+ case bootClasspathTag, libTag, staticLibTag:
+ checkLinkType(ctx, j, to, tag.(dependencyTag))
+ }
}
switch dep := module.(type) {
case Dependency:
diff --git a/java/resources.go b/java/java_resources.go
index a596fd7e..a596fd7e 100644
--- a/java/resources.go
+++ b/java/java_resources.go
diff --git a/java/java_test.go b/java/java_test.go
index 015c2331..fb8cc949 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -70,6 +70,7 @@ func testContext(config android.Config, bp string,
ctx := android.NewTestArchContext()
ctx.RegisterModuleType("android_app", android.ModuleFactoryAdaptor(AndroidAppFactory))
+ ctx.RegisterModuleType("android_library", android.ModuleFactoryAdaptor(AndroidLibraryFactory))
ctx.RegisterModuleType("java_binary_host", android.ModuleFactoryAdaptor(BinaryHostFactory))
ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(LibraryFactory(true)))
ctx.RegisterModuleType("java_library_host", android.ModuleFactoryAdaptor(LibraryHostFactory))
diff --git a/java/support_libraries.go b/java/support_libraries.go
new file mode 100644
index 00000000..320afae1
--- /dev/null
+++ b/java/support_libraries.go
@@ -0,0 +1,66 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+ "sort"
+ "strings"
+
+ "android/soong/android"
+)
+
+func init() {
+ android.RegisterMakeVarsProvider(pctx, supportLibrariesMakeVarsProvider)
+}
+
+func supportLibrariesMakeVarsProvider(ctx android.MakeVarsContext) {
+ var supportAars, supportJars []string
+
+ sctx := ctx.SingletonContext()
+ sctx.VisitAllModules(func(module android.Module) {
+ dir := sctx.ModuleDir(module)
+ switch {
+ case strings.HasPrefix(dir, "prebuilts/sdk/current/extras"),
+ dir == "prebuilts/sdk/current/androidx",
+ dir == "prebuilts/sdk/current/car",
+ dir == "prebuilts/sdk/current/optional",
+ dir == "prebuilts/sdk/current/support":
+ // Support library
+ default:
+ // Not a support library
+ return
+ }
+
+ name := sctx.ModuleName(module)
+ if strings.HasSuffix(name, "-nodeps") {
+ return
+ }
+
+ switch module.(type) {
+ case *AndroidLibrary, *AARImport:
+ supportAars = append(supportAars, name)
+ case *Library, *Import:
+ supportJars = append(supportJars, name)
+ default:
+ sctx.ModuleErrorf(module, "unknown module type %t", module)
+ }
+ })
+
+ sort.Strings(supportAars)
+ sort.Strings(supportJars)
+
+ ctx.Strict("SUPPORT_LIBRARIES_AARS", strings.Join(supportAars, " "))
+ ctx.Strict("SUPPORT_LIBRARIES_JARS", strings.Join(supportJars, " "))
+}
diff --git a/ui/logger/logger.go b/ui/logger/logger.go
index 15c413dd..c763e50c 100644
--- a/ui/logger/logger.go
+++ b/ui/logger/logger.go
@@ -85,7 +85,7 @@ func fileRotation(from, baseName, ext string, cur, max int) error {
}
if err := os.Rename(from, newName); err != nil {
- return fmt.Errorf("Failed to rotate", from, "to", newName, ".", err)
+ return fmt.Errorf("Failed to rotate %s to %s. %s", from, newName, err)
}
return nil
}
diff --git a/ui/logger/logger_test.go b/ui/logger/logger_test.go
index dc6f2e91..bdf0231a 100644
--- a/ui/logger/logger_test.go
+++ b/ui/logger/logger_test.go
@@ -106,7 +106,7 @@ func TestPanic(t *testing.T) {
if p == panicValue {
os.Exit(42)
} else {
- fmt.Fprintln(os.Stderr, "Expected %q, got %v", panicValue, p)
+ fmt.Fprintf(os.Stderr, "Expected %q, got %v\n", panicValue, p)
os.Exit(3)
}
}()