6 # Lib attributes are inherited to the lexical scope for performance reasons.
42 inherit (import ../../build-support/lib/cmake.nix { inherit lib stdenv; }) makeCMakeFlags;
43 inherit (import ../../build-support/lib/meson.nix { inherit lib stdenv; }) makeMesonFlags;
47 if builtins.isFunction fnOrAttrs
48 then makeDerivationExtensible fnOrAttrs
49 else makeDerivationExtensibleConst fnOrAttrs;
51 checkMeta = import ./check-meta.nix {
53 # Nix itself uses the `system` field of a derivation to decide where
54 # to build it. This is a bit confusing for cross compilation.
55 inherit (stdenv) hostPlatform;
58 # Based off lib.makeExtensible, with modifications:
59 makeDerivationExtensible = rattrs:
61 # NOTE: The following is a hint that will be printed by the Nix cli when
62 # encountering an infinite recursion. It must not be formatted into
63 # separate lines, because Nix would only show the last line of the comment.
65 # An infinite recursion here can be caused by having the attribute names of expression `e` in `.overrideAttrs(finalAttrs: previousAttrs: e)` depend on `finalAttrs`. Only the attribute values of `e` can depend on `finalAttrs`.
66 args = rattrs (args // { inherit finalPackage overrideAttrs; });
72 # Convert f0 to an overlay. Legacy is:
73 # overrideAttrs (super: {})
74 # We want to introduce self. We follow the convention of overlays:
75 # overrideAttrs (self: super: {})
76 # Which means the first parameter can be either self or super.
77 # This is surprising, but far better than the confusion that would
78 # arise from flipping an overlay's parameters in some cases.
81 if builtins.isFunction x
83 # Can't reuse `x`, because `self` comes first.
84 # Looks inefficient, but `f0 super` was a cheap thunk.
88 makeDerivationExtensible
89 (self: let super = rattrs self; in super // (if builtins.isFunction f0 || f0?__functor then f self super else f0));
92 mkDerivationSimple overrideAttrs args;
96 #makeDerivationExtensibleConst = attrs: makeDerivationExtensible (_: attrs);
97 # but pre-evaluated for a slight improvement in performance.
98 makeDerivationExtensibleConst = attrs:
105 if builtins.isFunction x
110 makeDerivationExtensible (self: attrs // (if builtins.isFunction f0 || f0?__functor then f self attrs else f0)))
113 knownHardeningFlags = [
127 removedOrReplacedAttrNames = [
128 "checkInputs" "installCheckInputs"
129 "nativeCheckInputs" "nativeInstallCheckInputs"
131 "__darwinAllowLocalNetworking"
132 "__impureHostDeps" "__propagatedImpureHostDeps"
133 "sandboxProfile" "propagatedSandboxProfile"
136 # Turn a derivation into its outPath without a string context attached.
137 # See the comment at the usage site.
138 unsafeDerivationToUntrackedOutpath = drv:
140 then builtins.unsafeDiscardStringContext drv.outPath
143 makeDerivationArgument =
146 # `makeDerivationArgument` is responsible for the `mkDerivation` arguments that
147 # affect the actual derivation, excluding a few behaviors that are not
148 # essential, and specific to `mkDerivation`: `env`, `cmakeFlags`, `mesonFlags`.
152 # * https://nixos.org/nixpkgs/manual/#sec-using-stdenv
153 # Details on how to use this mkDerivation function
155 # * https://nixos.org/manual/nix/stable/expressions/derivations.html#derivations
156 # Explanation about derivations in general
159 # These types of dependencies are all exhaustively documented in
160 # the "Specifying Dependencies" section of the "Standard
161 # Environment" chapter of the Nixpkgs manual.
163 # TODO(@Ericson2314): Stop using legacy dep attribute names
165 # host offset -> target offset
166 depsBuildBuild ? [] # -1 -> -1
167 , depsBuildBuildPropagated ? [] # -1 -> -1
168 , nativeBuildInputs ? [] # -1 -> 0 N.B. Legacy name
169 , propagatedNativeBuildInputs ? [] # -1 -> 0 N.B. Legacy name
170 , depsBuildTarget ? [] # -1 -> 1
171 , depsBuildTargetPropagated ? [] # -1 -> 1
173 , depsHostHost ? [] # 0 -> 0
174 , depsHostHostPropagated ? [] # 0 -> 0
175 , buildInputs ? [] # 0 -> 1 N.B. Legacy name
176 , propagatedBuildInputs ? [] # 0 -> 1 N.B. Legacy name
178 , depsTargetTarget ? [] # 1 -> 1
179 , depsTargetTargetPropagated ? [] # 1 -> 1
182 , installCheckInputs ? []
183 , nativeCheckInputs ? []
184 , nativeInstallCheckInputs ? []
187 , configureFlags ? []
188 , # Target is not included by default because most programs don't care.
189 # Including it then would cause needless mass rebuilds.
191 # TODO(@Ericson2314): Make [ "build" "host" ] always the default / resolve #87909
192 configurePlatforms ? optionals
193 (stdenv.hostPlatform != stdenv.buildPlatform || config.configurePlatformsByDefault)
196 # TODO(@Ericson2314): Make unconditional / resolve #33599
198 , doCheck ? config.doCheckByDefault or false
200 # TODO(@Ericson2314): Make unconditional / resolve #33599
202 , doInstallCheck ? config.doCheckByDefault or false
204 , # TODO(@Ericson2314): Make always true and remove / resolve #178468
205 strictDeps ? if config.strictDepsByDefault then true else stdenv.hostPlatform != stdenv.buildPlatform
207 , enableParallelBuilding ? config.enableParallelBuildingByDefault
209 , separateDebugInfo ? false
210 , outputs ? [ "out" ]
211 , __darwinAllowLocalNetworking ? false
212 , __impureHostDeps ? []
213 , __propagatedImpureHostDeps ? []
214 , sandboxProfile ? ""
215 , propagatedSandboxProfile ? ""
217 , hardeningEnable ? []
218 , hardeningDisable ? []
222 , __contentAddressed ?
223 (! attrs ? outputHash) # Fixed-output drvs can't be content addressed too
224 && config.contentAddressedByDefault
226 # Experimental. For simple packages mostly just works,
227 # but for anything complex, be prepared to debug if enabling.
228 , __structuredAttrs ? config.structuredAttrsByDefault or false
232 # Policy on acceptable hash types in nixpkgs
233 assert attrs ? outputHash -> (
235 attrs.outputHashAlgo or (head (splitString "-" attrs.outputHash));
237 if algo == "md5" then
238 throw "Rejected insecure ${algo} hash '${attrs.outputHash}'"
244 # TODO(@oxij, @Ericson2314): This is here to keep the old semantics, remove when
245 # no package has `doCheck = true`.
246 doCheck' = doCheck && stdenv.buildPlatform.canExecute stdenv.hostPlatform;
247 doInstallCheck' = doInstallCheck && stdenv.buildPlatform.canExecute stdenv.hostPlatform;
249 separateDebugInfo' = separateDebugInfo && stdenv.hostPlatform.isLinux;
250 outputs' = outputs ++ optional separateDebugInfo' "debug";
252 noNonNativeDeps = builtins.length (depsBuildTarget ++ depsBuildTargetPropagated
253 ++ depsHostHost ++ depsHostHostPropagated
254 ++ buildInputs ++ propagatedBuildInputs
255 ++ depsTargetTarget ++ depsTargetTargetPropagated) == 0;
256 dontAddHostSuffix = attrs ? outputHash && !noNonNativeDeps || !stdenv.hasCC;
258 hardeningDisable' = if any (x: x == "fortify") hardeningDisable
259 # disabling fortify implies fortify3 should also be disabled
260 then unique (hardeningDisable ++ [ "fortify3" ])
261 else hardeningDisable;
262 defaultHardeningFlags =
263 (if stdenv.hasCC then stdenv.cc else {}).defaultHardeningFlags or
264 # fallback safe-ish set of flags
265 (remove "pie" knownHardeningFlags);
266 enabledHardeningOptions =
267 if builtins.elem "all" hardeningDisable'
269 else subtractLists hardeningDisable' (defaultHardeningFlags ++ hardeningEnable);
270 # hardeningDisable additionally supports "all".
271 erroneousHardeningFlags = subtractLists knownHardeningFlags (hardeningEnable ++ remove "all" hardeningDisable);
273 checkDependencyList = checkDependencyList' [];
274 checkDependencyList' = positions: name: deps:
277 if isDerivation dep || dep == null || builtins.isString dep || builtins.isPath dep then dep
278 else if isList dep then checkDependencyList' ([index] ++ positions) name dep
279 else throw "Dependency is not of a valid type: ${concatMapStrings (ix: "element ${toString ix} of ") ([index] ++ positions)}${name} for ${attrs.name or attrs.pname}")
281 in if builtins.length erroneousHardeningFlags != 0
282 then abort ("mkDerivation was called with unsupported hardening flags: " + lib.generators.toPretty {} {
283 inherit erroneousHardeningFlags hardeningDisable hardeningEnable knownHardeningFlags;
287 doInstallCheck = doInstallCheck';
288 buildInputs' = buildInputs
289 ++ optionals doCheck checkInputs
290 ++ optionals doInstallCheck installCheckInputs;
291 nativeBuildInputs' = nativeBuildInputs
292 ++ optional separateDebugInfo' ../../build-support/setup-hooks/separate-debug-info.sh
293 ++ optional stdenv.hostPlatform.isWindows ../../build-support/setup-hooks/win-dll-link.sh
294 ++ optionals doCheck nativeCheckInputs
295 ++ optionals doInstallCheck nativeInstallCheckInputs;
301 (map (drv: getDev drv.__spliced.buildBuild or drv) (checkDependencyList "depsBuildBuild" depsBuildBuild))
302 (map (drv: getDev drv.__spliced.buildHost or drv) (checkDependencyList "nativeBuildInputs" nativeBuildInputs'))
303 (map (drv: getDev drv.__spliced.buildTarget or drv) (checkDependencyList "depsBuildTarget" depsBuildTarget))
306 (map (drv: getDev drv.__spliced.hostHost or drv) (checkDependencyList "depsHostHost" depsHostHost))
307 (map (drv: getDev drv.__spliced.hostTarget or drv) (checkDependencyList "buildInputs" buildInputs'))
310 (map (drv: getDev drv.__spliced.targetTarget or drv) (checkDependencyList "depsTargetTarget" depsTargetTarget))
313 propagatedDependencies = [
315 (map (drv: getDev drv.__spliced.buildBuild or drv) (checkDependencyList "depsBuildBuildPropagated" depsBuildBuildPropagated))
316 (map (drv: getDev drv.__spliced.buildHost or drv) (checkDependencyList "propagatedNativeBuildInputs" propagatedNativeBuildInputs))
317 (map (drv: getDev drv.__spliced.buildTarget or drv) (checkDependencyList "depsBuildTargetPropagated" depsBuildTargetPropagated))
320 (map (drv: getDev drv.__spliced.hostHost or drv) (checkDependencyList "depsHostHostPropagated" depsHostHostPropagated))
321 (map (drv: getDev drv.__spliced.hostTarget or drv) (checkDependencyList "propagatedBuildInputs" propagatedBuildInputs))
324 (map (drv: getDev drv.__spliced.targetTarget or drv) (checkDependencyList "depsTargetTargetPropagated" depsTargetTargetPropagated))
329 removeAttrs attrs removedOrReplacedAttrNames
330 // (optionalAttrs (attrs ? name || (attrs ? pname && attrs ? version)) {
333 # Indicate the host platform of the derivation if cross compiling.
334 # Fixed-output derivations like source tarballs shouldn't get a host
335 # suffix. But we have some weird ones with run-time deps that are
336 # just used for their side-affects. Those might as well since the
337 # hash can't be the same. See #32986.
338 hostSuffix = optionalString
339 (stdenv.hostPlatform != stdenv.buildPlatform && !dontAddHostSuffix)
340 "-${stdenv.hostPlatform.config}";
342 # Disambiguate statically built packages. This was originally
343 # introduce as a means to prevent nix-env to get confused between
344 # nix and nixStatic. This should be also achieved by moving the
345 # hostSuffix before the version, so we could contemplate removing
347 staticMarker = optionalString stdenv.hostPlatform.isStatic "-static";
349 lib.strings.sanitizeDerivationName (
351 then attrs.name + hostSuffix
353 # we cannot coerce null to a string below
354 assert assertMsg (attrs ? version && attrs.version != null) "The ‘version’ attribute cannot be null.";
355 "${attrs.pname}${staticMarker}${hostSuffix}-${attrs.version}"
358 builder = attrs.realBuilder or stdenv.shell;
359 args = attrs.args or ["-e" (attrs.builder or ./default-builder.sh)];
362 # The `system` attribute of a derivation has special meaning to Nix.
363 # Derivations set it to choose what sort of machine could be used to
364 # execute the build, The build platform entirely determines this,
365 # indeed more finely than Nix knows or cares about. The `system`
366 # attribute of `buildPlatfom` matches Nix's degree of specificity.
368 inherit (stdenv.buildPlatform) system;
370 userHook = config.stdenv.userHook or null;
371 __ignoreNulls = true;
372 inherit __structuredAttrs strictDeps;
374 depsBuildBuild = elemAt (elemAt dependencies 0) 0;
375 nativeBuildInputs = elemAt (elemAt dependencies 0) 1;
376 depsBuildTarget = elemAt (elemAt dependencies 0) 2;
377 depsHostHost = elemAt (elemAt dependencies 1) 0;
378 buildInputs = elemAt (elemAt dependencies 1) 1;
379 depsTargetTarget = elemAt (elemAt dependencies 2) 0;
381 depsBuildBuildPropagated = elemAt (elemAt propagatedDependencies 0) 0;
382 propagatedNativeBuildInputs = elemAt (elemAt propagatedDependencies 0) 1;
383 depsBuildTargetPropagated = elemAt (elemAt propagatedDependencies 0) 2;
384 depsHostHostPropagated = elemAt (elemAt propagatedDependencies 1) 0;
385 propagatedBuildInputs = elemAt (elemAt propagatedDependencies 1) 1;
386 depsTargetTargetPropagated = elemAt (elemAt propagatedDependencies 2) 0;
388 # This parameter is sometimes a string, sometimes null, and sometimes a list, yuck
391 ++ optional (elem "build" configurePlatforms) "--build=${stdenv.buildPlatform.config}"
392 ++ optional (elem "host" configurePlatforms) "--host=${stdenv.hostPlatform.config}"
393 ++ optional (elem "target" configurePlatforms) "--target=${stdenv.targetPlatform.config}";
397 inherit doCheck doInstallCheck;
400 } // optionalAttrs (__contentAddressed) {
401 inherit __contentAddressed;
402 # Provide default values for outputHashMode and outputHashAlgo because
403 # most people won't care about these anyways
404 outputHashAlgo = attrs.outputHashAlgo or "sha256";
405 outputHashMode = attrs.outputHashMode or "recursive";
406 } // optionalAttrs (enableParallelBuilding) {
407 inherit enableParallelBuilding;
408 enableParallelChecking = attrs.enableParallelChecking or true;
409 enableParallelInstalling = attrs.enableParallelInstalling or true;
410 } // optionalAttrs (hardeningDisable != [] || hardeningEnable != [] || stdenv.hostPlatform.isMusl) {
411 NIX_HARDENING_ENABLE = enabledHardeningOptions;
412 } // optionalAttrs (stdenv.hostPlatform.isx86_64 && stdenv.hostPlatform ? gcc.arch) {
413 requiredSystemFeatures = attrs.requiredSystemFeatures or [] ++ [ "gccarch-${stdenv.hostPlatform.gcc.arch}" ];
414 } // optionalAttrs (stdenv.buildPlatform.isDarwin) (
416 allDependencies = concatLists (concatLists dependencies);
417 allPropagatedDependencies = concatLists (concatLists propagatedDependencies);
419 computedSandboxProfile =
420 concatMap (input: input.__propagatedSandboxProfile or [])
421 (stdenv.extraNativeBuildInputs
422 ++ stdenv.extraBuildInputs
425 computedPropagatedSandboxProfile =
426 concatMap (input: input.__propagatedSandboxProfile or [])
427 allPropagatedDependencies;
429 computedImpureHostDeps =
430 unique (concatMap (input: input.__propagatedImpureHostDeps or [])
431 (stdenv.extraNativeBuildInputs
432 ++ stdenv.extraBuildInputs
433 ++ allDependencies));
435 computedPropagatedImpureHostDeps =
436 unique (concatMap (input: input.__propagatedImpureHostDeps or [])
437 allPropagatedDependencies);
439 inherit __darwinAllowLocalNetworking;
440 # TODO: remove `unique` once nix has a list canonicalization primitive
442 let profiles = [ stdenv.extraSandboxProfile ] ++ computedSandboxProfile ++ computedPropagatedSandboxProfile ++ [ propagatedSandboxProfile sandboxProfile ];
443 final = concatStringsSep "\n" (filter (x: x != "") (unique profiles));
445 __propagatedSandboxProfile = unique (computedPropagatedSandboxProfile ++ [ propagatedSandboxProfile ]);
446 __impureHostDeps = computedImpureHostDeps ++ computedPropagatedImpureHostDeps ++ __propagatedImpureHostDeps ++ __impureHostDeps ++ stdenv.__extraImpureHostDeps ++ [
452 __propagatedImpureHostDeps = computedPropagatedImpureHostDeps ++ __propagatedImpureHostDeps;
454 # If we use derivations directly here, they end up as build-time dependencies.
455 # This is especially problematic in the case of disallowed*, since the disallowed
456 # derivations will be built by nix as build-time dependencies, while those
457 # derivations might take a very long time to build, or might not even build
458 # successfully on the platform used.
459 # We can improve on this situation by instead passing only the outPath,
460 # without an attached string context, to nix. The out path will be a placeholder
461 # which will be replaced by the actual out path if the derivation in question
462 # is part of the final closure (and thus needs to be built). If it is not
463 # part of the final closure, then the placeholder will be passed along,
464 # but in that case we know for a fact that the derivation is not part of the closure.
465 # This means that passing the out path to nix does the right thing in either
466 # case, both for disallowed and allowed references/requisites, and we won't
467 # build the derivation if it wouldn't be part of the closure, saving time and resources.
468 # While the problem is less severe for allowed*, since we want the derivation
469 # to be built eventually, we would still like to get the error early and without
470 # having to wait while nix builds a derivation that might not be used.
471 # See also https://github.com/NixOS/nix/issues/4629
472 optionalAttrs (attrs ? disallowedReferences) {
473 disallowedReferences =
474 map unsafeDerivationToUntrackedOutpath attrs.disallowedReferences;
476 optionalAttrs (attrs ? disallowedRequisites) {
477 disallowedRequisites =
478 map unsafeDerivationToUntrackedOutpath attrs.disallowedRequisites;
480 optionalAttrs (attrs ? allowedReferences) {
482 mapNullable unsafeDerivationToUntrackedOutpath attrs.allowedReferences;
484 optionalAttrs (attrs ? allowedRequisites) {
486 mapNullable unsafeDerivationToUntrackedOutpath attrs.allowedRequisites;
492 mkDerivationSimple = overrideAttrs:
494 # `mkDerivation` wraps the builtin `derivation` function to
495 # produce derivations that use this stdenv and its shell.
497 # Internally, it delegates most of its behavior to `makeDerivationArgument`,
498 # except for the `env`, `cmakeFlags`, and `mesonFlags` attributes, as well
499 # as the attributes `meta` and `passthru` that affect [package attributes],
500 # and not the derivation itself.
504 # * https://nixos.org/nixpkgs/manual/#sec-using-stdenv
505 # Details on how to use this mkDerivation function
507 # * https://nixos.org/manual/nix/stable/expressions/derivations.html#derivations
508 # Explanation about derivations in general
510 # * [package attributes]: https://nixos.org/manual/nix/stable/glossary#package-attribute-set
519 , pos ? # position used in error messages and for meta.position
520 (if attrs.meta.description or null != null
521 then builtins.unsafeGetAttrPos "description" attrs.meta
522 else if attrs.version or null != null
523 then builtins.unsafeGetAttrPos "version" attrs
524 else builtins.unsafeGetAttrPos "name" attrs)
526 # Experimental. For simple packages mostly just works,
527 # but for anything complex, be prepared to debug if enabling.
528 , __structuredAttrs ? config.structuredAttrsByDefault or false
534 # Policy on acceptable hash types in nixpkgs
535 assert attrs ? outputHash -> (
537 attrs.outputHashAlgo or (head (splitString "-" attrs.outputHash));
539 if algo == "md5" then
540 throw "Rejected insecure ${algo} hash '${attrs.outputHash}'"
546 envIsExportable = isAttrs env && !isDerivation env;
548 derivationArg = makeDerivationArgument
551 (["meta" "passthru" "pos"]
552 ++ optional (__structuredAttrs || envIsExportable) "env"
554 // optionalAttrs __structuredAttrs { env = checkedEnv; }
556 cmakeFlags = makeCMakeFlags attrs;
557 mesonFlags = makeMesonFlags attrs;
560 meta = checkMeta.commonMeta {
561 inherit validity attrs pos;
562 references = attrs.nativeBuildInputs or [] ++ attrs.buildInputs or []
563 ++ attrs.propagatedNativeBuildInputs or [] ++ attrs.propagatedBuildInputs or [];
565 validity = checkMeta.assertValidity { inherit meta attrs; };
569 overlappingNames = attrNames (builtins.intersectAttrs env derivationArg);
571 assert assertMsg envIsExportable
572 "When using structured attributes, `env` must be an attribute set of environment variables.";
573 assert assertMsg (overlappingNames == [ ])
574 "The ‘env’ attribute set cannot contain any attributes passed to derivation. The following attributes are overlapping: ${concatStringsSep ", " overlappingNames}";
576 (n: v: assert assertMsg (isString v || isBool v || isInt v || isDerivation v)
577 "The ‘env’ attribute set can only contain derivation, string, boolean or integer attributes. The ‘${n}’ attribute is of type ${builtins.typeOf v}."; v)
580 # Fixed-output derivations may not reference other paths, which means that
581 # for a fixed-output derivation, the corresponding inputDerivation should
582 # *not* be fixed-output. To achieve this we simply delete the attributes that
583 # would make it fixed-output.
584 deleteFixedOutputRelatedAttrs = lib.flip builtins.removeAttrs [ "outputHashAlgo" "outputHash" "outputHashMode" ];
591 # A derivation that always builds successfully and whose runtime
592 # dependencies are the original derivations build time dependencies
593 # This allows easy building and distributing of all derivations
594 # needed to enter a nix-shell with
595 # nix-build shell.nix -A inputDerivation
596 inputDerivation = derivation (deleteFixedOutputRelatedAttrs derivationArg // {
597 # Add a name in case the original drv didn't have one
598 name = derivationArg.name or "inputDerivation";
599 # This always only has one output
602 # Propagate the original builder and arguments, since we override
603 # them and they might contain references to build inputs
604 _derivation_original_builder = derivationArg.builder;
605 _derivation_original_args = derivationArg.args;
607 builder = stdenv.shell;
608 # The bash builtin `export` dumps all current environment variables,
609 # which is where all build input references end up (e.g. $PATH for
610 # binaries). By writing this to $out, Nix can find and register
611 # them as runtime dependencies (since Nix greps for store paths
612 # through $out to find them)
615 for var in $passAsFile; do
616 pathVar="''${var}Path"
617 printf "%s" "$(< "''${!pathVar}")" >> $out
621 # inputDerivation produces the inputs; not the outputs, so any
622 # restrictions on what used to be the outputs don't serve a purpose
624 allowedReferences = null;
625 allowedRequisites = null;
626 disallowedReferences = [ ];
627 disallowedRequisites = [ ];
630 inherit passthru overrideAttrs;
633 # Pass through extra attributes that are not inputs, but
634 # should be made available to Nix expressions using the
635 # derivation (e.g., in assertions).
637 (derivation (derivationArg // optionalAttrs envIsExportable checkedEnv));
641 inherit mkDerivation;