I've found out that when GCC (tried on GCC 4.8 and GCC 6.4) finds real-ld executable in its search path, it is silently ignoring -fuse-ld=... option, and use real-ld instead of appropriate linker.
$ echo "int main(){}" > script.c
$ ln -s /usr/bin/ld real-ld
$ gcc -fuse-ld=gold -B$PWD script.c
$ readelf --string-dump=.note.gnu.gold-version a.out
readelf: a.out: Warning: Section '.note.gnu.gold-version' was not dumped because it does not exist!
Normally, without real-ld it will work as expected:
$ echo "int main(){}" > script.c
$ gcc -fuse-ld=gold script.c
$ readelf --string-dump=.note.gnu.gold-version a.out
String dump of section '.note.gnu.gold-version':
[ c] GNU
[ 10] gold 1.12
Documentation of GCC suggests that gold linker will be used.
Documentation of collect2 does not say anything about -fuse-ld feature...
tl;dr It is not possible [2]. This is a feature.
I've dug deep into GCC's collect2.c source code, it's history, and collect2 documentation, and came into conclusion that, based on those documents, it is expected behavior that
real-ldtakes precedence over all other binaries [1].However, logic of searching real ld, when
-fuse-ld=...is enabled, is vague and does not have reflection in documentation...Based on source code, as far as I understand C language,
-fuse-ld=...feature is effective only when collect2 tries to search forld.[1] One exception is when GCC is compiled with
--with-ld=..., but only for non-crosscompilers. It gives nothing if one cannot rebuild GCC (or uses crosscompiler).[2] Not entirely true. Just came into hackish idea to create own
real-ldthat would execld.gold, and modify compiler search path (using-B, instead of using-fuse-ld=...):