Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at netboot-syslinux-multiplatform 1611 lines 48 kB view raw
1# shellcheck shell=bash 2# shellcheck disable=1090,2154,2123,2034,2178,2048,2068,1091 3__nixpkgs_setup_set_original=$- 4set -eu 5set -o pipefail 6 7if [[ -n "${BASH_VERSINFO-}" && "${BASH_VERSINFO-}" -lt 4 ]]; then 8 echo "Detected Bash version that isn't supported by Nixpkgs (${BASH_VERSION})" 9 echo "Please install Bash 4 or greater to continue." 10 exit 1 11fi 12 13shopt -s inherit_errexit 14 15if (( "${NIX_DEBUG:-0}" >= 6 )); then 16 set -x 17fi 18 19if [ -f .attrs.sh ]; then 20 __structuredAttrs=1 21 echo "structuredAttrs is enabled" 22else 23 __structuredAttrs= 24fi 25 26if [ -n "$__structuredAttrs" ]; then 27 for outputName in "${!outputs[@]}"; do 28 # ex: out=/nix/store/... 29 export "$outputName=${outputs[$outputName]}" 30 done 31 32 # $NIX_ATTRS_JSON_FILE pointed to the wrong location in sandbox 33 # https://github.com/NixOS/nix/issues/6736; please keep around until the 34 # fix reaches *every patch version* that's >= lib/minver.nix 35 if ! [[ -e "$NIX_ATTRS_JSON_FILE" ]]; then 36 export NIX_ATTRS_JSON_FILE="$NIX_BUILD_TOP/.attrs.json" 37 fi 38 if ! [[ -e "$NIX_ATTRS_SH_FILE" ]]; then 39 export NIX_ATTRS_SH_FILE="$NIX_BUILD_TOP/.attrs.sh" 40 fi 41else 42 : "${outputs:=out}" 43fi 44 45getAllOutputNames() { 46 if [ -n "$__structuredAttrs" ]; then 47 echo "${!outputs[*]}" 48 else 49 echo "$outputs" 50 fi 51} 52 53###################################################################### 54# Hook handling. 55 56 57# Run all hooks with the specified name in the order in which they 58# were added, stopping if any fails (returns a non-zero exit 59# code). The hooks for <hookName> are the shell function or variable 60# <hookName>, and the values of the shell array ‘<hookName>Hooks’. 61runHook() { 62 local hookName="$1" 63 shift 64 local hooksSlice="${hookName%Hook}Hooks[@]" 65 66 local hook 67 # Hack around old bash being bad and thinking empty arrays are 68 # undefined. 69 for hook in "_callImplicitHook 0 $hookName" ${!hooksSlice+"${!hooksSlice}"}; do 70 _eval "$hook" "$@" 71 done 72 73 return 0 74} 75 76 77# Run all hooks with the specified name, until one succeeds (returns a 78# zero exit code). If none succeed, return a non-zero exit code. 79runOneHook() { 80 local hookName="$1" 81 shift 82 local hooksSlice="${hookName%Hook}Hooks[@]" 83 84 local hook ret=1 85 # Hack around old bash like above 86 for hook in "_callImplicitHook 1 $hookName" ${!hooksSlice+"${!hooksSlice}"}; do 87 if _eval "$hook" "$@"; then 88 ret=0 89 break 90 fi 91 done 92 93 return "$ret" 94} 95 96 97# Run the named hook, either by calling the function with that name or 98# by evaluating the variable with that name. This allows convenient 99# setting of hooks both from Nix expressions (as attributes / 100# environment variables) and from shell scripts (as functions). If you 101# want to allow multiple hooks, use runHook instead. 102_callImplicitHook() { 103 local def="$1" 104 local hookName="$2" 105 if declare -F "$hookName" > /dev/null; then 106 "$hookName" 107 elif type -p "$hookName" > /dev/null; then 108 source "$hookName" 109 elif [ -n "${!hookName:-}" ]; then 110 eval "${!hookName}" 111 else 112 return "$def" 113 fi 114 # `_eval` expects hook to need nounset disable and leave it 115 # disabled anyways, so Ok to to delegate. The alternative of a 116 # return trap is no good because it would affect nested returns. 117} 118 119 120# A function wrapper around ‘eval’ that ensures that ‘return’ inside 121# hooks exits the hook, not the caller. Also will only pass args if 122# command can take them 123_eval() { 124 if declare -F "$1" > /dev/null 2>&1; then 125 "$@" # including args 126 else 127 eval "$1" 128 fi 129} 130 131 132###################################################################### 133# Logging. 134 135# Prints a command such that all word splits are unambiguous. We need 136# to split the command in three parts because the middle format string 137# will be, and must be, repeated for each argument. The first argument 138# goes before the ':' and is just for convenience. 139echoCmd() { 140 printf "%s:" "$1" 141 shift 142 printf ' %q' "$@" 143 echo 144} 145 146 147###################################################################### 148# Error handling. 149 150exitHandler() { 151 exitCode="$?" 152 set +e 153 154 if [ -n "${showBuildStats:-}" ]; then 155 read -r -d '' -a buildTimes < <(times) 156 echo "build times:" 157 echo "user time for the shell ${buildTimes[0]}" 158 echo "system time for the shell ${buildTimes[1]}" 159 echo "user time for all child processes ${buildTimes[2]}" 160 echo "system time for all child processes ${buildTimes[3]}" 161 fi 162 163 if (( "$exitCode" != 0 )); then 164 runHook failureHook 165 166 # If the builder had a non-zero exit code and 167 # $succeedOnFailure is set, create the file 168 # ‘$out/nix-support/failed’ to signal failure, and exit 169 # normally. Otherwise, return the original exit code. 170 if [ -n "${succeedOnFailure:-}" ]; then 171 echo "build failed with exit code $exitCode (ignored)" 172 mkdir -p "$out/nix-support" 173 printf "%s" "$exitCode" > "$out/nix-support/failed" 174 exit 0 175 fi 176 177 else 178 runHook exitHook 179 fi 180 181 return "$exitCode" 182} 183 184trap "exitHandler" EXIT 185 186 187###################################################################### 188# Helper functions. 189 190 191addToSearchPathWithCustomDelimiter() { 192 local delimiter="$1" 193 local varName="$2" 194 local dir="$3" 195 if [[ -d "$dir" && "${!varName:+${delimiter}${!varName}${delimiter}}" \ 196 != *"${delimiter}${dir}${delimiter}"* ]]; then 197 export "${varName}=${!varName:+${!varName}${delimiter}}${dir}" 198 fi 199} 200 201addToSearchPath() { 202 addToSearchPathWithCustomDelimiter ":" "$@" 203} 204 205# Prepend elements to variable "$1", which may come from an attr. 206# 207# This is useful in generic setup code, which must (for now) support 208# both derivations with and without __structuredAttrs true, so the 209# variable may be an array or a space-separated string. 210# 211# Expressions for individual packages should simply switch to array 212# syntax when they switch to setting __structuredAttrs = true. 213prependToVar() { 214 local -n nameref="$1" 215 local useArray type 216 217 if [ -n "$__structuredAttrs" ]; then 218 useArray=true 219 else 220 useArray=false 221 fi 222 223 # check if variable already exist and if it does then do extra checks 224 if declare -p "$1" 2> /dev/null | grep -q '^'; then 225 type="$(declare -p "$1")" 226 if [[ "$type" =~ "declare -A" ]]; then 227 echo "prependToVar(): ERROR: trying to use prependToVar on an associative array." >&2 228 return 1 229 elif [[ "$type" =~ "declare -a" ]]; then 230 useArray=true 231 else 232 useArray=false 233 fi 234 fi 235 236 shift 237 238 if $useArray; then 239 nameref=( "$@" ${nameref+"${nameref[@]}"} ) 240 else 241 nameref="$* ${nameref-}" 242 fi 243} 244 245# Same as above 246appendToVar() { 247 local -n nameref="$1" 248 local useArray type 249 250 if [ -n "$__structuredAttrs" ]; then 251 useArray=true 252 else 253 useArray=false 254 fi 255 256 # check if variable already exist and if it does then do extra checks 257 if declare -p "$1" 2> /dev/null | grep -q '^'; then 258 type="$(declare -p "$1")" 259 if [[ "$type" =~ "declare -A" ]]; then 260 echo "appendToVar(): ERROR: trying to use appendToVar on an associative array, use variable+=([\"X\"]=\"Y\") instead." >&2 261 return 1 262 elif [[ "$type" =~ "declare -a" ]]; then 263 useArray=true 264 else 265 useArray=false 266 fi 267 fi 268 269 shift 270 271 if $useArray; then 272 nameref=( ${nameref+"${nameref[@]}"} "$@" ) 273 else 274 nameref="${nameref-} $*" 275 fi 276} 277 278# Accumulate into `flagsArray` the flags from the named variables. 279# 280# If __structuredAttrs, the variables are all treated as arrays 281# and simply concatenated onto `flagsArray`. 282# 283# If not __structuredAttrs, then: 284# * Each variable is treated as a string, and split on whitespace; 285# * except variables whose names end in "Array", which are treated 286# as arrays. 287_accumFlagsArray() { 288 local name 289 if [ -n "$__structuredAttrs" ]; then 290 for name in "$@"; do 291 local -n nameref="$name" 292 flagsArray+=( ${nameref+"${nameref[@]}"} ) 293 done 294 else 295 for name in "$@"; do 296 local -n nameref="$name" 297 case "$name" in 298 *Array) 299 flagsArray+=( ${nameref+"${nameref[@]}"} ) ;; 300 *) 301 flagsArray+=( ${nameref-} ) ;; 302 esac 303 done 304 fi 305 306} 307 308# Add $1/lib* into rpaths. 309# The function is used in multiple-outputs.sh hook, 310# so it is defined here but tried after the hook. 311_addRpathPrefix() { 312 if [ "${NIX_NO_SELF_RPATH:-0}" != 1 ]; then 313 export NIX_LDFLAGS="-rpath $1/lib ${NIX_LDFLAGS-}" 314 fi 315} 316 317# Return success if the specified file is an ELF object. 318isELF() { 319 local fn="$1" 320 local fd 321 local magic 322 exec {fd}< "$fn" 323 read -r -n 4 -u "$fd" magic 324 exec {fd}<&- 325 if [ "$magic" = $'\177ELF' ]; then return 0; else return 1; fi 326} 327 328# Return success if the specified file is a Mach-O object. 329isMachO() { 330 local fn="$1" 331 local fd 332 local magic 333 exec {fd}< "$fn" 334 read -r -n 4 -u "$fd" magic 335 exec {fd}<&- 336 337 # nix uses 'declare -F' in get-env.sh to retrieve the loaded functions. 338 # If we use the $'string' syntax instead of 'echo -ne' then 'declare' will print the raw characters and break nix. 339 # See https://github.com/NixOS/nixpkgs/pull/138334 and https://github.com/NixOS/nix/issues/5262. 340 341 # https://opensource.apple.com/source/lldb/lldb-310.2.36/examples/python/mach_o.py.auto.html 342 if [[ "$magic" = $(echo -ne "\xfe\xed\xfa\xcf") || "$magic" = $(echo -ne "\xcf\xfa\xed\xfe") ]]; then 343 # MH_MAGIC_64 || MH_CIGAM_64 344 return 0; 345 elif [[ "$magic" = $(echo -ne "\xfe\xed\xfa\xce") || "$magic" = $(echo -ne "\xce\xfa\xed\xfe") ]]; then 346 # MH_MAGIC || MH_CIGAM 347 return 0; 348 elif [[ "$magic" = $(echo -ne "\xca\xfe\xba\xbe") || "$magic" = $(echo -ne "\xbe\xba\xfe\xca") ]]; then 349 # FAT_MAGIC || FAT_CIGAM 350 return 0; 351 else 352 return 1; 353 fi 354} 355 356# Return success if the specified file is a script (i.e. starts with 357# "#!"). 358isScript() { 359 local fn="$1" 360 local fd 361 local magic 362 exec {fd}< "$fn" 363 read -r -n 2 -u "$fd" magic 364 exec {fd}<&- 365 if [[ "$magic" =~ \#! ]]; then return 0; else return 1; fi 366} 367 368# printf unfortunately will print a trailing newline regardless 369printLines() { 370 (( "$#" > 0 )) || return 0 371 printf '%s\n' "$@" 372} 373 374printWords() { 375 (( "$#" > 0 )) || return 0 376 printf '%s ' "$@" 377} 378 379###################################################################### 380# Initialisation. 381 382# If using structured attributes, export variables from `env` to the environment. 383# When not using structured attributes, those variables are already exported. 384if [[ -n $__structuredAttrs ]]; then 385 for envVar in "${!env[@]}"; do 386 declare -x "${envVar}=${env[${envVar}]}" 387 done 388fi 389 390 391# Set a fallback default value for SOURCE_DATE_EPOCH, used by some build tools 392# to provide a deterministic substitute for the "current" time. Note that 393# 315532800 = 1980-01-01 12:00:00. We use this date because python's wheel 394# implementation uses zip archive and zip does not support dates going back to 395# 1970. 396export SOURCE_DATE_EPOCH 397: "${SOURCE_DATE_EPOCH:=315532800}" 398 399 400# Wildcard expansions that don't match should expand to an empty list. 401# This ensures that, for instance, "for i in *; do ...; done" does the 402# right thing. 403shopt -s nullglob 404 405 406# Set up the initial path. 407PATH= 408HOST_PATH= 409for i in $initialPath; do 410 if [ "$i" = / ]; then i=; fi 411 addToSearchPath PATH "$i/bin" 412 413 # For backward compatibility, we add initial path to HOST_PATH so 414 # it can be used in auto patch-shebangs. Unfortunately this will 415 # not work with cross compilation. 416 if [ -z "${strictDeps-}" ]; then 417 addToSearchPath HOST_PATH "$i/bin" 418 fi 419done 420 421unset i 422 423if (( "${NIX_DEBUG:-0}" >= 1 )); then 424 echo "initial path: $PATH" 425fi 426 427 428# Check that the pre-hook initialised SHELL. 429if [ -z "${SHELL:-}" ]; then echo "SHELL not set"; exit 1; fi 430BASH="$SHELL" 431export CONFIG_SHELL="$SHELL" 432 433 434# Execute the pre-hook. 435if [ -z "${shell:-}" ]; then export shell="$SHELL"; fi 436runHook preHook 437 438 439# Allow the caller to augment buildInputs (it's not always possible to 440# do this before the call to setup.sh, since the PATH is empty at that 441# point; here we have a basic Unix environment). 442runHook addInputsHook 443 444 445# Package accumulators 446 447declare -a pkgsBuildBuild pkgsBuildHost pkgsBuildTarget 448declare -a pkgsHostHost pkgsHostTarget 449declare -a pkgsTargetTarget 450 451declare -a pkgBuildAccumVars=(pkgsBuildBuild pkgsBuildHost pkgsBuildTarget) 452declare -a pkgHostAccumVars=(pkgsHostHost pkgsHostTarget) 453declare -a pkgTargetAccumVars=(pkgsTargetTarget) 454 455declare -a pkgAccumVarVars=(pkgBuildAccumVars pkgHostAccumVars pkgTargetAccumVars) 456 457 458# Hooks 459 460declare -a envBuildBuildHooks envBuildHostHooks envBuildTargetHooks 461declare -a envHostHostHooks envHostTargetHooks 462declare -a envTargetTargetHooks 463 464declare -a pkgBuildHookVars=(envBuildBuildHook envBuildHostHook envBuildTargetHook) 465declare -a pkgHostHookVars=(envHostHostHook envHostTargetHook) 466declare -a pkgTargetHookVars=(envTargetTargetHook) 467 468declare -a pkgHookVarVars=(pkgBuildHookVars pkgHostHookVars pkgTargetHookVars) 469 470# those variables are declared here, since where and if they are used varies 471declare -a preFixupHooks fixupOutputHooks preConfigureHooks postFixupHooks postUnpackHooks unpackCmdHooks 472 473# Add env hooks for all sorts of deps with the specified host offset. 474addEnvHooks() { 475 local depHostOffset="$1" 476 shift 477 local pkgHookVarsSlice="${pkgHookVarVars[$depHostOffset + 1]}[@]" 478 local pkgHookVar 479 for pkgHookVar in "${!pkgHookVarsSlice}"; do 480 eval "${pkgHookVar}s"'+=("$@")' 481 done 482} 483 484 485# Propagated dep files 486 487declare -a propagatedBuildDepFiles=( 488 propagated-build-build-deps 489 propagated-native-build-inputs # Legacy name for back-compat 490 propagated-build-target-deps 491) 492declare -a propagatedHostDepFiles=( 493 propagated-host-host-deps 494 propagated-build-inputs # Legacy name for back-compat 495) 496declare -a propagatedTargetDepFiles=( 497 propagated-target-target-deps 498) 499declare -a propagatedDepFilesVars=( 500 propagatedBuildDepFiles 501 propagatedHostDepFiles 502 propagatedTargetDepFiles 503) 504 505# Platform offsets: build = -1, host = 0, target = 1 506declare -a allPlatOffsets=(-1 0 1) 507 508 509# Mutually-recursively find all build inputs. See the dependency section of the 510# stdenv chapter of the Nixpkgs manual for the specification this algorithm 511# implements. 512findInputs() { 513 local -r pkg="$1" 514 local -r hostOffset="$2" 515 local -r targetOffset="$3" 516 517 # Sanity check 518 (( hostOffset <= targetOffset )) || exit 1 519 520 local varVar="${pkgAccumVarVars[hostOffset + 1]}" 521 local varRef="$varVar[$((targetOffset - hostOffset))]" 522 local var="${!varRef}" 523 unset -v varVar varRef 524 525 # TODO(@Ericson2314): Restore using associative array once Darwin 526 # nix-shell doesn't use impure bash. This should replace the O(n) 527 # case with an O(1) hash map lookup, assuming bash is implemented 528 # well :D. 529 local varSlice="$var[*]" 530 # ${..-} to hack around old bash empty array problem 531 case "${!varSlice-}" in 532 *" $pkg "*) return 0 ;; 533 esac 534 unset -v varSlice 535 536 eval "$var"'+=("$pkg")' 537 538 if ! [ -e "$pkg" ]; then 539 echo "build input $pkg does not exist" >&2 540 exit 1 541 fi 542 543 # The current package's host and target offset together 544 # provide a <=-preserving homomorphism from the relative 545 # offsets to current offset 546 function mapOffset() { 547 local -r inputOffset="$1" 548 local -n outputOffset="$2" 549 if (( inputOffset <= 0 )); then 550 outputOffset=$((inputOffset + hostOffset)) 551 else 552 outputOffset=$((inputOffset - 1 + targetOffset)) 553 fi 554 } 555 556 # Host offset relative to that of the package whose immediate 557 # dependencies we are currently exploring. 558 local relHostOffset 559 for relHostOffset in "${allPlatOffsets[@]}"; do 560 # `+ 1` so we start at 0 for valid index 561 local files="${propagatedDepFilesVars[relHostOffset + 1]}" 562 563 # Host offset relative to the package currently being 564 # built---as absolute an offset as will be used. 565 local hostOffsetNext 566 mapOffset "$relHostOffset" hostOffsetNext 567 568 # Ensure we're in bounds relative to the package currently 569 # being built. 570 (( -1 <= hostOffsetNext && hostOffsetNext <= 1 )) || continue 571 572 # Target offset relative to the *host* offset of the package 573 # whose immediate dependencies we are currently exploring. 574 local relTargetOffset 575 for relTargetOffset in "${allPlatOffsets[@]}"; do 576 (( "$relHostOffset" <= "$relTargetOffset" )) || continue 577 578 local fileRef="${files}[$relTargetOffset - $relHostOffset]" 579 local file="${!fileRef}" 580 unset -v fileRef 581 582 # Target offset relative to the package currently being 583 # built. 584 local targetOffsetNext 585 mapOffset "$relTargetOffset" targetOffsetNext 586 587 # Once again, ensure we're in bounds relative to the 588 # package currently being built. 589 (( -1 <= hostOffsetNext && hostOffsetNext <= 1 )) || continue 590 591 [[ -f "$pkg/nix-support/$file" ]] || continue 592 593 local pkgNext 594 read -r -d '' pkgNext < "$pkg/nix-support/$file" || true 595 for pkgNext in $pkgNext; do 596 findInputs "$pkgNext" "$hostOffsetNext" "$targetOffsetNext" 597 done 598 done 599 done 600} 601 602# The way we handle deps* and *Inputs works with structured attrs 603# either enabled or disabled. For this it's convenient that the items 604# in each list must be store paths, and therefore space-free. 605 606# Make sure all are at least defined as empty 607: "${depsBuildBuild=}" "${depsBuildBuildPropagated=}" 608: "${nativeBuildInputs=}" "${propagatedNativeBuildInputs=}" "${defaultNativeBuildInputs=}" 609: "${depsBuildTarget=}" "${depsBuildTargetPropagated=}" 610: "${depsHostHost=}" "${depsHostHostPropagated=}" 611: "${buildInputs=}" "${propagatedBuildInputs=}" "${defaultBuildInputs=}" 612: "${depsTargetTarget=}" "${depsTargetTargetPropagated=}" 613 614for pkg in ${depsBuildBuild[@]} ${depsBuildBuildPropagated[@]}; do 615 findInputs "$pkg" -1 -1 616done 617for pkg in ${nativeBuildInputs[@]} ${propagatedNativeBuildInputs[@]}; do 618 findInputs "$pkg" -1 0 619done 620for pkg in ${depsBuildTarget[@]} ${depsBuildTargetPropagated[@]}; do 621 findInputs "$pkg" -1 1 622done 623for pkg in ${depsHostHost[@]} ${depsHostHostPropagated[@]}; do 624 findInputs "$pkg" 0 0 625done 626for pkg in ${buildInputs[@]} ${propagatedBuildInputs[@]} ; do 627 findInputs "$pkg" 0 1 628done 629for pkg in ${depsTargetTarget[@]} ${depsTargetTargetPropagated[@]}; do 630 findInputs "$pkg" 1 1 631done 632# Default inputs must be processed last 633for pkg in ${defaultNativeBuildInputs[@]}; do 634 findInputs "$pkg" -1 0 635done 636for pkg in ${defaultBuildInputs[@]}; do 637 findInputs "$pkg" 0 1 638done 639 640# Add package to the future PATH and run setup hooks 641activatePackage() { 642 local pkg="$1" 643 local -r hostOffset="$2" 644 local -r targetOffset="$3" 645 646 # Sanity check 647 (( hostOffset <= targetOffset )) || exit 1 648 649 if [ -f "$pkg" ]; then 650 source "$pkg" 651 fi 652 653 # Only dependencies whose host platform is guaranteed to match the 654 # build platform are included here. That would be `depsBuild*`, 655 # and legacy `nativeBuildInputs`, in general. If we aren't cross 656 # compiling, however, everything can be put on the PATH. To ease 657 # the transition, we do include everything in that case. 658 # 659 # TODO(@Ericson2314): Don't special-case native compilation 660 if [[ -z "${strictDeps-}" || "$hostOffset" -le -1 ]]; then 661 addToSearchPath _PATH "$pkg/bin" 662 fi 663 664 if (( hostOffset <= -1 )); then 665 addToSearchPath _XDG_DATA_DIRS "$pkg/share" 666 fi 667 668 if [[ "$hostOffset" -eq 0 && -d "$pkg/bin" ]]; then 669 addToSearchPath _HOST_PATH "$pkg/bin" 670 fi 671 672 if [[ -f "$pkg/nix-support/setup-hook" ]]; then 673 source "$pkg/nix-support/setup-hook" 674 fi 675} 676 677_activatePkgs() { 678 local hostOffset targetOffset 679 local pkg 680 681 for hostOffset in "${allPlatOffsets[@]}"; do 682 local pkgsVar="${pkgAccumVarVars[hostOffset + 1]}" 683 for targetOffset in "${allPlatOffsets[@]}"; do 684 (( hostOffset <= targetOffset )) || continue 685 local pkgsRef="${pkgsVar}[$targetOffset - $hostOffset]" 686 local pkgsSlice="${!pkgsRef}[@]" 687 for pkg in ${!pkgsSlice+"${!pkgsSlice}"}; do 688 activatePackage "$pkg" "$hostOffset" "$targetOffset" 689 done 690 done 691 done 692} 693 694# Run the package setup hooks and build _PATH 695_activatePkgs 696 697# Set the relevant environment variables to point to the build inputs 698# found above. 699# 700# These `depOffset`s, beyond indexing the arrays, also tell the env 701# hook what sort of dependency (ignoring propagatedness) is being 702# passed to the env hook. In a real language, we'd append a closure 703# with this information to the relevant env hook array, but bash 704# doesn't have closures, so it's easier to just pass this in. 705_addToEnv() { 706 local depHostOffset depTargetOffset 707 local pkg 708 709 for depHostOffset in "${allPlatOffsets[@]}"; do 710 local hookVar="${pkgHookVarVars[depHostOffset + 1]}" 711 local pkgsVar="${pkgAccumVarVars[depHostOffset + 1]}" 712 for depTargetOffset in "${allPlatOffsets[@]}"; do 713 (( depHostOffset <= depTargetOffset )) || continue 714 local hookRef="${hookVar}[$depTargetOffset - $depHostOffset]" 715 if [[ -z "${strictDeps-}" ]]; then 716 717 # Keep track of which packages we have visited before. 718 local visitedPkgs="" 719 720 # Apply environment hooks to all packages during native 721 # compilation to ease the transition. 722 # 723 # TODO(@Ericson2314): Don't special-case native compilation 724 for pkg in \ 725 "${pkgsBuildBuild[@]}" \ 726 "${pkgsBuildHost[@]}" \ 727 "${pkgsBuildTarget[@]}" \ 728 "${pkgsHostHost[@]}" \ 729 "${pkgsHostTarget[@]}" \ 730 "${pkgsTargetTarget[@]}" 731 do 732 if [[ "$visitedPkgs" = *"$pkg"* ]]; then 733 continue 734 fi 735 runHook "${!hookRef}" "$pkg" 736 visitedPkgs+=" $pkg" 737 done 738 else 739 local pkgsRef="${pkgsVar}[$depTargetOffset - $depHostOffset]" 740 local pkgsSlice="${!pkgsRef}[@]" 741 for pkg in ${!pkgsSlice+"${!pkgsSlice}"}; do 742 runHook "${!hookRef}" "$pkg" 743 done 744 fi 745 done 746 done 747} 748 749# Run the package-specific hooks set by the setup-hook scripts. 750_addToEnv 751 752 753# Unset setup-specific declared variables 754unset allPlatOffsets 755unset pkgBuildAccumVars pkgHostAccumVars pkgTargetAccumVars pkgAccumVarVars 756unset pkgBuildHookVars pkgHostHookVars pkgTargetHookVars pkgHookVarVars 757unset propagatedDepFilesVars 758 759 760_addRpathPrefix "$out" 761 762 763# Set the TZ (timezone) environment variable, otherwise commands like 764# `date' will complain (e.g., `Tue Mar 9 10:01:47 Local time zone must 765# be set--see zic manual page 2004'). 766export TZ=UTC 767 768 769# Set the prefix. This is generally $out, but it can be overriden, 770# for instance if we just want to perform a test build/install to a 771# temporary location and write a build report to $out. 772if [ -z "${prefix:-}" ]; then 773 prefix="$out"; 774fi 775 776if [ "${useTempPrefix:-}" = 1 ]; then 777 prefix="$NIX_BUILD_TOP/tmp_prefix"; 778fi 779 780 781PATH="${_PATH-}${_PATH:+${PATH:+:}}$PATH" 782HOST_PATH="${_HOST_PATH-}${_HOST_PATH:+${HOST_PATH:+:}}$HOST_PATH" 783export XDG_DATA_DIRS="${_XDG_DATA_DIRS-}${_XDG_DATA_DIRS:+${XDG_DATA_DIRS:+:}}${XDG_DATA_DIRS-}" 784if (( "${NIX_DEBUG:-0}" >= 1 )); then 785 echo "final path: $PATH" 786 echo "final host path: $HOST_PATH" 787 echo "final data dirs: $XDG_DATA_DIRS" 788fi 789 790unset _PATH 791unset _HOST_PATH 792unset _XDG_DATA_DIRS 793 794 795# Normalize the NIX_BUILD_CORES variable. The value might be 0, which 796# means that we're supposed to try and auto-detect the number of 797# available CPU cores at run-time. 798 799NIX_BUILD_CORES="${NIX_BUILD_CORES:-1}" 800if ((NIX_BUILD_CORES <= 0)); then 801 guess=$(nproc 2>/dev/null || true) 802 ((NIX_BUILD_CORES = guess <= 0 ? 1 : guess)) 803fi 804export NIX_BUILD_CORES 805 806 807# Prevent SSL libraries from using certificates in /etc/ssl, unless set explicitly. 808# Leave it in impure shells for convenience. 809if [[ -z "${NIX_SSL_CERT_FILE:-}" && "${IN_NIX_SHELL:-}" != "impure" ]]; then 810 export NIX_SSL_CERT_FILE=/no-cert-file.crt 811fi 812# Another variant left for compatibility. 813if [[ -z "${SSL_CERT_FILE:-}" && "${IN_NIX_SHELL:-}" != "impure" ]]; then 814 export SSL_CERT_FILE=/no-cert-file.crt 815fi 816 817 818###################################################################### 819# Textual substitution functions. 820 821 822substituteStream() { 823 local var=$1 824 local description=$2 825 shift 2 826 827 while (( "$#" )); do 828 case "$1" in 829 --replace) 830 pattern="$2" 831 replacement="$3" 832 shift 3 833 local savedvar 834 savedvar="${!var}" 835 eval "$var"'=${'"$var"'//"$pattern"/"$replacement"}' 836 if [ "$pattern" != "$replacement" ]; then 837 if [ "${!var}" == "$savedvar" ]; then 838 echo "substituteStream(): WARNING: pattern '$pattern' doesn't match anything in $description" >&2 839 fi 840 fi 841 ;; 842 843 --subst-var) 844 local varName="$2" 845 shift 2 846 # check if the used nix attribute name is a valid bash name 847 if ! [[ "$varName" =~ ^[a-zA-Z_][a-zA-Z0-9_]*$ ]]; then 848 echo "substituteStream(): ERROR: substitution variables must be valid Bash names, \"$varName\" isn't." >&2 849 return 1 850 fi 851 if [ -z ${!varName+x} ]; then 852 echo "substituteStream(): ERROR: variable \$$varName is unset" >&2 853 return 1 854 fi 855 pattern="@$varName@" 856 replacement="${!varName}" 857 eval "$var"'=${'"$var"'//"$pattern"/"$replacement"}' 858 ;; 859 860 --subst-var-by) 861 pattern="@$2@" 862 replacement="$3" 863 eval "$var"'=${'"$var"'//"$pattern"/"$replacement"}' 864 shift 3 865 ;; 866 867 *) 868 echo "substituteStream(): ERROR: Invalid command line argument: $1" >&2 869 return 1 870 ;; 871 esac 872 done 873 874 printf "%s" "${!var}" 875} 876 877# put the content of a file in a variable 878# fail loudly if provided with a binary (containing null bytes) 879consumeEntire() { 880 # read returns non-0 on EOF, so we want read to fail 881 if IFS='' read -r -d '' "$1" ; then 882 echo "consumeEntire(): ERROR: Input null bytes, won't process" >&2 883 return 1 884 fi 885} 886 887substitute() { 888 local input="$1" 889 local output="$2" 890 shift 2 891 892 if [ ! -f "$input" ]; then 893 echo "substitute(): ERROR: file '$input' does not exist" >&2 894 return 1 895 fi 896 897 local content 898 consumeEntire content < "$input" 899 900 if [ -e "$output" ]; then chmod +w "$output"; fi 901 substituteStream content "file '$input'" "$@" > "$output" 902} 903 904substituteInPlace() { 905 local -a fileNames=() 906 for arg in "$@"; do 907 if [[ "$arg" = "--"* ]]; then 908 break 909 fi 910 fileNames+=("$arg") 911 shift 912 done 913 914 for file in "${fileNames[@]}"; do 915 substitute "$file" "$file" "$@" 916 done 917} 918 919_allFlags() { 920 # export some local variables for the awk below 921 # so some substitutions such as name don't have to be in the env attrset 922 # when __structuredAttrs is enabled 923 export system pname name version 924 for varName in $(awk 'BEGIN { for (v in ENVIRON) if (v ~ /^[a-z][a-zA-Z0-9_]*$/) print v }'); do 925 if (( "${NIX_DEBUG:-0}" >= 1 )); then 926 printf "@%s@ -> %q\n" "${varName}" "${!varName}" 927 fi 928 args+=("--subst-var" "$varName") 929 done 930} 931 932substituteAllStream() { 933 local -a args=() 934 _allFlags 935 936 substituteStream "$1" "$2" "${args[@]}" 937} 938 939# Substitute all environment variables that start with a lowercase character and 940# are valid Bash names. 941substituteAll() { 942 local input="$1" 943 local output="$2" 944 945 local -a args=() 946 _allFlags 947 948 substitute "$input" "$output" "${args[@]}" 949} 950 951 952substituteAllInPlace() { 953 local fileName="$1" 954 shift 955 substituteAll "$fileName" "$fileName" "$@" 956} 957 958 959###################################################################### 960# What follows is the generic builder. 961 962 963# This function is useful for debugging broken Nix builds. It dumps 964# all environment variables to a file `env-vars' in the build 965# directory. If the build fails and the `-K' option is used, you can 966# then go to the build directory and source in `env-vars' to reproduce 967# the environment used for building. 968dumpVars() { 969 if [ "${noDumpEnvVars:-0}" != 1 ]; then 970 export 2>/dev/null >| "$NIX_BUILD_TOP/env-vars" || true 971 fi 972} 973 974 975# Utility function: echo the base name of the given path, with the 976# prefix `HASH-' removed, if present. 977stripHash() { 978 local strippedName casematchOpt=0 979 # On separate line for `set -e` 980 strippedName="$(basename -- "$1")" 981 shopt -q nocasematch && casematchOpt=1 982 shopt -u nocasematch 983 if [[ "$strippedName" =~ ^[a-z0-9]{32}- ]]; then 984 echo "${strippedName:33}" 985 else 986 echo "$strippedName" 987 fi 988 if (( casematchOpt )); then shopt -s nocasematch; fi 989} 990 991 992recordPropagatedDependencies() { 993 # Propagate dependencies into the development output. 994 declare -ra flatVars=( 995 # Build 996 depsBuildBuildPropagated 997 propagatedNativeBuildInputs 998 depsBuildTargetPropagated 999 # Host 1000 depsHostHostPropagated 1001 propagatedBuildInputs 1002 # Target 1003 depsTargetTargetPropagated 1004 ) 1005 declare -ra flatFiles=( 1006 "${propagatedBuildDepFiles[@]}" 1007 "${propagatedHostDepFiles[@]}" 1008 "${propagatedTargetDepFiles[@]}" 1009 ) 1010 1011 local propagatedInputsIndex 1012 for propagatedInputsIndex in "${!flatVars[@]}"; do 1013 local propagatedInputsSlice="${flatVars[$propagatedInputsIndex]}[@]" 1014 local propagatedInputsFile="${flatFiles[$propagatedInputsIndex]}" 1015 1016 [[ "${!propagatedInputsSlice}" ]] || continue 1017 1018 mkdir -p "${!outputDev}/nix-support" 1019 # shellcheck disable=SC2086 1020 printWords ${!propagatedInputsSlice} > "${!outputDev}/nix-support/$propagatedInputsFile" 1021 done 1022} 1023 1024 1025unpackCmdHooks+=(_defaultUnpack) 1026_defaultUnpack() { 1027 local fn="$1" 1028 local destination 1029 1030 if [ -d "$fn" ]; then 1031 1032 destination="$(stripHash "$fn")" 1033 1034 if [ -e "$destination" ]; then 1035 echo "Cannot copy $fn to $destination: destination already exists!" 1036 echo "Did you specify two \"srcs\" with the same \"name\"?" 1037 return 1 1038 fi 1039 1040 # We can't preserve hardlinks because they may have been 1041 # introduced by store optimization, which might break things 1042 # in the build. 1043 cp -pr --reflink=auto -- "$fn" "$destination" 1044 1045 else 1046 1047 case "$fn" in 1048 *.tar.xz | *.tar.lzma | *.txz) 1049 # Don't rely on tar knowing about .xz. 1050 xz -d < "$fn" | tar xf - --warning=no-timestamp 1051 ;; 1052 *.tar | *.tar.* | *.tgz | *.tbz2 | *.tbz) 1053 # GNU tar can automatically select the decompression method 1054 # (info "(tar) gzip"). 1055 tar xf "$fn" --warning=no-timestamp 1056 ;; 1057 *) 1058 return 1 1059 ;; 1060 esac 1061 1062 fi 1063} 1064 1065 1066unpackFile() { 1067 curSrc="$1" 1068 echo "unpacking source archive $curSrc" 1069 if ! runOneHook unpackCmd "$curSrc"; then 1070 echo "do not know how to unpack source archive $curSrc" 1071 exit 1 1072 fi 1073} 1074 1075 1076unpackPhase() { 1077 runHook preUnpack 1078 1079 if [ -z "${srcs:-}" ]; then 1080 if [ -z "${src:-}" ]; then 1081 # shellcheck disable=SC2016 1082 echo 'variable $src or $srcs should point to the source' 1083 exit 1 1084 fi 1085 srcs="$src" 1086 fi 1087 1088 local -a srcsArray 1089 if [ -n "$__structuredAttrs" ]; then 1090 srcsArray=( "${srcs[@]}" ) 1091 else 1092 srcsArray=( $srcs ) 1093 fi 1094 1095 # To determine the source directory created by unpacking the 1096 # source archives, we record the contents of the current 1097 # directory, then look below which directory got added. Yeah, 1098 # it's rather hacky. 1099 local dirsBefore="" 1100 for i in *; do 1101 if [ -d "$i" ]; then 1102 dirsBefore="$dirsBefore $i " 1103 fi 1104 done 1105 1106 # Unpack all source archives. 1107 for i in "${srcsArray[@]}"; do 1108 unpackFile "$i" 1109 done 1110 1111 # Find the source directory. 1112 1113 # set to empty if unset 1114 : "${sourceRoot=}" 1115 1116 if [ -n "${setSourceRoot:-}" ]; then 1117 runOneHook setSourceRoot 1118 elif [ -z "$sourceRoot" ]; then 1119 for i in *; do 1120 if [ -d "$i" ]; then 1121 case $dirsBefore in 1122 *\ $i\ *) 1123 ;; 1124 *) 1125 if [ -n "$sourceRoot" ]; then 1126 echo "unpacker produced multiple directories" 1127 exit 1 1128 fi 1129 sourceRoot="$i" 1130 ;; 1131 esac 1132 fi 1133 done 1134 fi 1135 1136 if [ -z "$sourceRoot" ]; then 1137 echo "unpacker appears to have produced no directories" 1138 exit 1 1139 fi 1140 1141 echo "source root is $sourceRoot" 1142 1143 # By default, add write permission to the sources. This is often 1144 # necessary when sources have been copied from other store 1145 # locations. 1146 if [ "${dontMakeSourcesWritable:-0}" != 1 ]; then 1147 chmod -R u+w -- "$sourceRoot" 1148 fi 1149 1150 runHook postUnpack 1151} 1152 1153 1154patchPhase() { 1155 runHook prePatch 1156 1157 local -a patchesArray 1158 if [ -n "$__structuredAttrs" ]; then 1159 patchesArray=( ${patches:+"${patches[@]}"} ) 1160 else 1161 patchesArray=( ${patches:-} ) 1162 fi 1163 1164 for i in "${patchesArray[@]}"; do 1165 echo "applying patch $i" 1166 local uncompress=cat 1167 case "$i" in 1168 *.gz) 1169 uncompress="gzip -d" 1170 ;; 1171 *.bz2) 1172 uncompress="bzip2 -d" 1173 ;; 1174 *.xz) 1175 uncompress="xz -d" 1176 ;; 1177 *.lzma) 1178 uncompress="lzma -d" 1179 ;; 1180 esac 1181 1182 local -a flagsArray 1183 if [ -n "$__structuredAttrs" ]; then 1184 flagsArray=( "${patchFlags[@]:--p1}" ) 1185 else 1186 # shellcheck disable=SC2086 1187 flagsArray=( ${patchFlags:--p1} ) 1188 fi 1189 # "2>&1" is a hack to make patch fail if the decompressor fails (nonexistent patch, etc.) 1190 # shellcheck disable=SC2086 1191 $uncompress < "$i" 2>&1 | patch "${flagsArray[@]}" 1192 done 1193 1194 runHook postPatch 1195} 1196 1197 1198fixLibtool() { 1199 local search_path 1200 for flag in $NIX_LDFLAGS; do 1201 case $flag in 1202 -L*) 1203 search_path+=" ${flag#-L}" 1204 ;; 1205 esac 1206 done 1207 1208 sed -i "$1" \ 1209 -e "s^eval \(sys_lib_search_path=\).*^\1'$search_path'^" \ 1210 -e 's^eval sys_lib_.+search_path=.*^^' 1211} 1212 1213 1214configurePhase() { 1215 runHook preConfigure 1216 1217 # set to empty if unset 1218 : "${configureScript=}" 1219 1220 if [[ -z "$configureScript" && -x ./configure ]]; then 1221 configureScript=./configure 1222 fi 1223 1224 if [ -z "${dontFixLibtool:-}" ]; then 1225 export lt_cv_deplibs_check_method="${lt_cv_deplibs_check_method-pass_all}" 1226 local i 1227 find . -iname "ltmain.sh" -print0 | while IFS='' read -r -d '' i; do 1228 echo "fixing libtool script $i" 1229 fixLibtool "$i" 1230 done 1231 1232 # replace `/usr/bin/file` with `file` in any `configure` 1233 # scripts with vendored libtool code. Preserve mtimes to 1234 # prevent some packages (e.g. libidn2) from spontaneously 1235 # autoreconf'ing themselves 1236 CONFIGURE_MTIME_REFERENCE=$(mktemp configure.mtime.reference.XXXXXX) 1237 find . \ 1238 -executable \ 1239 -type f \ 1240 -name configure \ 1241 -exec grep -l 'GNU Libtool is free software; you can redistribute it and/or modify' {} \; \ 1242 -exec touch -r {} "$CONFIGURE_MTIME_REFERENCE" \; \ 1243 -exec sed -i s_/usr/bin/file_file_g {} \; \ 1244 -exec touch -r "$CONFIGURE_MTIME_REFERENCE" {} \; 1245 rm -f "$CONFIGURE_MTIME_REFERENCE" 1246 fi 1247 1248 if [[ -z "${dontAddPrefix:-}" && -n "$prefix" ]]; then 1249 prependToVar configureFlags "${prefixKey:---prefix=}$prefix" 1250 fi 1251 1252 if [[ -f "$configureScript" ]]; then 1253 # Add --disable-dependency-tracking to speed up some builds. 1254 if [ -z "${dontAddDisableDepTrack:-}" ]; then 1255 if grep -q dependency-tracking "$configureScript"; then 1256 prependToVar configureFlags --disable-dependency-tracking 1257 fi 1258 fi 1259 1260 # By default, disable static builds. 1261 if [ -z "${dontDisableStatic:-}" ]; then 1262 if grep -q enable-static "$configureScript"; then 1263 prependToVar configureFlags --disable-static 1264 fi 1265 fi 1266 fi 1267 1268 if [ -n "$configureScript" ]; then 1269 local -a flagsArray 1270 _accumFlagsArray configureFlags configureFlagsArray 1271 1272 echoCmd 'configure flags' "${flagsArray[@]}" 1273 # shellcheck disable=SC2086 1274 $configureScript "${flagsArray[@]}" 1275 unset flagsArray 1276 else 1277 echo "no configure script, doing nothing" 1278 fi 1279 1280 runHook postConfigure 1281} 1282 1283 1284buildPhase() { 1285 runHook preBuild 1286 1287 if [[ -z "${makeFlags-}" && -z "${makefile:-}" && ! ( -e Makefile || -e makefile || -e GNUmakefile ) ]]; then 1288 echo "no Makefile or custom buildPhase, doing nothing" 1289 else 1290 foundMakefile=1 1291 1292 # shellcheck disable=SC2086 1293 local flagsArray=( 1294 ${enableParallelBuilding:+-j${NIX_BUILD_CORES}} 1295 SHELL=$SHELL 1296 ) 1297 _accumFlagsArray makeFlags makeFlagsArray buildFlags buildFlagsArray 1298 1299 echoCmd 'build flags' "${flagsArray[@]}" 1300 make ${makefile:+-f $makefile} "${flagsArray[@]}" 1301 unset flagsArray 1302 fi 1303 1304 runHook postBuild 1305} 1306 1307 1308checkPhase() { 1309 runHook preCheck 1310 1311 if [[ -z "${foundMakefile:-}" ]]; then 1312 echo "no Makefile or custom checkPhase, doing nothing" 1313 runHook postCheck 1314 return 1315 fi 1316 1317 if [[ -z "${checkTarget:-}" ]]; then 1318 #TODO(@oxij): should flagsArray influence make -n? 1319 if make -n ${makefile:+-f $makefile} check >/dev/null 2>&1; then 1320 checkTarget=check 1321 elif make -n ${makefile:+-f $makefile} test >/dev/null 2>&1; then 1322 checkTarget=test 1323 fi 1324 fi 1325 1326 if [[ -z "${checkTarget:-}" ]]; then 1327 echo "no check/test target in ${makefile:-Makefile}, doing nothing" 1328 else 1329 # Old bash empty array hack 1330 # shellcheck disable=SC2086 1331 local flagsArray=( 1332 ${enableParallelChecking:+-j${NIX_BUILD_CORES}} 1333 SHELL=$SHELL 1334 ) 1335 1336 _accumFlagsArray makeFlags makeFlagsArray 1337 if [ -n "$__structuredAttrs" ]; then 1338 flagsArray+=( "${checkFlags[@]:-VERBOSE=y}" ) 1339 else 1340 flagsArray+=( ${checkFlags:-VERBOSE=y} ) 1341 fi 1342 _accumFlagsArray checkFlagsArray 1343 flagsArray+=( ${checkTarget} ) 1344 1345 echoCmd 'check flags' "${flagsArray[@]}" 1346 make ${makefile:+-f $makefile} "${flagsArray[@]}" 1347 1348 unset flagsArray 1349 fi 1350 1351 runHook postCheck 1352} 1353 1354 1355installPhase() { 1356 runHook preInstall 1357 1358 # Dont reuse 'foundMakefile' set in buildPhase, a makefile may have been created in buildPhase 1359 if [[ -z "${makeFlags-}" && -z "${makefile:-}" && ! ( -e Makefile || -e makefile || -e GNUmakefile ) ]]; then 1360 echo "no Makefile or custom installPhase, doing nothing" 1361 runHook postInstall 1362 return 1363 else 1364 foundMakefile=1 1365 fi 1366 1367 if [ -n "$prefix" ]; then 1368 mkdir -p "$prefix" 1369 fi 1370 1371 # shellcheck disable=SC2086 1372 local flagsArray=( 1373 ${enableParallelInstalling:+-j${NIX_BUILD_CORES}} 1374 SHELL=$SHELL 1375 ) 1376 _accumFlagsArray makeFlags makeFlagsArray installFlags installFlagsArray 1377 if [ -n "$__structuredAttrs" ]; then 1378 flagsArray+=( "${installTargets[@]:-install}" ) 1379 else 1380 flagsArray+=( ${installTargets:-install} ) 1381 fi 1382 1383 echoCmd 'install flags' "${flagsArray[@]}" 1384 make ${makefile:+-f $makefile} "${flagsArray[@]}" 1385 unset flagsArray 1386 1387 runHook postInstall 1388} 1389 1390 1391# The fixup phase performs generic, package-independent stuff, like 1392# stripping binaries, running patchelf and setting 1393# propagated-build-inputs. 1394fixupPhase() { 1395 # Make sure everything is writable so "strip" et al. work. 1396 local output 1397 for output in $(getAllOutputNames); do 1398 if [ -e "${!output}" ]; then chmod -R u+w "${!output}"; fi 1399 done 1400 1401 runHook preFixup 1402 1403 # Apply fixup to each output. 1404 local output 1405 for output in $(getAllOutputNames); do 1406 prefix="${!output}" runHook fixupOutput 1407 done 1408 1409 1410 # record propagated dependencies & setup hook into the development output. 1411 recordPropagatedDependencies 1412 1413 if [ -n "${setupHook:-}" ]; then 1414 mkdir -p "${!outputDev}/nix-support" 1415 substituteAll "$setupHook" "${!outputDev}/nix-support/setup-hook" 1416 fi 1417 1418 # TODO(@Ericson2314): Remove after https://github.com/NixOS/nixpkgs/pull/31414 1419 if [ -n "${setupHooks:-}" ]; then 1420 mkdir -p "${!outputDev}/nix-support" 1421 local hook 1422 # have to use ${setupHooks[@]} without quotes because it needs to support setupHooks being a array or a whitespace separated string 1423 # # values of setupHooks won't have spaces so it won't cause problems 1424 # shellcheck disable=2068 1425 for hook in ${setupHooks[@]}; do 1426 local content 1427 consumeEntire content < "$hook" 1428 substituteAllStream content "file '$hook'" >> "${!outputDev}/nix-support/setup-hook" 1429 unset -v content 1430 done 1431 unset -v hook 1432 fi 1433 1434 # Propagate user-env packages into the output with binaries, TODO? 1435 1436 if [ -n "${propagatedUserEnvPkgs:-}" ]; then 1437 mkdir -p "${!outputBin}/nix-support" 1438 # shellcheck disable=SC2086 1439 printWords $propagatedUserEnvPkgs > "${!outputBin}/nix-support/propagated-user-env-packages" 1440 fi 1441 1442 runHook postFixup 1443} 1444 1445 1446installCheckPhase() { 1447 runHook preInstallCheck 1448 1449 if [[ -z "${foundMakefile:-}" ]]; then 1450 echo "no Makefile or custom installCheckPhase, doing nothing" 1451 #TODO(@oxij): should flagsArray influence make -n? 1452 elif [[ -z "${installCheckTarget:-}" ]] \ 1453 && ! make -n ${makefile:+-f $makefile} "${installCheckTarget:-installcheck}" >/dev/null 2>&1; then 1454 echo "no installcheck target in ${makefile:-Makefile}, doing nothing" 1455 else 1456 # Old bash empty array hack 1457 # shellcheck disable=SC2086 1458 local flagsArray=( 1459 ${enableParallelChecking:+-j${NIX_BUILD_CORES}} 1460 SHELL=$SHELL 1461 ) 1462 1463 _accumFlagsArray makeFlags makeFlagsArray \ 1464 installCheckFlags installCheckFlagsArray 1465 flagsArray+=( ${installCheckTarget:-installcheck} ) 1466 1467 echoCmd 'installcheck flags' "${flagsArray[@]}" 1468 make ${makefile:+-f $makefile} "${flagsArray[@]}" 1469 unset flagsArray 1470 fi 1471 1472 runHook postInstallCheck 1473} 1474 1475 1476distPhase() { 1477 runHook preDist 1478 1479 local flagsArray=() 1480 _accumFlagsArray distFlags distFlagsArray 1481 flagsArray+=( ${distTarget:-dist} ) 1482 1483 echo 'dist flags: %q' "${flagsArray[@]}" 1484 make ${makefile:+-f $makefile} "${flagsArray[@]}" 1485 1486 if [ "${dontCopyDist:-0}" != 1 ]; then 1487 mkdir -p "$out/tarballs" 1488 1489 # Note: don't quote $tarballs, since we explicitly permit 1490 # wildcards in there. 1491 # shellcheck disable=SC2086 1492 cp -pvd ${tarballs[*]:-*.tar.gz} "$out/tarballs" 1493 fi 1494 1495 runHook postDist 1496} 1497 1498 1499showPhaseHeader() { 1500 local phase="$1" 1501 case "$phase" in 1502 unpackPhase) echo "unpacking sources";; 1503 patchPhase) echo "patching sources";; 1504 configurePhase) echo "configuring";; 1505 buildPhase) echo "building";; 1506 checkPhase) echo "running tests";; 1507 installPhase) echo "installing";; 1508 fixupPhase) echo "post-installation fixup";; 1509 installCheckPhase) echo "running install tests";; 1510 *) echo "$phase";; 1511 esac 1512} 1513 1514 1515showPhaseFooter() { 1516 local phase="$1" 1517 local startTime="$2" 1518 local endTime="$3" 1519 local delta=$(( endTime - startTime )) 1520 (( delta < 30 )) && return 1521 1522 local H=$((delta/3600)) 1523 local M=$((delta%3600/60)) 1524 local S=$((delta%60)) 1525 echo -n "$phase completed in " 1526 (( H > 0 )) && echo -n "$H hours " 1527 (( M > 0 )) && echo -n "$M minutes " 1528 echo "$S seconds" 1529} 1530 1531 1532genericBuild() { 1533 # variable used by our gzip wrapper to add -n. 1534 # gzip is in common-path.nix and is added to nix-shell but we only want to change its behaviour in nix builds. do not move to a setupHook in gzip. 1535 export GZIP_NO_TIMESTAMPS=1 1536 1537 if [ -f "${buildCommandPath:-}" ]; then 1538 source "$buildCommandPath" 1539 return 1540 fi 1541 if [ -n "${buildCommand:-}" ]; then 1542 eval "$buildCommand" 1543 return 1544 fi 1545 1546 if [ -z "${phases[*]:-}" ]; then 1547 phases="${prePhases[*]:-} unpackPhase patchPhase ${preConfigurePhases[*]:-} \ 1548 configurePhase ${preBuildPhases[*]:-} buildPhase checkPhase \ 1549 ${preInstallPhases[*]:-} installPhase ${preFixupPhases[*]:-} fixupPhase installCheckPhase \ 1550 ${preDistPhases[*]:-} distPhase ${postPhases[*]:-}"; 1551 fi 1552 1553 # The use of ${phases[*]} gives the correct behavior both with and 1554 # without structured attrs. This relies on the fact that each 1555 # phase name is space-free, which it must be because it's the name 1556 # of either a shell variable or a shell function. 1557 for curPhase in ${phases[*]}; do 1558 if [[ "$curPhase" = unpackPhase && -n "${dontUnpack:-}" ]]; then continue; fi 1559 if [[ "$curPhase" = patchPhase && -n "${dontPatch:-}" ]]; then continue; fi 1560 if [[ "$curPhase" = configurePhase && -n "${dontConfigure:-}" ]]; then continue; fi 1561 if [[ "$curPhase" = buildPhase && -n "${dontBuild:-}" ]]; then continue; fi 1562 if [[ "$curPhase" = checkPhase && -z "${doCheck:-}" ]]; then continue; fi 1563 if [[ "$curPhase" = installPhase && -n "${dontInstall:-}" ]]; then continue; fi 1564 if [[ "$curPhase" = fixupPhase && -n "${dontFixup:-}" ]]; then continue; fi 1565 if [[ "$curPhase" = installCheckPhase && -z "${doInstallCheck:-}" ]]; then continue; fi 1566 if [[ "$curPhase" = distPhase && -z "${doDist:-}" ]]; then continue; fi 1567 1568 if [[ -n $NIX_LOG_FD ]]; then 1569 echo "@nix { \"action\": \"setPhase\", \"phase\": \"$curPhase\" }" >&"$NIX_LOG_FD" 1570 fi 1571 1572 showPhaseHeader "$curPhase" 1573 dumpVars 1574 1575 local startTime=$(date +"%s") 1576 1577 # Evaluate the variable named $curPhase if it exists, otherwise the 1578 # function named $curPhase. 1579 eval "${!curPhase:-$curPhase}" 1580 1581 local endTime=$(date +"%s") 1582 1583 showPhaseFooter "$curPhase" "$startTime" "$endTime" 1584 1585 if [ "$curPhase" = unpackPhase ]; then 1586 # make sure we can cd into the directory 1587 [ -z "${sourceRoot}" ] || chmod +x "${sourceRoot}" 1588 1589 cd "${sourceRoot:-.}" 1590 fi 1591 done 1592} 1593 1594 1595# Execute the post-hooks. 1596runHook postHook 1597 1598 1599# Execute the global user hook (defined through the Nixpkgs 1600# configuration option ‘stdenv.userHook’). This can be used to set 1601# global compiler optimisation flags, for instance. 1602runHook userHook 1603 1604 1605dumpVars 1606 1607 1608# Restore the original options for nix-shell 1609[[ $__nixpkgs_setup_set_original == *e* ]] || set +e 1610[[ $__nixpkgs_setup_set_original == *u* ]] || set +u 1611unset -v __nixpkgs_setup_set_original