The output of ld.lld -v
includes a message "compatiblewith GNU linkers" to address detectionmechanism used by GNU Libtool. This problem is described by Softwarecompatibility and our own "User-Agent" problem.
The latest m4/libtool.m4
continues to rely on aGNU
check.
1 | [AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld, |
Check-basedconfiguration can be a valuable tool, ensuring software remainsfunctional in the future. However, this example highlights how overlyspecific checks can lead to unintended consequences.
This blog post explores more forms of the "User-Agent" problemexposed by an LLD patch changing the version message format.
LLD supports many object file formats. It mimicks GNU ld for ELF andMSVC link.exe for PE/COFF. Previously, the ELF port displays the versioninformation like this: 1
2% /tmp/out/custom2/bin/ld.lld --version
LLD 19.0.0 (compatible with GNU linkers)
A recent patch (llvm-project#97323)changed it to one of the following formats, depending on the build-timevariable LLVM_APPEND_VC_REV
:
With LLVM_APPEND_VC_REV=on
: 1
2% /tmp/out/custom2/bin/ld.lld --version
LLD 19.0.0 (git@github.com:llvm/llvm-project.git 0f9fbbb63cfcd2069441aa2ebef622c9716f8dbb), compatible with GNU linkers
With LLVM_APPEND_VC_REV=off
: 1
2% /tmp/out/custom2/bin/ld.lld --version
LLD 19.0.0, compatible with GNU linkers
In Meson, mesonbuild/linkers/detect.py:guess_win_linker
checks the --version
output to determine whether the LLDinvocation is for ELF or PE/COFF. It performed an overly strict check"(compatible with GNU linkers)", which failed when the parentheses werestripped by #97323.
1 | # mesonbuild/linkers/detect.py |
The latest Meson has loosened the check (meson#13383).
The Linux kernel's scripts/ld-version.sh
script detectslinker versions. Introduced in 2014, it initially checked for GNU ldcompatibility with GCC LTO (though LTO support remains unmerged). It waslater revamped to handle LLD versions as well. While it can handlesuffixes like 2.34-4.fc32
, it struggles with versionscontaining with comma suffix (19.0.0,
).
1 | % scripts/ld-version.sh /tmp/out/custom2/bin/ld.lld |
The script extracts the version string from the--version
output and parses it as major.minor.patch.
1 | # Get the first line of the --version output. |
To support suffixes starting with either -
or,
, the script willemploy a POSIX shell trick utilizing the "Remove Largest SuffixPattern" feature:
1 | version=${version%%[!0-9.]*} |
Ever wondered what the subtle differences are between-v
, -V
, and --version
when usingGNU ld? Let's break it down:
--version
skips linker input processing and displaysbrief copyright information.-v
and -V
keep processing inputfiles.-V
goes a step further than -v
byincluding a list of supported BFD emulations alongside the versioninformation.Prior to September 2022, -V
in ld.lld used to an aliasfor --version
. This caused issues when usinggcc -v -fuse-ld=lld
on certain targets like*-freebsd
and powerpc-*
: gcc passes -V to thelinker, expecting it to process the input files and complete the linkingstep. However, ld.lld's behavior with -V
skipped thisprocess.
I made an adjustment by making-V
an alias for -v
instead. This ensuresthat gcc -v -fuse-ld=lld
performs the linking step.