Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: NixOS/nixpkgs
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 0186286433cc
Choose a base ref
...
head repository: NixOS/nixpkgs
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3e3bee0d0e1b
Choose a head ref
  • 3 commits
  • 5 files changed
  • 2 contributors

Commits on Nov 17, 2017

  1. cctools: Add patch for extra flag for sierra hack

    Patch is drawn from [1], made a PR at [2].
    
    Eventually, we might consider doing something for GNU binutils too, in
    order that we switch (the normal) ld-wrapper to always use this to
    leverage ld to resolve libraries, rather than faking it in bash.
    
    [1]: https://github.com/obsidiansystems/cctools-port/tree/libs-normalize
    [2]: tpoechtrager/cctools-port#34
    Ericson2314 committed Nov 17, 2017
    Copy the full SHA
    2e1f7db View commit details
  2. cc-wrapper: Utilize patched cctools ld for more robust macOS Sierra hack

    Also fix numberous bugs, such as:
    
     - Not getting confused on more flags taking file arguments.
    
     - Ensuring children reexport their children, but the original
       binary/library doesn't.
    
     - Not spawning children when it turns out we just dynamically link
       under the threshold but our total number of inputs exceeeds it.
    
     - Children were always named `libunnamed-*`, when that name was
       supposed to be the last resort only.
    
    In addition to the script, we also patch ld-wrapper to respect `.dylib`
    and `.so` alike. In a future version of nixpkgs, this can be so enabled
    by defaut. Newer nixpkgs will probably do this by default.
    Ericson2314 committed Nov 17, 2017

    Verified

    This commit was signed with the committer’s verified signature.
    Zuoqiu-Yingyi Yingyi / 颖逸
    Copy the full SHA
    30d3169 View commit details

Commits on Jan 17, 2018

  1. Merge pull request #29935 from obsidiansystems/appease-sierra-linker-…

    …17.09
    
    cc-wrapper: More intelligent sierra hack
    Ericson2314 authored Jan 17, 2018

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    3e3bee0 View commit details
4 changes: 3 additions & 1 deletion pkgs/build-support/cc-wrapper/default.nix
Original file line number Diff line number Diff line change
@@ -166,7 +166,9 @@ stdenv.mkDerivation {
'' else ''
ldInner="${prefix}ld-reexport-delegate"
wrap "$ldInner" ${./macos-sierra-reexport-hack.bash} ''${ld:-$ldPath/${prefix}ld}
wrap "${prefix}ld" ${./ld-wrapper.sh} "$out/bin/$ldInner"
cp ${./ld-wrapper.sh} ./ld-wrapper.sh
sed -i ./ld-wrapper.sh -e 's|\.so|\.dylib|g'
wrap ${prefix}ld ./ld-wrapper.sh "$out/bin/$ldInner"
unset ldInner
'') + ''
310 changes: 225 additions & 85 deletions pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash
Original file line number Diff line number Diff line change
@@ -2,105 +2,245 @@

set -eu -o pipefail

# For cmd | while read; do ...; done
shopt -s lastpipe

path_backup="$PATH"
if [ -n "@coreutils_bin@" ]; then
PATH="@coreutils_bin@/bin"
fi

declare -r recurThreshold=300

declare overflowCount=0
for ((n=0; n < $#; ++n)); do
case "${!n}" in
-l*) let overflowCount+=1 ;;
-reexport-l*) let overflowCount+=1 ;;
*) ;;
declare -ri recurThreshold=200
declare -i overflowCount=0

declare -ar origArgs=("$@")

# Throw away what we won't need
declare -a parentArgs=()

while (( $# )); do
case "$1" in
-l)
echo "cctools LD does not support '-l foo'" >&2
exit 1
;;
-lazy_library | -reexport_library | -upward_library | -weak_library)
overflowCount+=1
shift 2
;;
-l* | *.so | *.dylib | -lazy-l* | -reexport-l* | -upward-l* | -weak-l*)
overflowCount+=1
shift 1
;;
*.a | *.o)
shift 1
;;
-L | -F)
# Evidentally ld doesn't like using the child's RPATH, so it still
# needs these.
parentArgs+=("$1" "$2")
shift 2
;;
-L?* | -F?*)
parentArgs+=("$1")
shift 1
;;
-o)
outputName="$2"
parentArgs+=("$1" "$2")
shift 2
;;
-install_name | -dylib_install_name | -dynamic-linker | -plugin)
parentArgs+=("$1" "$2")
shift 2
;;
-rpath)
# Only an rpath to the child is needed, which we will add
shift 2
;;
*)
if [[ -f "$1" ]]; then
# Propabably a non-standard object file like Haskell's
# `.dyn_o`. Skip it like other inputs
:
else
parentArgs+=("$1")
fi
shift 1
;;
esac
done

