Pass pctx and ctx to NewRuleBuilder
Enable the RuleBuilder and RuleBuilderCommand methods to access
the BuilderContext by passing it to NewRuleBuilder instead of
RuleBuilder.Build.
Test: genrule_test.go
Test: rule_builder_test.go
Test: m checkbuild
Change-Id: I63e6597e19167393876dc2259d6f521363b7dabc
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 3efe9f8..e2d8187 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -37,6 +37,9 @@
// RuleBuilder provides an alternative to ModuleContext.Rule and ModuleContext.Build to add a command line to the build
// graph.
type RuleBuilder struct {
+ pctx PackageContext
+ ctx BuilderContext
+
commands []*RuleBuilderCommand
installs RuleBuilderInstalls
temporariesSet map[WritablePath]bool
@@ -44,14 +47,16 @@
sbox bool
highmem bool
remoteable RemoteRuleSupports
- sboxOutDir WritablePath
+ outDir WritablePath
sboxManifestPath WritablePath
missingDeps []string
}
// NewRuleBuilder returns a newly created RuleBuilder.
-func NewRuleBuilder() *RuleBuilder {
+func NewRuleBuilder(pctx PackageContext, ctx BuilderContext) *RuleBuilder {
return &RuleBuilder{
+ pctx: pctx,
+ ctx: ctx,
temporariesSet: make(map[WritablePath]bool),
}
}
@@ -130,7 +135,7 @@
panic("Sbox() is not compatible with Restat()")
}
r.sbox = true
- r.sboxOutDir = outputDir
+ r.outDir = outputDir
r.sboxManifestPath = manifestPath
return r
}
@@ -146,8 +151,7 @@
// race with any call to Build.
func (r *RuleBuilder) Command() *RuleBuilderCommand {
command := &RuleBuilderCommand{
- sbox: r.sbox,
- outDir: r.sboxOutDir,
+ rule: r,
}
r.commands = append(r.commands, command)
return command
@@ -395,19 +399,19 @@
var _ BuilderContext = ModuleContext(nil)
var _ BuilderContext = SingletonContext(nil)
-func (r *RuleBuilder) depFileMergerCmd(ctx PathContext, depFiles WritablePaths) *RuleBuilderCommand {
+func (r *RuleBuilder) depFileMergerCmd(depFiles WritablePaths) *RuleBuilderCommand {
return r.Command().
- BuiltTool(ctx, "dep_fixer").
+ BuiltTool("dep_fixer").
Inputs(depFiles.Paths())
}
// Build adds the built command line to the build graph, with dependencies on Inputs and Tools, and output files for
// Outputs.
-func (r *RuleBuilder) Build(pctx PackageContext, ctx BuilderContext, name string, desc string) {
+func (r *RuleBuilder) Build(name string, desc string) {
name = ninjaNameEscape(name)
if len(r.missingDeps) > 0 {
- ctx.Build(pctx, BuildParams{
+ r.ctx.Build(pctx, BuildParams{
Rule: ErrorRule,
Outputs: r.Outputs(),
OrderOnly: r.OrderOnlys(),
@@ -426,13 +430,13 @@
depFormat = blueprint.DepsGCC
if len(depFiles) > 1 {
// Add a command locally that merges all depfiles together into the first depfile.
- r.depFileMergerCmd(ctx, depFiles)
+ r.depFileMergerCmd(depFiles)
if r.sbox {
// Check for Rel() errors, as all depfiles should be in the output dir. Errors
// will be reported to the ctx.
for _, path := range depFiles[1:] {
- Rel(ctx, r.sboxOutDir.String(), path.String())
+ Rel(r.ctx, r.outDir.String(), path.String())
}
}
}
@@ -468,7 +472,7 @@
// to the output directory.
sboxOutputs := make([]string, len(outputs))
for i, output := range outputs {
- rel := Rel(ctx, r.sboxOutDir.String(), output.String())
+ rel := Rel(r.ctx, r.outDir.String(), output.String())
sboxOutputs[i] = filepath.Join(sboxOutDir, rel)
command.CopyAfter = append(command.CopyAfter, &sbox_proto.Copy{
From: proto.String(filepath.Join(sboxOutSubDir, rel)),
@@ -483,23 +487,27 @@
// Verify that the manifest textproto is not inside the sbox output directory, otherwise
// it will get deleted when the sbox rule clears its output directory.
- _, manifestInOutDir := MaybeRel(ctx, r.sboxOutDir.String(), r.sboxManifestPath.String())
+ _, manifestInOutDir := MaybeRel(r.ctx, r.outDir.String(), r.sboxManifestPath.String())
if manifestInOutDir {
- ReportPathErrorf(ctx, "sbox rule %q manifestPath %q must not be in outputDir %q",
- name, r.sboxManifestPath.String(), r.sboxOutDir.String())
+ ReportPathErrorf(r.ctx, "sbox rule %q manifestPath %q must not be in outputDir %q",
+ name, r.sboxManifestPath.String(), r.outDir.String())
}
// Create a rule to write the manifest as a the textproto.
- WriteFileRule(ctx, r.sboxManifestPath, proto.MarshalTextString(&manifest))
+ WriteFileRule(r.ctx, r.sboxManifestPath, proto.MarshalTextString(&manifest))
// Generate a new string to use as the command line of the sbox rule. This uses
// a RuleBuilderCommand as a convenience method of building the command line, then
// converts it to a string to replace commandString.
- sboxCmd := &RuleBuilderCommand{}
- sboxCmd.Text("rm -rf").Output(r.sboxOutDir)
+ sboxCmd := &RuleBuilderCommand{
+ rule: &RuleBuilder{
+ ctx: r.ctx,
+ },
+ }
+ sboxCmd.Text("rm -rf").Output(r.outDir)
sboxCmd.Text("&&")
- sboxCmd.BuiltTool(ctx, "sbox").
- Flag("--sandbox-path").Text(shared.TempDirForOutDir(PathForOutput(ctx).String())).
+ sboxCmd.BuiltTool("sbox").
+ Flag("--sandbox-path").Text(shared.TempDirForOutDir(PathForOutput(r.ctx).String())).
Flag("--manifest").Input(r.sboxManifestPath)
// Replace the command string, and add the sbox tool and manifest textproto to the
@@ -528,19 +536,19 @@
}
var pool blueprint.Pool
- if ctx.Config().UseGoma() && r.remoteable.Goma {
+ if r.ctx.Config().UseGoma() && r.remoteable.Goma {
// When USE_GOMA=true is set and the rule is supported by goma, allow jobs to run outside the local pool.
- } else if ctx.Config().UseRBE() && r.remoteable.RBE {
+ } else if r.ctx.Config().UseRBE() && r.remoteable.RBE {
// When USE_RBE=true is set and the rule is supported by RBE, use the remotePool.
pool = remotePool
} else if r.highmem {
pool = highmemPool
- } else if ctx.Config().UseRemoteBuild() {
+ } else if r.ctx.Config().UseRemoteBuild() {
pool = localPool
}
- ctx.Build(pctx, BuildParams{
- Rule: ctx.Rule(pctx, name, blueprint.RuleParams{
+ r.ctx.Build(r.pctx, BuildParams{
+ Rule: r.ctx.Rule(pctx, name, blueprint.RuleParams{
Command: commandString,
CommandDeps: tools.Strings(),
Restat: r.restat,
@@ -564,6 +572,8 @@
// RuleBuilderCommand, so they can be used chained or unchained. All methods that add text implicitly add a single
// space as a separator from the previous method.
type RuleBuilderCommand struct {
+ rule *RuleBuilder
+
buf strings.Builder
inputs Paths
implicits Paths
@@ -576,16 +586,11 @@
// spans [start,end) of the command that should not be ninja escaped
unescapedSpans [][2]int
-
- sbox bool
- // outDir is the directory that will contain the output files of the rules. sbox will copy
- // the output files from the sandbox directory to this directory when it finishes.
- outDir WritablePath
}
func (c *RuleBuilderCommand) addInput(path Path) string {
- if c.sbox {
- if rel, isRel, _ := maybeRelErr(c.outDir.String(), path.String()); isRel {
+ if c.rule.sbox {
+ if rel, isRel, _ := maybeRelErr(c.rule.outDir.String(), path.String()); isRel {
return filepath.Join(sboxOutDir, rel)
}
}
@@ -594,8 +599,8 @@
}
func (c *RuleBuilderCommand) addImplicit(path Path) string {
- if c.sbox {
- if rel, isRel, _ := maybeRelErr(c.outDir.String(), path.String()); isRel {
+ if c.rule.sbox {
+ if rel, isRel, _ := maybeRelErr(c.rule.outDir.String(), path.String()); isRel {
return filepath.Join(sboxOutDir, rel)
}
}
@@ -607,22 +612,19 @@
c.orderOnlys = append(c.orderOnlys, path)
}
-func (c *RuleBuilderCommand) outputStr(path WritablePath) string {
- if c.sbox {
- return SboxPathForOutput(path, c.outDir)
+// PathForOutput takes an output path and returns the appropriate path to use on the command
+// line. If sbox was enabled via a call to RuleBuilder.Sbox(), it returns a path with the
+// placeholder prefix used for outputs in sbox. If sbox is not enabled it returns the
+// original path.
+func (c *RuleBuilderCommand) PathForOutput(path WritablePath) string {
+ if c.rule.sbox {
+ // Errors will be handled in RuleBuilder.Build where we have a context to report them
+ rel, _, _ := maybeRelErr(c.rule.outDir.String(), path.String())
+ return filepath.Join(sboxOutDir, rel)
}
return path.String()
}
-// SboxPathForOutput takes an output path and the out directory passed to RuleBuilder.Sbox(),
-// and returns the corresponding path for the output in the sbox sandbox. This can be used
-// on the RuleBuilder command line to reference the output.
-func SboxPathForOutput(path WritablePath, outDir WritablePath) string {
- // Errors will be handled in RuleBuilder.Build where we have a context to report them
- rel, _, _ := maybeRelErr(outDir.String(), path.String())
- return filepath.Join(sboxOutDir, rel)
-}
-
// Text adds the specified raw text to the command line. The text should not contain input or output paths or the
// rule will not have them listed in its dependencies or outputs.
func (c *RuleBuilderCommand) Text(text string) *RuleBuilderCommand {
@@ -699,8 +701,8 @@
//
// It is equivalent to:
// cmd.Tool(ctx.Config().HostToolPath(ctx, tool))
-func (c *RuleBuilderCommand) BuiltTool(ctx PathContext, tool string) *RuleBuilderCommand {
- return c.Tool(ctx.Config().HostToolPath(ctx, tool))
+func (c *RuleBuilderCommand) BuiltTool(tool string) *RuleBuilderCommand {
+ return c.Tool(c.rule.ctx.Config().HostToolPath(c.rule.ctx, tool))
}
// PrebuiltBuildTool adds the specified tool path from prebuils/build-tools. The path will be also added to the
@@ -768,7 +770,7 @@
// RuleBuilder.Outputs.
func (c *RuleBuilderCommand) Output(path WritablePath) *RuleBuilderCommand {
c.outputs = append(c.outputs, path)
- return c.Text(c.outputStr(path))
+ return c.Text(c.PathForOutput(path))
}
// Outputs adds the specified output paths to the command line, separated by spaces. The paths will also be added to
@@ -783,7 +785,7 @@
// OutputDir adds the output directory to the command line. This is only available when used with RuleBuilder.Sbox,
// and will be the temporary output directory managed by sbox, not the final one.
func (c *RuleBuilderCommand) OutputDir() *RuleBuilderCommand {
- if !c.sbox {
+ if !c.rule.sbox {
panic("OutputDir only valid with Sbox")
}
return c.Text(sboxOutDir)
@@ -794,7 +796,7 @@
// commands in a single RuleBuilder then RuleBuilder.Build will add an extra command to merge the depfiles together.
func (c *RuleBuilderCommand) DepFile(path WritablePath) *RuleBuilderCommand {
c.depFiles = append(c.depFiles, path)
- return c.Text(c.outputStr(path))
+ return c.Text(c.PathForOutput(path))
}
// ImplicitOutput adds the specified output path to the dependencies returned by RuleBuilder.Outputs without modifying
@@ -885,14 +887,14 @@
// will also be added to the outputs returned by RuleBuilder.Outputs.
func (c *RuleBuilderCommand) FlagWithOutput(flag string, path WritablePath) *RuleBuilderCommand {
c.outputs = append(c.outputs, path)
- return c.Text(flag + c.outputStr(path))
+ return c.Text(flag + c.PathForOutput(path))
}
// FlagWithDepFile adds the specified flag and depfile path to the command line, with no separator between them. The path
// will also be added to the outputs returned by RuleBuilder.Outputs.
func (c *RuleBuilderCommand) FlagWithDepFile(flag string, path WritablePath) *RuleBuilderCommand {
c.depFiles = append(c.depFiles, path)
- return c.Text(flag + c.outputStr(path))
+ return c.Text(flag + c.PathForOutput(path))
}
// FlagWithRspFileInputList adds the specified flag and path to an rspfile to the command line, with no separator
@@ -987,3 +989,21 @@
h.Write([]byte(srcFileList))
return fmt.Sprintf("%x", h.Sum(nil))
}
+
+// BuilderContextForTesting returns a BuilderContext for the given config that can be used for tests
+// that need to call methods that take a BuilderContext.
+func BuilderContextForTesting(config Config) BuilderContext {
+ pathCtx := PathContextForTesting(config)
+ return builderContextForTests{
+ PathContext: pathCtx,
+ }
+}
+
+type builderContextForTests struct {
+ PathContext
+}
+
+func (builderContextForTests) Rule(PackageContext, string, blueprint.RuleParams, ...string) blueprint.Rule {
+ return nil
+}
+func (builderContextForTests) Build(PackageContext, BuildParams) {}