Define Soong phony rules in Make
To support dist-for-goals in Soong, we need to define all phony rules
in Make so that dist-for-goals can insert additional dependencies on
them. Collect all the phony rules in phonySingleton and write them
out as Make rules when Soong is embedded in Make, or as blueprint.Phony
rules when Soong is run standalone.
Bug: 153485543
Test: m checkbuild
Change-Id: I68201eff30744b0f487fc4f11f033767b53a627d
Merged-In: I68201eff30744b0f487fc4f11f033767b53a627d
(cherry picked from commit c3d87d3112
)
This commit is contained in:
parent
5a3458ddc0
commit
9855207d0e
|
@ -34,6 +34,7 @@ bootstrap_go_package {
|
|||
"package_ctx.go",
|
||||
"path_properties.go",
|
||||
"paths.go",
|
||||
"phony.go",
|
||||
"prebuilt.go",
|
||||
"proto.go",
|
||||
"register.go",
|
||||
|
|
|
@ -17,12 +17,11 @@ package android
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
"github.com/google/blueprint/pathtools"
|
||||
"github.com/google/blueprint/proptools"
|
||||
)
|
||||
|
||||
|
@ -84,6 +83,11 @@ type MakeVarsContext interface {
|
|||
// builder whenever a file matching the pattern as added or removed, without rerunning if a
|
||||
// file that does not match the pattern is added to a searched directory.
|
||||
GlobWithDeps(pattern string, excludes []string) ([]string, error)
|
||||
|
||||
// Phony creates a phony rule in Make, which will allow additional DistForGoal
|
||||
// dependencies to be added to it. Phony can be called on the same name multiple
|
||||
// times to add additional dependencies.
|
||||
Phony(names string, deps ...Path)
|
||||
}
|
||||
|
||||
var _ PathContext = MakeVarsContext(nil)
|
||||
|
@ -133,6 +137,7 @@ type makeVarsContext struct {
|
|||
config Config
|
||||
pctx PackageContext
|
||||
vars []makeVarsVariable
|
||||
phonies []phony
|
||||
}
|
||||
|
||||
var _ MakeVarsContext = &makeVarsContext{}
|
||||
|
@ -144,6 +149,11 @@ type makeVarsVariable struct {
|
|||
strict bool
|
||||
}
|
||||
|
||||
type phony struct {
|
||||
name string
|
||||
deps []string
|
||||
}
|
||||
|
||||
func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) {
|
||||
if !ctx.Config().EmbeddedInMake() {
|
||||
return
|
||||
|
@ -152,11 +162,15 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) {
|
|||
outFile := absolutePath(PathForOutput(ctx,
|
||||
"make_vars"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
|
||||
|
||||
lateOutFile := absolutePath(PathForOutput(ctx,
|
||||
"late"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
|
||||
|
||||
if ctx.Failed() {
|
||||
return
|
||||
}
|
||||
|
||||
vars := []makeVarsVariable{}
|
||||
var phonies []phony
|
||||
for _, provider := range makeVarsProviders {
|
||||
mctx := &makeVarsContext{
|
||||
SingletonContext: ctx,
|
||||
|
@ -166,6 +180,7 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) {
|
|||
provider.call(mctx)
|
||||
|
||||
vars = append(vars, mctx.vars...)
|
||||
phonies = append(phonies, mctx.phonies...)
|
||||
}
|
||||
|
||||
if ctx.Failed() {
|
||||
|
@ -174,17 +189,16 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) {
|
|||
|
||||
outBytes := s.writeVars(vars)
|
||||
|
||||
if _, err := os.Stat(absolutePath(outFile)); err == nil {
|
||||
if data, err := ioutil.ReadFile(absolutePath(outFile)); err == nil {
|
||||
if bytes.Equal(data, outBytes) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(absolutePath(outFile), outBytes, 0666); err != nil {
|
||||
if err := pathtools.WriteFileIfChanged(outFile, outBytes, 0666); err != nil {
|
||||
ctx.Errorf(err.Error())
|
||||
}
|
||||
|
||||
lateOutBytes := s.writeLate(phonies)
|
||||
|
||||
if err := pathtools.WriteFileIfChanged(lateOutFile, lateOutBytes, 0666); err != nil {
|
||||
ctx.Errorf(err.Error())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s *makeVarsSingleton) writeVars(vars []makeVarsVariable) []byte {
|
||||
|
@ -263,6 +277,26 @@ my_check_failed :=
|
|||
|
||||
fmt.Fprintln(buf, "\nsoong-compare-var :=")
|
||||
|
||||
fmt.Fprintln(buf)
|
||||
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func (s *makeVarsSingleton) writeLate(phonies []phony) []byte {
|
||||
buf := &bytes.Buffer{}
|
||||
|
||||
fmt.Fprint(buf, `# Autogenerated file
|
||||
|
||||
# Values written by Soong read after parsing all Android.mk files.
|
||||
|
||||
|
||||
`)
|
||||
|
||||
for _, phony := range phonies {
|
||||
fmt.Fprintf(buf, ".PHONY: %s\n", phony.name)
|
||||
fmt.Fprintf(buf, "%s: %s\n", phony.name, strings.Join(phony.deps, "\\\n "))
|
||||
}
|
||||
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
|
@ -299,6 +333,10 @@ func (c *makeVarsContext) addVariable(name, ninjaStr string, strict, sort bool)
|
|||
c.addVariableRaw(name, value, strict, sort)
|
||||
}
|
||||
|
||||
func (c *makeVarsContext) addPhony(name string, deps []string) {
|
||||
c.phonies = append(c.phonies, phony{name, deps})
|
||||
}
|
||||
|
||||
func (c *makeVarsContext) Strict(name, ninjaStr string) {
|
||||
c.addVariable(name, ninjaStr, true, false)
|
||||
}
|
||||
|
@ -318,3 +356,7 @@ func (c *makeVarsContext) CheckSorted(name, ninjaStr string) {
|
|||
func (c *makeVarsContext) CheckRaw(name, value string) {
|
||||
c.addVariableRaw(name, value, false, false)
|
||||
}
|
||||
|
||||
func (c *makeVarsContext) Phony(name string, deps ...Path) {
|
||||
c.addPhony(name, Paths(deps).Strings())
|
||||
}
|
||||
|
|
|
@ -194,6 +194,10 @@ type ModuleContext interface {
|
|||
// Similar to blueprint.ModuleContext.Build, but takes Paths instead of []string,
|
||||
// and performs more verification.
|
||||
Build(pctx PackageContext, params BuildParams)
|
||||
// Phony creates a Make-style phony rule, a rule with no commands that can depend on other
|
||||
// phony rules or real files. Phony can be called on the same name multiple times to add
|
||||
// additional dependencies.
|
||||
Phony(phony string, deps ...Path)
|
||||
|
||||
PrimaryModule() Module
|
||||
FinalModule() Module
|
||||
|
@ -706,6 +710,7 @@ type ModuleBase struct {
|
|||
installFiles Paths
|
||||
checkbuildFiles Paths
|
||||
noticeFile OptionalPath
|
||||
phonies map[string]Paths
|
||||
|
||||
// Used by buildTargetSingleton to create checkbuild and per-directory build targets
|
||||
// Only set on the final variant of each module
|
||||
|
@ -1075,26 +1080,17 @@ func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) {
|
|||
}
|
||||
|
||||
if len(allInstalledFiles) > 0 {
|
||||
name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+"-install")
|
||||
ctx.Build(pctx, BuildParams{
|
||||
Rule: blueprint.Phony,
|
||||
Output: name,
|
||||
Implicits: allInstalledFiles,
|
||||
Default: !ctx.Config().EmbeddedInMake(),
|
||||
})
|
||||
deps = append(deps, name)
|
||||
m.installTarget = name
|
||||
name := namespacePrefix + ctx.ModuleName() + "-install"
|
||||
ctx.Phony(name, allInstalledFiles...)
|
||||
m.installTarget = PathForPhony(ctx, name)
|
||||
deps = append(deps, m.installTarget)
|
||||
}
|
||||
|
||||
if len(allCheckbuildFiles) > 0 {
|
||||
name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+"-checkbuild")
|
||||
ctx.Build(pctx, BuildParams{
|
||||
Rule: blueprint.Phony,
|
||||
Output: name,
|
||||
Implicits: allCheckbuildFiles,
|
||||
})
|
||||
deps = append(deps, name)
|
||||
m.checkbuildTarget = name
|
||||
name := namespacePrefix + ctx.ModuleName() + "-checkbuild"
|
||||
ctx.Phony(name, allCheckbuildFiles...)
|
||||
m.checkbuildTarget = PathForPhony(ctx, name)
|
||||
deps = append(deps, m.checkbuildTarget)
|
||||
}
|
||||
|
||||
if len(deps) > 0 {
|
||||
|
@ -1103,12 +1099,7 @@ func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) {
|
|||
suffix = "-soong"
|
||||
}
|
||||
|
||||
name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+suffix)
|
||||
ctx.Build(pctx, BuildParams{
|
||||
Rule: blueprint.Phony,
|
||||
Outputs: []WritablePath{name},
|
||||
Implicits: deps,
|
||||
})
|
||||
ctx.Phony(namespacePrefix+ctx.ModuleName()+suffix, deps...)
|
||||
|
||||
m.blueprintDir = ctx.ModuleDir()
|
||||
}
|
||||
|
@ -1282,6 +1273,9 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
|
|||
m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...)
|
||||
m.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc)
|
||||
m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments)
|
||||
for k, v := range ctx.phonies {
|
||||
m.phonies[k] = append(m.phonies[k], v...)
|
||||
}
|
||||
} else if ctx.Config().AllowMissingDependencies() {
|
||||
// If the module is not enabled it will not create any build rules, nothing will call
|
||||
// ctx.GetMissingDependencies(), and blueprint will consider the missing dependencies to be unhandled
|
||||
|
@ -1419,6 +1413,7 @@ type moduleContext struct {
|
|||
installFiles Paths
|
||||
checkbuildFiles Paths
|
||||
module Module
|
||||
phonies map[string]Paths
|
||||
|
||||
// For tests
|
||||
buildParams []BuildParams
|
||||
|
@ -1533,6 +1528,11 @@ func (m *moduleContext) Build(pctx PackageContext, params BuildParams) {
|
|||
|
||||
m.bp.Build(pctx.PackageContext, convertBuildParams(params))
|
||||
}
|
||||
|
||||
func (m *moduleContext) Phony(name string, deps ...Path) {
|
||||
addPhony(m.config, name, deps...)
|
||||
}
|
||||
|
||||
func (m *moduleContext) GetMissingDependencies() []string {
|
||||
var missingDeps []string
|
||||
missingDeps = append(missingDeps, m.Module().base().commonProperties.MissingDeps...)
|
||||
|
@ -2167,9 +2167,8 @@ type buildTargetSingleton struct{}
|
|||
func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) {
|
||||
var checkbuildDeps Paths
|
||||
|
||||
mmTarget := func(dir string) WritablePath {
|
||||
return PathForPhony(ctx,
|
||||
"MODULES-IN-"+strings.Replace(filepath.Clean(dir), "/", "-", -1))
|
||||
mmTarget := func(dir string) string {
|
||||
return "MODULES-IN-" + strings.Replace(filepath.Clean(dir), "/", "-", -1)
|
||||
}
|
||||
|
||||
modulesInDir := make(map[string]Paths)
|
||||
|
@ -2195,11 +2194,7 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) {
|
|||
}
|
||||
|
||||
// Create a top-level checkbuild target that depends on all modules
|
||||
ctx.Build(pctx, BuildParams{
|
||||
Rule: blueprint.Phony,
|
||||
Output: PathForPhony(ctx, "checkbuild"+suffix),
|
||||
Implicits: checkbuildDeps,
|
||||
})
|
||||
ctx.Phony("checkbuild"+suffix, checkbuildDeps...)
|
||||
|
||||
// Make will generate the MODULES-IN-* targets
|
||||
if ctx.Config().EmbeddedInMake() {
|
||||
|
@ -2223,7 +2218,7 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) {
|
|||
for _, dir := range dirs {
|
||||
p := parentDir(dir)
|
||||
if p != "." && p != "/" {
|
||||
modulesInDir[p] = append(modulesInDir[p], mmTarget(dir))
|
||||
modulesInDir[p] = append(modulesInDir[p], PathForPhony(ctx, mmTarget(dir)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2231,14 +2226,7 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) {
|
|||
// depends on the MODULES-IN-* targets of all of its subdirectories that contain Android.bp
|
||||
// files.
|
||||
for _, dir := range dirs {
|
||||
ctx.Build(pctx, BuildParams{
|
||||
Rule: blueprint.Phony,
|
||||
Output: mmTarget(dir),
|
||||
Implicits: modulesInDir[dir],
|
||||
// HACK: checkbuild should be an optional build, but force it
|
||||
// enabled for now in standalone builds
|
||||
Default: !ctx.Config().EmbeddedInMake(),
|
||||
})
|
||||
ctx.Phony(mmTarget(dir), modulesInDir[dir]...)
|
||||
}
|
||||
|
||||
// Create (host|host-cross|target)-<OS> phony rules to build a reduced checkbuild.
|
||||
|
@ -2265,23 +2253,15 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) {
|
|||
continue
|
||||
}
|
||||
|
||||
name := PathForPhony(ctx, className+"-"+os.Name)
|
||||
osClass[className] = append(osClass[className], name)
|
||||
name := className + "-" + os.Name
|
||||
osClass[className] = append(osClass[className], PathForPhony(ctx, name))
|
||||
|
||||
ctx.Build(pctx, BuildParams{
|
||||
Rule: blueprint.Phony,
|
||||
Output: name,
|
||||
Implicits: deps,
|
||||
})
|
||||
ctx.Phony(name, deps...)
|
||||
}
|
||||
|
||||
// Wrap those into host|host-cross|target phony rules
|
||||
for _, class := range SortedStringKeys(osClass) {
|
||||
ctx.Build(pctx, BuildParams{
|
||||
Rule: blueprint.Phony,
|
||||
Output: PathForPhony(ctx, class),
|
||||
Implicits: osClass[class],
|
||||
})
|
||||
ctx.Phony(class, osClass[class]...)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
// Copyright 2020 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package android
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
)
|
||||
|
||||
var phonyMapOnceKey = NewOnceKey("phony")
|
||||
|
||||
type phonyMap map[string]Paths
|
||||
|
||||
var phonyMapLock sync.Mutex
|
||||
|
||||
func getPhonyMap(config Config) phonyMap {
|
||||
return config.Once(phonyMapOnceKey, func() interface{} {
|
||||
return make(phonyMap)
|
||||
}).(phonyMap)
|
||||
}
|
||||
|
||||
func addPhony(config Config, name string, deps ...Path) {
|
||||
phonyMap := getPhonyMap(config)
|
||||
phonyMapLock.Lock()
|
||||
defer phonyMapLock.Unlock()
|
||||
phonyMap[name] = append(phonyMap[name], deps...)
|
||||
}
|
||||
|
||||
type phonySingleton struct {
|
||||
phonyMap phonyMap
|
||||
phonyList []string
|
||||
}
|
||||
|
||||
var _ SingletonMakeVarsProvider = (*phonySingleton)(nil)
|
||||
|
||||
func (p *phonySingleton) GenerateBuildActions(ctx SingletonContext) {
|
||||
p.phonyMap = getPhonyMap(ctx.Config())
|
||||
p.phonyList = SortedStringKeys(p.phonyMap)
|
||||
for _, phony := range p.phonyList {
|
||||
p.phonyMap[phony] = SortedUniquePaths(p.phonyMap[phony])
|
||||
}
|
||||
|
||||
if !ctx.Config().EmbeddedInMake() {
|
||||
for _, phony := range p.phonyList {
|
||||
ctx.Build(pctx, BuildParams{
|
||||
Rule: blueprint.Phony,
|
||||
Outputs: []WritablePath{PathForPhony(ctx, phony)},
|
||||
Implicits: p.phonyMap[phony],
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p phonySingleton) MakeVars(ctx MakeVarsContext) {
|
||||
for _, phony := range p.phonyList {
|
||||
ctx.Phony(phony, p.phonyMap[phony]...)
|
||||
}
|
||||
}
|
||||
|
||||
func phonySingletonFactory() Singleton {
|
||||
return &phonySingleton{}
|
||||
}
|
|
@ -104,6 +104,9 @@ func (ctx *Context) Register() {
|
|||
|
||||
registerMutators(ctx.Context, preArch, preDeps, postDeps, finalDeps)
|
||||
|
||||
// Register phony just before makevars so it can write out its phony rules as Make rules
|
||||
ctx.RegisterSingletonType("phony", SingletonFactoryAdaptor(phonySingletonFactory))
|
||||
|
||||
// Register makevars after other singletons so they can export values through makevars
|
||||
ctx.RegisterSingletonType("makevars", SingletonFactoryAdaptor(makeVarsSingletonFunc))
|
||||
|
||||
|
|
|
@ -36,6 +36,12 @@ type SingletonContext interface {
|
|||
Variable(pctx PackageContext, name, value string)
|
||||
Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule
|
||||
Build(pctx PackageContext, params BuildParams)
|
||||
|
||||
// Phony creates a Make-style phony rule, a rule with no commands that can depend on other
|
||||
// phony rules or real files. Phony can be called on the same name multiple times to add
|
||||
// additional dependencies.
|
||||
Phony(name string, deps ...Path)
|
||||
|
||||
RequireNinjaVersion(major, minor, micro int)
|
||||
|
||||
// SetNinjaBuildDir sets the value of the top-level "builddir" Ninja variable
|
||||
|
@ -156,6 +162,10 @@ func (s *singletonContextAdaptor) Build(pctx PackageContext, params BuildParams)
|
|||
|
||||
}
|
||||
|
||||
func (s *singletonContextAdaptor) Phony(name string, deps ...Path) {
|
||||
addPhony(s.Config(), name, deps...)
|
||||
}
|
||||
|
||||
func (s *singletonContextAdaptor) SetNinjaBuildDir(pctx PackageContext, value string) {
|
||||
s.SingletonContext.SetNinjaBuildDir(pctx.PackageContext, value)
|
||||
}
|
||||
|
|
|
@ -69,9 +69,5 @@ func (c *docsSingleton) GenerateBuildActions(ctx SingletonContext) {
|
|||
})
|
||||
|
||||
// Add a phony target for building the documentation
|
||||
ctx.Build(pctx, BuildParams{
|
||||
Rule: blueprint.Phony,
|
||||
Output: PathForPhony(ctx, "soong_docs"),
|
||||
Input: docsFile,
|
||||
})
|
||||
ctx.Phony("soong_docs", docsFile)
|
||||
}
|
||||
|
|
7
cc/cc.go
7
cc/cc.go
|
@ -3188,12 +3188,7 @@ func (ks *kytheExtractAllSingleton) GenerateBuildActions(ctx android.SingletonCo
|
|||
})
|
||||
// TODO(asmundak): Perhaps emit a rule to output a warning if there were no xrefTargets
|
||||
if len(xrefTargets) > 0 {
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: blueprint.Phony,
|
||||
Output: android.PathForPhony(ctx, "xref_cxx"),
|
||||
Inputs: xrefTargets,
|
||||
//Default: true,
|
||||
})
|
||||
ctx.Phony("xref_cxx", xrefTargets...)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2852,11 +2852,7 @@ func (ks *kytheExtractJavaSingleton) GenerateBuildActions(ctx android.SingletonC
|
|||
})
|
||||
// TODO(asmundak): perhaps emit a rule to output a warning if there were no xrefTargets
|
||||
if len(xrefTargets) > 0 {
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: blueprint.Phony,
|
||||
Output: android.PathForPhony(ctx, "xref_java"),
|
||||
Inputs: xrefTargets,
|
||||
})
|
||||
ctx.Phony("xref_java", xrefTargets...)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue