Merge "Support tagged module references"
am: b4c35f3378
Change-Id: I5f262b69306816647aa72ebaba775a243244bacd
This commit is contained in:
@@ -81,6 +81,7 @@ bootstrap_go_package {
|
|||||||
"android/arch_test.go",
|
"android/arch_test.go",
|
||||||
"android/config_test.go",
|
"android/config_test.go",
|
||||||
"android/expand_test.go",
|
"android/expand_test.go",
|
||||||
|
"android/module_test.go",
|
||||||
"android/namespace_test.go",
|
"android/namespace_test.go",
|
||||||
"android/neverallow_test.go",
|
"android/neverallow_test.go",
|
||||||
"android/onceper_test.go",
|
"android/onceper_test.go",
|
||||||
|
@@ -1462,39 +1462,60 @@ func findStringInSlice(str string, slice []string) int {
|
|||||||
return -1
|
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] == ':' {
|
if len(s) > 1 && s[0] == ':' {
|
||||||
return s[1:]
|
return s[1:]
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
type sourceDependencyTag struct {
|
// SrcIsModule decodes module references in the format ":name{.tag}" into the module name and tag, ":name" into the
|
||||||
blueprint.BaseDependencyTag
|
// 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
|
// Adds necessary dependencies to satisfy filegroup or generated sources modules listed in srcFiles
|
||||||
// using ":module" syntax, if any.
|
// using ":module" syntax, if any.
|
||||||
//
|
//
|
||||||
// Deprecated: tag the property with `android:"path"` instead.
|
// Deprecated: tag the property with `android:"path"` instead.
|
||||||
func ExtractSourcesDeps(ctx BottomUpMutatorContext, srcFiles []string) {
|
func ExtractSourcesDeps(ctx BottomUpMutatorContext, srcFiles []string) {
|
||||||
var deps []string
|
|
||||||
set := make(map[string]bool)
|
set := make(map[string]bool)
|
||||||
|
|
||||||
for _, s := range srcFiles {
|
for _, s := range srcFiles {
|
||||||
if m := SrcIsModule(s); m != "" {
|
if m, t := SrcIsModuleWithTag(s); m != "" {
|
||||||
if _, found := set[m]; found {
|
if _, found := set[s]; found {
|
||||||
ctx.ModuleErrorf("found source dependency duplicate: %q!", m)
|
ctx.ModuleErrorf("found source dependency duplicate: %q!", s)
|
||||||
} else {
|
} else {
|
||||||
set[m] = true
|
set[s] = true
|
||||||
deps = append(deps, m)
|
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
|
// 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.
|
// Deprecated: tag the property with `android:"path"` instead.
|
||||||
func ExtractSourceDeps(ctx BottomUpMutatorContext, s *string) {
|
func ExtractSourceDeps(ctx BottomUpMutatorContext, s *string) {
|
||||||
if s != nil {
|
if s != nil {
|
||||||
if m := SrcIsModule(*s); m != "" {
|
if m, t := SrcIsModuleWithTag(*s); m != "" {
|
||||||
ctx.AddDependency(ctx.Module(), SourceDepTag, 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 {
|
type SourceFileProducer interface {
|
||||||
Srcs() Paths
|
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 {
|
type HostToolProvider interface {
|
||||||
HostToolPath() OptionalPath
|
HostToolPath() OptionalPath
|
||||||
}
|
}
|
||||||
|
141
android/module_test.go
Normal file
141
android/module_test.go
Normal file
@@ -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 := pathPropertiesForPropertyStruct(ctx, ps)
|
||||||
pathProperties = FirstUniqueStrings(pathProperties)
|
pathProperties = FirstUniqueStrings(pathProperties)
|
||||||
|
|
||||||
var deps []string
|
|
||||||
for _, s := range pathProperties {
|
for _, s := range pathProperties {
|
||||||
if m := SrcIsModule(s); m != "" {
|
if m, t := SrcIsModuleWithTag(s); m != "" {
|
||||||
deps = append(deps, 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) {
|
func (p *pathDepsMutatorTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
|
||||||
ctx.VisitDirectDepsWithTag(SourceDepTag, func(dep Module) {
|
ctx.VisitDirectDeps(func(dep Module) {
|
||||||
|
if _, ok := ctx.OtherModuleDependencyTag(dep).(sourceOrOutputDependencyTag); ok {
|
||||||
p.sourceDeps = append(p.sourceDeps, ctx.OtherModuleName(dep))
|
p.sourceDeps = append(p.sourceDeps, ctx.OtherModuleName(dep))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +61,7 @@ func TestPathDepsMutator(t *testing.T) {
|
|||||||
name: "foo",
|
name: "foo",
|
||||||
foo: ":a",
|
foo: ":a",
|
||||||
bar: [":b"],
|
bar: [":b"],
|
||||||
baz: ":c",
|
baz: ":c{.bar}",
|
||||||
qux: ":d",
|
qux: ":d",
|
||||||
}`,
|
}`,
|
||||||
deps: []string{"a", "b", "c"},
|
deps: []string{"a", "b", "c"},
|
||||||
|
@@ -217,21 +217,23 @@ func ExistentPathsForSources(ctx PathContext, paths []string) Paths {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// PathsForModuleSrc returns Paths rooted from the module's local source directory. It expands globs and references
|
// PathsForModuleSrc returns Paths rooted from the module's local source directory. It expands globs, references to
|
||||||
// to SourceFileProducer modules using the ":name" syntax. Properties passed as the paths argument must have been
|
// SourceFileProducer modules using the ":name" syntax, and references to OutputFileProducer modules using the
|
||||||
// annotated with struct tag `android:"path"` so that dependencies on SourceFileProducer modules will have already
|
// ":name{.tag}" syntax. Properties passed as the paths argument must have been annotated with struct tag
|
||||||
// been handled by the path_properties mutator. If ctx.Config().AllowMissingDependencies() is true, then any missing
|
// `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the
|
||||||
// SourceFileProducer dependencies will cause the module to be marked as having missing dependencies.
|
// 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 {
|
func PathsForModuleSrc(ctx ModuleContext, paths []string) Paths {
|
||||||
return PathsForModuleSrcExcludes(ctx, paths, nil)
|
return PathsForModuleSrcExcludes(ctx, paths, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PathsForModuleSrcExcludes returns Paths rooted from the module's local source directory, excluding paths listed in
|
// 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
|
// the excludes arguments. It expands globs, references to SourceFileProducer modules using the ":name" syntax, and
|
||||||
// using the ":name" syntax. Properties passed as the paths or excludes argument must have been annotated with struct
|
// references to OutputFileProducer modules using the ":name{.tag}" syntax. Properties passed as the paths or excludes
|
||||||
// tag `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the
|
// argument must have been annotated with struct tag `android:"path"` so that dependencies on SourceFileProducer modules
|
||||||
// path_properties mutator. If ctx.Config().AllowMissingDependencies() is true, then any missing SourceFileProducer
|
// will have already been handled by the path_properties mutator. If ctx.Config().AllowMissingDependencies() is
|
||||||
// dependencies will cause the module to be marked as having missing dependencies.
|
// 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 {
|
func PathsForModuleSrcExcludes(ctx ModuleContext, paths, excludes []string) Paths {
|
||||||
ret, missingDeps := PathsAndMissingDepsForModuleSrcExcludes(ctx, paths, excludes)
|
ret, missingDeps := PathsAndMissingDepsForModuleSrcExcludes(ctx, paths, excludes)
|
||||||
if ctx.Config().AllowMissingDependencies() {
|
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
|
// 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
|
// paths listed in the excludes arguments, and a list of missing dependencies. It expands globs, references to
|
||||||
// SourceFileProducer modules in both paths and excludes using the ":name" syntax. Properties passed as the paths or
|
// SourceFileProducer modules using the ":name" syntax, and references to OutputFileProducer modules using the
|
||||||
// excludes argument must have been annotated with struct tag `android:"path"` so that dependencies on
|
// ":name{.tag}" syntax. Properties passed as the paths or excludes argument must have been annotated with struct tag
|
||||||
// SourceFileProducer modules will have already been handled by the path_properties mutator. If
|
// `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the
|
||||||
// ctx.Config().AllowMissingDependencies() is true, then any missing SourceFileProducer dependencies will be returned,
|
// path_properties mutator. If ctx.Config().AllowMissingDependencies() is true then any missing SourceFileProducer or
|
||||||
// and they will NOT cause the module to be marked as having missing dependencies.
|
// 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) {
|
func PathsAndMissingDepsForModuleSrcExcludes(ctx ModuleContext, paths, excludes []string) (Paths, []string) {
|
||||||
prefix := pathForModuleSrc(ctx).String()
|
prefix := pathForModuleSrc(ctx).String()
|
||||||
|
|
||||||
@@ -262,16 +265,24 @@ func PathsAndMissingDepsForModuleSrcExcludes(ctx ModuleContext, paths, excludes
|
|||||||
var missingExcludeDeps []string
|
var missingExcludeDeps []string
|
||||||
|
|
||||||
for _, e := range excludes {
|
for _, e := range excludes {
|
||||||
if m := SrcIsModule(e); m != "" {
|
if m, t := SrcIsModuleWithTag(e); m != "" {
|
||||||
module := ctx.GetDirectDepWithTag(m, SourceDepTag)
|
module := ctx.GetDirectDepWithTag(m, sourceOrOutputDepTag(t))
|
||||||
if module == nil {
|
if module == nil {
|
||||||
missingExcludeDeps = append(missingExcludeDeps, m)
|
missingExcludeDeps = append(missingExcludeDeps, m)
|
||||||
continue
|
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()...)
|
expandedExcludes = append(expandedExcludes, srcProducer.Srcs().Strings()...)
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
expandedExcludes = append(expandedExcludes, filepath.Join(prefix, e))
|
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) {
|
func expandOneSrcPath(ctx ModuleContext, s string, expandedExcludes []string) (Paths, error) {
|
||||||
if m := SrcIsModule(s); m != "" {
|
if m, t := SrcIsModuleWithTag(s); m != "" {
|
||||||
module := ctx.GetDirectDepWithTag(m, SourceDepTag)
|
module := ctx.GetDirectDepWithTag(m, sourceOrOutputDepTag(t))
|
||||||
if module == nil {
|
if module == nil {
|
||||||
return nil, missingDependencyError{[]string{m}}
|
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()
|
moduleSrcs := srcProducer.Srcs()
|
||||||
for _, e := range expandedExcludes {
|
for _, e := range expandedExcludes {
|
||||||
for j := 0; j < len(moduleSrcs); j++ {
|
for j := 0; j < len(moduleSrcs); j++ {
|
||||||
@@ -324,7 +343,7 @@ func expandOneSrcPath(ctx ModuleContext, s string, expandedExcludes []string) (P
|
|||||||
}
|
}
|
||||||
return moduleSrcs, nil
|
return moduleSrcs, nil
|
||||||
} else {
|
} 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) {
|
} else if pathtools.IsGlob(s) {
|
||||||
paths := ctx.GlobFiles(pathForModuleSrc(ctx, s).String(), expandedExcludes)
|
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 {
|
type pathForModuleSrcTestCase struct {
|
||||||
name string
|
name string
|
||||||
bp string
|
bp string
|
||||||
@@ -776,6 +815,7 @@ func testPathForModuleSrc(t *testing.T, buildDir string, tests []pathForModuleSr
|
|||||||
ctx := NewTestContext()
|
ctx := NewTestContext()
|
||||||
|
|
||||||
ctx.RegisterModuleType("test", ModuleFactoryAdaptor(pathForModuleSrcTestModuleFactory))
|
ctx.RegisterModuleType("test", ModuleFactoryAdaptor(pathForModuleSrcTestModuleFactory))
|
||||||
|
ctx.RegisterModuleType("output_file_provider", ModuleFactoryAdaptor(pathForModuleSrcOutputFileProviderModuleFactory))
|
||||||
ctx.RegisterModuleType("filegroup", ModuleFactoryAdaptor(FileGroupFactory))
|
ctx.RegisterModuleType("filegroup", ModuleFactoryAdaptor(FileGroupFactory))
|
||||||
|
|
||||||
fgBp := `
|
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{
|
mockFS := map[string][]byte{
|
||||||
"fg/Android.bp": []byte(fgBp),
|
"fg/Android.bp": []byte(fgBp),
|
||||||
"foo/Android.bp": []byte(test.bp),
|
"foo/Android.bp": []byte(test.bp),
|
||||||
|
"ofp/Android.bp": []byte(ofpBp),
|
||||||
"fg/src/a": nil,
|
"fg/src/a": nil,
|
||||||
"foo/src/b": nil,
|
"foo/src/b": nil,
|
||||||
"foo/src/c": nil,
|
"foo/src/c": nil,
|
||||||
@@ -799,7 +848,7 @@ func testPathForModuleSrc(t *testing.T, buildDir string, tests []pathForModuleSr
|
|||||||
ctx.MockFileSystem(mockFS)
|
ctx.MockFileSystem(mockFS)
|
||||||
|
|
||||||
ctx.Register()
|
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)
|
FailIfErrored(t, errs)
|
||||||
_, errs = ctx.PrepareBuildActions(config)
|
_, errs = ctx.PrepareBuildActions(config)
|
||||||
FailIfErrored(t, errs)
|
FailIfErrored(t, errs)
|
||||||
@@ -826,6 +875,12 @@ func testPathForModuleSrc(t *testing.T, buildDir string, tests []pathForModuleSr
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPathsForModuleSrc(t *testing.T) {
|
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{
|
tests := []pathForModuleSrcTestCase{
|
||||||
{
|
{
|
||||||
name: "path",
|
name: "path",
|
||||||
@@ -870,6 +925,26 @@ func TestPathsForModuleSrc(t *testing.T) {
|
|||||||
srcs: []string{"fg/src/a"},
|
srcs: []string{"fg/src/a"},
|
||||||
rels: []string{"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",
|
name: "special characters glob",
|
||||||
bp: `
|
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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(buildDir)
|
defer os.RemoveAll(buildDir)
|
||||||
|
|
||||||
testPathForModuleSrc(t, buildDir, tests)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPathForModuleSrc(t *testing.T) {
|
|
||||||
tests := []pathForModuleSrcTestCase{
|
tests := []pathForModuleSrcTestCase{
|
||||||
{
|
{
|
||||||
name: "path",
|
name: "path",
|
||||||
@@ -923,6 +998,26 @@ func TestPathForModuleSrc(t *testing.T) {
|
|||||||
src: "fg/src/a",
|
src: "fg/src/a",
|
||||||
rel: "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",
|
name: "special characters glob",
|
||||||
bp: `
|
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)
|
testPathForModuleSrc(t, buildDir, tests)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
package android
|
package android
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -250,8 +251,13 @@ func (p *prebuiltModule) Prebuilt() *Prebuilt {
|
|||||||
return &p.prebuilt
|
return &p.prebuilt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *prebuiltModule) Srcs() Paths {
|
func (p *prebuiltModule) OutputFiles(tag string) (Paths, error) {
|
||||||
return Paths{p.src}
|
switch tag {
|
||||||
|
case "":
|
||||||
|
return Paths{p.src}, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type sourceModule struct {
|
type sourceModule struct {
|
||||||
|
20
apex/apex.go
20
apex/apex.go
@@ -560,11 +560,16 @@ func (a *apexBundle) getCertString(ctx android.BaseContext) string {
|
|||||||
return String(a.properties.Certificate)
|
return String(a.properties.Certificate)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *apexBundle) Srcs() android.Paths {
|
func (a *apexBundle) OutputFiles(tag string) (android.Paths, error) {
|
||||||
|
switch tag {
|
||||||
|
case "":
|
||||||
if file, ok := a.outputFiles[imageApex]; ok {
|
if file, ok := a.outputFiles[imageApex]; ok {
|
||||||
return android.Paths{file}
|
return android.Paths{file}, nil
|
||||||
} else {
|
} else {
|
||||||
return nil
|
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
|
p.properties.Source = src
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Prebuilt) Srcs() android.Paths {
|
func (p *Prebuilt) OutputFiles(tag string) (android.Paths, error) {
|
||||||
return android.Paths{p.outputApex}
|
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 {
|
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.
|
// of other modules.
|
||||||
func (bpf *bpf) Srcs() android.Paths {
|
func (bpf *bpf) OutputFiles(tag string) (android.Paths, error) {
|
||||||
return bpf.objs
|
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 {
|
func bpfFactory() android.Module {
|
||||||
module := &bpf{}
|
module := &bpf{}
|
||||||
|
18
cc/cc.go
18
cc/cc.go
@@ -19,6 +19,7 @@ package cc
|
|||||||
// is handled in builder.go
|
// is handled in builder.go
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -1925,11 +1926,16 @@ func (c *Module) IntermPathForModuleOut() android.OptionalPath {
|
|||||||
return c.outputFile
|
return c.outputFile
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Module) Srcs() android.Paths {
|
func (c *Module) OutputFiles(tag string) (android.Paths, error) {
|
||||||
|
switch tag {
|
||||||
|
case "":
|
||||||
if c.outputFile.Valid() {
|
if c.outputFile.Valid() {
|
||||||
return android.Paths{c.outputFile.Path()}
|
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 {
|
func (c *Module) static() bool {
|
||||||
@@ -2006,7 +2012,11 @@ func (c *Module) imageVariation() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Module) IDEInfo(dpInfo *android.IdeInfo) {
|
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) {
|
func (c *Module) AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer) {
|
||||||
|
@@ -130,8 +130,12 @@ func TestAppSplits(t *testing.T) {
|
|||||||
foo.Output(expectedOutput)
|
foo.Output(expectedOutput)
|
||||||
}
|
}
|
||||||
|
|
||||||
if g, w := foo.Module().(*AndroidApp).Srcs().Strings(), expectedOutputs; !reflect.DeepEqual(g, w) {
|
outputFiles, err := foo.Module().(*AndroidApp).OutputFiles("")
|
||||||
t.Errorf("want Srcs() = %q, got %q", w, g)
|
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
|
stubsSrcJar android.WritablePath
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *Javadoc) Srcs() android.Paths {
|
func (j *Javadoc) OutputFiles(tag string) (android.Paths, error) {
|
||||||
return android.Paths{j.stubsSrcJar}
|
switch tag {
|
||||||
|
case "":
|
||||||
|
return android.Paths{j.stubsSrcJar}, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func JavadocFactory() android.Module {
|
func JavadocFactory() android.Module {
|
||||||
@@ -519,7 +524,7 @@ func JavadocHostFactory() android.Module {
|
|||||||
return module
|
return module
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ android.SourceFileProducer = (*Javadoc)(nil)
|
var _ android.OutputFileProducer = (*Javadoc)(nil)
|
||||||
|
|
||||||
func (j *Javadoc) sdkVersion() string {
|
func (j *Javadoc) sdkVersion() string {
|
||||||
return String(j.properties.Sdk_version)
|
return String(j.properties.Sdk_version)
|
||||||
|
15
java/java.go
15
java/java.go
@@ -351,15 +351,20 @@ type Module struct {
|
|||||||
dexpreopter
|
dexpreopter
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *Module) Srcs() android.Paths {
|
func (j *Module) OutputFiles(tag string) (android.Paths, error) {
|
||||||
return append(android.Paths{j.outputFile}, j.extraOutputFiles...)
|
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 {
|
func (j *Module) DexJarFile() android.Path {
|
||||||
return j.dexJarFile
|
return j.dexJarFile
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ android.SourceFileProducer = (*Module)(nil)
|
var _ android.OutputFileProducer = (*Module)(nil)
|
||||||
|
|
||||||
type Dependency interface {
|
type Dependency interface {
|
||||||
HeaderJars() android.Paths
|
HeaderJars() android.Paths
|
||||||
@@ -813,8 +818,6 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
switch tag {
|
switch tag {
|
||||||
case android.DefaultsDepTag, android.SourceDepTag:
|
|
||||||
// Nothing to do
|
|
||||||
case systemModulesTag:
|
case systemModulesTag:
|
||||||
if deps.systemModules != nil {
|
if deps.systemModules != nil {
|
||||||
panic("Found two system module dependencies")
|
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")
|
panic("Missing directory for system module dependency")
|
||||||
}
|
}
|
||||||
deps.systemModules = sm.outputFile
|
deps.systemModules = sm.outputFile
|
||||||
default:
|
|
||||||
ctx.ModuleErrorf("depends on non-java module %q", otherName)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user