aboutsummaryrefslogtreecommitdiffstats
path: root/genrule
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2016-11-04 15:32:58 -0700
committerColin Cross <ccross@android.com>2016-11-07 10:53:49 -0800
commit6f080dff818c7a4e41d61520660c4a1298e48cb8 (patch)
tree5f25e82601d559e5e94e805e4948981b86b8d152 /genrule
parent6bde0948d2b0d1826098a0046da5a8a2ce017fb6 (diff)
downloadbuild_soong-6f080dff818c7a4e41d61520660c4a1298e48cb8.tar.gz
build_soong-6f080dff818c7a4e41d61520660c4a1298e48cb8.tar.bz2
build_soong-6f080dff818c7a4e41d61520660c4a1298e48cb8.zip
Support genrules with multiple tools
To allow genrules with more than one tool, rename the tool property to tools and make it an array, replace $tool with $(location <label>), and use $() for other variables for consistency. Also remove the host bin directory from the genrule path, and the $srcDir variable, using either of them would have caused dependency issues. Bug: 31948427 Test: compare build.ninja Change-Id: Icf6d3bce2bea00fec1363fd65c0bdf96d09281bf (cherry picked from commit de6bd86d240b98b7ea7ff6a0454a13edc639a163)
Diffstat (limited to 'genrule')
-rw-r--r--genrule/genrule.go128
1 files changed, 74 insertions, 54 deletions
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 5ee8b0bc..498858d2 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -15,7 +15,8 @@
package genrule
import (
- "os"
+ "fmt"
+ "strings"
"github.com/google/blueprint"
@@ -31,11 +32,6 @@ var (
pctx = android.NewPackageContext("android/soong/genrule")
)
-func init() {
- pctx.SourcePathVariable("srcDir", "")
- pctx.HostBinToolVariable("hostBin", "")
-}
-
type SourceFileGenerator interface {
GeneratedSourceFiles() android.Paths
GeneratedHeaderDir() android.Path
@@ -47,20 +43,24 @@ type HostToolProvider interface {
type generatorProperties struct {
// command to run on one or more input files. Available variables for substitution:
- // $tool: the path to the `tool` or `tool_file`
- // $in: one or more input files
- // $out: a single output file
- // $srcDir: the root directory of the source tree
- // $genDir: the sandbox directory for this tool; contains $out
- // The host bin directory will be in the path
+ // $(location): the path to the first entry in tools or tool_files
+ // $(location <label>): the path to the tool or tool_file with name <label>
+ // $(in): one or more input files
+ // $(out): a single output file
+ // $(genDir): the sandbox directory for this tool; contains $(out)
+ // $$: a literal $
+ //
+ // DO NOT directly reference paths to files in the source tree, or the
+ // command will be missing proper dependencies to re-run if the files
+ // change.
Cmd string
- // name of the module (if any) that produces the host executable. Leave empty for
+ // name of the modules (if any) that produces the host executable. Leave empty for
// prebuilts or scripts that do not need a module to build them.
- Tool string
+ Tools []string
// Local file that is used as the tool
- Tool_file string
+ Tool_files []string
}
type generator struct {
@@ -95,58 +95,36 @@ func (g *generator) GeneratedHeaderDir() android.Path {
func (g *generator) DepsMutator(ctx android.BottomUpMutatorContext) {
if g, ok := ctx.Module().(*generator); ok {
- if g.properties.Tool != "" {
+ if len(g.properties.Tools) > 0 {
ctx.AddFarVariationDependencies([]blueprint.Variation{
{"arch", ctx.AConfig().BuildOsVariant},
- }, nil, g.properties.Tool)
+ }, nil, g.properties.Tools...)
}
}
}
func (g *generator) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- if g.properties.Tool != "" && g.properties.Tool_file != "" {
- ctx.ModuleErrorf("`tool` and `tool_file` may not be specified at the same time")
+ if len(g.properties.Tools) == 0 && len(g.properties.Tool_files) == 0 {
+ ctx.ModuleErrorf("at least one `tools` or `tool_files` is required")
return
}
g.genPath = android.PathForModuleGen(ctx, "")
- cmd := os.Expand(g.properties.Cmd, func(name string) string {
- switch name {
- case "$":
- return "$$"
- case "tool":
- return "${tool}"
- case "in":
- return "${in}"
- case "out":
- return "${out}"
- case "srcDir":
- return "${srcDir}"
- case "genDir":
- return g.genPath.String()
- default:
- ctx.PropertyErrorf("cmd", "unknown variable '%s'", name)
- }
- return ""
- })
+ tools := map[string]android.Path{}
- g.rule = ctx.Rule(pctx, "generator", blueprint.RuleParams{
- Command: "PATH=$$PATH:$hostBin " + cmd,
- }, "tool")
-
- var tool string
- if g.properties.Tool_file != "" {
- toolpath := android.PathForModuleSrc(ctx, g.properties.Tool_file)
- g.deps = append(g.deps, toolpath)
- tool = toolpath.String()
- } else if g.properties.Tool != "" {
+ if len(g.properties.Tools) > 0 {
ctx.VisitDirectDeps(func(module blueprint.Module) {
if t, ok := module.(HostToolProvider); ok {
p := t.HostToolPath()
if p.Valid() {
g.deps = append(g.deps, p.Path())
- tool = p.String()
+ tool := ctx.OtherModuleName(module)
+ if _, exists := tools[tool]; !exists {
+ tools[tool] = p.Path()
+ } else {
+ ctx.ModuleErrorf("multiple tools for %q, %q and %q", tool, tools[tool], p.Path().String())
+ }
} else {
ctx.ModuleErrorf("host tool %q missing output file", ctx.OtherModuleName(module))
}
@@ -156,20 +134,62 @@ func (g *generator) GenerateAndroidBuildActions(ctx android.ModuleContext) {
})
}
+ for _, tool := range g.properties.Tool_files {
+ toolPath := android.PathForModuleSrc(ctx, tool)
+ g.deps = append(g.deps, toolPath)
+ if _, exists := tools[tool]; !exists {
+ tools[tool] = toolPath
+ } else {
+ ctx.ModuleErrorf("multiple tools for %q, %q and %q", tool, tools[tool], toolPath.String())
+ }
+ }
+
+ cmd, err := android.Expand(g.properties.Cmd, func(name string) (string, error) {
+ switch name {
+ case "location":
+ if len(g.properties.Tools) > 0 {
+ return tools[g.properties.Tools[0]].String(), nil
+ } else {
+ return tools[g.properties.Tool_files[0]].String(), nil
+ }
+ case "in":
+ return "${in}", nil
+ case "out":
+ return "${out}", nil
+ case "genDir":
+ return g.genPath.String(), nil
+ default:
+ if strings.HasPrefix(name, "location ") {
+ label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
+ if tool, ok := tools[label]; ok {
+ return tool.String(), nil
+ } else {
+ return "", fmt.Errorf("unknown location label %q", label)
+ }
+ }
+ return "", fmt.Errorf("unknown variable '$(%s)'", name)
+ }
+ })
+
+ if err != nil {
+ ctx.PropertyErrorf("cmd", "%s", err.Error())
+ }
+
+ g.rule = ctx.Rule(pctx, "generator", blueprint.RuleParams{
+ Command: cmd,
+ })
+
for _, task := range g.tasks(ctx) {
- g.generateSourceFile(ctx, task, tool)
+ g.generateSourceFile(ctx, task)
}
}
-func (g *generator) generateSourceFile(ctx android.ModuleContext, task generateTask, tool string) {
+func (g *generator) generateSourceFile(ctx android.ModuleContext, task generateTask) {
ctx.ModuleBuild(pctx, android.ModuleBuildParams{
Rule: g.rule,
Outputs: task.out,
Inputs: task.in,
Implicits: g.deps,
- Args: map[string]string{
- "tool": tool,
- },
})
for _, outputFile := range task.out {