Support tagged module references
There are cases where a module needs to refer to an intermediate output of another module instead of its final output. For example, a module may want to use the .jar containing .class files from another module whose final output is a .jar containing classes.dex files. Support a new ":module{.tag}" format in any property that is annotated with `android:"path"`, which will query the target module for its ".tag" output(s). Test: path_properties_test.go, paths_test.go Test: no unexpected changes in build.ninja Change-Id: Icd3c9b0d83ff125771767c04046fcffb9fc3f65a
This commit is contained in:
parent
4c2c46f0a7
commit
41955e8895
|
@ -81,6 +81,7 @@ bootstrap_go_package {
|
|||
"android/arch_test.go",
|
||||
"android/config_test.go",
|
||||
"android/expand_test.go",
|
||||
"android/module_test.go",
|
||||
"android/namespace_test.go",
|
||||
"android/neverallow_test.go",
|
||||
"android/onceper_test.go",
|
||||
|
|
|
@ -1462,39 +1462,60 @@ func findStringInSlice(str string, slice []string) int {
|
|||
return -1
|
||||
}
|
||||
|
||||
func SrcIsModule(s string) string {
|
||||
// SrcIsModule decodes module references in the format ":name" into the module name, or empty string if the input
|
||||
// was not a module reference.
|
||||
func SrcIsModule(s string) (module string) {
|
||||
if len(s) > 1 && s[0] == ':' {
|
||||
return s[1:]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type sourceDependencyTag struct {
|
||||
blueprint.BaseDependencyTag
|
||||
// SrcIsModule decodes module references in the format ":name{.tag}" into the module name and tag, ":name" into the
|
||||
// module name and an empty string for the tag, or empty strings if the input was not a module reference.
|
||||
func SrcIsModuleWithTag(s string) (module, tag string) {
|
||||
if len(s) > 1 && s[0] == ':' {
|
||||
module = s[1:]
|
||||
if tagStart := strings.IndexByte(module, '{'); tagStart > 0 {
|
||||
if module[len(module)-1] == '}' {
|
||||
tag = module[tagStart+1 : len(module)-1]
|
||||
module = module[:tagStart]
|
||||
return module, tag
|
||||
}
|
||||
}
|
||||
return module, ""
|
||||
}
|
||||
return "", ""
|
||||
}
|
||||
|
||||
var SourceDepTag sourceDependencyTag
|
||||
type sourceOrOutputDependencyTag struct {
|
||||
blueprint.BaseDependencyTag
|
||||
tag string
|
||||
}
|
||||
|
||||
func sourceOrOutputDepTag(tag string) blueprint.DependencyTag {
|
||||
return sourceOrOutputDependencyTag{tag: tag}
|
||||
}
|
||||
|
||||
var SourceDepTag = sourceOrOutputDepTag("")
|
||||
|
||||
// Adds necessary dependencies to satisfy filegroup or generated sources modules listed in srcFiles
|
||||
// using ":module" syntax, if any.
|
||||
//
|
||||
// Deprecated: tag the property with `android:"path"` instead.
|
||||
func ExtractSourcesDeps(ctx BottomUpMutatorContext, srcFiles []string) {
|
||||
var deps []string
|
||||
set := make(map[string]bool)
|
||||
|
||||
for _, s := range srcFiles {
|
||||
if m := SrcIsModule(s); m != "" {
|
||||
if _, found := set[m]; found {
|
||||
ctx.ModuleErrorf("found source dependency duplicate: %q!", m)
|
||||
if m, t := SrcIsModuleWithTag(s); m != "" {
|
||||
if _, found := set[s]; found {
|
||||
ctx.ModuleErrorf("found source dependency duplicate: %q!", s)
|
||||
} else {
|
||||
set[m] = true
|
||||
deps = append(deps, m)
|
||||
set[s] = true
|
||||
ctx.AddDependency(ctx.Module(), sourceOrOutputDepTag(t), m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx.AddDependency(ctx.Module(), SourceDepTag, deps...)
|
||||
}
|
||||
|
||||
// Adds necessary dependencies to satisfy filegroup or generated sources modules specified in s
|
||||
|
@ -1503,16 +1524,25 @@ func ExtractSourcesDeps(ctx BottomUpMutatorContext, srcFiles []string) {
|
|||
// Deprecated: tag the property with `android:"path"` instead.
|
||||
func ExtractSourceDeps(ctx BottomUpMutatorContext, s *string) {
|
||||
if s != nil {
|
||||
if m := SrcIsModule(*s); m != "" {
|
||||
ctx.AddDependency(ctx.Module(), SourceDepTag, m)
|
||||
if m, t := SrcIsModuleWithTag(*s); m != "" {
|
||||
ctx.AddDependency(ctx.Module(), sourceOrOutputDepTag(t), m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A module that implements SourceFileProducer can be referenced from any property that is tagged with `android:"path"`
|
||||
// using the ":module" syntax and provides a list of paths to be used as if they were listed in the property.
|
||||
type SourceFileProducer interface {
|
||||
Srcs() Paths
|
||||
}
|
||||
|
||||
// A module that implements OutputFileProducer can be referenced from any property that is tagged with `android:"path"`
|
||||
// using the ":module" syntax or ":module{.tag}" syntax and provides a list of otuput files to be used as if they were
|
||||
// listed in the property.
|
||||
type OutputFileProducer interface {
|
||||
OutputFiles(tag string) (Paths, error)
|
||||
}
|
||||
|
||||
type HostToolProvider interface {
|
||||
HostToolPath() OptionalPath
|
||||
}
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
// Copyright 2015 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 "testing"
|
||||
|
||||
func TestSrcIsModule(t *testing.T) {
|
||||
type args struct {
|
||||
s string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantModule string
|
||||
}{
|
||||
{
|
||||
name: "file",
|
||||
args: args{
|
||||
s: "foo",
|
||||
},
|
||||
wantModule: "",
|
||||
},
|
||||
{
|
||||
name: "module",
|
||||
args: args{
|
||||
s: ":foo",
|
||||
},
|
||||
wantModule: "foo",
|
||||
},
|
||||
{
|
||||
name: "tag",
|
||||
args: args{
|
||||
s: ":foo{.bar}",
|
||||
},
|
||||
wantModule: "foo{.bar}",
|
||||
},
|
||||
{
|
||||
name: "extra colon",
|
||||
args: args{
|
||||
s: ":foo:bar",
|
||||
},
|
||||
wantModule: "foo:bar",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if gotModule := SrcIsModule(tt.args.s); gotModule != tt.wantModule {
|
||||
t.Errorf("SrcIsModule() = %v, want %v", gotModule, tt.wantModule)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSrcIsModuleWithTag(t *testing.T) {
|
||||
type args struct {
|
||||
s string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantModule string
|
||||
wantTag string
|
||||
}{
|
||||
{
|
||||
name: "file",
|
||||
args: args{
|
||||
s: "foo",
|
||||
},
|
||||
wantModule: "",
|
||||
wantTag: "",
|
||||
},
|
||||
{
|
||||
name: "module",
|
||||
args: args{
|
||||
s: ":foo",
|
||||
},
|
||||
wantModule: "foo",
|
||||
wantTag: "",
|
||||
},
|
||||
{
|
||||
name: "tag",
|
||||
args: args{
|
||||
s: ":foo{.bar}",
|
||||
},
|
||||
wantModule: "foo",
|
||||
wantTag: ".bar",
|
||||
},
|
||||
{
|
||||
name: "empty tag",
|
||||
args: args{
|
||||
s: ":foo{}",
|
||||
},
|
||||
wantModule: "foo",
|
||||
wantTag: "",
|
||||
},
|
||||
{
|
||||
name: "extra colon",
|
||||
args: args{
|
||||
s: ":foo:bar",
|
||||
},
|
||||
wantModule: "foo:bar",
|
||||
},
|
||||
{
|
||||
name: "invalid tag",
|
||||
args: args{
|
||||
s: ":foo{.bar",
|
||||
},
|
||||
wantModule: "foo{.bar",
|
||||
},
|
||||
{
|
||||
name: "invalid tag 2",
|
||||
args: args{
|
||||
s: ":foo.bar}",
|
||||
},
|
||||
wantModule: "foo.bar}",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotModule, gotTag := SrcIsModuleWithTag(tt.args.s)
|
||||
if gotModule != tt.wantModule {
|
||||
t.Errorf("SrcIsModuleWithTag() gotModule = %v, want %v", gotModule, tt.wantModule)
|
||||
}
|
||||
if gotTag != tt.wantTag {
|
||||
t.Errorf("SrcIsModuleWithTag() gotTag = %v, want %v", gotTag, tt.wantTag)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -39,14 +39,12 @@ func pathDepsMutator(ctx BottomUpMutatorContext) {
|
|||
pathProperties := pathPropertiesForPropertyStruct(ctx, ps)
|
||||
pathProperties = FirstUniqueStrings(pathProperties)
|
||||
|
||||
var deps []string
|
||||
for _, s := range pathProperties {
|
||||
if m := SrcIsModule(s); m != "" {
|
||||
deps = append(deps, m)
|
||||
if m, t := SrcIsModuleWithTag(s); m != "" {
|
||||
ctx.AddDependency(ctx.Module(), sourceOrOutputDepTag(t), m)
|
||||
}
|
||||
}
|
||||
|
||||
ctx.AddDependency(ctx.Module(), SourceDepTag, deps...)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,8 +41,10 @@ func pathDepsMutatorTestModuleFactory() Module {
|
|||
}
|
||||
|
||||
func (p *pathDepsMutatorTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
|
||||
ctx.VisitDirectDepsWithTag(SourceDepTag, func(dep Module) {
|
||||
p.sourceDeps = append(p.sourceDeps, ctx.OtherModuleName(dep))
|
||||
ctx.VisitDirectDeps(func(dep Module) {
|
||||
if _, ok := ctx.OtherModuleDependencyTag(dep).(sourceOrOutputDependencyTag); ok {
|
||||
p.sourceDeps = append(p.sourceDeps, ctx.OtherModuleName(dep))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -59,7 +61,7 @@ func TestPathDepsMutator(t *testing.T) {
|
|||
name: "foo",
|
||||
foo: ":a",
|
||||
bar: [":b"],
|
||||
baz: ":c",
|
||||
baz: ":c{.bar}",
|
||||
qux: ":d",
|
||||
}`,
|
||||
deps: []string{"a", "b", "c"},
|
||||
|
|
|
@ -217,21 +217,23 @@ func ExistentPathsForSources(ctx PathContext, paths []string) Paths {
|
|||
return ret
|
||||
}
|
||||
|
||||
// PathsForModuleSrc returns Paths rooted from the module's local source directory. It expands globs and references
|
||||
// to SourceFileProducer modules using the ":name" syntax. Properties passed as the paths argument must have been
|
||||
// annotated with struct tag `android:"path"` so that dependencies on SourceFileProducer modules will have already
|
||||
// been handled by the path_properties mutator. If ctx.Config().AllowMissingDependencies() is true, then any missing
|
||||
// SourceFileProducer dependencies will cause the module to be marked as having missing dependencies.
|
||||
// PathsForModuleSrc returns Paths rooted from the module's local source directory. It expands globs, references to
|
||||
// SourceFileProducer modules using the ":name" syntax, and references to OutputFileProducer modules using the
|
||||
// ":name{.tag}" syntax. Properties passed as the paths argument must have been annotated with struct tag
|
||||
// `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the
|
||||
// path_properties mutator. If ctx.Config().AllowMissingDependencies() is true then any missing SourceFileProducer or
|
||||
// OutputFileProducer dependencies will cause the module to be marked as having missing dependencies.
|
||||
func PathsForModuleSrc(ctx ModuleContext, paths []string) Paths {
|
||||
return PathsForModuleSrcExcludes(ctx, paths, nil)
|
||||
}
|
||||
|
||||
// PathsForModuleSrcExcludes returns Paths rooted from the module's local source directory, excluding paths listed in
|
||||
// the excludes arguments. It expands globs and references to SourceFileProducer modules in both paths and excludes
|
||||
// using the ":name" syntax. Properties passed as the paths or excludes argument must have been annotated with struct
|
||||
// tag `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the
|
||||
// path_properties mutator. If ctx.Config().AllowMissingDependencies() is true, then any missing SourceFileProducer
|
||||
// dependencies will cause the module to be marked as having missing dependencies.
|
||||
// the excludes arguments. It expands globs, references to SourceFileProducer modules using the ":name" syntax, and
|
||||
// references to OutputFileProducer modules using the ":name{.tag}" syntax. Properties passed as the paths or excludes
|
||||
// argument must have been annotated with struct tag `android:"path"` so that dependencies on SourceFileProducer modules
|
||||
// will have already been handled by the path_properties mutator. If ctx.Config().AllowMissingDependencies() is
|
||||
// truethen any missing SourceFileProducer or OutputFileProducer dependencies will cause the module to be marked as
|
||||
// having missing dependencies.
|
||||
func PathsForModuleSrcExcludes(ctx ModuleContext, paths, excludes []string) Paths {
|
||||
ret, missingDeps := PathsAndMissingDepsForModuleSrcExcludes(ctx, paths, excludes)
|
||||
if ctx.Config().AllowMissingDependencies() {
|
||||
|
@ -245,12 +247,13 @@ func PathsForModuleSrcExcludes(ctx ModuleContext, paths, excludes []string) Path
|
|||
}
|
||||
|
||||
// PathsAndMissingDepsForModuleSrcExcludes returns Paths rooted from the module's local source directory, excluding
|
||||
// paths listed in the excludes arguments, and a list of missing dependencies. It expands globs and references to
|
||||
// SourceFileProducer modules in both paths and excludes using the ":name" syntax. Properties passed as the paths or
|
||||
// excludes argument must have been annotated with struct tag `android:"path"` so that dependencies on
|
||||
// SourceFileProducer modules will have already been handled by the path_properties mutator. If
|
||||
// ctx.Config().AllowMissingDependencies() is true, then any missing SourceFileProducer dependencies will be returned,
|
||||
// and they will NOT cause the module to be marked as having missing dependencies.
|
||||
// paths listed in the excludes arguments, and a list of missing dependencies. It expands globs, references to
|
||||
// SourceFileProducer modules using the ":name" syntax, and references to OutputFileProducer modules using the
|
||||
// ":name{.tag}" syntax. Properties passed as the paths or excludes argument must have been annotated with struct tag
|
||||
// `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the
|
||||
// path_properties mutator. If ctx.Config().AllowMissingDependencies() is true then any missing SourceFileProducer or
|
||||
// OutputFileProducer dependencies will be returned, and they will NOT cause the module to be marked as having missing
|
||||
// dependencies.
|
||||
func PathsAndMissingDepsForModuleSrcExcludes(ctx ModuleContext, paths, excludes []string) (Paths, []string) {
|
||||
prefix := pathForModuleSrc(ctx).String()
|
||||
|
||||
|
@ -262,16 +265,24 @@ func PathsAndMissingDepsForModuleSrcExcludes(ctx ModuleContext, paths, excludes
|
|||
var missingExcludeDeps []string
|
||||
|
||||
for _, e := range excludes {
|
||||
if m := SrcIsModule(e); m != "" {
|
||||
module := ctx.GetDirectDepWithTag(m, SourceDepTag)
|
||||
if m, t := SrcIsModuleWithTag(e); m != "" {
|
||||
module := ctx.GetDirectDepWithTag(m, sourceOrOutputDepTag(t))
|
||||
if module == nil {
|
||||
missingExcludeDeps = append(missingExcludeDeps, m)
|
||||
continue
|
||||
}
|
||||
if srcProducer, ok := module.(SourceFileProducer); ok {
|
||||
if outProducer, ok := module.(OutputFileProducer); ok {
|
||||
outputFiles, err := outProducer.OutputFiles(t)
|
||||
if err != nil {
|
||||
ctx.ModuleErrorf("path dependency %q: %s", e, err)
|
||||
}
|
||||
expandedExcludes = append(expandedExcludes, outputFiles.Strings()...)
|
||||
} else if t != "" {
|
||||
ctx.ModuleErrorf("path dependency %q is not an output file producing module", e)
|
||||
} else if srcProducer, ok := module.(SourceFileProducer); ok {
|
||||
expandedExcludes = append(expandedExcludes, srcProducer.Srcs().Strings()...)
|
||||
} else {
|
||||
ctx.ModuleErrorf("srcs dependency %q is not a source file producing module", m)
|
||||
ctx.ModuleErrorf("path dependency %q is not a source file producing module", e)
|
||||
}
|
||||
} else {
|
||||
expandedExcludes = append(expandedExcludes, filepath.Join(prefix, e))
|
||||
|
@ -307,12 +318,20 @@ func (e missingDependencyError) Error() string {
|
|||
}
|
||||
|
||||
func expandOneSrcPath(ctx ModuleContext, s string, expandedExcludes []string) (Paths, error) {
|
||||
if m := SrcIsModule(s); m != "" {
|
||||
module := ctx.GetDirectDepWithTag(m, SourceDepTag)
|
||||
if m, t := SrcIsModuleWithTag(s); m != "" {
|
||||
module := ctx.GetDirectDepWithTag(m, sourceOrOutputDepTag(t))
|
||||
if module == nil {
|
||||
return nil, missingDependencyError{[]string{m}}
|
||||
}
|
||||
if srcProducer, ok := module.(SourceFileProducer); ok {
|
||||
if outProducer, ok := module.(OutputFileProducer); ok {
|
||||
outputFiles, err := outProducer.OutputFiles(t)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("path dependency %q: %s", s, err)
|
||||
}
|
||||
return outputFiles, nil
|
||||
} else if t != "" {
|
||||
return nil, fmt.Errorf("path dependency %q is not an output file producing module", s)
|
||||
} else if srcProducer, ok := module.(SourceFileProducer); ok {
|
||||
moduleSrcs := srcProducer.Srcs()
|
||||
for _, e := range expandedExcludes {
|
||||
for j := 0; j < len(moduleSrcs); j++ {
|
||||
|
@ -324,7 +343,7 @@ func expandOneSrcPath(ctx ModuleContext, s string, expandedExcludes []string) (P
|
|||
}
|
||||
return moduleSrcs, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("path dependency %q is not a source file producing module", m)
|
||||
return nil, fmt.Errorf("path dependency %q is not a source file producing module", s)
|
||||
}
|
||||
} else if pathtools.IsGlob(s) {
|
||||
paths := ctx.GlobFiles(pathForModuleSrc(ctx, s).String(), expandedExcludes)
|
||||
|
|
|
@ -760,6 +760,45 @@ func (p *pathForModuleSrcTestModule) GenerateAndroidBuildActions(ctx ModuleConte
|
|||
}
|
||||
}
|
||||
|
||||
type pathForModuleSrcOutputFileProviderModule struct {
|
||||
ModuleBase
|
||||
props struct {
|
||||
Outs []string
|
||||
Tagged []string
|
||||
}
|
||||
|
||||
outs Paths
|
||||
tagged Paths
|
||||
}
|
||||
|
||||
func pathForModuleSrcOutputFileProviderModuleFactory() Module {
|
||||
module := &pathForModuleSrcOutputFileProviderModule{}
|
||||
module.AddProperties(&module.props)
|
||||
InitAndroidModule(module)
|
||||
return module
|
||||
}
|
||||
|
||||
func (p *pathForModuleSrcOutputFileProviderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
|
||||
for _, out := range p.props.Outs {
|
||||
p.outs = append(p.outs, PathForModuleOut(ctx, out))
|
||||
}
|
||||
|
||||
for _, tagged := range p.props.Tagged {
|
||||
p.tagged = append(p.tagged, PathForModuleOut(ctx, tagged))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *pathForModuleSrcOutputFileProviderModule) OutputFiles(tag string) (Paths, error) {
|
||||
switch tag {
|
||||
case "":
|
||||
return p.outs, nil
|
||||
case ".tagged":
|
||||
return p.tagged, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported tag %q", tag)
|
||||
}
|
||||
}
|
||||
|
||||
type pathForModuleSrcTestCase struct {
|
||||
name string
|
||||
bp string
|
||||
|
@ -776,6 +815,7 @@ func testPathForModuleSrc(t *testing.T, buildDir string, tests []pathForModuleSr
|
|||
ctx := NewTestContext()
|
||||
|
||||
ctx.RegisterModuleType("test", ModuleFactoryAdaptor(pathForModuleSrcTestModuleFactory))
|
||||
ctx.RegisterModuleType("output_file_provider", ModuleFactoryAdaptor(pathForModuleSrcOutputFileProviderModuleFactory))
|
||||
ctx.RegisterModuleType("filegroup", ModuleFactoryAdaptor(FileGroupFactory))
|
||||
|
||||
fgBp := `
|
||||
|
@ -785,9 +825,18 @@ func testPathForModuleSrc(t *testing.T, buildDir string, tests []pathForModuleSr
|
|||
}
|
||||
`
|
||||
|
||||
ofpBp := `
|
||||
output_file_provider {
|
||||
name: "b",
|
||||
outs: ["gen/b"],
|
||||
tagged: ["gen/c"],
|
||||
}
|
||||
`
|
||||
|
||||
mockFS := map[string][]byte{
|
||||
"fg/Android.bp": []byte(fgBp),
|
||||
"foo/Android.bp": []byte(test.bp),
|
||||
"ofp/Android.bp": []byte(ofpBp),
|
||||
"fg/src/a": nil,
|
||||
"foo/src/b": nil,
|
||||
"foo/src/c": nil,
|
||||
|
@ -799,7 +848,7 @@ func testPathForModuleSrc(t *testing.T, buildDir string, tests []pathForModuleSr
|
|||
ctx.MockFileSystem(mockFS)
|
||||
|
||||
ctx.Register()
|
||||
_, errs := ctx.ParseFileList(".", []string{"fg/Android.bp", "foo/Android.bp"})
|
||||
_, errs := ctx.ParseFileList(".", []string{"fg/Android.bp", "foo/Android.bp", "ofp/Android.bp"})
|
||||
FailIfErrored(t, errs)
|
||||
_, errs = ctx.PrepareBuildActions(config)
|
||||
FailIfErrored(t, errs)
|
||||
|
@ -826,6 +875,12 @@ func testPathForModuleSrc(t *testing.T, buildDir string, tests []pathForModuleSr
|
|||
}
|
||||
|
||||
func TestPathsForModuleSrc(t *testing.T) {
|
||||
buildDir, err := ioutil.TempDir("", "soong_paths_for_module_src_test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(buildDir)
|
||||
|
||||
tests := []pathForModuleSrcTestCase{
|
||||
{
|
||||
name: "path",
|
||||
|
@ -870,6 +925,26 @@ func TestPathsForModuleSrc(t *testing.T) {
|
|||
srcs: []string{"fg/src/a"},
|
||||
rels: []string{"src/a"},
|
||||
},
|
||||
{
|
||||
name: "output file provider",
|
||||
bp: `
|
||||
test {
|
||||
name: "foo",
|
||||
srcs: [":b"],
|
||||
}`,
|
||||
srcs: []string{buildDir + "/.intermediates/ofp/b/gen/b"},
|
||||
rels: []string{"gen/b"},
|
||||
},
|
||||
{
|
||||
name: "output file provider tagged",
|
||||
bp: `
|
||||
test {
|
||||
name: "foo",
|
||||
srcs: [":b{.tagged}"],
|
||||
}`,
|
||||
srcs: []string{buildDir + "/.intermediates/ofp/b/gen/c"},
|
||||
rels: []string{"gen/c"},
|
||||
},
|
||||
{
|
||||
name: "special characters glob",
|
||||
bp: `
|
||||
|
@ -882,16 +957,16 @@ func TestPathsForModuleSrc(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
buildDir, err := ioutil.TempDir("", "soong_paths_for_module_src_test")
|
||||
testPathForModuleSrc(t, buildDir, tests)
|
||||
}
|
||||
|
||||
func TestPathForModuleSrc(t *testing.T) {
|
||||
buildDir, err := ioutil.TempDir("", "soong_path_for_module_src_test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(buildDir)
|
||||
|
||||
testPathForModuleSrc(t, buildDir, tests)
|
||||
}
|
||||
|
||||
func TestPathForModuleSrc(t *testing.T) {
|
||||
tests := []pathForModuleSrcTestCase{
|
||||
{
|
||||
name: "path",
|
||||
|
@ -923,6 +998,26 @@ func TestPathForModuleSrc(t *testing.T) {
|
|||
src: "fg/src/a",
|
||||
rel: "src/a",
|
||||
},
|
||||
{
|
||||
name: "output file provider",
|
||||
bp: `
|
||||
test {
|
||||
name: "foo",
|
||||
src: ":b",
|
||||
}`,
|
||||
src: buildDir + "/.intermediates/ofp/b/gen/b",
|
||||
rel: "gen/b",
|
||||
},
|
||||
{
|
||||
name: "output file provider tagged",
|
||||
bp: `
|
||||
test {
|
||||
name: "foo",
|
||||
src: ":b{.tagged}",
|
||||
}`,
|
||||
src: buildDir + "/.intermediates/ofp/b/gen/c",
|
||||
rel: "gen/c",
|
||||
},
|
||||
{
|
||||
name: "special characters glob",
|
||||
bp: `
|
||||
|
@ -935,12 +1030,6 @@ func TestPathForModuleSrc(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
buildDir, err := ioutil.TempDir("", "soong_path_for_module_src_test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(buildDir)
|
||||
|
||||
testPathForModuleSrc(t, buildDir, tests)
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
package android
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
@ -250,8 +251,13 @@ func (p *prebuiltModule) Prebuilt() *Prebuilt {
|
|||
return &p.prebuilt
|
||||
}
|
||||
|
||||
func (p *prebuiltModule) Srcs() Paths {
|
||||
return Paths{p.src}
|
||||
func (p *prebuiltModule) OutputFiles(tag string) (Paths, error) {
|
||||
switch tag {
|
||||
case "":
|
||||
return Paths{p.src}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
|
||||
}
|
||||
}
|
||||
|
||||
type sourceModule struct {
|
||||
|
|
24
apex/apex.go
24
apex/apex.go
|
@ -560,11 +560,16 @@ func (a *apexBundle) getCertString(ctx android.BaseContext) string {
|
|||
return String(a.properties.Certificate)
|
||||
}
|
||||
|
||||
func (a *apexBundle) Srcs() android.Paths {
|
||||
if file, ok := a.outputFiles[imageApex]; ok {
|
||||
return android.Paths{file}
|
||||
} else {
|
||||
return nil
|
||||
func (a *apexBundle) OutputFiles(tag string) (android.Paths, error) {
|
||||
switch tag {
|
||||
case "":
|
||||
if file, ok := a.outputFiles[imageApex]; ok {
|
||||
return android.Paths{file}, nil
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1383,8 +1388,13 @@ func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {
|
|||
p.properties.Source = src
|
||||
}
|
||||
|
||||
func (p *Prebuilt) Srcs() android.Paths {
|
||||
return android.Paths{p.outputApex}
|
||||
func (p *Prebuilt) OutputFiles(tag string) (android.Paths, error) {
|
||||
switch tag {
|
||||
case "":
|
||||
return android.Paths{p.outputApex}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Prebuilt) InstallFilename() string {
|
||||
|
|
13
bpf/bpf.go
13
bpf/bpf.go
|
@ -122,13 +122,18 @@ func (bpf *bpf) AndroidMk() android.AndroidMkData {
|
|||
}
|
||||
}
|
||||
|
||||
// Implements SourceFileProducer interface so that the obj output can be used in the data property
|
||||
// Implements OutputFileFileProducer interface so that the obj output can be used in the data property
|
||||
// of other modules.
|
||||
func (bpf *bpf) Srcs() android.Paths {
|
||||
return bpf.objs
|
||||
func (bpf *bpf) OutputFiles(tag string) (android.Paths, error) {
|
||||
switch tag {
|
||||
case "":
|
||||
return bpf.objs, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
|
||||
}
|
||||
}
|
||||
|
||||
var _ android.SourceFileProducer = (*bpf)(nil)
|
||||
var _ android.OutputFileProducer = (*bpf)(nil)
|
||||
|
||||
func bpfFactory() android.Module {
|
||||
module := &bpf{}
|
||||
|
|
20
cc/cc.go
20
cc/cc.go
|
@ -19,6 +19,7 @@ package cc
|
|||
// is handled in builder.go
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -1925,11 +1926,16 @@ func (c *Module) IntermPathForModuleOut() android.OptionalPath {
|
|||
return c.outputFile
|
||||
}
|
||||
|
||||
func (c *Module) Srcs() android.Paths {
|
||||
if c.outputFile.Valid() {
|
||||
return android.Paths{c.outputFile.Path()}
|
||||
func (c *Module) OutputFiles(tag string) (android.Paths, error) {
|
||||
switch tag {
|
||||
case "":
|
||||
if c.outputFile.Valid() {
|
||||
return android.Paths{c.outputFile.Path()}, nil
|
||||
}
|
||||
return android.Paths{}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
|
||||
}
|
||||
return android.Paths{}
|
||||
}
|
||||
|
||||
func (c *Module) static() bool {
|
||||
|
@ -2006,7 +2012,11 @@ func (c *Module) imageVariation() string {
|
|||
}
|
||||
|
||||
func (c *Module) IDEInfo(dpInfo *android.IdeInfo) {
|
||||
dpInfo.Srcs = append(dpInfo.Srcs, c.Srcs().Strings()...)
|
||||
outputFiles, err := c.OutputFiles("")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
dpInfo.Srcs = append(dpInfo.Srcs, outputFiles.Strings()...)
|
||||
}
|
||||
|
||||
func (c *Module) AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer) {
|
||||
|
|
|
@ -130,8 +130,12 @@ func TestAppSplits(t *testing.T) {
|
|||
foo.Output(expectedOutput)
|
||||
}
|
||||
|
||||
if g, w := foo.Module().(*AndroidApp).Srcs().Strings(), expectedOutputs; !reflect.DeepEqual(g, w) {
|
||||
t.Errorf("want Srcs() = %q, got %q", w, g)
|
||||
outputFiles, err := foo.Module().(*AndroidApp).OutputFiles("")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if g, w := outputFiles.Strings(), expectedOutputs; !reflect.DeepEqual(g, w) {
|
||||
t.Errorf(`want OutputFiles("") = %q, got %q`, w, g)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -497,8 +497,13 @@ type Javadoc struct {
|
|||
stubsSrcJar android.WritablePath
|
||||
}
|
||||
|
||||
func (j *Javadoc) Srcs() android.Paths {
|
||||
return android.Paths{j.stubsSrcJar}
|
||||
func (j *Javadoc) OutputFiles(tag string) (android.Paths, error) {
|
||||
switch tag {
|
||||
case "":
|
||||
return android.Paths{j.stubsSrcJar}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
|
||||
}
|
||||
}
|
||||
|
||||
func JavadocFactory() android.Module {
|
||||
|
@ -519,7 +524,7 @@ func JavadocHostFactory() android.Module {
|
|||
return module
|
||||
}
|
||||
|
||||
var _ android.SourceFileProducer = (*Javadoc)(nil)
|
||||
var _ android.OutputFileProducer = (*Javadoc)(nil)
|
||||
|
||||
func (j *Javadoc) sdkVersion() string {
|
||||
return String(j.properties.Sdk_version)
|
||||
|
|
15
java/java.go
15
java/java.go
|
@ -351,15 +351,20 @@ type Module struct {
|
|||
dexpreopter
|
||||
}
|
||||
|
||||
func (j *Module) Srcs() android.Paths {
|
||||
return append(android.Paths{j.outputFile}, j.extraOutputFiles...)
|
||||
func (j *Module) OutputFiles(tag string) (android.Paths, error) {
|
||||
switch tag {
|
||||
case "":
|
||||
return append(android.Paths{j.outputFile}, j.extraOutputFiles...), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
|
||||
}
|
||||
}
|
||||
|
||||
func (j *Module) DexJarFile() android.Path {
|
||||
return j.dexJarFile
|
||||
}
|
||||
|
||||
var _ android.SourceFileProducer = (*Module)(nil)
|
||||
var _ android.OutputFileProducer = (*Module)(nil)
|
||||
|
||||
type Dependency interface {
|
||||
HeaderJars() android.Paths
|
||||
|
@ -813,8 +818,6 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
|
|||
}
|
||||
default:
|
||||
switch tag {
|
||||
case android.DefaultsDepTag, android.SourceDepTag:
|
||||
// Nothing to do
|
||||
case systemModulesTag:
|
||||
if deps.systemModules != nil {
|
||||
panic("Found two system module dependencies")
|
||||
|
@ -824,8 +827,6 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
|
|||
panic("Missing directory for system module dependency")
|
||||
}
|
||||
deps.systemModules = sm.outputFile
|
||||
default:
|
||||
ctx.ModuleErrorf("depends on non-java module %q", otherName)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue