Define Soong phony rules in Make am: c3d87d3112

Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1325397

Change-Id: Ia6a1f96c75c660525127c25472327dd78ba58124
This commit is contained in:
Colin Cross 2020-06-11 18:42:02 +00:00 committed by Automerger Merge Worker
commit 970fd93b92
9 changed files with 180 additions and 82 deletions

View File

@ -36,6 +36,7 @@ bootstrap_go_package {
"package_ctx.go",
"path_properties.go",
"paths.go",
"phony.go",
"prebuilt.go",
"proto.go",
"register.go",

View File

@ -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)
@ -130,9 +134,10 @@ var makeVarsProviders []makeVarsProvider
type makeVarsContext struct {
SingletonContext
config Config
pctx PackageContext
vars []makeVarsVariable
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())
}

View File

@ -207,6 +207,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
@ -722,6 +726,7 @@ type ModuleBase struct {
installFiles InstallPaths
checkbuildFiles Paths
noticeFiles Paths
phonies map[string]Paths
// Used by buildTargetSingleton to create checkbuild and per-directory build targets
// Only set on the final variant of each module
@ -1093,26 +1098,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.Paths(),
Default: !ctx.Config().EmbeddedInMake(),
})
deps = append(deps, name)
m.installTarget = name
name := namespacePrefix + ctx.ModuleName() + "-install"
ctx.Phony(name, allInstalledFiles.Paths()...)
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 {
@ -1121,12 +1117,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()
}
@ -1313,6 +1304,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
@ -1460,6 +1454,7 @@ type moduleContext struct {
installFiles InstallPaths
checkbuildFiles Paths
module Module
phonies map[string]Paths
// For tests
buildParams []BuildParams
@ -1574,6 +1569,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...)
@ -2233,9 +2233,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)
@ -2261,11 +2260,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() {
@ -2289,7 +2284,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)))
}
}
@ -2297,14 +2292,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.
@ -2331,23 +2319,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]...)
}
}

75
android/phony.go Normal file
View File

@ -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{}
}

View File

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

View File

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

View File

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

View File

@ -3223,12 +3223,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...)
}
}

View File

@ -2874,11 +2874,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...)
}
}