2023-05-08 23:00:47 +03:00
|
|
|
{ busybox, seed }:
|
2023-05-08 21:47:39 +03:00
|
|
|
|
|
|
|
with import ./config.nix;
|
|
|
|
|
|
|
|
let
|
|
|
|
contentAddressedByDefault = builtins.getEnv "NIX_TESTS_CA_BY_DEFAULT" == "1";
|
|
|
|
caArgs = if contentAddressedByDefault then {
|
|
|
|
__contentAddressed = true;
|
|
|
|
outputHashMode = "recursive";
|
|
|
|
outputHashAlgo = "sha256";
|
|
|
|
} else {};
|
|
|
|
|
|
|
|
mkDerivation = args:
|
|
|
|
derivation ({
|
|
|
|
inherit system;
|
|
|
|
builder = busybox;
|
structured attrs: improve support / usage of NIX_ATTRS_{SH,JSON}_FILE
In #4770 I implemented proper `nix-shell(1)` support for derivations
using `__structuredAttrs = true;`. Back then we decided to introduce two
new environment variables, `NIX_ATTRS_SH_FILE` for `.attrs.sh` and
`NIX_ATTRS_JSON_FILE` for `.attrs.json`. This was to avoid having to
copy these files to `$NIX_BUILD_TOP` in a `nix-shell(1)` session which
effectively meant copying these files to the project dir without
cleaning up afterwords[1].
On last NixCon I resumed hacking on `__structuredAttrs = true;` by
default for `nixpkgs` with a few other folks and getting back to it,
I identified a few problems with the how it's used in `nixpkgs`:
* A lot of builders in `nixpkgs` don't care about the env vars and
assume that `.attrs.sh` and `.attrs.json` are in `$NIX_BUILD_TOP`.
The sole reason why this works is that `nix-shell(1)` sources
the contents of `.attrs.sh` and then sources `$stdenv/setup` if it
exists. This may not be pretty, but it mostly works. One notable
difference when using nixpkgs' stdenv as of now is however that
`$__structuredAttrs` is set to `1` on regular builds, but set to
an empty string in a shell session.
Also, `.attrs.json` cannot be used in shell sessions because
it can only be accessed by `$NIX_ATTRS_JSON_FILE` and not by
`$NIX_BUILD_TOP/.attrs.json`.
I considered changing Nix to be compatible with what nixpkgs
effectively does, but then we'd have to either move $NIX_BUILD_TOP for
shell sessions to a temporary location (and thus breaking a lot of
assumptions) or we'd reintroduce all the problems we solved back then
by using these two env vars.
This is partly because I didn't document these variables back
then (mea culpa), so I decided to drop all mentions of
`.attrs.{json,sh}` in the manual and only refer to `$NIX_ATTRS_SH_FILE`
and `$NIX_ATTRS_JSON_FILE`. The same applies to all our integration tests.
Theoretically we could deprecated using `"$NIX_BUILD_TOP"/.attrs.sh` in
the future now.
* `nix develop` and `nix print-dev-env` don't support this environment
variable at all even though they're supposed to be part of the replacement
for `nix-shell` - for the drv debugging part to be precise.
This isn't a big deal for the vast majority of derivations, i.e.
derivations relying on nixpkgs' `stdenv` wiring things together
properly. This is because `nix develop` effectively "clones" the
derivation and replaces the builder with a script that dumps all of
the environment, shell variables, functions etc, so the state of
structured attrs being "sourced" is transmitted into the dev shell and
most of the time you don't need to worry about `.attrs.sh` not
existing because the shell is correctly configured and the
if [ -e .attrs.sh ]; then source .attrs.sh; fi
is simply omitted.
However, this will break when having a derivation that reads e.g. from
`.attrs.json` like
with import <nixpkgs> {};
runCommand "foo" { __structuredAttrs = true; foo.bar = 23; } ''
cat $NIX_ATTRS_JSON_FILE # doesn't work because it points to /build/.attrs.json
''
To work around this I employed a similar approach as it exists for
`nix-shell`: the `NIX_ATTRS_{JSON,SH}_FILE` vars are replaced with
temporary locations.
The contents of `.attrs.sh` and `.attrs.json` are now written into the
JSON by `get-env.sh`, the builder that `nix develop` injects into the
derivation it's debugging. So finally the exact file contents are
present and exported by `nix develop`.
I also made `.attrs.json` a JSON string in the JSON printed by
`get-env.sh` on purpose because then it's not necessary to serialize
the object structure again. `nix develop` only needs the JSON
as string because it's only written into the temporary file.
I'm not entirely sure if it makes sense to also use a temporary
location for `nix print-dev-env` (rather than just skipping the
rewrite in there), but this would probably break certain cases where
it's relied upon `$NIX_ATTRS_SH_FILE` to exist (prime example are the
`nix print-dev-env` test-cases I wrote in this patch using
`tests/shell.nix`, these would fail because the env var exists, but it
cannot read from it).
[1] https://github.com/NixOS/nix/pull/4770#issuecomment-836799719
2023-09-24 14:19:04 +03:00
|
|
|
args = ["sh" "-e" args.builder or (builtins.toFile "builder-${args.name}.sh" ''
|
|
|
|
if [ -e "$NIX_ATTRS_SH_FILE" ]; then source $NIX_ATTRS_SH_FILE; fi;
|
|
|
|
eval "$buildCommand"
|
|
|
|
'')];
|
2023-05-08 21:47:39 +03:00
|
|
|
} // removeAttrs args ["builder" "meta" "passthru"]
|
|
|
|
// caArgs)
|
|
|
|
// { meta = args.meta or {}; passthru = args.passthru or {}; };
|
|
|
|
|
|
|
|
input1 = mkDerivation {
|
|
|
|
shell = busybox;
|
2023-05-08 23:00:47 +03:00
|
|
|
name = "hermetic-input-1";
|
|
|
|
buildCommand = "echo hi-input1 seed=${toString seed}; echo FOO > $out";
|
2023-05-08 21:47:39 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
input2 = mkDerivation {
|
|
|
|
shell = busybox;
|
2023-05-08 23:00:47 +03:00
|
|
|
name = "hermetic-input-2";
|
2023-05-08 21:47:39 +03:00
|
|
|
buildCommand = "echo hi; echo BAR > $out";
|
|
|
|
};
|
|
|
|
|
|
|
|
input3 = mkDerivation {
|
|
|
|
shell = busybox;
|
2023-05-08 23:00:47 +03:00
|
|
|
name = "hermetic-input-3";
|
2023-05-08 21:47:39 +03:00
|
|
|
buildCommand = ''
|
|
|
|
echo hi-input3
|
|
|
|
read x < ${input2}
|
2023-07-25 18:44:39 +03:00
|
|
|
echo ${input2} $x BAZ > $out
|
2023-05-08 21:47:39 +03:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
in
|
|
|
|
|
|
|
|
mkDerivation {
|
|
|
|
shell = busybox;
|
2023-05-08 23:00:47 +03:00
|
|
|
name = "hermetic";
|
2023-05-08 21:47:39 +03:00
|
|
|
passthru = { inherit input1 input2 input3; };
|
|
|
|
buildCommand =
|
|
|
|
''
|
|
|
|
read x < ${input1}
|
|
|
|
read y < ${input3}
|
2023-07-25 18:44:39 +03:00
|
|
|
echo ${input1} ${input3} "$x $y" > $out
|
2023-05-08 21:47:39 +03:00
|
|
|
'';
|
|
|
|
}
|