diff options
author | Colin Cross <ccross@android.com> | 2016-11-04 15:32:58 -0700 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2016-11-07 10:53:49 -0800 |
commit | 6f080dff818c7a4e41d61520660c4a1298e48cb8 (patch) | |
tree | 5f25e82601d559e5e94e805e4948981b86b8d152 /genrule/genrule.go | |
parent | 6bde0948d2b0d1826098a0046da5a8a2ce017fb6 (diff) | |
download | build_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/genrule.go')
-rw-r--r-- | genrule/genrule.go | 128 |
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 { |