nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at devShellTools-shell 1092 lines 35 kB view raw
1{ 2 lib, 3 config, 4 stdenv, 5 stdenvNoCC, 6 jq, 7 lndir, 8 runtimeShell, 9 shellcheck-minimal, 10}: 11 12let 13 inherit (lib) 14 optionalAttrs 15 optionalString 16 hasPrefix 17 warn 18 map 19 isList 20 ; 21in 22 23rec { 24 25 # Docs in doc/build-helpers/trivial-build-helpers.chapter.md 26 # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-runCommand 27 runCommand = 28 name: env: 29 runCommandWith { 30 stdenv = stdenvNoCC; 31 runLocal = false; 32 inherit name; 33 derivationArgs = env; 34 }; 35 # Docs in doc/build-helpers/trivial-build-helpers.chapter.md 36 # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-runCommandLocal 37 runCommandLocal = 38 name: env: 39 runCommandWith { 40 stdenv = stdenvNoCC; 41 runLocal = true; 42 inherit name; 43 derivationArgs = env; 44 }; 45 # Docs in doc/build-helpers/trivial-build-helpers.chapter.md 46 # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-runCommandCC 47 runCommandCC = 48 name: env: 49 runCommandWith { 50 stdenv = stdenv; 51 runLocal = false; 52 inherit name; 53 derivationArgs = env; 54 }; 55 # `runCommandCCLocal` left out on purpose. 56 # We shouldn’t force the user to have a cc in scope. 57 58 # Docs in doc/build-helpers/trivial-build-helpers.chapter.md 59 # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-runCommandWith 60 runCommandWith = 61 let 62 # prevent infinite recursion for the default stdenv value 63 defaultStdenv = stdenv; 64 in 65 { 66 # which stdenv to use, defaults to a stdenv with a C compiler, pkgs.stdenv 67 stdenv ? defaultStdenv, 68 # whether to build this derivation locally instead of substituting 69 runLocal ? false, 70 # extra arguments to pass to stdenv.mkDerivation 71 derivationArgs ? { }, 72 # name of the resulting derivation 73 name, 74 # TODO(@Artturin): enable strictDeps always 75 }: 76 buildCommand: 77 stdenv.mkDerivation ( 78 { 79 enableParallelBuilding = true; 80 inherit buildCommand name; 81 passAsFile = [ "buildCommand" ] ++ (derivationArgs.passAsFile or [ ]); 82 } 83 // lib.optionalAttrs (!derivationArgs ? meta) { 84 pos = 85 let 86 args = builtins.attrNames derivationArgs; 87 in 88 if builtins.length args > 0 then 89 builtins.unsafeGetAttrPos (builtins.head args) derivationArgs 90 else 91 null; 92 } 93 // (lib.optionalAttrs runLocal { 94 preferLocalBuild = true; 95 allowSubstitutes = false; 96 }) 97 // builtins.removeAttrs derivationArgs [ "passAsFile" ] 98 ); 99 100 # Docs in doc/build-helpers/trivial-build-helpers.chapter.md 101 # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-writeTextFile 102 writeTextFile = 103 { 104 name, 105 text, 106 executable ? false, 107 destination ? "", 108 checkPhase ? "", 109 meta ? { }, 110 passthru ? { }, 111 allowSubstitutes ? false, 112 preferLocalBuild ? true, 113 derivationArgs ? { }, 114 }: 115 assert lib.assertMsg (destination != "" -> (lib.hasPrefix "/" destination && destination != "/")) '' 116 destination must be an absolute path, relative to the derivation's out path, 117 got '${destination}' instead. 118 119 Ensure that the path starts with a / and specifies at least the filename. 120 ''; 121 122 let 123 matches = builtins.match "/bin/([^/]+)" destination; 124 in 125 runCommand name 126 ( 127 { 128 inherit 129 text 130 executable 131 checkPhase 132 allowSubstitutes 133 preferLocalBuild 134 ; 135 passAsFile = [ "text" ] ++ derivationArgs.passAsFile or [ ]; 136 meta = 137 lib.optionalAttrs (executable && matches != null) { 138 mainProgram = lib.head matches; 139 } 140 // meta 141 // derivationArgs.meta or { }; 142 passthru = passthru // derivationArgs.passthru or { }; 143 } 144 // removeAttrs derivationArgs [ 145 "passAsFile" 146 "meta" 147 "passthru" 148 ] 149 ) 150 '' 151 target=$out${lib.escapeShellArg destination} 152 mkdir -p "$(dirname "$target")" 153 154 if [ -e "$textPath" ]; then 155 mv "$textPath" "$target" 156 else 157 echo -n "$text" > "$target" 158 fi 159 160 if [ -n "$executable" ]; then 161 chmod +x "$target" 162 fi 163 164 eval "$checkPhase" 165 ''; 166 167 # See doc/build-helpers/trivial-build-helpers.chapter.md 168 # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-text-writing 169 writeText = 170 name: text: 171 # TODO: To fully deprecate, replace the assertion with `lib.isString` and remove the warning 172 assert lib.assertMsg (lib.strings.isConvertibleWithToString text) 173 ''pkgs.writeText ${lib.strings.escapeNixString name}: The second argument should be a string, but it's a ${builtins.typeOf text} instead.''; 174 lib.warnIf (!lib.isString text) 175 ''pkgs.writeText ${lib.strings.escapeNixString name}: The second argument should be a string, but it's a ${builtins.typeOf text} instead, which is deprecated. Use `toString` to convert the value to a string first.'' 176 writeTextFile 177 { inherit name text; }; 178 179 # See doc/build-helpers/trivial-build-helpers.chapter.md 180 # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-text-writing 181 writeTextDir = 182 path: text: 183 writeTextFile { 184 inherit text; 185 name = builtins.baseNameOf path; 186 destination = "/${path}"; 187 }; 188 189 # See doc/build-helpers/trivial-build-helpers.chapter.md 190 # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-text-writing 191 writeScript = 192 name: text: 193 writeTextFile { 194 inherit name text; 195 executable = true; 196 }; 197 198 # See doc/build-helpers/trivial-build-helpers.chapter.md 199 # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-text-writing 200 writeScriptBin = 201 name: text: 202 writeTextFile { 203 inherit name text; 204 executable = true; 205 destination = "/bin/${name}"; 206 }; 207 208 # See doc/build-helpers/trivial-build-helpers.chapter.md 209 # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-text-writing 210 writeShellScript = 211 name: text: 212 writeTextFile { 213 inherit name; 214 executable = true; 215 text = '' 216 #!${runtimeShell} 217 ${text} 218 ''; 219 checkPhase = '' 220 ${stdenv.shellDryRun} "$target" 221 ''; 222 }; 223 224 # See doc/build-helpers/trivial-build-helpers.chapter.md 225 # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-text-writing 226 writeShellScriptBin = 227 name: text: 228 writeTextFile { 229 inherit name; 230 executable = true; 231 destination = "/bin/${name}"; 232 text = '' 233 #!${runtimeShell} 234 ${text} 235 ''; 236 checkPhase = '' 237 ${stdenv.shellDryRun} "$target" 238 ''; 239 meta.mainProgram = name; 240 }; 241 242 # TODO: move parameter documentation to the Nixpkgs manual 243 # See doc/build-helpers/trivial-build-helpers.chapter.md 244 # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-writeShellApplication 245 writeShellApplication = 246 { 247 /* 248 The name of the script to write. 249 250 Type: String 251 */ 252 name, 253 /* 254 The shell script's text, not including a shebang. 255 256 Type: String 257 */ 258 text, 259 /* 260 Inputs to add to the shell script's `$PATH` at runtime. 261 262 Type: [String|Derivation] 263 */ 264 runtimeInputs ? [ ], 265 /* 266 Extra environment variables to set at runtime. 267 268 Type: AttrSet 269 */ 270 runtimeEnv ? null, 271 /* 272 `stdenv.mkDerivation`'s `meta` argument. 273 274 Type: AttrSet 275 */ 276 meta ? { }, 277 /* 278 `stdenv.mkDerivation`'s `passthru` argument. 279 280 Type: AttrSet 281 */ 282 passthru ? { }, 283 /* 284 The `checkPhase` to run. Defaults to `shellcheck` on supported 285 platforms and `bash -n`. 286 287 The script path will be given as `$target` in the `checkPhase`. 288 289 Type: String 290 */ 291 checkPhase ? null, 292 /* 293 Checks to exclude when running `shellcheck`, e.g. `[ "SC2016" ]`. 294 295 See <https://www.shellcheck.net/wiki/> for a list of checks. 296 297 Type: [String] 298 */ 299 excludeShellChecks ? [ ], 300 /* 301 Extra command-line flags to pass to ShellCheck. 302 303 Type: [String] 304 */ 305 extraShellCheckFlags ? [ ], 306 /* 307 Bash options to activate with `set -o` at the start of the script. 308 309 Defaults to `[ "errexit" "nounset" "pipefail" ]`. 310 311 Type: [String] 312 */ 313 bashOptions ? [ 314 "errexit" 315 "nounset" 316 "pipefail" 317 ], 318 /* 319 Extra arguments to pass to `stdenv.mkDerivation`. 320 321 :::{.caution} 322 Certain derivation attributes are used internally, 323 overriding those could cause problems. 324 ::: 325 326 Type: AttrSet 327 */ 328 derivationArgs ? { }, 329 /* 330 Whether to inherit the current `$PATH` in the script. 331 332 Type: Bool 333 */ 334 inheritPath ? true, 335 }: 336 writeTextFile { 337 inherit 338 name 339 meta 340 passthru 341 derivationArgs 342 ; 343 executable = true; 344 destination = "/bin/${name}"; 345 allowSubstitutes = true; 346 preferLocalBuild = false; 347 text = '' 348 #!${runtimeShell} 349 ${lib.concatMapStringsSep "\n" (option: "set -o ${option}") bashOptions} 350 '' 351 + lib.optionalString (runtimeEnv != null) ( 352 lib.concatStrings ( 353 lib.mapAttrsToList (name: value: '' 354 ${lib.toShellVar name value} 355 export ${name} 356 '') runtimeEnv 357 ) 358 ) 359 + lib.optionalString (runtimeInputs != [ ]) '' 360 361 export PATH="${lib.makeBinPath runtimeInputs}${lib.optionalString inheritPath ":$PATH"}" 362 '' 363 + '' 364 365 ${text} 366 ''; 367 368 checkPhase = 369 let 370 excludeFlags = lib.optionals (excludeShellChecks != [ ]) [ 371 "--exclude" 372 (lib.concatStringsSep "," excludeShellChecks) 373 ]; 374 # GHC (=> shellcheck) isn't supported on some platforms (such as risc-v) 375 # but we still want to use writeShellApplication on those platforms 376 shellcheckCommand = lib.optionalString shellcheck-minimal.compiler.bootstrapAvailable '' 377 # use shellcheck which does not include docs 378 # pandoc takes long to build and documentation isn't needed for just running the cli 379 ${lib.getExe shellcheck-minimal} ${ 380 lib.escapeShellArgs (excludeFlags ++ extraShellCheckFlags) 381 } "$target" 382 ''; 383 in 384 if checkPhase == null then 385 '' 386 runHook preCheck 387 ${stdenv.shellDryRun} "$target" 388 ${shellcheckCommand} 389 runHook postCheck 390 '' 391 else 392 checkPhase; 393 }; 394 395 # Create a C binary 396 # TODO: add to writers? pkgs/build-support/writers 397 writeCBin = 398 pname: code: 399 runCommandCC pname 400 { 401 inherit pname code; 402 executable = true; 403 passAsFile = [ "code" ]; 404 # Pointless to do this on a remote machine. 405 preferLocalBuild = true; 406 allowSubstitutes = false; 407 meta = { 408 mainProgram = pname; 409 }; 410 } 411 '' 412 n=$out/bin/${pname} 413 mkdir -p "$(dirname "$n")" 414 mv "$codePath" code.c 415 $CC -x c code.c -o "$n" 416 ''; 417 418 # TODO: deduplicate with documentation in doc/build-helpers/trivial-build-helpers.chapter.md 419 # see also https://github.com/NixOS/nixpkgs/pull/249721 420 # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-concatText 421 /* 422 concat a list of files to the nix store. 423 The contents of files are added to the file in the store. 424 425 Example: 426 427 # Writes my-file to /nix/store/<store path> 428 concatTextFile { 429 name = "my-file"; 430 files = [ drv1 "${drv2}/path/to/file" ]; 431 } 432 433 See also the `concatText` helper function below. 434 435 # Writes executable my-file to /nix/store/<store path>/bin/my-file 436 concatTextFile { 437 name = "my-file"; 438 files = [ drv1 "${drv2}/path/to/file" ]; 439 executable = true; 440 destination = "/bin/my-file"; 441 } 442 */ 443 concatTextFile = 444 { 445 name, # the name of the derivation 446 files, 447 executable ? false, # run chmod +x ? 448 destination ? "", # relative path appended to $out eg "/bin/foo" 449 checkPhase ? "", # syntax checks, e.g. for scripts 450 meta ? { }, 451 passthru ? { }, 452 }: 453 runCommandLocal name 454 { 455 inherit 456 files 457 executable 458 checkPhase 459 meta 460 passthru 461 destination 462 ; 463 } 464 '' 465 file=$out$destination 466 mkdir -p "$(dirname "$file")" 467 cat $files > "$file" 468 469 if [ -n "$executable" ]; then 470 chmod +x "$file" 471 fi 472 473 eval "$checkPhase" 474 ''; 475 476 # TODO: deduplicate with documentation in doc/build-helpers/trivial-build-helpers.chapter.md 477 # see also https://github.com/NixOS/nixpkgs/pull/249721 478 # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-concatText 479 /* 480 Writes a text file to nix store with no optional parameters available. 481 482 Example: 483 484 # Writes contents of files to /nix/store/<store path> 485 concatText "my-file" [ file1 file2 ] 486 */ 487 concatText = name: files: concatTextFile { inherit name files; }; 488 489 # TODO: deduplicate with documentation in doc/build-helpers/trivial-build-helpers.chapter.md 490 # see also https://github.com/NixOS/nixpkgs/pull/249721 491 # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-concatText 492 /* 493 Writes a text file to nix store with and mark it as executable. 494 495 Example: 496 # Writes contents of files to /nix/store/<store path> 497 concatScript "my-file" [ file1 file2 ] 498 */ 499 concatScript = 500 name: files: 501 concatTextFile { 502 inherit name files; 503 executable = true; 504 }; 505 506 /* 507 TODO: Deduplicate this documentation. 508 More docs in doc/build-helpers/trivial-build-helpers.chapter.md 509 See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-symlinkJoin 510 511 Create a forest of symlinks to the files in `paths`. 512 513 This creates a single derivation that replicates the directory structure 514 of all the input paths. 515 516 BEWARE: it may not "work right" when the passed paths contain symlinks to directories. 517 518 Example: 519 520 # adds symlinks of hello to current build. 521 symlinkJoin { name = "myhello"; paths = [ pkgs.hello ]; } 522 523 # adds symlinks of hello and stack to current build and prints "links added" 524 symlinkJoin { name = "myexample"; paths = [ pkgs.hello pkgs.stack ]; postBuild = "echo links added"; } 525 526 This creates a derivation with a directory structure like the following: 527 528 /nix/store/sglsr5g079a5235hy29da3mq3hv8sjmm-myexample 529 |-- bin 530 | |-- hello -> /nix/store/qy93dp4a3rqyn2mz63fbxjg228hffwyw-hello-2.10/bin/hello 531 | `-- stack -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/bin/stack 532 `-- share 533 |-- bash-completion 534 | `-- completions 535 | `-- stack -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/share/bash-completion/completions/stack 536 |-- fish 537 | `-- vendor_completions.d 538 | `-- stack.fish -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/share/fish/vendor_completions.d/stack.fish 539 ... 540 541 To create a directory structure from a specific subdirectory of input `paths` instead of their full trees, 542 you can either append the subdirectory path to each input path, or use the `stripPrefix` argument to 543 remove the common prefix during linking. 544 545 Example: 546 547 # create symlinks of tmpfiles.d rules from multiple packages 548 symlinkJoin { name = "tmpfiles.d"; paths = [ pkgs.lvm2 pkgs.nix ]; stripPrefix = "/lib/tmpfiles.d"; } 549 550 This creates a derivation with a directory structure like the following: 551 552 /nix/store/m5s775yicb763hfa133jwml5hwmwzv14-tmpfiles.d 553 |-- lvm2.conf -> /nix/store/k6js0l5f0zpvrhay49579fj939j77p2w-lvm2-2.03.29/lib/tmpfiles.d/lvm2.conf 554 `-- nix-daemon.conf -> /nix/store/z4v2s3s3y79fmabhps5hakb3c5dwaj5a-nix-1.33.7/lib/tmpfiles.d/nix-daemon.conf 555 556 By default, packages that don't contain the specified subdirectory are silently skipped. 557 Set `failOnMissing = true` to make the build fail if any input package is missing the subdirectory 558 (this is the default behavior when not using stripPrefix). 559 560 symlinkJoin and linkFarm are similar functions, but they output 561 derivations with different structure. 562 563 symlinkJoin is used to create a derivation with a familiar directory 564 structure (top-level bin/, share/, etc), but with all actual files being symlinks to 565 the files in the input derivations. 566 567 symlinkJoin is used many places in nixpkgs to create a single derivation 568 that appears to contain binaries, libraries, documentation, etc from 569 multiple input derivations. 570 571 linkFarm is instead used to create a simple derivation with symlinks to 572 other derivations. A derivation created with linkFarm is often used in CI 573 as a easy way to build multiple derivations at once. 574 */ 575 symlinkJoin = 576 args_@{ 577 name ? 578 assert lib.assertMsg ( 579 args_ ? pname && args_ ? version 580 ) "symlinkJoin requires either a `name` OR `pname` and `version`"; 581 "${args_.pname}-${args_.version}", 582 paths, 583 stripPrefix ? "", 584 preferLocalBuild ? true, 585 allowSubstitutes ? false, 586 postBuild ? "", 587 failOnMissing ? stripPrefix == "", 588 ... 589 }: 590 assert lib.assertMsg (stripPrefix != "" -> (hasPrefix "/" stripPrefix && stripPrefix != "/")) '' 591 stripPrefix must be either an empty string (disable stripping behavior), or relative path prefixed with /. 592 593 Ensure that the path starts with / and specifies path to the subdirectory. 594 ''; 595 596 let 597 mapPaths = 598 f: paths: 599 map ( 600 path: 601 if path == null then 602 null 603 else if isList path then 604 mapPaths f path 605 else 606 f path 607 ) paths; 608 args = 609 removeAttrs args_ [ 610 "name" 611 "postBuild" 612 "stripPrefix" 613 "paths" 614 "failOnMissing" 615 ] 616 // { 617 inherit preferLocalBuild allowSubstitutes; 618 paths = mapPaths (path: "${path}${stripPrefix}") paths; 619 passAsFile = [ "paths" ]; 620 }; # pass the defaults 621 in 622 runCommand name args '' 623 mkdir -p $out 624 for i in $(cat $pathsPath); do 625 ${optionalString (!failOnMissing) "if test -d $i; then "}${lndir}/bin/lndir -silent $i $out${ 626 optionalString (!failOnMissing) "; fi" 627 } 628 done 629 ${postBuild} 630 ''; 631 632 # TODO: move linkFarm docs to the Nixpkgs manual 633 /* 634 Quickly create a set of symlinks to derivations. 635 636 This creates a simple derivation with symlinks to all inputs. 637 638 entries can be a list of attribute sets like 639 640 [ { name = "name" ; path = "/nix/store/..."; } ] 641 642 or an attribute set name -> path like: 643 644 { name = "/nix/store/..."; other = "/nix/store/..."; } 645 646 Example: 647 648 # Symlinks hello and stack paths in store to current $out/hello-test and 649 # $out/foobar. 650 linkFarm "myexample" [ { name = "hello-test"; path = pkgs.hello; } { name = "foobar"; path = pkgs.stack; } ] 651 652 This creates a derivation with a directory structure like the following: 653 654 /nix/store/qc5728m4sa344mbks99r3q05mymwm4rw-myexample 655 |-- foobar -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1 656 `-- hello-test -> /nix/store/qy93dp4a3rqyn2mz63fbxjg228hffwyw-hello-2.10 657 658 See the note on symlinkJoin for the difference between linkFarm and symlinkJoin. 659 */ 660 linkFarm = 661 name: entries: 662 let 663 entries' = 664 if (lib.isAttrs entries) then 665 entries 666 # We do this foldl to have last-wins semantics in case of repeated entries 667 else if (lib.isList entries) then 668 lib.foldl (a: b: a // { "${b.name}" = b.path; }) { } entries 669 else 670 throw "linkFarm entries must be either attrs or a list!"; 671 672 linkCommands = lib.mapAttrsToList (name: path: '' 673 mkdir -p -- "$(dirname -- ${lib.escapeShellArg "${name}"})" 674 ln -s -- ${lib.escapeShellArg "${path}"} ${lib.escapeShellArg "${name}"} 675 '') entries'; 676 in 677 runCommand name 678 { 679 preferLocalBuild = true; 680 allowSubstitutes = false; 681 passthru.entries = entries'; 682 } 683 '' 684 mkdir -p $out 685 cd $out 686 ${lib.concatStrings linkCommands} 687 ''; 688 689 # TODO: move linkFarmFromDrvs docs to the Nixpkgs manual 690 /* 691 Easily create a linkFarm from a set of derivations. 692 693 This calls linkFarm with a list of entries created from the list of input 694 derivations. It turns each input derivation into an attribute set 695 like { name = drv.name ; path = drv }, and passes this to linkFarm. 696 697 Example: 698 699 # Symlinks the hello, gcc, and ghc derivations in $out 700 linkFarmFromDrvs "myexample" [ pkgs.hello pkgs.gcc pkgs.ghc ] 701 702 This creates a derivation with a directory structure like the following: 703 704 /nix/store/m3s6wkjy9c3wy830201bqsb91nk2yj8c-myexample 705 |-- gcc-wrapper-9.2.0 -> /nix/store/fqhjxf9ii4w4gqcsx59fyw2vvj91486a-gcc-wrapper-9.2.0 706 |-- ghc-8.6.5 -> /nix/store/gnf3s07bglhbbk4y6m76sbh42siym0s6-ghc-8.6.5 707 `-- hello-2.10 -> /nix/store/k0ll91c4npk4lg8lqhx00glg2m735g74-hello-2.10 708 */ 709 linkFarmFromDrvs = 710 name: drvs: 711 let 712 mkEntryFromDrv = drv: { 713 name = drv.name; 714 path = drv; 715 }; 716 in 717 linkFarm name (map mkEntryFromDrv drvs); 718 719 # TODO: move onlyBin docs to the Nixpkgs manual 720 /* 721 Produce a derivation that links to the target derivation's `/bin`, 722 and *only* `/bin`. 723 724 This is useful when your favourite package doesn't have a separate 725 bin output and other contents of the package's output (e.g. setup 726 hooks) cause trouble when used in your environment. 727 */ 728 onlyBin = 729 drv: 730 runCommand "${drv.name}-only-bin" { } '' 731 mkdir -p $out 732 ln -s ${lib.getBin drv}/bin $out/bin 733 ''; 734 735 # Docs in doc/build-helpers/special/makesetuphook.section.md 736 # See https://nixos.org/manual/nixpkgs/unstable/#sec-pkgs.makeSetupHook 737 makeSetupHook = 738 { 739 name ? lib.warn "calling makeSetupHook without passing a name is deprecated." "hook", 740 # hooks go in nativeBuildInputs so these will be nativeBuildInputs 741 propagatedBuildInputs ? [ ], 742 propagatedNativeBuildInputs ? [ ], 743 # these will be buildInputs 744 depsTargetTargetPropagated ? [ ], 745 meta ? { }, 746 passthru ? { }, 747 substitutions ? { }, 748 }: 749 script: 750 runCommand name 751 ( 752 substitutions 753 // { 754 # TODO(@Artturin:) substitutions should be inside the env attrset 755 # but users are likely passing non-substitution arguments through substitutions 756 # turn off __structuredAttrs to unbreak substituteAll 757 __structuredAttrs = false; 758 inherit meta; 759 inherit depsTargetTargetPropagated; 760 inherit propagatedBuildInputs; 761 inherit propagatedNativeBuildInputs; 762 strictDeps = true; 763 # TODO 2023-01, no backport: simplify to inherit passthru; 764 passthru = 765 passthru 766 // optionalAttrs (substitutions ? passthru) ( 767 warn "makeSetupHook (name = ${lib.strings.escapeNixString name}): `substitutions.passthru` is deprecated. Please set `passthru` directly." substitutions.passthru 768 ); 769 } 770 ) 771 ( 772 '' 773 mkdir -p $out/nix-support 774 cp ${script} $out/nix-support/setup-hook 775 recordPropagatedDependencies 776 '' 777 + lib.optionalString (substitutions != { }) '' 778 substituteAll ${script} $out/nix-support/setup-hook 779 '' 780 ); 781 782 # Docs in doc/build-helpers/trivial-build-helpers.chapter.md 783 # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-writeClosure 784 writeClosure = 785 paths: 786 runCommand "runtime-deps" 787 { 788 # Get the cleaner exportReferencesGraph interface 789 __structuredAttrs = true; 790 exportReferencesGraph.graph = paths; 791 nativeBuildInputs = [ jq ]; 792 } 793 '' 794 jq -r ".graph | map(.path) | sort | .[]" "$NIX_ATTRS_JSON_FILE" > "$out" 795 ''; 796 797 # Docs in doc/build-helpers/trivial-build-helpers.chapter.md 798 # See https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-writeDirectReferencesToFile 799 writeDirectReferencesToFile = 800 path: 801 runCommand "runtime-references" 802 { 803 exportReferencesGraph = [ 804 "graph" 805 path 806 ]; 807 inherit path; 808 } 809 '' 810 touch ./references 811 while read p; do 812 read dummy 813 read nrRefs 814 if [[ $p == $path ]]; then 815 for ((i = 0; i < nrRefs; i++)); do 816 read ref; 817 echo $ref >>./references 818 done 819 else 820 for ((i = 0; i < nrRefs; i++)); do 821 read ref; 822 done 823 fi 824 done < graph 825 sort ./references >$out 826 ''; 827 828 # TODO: move writeStringReferencesToFile docs to the Nixpkgs manual 829 /* 830 Extract a string's references to derivations and paths (its 831 context) and write them to a text file, removing the input string 832 itself from the dependency graph. This is useful when you want to 833 make a derivation depend on the string's references, but not its 834 contents (to avoid unnecessary rebuilds, for example). 835 836 Note that this only works as intended on Nix >= 2.3. 837 */ 838 writeStringReferencesToFile = 839 string: 840 /* 841 The basic operation this performs is to copy the string context 842 from `string` to a second string and wrap that string in a 843 derivation. However, that alone is not enough, since nothing in the 844 string refers to the output paths of the derivations/paths in its 845 context, meaning they'll be considered build-time dependencies and 846 removed from the wrapper derivation's closure. Putting the 847 necessary output paths in the new string is however not very 848 straightforward - the attrset returned by `getContext` contains 849 only references to derivations' .drv-paths, not their output 850 paths. In order to "convert" them, we try to extract the 851 corresponding paths from the original string using regex. 852 */ 853 let 854 # Taken from https://github.com/NixOS/nix/blob/130284b8508dad3c70e8160b15f3d62042fc730a/src/libutil/hash.cc#L84 855 nixHashChars = "0123456789abcdfghijklmnpqrsvwxyz"; 856 context = builtins.getContext string; 857 derivations = lib.filterAttrs (n: v: v ? outputs) context; 858 # Objects copied from outside of the store, such as paths and 859 # `builtins.fetch*`ed ones 860 sources = lib.attrNames (lib.filterAttrs (n: v: v ? path) context); 861 packages = lib.mapAttrs' (name: value: { 862 inherit value; 863 name = lib.head (builtins.match "${builtins.storeDir}/[${nixHashChars}]+-(.*)\\.drv" name); 864 }) derivations; 865 # The syntax of output paths differs between outputs named `out` 866 # and other, explicitly named ones. For explicitly named ones, 867 # the output name is suffixed as `-name`, but `out` outputs 868 # aren't suffixed at all, and thus aren't easily distinguished 869 # from named output paths. Therefore, we find all the named ones 870 # first so we can use them to remove false matches when looking 871 # for `out` outputs (see the definition of `outputPaths`). 872 namedOutputPaths = lib.flatten ( 873 lib.mapAttrsToList ( 874 name: value: 875 (map ( 876 output: 877 lib.filter lib.isList ( 878 builtins.split "(${builtins.storeDir}/[${nixHashChars}]+-${name}-${output})" string 879 ) 880 ) (lib.remove "out" value.outputs)) 881 ) packages 882 ); 883 # Only `out` outputs 884 outputPaths = lib.flatten ( 885 lib.mapAttrsToList ( 886 name: value: 887 if lib.elem "out" value.outputs then 888 lib.filter ( 889 x: 890 lib.isList x 891 && 892 # If the matched path is in `namedOutputPaths`, 893 # it's a partial match of an output path where 894 # the output name isn't `out` 895 lib.all (o: !lib.hasPrefix (lib.head x) o) namedOutputPaths 896 ) (builtins.split "(${builtins.storeDir}/[${nixHashChars}]+-${name})" string) 897 else 898 [ ] 899 ) packages 900 ); 901 allPaths = lib.concatStringsSep "\n" (lib.unique (sources ++ namedOutputPaths ++ outputPaths)); 902 allPathsWithContext = builtins.appendContext allPaths context; 903 in 904 if builtins ? getContext then 905 writeText "string-references" allPathsWithContext 906 else 907 writeDirectReferencesToFile (writeText "string-file" string); 908 909 # Docs in doc/build-helpers/fetchers.chapter.md 910 # See https://nixos.org/manual/nixpkgs/unstable/#requirefile 911 requireFile = 912 { 913 name ? null, 914 sha256 ? null, 915 sha1 ? null, 916 hash ? null, 917 url ? null, 918 message ? null, 919 hashMode ? "flat", 920 }: 921 assert (message != null) || (url != null); 922 assert (sha256 != null) || (sha1 != null) || (hash != null); 923 assert (name != null) || (url != null); 924 let 925 msg = 926 if message != null then 927 message 928 else 929 '' 930 Unfortunately, we cannot download file ${name_} automatically. 931 Please go to ${url} to download it yourself, and add it to the Nix store 932 using either 933 nix-store --add-fixed ${hashAlgo} ${name_} 934 or 935 nix-prefetch-url --type ${hashAlgo} file:///path/to/${name_} 936 ''; 937 hashAlgo = 938 if hash != null then 939 (builtins.head (lib.strings.splitString "-" hash)) 940 else if sha256 != null then 941 "sha256" 942 else 943 "sha1"; 944 hashAlgo_ = if hash != null then "" else hashAlgo; 945 hash_ = 946 if hash != null then 947 hash 948 else if sha256 != null then 949 sha256 950 else 951 sha1; 952 name_ = if name == null then baseNameOf (toString url) else name; 953 in 954 stdenvNoCC.mkDerivation { 955 name = name_; 956 outputHashMode = hashMode; 957 outputHashAlgo = hashAlgo_; 958 outputHash = hash_; 959 preferLocalBuild = true; 960 allowSubstitutes = false; 961 builder = writeScript "restrict-message" '' 962 source ${stdenvNoCC}/setup 963 cat <<_EOF_ 964 965 *** 966 ${msg} 967 *** 968 969 _EOF_ 970 exit 1 971 ''; 972 }; 973 974 # TODO: move copyPathToStore docs to the Nixpkgs manual 975 /* 976 Copy a path to the Nix store. 977 Nix automatically copies files to the store before stringifying paths. 978 If you need the store path of a file, ${copyPathToStore <path>} can be 979 shortened to ${<path>}. 980 */ 981 copyPathToStore = builtins.filterSource (p: t: true); 982 983 # TODO: move copyPathsToStore docs to the Nixpkgs manual 984 # Copy a list of paths to the Nix store. 985 copyPathsToStore = builtins.map copyPathToStore; 986 987 # TODO: move applyPatches docs to the Nixpkgs manual 988 /* 989 Applies a list of patches to a source directory. 990 991 Example: 992 993 # Patching nixpkgs: 994 995 applyPatches { 996 src = pkgs.path; 997 patches = [ 998 (pkgs.fetchpatch { 999 url = "https://github.com/NixOS/nixpkgs/commit/1f770d20550a413e508e081ddc08464e9d08ba3d.patch"; 1000 sha256 = "1nlzx171y3r3jbk0qhvnl711kmdk57jlq4na8f8bs8wz2pbffymr"; 1001 }) 1002 ]; 1003 } 1004 */ 1005 applyPatches = 1006 { 1007 src, 1008 name ? 1009 ( 1010 if builtins.typeOf src == "path" then 1011 builtins.baseNameOf src 1012 else if builtins.isAttrs src && builtins.hasAttr "name" src then 1013 src.name 1014 else 1015 throw "applyPatches: please supply a `name` argument because a default name can only be computed when the `src` is a path or is an attribute set with a `name` attribute." 1016 ) 1017 + "-patched", 1018 patches ? [ ], 1019 prePatch ? "", 1020 postPatch ? "", 1021 ... 1022 }@args: 1023 assert lib.assertMsg ( 1024 !args ? meta 1025 ) "applyPatches will not merge 'meta', change it in 'src' instead"; 1026 assert lib.assertMsg ( 1027 !args ? passthru 1028 ) "applyPatches will not merge 'passthru', change it in 'src' instead"; 1029 if patches == [ ] && prePatch == "" && postPatch == "" then 1030 src # nothing to do, so use original src to avoid additional drv 1031 else 1032 let 1033 keepAttrs = names: lib.filterAttrs (name: val: lib.elem name names); 1034 # enables tools like nix-update to determine what src attributes to replace 1035 extraPassthru = lib.optionalAttrs (lib.isAttrs src) ( 1036 keepAttrs [ 1037 "rev" 1038 "tag" 1039 "url" 1040 "outputHash" 1041 "outputHashAlgo" 1042 ] src 1043 ); 1044 in 1045 stdenvNoCC.mkDerivation ( 1046 { 1047 inherit 1048 name 1049 src 1050 patches 1051 prePatch 1052 postPatch 1053 ; 1054 preferLocalBuild = true; 1055 allowSubstitutes = false; 1056 phases = "unpackPhase patchPhase installPhase"; 1057 installPhase = "cp -R ./ $out"; 1058 } 1059 # Carry (and merge) information from the underlying `src` if present. 1060 // (optionalAttrs (src ? meta) { 1061 inherit (src) meta; 1062 }) 1063 // (optionalAttrs (extraPassthru != { } || src ? passthru) { 1064 passthru = extraPassthru // src.passthru or { }; 1065 }) 1066 # Forward any additional arguments to the derivation 1067 // (removeAttrs args [ 1068 "src" 1069 "name" 1070 "patches" 1071 "prePatch" 1072 "postPatch" 1073 ]) 1074 ); 1075 1076 # TODO: move docs to Nixpkgs manual 1077 # An immutable file in the store with a length of 0 bytes. 1078 emptyFile = runCommand "empty-file" { 1079 outputHash = "sha256-d6xi4mKdjkX2JFicDIv5niSzpyI0m/Hnm8GGAIU04kY="; 1080 outputHashMode = "recursive"; 1081 preferLocalBuild = true; 1082 } "touch $out"; 1083 1084 # TODO: move docs to Nixpkgs manual 1085 # An immutable empty directory in the store. 1086 emptyDirectory = runCommand "empty-directory" { 1087 outputHashAlgo = "sha256"; 1088 outputHashMode = "recursive"; 1089 outputHash = "0sjjj9z1dhilhpc8pq4154czrb79z9cm044jvn75kxcjv6v5l2m5"; 1090 preferLocalBuild = true; 1091 } "mkdir $out"; 1092}