I need to pass some objects from [ some assembler | another compiler | an archive ] directly to the linker.
But seems that the ld
being found on the path is [ broken | missing | linking for the wrong ABI ].
And sometimes, I can't even find ld
at all.
How can I find the actual linker being used, by whatever the C compiler happens to be,
[ on a Mac | on Linux | on BSD | from a configure script ]?
I just had to figure this one out.
It was kind of tough, so I thought I'd share.
Give this a shot:
#!/usr/bin/env sh
# 'main;' is the shortest C program possible (I think.).
# So it is compiled, linked, and written to /dev/null.
# So if the linker can't link, this should return 1.
for link in collect2 ld; do # Order matters, because of GCC.
echo 'main;' | $CC -v -x c - -o /dev/null -\#\#\# 2>&1 | grep -q $link &&
echo 'main;' | $CC -v -x c - -o /dev/null -\#\#\# 2>&1 | grep $link |
sed -e "s|\(.*$link\).*|\1|" -e 's/ //g' -e 's|"||' && break
done
# That should work on just about anything, and returns an absolute path,
# except with ICC. If we want to try to get an absolute path there too,
# we have to:
# If 'which' is missing, and it might not have an -s flag.
which="$(which which >/dev/null 2>&1)" || which=echo
$which "$(for link in collect2 ld; do
echo 'main;' | $CC -v -x c - -o /dev/null -\#\#\# 2>&1 | grep -q $link &&
echo 'main;' | $CC -v -x c - -o /dev/null -\#\#\# 2>&1 | grep $link |
sed -e "s|\(.*$link\).*|\1|" -e 's/ //g' -e 's|"||' && break
done)"
So you might have just said,
Come on guy, no way that's necessary! Just, like,
which ld
.
Honestly and truly, that doesn't work for me a large portion of the time.
Its not so unusual today, since ld
is frequently a wrapper.
Lets test it, see what turns up:
#!/usr/bin/env sh
# On my Mac, nothing too special, I swear.
# Just a MacBook, Xcode, GCC from Homebrew, and one commercial compiler.
echo; $which ld; echo "...Not necessarily."; echo
for CC in cc gcc clang icc; do echo $c:
for link in collect2 ld; do
echo 'main;' | $CC -v -x c - -o /dev/null -\#\#\# 2>&1 | grep -q $link &&
echo 'main;' | $CC -v -x c - -o /dev/null -\#\#\# 2>&1 | grep $link |
sed -e "s|\(.*$link\).*|\1|" -e 's/ //g' -e 's|"||' && break
done
which="$(which which 2>/dev/null 1>&1)" || which=echo
$which "$(for link in collect2 ld; do
echo 'main;' | $CC -v -x c - -o /dev/null -\#\#\# 2>&1 | grep -q $link &&
echo 'main;' | $CC -v -x c - -o /dev/null -\#\#\# 2>&1 | grep $link |
sed -e "s|\(.*$link\).*|\1|" -e 's/ //g' -e 's|"||' && break
done)"
echo
done
Returns:
/usr/bin/ld
...Not necessarily.
cc:
/Applications/Xcode51-Beta4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld
/Applications/Xcode51-Beta4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld
gcc:
/Users/Shared/usr/local/Cellar/gcc49/4.9-20140119/libexec/gcc/x86_64-apple-darwin13.1.0/4.9.0/collect2
/Users/Shared/usr/local/Cellar/gcc49/4.9-20140119/libexec/gcc/x86_64-apple-darwin13.1.0/4.9.0/collect2
clang:
/Applications/Xcode51-Beta4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld
/Applications/Xcode51-Beta4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld
icc:
ld
/usr/bin/ld