Add depfile handling for bazel_handler.
Test: go test soong tests Test: TODO mixed build change header, mixed build Change-Id: I7c51faf2d5b1a8717cbab6bb0b3eb75c307fcd85
This commit is contained in:
parent
dca349a782
commit
de116856fb
|
@ -746,6 +746,10 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) {
|
|||
cmd.Implicit(PathForBazelOut(ctx, inputPath))
|
||||
}
|
||||
|
||||
if depfile := buildStatement.Depfile; depfile != nil {
|
||||
cmd.ImplicitDepFile(PathForBazelOut(ctx, *depfile))
|
||||
}
|
||||
|
||||
// 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
|
||||
|
|
|
@ -74,6 +74,7 @@ type actionGraphContainer struct {
|
|||
// with a Bazel action from Bazel's action graph.
|
||||
type BuildStatement struct {
|
||||
Command string
|
||||
Depfile *string
|
||||
OutputPaths []string
|
||||
InputPaths []string
|
||||
Env []KeyValuePair
|
||||
|
@ -133,12 +134,22 @@ func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, error) {
|
|||
continue
|
||||
}
|
||||
outputPaths := []string{}
|
||||
var depfile *string
|
||||
for _, outputId := range actionEntry.OutputIds {
|
||||
outputPath, exists := artifactIdToPath[outputId]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("undefined outputId %d", outputId)
|
||||
}
|
||||
outputPaths = append(outputPaths, outputPath)
|
||||
ext := filepath.Ext(outputPath)
|
||||
if ext == ".d" {
|
||||
if depfile != nil {
|
||||
return nil, fmt.Errorf("found multiple potential depfiles %q, %q", *depfile, outputPath)
|
||||
} else {
|
||||
depfile = &outputPath
|
||||
}
|
||||
} else {
|
||||
outputPaths = append(outputPaths, outputPath)
|
||||
}
|
||||
}
|
||||
inputPaths := []string{}
|
||||
for _, inputDepSetId := range actionEntry.InputDepSetIds {
|
||||
|
@ -161,12 +172,13 @@ func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, error) {
|
|||
}
|
||||
buildStatement := BuildStatement{
|
||||
Command: strings.Join(proptools.ShellEscapeList(actionEntry.Arguments), " "),
|
||||
Depfile: depfile,
|
||||
OutputPaths: outputPaths,
|
||||
InputPaths: inputPaths,
|
||||
Env: actionEntry.EnvironmentVariables,
|
||||
Mnemonic: actionEntry.Mnemonic}
|
||||
if len(actionEntry.Arguments) < 1 {
|
||||
return nil, fmt.Errorf("received action with no command: [%s]", buildStatement)
|
||||
return nil, fmt.Errorf("received action with no command: [%v]", buildStatement)
|
||||
continue
|
||||
}
|
||||
buildStatements = append(buildStatements, buildStatement)
|
||||
|
|
|
@ -393,6 +393,109 @@ func TestInvalidPathFragmentId(t *testing.T) {
|
|||
assertError(t, err, "undefined path fragment id 3")
|
||||
}
|
||||
|
||||
func TestDepfiles(t *testing.T) {
|
||||
const inputString = `
|
||||
{
|
||||
"artifacts": [{
|
||||
"id": 1,
|
||||
"pathFragmentId": 1
|
||||
}, {
|
||||
"id": 2,
|
||||
"pathFragmentId": 2
|
||||
}, {
|
||||
"id": 3,
|
||||
"pathFragmentId": 3
|
||||
}],
|
||||
"actions": [{
|
||||
"targetId": 1,
|
||||
"actionKey": "x",
|
||||
"mnemonic": "x",
|
||||
"arguments": ["touch", "foo"],
|
||||
"inputDepSetIds": [1],
|
||||
"outputIds": [2, 3],
|
||||
"primaryOutputId": 2
|
||||
}],
|
||||
"depSetOfFiles": [{
|
||||
"id": 1,
|
||||
"directArtifactIds": [1, 2, 3]
|
||||
}],
|
||||
"pathFragments": [{
|
||||
"id": 1,
|
||||
"label": "one"
|
||||
}, {
|
||||
"id": 2,
|
||||
"label": "two"
|
||||
}, {
|
||||
"id": 3,
|
||||
"label": "two.d"
|
||||
}]
|
||||
}`
|
||||
|
||||
actual, err := AqueryBuildStatements([]byte(inputString))
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error %q", err)
|
||||
}
|
||||
if expected := 1; len(actual) != expected {
|
||||
t.Fatalf("Expected %d build statements, got %d", expected, len(actual))
|
||||
}
|
||||
|
||||
bs := actual[0]
|
||||
expectedDepfile := "two.d"
|
||||
if bs.Depfile == nil {
|
||||
t.Errorf("Expected depfile %q, but there was none found", expectedDepfile)
|
||||
} else if *bs.Depfile != expectedDepfile {
|
||||
t.Errorf("Expected depfile %q, but got %q", expectedDepfile, *bs.Depfile)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMultipleDepfiles(t *testing.T) {
|
||||
const inputString = `
|
||||
{
|
||||
"artifacts": [{
|
||||
"id": 1,
|
||||
"pathFragmentId": 1
|
||||
}, {
|
||||
"id": 2,
|
||||
"pathFragmentId": 2
|
||||
}, {
|
||||
"id": 3,
|
||||
"pathFragmentId": 3
|
||||
}, {
|
||||
"id": 4,
|
||||
"pathFragmentId": 4
|
||||
}],
|
||||
"actions": [{
|
||||
"targetId": 1,
|
||||
"actionKey": "x",
|
||||
"mnemonic": "x",
|
||||
"arguments": ["touch", "foo"],
|
||||
"inputDepSetIds": [1],
|
||||
"outputIds": [2,3,4],
|
||||
"primaryOutputId": 2
|
||||
}],
|
||||
"depSetOfFiles": [{
|
||||
"id": 1,
|
||||
"directArtifactIds": [1, 2, 3, 4]
|
||||
}],
|
||||
"pathFragments": [{
|
||||
"id": 1,
|
||||
"label": "one"
|
||||
}, {
|
||||
"id": 2,
|
||||
"label": "two"
|
||||
}, {
|
||||
"id": 3,
|
||||
"label": "two.d"
|
||||
}, {
|
||||
"id": 4,
|
||||
"label": "other.d"
|
||||
}]
|
||||
}`
|
||||
|
||||
_, err := AqueryBuildStatements([]byte(inputString))
|
||||
assertError(t, err, `found multiple potential depfiles "two.d", "other.d"`)
|
||||
}
|
||||
|
||||
func TestTransitiveInputDepsets(t *testing.T) {
|
||||
// The input aquery for this test comes from a proof-of-concept starlark rule which registers
|
||||
// a single action with many inputs given via a deep depset.
|
||||
|
@ -627,7 +730,7 @@ func assertError(t *testing.T, err error, expected string) {
|
|||
// Build statement equivalence is determined using buildStatementEquals.
|
||||
func assertBuildStatements(t *testing.T, expected []BuildStatement, actual []BuildStatement) {
|
||||
if len(expected) != len(actual) {
|
||||
t.Errorf("expected %d build statements, but got %d,\n expected: %s,\n actual: %s",
|
||||
t.Errorf("expected %d build statements, but got %d,\n expected: %v,\n actual: %v",
|
||||
len(expected), len(actual), expected, actual)
|
||||
return
|
||||
}
|
||||
|
@ -638,7 +741,7 @@ ACTUAL_LOOP:
|
|||
continue ACTUAL_LOOP
|
||||
}
|
||||
}
|
||||
t.Errorf("unexpected build statement %s.\n expected: %s",
|
||||
t.Errorf("unexpected build statement %v.\n expected: %v",
|
||||
actualStatement, expected)
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue