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))
|
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,
|
// 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
|
// 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
|
// 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.
|
// with a Bazel action from Bazel's action graph.
|
||||||
type BuildStatement struct {
|
type BuildStatement struct {
|
||||||
Command string
|
Command string
|
||||||
|
Depfile *string
|
||||||
OutputPaths []string
|
OutputPaths []string
|
||||||
InputPaths []string
|
InputPaths []string
|
||||||
Env []KeyValuePair
|
Env []KeyValuePair
|
||||||
|
@ -133,12 +134,22 @@ func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
outputPaths := []string{}
|
outputPaths := []string{}
|
||||||
|
var depfile *string
|
||||||
for _, outputId := range actionEntry.OutputIds {
|
for _, outputId := range actionEntry.OutputIds {
|
||||||
outputPath, exists := artifactIdToPath[outputId]
|
outputPath, exists := artifactIdToPath[outputId]
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil, fmt.Errorf("undefined outputId %d", outputId)
|
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{}
|
inputPaths := []string{}
|
||||||
for _, inputDepSetId := range actionEntry.InputDepSetIds {
|
for _, inputDepSetId := range actionEntry.InputDepSetIds {
|
||||||
|
@ -161,12 +172,13 @@ func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, error) {
|
||||||
}
|
}
|
||||||
buildStatement := BuildStatement{
|
buildStatement := BuildStatement{
|
||||||
Command: strings.Join(proptools.ShellEscapeList(actionEntry.Arguments), " "),
|
Command: strings.Join(proptools.ShellEscapeList(actionEntry.Arguments), " "),
|
||||||
|
Depfile: depfile,
|
||||||
OutputPaths: outputPaths,
|
OutputPaths: outputPaths,
|
||||||
InputPaths: inputPaths,
|
InputPaths: inputPaths,
|
||||||
Env: actionEntry.EnvironmentVariables,
|
Env: actionEntry.EnvironmentVariables,
|
||||||
Mnemonic: actionEntry.Mnemonic}
|
Mnemonic: actionEntry.Mnemonic}
|
||||||
if len(actionEntry.Arguments) < 1 {
|
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
|
continue
|
||||||
}
|
}
|
||||||
buildStatements = append(buildStatements, buildStatement)
|
buildStatements = append(buildStatements, buildStatement)
|
||||||
|
|
|
@ -393,6 +393,109 @@ func TestInvalidPathFragmentId(t *testing.T) {
|
||||||
assertError(t, err, "undefined path fragment id 3")
|
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) {
|
func TestTransitiveInputDepsets(t *testing.T) {
|
||||||
// The input aquery for this test comes from a proof-of-concept starlark rule which registers
|
// 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.
|
// 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.
|
// Build statement equivalence is determined using buildStatementEquals.
|
||||||
func assertBuildStatements(t *testing.T, expected []BuildStatement, actual []BuildStatement) {
|
func assertBuildStatements(t *testing.T, expected []BuildStatement, actual []BuildStatement) {
|
||||||
if len(expected) != len(actual) {
|
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)
|
len(expected), len(actual), expected, actual)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -638,7 +741,7 @@ ACTUAL_LOOP:
|
||||||
continue 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)
|
actualStatement, expected)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue