Loading android/filegroup.go +1 −1 Original line number Diff line number Diff line Loading @@ -60,7 +60,7 @@ func FileGroupFactory() Module { } func (fg *fileGroup) GenerateAndroidBuildActions(ctx ModuleContext) { fg.srcs = ctx.ExpandSources(fg.properties.Srcs, fg.properties.Exclude_srcs) fg.srcs = PathsForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs) if fg.properties.Path != nil { fg.srcs = PathsWithModuleSrcSubDir(ctx, fg.srcs, String(fg.properties.Path)) Loading android/module.go +8 −81 Original line number Diff line number Diff line Loading @@ -854,7 +854,7 @@ func (a *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) if a.commonProperties.Notice != nil { // For filegroup-based notice file references. a.noticeFile = ctx.ExpandSource(*a.commonProperties.Notice, "notice") a.noticeFile = PathForModuleSrc(ctx, *a.commonProperties.Notice) } } Loading Loading @@ -1419,91 +1419,18 @@ type SourceFileProducer interface { // Returns a list of paths expanded from globs and modules referenced using ":module" syntax. The property must // be tagged with `android:"path" to support automatic source module dependency resolution. // // Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead. func (ctx *androidModuleContext) ExpandSources(srcFiles, excludes []string) Paths { prefix := PathForModuleSrc(ctx).String() var expandedExcludes []string if excludes != nil { expandedExcludes = make([]string, 0, len(excludes)) } for _, e := range excludes { if m := SrcIsModule(e); m != "" { module := ctx.GetDirectDepWithTag(m, SourceDepTag) if module == nil { if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies([]string{m}) } else { ctx.ModuleErrorf(`missing dependency on %q, is the property annotated with android:"path"?`, m) } continue } 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) } } else { expandedExcludes = append(expandedExcludes, filepath.Join(prefix, e)) } } expandedSrcFiles := make(Paths, 0, len(srcFiles)) for _, s := range srcFiles { if m := SrcIsModule(s); m != "" { module := ctx.GetDirectDepWithTag(m, SourceDepTag) if module == nil { if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies([]string{m}) } else { ctx.ModuleErrorf(`missing dependency on %q, is the property annotated with android:"path"?`, m) } continue } if srcProducer, ok := module.(SourceFileProducer); ok { moduleSrcs := srcProducer.Srcs() for _, e := range expandedExcludes { for j, ms := range moduleSrcs { if ms.String() == e { moduleSrcs = append(moduleSrcs[:j], moduleSrcs[j+1:]...) } } } expandedSrcFiles = append(expandedSrcFiles, moduleSrcs...) } else { ctx.ModuleErrorf("srcs dependency %q is not a source file producing module", m) } } else if pathtools.IsGlob(s) { globbedSrcFiles := ctx.GlobFiles(filepath.Join(prefix, s), expandedExcludes) globbedSrcFiles = PathsWithModuleSrcSubDir(ctx, globbedSrcFiles, "") expandedSrcFiles = append(expandedSrcFiles, globbedSrcFiles...) } else { p := PathForModuleSrc(ctx, s) j := findStringInSlice(p.String(), expandedExcludes) if j == -1 { expandedSrcFiles = append(expandedSrcFiles, p) } } } return expandedSrcFiles return PathsForModuleSrcExcludes(ctx, srcFiles, excludes) } // Returns a single path expanded from globs and modules referenced using ":module" syntax. The property must // be tagged with `android:"path" to support automatic source module dependency resolution. // // Deprecated: use PathForModuleSrc instead. func (ctx *androidModuleContext) ExpandSource(srcFile, prop string) Path { srcFiles := ctx.ExpandSources([]string{srcFile}, nil) if len(srcFiles) == 1 { return srcFiles[0] } else if len(srcFiles) == 0 { if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies([]string{srcFile}) } else { ctx.PropertyErrorf(prop, "%s path %s does not exist", prop, srcFile) } return nil } else { ctx.PropertyErrorf(prop, "module providing %s must produce exactly one file", prop) return nil } return PathForModuleSrc(ctx, srcFile) } // Returns an optional single path expanded from globs and modules referenced using ":module" syntax if Loading @@ -1511,7 +1438,7 @@ func (ctx *androidModuleContext) ExpandSource(srcFile, prop string) Path { // dependency resolution. func (ctx *androidModuleContext) ExpandOptionalSource(srcFile *string, prop string) OptionalPath { if srcFile != nil { return OptionalPathForPath(ctx.ExpandSource(*srcFile, prop)) return OptionalPathForPath(PathForModuleSrc(ctx, *srcFile)) } return OptionalPath{} } Loading android/paths.go +120 −12 Original line number Diff line number Diff line Loading @@ -220,11 +220,104 @@ func ExistentPathsForSources(ctx PathContext, paths []string) Paths { // PathsForModuleSrc returns Paths rooted from the module's local source // directory func PathsForModuleSrc(ctx ModuleContext, paths []string) Paths { ret := make(Paths, len(paths)) for i, path := range paths { ret[i] = PathForModuleSrc(ctx, path) return PathsForModuleSrcExcludes(ctx, paths, nil) } func PathsForModuleSrcExcludes(ctx ModuleContext, paths, excludes []string) Paths { prefix := pathForModuleSrc(ctx).String() var expandedExcludes []string if excludes != nil { expandedExcludes = make([]string, 0, len(excludes)) } for _, e := range excludes { if m := SrcIsModule(e); m != "" { module := ctx.GetDirectDepWithTag(m, SourceDepTag) if module == nil { if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies([]string{m}) } else { ctx.ModuleErrorf(`missing dependency on %q, is the property annotated with android:"path"?`, m) } continue } 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) } } else { expandedExcludes = append(expandedExcludes, filepath.Join(prefix, e)) } } if paths == nil { return nil } expandedSrcFiles := make(Paths, 0, len(paths)) for _, s := range paths { srcFiles, err := expandOneSrcPath(ctx, s, expandedExcludes) if depErr, ok := err.(missingDependencyError); ok { if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies(depErr.missingDeps) } else { ctx.ModuleErrorf(`%s, is the property annotated with android:"path"?`, depErr.Error()) } } else if err != nil { reportPathError(ctx, err) } expandedSrcFiles = append(expandedSrcFiles, srcFiles...) } return expandedSrcFiles } type missingDependencyError struct { missingDeps []string } func (e missingDependencyError) Error() string { return "missing dependencies: " + strings.Join(e.missingDeps, ", ") } func expandOneSrcPath(ctx ModuleContext, s string, expandedExcludes []string) (Paths, error) { if m := SrcIsModule(s); m != "" { module := ctx.GetDirectDepWithTag(m, SourceDepTag) if module == nil { return nil, missingDependencyError{[]string{m}} } if srcProducer, ok := module.(SourceFileProducer); ok { moduleSrcs := srcProducer.Srcs() for _, e := range expandedExcludes { for j := 0; j < len(moduleSrcs); j++ { if moduleSrcs[j].String() == e { moduleSrcs = append(moduleSrcs[:j], moduleSrcs[j+1:]...) j-- } } } return moduleSrcs, nil } else { return nil, fmt.Errorf("path dependency %q is not a source file producing module", m) } } else if pathtools.IsGlob(s) { paths := ctx.GlobFiles(pathForModuleSrc(ctx, s).String(), expandedExcludes) return PathsWithModuleSrcSubDir(ctx, paths, ""), nil } else { p := pathForModuleSrc(ctx, s) if exists, _, err := ctx.Fs().Exists(p.String()); err != nil { reportPathErrorf(ctx, "%s: %s", p, err.Error()) } else if !exists { reportPathErrorf(ctx, "module source path %q does not exist", p) } j := findStringInSlice(p.String(), expandedExcludes) if j >= 0 { return nil, nil } return Paths{p}, nil } return ret } // pathsForModuleSrcFromFullPath returns Paths rooted from the module's local Loading Loading @@ -750,15 +843,30 @@ var _ resPathProvider = SourcePath{} // PathForModuleSrc returns a Path representing the paths... under the // module's local source directory. func PathForModuleSrc(ctx ModuleContext, paths ...string) Path { path := pathForModuleSrc(ctx, paths...) if exists, _, err := ctx.Fs().Exists(path.String()); err != nil { reportPathErrorf(ctx, "%s: %s", path, err.Error()) } else if !exists { reportPathErrorf(ctx, "module source path %q does not exist", path) func PathForModuleSrc(ctx ModuleContext, pathComponents ...string) Path { p, err := validatePath(pathComponents...) if err != nil { reportPathError(ctx, err) } return path paths, err := expandOneSrcPath(ctx, p, nil) if err != nil { if depErr, ok := err.(missingDependencyError); ok { if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies(depErr.missingDeps) } else { ctx.ModuleErrorf(`%s, is the property annotated with android:"path"?`, depErr.Error()) } } else { reportPathError(ctx, err) } return nil } else if len(paths) == 0 { reportPathErrorf(ctx, "%q produced no files, expected exactly one", p) return nil } else if len(paths) > 1 { reportPathErrorf(ctx, "%q produced %d files, expected exactly one", p, len(paths)) } return paths[0] } func pathForModuleSrc(ctx ModuleContext, paths ...string) SourcePath { Loading android/paths_test.go +190 −50 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import ( "testing" "github.com/google/blueprint/pathtools" "github.com/google/blueprint/proptools" ) type strsTestCase struct { Loading Loading @@ -706,39 +707,117 @@ func TestPathForSource(t *testing.T) { } } type expandSourcesTestModule struct { type pathForModuleSrcTestModule struct { ModuleBase props struct { Srcs []string `android:"path"` Exclude_srcs []string `android:"path"` Src *string `android:"path"` } srcs Paths src string rel string srcs []string rels []string missingDeps []string } func expandSourcesTestModuleFactory() Module { module := &expandSourcesTestModule{} func pathForModuleSrcTestModuleFactory() Module { module := &pathForModuleSrcTestModule{} module.AddProperties(&module.props) InitAndroidModule(module) return module } func (p *expandSourcesTestModule) GenerateAndroidBuildActions(ctx ModuleContext) { p.srcs = ctx.ExpandSources(p.props.Srcs, p.props.Exclude_srcs) func (p *pathForModuleSrcTestModule) GenerateAndroidBuildActions(ctx ModuleContext) { srcs := PathsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs) p.srcs = srcs.Strings() for _, src := range p.srcs { for _, src := range srcs { p.rels = append(p.rels, src.Rel()) } if p.props.Src != nil { src := PathForModuleSrc(ctx, *p.props.Src) if src != nil { p.src = src.String() p.rel = src.Rel() } } p.missingDeps = ctx.GetMissingDependencies() } func TestExpandSources(t *testing.T) { tests := []struct { type pathForModuleSrcTestCase struct { name string bp string srcs []string rels []string }{ src string rel string } func testPathForModuleSrc(t *testing.T, buildDir string, tests []pathForModuleSrcTestCase) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { config := TestConfig(buildDir, nil) ctx := NewTestContext() ctx.RegisterModuleType("test", ModuleFactoryAdaptor(pathForModuleSrcTestModuleFactory)) ctx.RegisterModuleType("filegroup", ModuleFactoryAdaptor(FileGroupFactory)) fgBp := ` filegroup { name: "a", srcs: ["src/a"], } ` mockFS := map[string][]byte{ "fg/Android.bp": []byte(fgBp), "foo/Android.bp": []byte(test.bp), "fg/src/a": nil, "foo/src/b": nil, "foo/src/c": nil, "foo/src/d": nil, "foo/src/e/e": nil, "foo/src_special/$": nil, } ctx.MockFileSystem(mockFS) ctx.Register() _, errs := ctx.ParseFileList(".", []string{"fg/Android.bp", "foo/Android.bp"}) FailIfErrored(t, errs) _, errs = ctx.PrepareBuildActions(config) FailIfErrored(t, errs) m := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule) if g, w := m.srcs, test.srcs; !reflect.DeepEqual(g, w) { t.Errorf("want srcs %q, got %q", w, g) } if g, w := m.rels, test.rels; !reflect.DeepEqual(g, w) { t.Errorf("want rels %q, got %q", w, g) } if g, w := m.src, test.src; g != w { t.Errorf("want src %q, got %q", w, g) } if g, w := m.rel, test.rel; g != w { t.Errorf("want rel %q, got %q", w, g) } }) } } func TestPathsForModuleSrc(t *testing.T) { tests := []pathForModuleSrcTestCase{ { name: "path", bp: ` Loading Loading @@ -794,57 +873,118 @@ func TestExpandSources(t *testing.T) { }, } buildDir, err := ioutil.TempDir("", "soong_paths_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", bp: ` test { name: "foo", src: "src/b", }`, src: "foo/src/b", rel: "src/b", }, { name: "glob", bp: ` test { name: "foo", src: "src/e/*", }`, src: "foo/src/e/e", rel: "src/e/e", }, { name: "filegroup", bp: ` test { name: "foo", src: ":a", }`, src: "fg/src/a", rel: "src/a", }, { name: "special characters glob", bp: ` test { name: "foo", src: "src_special/*", }`, src: "foo/src_special/$", rel: "src_special/$", }, } buildDir, err := ioutil.TempDir("", "soong_path_for_module_src_test") if err != nil { t.Fatal(err) } defer os.RemoveAll(buildDir) for _, test := range tests { t.Run(test.name, func(t *testing.T) { testPathForModuleSrc(t, buildDir, tests) } func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) { buildDir, err := ioutil.TempDir("", "soong_paths_for_module_src_allow_missing_dependencies_test") if err != nil { t.Fatal(err) } defer os.RemoveAll(buildDir) config := TestConfig(buildDir, nil) config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true) ctx := NewTestContext() ctx.SetAllowMissingDependencies(true) ctx.RegisterModuleType("test", ModuleFactoryAdaptor(expandSourcesTestModuleFactory)) ctx.RegisterModuleType("filegroup", ModuleFactoryAdaptor(FileGroupFactory)) ctx.RegisterModuleType("test", ModuleFactoryAdaptor(pathForModuleSrcTestModuleFactory)) fgBp := ` filegroup { name: "a", srcs: ["src/a"], bp := ` test { name: "foo", srcs: [":a"], exclude_srcs: [":b"], src: ":c", } ` mockFS := map[string][]byte{ "fg/Android.bp": []byte(fgBp), "foo/Android.bp": []byte(test.bp), "fg/src/a": nil, "foo/src/b": nil, "foo/src/c": nil, "foo/src/d": nil, "foo/src/e/e": nil, "foo/src_special/$": nil, "Android.bp": []byte(bp), } ctx.MockFileSystem(mockFS) ctx.Register() _, errs := ctx.ParseFileList(".", []string{"fg/Android.bp", "foo/Android.bp"}) _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) FailIfErrored(t, errs) _, errs = ctx.PrepareBuildActions(config) FailIfErrored(t, errs) m := ctx.ModuleForTests("foo", "").Module().(*expandSourcesTestModule) foo := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule) if g, w := m.srcs.Strings(), test.srcs; !reflect.DeepEqual(g, w) { t.Errorf("want srcs %q, got %q", w, g) if g, w := foo.missingDeps, []string{"a", "b", "c"}; !reflect.DeepEqual(g, w) { t.Errorf("want missing deps %q, got %q", w, g) } if g, w := m.rels, test.rels; !reflect.DeepEqual(g, w) { t.Errorf("want rels %q, got %q", w, g) if g, w := foo.srcs, []string{}; !reflect.DeepEqual(g, w) { t.Errorf("want srcs %q, got %q", w, g) } }) if g, w := foo.src, ""; g != w { t.Errorf("want src %q, got %q", w, g) } } func ExampleOutputPath_ReplaceExtension() { Loading android/prebuilt.go +1 −1 Original line number Diff line number Diff line Loading @@ -61,7 +61,7 @@ func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path { // Return the singleton source after expanding any filegroup in the // sources. return ctx.ExpandSource((*p.srcs)[0], "") return PathForModuleSrc(ctx, (*p.srcs)[0]) } func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) { Loading Loading
android/filegroup.go +1 −1 Original line number Diff line number Diff line Loading @@ -60,7 +60,7 @@ func FileGroupFactory() Module { } func (fg *fileGroup) GenerateAndroidBuildActions(ctx ModuleContext) { fg.srcs = ctx.ExpandSources(fg.properties.Srcs, fg.properties.Exclude_srcs) fg.srcs = PathsForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs) if fg.properties.Path != nil { fg.srcs = PathsWithModuleSrcSubDir(ctx, fg.srcs, String(fg.properties.Path)) Loading
android/module.go +8 −81 Original line number Diff line number Diff line Loading @@ -854,7 +854,7 @@ func (a *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) if a.commonProperties.Notice != nil { // For filegroup-based notice file references. a.noticeFile = ctx.ExpandSource(*a.commonProperties.Notice, "notice") a.noticeFile = PathForModuleSrc(ctx, *a.commonProperties.Notice) } } Loading Loading @@ -1419,91 +1419,18 @@ type SourceFileProducer interface { // Returns a list of paths expanded from globs and modules referenced using ":module" syntax. The property must // be tagged with `android:"path" to support automatic source module dependency resolution. // // Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead. func (ctx *androidModuleContext) ExpandSources(srcFiles, excludes []string) Paths { prefix := PathForModuleSrc(ctx).String() var expandedExcludes []string if excludes != nil { expandedExcludes = make([]string, 0, len(excludes)) } for _, e := range excludes { if m := SrcIsModule(e); m != "" { module := ctx.GetDirectDepWithTag(m, SourceDepTag) if module == nil { if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies([]string{m}) } else { ctx.ModuleErrorf(`missing dependency on %q, is the property annotated with android:"path"?`, m) } continue } 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) } } else { expandedExcludes = append(expandedExcludes, filepath.Join(prefix, e)) } } expandedSrcFiles := make(Paths, 0, len(srcFiles)) for _, s := range srcFiles { if m := SrcIsModule(s); m != "" { module := ctx.GetDirectDepWithTag(m, SourceDepTag) if module == nil { if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies([]string{m}) } else { ctx.ModuleErrorf(`missing dependency on %q, is the property annotated with android:"path"?`, m) } continue } if srcProducer, ok := module.(SourceFileProducer); ok { moduleSrcs := srcProducer.Srcs() for _, e := range expandedExcludes { for j, ms := range moduleSrcs { if ms.String() == e { moduleSrcs = append(moduleSrcs[:j], moduleSrcs[j+1:]...) } } } expandedSrcFiles = append(expandedSrcFiles, moduleSrcs...) } else { ctx.ModuleErrorf("srcs dependency %q is not a source file producing module", m) } } else if pathtools.IsGlob(s) { globbedSrcFiles := ctx.GlobFiles(filepath.Join(prefix, s), expandedExcludes) globbedSrcFiles = PathsWithModuleSrcSubDir(ctx, globbedSrcFiles, "") expandedSrcFiles = append(expandedSrcFiles, globbedSrcFiles...) } else { p := PathForModuleSrc(ctx, s) j := findStringInSlice(p.String(), expandedExcludes) if j == -1 { expandedSrcFiles = append(expandedSrcFiles, p) } } } return expandedSrcFiles return PathsForModuleSrcExcludes(ctx, srcFiles, excludes) } // Returns a single path expanded from globs and modules referenced using ":module" syntax. The property must // be tagged with `android:"path" to support automatic source module dependency resolution. // // Deprecated: use PathForModuleSrc instead. func (ctx *androidModuleContext) ExpandSource(srcFile, prop string) Path { srcFiles := ctx.ExpandSources([]string{srcFile}, nil) if len(srcFiles) == 1 { return srcFiles[0] } else if len(srcFiles) == 0 { if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies([]string{srcFile}) } else { ctx.PropertyErrorf(prop, "%s path %s does not exist", prop, srcFile) } return nil } else { ctx.PropertyErrorf(prop, "module providing %s must produce exactly one file", prop) return nil } return PathForModuleSrc(ctx, srcFile) } // Returns an optional single path expanded from globs and modules referenced using ":module" syntax if Loading @@ -1511,7 +1438,7 @@ func (ctx *androidModuleContext) ExpandSource(srcFile, prop string) Path { // dependency resolution. func (ctx *androidModuleContext) ExpandOptionalSource(srcFile *string, prop string) OptionalPath { if srcFile != nil { return OptionalPathForPath(ctx.ExpandSource(*srcFile, prop)) return OptionalPathForPath(PathForModuleSrc(ctx, *srcFile)) } return OptionalPath{} } Loading
android/paths.go +120 −12 Original line number Diff line number Diff line Loading @@ -220,11 +220,104 @@ func ExistentPathsForSources(ctx PathContext, paths []string) Paths { // PathsForModuleSrc returns Paths rooted from the module's local source // directory func PathsForModuleSrc(ctx ModuleContext, paths []string) Paths { ret := make(Paths, len(paths)) for i, path := range paths { ret[i] = PathForModuleSrc(ctx, path) return PathsForModuleSrcExcludes(ctx, paths, nil) } func PathsForModuleSrcExcludes(ctx ModuleContext, paths, excludes []string) Paths { prefix := pathForModuleSrc(ctx).String() var expandedExcludes []string if excludes != nil { expandedExcludes = make([]string, 0, len(excludes)) } for _, e := range excludes { if m := SrcIsModule(e); m != "" { module := ctx.GetDirectDepWithTag(m, SourceDepTag) if module == nil { if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies([]string{m}) } else { ctx.ModuleErrorf(`missing dependency on %q, is the property annotated with android:"path"?`, m) } continue } 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) } } else { expandedExcludes = append(expandedExcludes, filepath.Join(prefix, e)) } } if paths == nil { return nil } expandedSrcFiles := make(Paths, 0, len(paths)) for _, s := range paths { srcFiles, err := expandOneSrcPath(ctx, s, expandedExcludes) if depErr, ok := err.(missingDependencyError); ok { if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies(depErr.missingDeps) } else { ctx.ModuleErrorf(`%s, is the property annotated with android:"path"?`, depErr.Error()) } } else if err != nil { reportPathError(ctx, err) } expandedSrcFiles = append(expandedSrcFiles, srcFiles...) } return expandedSrcFiles } type missingDependencyError struct { missingDeps []string } func (e missingDependencyError) Error() string { return "missing dependencies: " + strings.Join(e.missingDeps, ", ") } func expandOneSrcPath(ctx ModuleContext, s string, expandedExcludes []string) (Paths, error) { if m := SrcIsModule(s); m != "" { module := ctx.GetDirectDepWithTag(m, SourceDepTag) if module == nil { return nil, missingDependencyError{[]string{m}} } if srcProducer, ok := module.(SourceFileProducer); ok { moduleSrcs := srcProducer.Srcs() for _, e := range expandedExcludes { for j := 0; j < len(moduleSrcs); j++ { if moduleSrcs[j].String() == e { moduleSrcs = append(moduleSrcs[:j], moduleSrcs[j+1:]...) j-- } } } return moduleSrcs, nil } else { return nil, fmt.Errorf("path dependency %q is not a source file producing module", m) } } else if pathtools.IsGlob(s) { paths := ctx.GlobFiles(pathForModuleSrc(ctx, s).String(), expandedExcludes) return PathsWithModuleSrcSubDir(ctx, paths, ""), nil } else { p := pathForModuleSrc(ctx, s) if exists, _, err := ctx.Fs().Exists(p.String()); err != nil { reportPathErrorf(ctx, "%s: %s", p, err.Error()) } else if !exists { reportPathErrorf(ctx, "module source path %q does not exist", p) } j := findStringInSlice(p.String(), expandedExcludes) if j >= 0 { return nil, nil } return Paths{p}, nil } return ret } // pathsForModuleSrcFromFullPath returns Paths rooted from the module's local Loading Loading @@ -750,15 +843,30 @@ var _ resPathProvider = SourcePath{} // PathForModuleSrc returns a Path representing the paths... under the // module's local source directory. func PathForModuleSrc(ctx ModuleContext, paths ...string) Path { path := pathForModuleSrc(ctx, paths...) if exists, _, err := ctx.Fs().Exists(path.String()); err != nil { reportPathErrorf(ctx, "%s: %s", path, err.Error()) } else if !exists { reportPathErrorf(ctx, "module source path %q does not exist", path) func PathForModuleSrc(ctx ModuleContext, pathComponents ...string) Path { p, err := validatePath(pathComponents...) if err != nil { reportPathError(ctx, err) } return path paths, err := expandOneSrcPath(ctx, p, nil) if err != nil { if depErr, ok := err.(missingDependencyError); ok { if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies(depErr.missingDeps) } else { ctx.ModuleErrorf(`%s, is the property annotated with android:"path"?`, depErr.Error()) } } else { reportPathError(ctx, err) } return nil } else if len(paths) == 0 { reportPathErrorf(ctx, "%q produced no files, expected exactly one", p) return nil } else if len(paths) > 1 { reportPathErrorf(ctx, "%q produced %d files, expected exactly one", p, len(paths)) } return paths[0] } func pathForModuleSrc(ctx ModuleContext, paths ...string) SourcePath { Loading
android/paths_test.go +190 −50 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import ( "testing" "github.com/google/blueprint/pathtools" "github.com/google/blueprint/proptools" ) type strsTestCase struct { Loading Loading @@ -706,39 +707,117 @@ func TestPathForSource(t *testing.T) { } } type expandSourcesTestModule struct { type pathForModuleSrcTestModule struct { ModuleBase props struct { Srcs []string `android:"path"` Exclude_srcs []string `android:"path"` Src *string `android:"path"` } srcs Paths src string rel string srcs []string rels []string missingDeps []string } func expandSourcesTestModuleFactory() Module { module := &expandSourcesTestModule{} func pathForModuleSrcTestModuleFactory() Module { module := &pathForModuleSrcTestModule{} module.AddProperties(&module.props) InitAndroidModule(module) return module } func (p *expandSourcesTestModule) GenerateAndroidBuildActions(ctx ModuleContext) { p.srcs = ctx.ExpandSources(p.props.Srcs, p.props.Exclude_srcs) func (p *pathForModuleSrcTestModule) GenerateAndroidBuildActions(ctx ModuleContext) { srcs := PathsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs) p.srcs = srcs.Strings() for _, src := range p.srcs { for _, src := range srcs { p.rels = append(p.rels, src.Rel()) } if p.props.Src != nil { src := PathForModuleSrc(ctx, *p.props.Src) if src != nil { p.src = src.String() p.rel = src.Rel() } } p.missingDeps = ctx.GetMissingDependencies() } func TestExpandSources(t *testing.T) { tests := []struct { type pathForModuleSrcTestCase struct { name string bp string srcs []string rels []string }{ src string rel string } func testPathForModuleSrc(t *testing.T, buildDir string, tests []pathForModuleSrcTestCase) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { config := TestConfig(buildDir, nil) ctx := NewTestContext() ctx.RegisterModuleType("test", ModuleFactoryAdaptor(pathForModuleSrcTestModuleFactory)) ctx.RegisterModuleType("filegroup", ModuleFactoryAdaptor(FileGroupFactory)) fgBp := ` filegroup { name: "a", srcs: ["src/a"], } ` mockFS := map[string][]byte{ "fg/Android.bp": []byte(fgBp), "foo/Android.bp": []byte(test.bp), "fg/src/a": nil, "foo/src/b": nil, "foo/src/c": nil, "foo/src/d": nil, "foo/src/e/e": nil, "foo/src_special/$": nil, } ctx.MockFileSystem(mockFS) ctx.Register() _, errs := ctx.ParseFileList(".", []string{"fg/Android.bp", "foo/Android.bp"}) FailIfErrored(t, errs) _, errs = ctx.PrepareBuildActions(config) FailIfErrored(t, errs) m := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule) if g, w := m.srcs, test.srcs; !reflect.DeepEqual(g, w) { t.Errorf("want srcs %q, got %q", w, g) } if g, w := m.rels, test.rels; !reflect.DeepEqual(g, w) { t.Errorf("want rels %q, got %q", w, g) } if g, w := m.src, test.src; g != w { t.Errorf("want src %q, got %q", w, g) } if g, w := m.rel, test.rel; g != w { t.Errorf("want rel %q, got %q", w, g) } }) } } func TestPathsForModuleSrc(t *testing.T) { tests := []pathForModuleSrcTestCase{ { name: "path", bp: ` Loading Loading @@ -794,57 +873,118 @@ func TestExpandSources(t *testing.T) { }, } buildDir, err := ioutil.TempDir("", "soong_paths_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", bp: ` test { name: "foo", src: "src/b", }`, src: "foo/src/b", rel: "src/b", }, { name: "glob", bp: ` test { name: "foo", src: "src/e/*", }`, src: "foo/src/e/e", rel: "src/e/e", }, { name: "filegroup", bp: ` test { name: "foo", src: ":a", }`, src: "fg/src/a", rel: "src/a", }, { name: "special characters glob", bp: ` test { name: "foo", src: "src_special/*", }`, src: "foo/src_special/$", rel: "src_special/$", }, } buildDir, err := ioutil.TempDir("", "soong_path_for_module_src_test") if err != nil { t.Fatal(err) } defer os.RemoveAll(buildDir) for _, test := range tests { t.Run(test.name, func(t *testing.T) { testPathForModuleSrc(t, buildDir, tests) } func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) { buildDir, err := ioutil.TempDir("", "soong_paths_for_module_src_allow_missing_dependencies_test") if err != nil { t.Fatal(err) } defer os.RemoveAll(buildDir) config := TestConfig(buildDir, nil) config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true) ctx := NewTestContext() ctx.SetAllowMissingDependencies(true) ctx.RegisterModuleType("test", ModuleFactoryAdaptor(expandSourcesTestModuleFactory)) ctx.RegisterModuleType("filegroup", ModuleFactoryAdaptor(FileGroupFactory)) ctx.RegisterModuleType("test", ModuleFactoryAdaptor(pathForModuleSrcTestModuleFactory)) fgBp := ` filegroup { name: "a", srcs: ["src/a"], bp := ` test { name: "foo", srcs: [":a"], exclude_srcs: [":b"], src: ":c", } ` mockFS := map[string][]byte{ "fg/Android.bp": []byte(fgBp), "foo/Android.bp": []byte(test.bp), "fg/src/a": nil, "foo/src/b": nil, "foo/src/c": nil, "foo/src/d": nil, "foo/src/e/e": nil, "foo/src_special/$": nil, "Android.bp": []byte(bp), } ctx.MockFileSystem(mockFS) ctx.Register() _, errs := ctx.ParseFileList(".", []string{"fg/Android.bp", "foo/Android.bp"}) _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) FailIfErrored(t, errs) _, errs = ctx.PrepareBuildActions(config) FailIfErrored(t, errs) m := ctx.ModuleForTests("foo", "").Module().(*expandSourcesTestModule) foo := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule) if g, w := m.srcs.Strings(), test.srcs; !reflect.DeepEqual(g, w) { t.Errorf("want srcs %q, got %q", w, g) if g, w := foo.missingDeps, []string{"a", "b", "c"}; !reflect.DeepEqual(g, w) { t.Errorf("want missing deps %q, got %q", w, g) } if g, w := m.rels, test.rels; !reflect.DeepEqual(g, w) { t.Errorf("want rels %q, got %q", w, g) if g, w := foo.srcs, []string{}; !reflect.DeepEqual(g, w) { t.Errorf("want srcs %q, got %q", w, g) } }) if g, w := foo.src, ""; g != w { t.Errorf("want src %q, got %q", w, g) } } func ExampleOutputPath_ReplaceExtension() { Loading
android/prebuilt.go +1 −1 Original line number Diff line number Diff line Loading @@ -61,7 +61,7 @@ func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path { // Return the singleton source after expanding any filegroup in the // sources. return ctx.ExpandSource((*p.srcs)[0], "") return PathForModuleSrc(ctx, (*p.srcs)[0]) } func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) { Loading