This is an archive of the discontinued LLVM Phabricator instance.

[runtimes] Move libunwind, libc++abi and libc++ to lib/$target/c++ and include/c++
ClosedPublic

Authored by phosek on Mar 8 2019, 5:08 PM.

Details

Summary

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.

Diff Detail

Repository
rC Clang

Event Timeline

phosek created this revision.Mar 8 2019, 5:08 PM
Herald added projects: Restricted Project, Restricted Project, Restricted Project. · View Herald Transcript
phosek added a comment.EditedMar 8 2019, 5:09 PM

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)".

smeenai added inline comments.Mar 8 2019, 5:11 PM
clang/test/Driver/linux-per-target-runtime-dir.c
15 ↗(On Diff #189968)

Shouldn't this have the clang component now?

phosek added a comment.Mar 8 2019, 5:14 PM

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}.

phosek marked an inline comment as done.Mar 8 2019, 5:15 PM
phosek added inline comments.
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?

smeenai added inline comments.Mar 8 2019, 5:17 PM
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?

ormris added a subscriber: ormris.Mar 8 2019, 5:19 PM
phosek updated this revision to Diff 189972.Mar 8 2019, 5:27 PM
phosek marked 2 inline comments as done.
phosek added inline comments.
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.

smeenai accepted this revision.Mar 11 2019, 11:49 AM

LGTM, though you may wanna wait for @jdenny too.

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}.

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.

This revision is now accepted and ready to land.Mar 11 2019, 11:49 AM
phosek marked an inline comment as done.Mar 12 2019, 12:52 AM

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.

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.

jdenny accepted this revision.Mar 13 2019, 10:58 AM

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}.

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.

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.

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.

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?

Is there anything I can do to help this patch make progress?

Is there anything I can do to help this patch make progress?

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.

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.

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++.

ormris removed a subscriber: ormris.Apr 18 2019, 1:28 PM

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.

Does that inconsistency cause a practical problem?

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
            ...

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

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?

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

Iibc++ uses this scheme to allow the possibility of evolving the API but I'm not sure if it's necessary for openmp.

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.

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).

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.

phosek updated this revision to Diff 197241.Apr 29 2019, 6:46 PM
phosek retitled this revision from [runtimes] Move libunwind, libc++abi and libc++ to lib/clang/ and include/ to [runtimes] Move libunwind, libc++abi and libc++ to lib/$target/c++ and include/c++.
phosek edited the summary of this revision. (Show Details)

I've updated and rebased the patch, let me know what you think.

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).

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.

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++?

phosek marked an inline comment as done.Apr 30 2019, 11:23 AM
phosek added inline comments.
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 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).

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.

Thanks, I wasn't aware. I still see only .1 in my build, so apparently a different config is needed.

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.

phosek marked an inline comment as not done.Apr 30 2019, 12:40 PM
phosek added a subscriber: rsmith.
phosek added inline comments.
libunwind/CMakeLists.txt
190 ↗(On Diff #197241)

@EricWF @rsmith is this something you have an opinion on (or can you recommend someone who might)?

echristo added a subscriber: echristo.

Adding Sterling and Chris to this to take a look at the new layout :)

saugustine accepted this revision.May 8 2019, 3:09 PM
This revision was automatically updated to reflect the committed changes.

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.
E5ten added a subscriber: E5ten.Jun 3 2019, 3:54 PM