Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit de116856 authored by Liz Kammer's avatar Liz Kammer
Browse files

Add depfile handling for bazel_handler.

Test: go test soong tests
Test: TODO mixed build change header, mixed build
Change-Id: I7c51faf2d5b1a8717cbab6bb0b3eb75c307fcd85
parent dca349a7
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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
+14 −2
Original line number Diff line number Diff line
@@ -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,13 +134,23 @@ 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)
			}
			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 {
			inputArtifacts, err :=
@@ -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)
+105 −2
Original line number Diff line number Diff line
@@ -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
	}