The output of ld.lld -v
includes a message "compatible
with GNU linkers" to address detection
mechanism used by GNU Libtool. This problem is described by Software
compatibility and our own "User-Agent" problem.
The latest m4/libtool.m4
continues to rely on a
GNU
check.
1 | [AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld, |
Check-based configuration can be a valuable tool, ensuring software remains functional in the future. However, this example highlights how overly specific checks can lead to unintended consequences.
This blog post explores more forms of the "User-Agent" problem exposed by an LLD patch changing the version message format.
LLD supports many object file formats. It mimicks GNU ld for ELF and MSVC link.exe for PE/COFF. Previously, the ELF port displays the version information like this:
1 | % /tmp/out/custom2/bin/ld.lld --version |
A recent patch (llvm-project#97323)
changed it to one of the following formats, depending on the build-time
variable LLVM_APPEND_VC_REV
:
With LLVM_APPEND_VC_REV=on
:
1 | % /tmp/out/custom2/bin/ld.lld --version |
With LLVM_APPEND_VC_REV=off
:
1 | % /tmp/out/custom2/bin/ld.lld --version |
Meson
In Meson, mesonbuild/linkers/detect.py:guess_win_linker
checks the --version
output to determine whether the LLD
invocation is for ELF or PE/COFF. It performed an overly strict check
"(compatible with GNU linkers)", which failed when the parentheses were
stripped by #97323.
1 |
|
The latest Meson has loosened the check (meson#13383).
Linux kernel
The Linux kernel's scripts/ld-version.sh
script detects
linker versions. Introduced in 2014, it initially checked for GNU ld
compatibility with GCC LTO (though LTO support remains unmerged). It was
later revamped to handle LLD versions as well. While it can handle
suffixes like 2.34-4.fc32
, it struggles with versions
containing 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 |
|
To support suffixes starting with either -
or
,
, the script will
employ a POSIX shell trick utilizing the "Remove Largest Suffix
Pattern" feature:
1 | version=${version%%[!0-9.]*} |
More fun with versions
Ever wondered what the subtle differences are between
-v
, -V
, and --version
when using
GNU ld? Let's break it down:
--version
skips linker input processing and displays brief copyright information.-v
and-V
keep processing input files.-V
goes a step further than-v
by including a list of supported BFD emulations alongside the version information.
Prior to September 2022, -V
in ld.lld used to an alias
for --version
. This caused issues when using
gcc -v -fuse-ld=lld
on certain targets like
*-freebsd
and powerpc-*
: gcc passes -V to the
linker, expecting it to process the input files and complete the linking
step. However, ld.lld's behavior with -V
skipped this
process.
I made an adjustment by making
-V
an alias for -v
instead. This ensures
that gcc -v -fuse-ld=lld
performs the linking step.