This change is a consequence of the discussion in "RFC: Place libs in
Clang-dedicated directories", specifically the suggestion that
libunwind, libc++abi and libc++ shouldn't be using Clang resource
directory. Tools like clangd make this assumption, but this is
currently not true for the LLVM_ENABLE_PER_TARGET_RUNTIME_DIR build.
This change addresses that by moving the output of these libraries to
lib/$target/c++ and include/c++ directories, leaving resource directory only
for compiler-rt runtimes and Clang builtin headers.
Details
- Reviewers
smeenai beanz jdenny EricWF saugustine cmatthews - Commits
- rZORG23b95ce250b5: [runtimes] Move libunwind, libc++abi and libc++ to lib/$target/c++ and…
rG23b95ce250b5: [runtimes] Move libunwind, libc++abi and libc++ to lib/$target/c++ and…
rUNW361432: [runtimes] Move libunwind, libc++abi and libc++ to lib/$target/c++ and…
rCXXA361432: [runtimes] Move libunwind, libc++abi and libc++ to lib/$target/c++ and…
rG81f433b48c18: [runtimes] Move libunwind, libc++abi and libc++ to lib/$target/c++ and…
rCXX361432: [runtimes] Move libunwind, libc++abi and libc++ to lib/$target/c++ and…
rL361432: [runtimes] Move libunwind, libc++abi and libc++ to lib/$target/c++ and…
rC361432: [runtimes] Move libunwind, libc++abi and libc++ to lib/$target/c++ and…
Diff Detail
- Repository
- rC Clang
Event Timeline
This is a reland of D59013, apart from fixing the failing test on Windows, it also changes one thing where libraries are installed in lib/clang/<target> rather than lib/<target> based on the discussion in "RFC: Place libs in Clang-dedicated directories (affects openmp, libcxx, libunwind, compiler-rt)".
clang/test/Driver/linux-per-target-runtime-dir.c | ||
---|---|---|
15 ↗ | (On Diff #189968) | Shouldn't this have the clang component now? |
The layout currently looks as follows:
compiler-rt: headers: $prefix/lib/clang/$version/include libraries: $prefix/lib/clang/$version/$triple/lib/$name.$ext libc++, libc++abi, libunwind: headers: $prefix/include/c++/v1 libraries: $prefix/lib/clang/$triple/$name.$ext
So if we take x86_64-linux-gnu as an example target, it'd be:
include/c++/v1 lib/clang/x86_64-linux-gnu/{libc++.so,libc++abi.so,libunwind.so} lib/clang/9.0.0/x86_64-linux-gnu/lib/libclang_rt.builtins.a
I'm not super enthusiastic about the duplicated triple, but the only way to eliminate it would be to move the Clang resource directory inside of lib/clang/x86_64-linux-gnu, i.e. we'd have lib/clang/x86_64-linux-gnu/9.0.0/{include,lib}.
clang/test/Driver/linux-per-target-runtime-dir.c | ||
---|---|---|
15 ↗ | (On Diff #189968) | I haven't changed the location of headers, only libraries. Do you think we should move libc++ headers into clang subdirectory inside include as well? |
clang/test/Driver/linux-per-target-runtime-dir.c | ||
---|---|---|
15 ↗ | (On Diff #189968) | This is -L, so it's the search path for the libraries, right? |
clang/test/Driver/linux-per-target-runtime-dir.c | ||
---|---|---|
15 ↗ | (On Diff #189968) | Sorry about that, I was looking at a wrong line, you're right. |
LGTM, though you may wanna wait for @jdenny too.
I don't think the duplicated triple is too huge of a deal. I think the layout where the resource directory is moved inside the triple directory is a bit nicer, but I also don't know how much work that change would be and if it's worth it.
clang/test/Driver/linux-per-target-runtime-dir.c | ||
---|---|---|
15 ↗ | (On Diff #189972) | Idk if it's worth making this a bit more specific – clang -### should print out its InstallerDir, so you could capture that in a FileCheck regex and use it to check the exact path. |
One downside is that we would be duplicating Clang resource headers for each target which may not be too big of a deal but something worth mentioning.
clang/test/Driver/linux-per-target-runtime-dir.c | ||
---|---|---|
15 ↗ | (On Diff #189972) | I did that in the previous version but that was breaking on Windows and haven't yet figured out how to make it work there. |
lib/x86_64-linux-gnu/clang/9.0.0/{include,lib} would mean less duplication of the triple within system directories. Is there a reason not to do that? I'm not necessarily advocating for this. I'm just trying to understand what you've chosen.
In that case, could we symlink the target-specific include directories to a common directory?
Regardless of these points, your patch appears to strictly improve the situation, so maybe we should see how things go with it and then make further changes later if desired.
So, LGTM modulo the question I added inline. Thanks.
libcxx/lib/CMakeLists.txt | ||
---|---|---|
407 ↗ | (On Diff #189972) | Assume LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=True. Without your patch, it looks to me like specifying LIBCXX_INSTALL_PREFIX collapses the library destination from $prefix/lib/clang/$version/$triple/lib to $prefix/lib. With your patch, it looks to me like the library destination is always $prefix/lib/clang/$triple, and specifying LIBCXX_INSTALL_PREFIX simply changes $prefix. Is that correct? If so, is that worthwhile to note in the summary? |
I think it's ready to land. I was just waiting if anyone else wants to chime in, but it doesn't seem like.
I was also thinking about alternative names for the library path, specifically for headers we use include/c++ but for libraries we'll now use lib/clang/<target> which is not very consistent. I was considering lib/c++/<target> instead but that wouldn't work for libomp and I didn't come up with any other better alternatives.
Does that inconsistency cause a practical problem?
I was considering lib/c++/<target> instead
A practical benefit might be the ability to use -L to expose clang's c++ libs without exposing other clang libs as well, but I'm not sure whether that's a real use case.
but that wouldn't work for libomp
If we decide libomp shouldn't be version-locked, then I guess lib/openmp/<target> would work.
Is it safe to assume that lib/c++ and lib/openmp would manage to be as clang-dedicated as lib/clang? If other packages don't install to include/c++, then I suppose they don't install to lib/c++.
Not at the moment as far as I'm aware, but I'd like to make sure we consider all aspects to avoid more transitions in the future.
I was considering lib/c++/<target> instead
A practical benefit might be the ability to use -L to expose clang's c++ libs without exposing other clang libs as well, but I'm not sure whether that's a real use case.
This may be also beneficial for other compilers that would like to support Clang's C++ library.
but that wouldn't work for libomp
If we decide libomp shouldn't be version-locked, then I guess lib/openmp/<target> would work.
SGTM
Is it safe to assume that lib/c++ and lib/openmp would manage to be as clang-dedicated as lib/clang? If other packages don't install to include/c++, then I suppose they don't install to lib/c++.
AFAIK no other libraries currently use lib/c++.
Does the following match what you have in mind?
$prefix/ include/ c++/ v1/ limits.h ... openmp/ v1/ <------ I don't think openmp has anything like this now omp.h ompt.h ... lib/ c++/ $target/ libc++abi.so ... openmp/ $target/ libomp.so ... clang/ 9.0.0/ <----- resource directory include/ lib/ $target/ libclang_rt.asan_cxx.a ...
Iibc++ uses this scheme to allow the possibility of evolving the API but I'm not sure if it's necessary for openmp.
omp.h ompt.h ... lib/ c++/ $target/ libc++abi.so ... openmp/ $target/ libomp.so ... clang/ 9.0.0/ <----- resource directory include/ lib/ $target/ libclang_rt.asan_cxx.a ...
Almost with a small variation:
$prefix/ include/ c++/ v1/ limits.h ... openmp/ omp.h ompt.h ... lib/ $target/ <--- This way we don't have to duplicate $target in each subdirectory and it matches the layout of the resource directory c++/ libc++abi.so ... openmp/ libomp.so ... clang/ 9.0.0/ include/ lib/ $target/ libclang_rt.asan_cxx.a ...
WDYT?
It seems we have roughly the same situation for their ABIs. That is, for .so files, someone noted that libc++ and libunwind have always used the same version, .1, and openmp doesn't use a version (except in Debian packages). In other words, for each of these three, a change in ABI compatibility has never been indicated. For openmp only, it's apparently assumed a change never will need to be indicated (except in Debian packages).
There may be some very good rationale for why openmp is different in this way, but I haven't yet learned what it is.
omp.h ompt.h ... lib/ c++/ $target/ libc++abi.so ... openmp/ $target/ libomp.so ... clang/ 9.0.0/ <----- resource directory include/ lib/ $target/ libclang_rt.asan_cxx.a ...Almost with a small variation:
$prefix/ include/ c++/ v1/ limits.h ... openmp/ omp.h ompt.h ... lib/ $target/ <--- This way we don't have to duplicate $target in each subdirectory
We duplicate c++, openmp, etc. in each $target instead. If you have only one target, I guess that's better. Otherwise, does it matter?
and it matches the layout of the resource directory
Does the resource directory have any subproject directories, like c++, openmp, etc? If not, then it matches just as well either way. You just remove the level of subproject directories, right?
c++/ libc++abi.so ... openmp/ libomp.so ... clang/ 9.0.0/ include/ lib/ $target/ libclang_rt.asan_cxx.a ...WDYT?
To be clear, I'm not opposed to your proposals. I'm just trying to understand the relative advantages. Thanks.
They already use .2 for ABI v2 which is currently considered unstable but some project like Fuchsia already use. There's also an ongoing discussion to stabilize v2. However, this is only affecting the ABI and therefore .so, not headers which will continue using v1 as far as I'm aware (since the API is defined by the C++ standard after all).
There may be some very good rationale for why openmp is different in this way, but I haven't yet learned what it is.
@EricWF might have some insight into this.
We duplicate c++, openmp, etc. in each $target instead. If you have only one target, I guess that's better. Otherwise, does it matter?
Not every target may distribute or even support every runtime. For example, we don't currently ship openmp on Fuchsia because we haven't ported it yet. Similarly we don't ship every compiler-rt runtime.
and it matches the layout of the resource directory
Does the resource directory have any subproject directories, like c++, openmp, etc? If not, then it matches just as well either way. You just remove the level of subproject directories, right?
Not at the moment, but when designing the current resource directory layout, I haven't given this much though to various aspect so I wouldn't take it as indicative.
To be clear, I'm not opposed to your proposals. I'm just trying to understand the relative advantages. Thanks.
That makes sense, I'd like to understand various requirements for different runtimes before settling on the final layout. Updating this patch should be straightforward.
Thanks, I wasn't aware. I still see only .1 in my build, so apparently a different config is needed.
libunwind/CMakeLists.txt | ||
---|---|---|
190 ↗ | (On Diff #197241) | I naively assumed libunwind would have its own directory so it could be selected independently. Does this mean any library for C++ goes in c++? |
libunwind/CMakeLists.txt | ||
---|---|---|
190 ↗ | (On Diff #197241) | We could do that, but I'm not sure if it's worth doing without a clear use case? Do you know of any client that would want to consume libunwind independently of other C++ libraries? I'm aware of Rust but they build libunwind independently so there's no need for this. |
It's the LIBCXX_ABI_VERSION CMake option, see https://github.com/llvm/llvm-project/blob/master/libcxx/CMakeLists.txt#L121
Thanks.
libunwind/CMakeLists.txt | ||
---|---|---|
190 ↗ | (On Diff #197241) | I'm afraid I have no idea. I'm not close enough to these libraries to be an adequate reviewer by myself. Another reviewer should probably take a look at the new version of the patch. |
This commit stopped clang++ from finding libc++:
main.cc:
#include <vector> int main() { std::vector<int> x; return x.size(); }
$ clang++ main.cc -stdlib=libc++ -v clang version 9.0.0 (/w/src/llvm.org/tools/clang 754813c4737a444eeb4ea5b4070073dd251504cc) (/w/src/llvm.org e145e44a7c34acf851da0d6a2c66b274b6ebc82d) Target: x86_64-unknown-linux-gnu Thread model: posix InstalledDir: /w/c/org/bin Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8 Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8.4 Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9 Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9.3 Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8 Candidate multilib: .;@m64 Candidate multilib: 32;@m32 Candidate multilib: x32;@mx32 Selected multilib: .;@m64 "/w/c/org/bin/clang-9" -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -mrelax-all -disable-free -main-file-name main.cc -mrelocation-model static -mthread-model posix -mdisable-fp-elim -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -v -resource-dir /w/c/org/lib/clang/9.0.0 -internal-isystem /usr/local/include -internal-isystem /w/c/org/lib/clang/9.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdeprecated-macro -fdebug-compilation-dir /w/test -ferror-limit 19 -fmessage-length 0 -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -faddrsig -o /tmp/main-32e7f3.o -x c++ main.cc clang -cc1 version 9.0.0 based upon LLVM 9.0.0svn default target x86_64-unknown-linux-gnu ignoring nonexistent directory "/include" #include "..." search starts here: #include <...> search starts here: /usr/local/include /w/c/org/lib/clang/9.0.0/include /usr/include/x86_64-linux-gnu /usr/include End of search list. main.cc:1:10: fatal error: 'vector' file not found #include <vector> ^~~~~~~~ 1 error generated.