From 7b310eefb74fc93f80c359d0b0486fc242100946 Mon Sep 17 00:00:00 2001 From: Dan Willemsen Date: Fri, 18 Dec 2015 15:11:17 -0800 Subject: Make global C include paths optional Only add them to the global C include paths if they exist. And make sure to set up proper dependencies so that we notice when they are added or removed. Change-Id: Ia9df14f6ae6869927ad3d3a15fb5a8081f616a81 --- common/package_ctx.go | 26 +++++++++++++-------- common/paths.go | 64 ++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 72 insertions(+), 18 deletions(-) (limited to 'common') diff --git a/common/package_ctx.go b/common/package_ctx.go index cd18b658..233da5f8 100644 --- a/common/package_ctx.go +++ b/common/package_ctx.go @@ -37,6 +37,7 @@ func NewPackageContext(pkgPath string) AndroidPackageContext { // The most common use here will be with VariableFunc, where only a config is // provided, and an error should be returned. type configErrorWrapper struct { + pctx AndroidPackageContext config Config errors []error } @@ -50,6 +51,9 @@ func (e *configErrorWrapper) Config() interface{} { func (e *configErrorWrapper) Errorf(format string, args ...interface{}) { e.errors = append(e.errors, fmt.Errorf(format, args...)) } +func (e *configErrorWrapper) AddNinjaFileDeps(deps ...string) { + e.pctx.AddNinjaFileDeps(deps...) +} // SourcePathVariable returns a Variable whose value is the source directory // appended with the supplied path. It may only be called during a Go package's @@ -57,7 +61,7 @@ func (e *configErrorWrapper) Errorf(format string, args ...interface{}) { // package-scoped variable's initialization. func (p AndroidPackageContext) SourcePathVariable(name, path string) blueprint.Variable { return p.VariableFunc(name, func(config interface{}) (string, error) { - ctx := &configErrorWrapper{config.(Config), []error{}} + ctx := &configErrorWrapper{p, config.(Config), []error{}} p := safePathForSource(ctx, path) if len(ctx.errors) > 0 { return "", ctx.errors[0] @@ -72,7 +76,7 @@ func (p AndroidPackageContext) SourcePathVariable(name, path string) blueprint.V // package-scoped variable's initialization. func (p AndroidPackageContext) HostBinToolVariable(name, path string) blueprint.Variable { return p.VariableFunc(name, func(config interface{}) (string, error) { - ctx := &configErrorWrapper{config.(Config), []error{}} + ctx := &configErrorWrapper{p, config.(Config), []error{}} p := PathForOutput(ctx, "host", ctx.config.PrebuiltOS(), "bin", path) if len(ctx.errors) > 0 { return "", ctx.errors[0] @@ -87,7 +91,7 @@ func (p AndroidPackageContext) HostBinToolVariable(name, path string) blueprint. // part of a package-scoped variable's initialization. func (p AndroidPackageContext) HostJavaToolVariable(name, path string) blueprint.Variable { return p.VariableFunc(name, func(config interface{}) (string, error) { - ctx := &configErrorWrapper{config.(Config), []error{}} + ctx := &configErrorWrapper{p, config.(Config), []error{}} p := PathForOutput(ctx, "host", ctx.config.PrebuiltOS(), "framework", path) if len(ctx.errors) > 0 { return "", ctx.errors[0] @@ -102,7 +106,7 @@ func (p AndroidPackageContext) HostJavaToolVariable(name, path string) blueprint // package-scoped variable's initialization. func (p AndroidPackageContext) IntermediatesPathVariable(name, path string) blueprint.Variable { return p.VariableFunc(name, func(config interface{}) (string, error) { - ctx := &configErrorWrapper{config.(Config), []error{}} + ctx := &configErrorWrapper{p, config.(Config), []error{}} p := PathForIntermediates(ctx, path) if len(ctx.errors) > 0 { return "", ctx.errors[0] @@ -111,14 +115,16 @@ func (p AndroidPackageContext) IntermediatesPathVariable(name, path string) blue }) } -// PrefixedPathsForSourceVariable returns a Variable whose value is the -// list of source paths prefixed with the supplied prefix. It may only be -// called during a Go package's initialization - either from the init() +// PrefixedPathsForOptionalSourceVariable returns a Variable whose value is the +// list of present source paths prefixed with the supplied prefix. It may only +// be called during a Go package's initialization - either from the init() // function or as part of a package-scoped variable's initialization. -func (p AndroidPackageContext) PrefixedPathsForSourceVariable(name, prefix string, paths []string) blueprint.Variable { +func (p AndroidPackageContext) PrefixedPathsForOptionalSourceVariable( + name, prefix string, paths []string) blueprint.Variable { + return p.VariableFunc(name, func(config interface{}) (string, error) { - ctx := &configErrorWrapper{config.(Config), []error{}} - paths := PathsForSource(ctx, paths) + ctx := &configErrorWrapper{p, config.(Config), []error{}} + paths := PathsForOptionalSource(ctx, "", paths) if len(ctx.errors) > 0 { return "", ctx.errors[0] } diff --git a/common/paths.go b/common/paths.go index 8a085ea1..e0d4914d 100644 --- a/common/paths.go +++ b/common/paths.go @@ -21,6 +21,8 @@ import ( "reflect" "strings" + "android/soong/glob" + "github.com/google/blueprint" "github.com/google/blueprint/pathtools" ) @@ -29,6 +31,7 @@ import ( // Path methods. type PathContext interface { Config() interface{} + AddNinjaFileDeps(deps ...string) } var _ PathContext = blueprint.SingletonContext(nil) @@ -177,6 +180,20 @@ func PathsForSource(ctx PathContext, paths []string) Paths { return ret } +// PathsForOptionalSource returns a list of Paths rooted from SrcDir that are +// found in the tree. If any are not found, they are omitted from the list, +// and dependencies are added so that we're re-run when they are added. +func PathsForOptionalSource(ctx PathContext, intermediates string, paths []string) Paths { + ret := make(Paths, 0, len(paths)) + for _, path := range paths { + p := OptionalPathForSource(ctx, intermediates, path) + if p.Valid() { + ret = append(ret, p.Path()) + } + } + return ret +} + // PathsForModuleSrc returns Paths rooted from the module's local source // directory func PathsForModuleSrc(ctx AndroidModuleContext, paths []string) Paths { @@ -319,7 +336,12 @@ func PathForSource(ctx PathContext, paths ...string) SourcePath { // OptionalPathForSource returns an OptionalPath with the SourcePath if the // path exists, or an empty OptionalPath if it doesn't exist. Dependencies are added // so that the ninja file will be regenerated if the state of the path changes. -func OptionalPathForSource(ctx blueprint.SingletonContext, intermediates string, paths ...string) OptionalPath { +func OptionalPathForSource(ctx PathContext, intermediates string, paths ...string) OptionalPath { + if len(paths) == 0 { + // For when someone forgets the 'intermediates' argument + panic("Missing path(s)") + } + p := validatePath(ctx, paths...) path := SourcePath{basePath{p, pathConfig(ctx)}} @@ -338,16 +360,39 @@ func OptionalPathForSource(ctx blueprint.SingletonContext, intermediates string, return OptionalPath{} } - // Use glob to produce proper dependencies, even though we only want - // a single file. - files, err := Glob(ctx, PathForIntermediates(ctx, intermediates).String(), path.String(), nil) - if err != nil { - reportPathError(ctx, "glob: %s", err.Error()) + if glob.IsGlob(path.String()) { + reportPathError(ctx, "path may not contain a glob: %s", path.String()) return OptionalPath{} } - if len(files) == 0 { - return OptionalPath{} + if gctx, ok := ctx.(globContext); ok { + // Use glob to produce proper dependencies, even though we only want + // a single file. + files, err := Glob(gctx, PathForIntermediates(ctx, intermediates).String(), path.String(), nil) + if err != nil { + reportPathError(ctx, "glob: %s", err.Error()) + return OptionalPath{} + } + + if len(files) == 0 { + return OptionalPath{} + } + } else { + // We cannot add build statements in this context, so we fall back to + // AddNinjaFileDeps + files, dirs, err := pathtools.Glob(path.String()) + if err != nil { + reportPathError(ctx, "glob: %s", err.Error()) + return OptionalPath{} + } + + ctx.AddNinjaFileDeps(dirs...) + + if len(files) == 0 { + return OptionalPath{} + } + + ctx.AddNinjaFileDeps(path.String()) } return OptionalPathForPath(path) } @@ -377,6 +422,9 @@ func (p SourcePath) OverlayPath(ctx AndroidModuleContext, path Path) OptionalPat } dir := filepath.Join(p.config.srcDir, p.path, relDir) // Use Glob so that we are run again if the directory is added. + if glob.IsGlob(dir) { + reportPathError(ctx, "Path may not contain a glob: %s", dir) + } paths, err := Glob(ctx, PathForModuleOut(ctx, "overlay").String(), dir, []string{}) if err != nil { reportPathError(ctx, "glob: %s", err.Error()) -- cgit v1.2.3