aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2019-07-16 02:09:29 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2019-07-16 02:09:29 +0000
commit0f7dbd0d553e7bd5dc09d11464ef2df782822aee (patch)
treedea0fc501d7dce54d767d4ff0cd162eb44f98528
parent34b1b279814b2131ecfa3b4d14fdbae02b391951 (diff)
parent12df5fb47174ac5a4f365deb99942644092b549b (diff)
downloadbuild_soong-0f7dbd0d553e7bd5dc09d11464ef2df782822aee.tar.gz
build_soong-0f7dbd0d553e7bd5dc09d11464ef2df782822aee.tar.bz2
build_soong-0f7dbd0d553e7bd5dc09d11464ef2df782822aee.zip
Merge "soong: Fix AndroidMk with *Required properties"
-rw-r--r--Android.bp2
-rw-r--r--android/androidmk.go38
-rw-r--r--android/androidmk_test.go82
-rw-r--r--android/testing.go11
-rw-r--r--android/util.go11
-rw-r--r--java/androidmk_test.go184
6 files changed, 314 insertions, 14 deletions
diff --git a/Android.bp b/Android.bp
index 1b68adb1..4893de6d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -81,6 +81,7 @@ bootstrap_go_package {
],
testSrcs: [
"android/android_test.go",
+ "android/androidmk_test.go",
"android/arch_test.go",
"android/config_test.go",
"android/expand_test.go",
@@ -291,6 +292,7 @@ bootstrap_go_package {
"java/testing.go",
],
testSrcs: [
+ "java/androidmk_test.go",
"java/app_test.go",
"java/device_host_converter_test.go",
"java/dexpreopt_test.go",
diff --git a/android/androidmk.go b/android/androidmk.go
index 9bc26922..c24ac578 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -391,19 +391,7 @@ func translateGoBinaryModule(ctx SingletonContext, w io.Writer, mod blueprint.Mo
return nil
}
-func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
- provider AndroidMkDataProvider) error {
-
- amod := mod.(Module).base()
- if shouldSkipAndroidMkProcessing(amod) {
- return nil
- }
-
- data := provider.AndroidMk()
- if data.Include == "" {
- data.Include = "$(BUILD_PREBUILT)"
- }
-
+func (data *AndroidMkData) fillInData(config Config, bpPath string, mod blueprint.Module) {
// Get the preamble content through AndroidMkEntries logic.
entries := AndroidMkEntries{
Class: data.Class,
@@ -416,11 +404,33 @@ func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Mod
Host_required: data.Host_required,
Target_required: data.Target_required,
}
- entries.fillInEntries(ctx.Config(), ctx.BlueprintFile(mod), mod)
+ entries.fillInEntries(config, bpPath, mod)
+
// preamble doesn't need the footer content.
entries.footer = bytes.Buffer{}
entries.write(&data.preamble)
+ // copy entries back to data since it is used in Custom
+ data.Required = entries.Required
+ data.Host_required = entries.Host_required
+ data.Target_required = entries.Target_required
+}
+
+func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
+ provider AndroidMkDataProvider) error {
+
+ amod := mod.(Module).base()
+ if shouldSkipAndroidMkProcessing(amod) {
+ return nil
+ }
+
+ data := provider.AndroidMk()
+ if data.Include == "" {
+ data.Include = "$(BUILD_PREBUILT)"
+ }
+
+ data.fillInData(ctx.Config(), ctx.BlueprintFile(mod), mod)
+
prefix := ""
if amod.ArchSpecific() {
switch amod.Os().Class {
diff --git a/android/androidmk_test.go b/android/androidmk_test.go
new file mode 100644
index 00000000..0bb455bb
--- /dev/null
+++ b/android/androidmk_test.go
@@ -0,0 +1,82 @@
+// Copyright 2019 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 android
+
+import (
+ "io"
+ "reflect"
+ "testing"
+)
+
+type customModule struct {
+ ModuleBase
+ data AndroidMkData
+}
+
+func (m *customModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+}
+
+func (m *customModule) AndroidMk() AndroidMkData {
+ return AndroidMkData{
+ Custom: func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) {
+ m.data = data
+ },
+ }
+}
+
+func customModuleFactory() Module {
+ module := &customModule{}
+ InitAndroidModule(module)
+ return module
+}
+
+func TestAndroidMkSingleton_PassesUpdatedAndroidMkDataToCustomCallback(t *testing.T) {
+ config := TestConfig(buildDir, nil)
+ config.inMake = true // Enable androidmk Singleton
+
+ ctx := NewTestContext()
+ ctx.RegisterSingletonType("androidmk", SingletonFactoryAdaptor(AndroidMkSingleton))
+ ctx.RegisterModuleType("custom", ModuleFactoryAdaptor(customModuleFactory))
+ ctx.Register()
+
+ bp := `
+ custom {
+ name: "foo",
+ required: ["bar"],
+ host_required: ["baz"],
+ target_required: ["qux"],
+ }
+ `
+
+ ctx.MockFileSystem(map[string][]byte{
+ "Android.bp": []byte(bp),
+ })
+
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ FailIfErrored(t, errs)
+
+ m := ctx.ModuleForTests("foo", "").Module().(*customModule)
+
+ assertEqual := func(expected interface{}, actual interface{}) {
+ if !reflect.DeepEqual(expected, actual) {
+ t.Errorf("%q expected, but got %q", expected, actual)
+ }
+ }
+ assertEqual([]string{"bar"}, m.data.Required)
+ assertEqual([]string{"baz"}, m.data.Host_required)
+ assertEqual([]string{"qux"}, m.data.Target_required)
+}
diff --git a/android/testing.go b/android/testing.go
index 44bee4b7..12e30ec5 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -382,3 +382,14 @@ func AndroidMkEntriesForTest(t *testing.T, config Config, bpPath string, mod blu
entries.fillInEntries(config, bpPath, mod)
return entries
}
+
+func AndroidMkDataForTest(t *testing.T, config Config, bpPath string, mod blueprint.Module) AndroidMkData {
+ var p AndroidMkDataProvider
+ var ok bool
+ if p, ok = mod.(AndroidMkDataProvider); !ok {
+ t.Errorf("module does not implmement AndroidMkDataProvider: " + mod.Name())
+ }
+ data := p.AndroidMk()
+ data.fillInData(config, bpPath, mod)
+ return data
+}
diff --git a/android/util.go b/android/util.go
index 3b8bc783..97bec102 100644
--- a/android/util.go
+++ b/android/util.go
@@ -115,6 +115,17 @@ func PrefixInList(s string, list []string) bool {
return false
}
+// IndexListPred returns the index of the element which in the given `list` satisfying the predicate, or -1 if there is no such element.
+func IndexListPred(pred func(s string) bool, list []string) int {
+ for i, l := range list {
+ if pred(l) {
+ return i
+ }
+ }
+
+ return -1
+}
+
func FilterList(list []string, filter []string) (remainder []string, filtered []string) {
for _, l := range list {
if InList(l, filter) {
diff --git a/java/androidmk_test.go b/java/androidmk_test.go
new file mode 100644
index 00000000..107837d0
--- /dev/null
+++ b/java/androidmk_test.go
@@ -0,0 +1,184 @@
+// Copyright 2019 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 (
+ "android/soong/android"
+ "bytes"
+ "io"
+ "io/ioutil"
+ "strings"
+ "testing"
+)
+
+type testAndroidMk struct {
+ *testing.T
+ body []byte
+}
+type testAndroidMkModule struct {
+ *testing.T
+ props map[string]string
+}
+
+func newTestAndroidMk(t *testing.T, r io.Reader) *testAndroidMk {
+ t.Helper()
+ buf, err := ioutil.ReadAll(r)
+ if err != nil {
+ t.Fatal("failed to open read Android.mk.", err)
+ }
+ return &testAndroidMk{
+ T: t,
+ body: buf,
+ }
+}
+
+func parseAndroidMkProps(lines []string) map[string]string {
+ props := make(map[string]string)
+ for _, line := range lines {
+ line = strings.TrimLeft(line, " ")
+ if line == "" || strings.HasPrefix(line, "#") {
+ continue
+ }
+ tokens := strings.Split(line, " ")
+ if tokens[1] == "+=" {
+ props[tokens[0]] += " " + strings.Join(tokens[2:], " ")
+ } else {
+ props[tokens[0]] = strings.Join(tokens[2:], " ")
+ }
+ }
+ return props
+}
+
+func (t *testAndroidMk) moduleFor(moduleName string) *testAndroidMkModule {
+ t.Helper()
+ lines := strings.Split(string(t.body), "\n")
+ index := android.IndexList("LOCAL_MODULE := "+moduleName, lines)
+ if index == -1 {
+ t.Fatalf("%q is not found.", moduleName)
+ }
+ lines = lines[index:]
+ includeIndex := android.IndexListPred(func(line string) bool {
+ return strings.HasPrefix(line, "include")
+ }, lines)
+ if includeIndex == -1 {
+ t.Fatalf("%q is not properly defined. (\"include\" not found).", moduleName)
+ }
+ props := parseAndroidMkProps(lines[:includeIndex])
+ return &testAndroidMkModule{
+ T: t.T,
+ props: props,
+ }
+}
+
+func (t *testAndroidMkModule) hasRequired(dep string) {
+ t.Helper()
+ required, ok := t.props["LOCAL_REQUIRED_MODULES"]
+ if !ok {
+ t.Error("LOCAL_REQUIRED_MODULES is not found.")
+ return
+ }
+ if !android.InList(dep, strings.Split(required, " ")) {
+ t.Errorf("%q is expected in LOCAL_REQUIRED_MODULES, but not found in %q.", dep, required)
+ }
+}
+
+func (t *testAndroidMkModule) hasNoRequired(dep string) {
+ t.Helper()
+ required, ok := t.props["LOCAL_REQUIRED_MODULES"]
+ if !ok {
+ return
+ }
+ if android.InList(dep, strings.Split(required, " ")) {
+ t.Errorf("%q is not expected in LOCAL_REQUIRED_MODULES, but found.", dep)
+ }
+}
+
+func getAndroidMk(t *testing.T, ctx *android.TestContext, config android.Config, name string) *testAndroidMk {
+ t.Helper()
+ lib, _ := ctx.ModuleForTests(name, "android_common").Module().(*Library)
+ data := android.AndroidMkDataForTest(t, config, "", lib)
+ w := &bytes.Buffer{}
+ data.Custom(w, name, "", "", data)
+ return newTestAndroidMk(t, w)
+}
+
+func TestRequired(t *testing.T) {
+ config := testConfig(nil)
+ ctx := testContext(config, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ required: ["libfoo"],
+ }
+ `, nil)
+ run(t, ctx, config)
+
+ mk := getAndroidMk(t, ctx, config, "foo")
+ mk.moduleFor("foo").hasRequired("libfoo")
+}
+
+func TestHostdex(t *testing.T) {
+ config := testConfig(nil)
+ ctx := testContext(config, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ hostdex: true,
+ }
+ `, nil)
+ run(t, ctx, config)
+
+ mk := getAndroidMk(t, ctx, config, "foo")
+ mk.moduleFor("foo")
+ mk.moduleFor("foo-hostdex")
+}
+
+func TestHostdexRequired(t *testing.T) {
+ config := testConfig(nil)
+ ctx := testContext(config, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ hostdex: true,
+ required: ["libfoo"],
+ }
+ `, nil)
+ run(t, ctx, config)
+
+ mk := getAndroidMk(t, ctx, config, "foo")
+ mk.moduleFor("foo").hasRequired("libfoo")
+ mk.moduleFor("foo-hostdex").hasRequired("libfoo")
+}
+
+func TestHostdexSpecificRequired(t *testing.T) {
+ config := testConfig(nil)
+ ctx := testContext(config, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ hostdex: true,
+ target: {
+ hostdex: {
+ required: ["libfoo"],
+ },
+ },
+ }
+ `, nil)
+ run(t, ctx, config)
+
+ mk := getAndroidMk(t, ctx, config, "foo")
+ mk.moduleFor("foo").hasNoRequired("libfoo")
+ mk.moduleFor("foo-hostdex").hasRequired("libfoo")
+}