Add functionality to sandbox mixed build actions
The use case for this is for building rules_go's root builder which runs into issues when built in a directory that contains a symlink to prebuilts/go The implementation will involve two changes of working dir - `sbox` to change the working directory to __SBOX_SANDBOX_DIR__ - the generated manifest will change the working directory to mixed build execution root relative to that Implemenation details 1. Create a unique intermediate path by hashing the outputs of a buildAction. "out/bazel/output/execroot/__main__/" was deliberately not chosen as the outpuDir for the sandbox because ruleBuilder would wipe it. `sbox` will generate the files in __SBOX_SANDBOX_DIR__ and then place the files in this intermediate directory. 2. After the files have been generated in (1), copy them to out/bazel/output/execroot/__main__/... 3. For bazel depsets that are inputs of an action, copy the direct artifacts into the sandbox instead of the phony target 4. Make sandboxing an opt-in. Currently we will only use it for `GoToolchainBinaryBuild` In the current implementation, (3) will increase the size of the ninja file. With sboxing turned on for only GoToolchainBinaryBuild, this will increase the size of the ninja file by around 1.3% on aosp's cf Test: m com.android.neuralnetworks (will build soong_zip from source using rules_go) Test: OUT_DIR=out.other m com.android.neuralnetworks Bug: 289102849 Change-Id: I7addda9af583ba0ff306e50c1dfa16ed16c29799
This commit is contained in:
@@ -181,13 +181,62 @@ func TestInvokeBazelPopulatesBuildStatements(t *testing.T) {
|
||||
|
||||
cmd := RuleBuilderCommand{}
|
||||
ctx := builderContextForTests{PathContextForTesting(TestConfig("out", nil, "", nil))}
|
||||
createCommand(&cmd, got[0], "test/exec_root", "test/bazel_out", ctx)
|
||||
createCommand(&cmd, got[0], "test/exec_root", "test/bazel_out", ctx, map[string]bazel.AqueryDepset{})
|
||||
if actual, expected := cmd.buf.String(), testCase.command; expected != actual {
|
||||
t.Errorf("expected: [%s], actual: [%s]", expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMixedBuildSandboxedAction(t *testing.T) {
|
||||
input := `{
|
||||
"artifacts": [
|
||||
{ "id": 1, "path_fragment_id": 1 },
|
||||
{ "id": 2, "path_fragment_id": 2 }],
|
||||
"actions": [{
|
||||
"target_Id": 1,
|
||||
"action_Key": "x",
|
||||
"mnemonic": "x",
|
||||
"arguments": ["touch", "foo"],
|
||||
"input_dep_set_ids": [1],
|
||||
"output_Ids": [1],
|
||||
"primary_output_id": 1
|
||||
}],
|
||||
"dep_set_of_files": [
|
||||
{ "id": 1, "direct_artifact_ids": [1, 2] }],
|
||||
"path_fragments": [
|
||||
{ "id": 1, "label": "one" },
|
||||
{ "id": 2, "label": "two" }]
|
||||
}`
|
||||
data, err := JsonToActionGraphContainer(input)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
bazelContext, _ := testBazelContext(t, map[bazelCommand]string{aqueryCmd: string(data)})
|
||||
|
||||
err = bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
|
||||
if err != nil {
|
||||
t.Fatalf("TestMixedBuildSandboxedAction did not expect error invoking Bazel, but got %s", err)
|
||||
}
|
||||
|
||||
statement := bazelContext.BuildStatementsToRegister()[0]
|
||||
statement.ShouldRunInSbox = true
|
||||
|
||||
cmd := RuleBuilderCommand{}
|
||||
ctx := builderContextForTests{PathContextForTesting(TestConfig("out", nil, "", nil))}
|
||||
createCommand(&cmd, statement, "test/exec_root", "test/bazel_out", ctx, map[string]bazel.AqueryDepset{})
|
||||
// Assert that the output is generated in an intermediate directory
|
||||
// fe05bcdcdc4928012781a5f1a2a77cbb5398e106 is the sha1 checksum of "one"
|
||||
if actual, expected := cmd.outputs[0].String(), "out/soong/mixed_build_sbox_intermediates/fe05bcdcdc4928012781a5f1a2a77cbb5398e106/test/exec_root/one"; expected != actual {
|
||||
t.Errorf("expected: [%s], actual: [%s]", expected, actual)
|
||||
}
|
||||
|
||||
// Assert the actual command remains unchanged inside the sandbox
|
||||
if actual, expected := cmd.buf.String(), "mkdir -p 'test/exec_root' && cd 'test/exec_root' && rm -rf 'one' && touch foo"; expected != actual {
|
||||
t.Errorf("expected: [%s], actual: [%s]", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoverageFlagsAfterInvokeBazel(t *testing.T) {
|
||||
testConfig.productVariables.ClangCoverage = boolPtr(true)
|
||||
|
||||
|
Reference in New Issue
Block a user