Skip to content

Commit 6be956b

Browse files
committed
pre-build-hook: Provide it with a JSON serialization of the BasicDerivation
The hook gets the path of the derivation as an argument, but the derivation typically doesn't exist when called as a remote build.
1 parent 4acdb39 commit 6be956b

4 files changed

Lines changed: 68 additions & 5 deletions

File tree

src/libstore/include/nix/store/globals.hh

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,10 +1081,24 @@ public:
10811081
captured by the derivation model itself and are too variable between
10821082
different versions of the same system to be hard-coded into nix.
10831083
1084-
The hook is passed the derivation path and, if sandboxes are
1085-
enabled, the sandbox directory. It can then modify the sandbox and
1086-
send a series of commands to modify various settings to stdout. The
1087-
currently recognized commands are:
1084+
The hook receives the derivation to be built as JSON in the file
1085+
pointed to by the environment variable `NIX_DERIVATION_V4`. See
1086+
[@docroot@/protocols/json/derivation/index.md](@docroot@/protocols/json/derivation/index.md)
1087+
for the format. For example, to read the `requiredSystemFeatures`
1088+
attribute:
1089+
1090+
```sh
1091+
jq -r '.env.requiredSystemFeatures' < "$NIX_DERIVATION_V4"
1092+
```
1093+
1094+
> **Deprecated**
1095+
> Using the derivation store path passed as `argv[1]` to inspect the
1096+
> derivation is deprecated and not recommended. This path may not
1097+
> exist when Nix is invoked as a remote builder.
1098+
1099+
If sandboxes are enabled, the hook also receives the sandbox
1100+
directory as `argv[2]`. It can send a series of commands to modify
1101+
various settings to stdout. The currently recognized commands are:
10881102
10891103
- `extra-sandbox-paths`\
10901104
Pass a list of files and directories to be included in the

src/libstore/unix/build/derivation-builder.cc

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "nix/util/terminal.hh"
2323
#include "nix/store/provenance.hh"
2424

25+
#include <nlohmann/json.hpp>
2526
#include <queue>
2627

2728
#include <sys/un.h>
@@ -932,8 +933,27 @@ PathsInChroot DerivationBuilderImpl::getPathsInSandbox()
932933

933934
enum BuildHookState { stBegin, stExtraChrootDirs };
934935

936+
nlohmann::json drvJson = drv;
937+
938+
auto [tmpFd, drvJsonPath] = createTempFile("nix-drv-json");
939+
writeFile(drvJsonPath, drvJson.dump());
940+
AutoDelete drvJsonFile(drvJsonPath, false);
941+
942+
auto hookEnv = getEnv();
943+
static_assert(expectedJsonVersionDerivation == 4);
944+
hookEnv["NIX_DERIVATION_V4"] = drvJsonPath;
945+
946+
auto [hookStatus, lines] = runProgram(
947+
RunOptions{
948+
.program = settings.preBuildHook,
949+
.lookupPath = false,
950+
.args = getPreBuildHookArgs(),
951+
.environment = std::move(hookEnv),
952+
});
953+
if (!statusOk(hookStatus))
954+
throw ExecError(hookStatus, "pre-build hook '%1%' %2%", settings.preBuildHook, statusToString(hookStatus));
955+
935956
auto state = stBegin;
936-
auto lines = runProgram(settings.preBuildHook, false, getPreBuildHookArgs());
937957
auto lastPos = std::string::size_type{0};
938958
for (auto nlPos = lines.find('\n'); nlPos != std::string::npos; nlPos = lines.find('\n', lastPos)) {
939959
auto line = lines.substr(lastPos, nlPos - lastPos);

tests/functional/linux-sandbox.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,24 @@ nix-sandbox-build symlink-derivation.nix -A test_sandbox_paths \
102102
expectStderr 1 nix-sandbox-build --option extra-sandbox-paths '/does-not-exist' \
103103
-E 'with import '"${config_nix}"'; mkDerivation { name = "trivial"; buildCommand = "echo > $out"; }' |
104104
grepQuiet "path '/does-not-exist' is configured as part of the \`sandbox-paths\` option, but is inaccessible"
105+
106+
# Test pre-build-hook.
107+
DEST="$TEST_ROOT/hook-output"
108+
HOOK="$TEST_ROOT/pre-build-hook"
109+
110+
echo foo > "$TEST_ROOT"/fnord
111+
112+
cat > "$HOOK" <<EOF
113+
#! $SHELL -e
114+
jq -r .env.name < "\$NIX_DERIVATION_V4" > "$DEST"
115+
echo "hello from hook!" >&2
116+
echo "extra-sandbox-paths"
117+
echo "/foo/bar=$TEST_ROOT/fnord"
118+
EOF
119+
chmod +x "$HOOK"
120+
121+
outPath=$(nix-build --no-out-link --sandbox-paths /nix/store --pre-build-hook "$HOOK" symlink-derivation.nix -A test_sandbox_paths_2)
122+
123+
[[ $(cat "$TEST_ROOT/store0/nix/store/$(basename "$outPath")/xyzzy") = foo ]]
124+
125+
[[ "$(cat "$DEST")" == "test-sandbox-paths-2" ]]

tests/functional/symlink-derivation.nix

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,12 @@ in
5656
touch $out
5757
'';
5858
};
59+
60+
test_sandbox_paths_2 = mkDerivation {
61+
name = "test-sandbox-paths-2";
62+
buildCommand = ''
63+
mkdir $out
64+
cat /foo/bar > $out/xyzzy
65+
'';
66+
};
5967
}

0 commit comments

Comments
 (0)