How to Make Clang 17+ Use Libc++ Installed in the LLVM Library Path by Default?

Up to clang 16 (and at least since clang 11, when I began building my clang toolchain), it was possible to build and install libc++ in the LLVM library directory, and the clang frontend would then automatically add the LLVM library directory to its library search path. This allows for easy switching between different clang+libc++ versions. Each clang will only link with libc++ installed in the same LLVM install prefix.

However, starting with clang 17, this feature was removed alongside the LLVM_ENABLE_PROJECTS=libcxx support, even if one can actually install libc++ to the LLVM library path with LLVM_ENABLE_RUNTIMES. A quick review of clang/lib/Driver/ToolChains/Linux.cpp shows that all library search paths are now relative to the sysroot, means that I have to create separate sysroots for different coexisting clang+libc++ toolchains, inconvenient and cumbersome.

For now, I have backported that feature from clang 16 in my personal build, but I’m unsure if this goes against best practices and would be intentionally rendered non-functional in the future.

The build script I used is here: https://github.com/erinacio/personal-pkgbuilds/blob/master/llvm-project-17/PKGBUILD.

Can you explain what layout you have? Normally the clang driver should find the libc++ installed in <clang>/lib/<triple>. So if you build for x86_64-unknown-linux-gnu you need to make sure to pass --target=x86_64-unknown-linux-gnu or have the default triplet set to that.

There are some problems with triple normalization that happens at times, so the target need to match the directory name exactly (i.e.you can’t pass --target=x86_64-linux-gnu, since it won’t expand to the right thing).

The target triple is x86_64-pc-linux-gnu. This is also the target triple used by the host gcc:

$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/13.2.1/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure --enable-languages=ada,c,c++,d,fortran,go,lto,objc,obj-c++ --enable-bootstrap --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --with-build-config=bootstrap-lto --with-linker-hash-style=gnu --with-system-zlib --enable-__cxa_atexit --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-libstdcxx-backtrace --enable-link-serialization=1 --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-werror
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 13.2.1 20230801 (GCC)

Also, I used LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF to explicitly disable per-target runtime directory, as can be seen from my build script. So I think the target triple should not affect runtime library directory.

My LLVM install prefix for clang 17 is /opt/llvm17. libc++ is installed in the LLVM library directory, so we got /opt/llvm17/lib/lib{c++,c++abi,unwind}.{a,so,so.1,so.1.0}. The detailed file layout is here: https://gist.github.com/erinacio/b2c851dc7e2c1a94e5992e05a4672557.