Inconsistent libc++ search paths

Hi,

in lib/Driver/ToolChains/Linux.cpp, the search order for libc++
headers and libraries seems inconsistent.

Headers are searched in
1. Resource dir
2. Driver dir
3. %sysroot/usr/include/c++

Libraries are searched in
1. Driver dir only if it is under sysroot (!)
2. %sysroot/lib
3. %sysroot/usr/lib

When building with what Linux::addLibCxxIncludePaths calls
"development, non-installed" clang and a sysroot (ex. I'm using one
from Android NDK) where both locations have a copy of libc++, clang
picks libc++ headers from its resource dir, and an incompatible
library from sysroot.

Comments around the library search code suggest that the order should
not be changed. Does it make sense to tweak the headers search order
to match? That way building with local libc++ and a sysroot would
require extra flags (because clang would default to sysroot headers),
but that is already the case for the -shared-libc++ case.

Maybe the reason they differ is so you get new libc++ headers but still use the system dylib by default on Mac? I know that’s a use case that’s fairly carefully maintained, but idk if it’s intended to be the default.

From the NDK side of things, changing the libc++ header search to match the libc++ library search should be fine.

Definitely a bug, not sure what should be the right fix (match includes with libraries, the other way around or something in between), but wanted to point out another oddity in described driver behavior.
We should not use -resource-dir for anything other than the internal clang headers, tools like clang-tidy or clangd rely on this to override the internal headers without overriding the C++ standard library.

Maybe the reason they differ is so you get new libc++ headers but still use the system dylib by default on Mac? I know that’s a use case that’s fairly carefully maintained, but idk if it’s intended to be the default.

I don’t think that’s the case. The search paths for libc++ on MacOS are handled in “lib/Driver/ToolChains/Darwin.cpp” in DarwinClang::AddClangCXXStdlibIncludeArgs.

This is already unified, but only for the per-target runtime layout (LLVM’s CMake build uses that layout when you set the LLVM_ENABLE_PER_TARGET_RUNTIME_DIR option).

Definitely a bug, not sure what should be the right fix (match includes with libraries, the other way around or something in between), but wanted to point out another oddity in described driver behavior.
We should not use -resource-dir for anything other than the internal clang headers, tools like clang-tidy or clangd rely on this to override the internal headers without overriding the C++ standard library.

There seems to be an overlap between http://lists.llvm.org/pipermail/cfe-dev/2019-February/061307.html which has the discussion on where to place different libraries and headers. We should consider unifying the two discussions.

Maybe the reason they differ is so you get new libc++ headers but still use the system dylib by default on Mac? I know that’s a use case that’s fairly carefully maintained, but idk if it’s intended to be the default.

I don’t think that’s the case. The search paths for libc++ on MacOS are handled in “lib/Driver/ToolChains/Darwin.cpp” in DarwinClang::AddClangCXXStdlibIncludeArgs.

On Darwin Clang prefers libc++ headers from Clang but always uses system libc++. I tried to change that in D45639 and make it behave like other platforms but I’ve been told that this is WAI.

I still think it’s unfortunate because it requires solutions like -nostdlib++ libc++.a libc++abi.a libunwind.a to use libc++ that comes with Clang instead of the system one (we also cannot combine these into a single library because D44671 never landed).

From the NDK side of things, changing the libc++ header search to match the libc++ library search should be fine.

Hi,

in lib/Driver/ToolChains/Linux.cpp, the search order for libc++
headers and libraries seems inconsistent.

Headers are searched in

  1. Resource dir
  2. Driver dir
  3. %sysroot/usr/include/c++

Libraries are searched in

The first one will be Resource dir, but only if you’re using the per-target runtime layout. In that case the first location that’s searched is lib/clang/9.0.0//lib.

Thanks for the pointer, I have not been following this discussion, doing that now. Don’t have anything to add at this point, though.
I think the important part is covered in the first message of the thread “if there is no version lock with the compiler, it should not live in the resource directory”. As long as this holds, our tools should be fine.