Skip to content
20 changes: 15 additions & 5 deletions lib/customisation.nix
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ rec {
overrideDerivation = drv: f:
let
newDrv = derivation (drv.drvAttrs // (f drv));
in addPassthru newDrv (
in lib.flip (extendDerivation true) newDrv (
{ meta = drv.meta or {};
passthru = if drv ? passthru then drv.passthru else {};
}
Expand Down Expand Up @@ -131,8 +131,8 @@ rec {


/* Add attributes to each output of a derivation without changing
the derivation itself. */
addPassthru = drv: passthru:
the derivation itself and check a given condition when evaluating. */
extendDerivation = condition: passthru: drv:
let
outputs = drv.outputs or [ "out" ];

Expand All @@ -142,13 +142,23 @@ rec {
outputToAttrListElement = outputName:
{ name = outputName;
value = commonAttrs // {
inherit (drv.${outputName}) outPath drvPath type outputName;
inherit (drv.${outputName}) type outputName;
drvPath = assert condition; drv.${outputName}.drvPath;
outPath = assert condition; drv.${outputName}.outPath;
};
};

outputsList = map outputToAttrListElement outputs;
in commonAttrs // { outputUnspecified = true; };
in commonAttrs // {
outputUnspecified = true;
drvPath = assert condition; drv.drvPath;
outPath = assert condition; drv.outPath;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

follow-up: I think exposing the condition here might be helpful in the future as a way to filter out bad packages from the input lists, such as preventing X libraries to be used.

Note, In the case of check-meta.nix, this assert condition; statement is only used to enforce the strictness of the condition, as it will throw before the assertion can catch it. There is no proper false value returned, unless the config.handleEvalIssue function is set to return it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check-meta.nix will throw before the assertion can catch it

check-meta.nix is being changed in this PR to return a boolean.

};

/* Add attributes to each output of a derivation without changing
the derivation itself. */
addPassthru = lib.warn "`addPassthru` is deprecated, replace with `extendDerivation true`"
(extendDerivation true);

/* Strip a derivation of all non-essential attributes, returning
only those needed by hydra-eval-jobs. Also strictly evaluate the
Expand Down
3 changes: 2 additions & 1 deletion lib/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ let
inherit (stringsWithDeps) textClosureList textClosureMap
noDepEntry fullDepEntry packEntry stringAfter;
inherit (customisation) overrideDerivation makeOverridable
callPackageWith callPackagesWith addPassthru hydraJob makeScope;
callPackageWith callPackagesWith extendDerivation addPassthru
hydraJob makeScope;
inherit (meta) addMetaAttrs dontDistribute setName updateName
appendToName mapDerivationAttrset lowPrio lowPrioSet hiPrio
hiPrioSet;
Expand Down
8 changes: 5 additions & 3 deletions pkgs/os-specific/linux/kernel/generic.nix
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,12 @@ let
passthru = kernel.passthru // (removeAttrs passthru [ "passthru" ]);
};

nativeDrv = lib.addPassthru kernel.nativeDrv passthru;
addPassthru' = lib.extendDerivation true passthru;

crossDrv = lib.addPassthru kernel.crossDrv passthru;
nativeDrv = addPassthru' kernel.nativeDrv;

crossDrv = addPassthru' kernel.crossDrv;

in if kernel ? crossDrv
then nativeDrv // { inherit nativeDrv crossDrv; }
else lib.addPassthru kernel passthru
else addPassthru' kernel
23 changes: 11 additions & 12 deletions pkgs/stdenv/generic/check-meta.nix
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Extend a derivation with checks for brokenness, license, etc. Throw a
# descriptive error when the check fails; return `derivationArg` otherwise.
# Note: no dependencies are checked in this step.
# Checks derivation meta and attrs for problems (like brokenness,
# licenses, etc).

{ lib, config, system, meta, derivationArg, mkDerivationArg }:

Expand Down Expand Up @@ -154,12 +153,14 @@ let

# Weirder stuff that doesn't appear in the documentation?
knownVulnerabilities = listOf str;
name = str;
version = str;
tag = str;
updateWalker = bool;
executables = listOf str;
outputsToInstall = listOf str;
position = str;
evaluates = bool;
repositories = attrsOf str;
isBuildPythonPackage = platforms;
schedulingPriority = str;
Expand Down Expand Up @@ -196,13 +197,11 @@ let
{ valid = false; reason = "unknown-meta"; errormsg = "has an invalid meta attrset:${lib.concatMapStrings (x: "\n\t - " + x) res}"; }
else { valid = true; };

validity = checkValidity attrs;

in validity // {
# Throw an error if trying to evaluate an non-valid derivation
validityCondition =
let v = checkValidity attrs;
in if !v.valid
then handleEvalIssue (removeAttrs v ["valid"])
else true;

in
assert validityCondition;
derivationArg
handled = if !validity.valid
then handleEvalIssue (removeAttrs validity ["valid"])
else true;
}
75 changes: 47 additions & 28 deletions pkgs/stdenv/generic/make-derivation.nix
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ rec {
inherit erroneousHardeningFlags hardeningDisable hardeningEnable supportedHardeningFlags;
})
else let
references = nativeBuildInputs ++ buildInputs
++ propagatedNativeBuildInputs ++ propagatedBuildInputs;

dependencies = map (map lib.chooseDevOutputs) [
[
(map (drv: drv.__spliced.buildBuild or drv) depsBuildBuild)
Expand Down Expand Up @@ -131,9 +134,12 @@ rec {
(lib.concatLists propagatedDependencies));
in
{
name = name + lib.optionalString
# A hack to make `nix-env -qa` and `nix search` ignore broken packages.
# TODO(@oxij): remove this assert when something like NixOS/nix#1771 gets merged into nix.
name = assert validity.handled; name + lib.optionalString
(stdenv.hostPlatform != stdenv.buildPlatform)
("-" + stdenv.hostPlatform.config);

builder = attrs.realBuilder or stdenv.shell;
args = attrs.args or ["-e" (attrs.builder or ./default-builder.sh)];
inherit stdenv;
Expand Down Expand Up @@ -182,46 +188,59 @@ rec {
outputs = outputs';
} else { }));

validity = import ./check-meta.nix {
inherit lib config meta derivationArg;
mkDerivationArg = attrs;
# Nix itself uses the `system` field of a derivation to decide where
# to build it. This is a bit confusing for cross compilation.
inherit (stdenv) system;
};

# The meta attribute is passed in the resulting attribute set,
# but it's not part of the actual derivation, i.e., it's not
# passed to the builder and is not a dependency. But since we
# include it in the result, it *is* available to nix-env for queries.
meta = { }
meta = {
# `name` above includes cross-compilation cruft (and is under assert),
# lets have a clean always accessible version here.
inherit name;

# If the packager hasn't specified `outputsToInstall`, choose a default,
# which is the name of `p.bin or p.out or p`;
# if he has specified it, it will be overridden below in `// meta`.
# Note: This default probably shouldn't be globally configurable.
# Services and users should specify outputs explicitly,
# unless they are comfortable with this default.
// { outputsToInstall =
let
outs = outputs'; # the value passed to derivation primitive
hasOutput = out: builtins.elem out outs;
in [( lib.findFirst hasOutput null (["bin" "out"] ++ outs) )];
outputsToInstall =
let
outs = outputs'; # the value passed to derivation primitive
hasOutput = out: builtins.elem out outs;
in [( lib.findFirst hasOutput null (["bin" "out"] ++ outs) )];
}
// attrs.meta or {}
# Fill `meta.position` to identify the source location of the package.
// lib.optionalAttrs (pos != null)
{ position = pos.file + ":" + toString pos.line; }
;
# Fill `meta.position` to identify the source location of the package.
// lib.optionalAttrs (pos != null) {
position = pos.file + ":" + toString pos.line;
# Expose the result of the checks for everyone to see.
} // {
evaluates = validity.valid
&& (if config.checkMetaRecursively or false
then lib.all (d: d.meta.evaluates or true) references
else true);
};

in

lib.addPassthru
(derivation (import ./check-meta.nix
{
inherit lib config meta derivationArg;
mkDerivationArg = attrs;
# Nix itself uses the `system` field of a derivation to decide where
# to build it. This is a bit confusing for cross compilation.
inherit (stdenv) system;
}))
( {
overrideAttrs = f: mkDerivation (attrs // (f attrs));
inherit meta passthru;
} //
# Pass through extra attributes that are not inputs, but
# should be made available to Nix expressions using the
# derivation (e.g., in assertions).
passthru);
lib.extendDerivation
validity.handled
({
overrideAttrs = f: mkDerivation (attrs // (f attrs));
inherit meta passthru;
} //
# Pass through extra attributes that are not inputs, but
# should be made available to Nix expressions using the
# derivation (e.g., in assertions).
passthru)
(derivation derivationArg);

}