declare -a allArgs=()


if (( "$overflowCount" <= "$recurThreshold" )); then
allArgs=("$@")
else
declare -a childrenLookup=() childrenLink=()

while (( $# )); do
case "$1" in
-L/*)
childrenLookup+=("$1")
allArgs+=("$1")
;;
-L)
echo "cctools LD does not support '-L foo' or '-l foo'" >&2
exit 1
;;
-l)
echo "cctools LD does not support '-L foo' or '-l foo'" >&2
exit 1
;;
-lazy_library | -lazy_framework | -lto_library)
# We aren't linking any "azy_library", "to_library", etc.
allArgs+=("$1")
;;
-lazy-l | -weak-l) allArgs+=("$1") ;;
# We can't so easily prevent header issues from these.
-lSystem) allArgs+=("$1") ;;
# Special case as indirection seems like a bad idea for something
# so fundamental. Can be removed for simplicity.
-l?* | -reexport-l?*) childrenLink+=("$1") ;;
*) allArgs+=("$1") ;;
esac

shift
done
if [ -n "${NIX_DEBUG:-}" ]; then
echo "ld-wrapper: Only ${overflowCount} inputs counted while ${recurThreshold} is the ceiling, linking normally. " >&2
fi
PATH="$path_backup"
exec @prog@ "${origArgs[@]}"
fi



if [ -n "${NIX_DEBUG:-}" ]; then
echo "ld-wrapper: ${overflowCount} inputs counted when ${recurThreshold} is the ceiling, inspecting further. " >&2
fi

# Collect the normalized linker input
declare -a norm=()

declare n=0
while (( $n < "${#childrenLink[@]}" )); do
if [[ "${childrenLink[n]}" = -l* ]]; then
childrenLink[n]="-reexport${childrenLink[n]}"
fi
let ++n
# Arguments are null-separated
@prog@ --dump-normalized-lib-args "${origArgs[@]}" |
while IFS= read -r -d '' input; do
norm+=("$input")
done
unset n

declare -r outputNameLibless=$(basename $( \
if [[ -z "${outputName:+isUndefined}" ]]; then
echo unnamed
elif [[ "${outputName:0:3}" = lib ]]; then
echo "${outputName:3}"
else
echo "${outputName}"
fi))
declare -ra children=("$outputNameLibless-reexport-delegate-0" \
"$outputNameLibless-reexport-delegate-1")
mkdir -p "$out/lib"
PATH="$PATH:@out@/bin"
symbolBloatObject=$outputNameLibless-symbol-hack.o
if [[ ! -e $symbolBloatObject ]]; then
printf '.private_extern _______child_hack_foo\nchild_hack_foo:\n' \
| @binPrefix@as -- -o $symbolBloatObject

declare -i leafCount=0
declare lastLeaf=''
declare -a childrenInputs=() trailingInputs=()
while (( "${#norm[@]}" )); do
case "${norm[0]}" in
-lazy_library | -upward_library)
# TODO(@Ericson2314): Don't do that, but intersperse children
# between such args.
echo "ld-wrapper: Warning: Potentially changing link order" >&2
trailingInputs+=("${norm[0]}" "${norm[1]}")
norm=("${norm[@]:2}")
;;
-reexport_library | -weak_library)
childrenInputs+=("${norm[0]}" "${norm[1]}")
if [[ "${norm[1]}" != "$lastLeaf" ]]; then
leafCount+=1
lastLeaf="${norm[1]}"
fi
norm=("${norm[@]:2}")
;;
*.so | *.dylib)
childrenInputs+=(-reexport_library "${norm[0]}")
if [[ "${norm[0]}" != "$lastLeaf" ]]; then
leafCount+=1
lastLeaf="${norm[0]}"
fi
norm=("${norm[@]:1}")
;;
*.o | *.a)
# Don't delegate object files or static libs
parentArgs+=("${norm[0]}")
norm=("${norm[@]:1}")
;;
*)
if [[ -f "${norm[0]}" ]]; then
# Propabably a non-standard object file. We'll let it by.
parentArgs+=("${norm[0]}")
norm=("${norm[@]:1}")
else
echo "ld-wrapper: Internal Error: Invalid normalized argument" >&2
exit -1
fi
;;
esac
done



if (( "$leafCount" <= "$recurThreshold" )); then
if [ -n "${NIX_DEBUG:-}" ]; then
echo "ld-wrapper: Only ${leafCount} *dynamic* inputs counted while ${recurThreshold} is the ceiling, linking normally. " >&2
fi
PATH="$path_backup"
exec @prog@ "${origArgs[@]}"
fi



if [ -n "${NIX_DEBUG:-}" ]; then
echo "ld-wrapper: ${leafCount} *dynamic* inputs counted when ${recurThreshold} is the ceiling, delegating to children. " >&2
fi

declare -r outputNameLibless=$( \
if [[ -z "${outputName:+isUndefined}" ]]; then
echo unnamed
return 0;
fi
baseName=$(basename ${outputName})
if [[ "$baseName" = lib* ]]; then
baseName="${baseName:3}"
fi
echo "$baseName")

declare -ra children=(
"$outputNameLibless-reexport-delegate-0"
"$outputNameLibless-reexport-delegate-1"
)

mkdir -p "$out/lib"

symbolBloatObject=$outputNameLibless-symbol-hack.o
if [[ ! -f $symbolBloatObject ]]; then
# `-Q` means use GNU Assembler rather than Clang, avoiding an awkward
# dependency cycle.
printf '.private_extern _______child_hack_foo\nchild_hack_foo:\n' |
PATH="$PATH:@out@/bin" @binPrefix@as -Q -- -o $symbolBloatObject
fi

# Split inputs between children
declare -a child0Inputs=() child1Inputs=("${childrenInputs[@]}")
let "countFirstChild = $leafCount / 2" || true
lastLeaf=''
while (( "$countFirstChild" )); do
case "${child1Inputs[0]}" in
-reexport_library | -weak_library)
child0Inputs+=("${child1Inputs[0]}" "${child1Inputs[1]}")
if [[ "${child1Inputs[1]}" != "$lastLeaf" ]]; then
let countFirstChild-=1 || true
lastLeaf="${child1Inputs[1]}"
fi
child1Inputs=("${child1Inputs[@]:2}")
;;
*.so | *.dylib)
child0Inputs+=(-reexport_library "${child1Inputs[0]}")
if [[ "${child1Inputs[0]}" != "$lastLeaf" ]]; then
let countFirstChild-=1 || true
lastLeaf="${child1Inputs[1]}"
fi
child1Inputs=("${child1Inputs[@]:2}")
;;
*)
echo "ld-wrapper: Internal Error: Invalid delegated input" >&2
exit -1
;;
esac
done


# First half of libs
@out@/bin/@binPrefix@ld \
-macosx_version_min $MACOSX_DEPLOYMENT_TARGET -arch x86_64 -dylib \
-o "$out/lib/lib${children[0]}.dylib" \
-install_name "$out/lib/lib${children[0]}.dylib" \
"$symbolBloatObject" "${child0Inputs[@]}" "${trailingInputs[@]}"

# Second half of libs
@out@/bin/@binPrefix@ld \
-macosx_version_min $MACOSX_DEPLOYMENT_TARGET -arch x86_64 -dylib \
-o "$out/lib/lib${children[1]}.dylib" \
-install_name "$out/lib/lib${children[1]}.dylib" \
"$symbolBloatObject" "${child1Inputs[@]}" "${trailingInputs[@]}"

parentArgs+=("-L$out/lib" -rpath "$out/lib")
if [[ $outputName != *reexport-delegate* ]]; then
parentArgs+=("-l${children[0]}" "-l${children[1]}")
else
parentArgs+=("-reexport-l${children[0]}" "-reexport-l${children[1]}")
fi

parentArgs+=("${trailingInputs[@]}")

# first half of libs
@binPrefix@ld -macosx_version_min $MACOSX_DEPLOYMENT_TARGET -arch x86_64 -dylib \
-o "$out/lib/lib${children[0]}.dylib" \
-install_name "$out/lib/lib${children[0]}.dylib" \
"${childrenLookup[@]}" "$symbolBloatObject" \
"${childrenLink[@]:0:$((${#childrenLink[@]} / 2 ))}"
# second half of libs
@binPrefix@ld -macosx_version_min $MACOSX_DEPLOYMENT_TARGET -arch x86_64 -dylib \
-o "$out/lib/lib${children[1]}.dylib" \
-install_name "$out/lib/lib${children[1]}.dylib" \
"${childrenLookup[@]}" "$symbolBloatObject" \
"${childrenLink[@]:$((${#childrenLink[@]} / 2 ))}"
allArgs+=("-L$out/lib" "-l${children[0]}" "-l${children[1]}")
if [ -n "${NIX_DEBUG:-}" ]; then
echo "flags using delegated children to @prog@:" >&2
printf " %q\n" "${parentArgs[@]}" >&2
fi

PATH="$path_backup"
exec @prog@ "${allArgs[@]}"
exec @prog@ "${parentArgs[@]}"
Loading