Revert^4 "allow Ninja variables in RuleBuilder API"

789a7e0883

Change-Id: Iee1156adf0ad6e6d2ae7e22d90a447d4b564e59f
This commit is contained in:
Sam Delmerico 2023-09-25 12:13:17 +00:00
parent 63ca14e9b7
commit 285b66a117
3 changed files with 115 additions and 15 deletions

View file

@ -474,13 +474,23 @@ func (r *RuleBuilder) depFileMergerCmd(depFiles WritablePaths) *RuleBuilderComma
Inputs(depFiles.Paths()) Inputs(depFiles.Paths())
} }
// BuildWithNinjaVars adds the built command line to the build graph, with dependencies on Inputs and Tools, and output files for
// Outputs. This function will not escape Ninja variables, so it may be used to write sandbox manifests using Ninja variables.
func (r *RuleBuilder) BuildWithUnescapedNinjaVars(name string, desc string) {
r.build(name, desc, false)
}
// Build adds the built command line to the build graph, with dependencies on Inputs and Tools, and output files for // Build adds the built command line to the build graph, with dependencies on Inputs and Tools, and output files for
// Outputs. // Outputs.
func (r *RuleBuilder) Build(name string, desc string) { func (r *RuleBuilder) Build(name string, desc string) {
r.build(name, desc, true)
}
func (r *RuleBuilder) build(name string, desc string, ninjaEscapeCommandString bool) {
name = ninjaNameEscape(name) name = ninjaNameEscape(name)
if len(r.missingDeps) > 0 { if len(r.missingDeps) > 0 {
r.ctx.Build(pctx, BuildParams{ r.ctx.Build(r.pctx, BuildParams{
Rule: ErrorRule, Rule: ErrorRule,
Outputs: r.Outputs(), Outputs: r.Outputs(),
Description: desc, Description: desc,
@ -619,12 +629,35 @@ func (r *RuleBuilder) Build(name string, desc string) {
name, r.sboxManifestPath.String(), r.outDir.String()) name, r.sboxManifestPath.String(), r.outDir.String())
} }
// Create a rule to write the manifest as a the textproto. // Create a rule to write the manifest as textproto.
pbText, err := prototext.Marshal(&manifest) pbText, err := prototext.Marshal(&manifest)
if err != nil { if err != nil {
ReportPathErrorf(r.ctx, "sbox manifest failed to marshal: %q", err) ReportPathErrorf(r.ctx, "sbox manifest failed to marshal: %q", err)
} }
if ninjaEscapeCommandString {
WriteFileRule(r.ctx, r.sboxManifestPath, string(pbText)) WriteFileRule(r.ctx, r.sboxManifestPath, string(pbText))
} else {
// We need to have a rule to write files that is
// defined on the RuleBuilder's pctx in order to
// write Ninja variables in the string.
// The WriteFileRule function above rule can only write
// raw strings because it is defined on the android
// package's pctx, and it can't access variables defined
// in another context.
r.ctx.Build(r.pctx, BuildParams{
Rule: r.ctx.Rule(r.pctx, "unescapedWriteFile", blueprint.RuleParams{
Command: `rm -rf ${out} && cat ${out}.rsp > ${out}`,
Rspfile: "${out}.rsp",
RspfileContent: "${content}",
Description: "write file",
}, "content"),
Output: r.sboxManifestPath,
Description: "write sbox manifest " + r.sboxManifestPath.Base(),
Args: map[string]string{
"content": string(pbText),
},
})
}
// Generate a new string to use as the command line of the sbox rule. This uses // 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 // a RuleBuilderCommand as a convenience method of building the command line, then
@ -724,7 +757,7 @@ func (r *RuleBuilder) Build(name string, desc string) {
} }
r.ctx.Build(r.pctx, BuildParams{ r.ctx.Build(r.pctx, BuildParams{
Rule: r.ctx.Rule(pctx, name, blueprint.RuleParams{ Rule: r.ctx.Rule(r.pctx, name, blueprint.RuleParams{
Command: proptools.NinjaEscape(commandString), Command: proptools.NinjaEscape(commandString),
CommandDeps: proptools.NinjaEscapeList(tools.Strings()), CommandDeps: proptools.NinjaEscapeList(tools.Strings()),
Restat: r.restat, Restat: r.restat,

View file

@ -28,6 +28,17 @@ import (
"android/soong/shared" "android/soong/shared"
) )
var (
pctx_ruleBuilderTest = NewPackageContext("android/soong/rule_builder")
pctx_ruleBuilderTestSubContext = NewPackageContext("android/soong/rule_builder/config")
)
func init() {
pctx_ruleBuilderTest.Import("android/soong/rule_builder/config")
pctx_ruleBuilderTest.StaticVariable("cmdFlags", "${config.ConfigFlags}")
pctx_ruleBuilderTestSubContext.StaticVariable("ConfigFlags", "--some-clang-flag")
}
func builderContext() BuilderContext { func builderContext() BuilderContext {
return BuilderContextForTesting(TestConfig("out", nil, "", map[string][]byte{ return BuilderContextForTesting(TestConfig("out", nil, "", map[string][]byte{
"ld": nil, "ld": nil,
@ -497,10 +508,12 @@ type testRuleBuilderModule struct {
ModuleBase ModuleBase
properties struct { properties struct {
Srcs []string Srcs []string
Flags []string
Restat bool Restat bool
Sbox bool Sbox bool
Sbox_inputs bool Sbox_inputs bool
Unescape_ninja_vars bool
} }
} }
@ -518,8 +531,9 @@ func (t *testRuleBuilderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
rspFileContents2 := PathsForSource(ctx, []string{"rsp_in2"}) rspFileContents2 := PathsForSource(ctx, []string{"rsp_in2"})
manifestPath := PathForModuleOut(ctx, "sbox.textproto") manifestPath := PathForModuleOut(ctx, "sbox.textproto")
testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, out, outDep, outDir, testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, t.properties.Flags,
manifestPath, t.properties.Restat, t.properties.Sbox, t.properties.Sbox_inputs, out, outDep, outDir,
manifestPath, t.properties.Restat, t.properties.Sbox, t.properties.Sbox_inputs, t.properties.Unescape_ninja_vars,
rspFile, rspFileContents, rspFile2, rspFileContents2) rspFile, rspFileContents, rspFile2, rspFileContents2)
} }
@ -543,17 +557,18 @@ func (t *testRuleBuilderSingleton) GenerateBuildActions(ctx SingletonContext) {
rspFileContents2 := PathsForSource(ctx, []string{"rsp_in2"}) rspFileContents2 := PathsForSource(ctx, []string{"rsp_in2"})
manifestPath := PathForOutput(ctx, "singleton/sbox.textproto") manifestPath := PathForOutput(ctx, "singleton/sbox.textproto")
testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, out, outDep, outDir, testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, nil, out, outDep, outDir,
manifestPath, true, false, false, manifestPath, true, false, false, false,
rspFile, rspFileContents, rspFile2, rspFileContents2) rspFile, rspFileContents, rspFile2, rspFileContents2)
} }
func testRuleBuilder_Build(ctx BuilderContext, in Paths, implicit, orderOnly, validation Path, func testRuleBuilder_Build(ctx BuilderContext, in Paths, implicit, orderOnly, validation Path,
flags []string,
out, outDep, outDir, manifestPath WritablePath, out, outDep, outDir, manifestPath WritablePath,
restat, sbox, sboxInputs bool, restat, sbox, sboxInputs, unescapeNinjaVars bool,
rspFile WritablePath, rspFileContents Paths, rspFile2 WritablePath, rspFileContents2 Paths) { rspFile WritablePath, rspFileContents Paths, rspFile2 WritablePath, rspFileContents2 Paths) {
rule := NewRuleBuilder(pctx, ctx) rule := NewRuleBuilder(pctx_ruleBuilderTest, ctx)
if sbox { if sbox {
rule.Sbox(outDir, manifestPath) rule.Sbox(outDir, manifestPath)
@ -564,6 +579,7 @@ func testRuleBuilder_Build(ctx BuilderContext, in Paths, implicit, orderOnly, va
rule.Command(). rule.Command().
Tool(PathForSource(ctx, "cp")). Tool(PathForSource(ctx, "cp")).
Flags(flags).
Inputs(in). Inputs(in).
Implicit(implicit). Implicit(implicit).
OrderOnly(orderOnly). OrderOnly(orderOnly).
@ -577,7 +593,11 @@ func testRuleBuilder_Build(ctx BuilderContext, in Paths, implicit, orderOnly, va
rule.Restat() rule.Restat()
} }
if unescapeNinjaVars {
rule.BuildWithUnescapedNinjaVars("rule", "desc")
} else {
rule.Build("rule", "desc") rule.Build("rule", "desc")
}
} }
var prepareForRuleBuilderTest = FixtureRegisterWithContext(func(ctx RegistrationContext) { var prepareForRuleBuilderTest = FixtureRegisterWithContext(func(ctx RegistrationContext) {
@ -792,3 +812,47 @@ func TestRuleBuilderHashInputs(t *testing.T) {
}) })
} }
} }
func TestRuleBuilderWithNinjaVarEscaping(t *testing.T) {
bp := `
rule_builder_test {
name: "foo_sbox_escaped_ninja",
flags: ["${cmdFlags}"],
sbox: true,
sbox_inputs: true,
}
rule_builder_test {
name: "foo_sbox",
flags: ["${cmdFlags}"],
sbox: true,
sbox_inputs: true,
unescape_ninja_vars: true,
}
`
result := GroupFixturePreparers(
prepareForRuleBuilderTest,
FixtureWithRootAndroidBp(bp),
).RunTest(t)
escapedNinjaMod := result.ModuleForTests("foo_sbox_escaped_ninja", "").Rule("writeFile")
AssertStringDoesContain(
t,
"",
escapedNinjaMod.BuildParams.Args["content"],
"$${cmdFlags}",
)
unescapedNinjaMod := result.ModuleForTests("foo_sbox", "").Rule("unescapedWriteFile")
AssertStringDoesContain(
t,
"",
unescapedNinjaMod.BuildParams.Args["content"],
"${cmdFlags}",
)
AssertStringDoesNotContain(
t,
"",
unescapedNinjaMod.BuildParams.Args["content"],
"$${cmdFlags}",
)
}

View file

@ -119,6 +119,9 @@ func run() error {
} }
manifest, err := readManifest(manifestFile) manifest, err := readManifest(manifestFile)
if err != nil {
return err
}
if len(manifest.Commands) == 0 { if len(manifest.Commands) == 0 {
return fmt.Errorf("at least one commands entry is required in %q", manifestFile) return fmt.Errorf("at least one commands entry is required in %q", manifestFile)