1# This setup hook strips libraries and executables in the fixup phase. 2 3fixupOutputHooks+=(_doStrip) 4 5_doStrip() { 6 # We don't bother to strip build platform code because it shouldn't make it 7 # to $out anyways---if it does, that's a bigger problem that a lack of 8 # stripping will help catch. 9 local -ra flags=(dontStripHost dontStripTarget) 10 local -ra debugDirs=(stripDebugList stripDebugListTarget) 11 local -ra allDirs=(stripAllList stripAllListTarget) 12 local -ra stripCmds=(STRIP STRIP_FOR_TARGET) 13 local -ra ranlibCmds=(RANLIB RANLIB_FOR_TARGET) 14 15 # TODO(structured-attrs): This doesn't work correctly if one of 16 # the items in strip*List or strip*Flags contains a space, 17 # even with structured attrs enabled. This is OK for now 18 # because very few packages set any of these, and it doesn't 19 # affect any of them. 20 # 21 # After __structuredAttrs = true is universal, come back and 22 # push arrays all the way through this logic. 23 24 # Strip only host paths by default. Leave targets as is. 25 stripDebugList=${stripDebugList[*]:-lib lib32 lib64 libexec bin sbin Applications Library/Frameworks} 26 stripDebugListTarget=${stripDebugListTarget[*]:-} 27 stripAllList=${stripAllList[*]:-} 28 stripAllListTarget=${stripAllListTarget[*]:-} 29 30 local i 31 for i in ${!stripCmds[@]}; do 32 local -n flag="${flags[$i]}" 33 local -n debugDirList="${debugDirs[$i]}" 34 local -n allDirList="${allDirs[$i]}" 35 local -n stripCmd="${stripCmds[$i]}" 36 local -n ranlibCmd="${ranlibCmds[$i]}" 37 38 # `dontStrip` disables them all 39 if [[ "${dontStrip-}" || "${flag-}" ]] || ! type -f "${stripCmd-}" 2>/dev/null 1>&2 40 then continue; fi 41 42 stripDirs "$stripCmd" "$ranlibCmd" "$debugDirList" "${stripDebugFlags[*]:--S -p}" 43 stripDirs "$stripCmd" "$ranlibCmd" "$allDirList" "${stripAllFlags[*]:--s -p}" 44 done 45} 46 47stripDirs() { 48 local cmd="$1" 49 local ranlibCmd="$2" 50 local paths="$3" 51 local stripFlags="$4" 52 local excludeFlags=() 53 local pathsNew= 54 55 [ -z "$cmd" ] && echo "stripDirs: Strip command is empty" 1>&2 && exit 1 56 [ -z "$ranlibCmd" ] && echo "stripDirs: Ranlib command is empty" 1>&2 && exit 1 57 58 local pattern 59 if [ -n "${stripExclude:-}" ]; then 60 for pattern in "${stripExclude[@]}"; do 61 excludeFlags+=(-a '!' '(' -name "$pattern" -o -wholename "$prefix/$pattern" ')' ) 62 done 63 fi 64 65 local p 66 for p in ${paths}; do 67 if [ -e "$prefix/$p" ]; then 68 pathsNew="${pathsNew} $prefix/$p" 69 fi 70 done 71 paths=${pathsNew} 72 73 if [ -n "${paths}" ]; then 74 echo "stripping (with command $cmd and flags $stripFlags) in $paths" 75 local striperr 76 striperr="$(mktemp --tmpdir="$TMPDIR" 'striperr.XXXXXX')" 77 # Make sure we process files only once. `strip`ping the same file through different 78 # links in parallel can corrupt it: 79 # https://github.com/NixOS/nixpkgs/issues/246147#issuecomment-1657072039 80 81 # Do not strip lib/debug. This is a directory used by setup-hooks/separate-debug-info.sh. 82 # Print out each file's device and inode (which will be the same if two files are hardlinked 83 # or are the same file found through different symlinks), followed by its path... 84 find $paths -type f "${excludeFlags[@]}" -a '!' -path "$prefix/lib/debug/*" -printf '%D-%i,%p\0' | 85 # ... sort/uniq by device/inode, then cut them out and keep the path, ... 86 sort -t, -k1,1 -u -z | cut -d, -f2- -z | 87 # and finally strip each unique path in parallel. 88 xargs -r -0 -n1 -P "$NIX_BUILD_CORES" -- $cmd $stripFlags 2>"$striperr" || exit_code=$? 89 # xargs exits with status code 123 if some but not all of the 90 # processes fail. We don't care if some of the files couldn't 91 # be stripped, so ignore specifically this code. 92 [[ "$exit_code" = 123 || -z "$exit_code" ]] || (cat "$striperr" 1>&2 && exit 1) 93 94 rm "$striperr" 95 # 'strip' does not normally preserve archive index in .a files. 96 # This usually causes linking failures against static libs like: 97 # ld: ...-i686-w64-mingw32-stage-final-gcc-13.0.0-lib/i686-w64-mingw32/lib/libstdc++.dll.a: 98 # error adding symbols: archive has no index; run ranlib to add one 99 # Restore the index by running 'ranlib'. 100 find $paths -name '*.a' -type f -exec $ranlibCmd '{}' \; 2>/dev/null 101 fi 102}