about summary refs log tree commit diff
path: root/pkgs/stdenv/generic/setup.sh
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/stdenv/generic/setup.sh')
-rw-r--r--pkgs/stdenv/generic/setup.sh107
1 files changed, 88 insertions, 19 deletions
diff --git a/pkgs/stdenv/generic/setup.sh b/pkgs/stdenv/generic/setup.sh
index 30ca0e125a38..25113bc91bb3 100644
--- a/pkgs/stdenv/generic/setup.sh
+++ b/pkgs/stdenv/generic/setup.sh
@@ -93,6 +93,7 @@ PATH=
 for i in $NIX_GCC @initialPath@; do
     if [ "$i" = / ]; then i=; fi
     addToSearchPath PATH $i/bin
+    addToSearchPath PATH $i/sbin
 done
 
 if [ "$NIX_DEBUG" = 1 ]; then
@@ -102,6 +103,7 @@ fi
 
 # Execute the pre-hook.
 export SHELL=@shell@
+export CONFIG_SHELL="$SHELL"
 if [ -z "$shell" ]; then export shell=@shell@; fi
 runHook preHook
 
@@ -109,7 +111,6 @@ runHook preHook
 # Check that the pre-hook initialised SHELL.
 if [ -z "$SHELL" ]; then echo "SHELL not set"; exit 1; fi
 
-
 # Hack: run gcc's setup hook.
 envHooks=()
 crossEnvHooks=()
