Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1{ lib, config }:
2
3stdenv:
4
5let
6 # Lib attributes are inherited to the lexical scope for performance reasons.
7 inherit (lib)
8 any
9 assertMsg
10 attrNames
11 boolToString
12 concatLists
13 concatMap
14 concatMapStrings
15 concatStringsSep
16 elem
17 elemAt
18 extendDerivation
19 filter
20 findFirst
21 getDev
22 head
23 imap1
24 isAttrs
25 isBool
26 isDerivation
27 isInt
28 isList
29 isString
30 mapAttrs
31 mapNullable
32 optional
33 optionalAttrs
34 optionalString
35 optionals
36 pipe
37 remove
38 splitString
39 subtractLists
40 toFunction
41 unique
42 zipAttrsWith
43 ;
44
45 inherit (import ../../build-support/lib/cmake.nix { inherit lib stdenv; }) makeCMakeFlags;
46 inherit (import ../../build-support/lib/meson.nix { inherit lib stdenv; }) makeMesonFlags;
47
48 /**
49 This function creates a derivation, and returns it in the form of a [package attribute set](https://nix.dev/manual/nix/latest/glossary#package-attribute-set)
50 that refers to the derivation's outputs.
51
52 `mkDerivation` takes many argument attributes, most of which affect the derivation environment,
53 but [`meta`](#chap-meta) and [`passthru`](#var-stdenv-passthru) only directly affect package attributes.
54
55 The `mkDerivation` argument attributes can be made to refer to one another by passing a function to `mkDerivation`.
56 See [Fixed-point argument of `mkDerivation`](#mkderivation-recursive-attributes).
57
58 Reference documentation see: https://nixos.org/manual/nixpkgs/stable/#sec-using-stdenv
59
60 :::{.note}
61 This is used as the fundamental building block of most other functions in Nixpkgs for creating derivations.
62
63 Most arguments are also passed through to the underlying call of [`builtins.derivation`](https://nixos.org/manual/nix/stable/language/derivations).
64 :::
65 */
66 mkDerivation = fnOrAttrs: makeDerivationExtensible (toFunction fnOrAttrs);
67
68 checkMeta = import ./check-meta.nix {
69 inherit lib config;
70 # Nix itself uses the `system` field of a derivation to decide where
71 # to build it. This is a bit confusing for cross compilation.
72 inherit (stdenv) hostPlatform;
73 };
74
75 # Based off lib.makeExtensible, with modifications:
76 makeDerivationExtensible =
77 rattrs:
78 let
79 # NOTE: The following is a hint that will be printed by the Nix cli when
80 # encountering an infinite recursion. It must not be formatted into
81 # separate lines, because Nix would only show the last line of the comment.
82
83 # 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`.
84 args = rattrs (args // { inherit finalPackage overrideAttrs; });
85 # ^^^^
86
87 overrideAttrs =
88 f0:
89 let
90 extends' =
91 overlay: f:
92 (
93 final:
94 let
95 prev = f final;
96 thisOverlay = overlay final prev;
97 warnForBadVersionOverride = (
98 thisOverlay ? version
99 && prev ? version
100 # We could check that the version is actually distinct, but that
101 # would probably just delay the inevitable, or preserve tech debt.
102 # && prev.version != thisOverlay.version
103 && !(thisOverlay ? src)
104 && !(thisOverlay.__intentionallyOverridingVersion or false)
105 );
106 pname = args.pname or "<unknown name>";
107 version = args.version or "<unknown version>";
108 pos = builtins.unsafeGetAttrPos "version" thisOverlay;
109 in
110 lib.warnIf warnForBadVersionOverride ''
111 ${
112 args.name or "${pname}-${version}"
113 } was overridden with `version` but not `src` at ${pos.file or "<unknown file>"}:${
114 builtins.toString pos.line or "<unknown line>"
115 }:${builtins.toString pos.column or "<unknown column>"}.
116
117 This is most likely not what you want. In order to properly change the version of a package, override
118 both the `version` and `src` attributes:
119
120 hello.overrideAttrs (oldAttrs: rec {
121 version = "1.0.0";
122 src = pkgs.fetchurl {
123 url = "mirror://gnu/hello/hello-''${version}.tar.gz";
124 hash = "...";
125 };
126 })
127
128 (To silence this warning, set `__intentionallyOverridingVersion = true` in your `overrideAttrs` call.)
129 '' (prev // (builtins.removeAttrs thisOverlay [ "__intentionallyOverridingVersion" ]))
130 );
131 in
132 makeDerivationExtensible (extends' (lib.toExtension f0) rattrs);
133
134 finalPackage = mkDerivationSimple overrideAttrs args;
135
136 in
137 finalPackage;
138
139 knownHardeningFlags = [
140 "bindnow"
141 "format"
142 "fortify"
143 "fortify3"
144 "strictflexarrays1"
145 "strictflexarrays3"
146 "shadowstack"
147 "nostrictaliasing"
148 "pacret"
149 "pic"
150 "pie"
151 "relro"
152 "stackprotector"
153 "stackclashprotection"
154 "strictoverflow"
155 "trivialautovarinit"
156 "zerocallusedregs"
157 ];
158
159 removedOrReplacedAttrNames = [
160 "checkInputs"
161 "installCheckInputs"
162 "nativeCheckInputs"
163 "nativeInstallCheckInputs"
164 "__contentAddressed"
165 "__darwinAllowLocalNetworking"
166 "__impureHostDeps"
167 "__propagatedImpureHostDeps"
168 "sandboxProfile"
169 "propagatedSandboxProfile"
170 "disallowedReferences"
171 "disallowedRequisites"
172 "allowedReferences"
173 "allowedRequisites"
174 ];
175
176 # Turn a derivation into its outPath without a string context attached.
177 # See the comment at the usage site.
178 unsafeDerivationToUntrackedOutpath =
179 drv:
180 if isDerivation drv && (!drv.__contentAddressed or false) then
181 builtins.unsafeDiscardStringContext drv.outPath
182 else
183 drv;
184
185 makeOutputChecks =
186 attrs:
187 # If we use derivations directly here, they end up as build-time dependencies.
188 # This is especially problematic in the case of disallowed*, since the disallowed
189 # derivations will be built by nix as build-time dependencies, while those
190 # derivations might take a very long time to build, or might not even build
191 # successfully on the platform used.
192 # We can improve on this situation by instead passing only the outPath,
193 # without an attached string context, to nix. The out path will be a placeholder
194 # which will be replaced by the actual out path if the derivation in question
195 # is part of the final closure (and thus needs to be built). If it is not
196 # part of the final closure, then the placeholder will be passed along,
197 # but in that case we know for a fact that the derivation is not part of the closure.
198 # This means that passing the out path to nix does the right thing in either
199 # case, both for disallowed and allowed references/requisites, and we won't
200 # build the derivation if it wouldn't be part of the closure, saving time and resources.
201 # While the problem is less severe for allowed*, since we want the derivation
202 # to be built eventually, we would still like to get the error early and without
203 # having to wait while nix builds a derivation that might not be used.
204 # See also https://github.com/NixOS/nix/issues/4629
205 {
206 ${if (attrs ? disallowedReferences) then "disallowedReferences" else null} =
207 map unsafeDerivationToUntrackedOutpath attrs.disallowedReferences;
208 ${if (attrs ? disallowedRequisites) then "disallowedRequisites" else null} =
209 map unsafeDerivationToUntrackedOutpath attrs.disallowedRequisites;
210 ${if (attrs ? allowedReferences) then "allowedReferences" else null} =
211 mapNullable unsafeDerivationToUntrackedOutpath attrs.allowedReferences;
212 ${if (attrs ? allowedRequisites) then "allowedRequisites" else null} =
213 mapNullable unsafeDerivationToUntrackedOutpath attrs.allowedRequisites;
214 };
215
216 makeDerivationArgument =
217
218 # `makeDerivationArgument` is responsible for the `mkDerivation` arguments that
219 # affect the actual derivation, excluding a few behaviors that are not
220 # essential, and specific to `mkDerivation`: `env`, `cmakeFlags`, `mesonFlags`.
221 #
222 # See also:
223 #
224 # * https://nixos.org/nixpkgs/manual/#sec-using-stdenv
225 # Details on how to use this mkDerivation function
226 #
227 # * https://nixos.org/manual/nix/stable/expressions/derivations.html#derivations
228 # Explanation about derivations in general
229 {
230
231 # These types of dependencies are all exhaustively documented in
232 # the "Specifying Dependencies" section of the "Standard
233 # Environment" chapter of the Nixpkgs manual.
234
235 # TODO(@Ericson2314): Stop using legacy dep attribute names
236
237 # host offset -> target offset
238 depsBuildBuild ? [ ], # -1 -> -1
239 depsBuildBuildPropagated ? [ ], # -1 -> -1
240 nativeBuildInputs ? [ ], # -1 -> 0 N.B. Legacy name
241 propagatedNativeBuildInputs ? [ ], # -1 -> 0 N.B. Legacy name
242 depsBuildTarget ? [ ], # -1 -> 1
243 depsBuildTargetPropagated ? [ ], # -1 -> 1
244
245 depsHostHost ? [ ], # 0 -> 0
246 depsHostHostPropagated ? [ ], # 0 -> 0
247 buildInputs ? [ ], # 0 -> 1 N.B. Legacy name
248 propagatedBuildInputs ? [ ], # 0 -> 1 N.B. Legacy name
249
250 depsTargetTarget ? [ ], # 1 -> 1
251 depsTargetTargetPropagated ? [ ], # 1 -> 1
252
253 checkInputs ? [ ],
254 installCheckInputs ? [ ],
255 nativeCheckInputs ? [ ],
256 nativeInstallCheckInputs ? [ ],
257
258 # Configure Phase
259 configureFlags ? [ ],
260 # Target is not included by default because most programs don't care.
261 # Including it then would cause needless mass rebuilds.
262 #
263 # TODO(@Ericson2314): Make [ "build" "host" ] always the default / resolve #87909
264 configurePlatforms ?
265 optionals (stdenv.hostPlatform != stdenv.buildPlatform || config.configurePlatformsByDefault)
266 [
267 "build"
268 "host"
269 ],
270
271 # TODO(@Ericson2314): Make unconditional / resolve #33599
272 # Check phase
273 doCheck ? config.doCheckByDefault or false,
274
275 # TODO(@Ericson2314): Make unconditional / resolve #33599
276 # InstallCheck phase
277 doInstallCheck ? config.doCheckByDefault or false,
278
279 # TODO(@Ericson2314): Make always true and remove / resolve #178468
280 strictDeps ?
281 if config.strictDepsByDefault then true else stdenv.hostPlatform != stdenv.buildPlatform,
282
283 enableParallelBuilding ? config.enableParallelBuildingByDefault,
284
285 separateDebugInfo ? false,
286 outputs ? [ "out" ],
287 __darwinAllowLocalNetworking ? false,
288 __impureHostDeps ? [ ],
289 __propagatedImpureHostDeps ? [ ],
290 sandboxProfile ? "",
291 propagatedSandboxProfile ? "",
292
293 hardeningEnable ? [ ],
294 hardeningDisable ? [ ],
295
296 patches ? [ ],
297
298 __contentAddressed ?
299 (!attrs ? outputHash) # Fixed-output drvs can't be content addressed too
300 && config.contentAddressedByDefault,
301
302 # Experimental. For simple packages mostly just works,
303 # but for anything complex, be prepared to debug if enabling.
304 __structuredAttrs ? config.structuredAttrsByDefault or false,
305
306 ...
307 }@attrs:
308
309 # Policy on acceptable hash types in nixpkgs
310 assert
311 attrs ? outputHash
312 -> (
313 let
314 algo = attrs.outputHashAlgo or (head (splitString "-" attrs.outputHash));
315 in
316 if algo == "md5" then throw "Rejected insecure ${algo} hash '${attrs.outputHash}'" else true
317 );
318
319 let
320 # TODO(@oxij, @Ericson2314): This is here to keep the old semantics, remove when
321 # no package has `doCheck = true`.
322 doCheck' = doCheck && stdenv.buildPlatform.canExecute stdenv.hostPlatform;
323 doInstallCheck' = doInstallCheck && stdenv.buildPlatform.canExecute stdenv.hostPlatform;
324
325 separateDebugInfo' =
326 let
327 actualValue = separateDebugInfo && stdenv.hostPlatform.isLinux;
328 conflictingOption =
329 attrs ? "disallowedReferences"
330 || attrs ? "disallowedRequisites"
331 || attrs ? "allowedRequisites"
332 || attrs ? "allowedReferences";
333 in
334 if actualValue && conflictingOption && !__structuredAttrs then
335 throw "separateDebugInfo = true in ${
336 attrs.pname or "mkDerivation argument"
337 } requires __structuredAttrs if {dis,}allowedRequisites or {dis,}allowedReferences is set"
338 else
339 actualValue;
340 outputs' = outputs ++ optional separateDebugInfo' "debug";
341
342 noNonNativeDeps =
343 builtins.length (
344 depsBuildTarget
345 ++ depsBuildTargetPropagated
346 ++ depsHostHost
347 ++ depsHostHostPropagated
348 ++ buildInputs
349 ++ propagatedBuildInputs
350 ++ depsTargetTarget
351 ++ depsTargetTargetPropagated
352 ) == 0;
353 dontAddHostSuffix = attrs ? outputHash && !noNonNativeDeps || !stdenv.hasCC;
354
355 concretizeFlagImplications =
356 flag: impliesFlags: list:
357 if any (x: x == flag) list then (list ++ impliesFlags) else list;
358
359 hardeningDisable' = unique (
360 pipe hardeningDisable [
361 # disabling fortify implies fortify3 should also be disabled
362 (concretizeFlagImplications "fortify" [ "fortify3" ])
363 # disabling strictflexarrays1 implies strictflexarrays3 should also be disabled
364 (concretizeFlagImplications "strictflexarrays1" [ "strictflexarrays3" ])
365 ]
366 );
367 defaultHardeningFlags =
368 (if stdenv.hasCC then stdenv.cc else { }).defaultHardeningFlags or
369 # fallback safe-ish set of flags
370 (
371 if with stdenv.hostPlatform; isOpenBSD && isStatic then
372 knownHardeningFlags # Need pie, in fact
373 else
374 remove "pie" knownHardeningFlags
375 );
376 enabledHardeningOptions =
377 if builtins.elem "all" hardeningDisable' then
378 [ ]
379 else
380 subtractLists hardeningDisable' (defaultHardeningFlags ++ hardeningEnable);
381 # hardeningDisable additionally supports "all".
382 erroneousHardeningFlags = subtractLists knownHardeningFlags (
383 hardeningEnable ++ remove "all" hardeningDisable
384 );
385
386 checkDependencyList = checkDependencyList' [ ];
387 checkDependencyList' =
388 positions: name: deps:
389 imap1 (
390 index: dep:
391 if dep == null || isDerivation dep || builtins.isString dep || builtins.isPath dep then
392 dep
393 else if isList dep then
394 checkDependencyList' ([ index ] ++ positions) name dep
395 else
396 throw "Dependency is not of a valid type: ${
397 concatMapStrings (ix: "element ${toString ix} of ") ([ index ] ++ positions)
398 }${name} for ${attrs.name or attrs.pname}"
399 ) deps;
400 in
401 if builtins.length erroneousHardeningFlags != 0 then
402 abort (
403 "mkDerivation was called with unsupported hardening flags: "
404 + lib.generators.toPretty { } {
405 inherit
406 erroneousHardeningFlags
407 hardeningDisable
408 hardeningEnable
409 knownHardeningFlags
410 ;
411 }
412 )
413 else
414 let
415 doCheck = doCheck';
416 doInstallCheck = doInstallCheck';
417 buildInputs' =
418 buildInputs ++ optionals doCheck checkInputs ++ optionals doInstallCheck installCheckInputs;
419 nativeBuildInputs' =
420 nativeBuildInputs
421 ++ optional separateDebugInfo' ../../build-support/setup-hooks/separate-debug-info.sh
422 ++ optional stdenv.hostPlatform.isWindows ../../build-support/setup-hooks/win-dll-link.sh
423 ++ optionals doCheck nativeCheckInputs
424 ++ optionals doInstallCheck nativeInstallCheckInputs;
425
426 outputs = outputs';
427
428 dependencies = [
429 [
430 (map (drv: getDev drv.__spliced.buildBuild or drv) (
431 checkDependencyList "depsBuildBuild" depsBuildBuild
432 ))
433 (map (drv: getDev drv.__spliced.buildHost or drv) (
434 checkDependencyList "nativeBuildInputs" nativeBuildInputs'
435 ))
436 (map (drv: getDev drv.__spliced.buildTarget or drv) (
437 checkDependencyList "depsBuildTarget" depsBuildTarget
438 ))
439 ]
440 [
441 (map (drv: getDev drv.__spliced.hostHost or drv) (checkDependencyList "depsHostHost" depsHostHost))
442 (map (drv: getDev drv.__spliced.hostTarget or drv) (checkDependencyList "buildInputs" buildInputs'))
443 ]
444 [
445 (map (drv: getDev drv.__spliced.targetTarget or drv) (
446 checkDependencyList "depsTargetTarget" depsTargetTarget
447 ))
448 ]
449 ];
450 propagatedDependencies = [
451 [
452 (map (drv: getDev drv.__spliced.buildBuild or drv) (
453 checkDependencyList "depsBuildBuildPropagated" depsBuildBuildPropagated
454 ))
455 (map (drv: getDev drv.__spliced.buildHost or drv) (
456 checkDependencyList "propagatedNativeBuildInputs" propagatedNativeBuildInputs
457 ))
458 (map (drv: getDev drv.__spliced.buildTarget or drv) (
459 checkDependencyList "depsBuildTargetPropagated" depsBuildTargetPropagated
460 ))
461 ]
462 [
463 (map (drv: getDev drv.__spliced.hostHost or drv) (
464 checkDependencyList "depsHostHostPropagated" depsHostHostPropagated
465 ))
466 (map (drv: getDev drv.__spliced.hostTarget or drv) (
467 checkDependencyList "propagatedBuildInputs" propagatedBuildInputs
468 ))
469 ]
470 [
471 (map (drv: getDev drv.__spliced.targetTarget or drv) (
472 checkDependencyList "depsTargetTargetPropagated" depsTargetTargetPropagated
473 ))
474 ]
475 ];
476
477 derivationArg =
478 removeAttrs attrs removedOrReplacedAttrNames
479 // {
480 ${if (attrs ? name || (attrs ? pname && attrs ? version)) then "name" else null} =
481 let
482 # Indicate the host platform of the derivation if cross compiling.
483 # Fixed-output derivations like source tarballs shouldn't get a host
484 # suffix. But we have some weird ones with run-time deps that are
485 # just used for their side-affects. Those might as well since the
486 # hash can't be the same. See #32986.
487 hostSuffix = optionalString (
488 stdenv.hostPlatform != stdenv.buildPlatform && !dontAddHostSuffix
489 ) "-${stdenv.hostPlatform.config}";
490
491 # Disambiguate statically built packages. This was originally
492 # introduce as a means to prevent nix-env to get confused between
493 # nix and nixStatic. This should be also achieved by moving the
494 # hostSuffix before the version, so we could contemplate removing
495 # it again.
496 staticMarker = optionalString stdenv.hostPlatform.isStatic "-static";
497 in
498 lib.strings.sanitizeDerivationName (
499 if attrs ? name then
500 attrs.name + hostSuffix
501 else
502 # we cannot coerce null to a string below
503 assert assertMsg (
504 attrs ? version && attrs.version != null
505 ) "The `version` attribute cannot be null.";
506 "${attrs.pname}${staticMarker}${hostSuffix}-${attrs.version}"
507 );
508
509 builder = attrs.realBuilder or stdenv.shell;
510 args =
511 attrs.args or [
512 "-e"
513 ./source-stdenv.sh
514 (attrs.builder or ./default-builder.sh)
515 ];
516 inherit stdenv;
517
518 # The `system` attribute of a derivation has special meaning to Nix.
519 # Derivations set it to choose what sort of machine could be used to
520 # execute the build, The build platform entirely determines this,
521 # indeed more finely than Nix knows or cares about. The `system`
522 # attribute of `buildPlatform` matches Nix's degree of specificity.
523 # exactly.
524 inherit (stdenv.buildPlatform) system;
525
526 userHook = config.stdenv.userHook or null;
527 __ignoreNulls = true;
528 inherit __structuredAttrs strictDeps;
529
530 depsBuildBuild = elemAt (elemAt dependencies 0) 0;
531 nativeBuildInputs = elemAt (elemAt dependencies 0) 1;
532 depsBuildTarget = elemAt (elemAt dependencies 0) 2;
533 depsHostHost = elemAt (elemAt dependencies 1) 0;
534 buildInputs = elemAt (elemAt dependencies 1) 1;
535 depsTargetTarget = elemAt (elemAt dependencies 2) 0;
536
537 depsBuildBuildPropagated = elemAt (elemAt propagatedDependencies 0) 0;
538 propagatedNativeBuildInputs = elemAt (elemAt propagatedDependencies 0) 1;
539 depsBuildTargetPropagated = elemAt (elemAt propagatedDependencies 0) 2;
540 depsHostHostPropagated = elemAt (elemAt propagatedDependencies 1) 0;
541 propagatedBuildInputs = elemAt (elemAt propagatedDependencies 1) 1;
542 depsTargetTargetPropagated = elemAt (elemAt propagatedDependencies 2) 0;
543
544 # This parameter is sometimes a string, sometimes null, and sometimes a list, yuck
545 configureFlags =
546 configureFlags
547 ++ optional (elem "build" configurePlatforms) "--build=${stdenv.buildPlatform.config}"
548 ++ optional (elem "host" configurePlatforms) "--host=${stdenv.hostPlatform.config}"
549 ++ optional (elem "target" configurePlatforms) "--target=${stdenv.targetPlatform.config}";
550
551 inherit patches;
552
553 inherit doCheck doInstallCheck;
554
555 inherit outputs;
556
557 # When the derivations is content addressed provide default values
558 # for outputHashMode and outputHashAlgo because most people won't
559 # care about these anyways
560 ${if __contentAddressed then "__contentAddressed" else null} = __contentAddressed;
561 ${if __contentAddressed then "outputHashAlgo" else null} = attrs.outputHashAlgo or "sha256";
562 ${if __contentAddressed then "outputHashMode" else null} = attrs.outputHashMode or "recursive";
563
564 ${if enableParallelBuilding then "enableParallelBuilding" else null} = enableParallelBuilding;
565 ${if enableParallelBuilding then "enableParallelChecking" else null} =
566 attrs.enableParallelChecking or true;
567 ${if enableParallelBuilding then "enableParallelInstalling" else null} =
568 attrs.enableParallelInstalling or true;
569
570 ${
571 if (hardeningDisable != [ ] || hardeningEnable != [ ] || stdenv.hostPlatform.isMusl) then
572 "NIX_HARDENING_ENABLE"
573 else
574 null
575 } =
576 builtins.concatStringsSep " " enabledHardeningOptions;
577
578 # TODO: remove platform condition
579 # Enabling this check could be a breaking change as it requires to edit nix.conf
580 # NixOS module already sets gccarch, unsure of nix installers and other distributions
581 ${
582 if
583 stdenv.buildPlatform ? gcc.arch
584 && !(
585 stdenv.buildPlatform.isAarch64
586 && (
587 # `aarch64-darwin` sets `{gcc.arch = "armv8.3-a+crypto+sha2+...";}`
588 stdenv.buildPlatform.isDarwin
589 ||
590 # `aarch64-linux` has `{ gcc.arch = "armv8-a"; }` set by default
591 stdenv.buildPlatform.gcc.arch == "armv8-a"
592 )
593 )
594 then
595 "requiredSystemFeatures"
596 else
597 null
598 } =
599 attrs.requiredSystemFeatures or [ ] ++ [
600 "gccarch-${stdenv.buildPlatform.gcc.arch}"
601 ];
602 }
603 // optionalAttrs (stdenv.buildPlatform.isDarwin) (
604 let
605 allDependencies = concatLists (concatLists dependencies);
606 allPropagatedDependencies = concatLists (concatLists propagatedDependencies);
607
608 computedSandboxProfile = concatMap (input: input.__propagatedSandboxProfile or [ ]) (
609 stdenv.extraNativeBuildInputs ++ stdenv.extraBuildInputs ++ allDependencies
610 );
611
612 computedPropagatedSandboxProfile = concatMap (
613 input: input.__propagatedSandboxProfile or [ ]
614 ) allPropagatedDependencies;
615
616 computedImpureHostDeps = unique (
617 concatMap (input: input.__propagatedImpureHostDeps or [ ]) (
618 stdenv.extraNativeBuildInputs ++ stdenv.extraBuildInputs ++ allDependencies
619 )
620 );
621
622 computedPropagatedImpureHostDeps = unique (
623 concatMap (input: input.__propagatedImpureHostDeps or [ ]) allPropagatedDependencies
624 );
625 in
626 {
627 inherit __darwinAllowLocalNetworking;
628 # TODO: remove `unique` once nix has a list canonicalization primitive
629 __sandboxProfile =
630 let
631 profiles = [
632 stdenv.extraSandboxProfile
633 ]
634 ++ computedSandboxProfile
635 ++ computedPropagatedSandboxProfile
636 ++ [
637 propagatedSandboxProfile
638 sandboxProfile
639 ];
640 final = concatStringsSep "\n" (filter (x: x != "") (unique profiles));
641 in
642 final;
643 __propagatedSandboxProfile = unique (
644 computedPropagatedSandboxProfile ++ [ propagatedSandboxProfile ]
645 );
646 __impureHostDeps =
647 computedImpureHostDeps
648 ++ computedPropagatedImpureHostDeps
649 ++ __propagatedImpureHostDeps
650 ++ __impureHostDeps
651 ++ stdenv.__extraImpureHostDeps
652 ++ [
653 "/dev/zero"
654 "/dev/random"
655 "/dev/urandom"
656 "/bin/sh"
657 ];
658 __propagatedImpureHostDeps = computedPropagatedImpureHostDeps ++ __propagatedImpureHostDeps;
659 }
660 )
661 // (
662 if !__structuredAttrs then
663 makeOutputChecks attrs
664 else
665 {
666 outputChecks = builtins.listToAttrs (
667 map (name: {
668 inherit name;
669 value =
670 let
671 raw = zipAttrsWith (_: builtins.concatLists) [
672 (makeOutputChecks attrs)
673 (makeOutputChecks attrs.outputChecks.${name} or { })
674 ];
675 in
676 # separateDebugInfo = true will put all sorts of files in
677 # the debug output which could carry references, but
678 # that's "normal". Notably it symlinks to the source.
679 # So disable reference checking for the debug output
680 if separateDebugInfo' && name == "debug" then
681 removeAttrs raw [
682 "allowedReferences"
683 "allowedRequisites"
684 "disallowedReferences"
685 "disallowedRequisites"
686 ]
687 else
688 raw;
689 }) outputs
690 );
691 }
692 );
693
694 in
695 derivationArg;
696
697 mkDerivationSimple =
698 overrideAttrs:
699
700 # `mkDerivation` wraps the builtin `derivation` function to
701 # produce derivations that use this stdenv and its shell.
702 #
703 # Internally, it delegates most of its behavior to `makeDerivationArgument`,
704 # except for the `env`, `cmakeFlags`, and `mesonFlags` attributes, as well
705 # as the attributes `meta` and `passthru` that affect [package attributes],
706 # and not the derivation itself.
707 #
708 # See also:
709 #
710 # * https://nixos.org/nixpkgs/manual/#sec-using-stdenv
711 # Details on how to use this mkDerivation function
712 #
713 # * https://nixos.org/manual/nix/stable/expressions/derivations.html#derivations
714 # Explanation about derivations in general
715 #
716 # * [package attributes]: https://nixos.org/manual/nix/stable/glossary#package-attribute-set
717 {
718
719 # Configure Phase
720 cmakeFlags ? [ ],
721 mesonFlags ? [ ],
722
723 meta ? { },
724 passthru ? { },
725 pos ? # position used in error messages and for meta.position
726 (
727 if attrs.meta.description or null != null then
728 builtins.unsafeGetAttrPos "description" attrs.meta
729 else if attrs.version or null != null then
730 builtins.unsafeGetAttrPos "version" attrs
731 else
732 builtins.unsafeGetAttrPos "name" attrs
733 ),
734
735 # Experimental. For simple packages mostly just works,
736 # but for anything complex, be prepared to debug if enabling.
737 __structuredAttrs ? config.structuredAttrsByDefault or false,
738
739 env ? { },
740
741 ...
742 }@attrs:
743
744 # Policy on acceptable hash types in nixpkgs
745 assert
746 attrs ? outputHash
747 -> (
748 let
749 algo = attrs.outputHashAlgo or (head (splitString "-" attrs.outputHash));
750 in
751 if algo == "md5" then throw "Rejected insecure ${algo} hash '${attrs.outputHash}'" else true
752 );
753
754 let
755 mainProgram = meta.mainProgram or null;
756 env' = env // lib.optionalAttrs (mainProgram != null) { NIX_MAIN_PROGRAM = mainProgram; };
757
758 derivationArg = makeDerivationArgument (
759 removeAttrs attrs ([
760 "meta"
761 "passthru"
762 "pos"
763 "env"
764 ])
765 // lib.optionalAttrs __structuredAttrs { env = checkedEnv; }
766 // {
767 cmakeFlags = makeCMakeFlags attrs;
768 mesonFlags = makeMesonFlags attrs;
769 }
770 );
771
772 meta = checkMeta.commonMeta {
773 inherit validity attrs pos;
774 references =
775 attrs.nativeBuildInputs or [ ]
776 ++ attrs.buildInputs or [ ]
777 ++ attrs.propagatedNativeBuildInputs or [ ]
778 ++ attrs.propagatedBuildInputs or [ ];
779 };
780 validity = checkMeta.assertValidity { inherit meta attrs; };
781
782 checkedEnv =
783 let
784 overlappingNames = attrNames (builtins.intersectAttrs env' derivationArg);
785 prettyPrint = lib.generators.toPretty { };
786 makeError =
787 name:
788 " - ${name}: in `env`: ${prettyPrint env'.${name}}; in derivation arguments: ${
789 prettyPrint derivationArg.${name}
790 }";
791 errors = lib.concatMapStringsSep "\n" makeError overlappingNames;
792 in
793 assert assertMsg (isAttrs env && !isDerivation env)
794 "`env` must be an attribute set of environment variables. Set `env.env` or pick a more specific name.";
795 assert assertMsg (overlappingNames == [ ])
796 "The `env` attribute set cannot contain any attributes passed to derivation. The following attributes are overlapping:\n${errors}";
797 mapAttrs (
798 n: v:
799 assert assertMsg (isString v || isBool v || isInt v || isDerivation v)
800 "The `env` attribute set can only contain derivation, string, boolean or integer attributes. The `${n}` attribute is of type ${builtins.typeOf v}.";
801 v
802 ) env';
803
804 # Fixed-output derivations may not reference other paths, which means that
805 # for a fixed-output derivation, the corresponding inputDerivation should
806 # *not* be fixed-output. To achieve this we simply delete the attributes that
807 # would make it fixed-output.
808 deleteFixedOutputRelatedAttrs = lib.flip builtins.removeAttrs [
809 "outputHashAlgo"
810 "outputHash"
811 "outputHashMode"
812 ];
813
814 in
815
816 extendDerivation validity.handled (
817 {
818 # A derivation that always builds successfully and whose runtime
819 # dependencies are the original derivations build time dependencies
820 # This allows easy building and distributing of all derivations
821 # needed to enter a nix-shell with
822 # nix-build shell.nix -A inputDerivation
823 inputDerivation = derivation (
824 deleteFixedOutputRelatedAttrs derivationArg
825 // {
826 # Add a name in case the original drv didn't have one
827 name = derivationArg.name or "inputDerivation";
828 # This always only has one output
829 outputs = [ "out" ];
830
831 # Propagate the original builder and arguments, since we override
832 # them and they might contain references to build inputs
833 _derivation_original_builder = derivationArg.builder;
834 _derivation_original_args = derivationArg.args;
835
836 builder = stdenv.shell;
837 # The builtin `declare -p` dumps all bash and environment variables,
838 # which is where all build input references end up (e.g. $PATH for
839 # binaries). By writing this to $out, Nix can find and register
840 # them as runtime dependencies (since Nix greps for store paths
841 # through $out to find them). Using placeholder for $out works with
842 # and without structuredAttrs.
843 # This build script does not use setup.sh or stdenv, to keep
844 # the env most pristine. This gives us a very bare bones env,
845 # hence the extra/duplicated compatibility logic and "pure bash" style.
846 args = [
847 "-c"
848 ''
849 out="${placeholder "out"}"
850 if [ -e "$NIX_ATTRS_SH_FILE" ]; then . "$NIX_ATTRS_SH_FILE"; elif [ -f .attrs.sh ]; then . .attrs.sh; fi
851 declare -p > $out
852 for var in $passAsFile; do
853 pathVar="''${var}Path"
854 printf "%s" "$(< "''${!pathVar}")" >> $out
855 done
856 ''
857 ];
858 }
859 // (
860 let
861 sharedOutputChecks = {
862 # inputDerivation produces the inputs; not the outputs, so any
863 # restrictions on what used to be the outputs don't serve a purpose
864 # anymore.
865 allowedReferences = null;
866 allowedRequisites = null;
867 disallowedReferences = [ ];
868 disallowedRequisites = [ ];
869 };
870 in
871 if __structuredAttrs then
872 {
873 outputChecks.out = sharedOutputChecks;
874 }
875 else
876 sharedOutputChecks
877 )
878 );
879
880 inherit passthru overrideAttrs;
881 inherit meta;
882 }
883 //
884 # Pass through extra attributes that are not inputs, but
885 # should be made available to Nix expressions using the
886 # derivation (e.g., in assertions).
887 passthru
888 ) (derivation (derivationArg // checkedEnv));
889
890in
891{
892 inherit mkDerivation;
893}