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.
// Do not add anything to this list.
pctx.PrefixedPathsForSourceVariable("commonGlobalIncludes", "-isystem ",
pctx.PrefixedPathsForOptionalSourceVariable("commonGlobalIncludes", "-isystem ",
[]string{
"system/core/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
// 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]
}

View File

@@ -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())