Merge "soong: Fix AndroidMk with *Required properties"
am: 0f7dbd0d55
Change-Id: I588aeda47a66334b16294e36333f653001fd37b1
This commit is contained in:
commit
962982a731
6 changed files with 316 additions and 16 deletions
|
@ -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",
|
||||
|
|
|
@ -391,6 +391,31 @@ func translateGoBinaryModule(ctx SingletonContext, w io.Writer, mod blueprint.Mo
|
|||
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,
|
||||
provider AndroidMkDataProvider) error {
|
||||
|
||||
|
@ -404,22 +429,7 @@ func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Mod
|
|||
data.Include = "$(BUILD_PREBUILT)"
|
||||
}
|
||||
|
||||
// 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(ctx.Config(), ctx.BlueprintFile(mod), mod)
|
||||
// preamble doesn't need the footer content.
|
||||
entries.footer = bytes.Buffer{}
|
||||
entries.write(&data.preamble)
|
||||
data.fillInData(ctx.Config(), ctx.BlueprintFile(mod), mod)
|
||||
|
||||
prefix := ""
|
||||
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)
|
||||
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
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
|
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")
|
||||
}
|
Loading…
Reference in a new issue