Question

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 ]?

Was it helpful?

Solution

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top