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
This commit is contained in:
Dan Willemsen
2015-12-18 15:11:17 -08:00
parent 122d9f3e1d
commit 7b310eefb7
3 changed files with 73 additions and 19 deletions

View File

@@ -125,7 +125,7 @@ func init() {
// Everything in this list is a crime against abstraction and dependency tracking. // Everything in this list is a crime against abstraction and dependency tracking.
// Do not add anything to this list. // Do not add anything to this list.
pctx.PrefixedPathsForSourceVariable("commonGlobalIncludes", "-isystem ", pctx.PrefixedPathsForOptionalSourceVariable("commonGlobalIncludes", "-isystem ",
[]string{ []string{
"system/core/include", "system/core/include",
"hardware/libhardware/include", "hardware/libhardware/include",

View File

@@ -37,6 +37,7 @@ func NewPackageContext(pkgPath string) AndroidPackageContext {
// The most common use here will be with VariableFunc, where only a config is // The most common use here will be with VariableFunc, where only a config is
// provided, and an error should be returned. // provided, and an error should be returned.
type configErrorWrapper struct { type configErrorWrapper struct {
pctx AndroidPackageContext
config Config config Config
errors []error errors []error
} }
@@ -50,6 +51,9 @@ func (e *configErrorWrapper) Config() interface{} {
func (e *configErrorWrapper) Errorf(format string, args ...interface{}) { func (e *configErrorWrapper) Errorf(format string, args ...interface{}) {
e.errors = append(e.errors, fmt.Errorf(format, args...)) 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 // 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 // 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. // package-scoped variable's initialization.
func (p AndroidPackageContext) SourcePathVariable(name, path string) blueprint.Variable { func (p AndroidPackageContext) SourcePathVariable(name, path string) blueprint.Variable {
return p.VariableFunc(name, func(config interface{}) (string, error) { return p.VariableFunc(name, func(config interface{}) (string, error) {
ctx := &configErrorWrapper{config.(Config), []error{}} ctx := &configErrorWrapper{p, config.(Config), []error{}}
p := safePathForSource(ctx, path) p := safePathForSource(ctx, path)
if len(ctx.errors) > 0 { if len(ctx.errors) > 0 {
return "", 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. // package-scoped variable's initialization.
func (p AndroidPackageContext) HostBinToolVariable(name, path string) blueprint.Variable { func (p AndroidPackageContext) HostBinToolVariable(name, path string) blueprint.Variable {
return p.VariableFunc(name, func(config interface{}) (string, error) { 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) p := PathForOutput(ctx, "host", ctx.config.PrebuiltOS(), "bin", path)
if len(ctx.errors) > 0 { if len(ctx.errors) > 0 {
return "", 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. // part of a package-scoped variable's initialization.
func (p AndroidPackageContext) HostJavaToolVariable(name, path string) blueprint.Variable { func (p AndroidPackageContext) HostJavaToolVariable(name, path string) blueprint.Variable {
return p.VariableFunc(name, func(config interface{}) (string, error) { 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) p := PathForOutput(ctx, "host", ctx.config.PrebuiltOS(), "framework", path)
if len(ctx.errors) > 0 { if len(ctx.errors) > 0 {
return "", ctx.errors[0] return "", ctx.errors[0]
@@ -102,7 +106,7 @@ func (p AndroidPackageContext) HostJavaToolVariable(name, path string) blueprint
// package-scoped variable's initialization. // package-scoped variable's initialization.
func (p AndroidPackageContext) IntermediatesPathVariable(name, path string) blueprint.Variable { func (p AndroidPackageContext) IntermediatesPathVariable(name, path string) blueprint.Variable {
return p.VariableFunc(name, func(config interface{}) (string, error) { return p.VariableFunc(name, func(config interface{}) (string, error) {
ctx := &configErrorWrapper{config.(Config), []error{}} ctx := &configErrorWrapper{p, config.(Config), []error{}}
p := PathForIntermediates(ctx, path) p := PathForIntermediates(ctx, path)
if len(ctx.errors) > 0 { if len(ctx.errors) > 0 {
return "", 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 // PrefixedPathsForOptionalSourceVariable returns a Variable whose value is the
// list of source paths prefixed with the supplied prefix. It may only be // list of present source paths prefixed with the supplied prefix. It may only
// called during a Go package's initialization - either from the init() // be called during a Go package's initialization - either from the init()
// function or as part of a package-scoped variable's initialization. // 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) { return p.VariableFunc(name, func(config interface{}) (string, error) {
ctx := &configErrorWrapper{config.(Config), []error{}} ctx := &configErrorWrapper{p, config.(Config), []error{}}
paths := PathsForSource(ctx, paths) paths := PathsForOptionalSource(ctx, "", paths)
if len(ctx.errors) > 0 { if len(ctx.errors) > 0 {
return "", ctx.errors[0] return "", ctx.errors[0]
} }

View File

@@ -21,6 +21,8 @@ import (
"reflect" "reflect"
"strings" "strings"
"android/soong/glob"
"github.com/google/blueprint" "github.com/google/blueprint"
"github.com/google/blueprint/pathtools" "github.com/google/blueprint/pathtools"
) )
@@ -29,6 +31,7 @@ import (
// Path methods. // Path methods.
type PathContext interface { type PathContext interface {
Config() interface{} Config() interface{}
AddNinjaFileDeps(deps ...string)
} }
var _ PathContext = blueprint.SingletonContext(nil) var _ PathContext = blueprint.SingletonContext(nil)
@@ -177,6 +180,20 @@ func PathsForSource(ctx PathContext, paths []string) Paths {
return ret 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 // PathsForModuleSrc returns Paths rooted from the module's local source
// directory // directory
func PathsForModuleSrc(ctx AndroidModuleContext, paths []string) Paths { 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 // OptionalPathForSource returns an OptionalPath with the SourcePath if the
// path exists, or an empty OptionalPath if it doesn't exist. Dependencies are added // 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. // 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...) p := validatePath(ctx, paths...)
path := SourcePath{basePath{p, pathConfig(ctx)}} path := SourcePath{basePath{p, pathConfig(ctx)}}
@@ -338,9 +360,15 @@ func OptionalPathForSource(ctx blueprint.SingletonContext, intermediates string,
return OptionalPath{} return OptionalPath{}
} }
if glob.IsGlob(path.String()) {
reportPathError(ctx, "path may not contain a glob: %s", path.String())
return OptionalPath{}
}
if gctx, ok := ctx.(globContext); ok {
// Use glob to produce proper dependencies, even though we only want // Use glob to produce proper dependencies, even though we only want
// a single file. // a single file.
files, err := Glob(ctx, PathForIntermediates(ctx, intermediates).String(), path.String(), nil) files, err := Glob(gctx, PathForIntermediates(ctx, intermediates).String(), path.String(), nil)
if err != nil { if err != nil {
reportPathError(ctx, "glob: %s", err.Error()) reportPathError(ctx, "glob: %s", err.Error())
return OptionalPath{} return OptionalPath{}
@@ -349,6 +377,23 @@ func OptionalPathForSource(ctx blueprint.SingletonContext, intermediates string,
if len(files) == 0 { if len(files) == 0 {
return OptionalPath{} 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) 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) dir := filepath.Join(p.config.srcDir, p.path, relDir)
// Use Glob so that we are run again if the directory is added. // 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{}) paths, err := Glob(ctx, PathForModuleOut(ctx, "overlay").String(), dir, []string{})
if err != nil { if err != nil {
reportPathError(ctx, "glob: %s", err.Error()) reportPathError(ctx, "glob: %s", err.Error())