Loading android/bazel_handler.go +55 −41 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import ( "io/ioutil" "os" "os/exec" "path" "path/filepath" "runtime" "strings" Loading Loading @@ -870,16 +871,29 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) { }) } // Register bazel-owned build statements (obtained from the aquery invocation). executionRoot := path.Join(ctx.Config().BazelContext.OutputBase(), "execroot", "__main__") bazelOutDir := path.Join(executionRoot, "bazel-out") for index, buildStatement := range ctx.Config().BazelContext.BuildStatementsToRegister() { if len(buildStatement.Command) < 1 { panic(fmt.Sprintf("unhandled build statement: %v", buildStatement)) } rule := NewRuleBuilder(pctx, ctx) cmd := rule.Command() createCommand(rule.Command(), buildStatement, executionRoot, bazelOutDir, ctx) // This is required to silence warnings pertaining to unexpected timestamps. Particularly, // some Bazel builtins (such as files in the bazel_tools directory) have far-future // timestamps. Without restat, Ninja would emit warnings that the input files of a // build statement have later timestamps than the outputs. rule.Restat() desc := fmt.Sprintf("%s: %s", buildStatement.Mnemonic, buildStatement.OutputPaths) rule.Build(fmt.Sprintf("bazel %d", index), desc) } } // cd into Bazel's execution root, which is the action cwd. cmd.Text(fmt.Sprintf("cd %s/execroot/__main__ &&", ctx.Config().BazelContext.OutputBase())) // Register bazel-owned build statements (obtained from the aquery invocation). func createCommand(cmd *RuleBuilderCommand, buildStatement bazel.BuildStatement, executionRoot string, bazelOutDir string, ctx PathContext) { // executionRoot is the action cwd. cmd.Text(fmt.Sprintf("cd '%s' &&", executionRoot)) // Remove old outputs, as some actions might not rerun if the outputs are detected. if len(buildStatement.OutputPaths) > 0 { Loading Loading @@ -910,22 +924,22 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) { } if depfile := buildStatement.Depfile; depfile != nil { // The paths in depfile are relative to `executionRoot`. // Hence, they need to be corrected by replacing "bazel-out" // with the full `bazelOutDir`. // Otherwise, implicit outputs and implicit inputs under "bazel-out/" // would be deemed missing. // (Note: The regexp uses a capture group because the version of sed // does not support a look-behind pattern.) replacement := fmt.Sprintf(`&& sed -i'' -E 's@(^|\s|")bazel-out/@\1%s/@g' '%s'`, bazelOutDir, *depfile) cmd.Text(replacement) cmd.ImplicitDepFile(PathForBazelOut(ctx, *depfile)) } for _, symlinkPath := range buildStatement.SymlinkPaths { cmd.ImplicitSymlinkOutput(PathForBazelOut(ctx, symlinkPath)) } // This is required to silence warnings pertaining to unexpected timestamps. Particularly, // some Bazel builtins (such as files in the bazel_tools directory) have far-future // timestamps. Without restat, Ninja would emit warnings that the input files of a // build statement have later timestamps than the outputs. rule.Restat() desc := fmt.Sprintf("%s: %s", buildStatement.Mnemonic, buildStatement.OutputPaths) rule.Build(fmt.Sprintf("bazel %d", index), desc) } } func getCqueryId(key cqueryKey) string { Loading android/bazel_handler_test.go +59 −9 Original line number Diff line number Diff line Loading @@ -57,8 +57,13 @@ func TestInvokeBazelWritesBazelFiles(t *testing.T) { } func TestInvokeBazelPopulatesBuildStatements(t *testing.T) { bazelContext, _ := testBazelContext(t, map[bazelCommand]string{ bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: ` type testCase struct { input string command string } var testCases = []testCase{ {` { "artifacts": [{ "id": 1, Loading Loading @@ -88,7 +93,45 @@ func TestInvokeBazelPopulatesBuildStatements(t *testing.T) { "label": "two" }] }`, }) "cd 'er' && rm -f one && touch foo", }, {` { "artifacts": [{ "id": 1, "pathFragmentId": 10 }, { "id": 2, "pathFragmentId": 20 }], "actions": [{ "targetId": 100, "actionKey": "x", "mnemonic": "x", "arguments": ["bogus", "command"], "outputIds": [1, 2], "primaryOutputId": 1 }], "pathFragments": [{ "id": 10, "label": "one", "parentId": 30 }, { "id": 20, "label": "one.d", "parentId": 30 }, { "id": 30, "label": "parent" }] }`, `cd 'er' && rm -f parent/one && bogus command && sed -i'' -E 's@(^|\s|")bazel-out/@\1bo/@g' 'parent/one.d'`, }, } for _, testCase := range testCases { bazelContext, _ := testBazelContext(t, map[bazelCommand]string{ bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: testCase.input}) err := bazelContext.InvokeBazel(testConfig) if err != nil { t.Fatalf("Did not expect error invoking Bazel, but got %s", err) Loading @@ -96,7 +139,14 @@ func TestInvokeBazelPopulatesBuildStatements(t *testing.T) { got := bazelContext.BuildStatementsToRegister() if want := 1; len(got) != want { t.Errorf("Expected %d registered build statements, got %#v", want, got) t.Errorf("expected %d registered build statements, but got %#v", want, got) } cmd := RuleBuilderCommand{} createCommand(&cmd, got[0], "er", "bo", PathContextForTesting(TestConfig("out", nil, "", nil))) if actual := cmd.buf.String(); testCase.command != actual { t.Errorf("expected: [%s], actual: [%s]", testCase.command, actual) } } } Loading Loading
android/bazel_handler.go +55 −41 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import ( "io/ioutil" "os" "os/exec" "path" "path/filepath" "runtime" "strings" Loading Loading @@ -870,16 +871,29 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) { }) } // Register bazel-owned build statements (obtained from the aquery invocation). executionRoot := path.Join(ctx.Config().BazelContext.OutputBase(), "execroot", "__main__") bazelOutDir := path.Join(executionRoot, "bazel-out") for index, buildStatement := range ctx.Config().BazelContext.BuildStatementsToRegister() { if len(buildStatement.Command) < 1 { panic(fmt.Sprintf("unhandled build statement: %v", buildStatement)) } rule := NewRuleBuilder(pctx, ctx) cmd := rule.Command() createCommand(rule.Command(), buildStatement, executionRoot, bazelOutDir, ctx) // This is required to silence warnings pertaining to unexpected timestamps. Particularly, // some Bazel builtins (such as files in the bazel_tools directory) have far-future // timestamps. Without restat, Ninja would emit warnings that the input files of a // build statement have later timestamps than the outputs. rule.Restat() desc := fmt.Sprintf("%s: %s", buildStatement.Mnemonic, buildStatement.OutputPaths) rule.Build(fmt.Sprintf("bazel %d", index), desc) } } // cd into Bazel's execution root, which is the action cwd. cmd.Text(fmt.Sprintf("cd %s/execroot/__main__ &&", ctx.Config().BazelContext.OutputBase())) // Register bazel-owned build statements (obtained from the aquery invocation). func createCommand(cmd *RuleBuilderCommand, buildStatement bazel.BuildStatement, executionRoot string, bazelOutDir string, ctx PathContext) { // executionRoot is the action cwd. cmd.Text(fmt.Sprintf("cd '%s' &&", executionRoot)) // Remove old outputs, as some actions might not rerun if the outputs are detected. if len(buildStatement.OutputPaths) > 0 { Loading Loading @@ -910,22 +924,22 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) { } if depfile := buildStatement.Depfile; depfile != nil { // The paths in depfile are relative to `executionRoot`. // Hence, they need to be corrected by replacing "bazel-out" // with the full `bazelOutDir`. // Otherwise, implicit outputs and implicit inputs under "bazel-out/" // would be deemed missing. // (Note: The regexp uses a capture group because the version of sed // does not support a look-behind pattern.) replacement := fmt.Sprintf(`&& sed -i'' -E 's@(^|\s|")bazel-out/@\1%s/@g' '%s'`, bazelOutDir, *depfile) cmd.Text(replacement) cmd.ImplicitDepFile(PathForBazelOut(ctx, *depfile)) } for _, symlinkPath := range buildStatement.SymlinkPaths { cmd.ImplicitSymlinkOutput(PathForBazelOut(ctx, symlinkPath)) } // This is required to silence warnings pertaining to unexpected timestamps. Particularly, // some Bazel builtins (such as files in the bazel_tools directory) have far-future // timestamps. Without restat, Ninja would emit warnings that the input files of a // build statement have later timestamps than the outputs. rule.Restat() desc := fmt.Sprintf("%s: %s", buildStatement.Mnemonic, buildStatement.OutputPaths) rule.Build(fmt.Sprintf("bazel %d", index), desc) } } func getCqueryId(key cqueryKey) string { Loading
android/bazel_handler_test.go +59 −9 Original line number Diff line number Diff line Loading @@ -57,8 +57,13 @@ func TestInvokeBazelWritesBazelFiles(t *testing.T) { } func TestInvokeBazelPopulatesBuildStatements(t *testing.T) { bazelContext, _ := testBazelContext(t, map[bazelCommand]string{ bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: ` type testCase struct { input string command string } var testCases = []testCase{ {` { "artifacts": [{ "id": 1, Loading Loading @@ -88,7 +93,45 @@ func TestInvokeBazelPopulatesBuildStatements(t *testing.T) { "label": "two" }] }`, }) "cd 'er' && rm -f one && touch foo", }, {` { "artifacts": [{ "id": 1, "pathFragmentId": 10 }, { "id": 2, "pathFragmentId": 20 }], "actions": [{ "targetId": 100, "actionKey": "x", "mnemonic": "x", "arguments": ["bogus", "command"], "outputIds": [1, 2], "primaryOutputId": 1 }], "pathFragments": [{ "id": 10, "label": "one", "parentId": 30 }, { "id": 20, "label": "one.d", "parentId": 30 }, { "id": 30, "label": "parent" }] }`, `cd 'er' && rm -f parent/one && bogus command && sed -i'' -E 's@(^|\s|")bazel-out/@\1bo/@g' 'parent/one.d'`, }, } for _, testCase := range testCases { bazelContext, _ := testBazelContext(t, map[bazelCommand]string{ bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: testCase.input}) err := bazelContext.InvokeBazel(testConfig) if err != nil { t.Fatalf("Did not expect error invoking Bazel, but got %s", err) Loading @@ -96,7 +139,14 @@ func TestInvokeBazelPopulatesBuildStatements(t *testing.T) { got := bazelContext.BuildStatementsToRegister() if want := 1; len(got) != want { t.Errorf("Expected %d registered build statements, got %#v", want, got) t.Errorf("expected %d registered build statements, but got %#v", want, got) } cmd := RuleBuilderCommand{} createCommand(&cmd, got[0], "er", "bo", PathContextForTesting(TestConfig("out", nil, "", nil))) if actual := cmd.buf.String(); testCase.command != actual { t.Errorf("expected: [%s], actual: [%s]", testCase.command, actual) } } } Loading