Without --target=
, Clang should be able to pick up the system include and library paths. This shall never change.
Clang has some loose behaviors on how --target=
selects multiarch include and library paths.
For the example builds below, run ninja clang cxx cxxabi asan
to build needed targets.
–target= and libc++/compiler-rt multiarch paths
For a -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=on -DLLVM_DEFAULT_TARGET_TRIPLE=x86_64-unknown-linux-gnu
build , the libc++ multiarch directory and compiler-rt multiarch directory have x86_64-unknown-linux-gnu
in the path. However, --target=x86_64-linux-gnu
picks such multiarch directories:
% /tmp/out/custom0/bin/clang++ --target=x86_64-linux-gnu --stdlib=libc++ -fsanitize=address a.cc -o a -v |& sed -E 's/ "?-[iIL]/\n&/g'
...
clang -cc1 version 15.0.0 based upon LLVM 15.0.0git default target x86_64-unknown-linux-gnu
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/include"
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include <...> search starts here:
/tmp/out/custom0/bin/../include/x86_64-unknown-linux-gnu/c++/v1
/tmp/out/custom0/bin/../include/c++/v1
/tmp/out/custom0/lib/clang/15.0.0/include
/usr/local/include
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
"/usr/bin/x86_64-linux-gnu-ld" --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a /lib/x86_64-linux-gnu/crt1.o /lib/x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/11/crtbegin.o
-L/tmp/out/custom0/bin/../lib/x86_64-unknown-linux-gnu
-L/usr/lib/gcc/x86_64-linux-gnu/11
-L/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib64
-L/lib/x86_64-linux-gnu
-L/lib/../lib64
-L/usr/lib/x86_64-linux-gnu
-L/usr/lib/../lib64
-L/tmp/out/custom0/bin/../lib
-L/lib
-L/usr/lib ...
Proposal: drop the loose behavior
–target= and system (glibc,GCC) multiarch paths
On Debian, the system (glibc,GCC) include and library paths use something like /usr/include/x86_64-linux-gnu/c++/11/
, /usr/lib/x86_64-linux-gnu
,
% g++ -dumpmachine
x86_64-linux-gnu
Note the ‘vendor’ part is omitted. It is due to Debian multiarch scheme: https://wiki.debian.org/Multiarch/Tuples.
Unfortunately, our CMake build system defaults LLVM_DEFAULT_TARGET_TRIPLE
to the normalized x86_64-unknown-linux-gnu
.
(mordern config.guess
uses x86_64-pc-linux-gnu
: ~/Dev/gcc/config.guess
=> x86_64-pc-linux-gnu
)
However, a specified mismatching --target=x86_64-unknown-linux-gnu
may pick up system x86_64-linux-gnu
.
I consider this unfortunate and it’d be better we can drop this behavior.
This mismatch works because in clang/lib/Driver/ToolChains/Gnu.cpp
, X86_64Triples
encodes
static const char *const X86_64Triples[] = {
"x86_64-linux-gnu", "x86_64-unknown-linux-gnu",
"x86_64-pc-linux-gnu", "x86_64-redhat-linux6E",
"x86_64-redhat-linux", "x86_64-suse-linux",
"x86_64-manbo-linux-gnu", "x86_64-linux-gnu",
"x86_64-slackware-linux", "x86_64-unknown-linux",
"x86_64-amazon-linux"};
These variables are discouraged. Please never add new values.
For a Linux x86_64 triple, Clang detects GCC installations in paths constructed from these triples.
% /tmp/out/custom0/bin/clang++ --target=x86_64-unknown-linux-gnu --stdlib=libstdc++ a.cc -o a -v |& sed -E 's/ "?-[iIL]/\n&/g'
...
clang -cc1 version 15.0.0 based upon LLVM 15.0.0git default target x86_64-unknown-linux-gnu
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/include"
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11
/usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/x86_64-linux-gnu/c++/11
/usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/backward
/tmp/out/custom0/lib/clang/15.0.0/include
/usr/local/include
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
"/usr/local/bin/ld" --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a /lib/x86_64-linux-gnu/crt1.o /lib/x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/11/crtbegin.o
-L/tmp/out/custom0/bin/../lib/x86_64-unknown-linux-gnu
-L/usr/lib/gcc/x86_64-linux-gnu/11
-L/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib64
-L/lib/x86_64-linux-gnu
-L/lib/../lib64
-L/usr/lib/x86_64-linux-gnu
-L/usr/lib/../lib64
-L/tmp/out/custom0/bin/../lib
-L/lib
-L/usr/lib ...
As said, a random Linux x86_64 triple can pick up system x86_64-linux-gnu
. This means:
% /tmp/out/custom0/bin/clang++ --target=x86_64-linux --stdlib=libstdc++ a.cc -o a -v |& sed -E 's/ "?-[iIL]/\n&/g'
same output
% /tmp/out/custom0/bin/clang++ --target=x86_64-linux-musl --stdlib=libstdc++ a.cc -o a -v |& sed -E 's/ "?-[iIL]/\n&/g'
same output
Proposal: even if we decide to prolong the support for --target=x86_64-unknown-linux-gnu
on Debian (see below), the loose behavior related to x86_64-linux
/x86_64-linux-musl
should be removed.
Long-term proposal: For Debian and its derivatives, --target=x86_64-unknown-linux-gnu
should not pick system x86_64-linux-gnu
.
Clang installations should use -DLLVM_DEFAULT_TARGET_TRIPLE=x86_64-linux-gnu
or --target=x86_64-linux-gnu
to pick up system x86_64-linux-gnu
.
The long-term proposal needs to fix a few things. x86_64-redhat-linux
may be problematic as well. We may need to make x86_64-redhat-linux-gnu
behave similar to x86_64-redhat-linux
.
See ⚙ D111367 [Driver] Change -dumpmachine to respect --target/LLVM_DEFAULT_TARGET_TRIPLE verbatim
Prebuilt Clang works on nearly every Linux distro without --target=
Not sure if anyone does this.
Such a prebuilt Clang definitely does not work on a Linux distro with a triple not listed on clang/lib/Driver/ToolChains/Gnu.cpp
:X86_64Triples
.
I think such the distributor should specify correct --target= for their prebuilt Clang, possibly via a wrapper.
It’s not Clang driver’s job to enumerate the endless different triples.
Such distributors may ship libc++/compiler-rt multiarch directories beside Clang.
This is strongly discouraged since a prebuilt library may not necessarily run on a random different distribution.
If the distributor wants to hack up things, they can rename the multiarch directories to match the system, then use the correct --target=.
Again, it’s not Clang driver’s job to enumerate the endless different triples.