paths in depfiles are relative to $OUT_DIR
Test: USE_BAZEL_ANALYSIS=1 m libc droid Bug: b/232250671 Change-Id: I7a570894371bd31339ab0cf3c619c30b3cf8cd73
This commit is contained in:
@@ -21,6 +21,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -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() {
|
for index, buildStatement := range ctx.Config().BazelContext.BuildStatementsToRegister() {
|
||||||
if len(buildStatement.Command) < 1 {
|
if len(buildStatement.Command) < 1 {
|
||||||
panic(fmt.Sprintf("unhandled build statement: %v", buildStatement))
|
panic(fmt.Sprintf("unhandled build statement: %v", buildStatement))
|
||||||
}
|
}
|
||||||
rule := NewRuleBuilder(pctx, ctx)
|
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()
|
||||||
|
|
||||||
// cd into Bazel's execution root, which is the action cwd.
|
desc := fmt.Sprintf("%s: %s", buildStatement.Mnemonic, buildStatement.OutputPaths)
|
||||||
cmd.Text(fmt.Sprintf("cd %s/execroot/__main__ &&", ctx.Config().BazelContext.OutputBase()))
|
rule.Build(fmt.Sprintf("bazel %d", index), desc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
// Remove old outputs, as some actions might not rerun if the outputs are detected.
|
||||||
if len(buildStatement.OutputPaths) > 0 {
|
if len(buildStatement.OutputPaths) > 0 {
|
||||||
@@ -910,22 +924,22 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if depfile := buildStatement.Depfile; depfile != nil {
|
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))
|
cmd.ImplicitDepFile(PathForBazelOut(ctx, *depfile))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, symlinkPath := range buildStatement.SymlinkPaths {
|
for _, symlinkPath := range buildStatement.SymlinkPaths {
|
||||||
cmd.ImplicitSymlinkOutput(PathForBazelOut(ctx, symlinkPath))
|
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 {
|
func getCqueryId(key cqueryKey) string {
|
||||||
|
@@ -57,8 +57,13 @@ func TestInvokeBazelWritesBazelFiles(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestInvokeBazelPopulatesBuildStatements(t *testing.T) {
|
func TestInvokeBazelPopulatesBuildStatements(t *testing.T) {
|
||||||
bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
|
type testCase struct {
|
||||||
bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: `
|
input string
|
||||||
|
command string
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCases = []testCase{
|
||||||
|
{`
|
||||||
{
|
{
|
||||||
"artifacts": [{
|
"artifacts": [{
|
||||||
"id": 1,
|
"id": 1,
|
||||||
@@ -88,7 +93,45 @@ func TestInvokeBazelPopulatesBuildStatements(t *testing.T) {
|
|||||||
"label": "two"
|
"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)
|
err := bazelContext.InvokeBazel(testConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
|
t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
|
||||||
@@ -96,7 +139,14 @@ func TestInvokeBazelPopulatesBuildStatements(t *testing.T) {
|
|||||||
|
|
||||||
got := bazelContext.BuildStatementsToRegister()
|
got := bazelContext.BuildStatementsToRegister()
|
||||||
if want := 1; len(got) != want {
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user