From 2019658b86efa7c3ff1ad3853e408cafb32c2953 Mon Sep 17 00:00:00 2001 From: Dan Willemsen Date: Fri, 17 Jul 2020 19:28:53 -0700 Subject: [PATCH] Support per-module MakeVars This allows setting per-module make variables earlier in the build, particularly for prebuilt_build_tool users like LEX/M4/BISON. I moved filegroup over because it's a simpler common interface, but it doesn't strictly need it. With this, the last user of the hardcoded cc.m4Cmd variable is gone. Test: Inspect out/soong/make_vars-*.mk, out/soong/late-*.mk Test: treehugger Change-Id: I195b688131feac0c100c338a0749368aa5d50f4f --- android/filegroup.go | 23 +------ android/makevars.go | 121 ++++++++++++++++++++++++--------- android/prebuilt_build_tool.go | 10 +++ cc/gen.go | 2 - cc/makevars.go | 2 - 5 files changed, 103 insertions(+), 55 deletions(-) diff --git a/android/filegroup.go b/android/filegroup.go index ec522fc06..68311e39a 100644 --- a/android/filegroup.go +++ b/android/filegroup.go @@ -15,9 +15,7 @@ package android import ( - "io" "strings" - "text/template" ) func init() { @@ -71,23 +69,8 @@ func (fg *fileGroup) Srcs() Paths { return append(Paths{}, fg.srcs...) } -var androidMkTemplate = template.Must(template.New("filegroup").Parse(` -ifdef {{.makeVar}} - $(error variable {{.makeVar}} set by soong module is already set in make) -endif -{{.makeVar}} := {{.value}} -.KATI_READONLY := {{.makeVar}} -`)) - -func (fg *fileGroup) AndroidMk() AndroidMkData { - return AndroidMkData{ - Custom: func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) { - if makeVar := String(fg.properties.Export_to_make_var); makeVar != "" { - androidMkTemplate.Execute(w, map[string]string{ - "makeVar": makeVar, - "value": strings.Join(fg.srcs.Strings(), " "), - }) - } - }, +func (fg *fileGroup) MakeVars(ctx MakeVarsModuleContext) { + if makeVar := String(fg.properties.Export_to_make_var); makeVar != "" { + ctx.StrictRaw(makeVar, strings.Join(fg.srcs.Strings(), " ")) } } diff --git a/android/makevars.go b/android/makevars.go index ff7c8e4a7..86f4b424b 100644 --- a/android/makevars.go +++ b/android/makevars.go @@ -17,6 +17,7 @@ package android import ( "bytes" "fmt" + "sort" "strconv" "strings" @@ -34,43 +35,16 @@ func androidMakeVarsProvider(ctx MakeVarsContext) { } /////////////////////////////////////////////////////////////////////////////// -// Interface for other packages to use to declare make variables -type MakeVarsContext interface { + +// BaseMakeVarsContext contains the common functions for other packages to use +// to declare make variables +type BaseMakeVarsContext interface { Config() Config DeviceConfig() DeviceConfig AddNinjaFileDeps(deps ...string) - ModuleName(module blueprint.Module) string - ModuleDir(module blueprint.Module) string - ModuleSubDir(module blueprint.Module) string - ModuleType(module blueprint.Module) string - BlueprintFile(module blueprint.Module) string - - ModuleErrorf(module blueprint.Module, format string, args ...interface{}) - Errorf(format string, args ...interface{}) Failed() bool - VisitAllModules(visit func(Module)) - VisitAllModulesIf(pred func(Module) bool, visit func(Module)) - - // Verify the make variable matches the Soong version, fail the build - // if it does not. If the make variable is empty, just set it. - Strict(name, ninjaStr string) - // Check to see if the make variable matches the Soong version, warn if - // it does not. If the make variable is empty, just set it. - Check(name, ninjaStr string) - - // These are equivalent to the above, but sort the make and soong - // variables before comparing them. They also show the unique entries - // in each list when displaying the difference, instead of the entire - // string. - StrictSorted(name, ninjaStr string) - CheckSorted(name, ninjaStr string) - - // Evaluates a ninja string and returns the result. Used if more - // complicated modification needs to happen before giving it to Make. - Eval(ninjaStr string) (string, error) - // These are equivalent to Strict and Check, but do not attempt to // evaluate the values before writing them to the Makefile. They can // be used when all ninja variables have already been evaluated through @@ -108,6 +82,48 @@ type MakeVarsContext interface { DistForGoalsWithFilename(goals []string, path Path, filename string) } +// MakeVarsContext contains the set of functions available for MakeVarsProvider +// and SingletonMakeVarsProvider implementations. +type MakeVarsContext interface { + BaseMakeVarsContext + + ModuleName(module blueprint.Module) string + ModuleDir(module blueprint.Module) string + ModuleSubDir(module blueprint.Module) string + ModuleType(module blueprint.Module) string + BlueprintFile(module blueprint.Module) string + + ModuleErrorf(module blueprint.Module, format string, args ...interface{}) + Errorf(format string, args ...interface{}) + + VisitAllModules(visit func(Module)) + VisitAllModulesIf(pred func(Module) bool, visit func(Module)) + + // Verify the make variable matches the Soong version, fail the build + // if it does not. If the make variable is empty, just set it. + Strict(name, ninjaStr string) + // Check to see if the make variable matches the Soong version, warn if + // it does not. If the make variable is empty, just set it. + Check(name, ninjaStr string) + + // These are equivalent to the above, but sort the make and soong + // variables before comparing them. They also show the unique entries + // in each list when displaying the difference, instead of the entire + // string. + StrictSorted(name, ninjaStr string) + CheckSorted(name, ninjaStr string) + + // Evaluates a ninja string and returns the result. Used if more + // complicated modification needs to happen before giving it to Make. + Eval(ninjaStr string) (string, error) +} + +// MakeVarsModuleContext contains the set of functions available for modules +// implementing the ModuleMakeVarsProvider interface. +type MakeVarsModuleContext interface { + BaseMakeVarsContext +} + var _ PathContext = MakeVarsContext(nil) type MakeVarsProvider func(ctx MakeVarsContext) @@ -135,6 +151,14 @@ func SingletonmakeVarsProviderAdapter(singleton SingletonMakeVarsProvider) MakeV return func(ctx MakeVarsContext) { singleton.MakeVars(ctx) } } +// ModuleMakeVarsProvider is a Module with an extra method to provide extra values to be exported to Make. +type ModuleMakeVarsProvider interface { + Module + + // MakeVars uses a MakeVarsModuleContext to provide extra values to be exported to Make. + MakeVars(ctx MakeVarsModuleContext) +} + /////////////////////////////////////////////////////////////////////////////// func makeVarsSingletonFunc() Singleton { @@ -209,10 +233,45 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) { dists = append(dists, mctx.dists...) } + ctx.VisitAllModules(func(m Module) { + if provider, ok := m.(ModuleMakeVarsProvider); ok { + mctx := &makeVarsContext{ + SingletonContext: ctx, + } + + provider.MakeVars(mctx) + + vars = append(vars, mctx.vars...) + phonies = append(phonies, mctx.phonies...) + dists = append(dists, mctx.dists...) + } + }) + if ctx.Failed() { return } + sort.Slice(vars, func(i, j int) bool { + return vars[i].name < vars[j].name + }) + sort.Slice(phonies, func(i, j int) bool { + return phonies[i].name < phonies[j].name + }) + lessArr := func(a, b []string) bool { + if len(a) == len(b) { + for i := range a { + if a[i] < b[i] { + return true + } + } + return false + } + return len(a) < len(b) + } + sort.Slice(dists, func(i, j int) bool { + return lessArr(dists[i].goals, dists[j].goals) || lessArr(dists[i].paths, dists[j].paths) + }) + outBytes := s.writeVars(vars) if err := pathtools.WriteFileIfChanged(outFile, outBytes, 0666); err != nil { diff --git a/android/prebuilt_build_tool.go b/android/prebuilt_build_tool.go index a9f29ef69..561771b76 100644 --- a/android/prebuilt_build_tool.go +++ b/android/prebuilt_build_tool.go @@ -29,6 +29,10 @@ type prebuiltBuildToolProperties struct { // Extra files that should trigger rules using this tool to rebuild Deps []string `android:"path,arch_variant"` + + // Create a make variable with the specified name that contains the path to + // this prebuilt built tool, relative to the root of the source tree. + Export_to_make_var *string } type prebuiltBuildTool struct { @@ -81,6 +85,12 @@ func (t *prebuiltBuildTool) HostToolPath() OptionalPath { return t.toolPath } +func (t *prebuiltBuildTool) MakeVars(ctx MakeVarsModuleContext) { + if makeVar := String(t.properties.Export_to_make_var); makeVar != "" { + ctx.StrictRaw(makeVar, t.toolPath.String()) + } +} + var _ HostToolProvider = &prebuiltBuildTool{} // prebuilt_build_tool is to declare prebuilts to be used during the build, particularly for use diff --git a/cc/gen.go b/cc/gen.go index 6f9036bd9..edae061ce 100644 --- a/cc/gen.go +++ b/cc/gen.go @@ -24,8 +24,6 @@ import ( ) func init() { - pctx.SourcePathVariable("m4Cmd", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/m4") - pctx.HostBinToolVariable("aidlCmd", "aidl-cpp") pctx.HostBinToolVariable("syspropCmd", "sysprop_cpp") } diff --git a/cc/makevars.go b/cc/makevars.go index 968eeb5f4..dcfd6d8ef 100644 --- a/cc/makevars.go +++ b/cc/makevars.go @@ -148,8 +148,6 @@ func makeVarsProvider(ctx android.MakeVarsContext) { ctx.Strict("AIDL_CPP", "${aidlCmd}") ctx.Strict("ALLOWED_MANUAL_INTERFACE_PATHS", strings.Join(allowedManualInterfacePaths, " ")) - ctx.Strict("M4", "${m4Cmd}") - ctx.Strict("RS_GLOBAL_INCLUDES", "${config.RsGlobalIncludes}") ctx.Strict("SOONG_STRIP_PATH", "${stripPath}")