@@ -120,6 +121,7 @@ fi
 
 # Ensure that the given directories exists.
 ensureDir() {
+    echo "warning: ‘ensureDir’ is deprecated; use ‘mkdir’ instead" >&2
     local dir
     for dir in "$@"; do
         if ! [ -x "$dir" ]; then mkdir -p "$dir"; fi
@@ -294,11 +296,23 @@ stripDirs() {
 
     for d in $subdirs; do
         if [ -d "$prefix/$d" ]; then
-            stripDir "$prefix/$d" "$stripFlags"
+            stripDir "$prefix/$d" "$commonStripFlags" "$stripFlags"
         fi
     done
 }
 
+# PaX-mark binaries
+paxmark() {
+    local flags="$1"
+    shift
+
+    if [ -z "@needsPax@" ]; then
+        return
+    fi
+
+    paxctl -c "$@"
+    paxctl -zex -${flags} "$@"
+}
 
 ######################################################################
 # Textual substitution functions.
@@ -310,9 +324,11 @@ substitute() {
 
     local -a params=("$@")
 
-    local n p pattern replacement varName
+    local n p pattern replacement varName content
 
-    local content="$(cat $input)"
+    # a slightly hacky way to keep newline at the end
+    content="$(cat $input; echo -n X)"
+    content="${content%X}"
 
     for ((n = 2; n < ${#params[*]}; n += 1)); do
         p=${params[$n]}
@@ -545,11 +561,15 @@ patchPhase() {
             *.bz2)
                 uncompress="bzip2 -d"
                 ;;
+            *.xz)
+                uncompress="xz -d"
+                ;;
             *.lzma)
                 uncompress="lzma -d"
                 ;;
         esac
-        $uncompress < $i | patch ${patchFlags:--p1}
+        # "2>&1" is a hack to make patch fail if the decompressor fails (nonexistent patch, etc.)
+        $uncompress < $i 2>&1 | patch ${patchFlags:--p1}
         stopNest
     done
 
@@ -574,7 +594,7 @@ configurePhase() {
     fi
 
     if [ -z "$dontFixLibtool" ]; then
-        for i in $(find . -name "ltmain.sh"); do
+        find . -iname "ltmain.sh" | while read i; do
             echo "fixing libtool script $i"
             fixLibtool $i
         done
@@ -641,6 +661,9 @@ buildPhase() {
         return
     fi
 
+    # See https://github.com/NixOS/nixpkgs/pull/1354#issuecomment-31260409
+    makeFlags="SHELL=$SHELL $makeFlags"
+
     echo "make flags: $makeFlags ${makeFlagsArray[@]} $buildFlags ${buildFlagsArray[@]}"
     make ${makefile:+-f $makefile} \
         ${enableParallelBuilding:+-j${NIX_BUILD_CORES} -l${NIX_BUILD_CORES}} \
@@ -672,7 +695,7 @@ patchELF() {
         find "$dir" \( \
             \( -type f -a -name "*.so*" \) -o \
             \( -type f -a -perm +0100 \) \
-            \) -print -exec patchelf --shrink-rpath {} \;
+            \) -print -exec patchelf --shrink-rpath '{}' \;
         stopNest
     fi
 }
@@ -682,20 +705,59 @@ patchShebangs() {
     # Rewrite all script interpreter file names (`#! /path') under the
     # specified  directory tree to paths found in $PATH.  E.g.,
     # /bin/sh will be rewritten to /nix/store/<hash>-some-bash/bin/sh.
+    # /usr/bin/env gets special treatment so that ".../bin/env python" is
+    # rewritten to /nix/store/<hash>/bin/python.
     # Interpreters that are already in the store are left untouched.
     local dir="$1"
     header "patching script interpreter paths in $dir"
     local f
-    for f in $(find "$dir" -type f -perm +0100); do
-        local oldPath=$(sed -ne '1 s,^#![ ]*\([^ ]*\).*$,\1,p' "$f")
+    local oldPath
+    local newPath
+    local arg0
+    local args
+    local oldInterpreterLine
+    local newInterpreterLine
+
+    find "$dir" -type f -perm +0100 | while read f; do
+        if [ "$(head -1 "$f" | head -c +2)" != '#!' ]; then
+            # missing shebang => not a script
+            continue
+        fi
+
+        oldInterpreterLine=$(head -1 "$f" | tail -c +3)
+        read -r oldPath arg0 args <<< "$oldInterpreterLine"
+
+        if $(echo "$oldPath" | grep -q "/bin/env$"); then
+            # Check for unsupported 'env' functionality:
+            # - options: something starting with a '-'
+            # - environment variables: foo=bar
+            if $(echo "$arg0" | grep -q -- "^-.*\|.*=.*"); then
+                echo "unsupported interpreter directive \"$oldInterpreterLine\" (set dontPatchShebangs=1 and handle shebang patching yourself)"
+                exit 1
+            fi
+            newPath="$(command -v "$arg0" || true)"
+        else
+            if [ "$oldPath" = "" ]; then
+                # If no interpreter is specified linux will use /bin/sh. Set
+                # oldpath="/bin/sh" so that we get /nix/store/.../sh.
+                oldPath="/bin/sh"
+            fi
+            newPath="$(command -v "$(basename "$oldPath")" || true)"
+            args="$arg0 $args"
+        fi
+
+        newInterpreterLine="$newPath $args"
+
         if [ -n "$oldPath" -a "${oldPath:0:${#NIX_STORE}}" != "$NIX_STORE" ]; then
-            local newPath=$(type -P $(basename $oldPath) || true)
             if [ -n "$newPath" -a "$newPath" != "$oldPath" ]; then
-                echo "$f: interpreter changed from $oldPath to $newPath"
-                sed -i -e "1 s,$oldPath,$newPath," "$f"
+                echo "$f: interpreter directive changed from \"$oldInterpreterLine\" to \"$newInterpreterLine\""
+                # escape the escape chars so that sed doesn't interpret them
+                escapedInterpreterLine=$(echo "$newInterpreterLine" | sed 's|\\|\\\\|g')
+                sed -i -e "1 s|.*|#\!$escapedInterpreterLine|" "$f"
             fi
         fi
     done
+
     stopNest
 }
 
@@ -804,16 +866,22 @@ fixupPrefix() {
     fi
 
     if [ -z "$dontGzipMan" ]; then
+        echo "gzipping man pages"
         GLOBIGNORE=.:..:*.gz:*.bz2
-        for f in $prefix/share/man/*/* $prefix/share/man/*/*/*; do
-            if [ -f $f ]; then
-                if gzip -c $f > $f.gz; then
-                    rm $f
+        for f in "$prefix"/share/man/*/* "$prefix"/share/man/*/*/*; do
+            if [ -f "$f" -a ! -L "$f" ]; then
+                if gzip -c -n "$f" > "$f".gz; then
+                    rm "$f"
                 else
-                    rm $f.gz
+                    rm "$f".gz
                 fi
             fi
         done
+        for f in "$out"/share/man/*/* "$out"/share/man/*/*/*; do
+            if [ -L "$f" -a -f `readlink -f "$f"`.gz ]; then
+                ln -sf `readlink "$f"`.gz "$f".gz && rm "$f"
+            fi
+        done
         unset GLOBIGNORE
     fi
 
@@ -896,7 +964,7 @@ genericBuild() {
     if [ -z "$phases" ]; then
         phases="$prePhases unpackPhase patchPhase $preConfigurePhases \
             configurePhase $preBuildPhases buildPhase checkPhase \
-            $preInstallPhases installPhase fixupPhase installCheckPhase \
+            $preInstallPhases installPhase $preFixupPhases fixupPhase installCheckPhase \
             $preDistPhases distPhase $postPhases";
     fi
 
@@ -934,7 +1002,8 @@ genericBuild() {
 }
 
 
-# Execute the post-hook.
+# Execute the post-hooks.
+for i in "${postHooks[@]}"; do $i; done
 runHook postHook