Currently srcOnly assumes that it can pass drv.drvAttrs to
drv.stdenv.mkDerivation and obtain basically the same resulting
derivation, i.e. that drvAttrs and the arguments passed to
stdenv.mkDerivation are equivalent.
It is obvious, that stdenv.mkDerivation may at any point violate this
assumption. Currently, there are two (known) problems stemming from this
assumption affecting srcOnly:
- If __structuredAttrs = true, drvAttrs will contain the env attribute
set as passed to stdenv.mkDerivation as well as its members at the
top level like they need to be passed to builtins.derivation.
If such an attribute set is passed to stdenv.mkDerivation again,
it triggers its consistency check implemented in #332750.
This affects e.g. pkgs.git since 318b8c61bd.
- The use of stdenv adapters that modify the env attribute set
(like withCFlags) causes another issue. In such cases, the
effect of the adapter, e.g. setting env.NIX_CFLAGS_COMPILE
can be observed as drvAttrs.NIX_CFLAGS_COMPILE. Without
__structuredAttrs, drvAttrs.env.NIX_CFLAGS_COMPILE would
not be set.
However, because srcOnly dutifully uses the same stdenv as the
original derivation, the stdenv adapter will be applied to the
derivation constructed by srcOnly as well. Because it can't tell that
NIX_CFLAGS_COMPILE was set by the adapter, it'll pass it to
stdenv.mkDerivation. Unaware of this, the stdenv adapter is applied
again and sets env.NIX_CFLAGS_COMPILE, triggering the same consistency
check as above.
tests.srcOnly now also checks that both these issues have been fixed in
srcOnly.
The solution to this is to change the derivation instead of
reconstructing it. Since srcOnly assumes that the input derivation is
based on stdenv.mkDerivation anyways, we are entitled to take advantage
of overrideAttrs. This enables us to see the (effective) arguments
passed to stdenv.mkDerivation via prevAttrs -- before any duplication
between env and the top level happens. We are also guaranteed that the
stdenv adapters are applied only once.
Resolves#269539.
Note that this commit passes the tests.srcOnly test suite both before
and after the change to getEquivAttrs, i.e. that test suite change may
be rebased out or applied after this commit.
The ability to use srcOnly on derivations and as a builder can be
formulated like this: Given a derivation `drv` with the expression:
stdenv.mkDerivation {
name = "drv";
…
}
We can transform it to
srcOnly {
stdenv = stdenv;
name = "drv";
…
}
and expect to get the same result as `srcOnly drv`.
This commit changes tests.srcOnly to test this assumption. The
arguments effectively passed to mkDerivation are computed using
getEquivAttrs which then also records the used stdenv for the benefit
of srcOnly.
This is better than using drvAttrs like before because there is actually
no guarantee that drvAttrs is the same as what was passed to
stdenv.mkDerivation. mkDerivation may transform arguments before passing
them on to builtins.derivation. For example, it performs extra
checks on `env` as well as consistency checks with the top level
argument. This can even lead to issues with srcOnly:
https://github.com/NixOS/nixpkgs/issues/269539
Furthermore, the drvAttrs check really only checks something that is
practically statically guaranteed by srcOnly internals before this
commit (assuming that drvAttrs doesn't contain an attribute also named
drvAttrs):
args = attrs.drvAttrs or attrs;
This makes the test more portable, as glibc does not evaluate on
all platforms.
Unfortunately the test fails on darwin for an unrelated reason.
__impureHostDeps values were duplicated.