Factor out fixup phase stuff into separate setup hooks

This commit is contained in:
Eelco Dolstra 2014-06-27 13:33:05 +02:00
parent d7a4fa26b0
commit daa66b8b1c
5 changed files with 134 additions and 123 deletions

View File

@ -0,0 +1,27 @@
addHook fixupOutput 'if [ -z "$dontGzipMan" ]; then compressManPages "$prefix"; fi'
compressManPages() {
local dir="$1"
echo "gzipping man pages in $dir"
GLOBIGNORE=.:..:*.gz:*.bz2
for f in "$dir"/share/man/*/* "$dir"/share/man/*/*/*; do
if [ -f "$f" -a ! -L "$f" ]; then
if gzip -c -n "$f" > "$f".gz; then
rm "$f"
else
rm "$f".gz
fi
fi
done
for f in "$dir"/share/man/*/* "$dir"/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
}

View File

@ -0,0 +1,62 @@
# This setup hook causes the fixup phase to rewrite all script
# interpreter file names (`#! /path') 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.
addHook fixupOutput 'if [ -z "$dontPatchShebangs" ]; then patchShebangs "$prefix"; fi'
patchShebangs() {
local dir="$1"
header "patching script interpreter paths in $dir"
local 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
if [ -n "$newPath" -a "$newPath" != "$oldPath" ]; then
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
}

View File

@ -0,0 +1,36 @@
# This setup hook strips libraries and executables in the fixup phase.
addHook fixupOutput _doStrip
_doStrip() {
if [ -z "$dontStrip" ]; then
stripDebugList=${stripDebugList:-lib lib32 lib64 libexec bin sbin}
if [ -n "$stripDebugList" ]; then
stripDirs "$stripDebugList" "${stripDebugFlags:--S}"
fi
stripAllList=${stripAllList:-}
if [ -n "$stripAllList" ]; then
stripDirs "$stripAllList" "${stripAllFlags:--s}"
fi
fi
}
stripDirs() {
local dirs="$1"
local stripFlags="$2"
local dirsNew=
for d in ${dirs}; do
if [ -d "$prefix/$d" ]; then
dirsNew="${dirsNew} $prefix/$d "
fi
done
dirs=${dirsNew}
if [ -n "${dirs}" ]; then
header "stripping (with flags $stripFlags) in $dirs"
find $dirs -type f -print0 | xargs -0 ${xargsFlags:--r} strip $commonStripFlags $stripFlags || true
stopNest
fi
}

View File

@ -31,6 +31,12 @@ let
unsafeGetAttrPos = builtins.unsafeGetAttrPos or (n: as: null);
extraBuildInputs' = extraBuildInputs ++
[ ../../build-support/setup-hooks/compress-man-pages.sh
../../build-support/setup-hooks/strip.sh
../../build-support/setup-hooks/patch-shebangs.sh
];
# The stdenv that we are producing.
result =
@ -106,10 +112,10 @@ let
__ignoreNulls = true;
# Inputs built by the cross compiler.
buildInputs = lib.optionals (crossConfig != null) (buildInputs ++ extraBuildInputs);
buildInputs = lib.optionals (crossConfig != null) (buildInputs ++ extraBuildInputs');
propagatedBuildInputs = lib.optionals (crossConfig != null) propagatedBuildInputs;
# Inputs built by the usual native compiler.
nativeBuildInputs = nativeBuildInputs ++ lib.optionals (crossConfig == null) (buildInputs ++ extraBuildInputs);
nativeBuildInputs = nativeBuildInputs ++ lib.optionals (crossConfig == null) (buildInputs ++ extraBuildInputs');
propagatedNativeBuildInputs = propagatedNativeBuildInputs ++
lib.optionals (crossConfig == null) propagatedBuildInputs;
}))) (

View File

@ -325,25 +325,6 @@ export NIX_BUILD_CORES
# Misc. helper functions.
stripDirs() {
local dirs="$1"
local stripFlags="$2"
local dirsNew=
for d in ${dirs}; do
if [ -d "$prefix/$d" ]; then
dirsNew="${dirsNew} $prefix/$d "
fi
done
dirs=${dirsNew}
if [ -n "${dirs}" ]; then
header "stripping (with flags $stripFlags) in $dirs"
find $dirs -type f -print0 | xargs -0 ${xargsFlags:--r} strip $commonStripFlags $stripFlags || true
stopNest
fi
}
# PaX-mark binaries
paxmark() {
local flags="$1"
@ -357,6 +338,7 @@ paxmark() {
paxctl -zex -${flags} "$@"
}
######################################################################
# Textual substitution functions.
@ -702,67 +684,6 @@ checkPhase() {
}
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.
header "patching script interpreter paths"
local dir="$1"
local 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
if [ -n "$newPath" -a "$newPath" != "$oldPath" ]; then
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
}
installPhase() {
runHook preInstall
@ -838,47 +759,6 @@ fixupPhase() {
}
addHook fixupOutput _defaultFixupOutput
_defaultFixupOutput() {
if [ -z "$dontGzipMan" ]; then
echo "gzipping man pages"
GLOBIGNORE=.:..:*.gz:*.bz2
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
fi
fi
done
for f in "$prefix"/share/man/*/* "$prefix"/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
# TODO: strip _only_ ELF executables, and return || fail here...
if [ -z "$dontStrip" ]; then
stripDebugList=${stripDebugList:-lib lib32 lib64 libexec bin sbin}
if [ -n "$stripDebugList" ]; then
stripDirs "$stripDebugList" "${stripDebugFlags:--S}"
fi
stripAllList=${stripAllList:-}
if [ -n "$stripAllList" ]; then
stripDirs "$stripAllList" "${stripAllFlags:--s}"
fi
fi
if [ -z "$dontPatchShebangs" ]; then
patchShebangs "$prefix"
fi
}
installCheckPhase() {
runHook preInstallCheck