Loading android/rule_builder.go +6 −0 Original line number Diff line number Diff line Loading @@ -554,6 +554,12 @@ func (r *RuleBuilder) build(name string, desc string, ninjaEscapeCommandString b To: proto.String(r.sboxPathForInputRel(input)), }) } for _, input := range r.OrderOnlys() { command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{ From: proto.String(input.String()), To: proto.String(r.sboxPathForInputRel(input)), }) } // If using rsp files copy them and their contents into the sbox directory with // the appropriate path mappings. Loading genrule/genrule.go +35 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,21 @@ type generatorProperties struct { // Enable restat to update the output only if the output is changed Write_if_changed *bool // When set to true, an additional $(build_number_file) label will be available // to use in the cmd. This will be the location of a text file containing the // build number. The dependency on this file will be "order-only", meaning that // the genrule will not rerun when only this file changes, to avoid rerunning // the genrule every build, because the build number changes every build. // This also means that you should not attempt to consume the build number from // the result of this genrule in another build rule. If you do, the build number // in the second build rule will be stale when the second build rule rebuilds // but this genrule does not. Only certain allowlisted modules are allowed to // use this property, usages of the build number should be kept to the absolute // minimum. Particularly no modules on the system image may include the build // number. Prefer using libbuildversion via the use_version_lib property on // cc modules. Uses_order_only_build_number_file *bool } type Module struct { Loading Loading @@ -228,6 +243,15 @@ func toolDepsMutator(ctx android.BottomUpMutatorContext) { } } // This allowlist should be kept to the bare minimum, it's // intended for things that existed before the build number // was tightly controlled. Prefer using libbuildversion // via the use_version_lib property of cc modules. var genrule_build_number_allowlist = map[string]bool{ "build/soong/tests:gen": true, "tools/tradefederation/core:tradefed_zip": true, } // generateCommonBuildActions contains build action generation logic // common to both the mixed build case and the legacy case of genrule processing. // To fully support genrule in mixed builds, the contents of this function should Loading Loading @@ -470,6 +494,11 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) { return strings.Join(proptools.ShellEscapeList(sandboxOuts), " "), nil case "genDir": return proptools.ShellEscape(cmd.PathForOutput(task.genDir)), nil case "build_number_file": if !proptools.Bool(g.properties.Uses_order_only_build_number_file) { return reportError("to use the $(build_number_file) label, you must set uses_order_only_build_number_file: true") } return proptools.ShellEscape(cmd.PathForInput(ctx.Config().BuildNumberFile(ctx))), nil default: if strings.HasPrefix(name, "location ") { label := strings.TrimSpace(strings.TrimPrefix(name, "location ")) Loading Loading @@ -516,6 +545,12 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) { cmd.Implicits(task.in) cmd.ImplicitTools(tools) cmd.ImplicitPackagedTools(packagedTools) if proptools.Bool(g.properties.Uses_order_only_build_number_file) { if _, ok := genrule_build_number_allowlist[ctx.ModuleDir()+":"+ctx.ModuleName()]; !ok { ctx.ModuleErrorf("Only allowlisted modules may use uses_order_only_build_number_file: true") } cmd.OrderOnly(ctx.Config().BuildNumberFile(ctx)) } // Create the rule to run the genrule command inside sbox. rule.Build(name, desc) Loading genrule/genrule_test.go +63 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ import ( "os" "regexp" "strconv" "strings" "testing" "android/soong/android" Loading Loading @@ -1192,6 +1193,68 @@ func TestGenruleWithGlobPaths(t *testing.T) { } } func TestGenruleUsesOrderOnlyBuildNumberFile(t *testing.T) { testCases := []struct { name string bp string fs android.MockFS expectedError string expectedCommand string }{ { name: "not allowed when not in allowlist", fs: android.MockFS{ "foo/Android.bp": []byte(` genrule { name: "gen", uses_order_only_build_number_file: true, cmd: "cp $(build_number_file) $(out)", out: ["out.txt"], } `), }, expectedError: `Only allowlisted modules may use uses_order_only_build_number_file: true`, }, { name: "normal", fs: android.MockFS{ "build/soong/tests/Android.bp": []byte(` genrule { name: "gen", uses_order_only_build_number_file: true, cmd: "cp $(build_number_file) $(out)", out: ["out.txt"], } `), }, expectedCommand: `cp BUILD_NUMBER_FILE __SBOX_SANDBOX_DIR__/out/out.txt`, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { fixtures := android.GroupFixturePreparers( prepareForGenRuleTest, android.PrepareForTestWithVisibility, android.FixtureMergeMockFs(tc.fs), android.FixtureModifyConfigAndContext(func(config android.Config, ctx *android.TestContext) { config.TestProductVariables.BuildNumberFile = proptools.StringPtr("build_number.txt") }), ) if tc.expectedError != "" { fixtures = fixtures.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(tc.expectedError)) } result := fixtures.RunTest(t) if tc.expectedError == "" { tc.expectedCommand = strings.ReplaceAll(tc.expectedCommand, "BUILD_NUMBER_FILE", result.Config.SoongOutDir()+"/build_number.txt") gen := result.Module("gen", "").(*Module) android.AssertStringEquals(t, "raw commands", tc.expectedCommand, gen.rawCommands[0]) } }) } } type testTool struct { android.ModuleBase outputFile android.Path Loading Loading
android/rule_builder.go +6 −0 Original line number Diff line number Diff line Loading @@ -554,6 +554,12 @@ func (r *RuleBuilder) build(name string, desc string, ninjaEscapeCommandString b To: proto.String(r.sboxPathForInputRel(input)), }) } for _, input := range r.OrderOnlys() { command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{ From: proto.String(input.String()), To: proto.String(r.sboxPathForInputRel(input)), }) } // If using rsp files copy them and their contents into the sbox directory with // the appropriate path mappings. Loading
genrule/genrule.go +35 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,21 @@ type generatorProperties struct { // Enable restat to update the output only if the output is changed Write_if_changed *bool // When set to true, an additional $(build_number_file) label will be available // to use in the cmd. This will be the location of a text file containing the // build number. The dependency on this file will be "order-only", meaning that // the genrule will not rerun when only this file changes, to avoid rerunning // the genrule every build, because the build number changes every build. // This also means that you should not attempt to consume the build number from // the result of this genrule in another build rule. If you do, the build number // in the second build rule will be stale when the second build rule rebuilds // but this genrule does not. Only certain allowlisted modules are allowed to // use this property, usages of the build number should be kept to the absolute // minimum. Particularly no modules on the system image may include the build // number. Prefer using libbuildversion via the use_version_lib property on // cc modules. Uses_order_only_build_number_file *bool } type Module struct { Loading Loading @@ -228,6 +243,15 @@ func toolDepsMutator(ctx android.BottomUpMutatorContext) { } } // This allowlist should be kept to the bare minimum, it's // intended for things that existed before the build number // was tightly controlled. Prefer using libbuildversion // via the use_version_lib property of cc modules. var genrule_build_number_allowlist = map[string]bool{ "build/soong/tests:gen": true, "tools/tradefederation/core:tradefed_zip": true, } // generateCommonBuildActions contains build action generation logic // common to both the mixed build case and the legacy case of genrule processing. // To fully support genrule in mixed builds, the contents of this function should Loading Loading @@ -470,6 +494,11 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) { return strings.Join(proptools.ShellEscapeList(sandboxOuts), " "), nil case "genDir": return proptools.ShellEscape(cmd.PathForOutput(task.genDir)), nil case "build_number_file": if !proptools.Bool(g.properties.Uses_order_only_build_number_file) { return reportError("to use the $(build_number_file) label, you must set uses_order_only_build_number_file: true") } return proptools.ShellEscape(cmd.PathForInput(ctx.Config().BuildNumberFile(ctx))), nil default: if strings.HasPrefix(name, "location ") { label := strings.TrimSpace(strings.TrimPrefix(name, "location ")) Loading Loading @@ -516,6 +545,12 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) { cmd.Implicits(task.in) cmd.ImplicitTools(tools) cmd.ImplicitPackagedTools(packagedTools) if proptools.Bool(g.properties.Uses_order_only_build_number_file) { if _, ok := genrule_build_number_allowlist[ctx.ModuleDir()+":"+ctx.ModuleName()]; !ok { ctx.ModuleErrorf("Only allowlisted modules may use uses_order_only_build_number_file: true") } cmd.OrderOnly(ctx.Config().BuildNumberFile(ctx)) } // Create the rule to run the genrule command inside sbox. rule.Build(name, desc) Loading
genrule/genrule_test.go +63 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ import ( "os" "regexp" "strconv" "strings" "testing" "android/soong/android" Loading Loading @@ -1192,6 +1193,68 @@ func TestGenruleWithGlobPaths(t *testing.T) { } } func TestGenruleUsesOrderOnlyBuildNumberFile(t *testing.T) { testCases := []struct { name string bp string fs android.MockFS expectedError string expectedCommand string }{ { name: "not allowed when not in allowlist", fs: android.MockFS{ "foo/Android.bp": []byte(` genrule { name: "gen", uses_order_only_build_number_file: true, cmd: "cp $(build_number_file) $(out)", out: ["out.txt"], } `), }, expectedError: `Only allowlisted modules may use uses_order_only_build_number_file: true`, }, { name: "normal", fs: android.MockFS{ "build/soong/tests/Android.bp": []byte(` genrule { name: "gen", uses_order_only_build_number_file: true, cmd: "cp $(build_number_file) $(out)", out: ["out.txt"], } `), }, expectedCommand: `cp BUILD_NUMBER_FILE __SBOX_SANDBOX_DIR__/out/out.txt`, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { fixtures := android.GroupFixturePreparers( prepareForGenRuleTest, android.PrepareForTestWithVisibility, android.FixtureMergeMockFs(tc.fs), android.FixtureModifyConfigAndContext(func(config android.Config, ctx *android.TestContext) { config.TestProductVariables.BuildNumberFile = proptools.StringPtr("build_number.txt") }), ) if tc.expectedError != "" { fixtures = fixtures.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(tc.expectedError)) } result := fixtures.RunTest(t) if tc.expectedError == "" { tc.expectedCommand = strings.ReplaceAll(tc.expectedCommand, "BUILD_NUMBER_FILE", result.Config.SoongOutDir()+"/build_number.txt") gen := result.Module("gen", "").(*Module) android.AssertStringEquals(t, "raw commands", tc.expectedCommand, gen.rawCommands[0]) } }) } } type testTool struct { android.ModuleBase outputFile android.Path Loading