Merge "soong: Fix AndroidMk with *Required properties"
This commit is contained in:
@@ -81,6 +81,7 @@ bootstrap_go_package {
|
|||||||
],
|
],
|
||||||
testSrcs: [
|
testSrcs: [
|
||||||
"android/android_test.go",
|
"android/android_test.go",
|
||||||
|
"android/androidmk_test.go",
|
||||||
"android/arch_test.go",
|
"android/arch_test.go",
|
||||||
"android/config_test.go",
|
"android/config_test.go",
|
||||||
"android/expand_test.go",
|
"android/expand_test.go",
|
||||||
@@ -291,6 +292,7 @@ bootstrap_go_package {
|
|||||||
"java/testing.go",
|
"java/testing.go",
|
||||||
],
|
],
|
||||||
testSrcs: [
|
testSrcs: [
|
||||||
|
"java/androidmk_test.go",
|
||||||
"java/app_test.go",
|
"java/app_test.go",
|
||||||
"java/device_host_converter_test.go",
|
"java/device_host_converter_test.go",
|
||||||
"java/dexpreopt_test.go",
|
"java/dexpreopt_test.go",
|
||||||
|
@@ -391,6 +391,31 @@ func translateGoBinaryModule(ctx SingletonContext, w io.Writer, mod blueprint.Mo
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (data *AndroidMkData) fillInData(config Config, bpPath string, mod blueprint.Module) {
|
||||||
|
// Get the preamble content through AndroidMkEntries logic.
|
||||||
|
entries := AndroidMkEntries{
|
||||||
|
Class: data.Class,
|
||||||
|
SubName: data.SubName,
|
||||||
|
DistFile: data.DistFile,
|
||||||
|
OutputFile: data.OutputFile,
|
||||||
|
Disabled: data.Disabled,
|
||||||
|
Include: data.Include,
|
||||||
|
Required: data.Required,
|
||||||
|
Host_required: data.Host_required,
|
||||||
|
Target_required: data.Target_required,
|
||||||
|
}
|
||||||
|
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,
|
func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
|
||||||
provider AndroidMkDataProvider) error {
|
provider AndroidMkDataProvider) error {
|
||||||
|
|
||||||
@@ -404,22 +429,7 @@ func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Mod
|
|||||||
data.Include = "$(BUILD_PREBUILT)"
|
data.Include = "$(BUILD_PREBUILT)"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the preamble content through AndroidMkEntries logic.
|
data.fillInData(ctx.Config(), ctx.BlueprintFile(mod), mod)
|
||||||
entries := AndroidMkEntries{
|
|
||||||
Class: data.Class,
|
|
||||||
SubName: data.SubName,
|
|
||||||
DistFile: data.DistFile,
|
|
||||||
OutputFile: data.OutputFile,
|
|
||||||
Disabled: data.Disabled,
|
|
||||||
Include: data.Include,
|
|
||||||
Required: data.Required,
|
|
||||||
Host_required: data.Host_required,
|
|
||||||
Target_required: data.Target_required,
|
|
||||||
}
|
|
||||||
entries.fillInEntries(ctx.Config(), ctx.BlueprintFile(mod), mod)
|
|
||||||
// preamble doesn't need the footer content.
|
|
||||||
entries.footer = bytes.Buffer{}
|
|
||||||
entries.write(&data.preamble)
|
|
||||||
|
|
||||||
prefix := ""
|
prefix := ""
|
||||||
if amod.ArchSpecific() {
|
if amod.ArchSpecific() {
|
||||||
|
82
android/androidmk_test.go
Normal file
82
android/androidmk_test.go
Normal file
@@ -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)
|
||||||
|
}
|
@@ -382,3 +382,14 @@ func AndroidMkEntriesForTest(t *testing.T, config Config, bpPath string, mod blu
|
|||||||
entries.fillInEntries(config, bpPath, mod)
|
entries.fillInEntries(config, bpPath, mod)
|
||||||
return entries
|
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
|
||||||
|
}
|
||||||
|
@@ -115,6 +115,17 @@ func PrefixInList(s string, list []string) bool {
|
|||||||
return false
|
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) {
|
func FilterList(list []string, filter []string) (remainder []string, filtered []string) {
|
||||||
for _, l := range list {
|
for _, l := range list {
|
||||||
if InList(l, filter) {
|
if InList(l, filter) {
|
||||||
|
184
java/androidmk_test.go
Normal file
184
java/androidmk_test.go
Normal file
@@ -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")
|
||||||
|
}
|
Reference in New Issue
Block a user