[cfe-dev] RFC: Place libs in Clang-dedicated directories (affects openmp, libcxx, libunwind, compiler-rt)
Jonas Hahnfeld via cfe-dev
cfe-dev at lists.llvm.org
Sun Feb 17 04:05:21 PST 2019
Hi Joel,
Am Donnerstag, den 14.02.2019, 17:29 -0500 schrieb Joel E. Denny:
> Hi,
>
> This RFC discusses placing Clang's libraries in Clang-dedicated
> directories (somewhere within `lib/clang` instead of `lib`) in both
> build trees and install trees. While fixing broken linking with
> openmp libraries was the original motivation, subprojects potentially
> affected by that problem or this change also include libcxx,
> libunwind, and compiler-rt.
>
> Motivation: Broken Default Linking
> ----------------------------------
>
> Clang by default prefers system openmp libraries over the ones built
> alongside Clang. The effect is that Clang-compiled openmp applications
> sometimes misbehave if the user doesn't adjust the library search
> path.
>
> For example, where `/home/jdenny/llvm` is built and installed from git
> master, but where my system openmp libraries under
> `/usr/lib/x86_64-linux-gnu` are from LLVM 6.0:
>
> ```
> $ cd /home/jdenny/llvm
> $ cat test.c
> #include <stdio.h>
> int main() {
> #pragma omp target teams
> printf("hello\n");
> return 0;
> }
> $ ./bin/clang -fopenmp -fopenmp-targets=nvptx64 test.c
> $ ./a.out
> ./a.out: error while loading shared libraries: libomptarget.so: cannot
> open shared object file: No such file or directory
> $ LD_LIBRARY_PATH=lib ./a.out
> Segmentation fault (core dumped)
> $ LD_LIBRARY_PATH=lib ldd a.out | grep libomp
> libomp.so.5 => /usr/lib/x86_64-linux-gnu/libomp.so.5
> (0x00007fab59748000)
> libomptarget.so => lib/libomptarget.so (0x00007fab59515000)
> ```
>
> The problem here is a little subtle. `-v` reveals that Clang
> specifies `-L/usr/lib/x86_64-linux-gnu` before
> `-L/home/jdenny/llvm/lib` when linking, and I have:
>
> ```
> $ ls -l /usr/lib/x86_64-linux-gnu/libomp.so
> lrwxrwxrwx 1 root root 11 Jan 7 2018
> /usr/lib/x86_64-linux-gnu/libomp.so -> libomp.so.5
> ```
>
> As a result, Clang links the executable as follows:
>
> ```
> $ readelf -d a.out | grep libomp.so
> 0x0000000000000001 (NEEDED) Shared library: [libomp.so.5]
> ```
>
> Now `LD_LIBRARY_PATH` cannot force `a.out` to find Clang's `libomp.so`
> because `a.out` wants `libomp.so.5` instead.
>
> As far as I know, there's nothing unusual about my system, which is a
> typical Ubuntu 18.04.2 installation. However, I have learned from
> others that `libomp.so.5` is installed by Debian's packages not by
> LLVM's cmake files [1], so many people might not see this particular
> problem.
>
> Even if `/usr/lib/x86_64-linux-gnu/libomp.so` weren't a symbolic link,
> it's still the wrong library, and incompatibilities could have caused
> a link failure instead of a run-time failure.
>
> Either way, it seems surprising and confusing that Clang doesn't
> always prefer its own libraries.
>
> Solution: Early `-L` for Clang-Dedicated Directory
> --------------------------------------------------
>
> The easiest solution is probably to assume users will manually specify
> `-L` when necessary to link against the right `libomp.so`. However,
> it seems like Clang should just do that automatically to help
> unsuspecting users avoid surprises like the one above.
+1 that Clang should get this right in most cases.
> I wrote a patch to make that happen [2]. The patch's basic approach
> is to place `libomp .so` in a directory for which, when linking, Clang
> automatically specifies a `-L` earlier than any `-L` for a system
> library directory. It's important that the directory is a
> Clang-dedicated directory (somewhere under `lib/clang`) so that other
> libraries unrelated to Clang are not accidentally elevated in the
> library search path. When possible, the patch makes this change for
> both the build tree and install tree so users can work out of either
> tree.
The drawback is that this directory is added before LIBRARY_PATH, see
below.
> This solution seems straight-forward, but it raises many questions.
>
> Q1: What is the right Clang-dedicated directory?
> ------------------------------------------------
>
> There are many possibilities. On my system:
>
> * `lib`: This directory is obviously not Clang-dedicated, but it's
> where libcxx, libunwind, and openmp currently place their libraries by
> default.
>
> * `lib/clang/9.0.0/lib/linux`: This directory is where compiler-rt
> libraries are placed by default, and their names are like
> `libclang_rt.asan-x86_64.so`.
>
> * `lib/clang/9.0.0/x86_64-unknown-linux-gnu/lib`: When the cmake
> option `-DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=True` is set, this
> directory is where compiler-rt, libcxx, and libunwind libraries are
> placed, and the compiler-rt libraries then drop the redundant
> `-x86_64` from their names.
>
> * `lib/clang/9.0.0/lib/linux/x86_64`: This directory has the nice
> advantage that `-frtlib-add-rpath` tells Clang to add a `-rpath` for
> this directory so you don't have to set `LD_LIBRARY_PATH` when
> executing `a.out`. However, it turns out that `-rpath` doesn't work
> correctly for me in the case of openmp offloading [3]. As far as I
> can tell, this directory is currently populated only by some Android
> tool chains [3].
>
> * For libcxx and libunwind libraries, it's been suggested that a
> Clang-dedicated directory should not be specific to the Clang version
> (shouldn't contain `9.0.0`) because the libraries themselves are not
> locked to the Clang version, and a possible directory layout has been
> proposed [4]. My understanding is that this approach generally makes
> sense when the shared libraries have version numbers, like
> `libomp.so.5`. In that case, it needs to be possible to find older
> shared libraries that older software has already become dependent upon
> while using older Clang installations. It's easier to find them, with
> `LD_LIBRARY_PATH` for example, if every Clang installation places such
> libraries in the same Clang-version-independent directory, where the
> libraries are still distinct due to the version numbers in their
> names, instead of placing them in a bunch of different
> Clang-version-specific directories. Please correct me if I've
> misunderstood this situation.
AFAIK libc++ and libunwind are using the same ABI version .1 since the
beginning. That's probably kind of the same guarantee that libomp has:
You can run an old binary with a newer version of the library.
However, that defeats the point of being "distinct" when installing the
libraries in a single directory that is independent of the Clang
version.
> Which choice is right for openmp libraries? Debian is giving version
> numbers to `libomp.so`, but is that right? If it is, the last choice
> might make sense. If not, perhaps one of the previous choices is
> better.
>
> Q2: Should `lib` also contain the libraries?
> --------------------------------------------
>
> As mentioned above, `-DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=True` moves
> libcxx, libunwind, and compiler-rt libraries to their new
> Clang-dedicated directory. However, the patch I've proposed for
> openmp instead duplicates libraries into their new Clang-dedicated
> directory. I figured duplicating would be better for backward
> compatibility than moving. Is it necessary?
>
> (Actually, I should probably be creating symlinks instead of duplicates.)
>
> Q3: Is it really OK to elevate Clang's libraries?
> -------------------------------------------------
>
> For me, this is the biggest unknown about this change. That is, does
> any user depend on being able to drop his own `libomp.so` in a system
> library directory so that Clang will prefer it over Clang's own
> `libomp.so`? If so, is that an important enough use case that we
> should continue to risk subtly breaking the compiles of other users by
> default?
As I said in the reviews we are building and using custom versions of
libomp with a globally installed (release) version of Clang (like we
can do with the Intel Compiler). For my usage I'm currently relying on
a combination of LIBRARY_PATH and LD_LIBRARY_PATH which many people
think is fragile, but it has worked so far. I guess we could switch to
using `-L` (and LD_LIBRARY_PATH), but setting an environment variable
is easier than telling all kind of build systems to modify their
compiler invocations...
I'm not sure if that qualifies as "important enough", but I think
that's a valid use case that would break with the proposed changes.
Maybe we can have a directory that is added after LIBRARY_PATH but
before all "default" system directories?
> Q4: Should libcxx, libunwind, or compiler-rt be changed too?
> ------------------------------------------------------------
>
> An early reaction to my patch was that we need to either handle the
> various Clang libraries consistently or show why they should be
> handled differently. My patch so far only changes openmp, and it does
> not make it consistent with other subprojects' libraries.
>
> Keep in mind that, while compiler-rt libraries are already placed in a
> Clang-dedicated directory by default, libcxx and libunwind libraries
> are not and so could potentially be affected by the motivating example
> I gave. Must users specify
> `-DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=True` (which adds the problem of
> Clang-version locking) to avoid that problem? Shouldn't the default
> configuration be the most user-friendly?
>
> Conclusion
> ----------
>
> So far, my estimate at the best path forward is as follows:
>
> * openmp and compiler-rt libraries should always be placed in a
> Clang-dedicated, Clang-version-specific directory.
Based on the reasons given above I don't understand why openmp needs to
be version-locked with Clang. I think the guarantee is that you can run
old binaries with a newer version of the library, just as you can with
libc++ and friends. So why should openmp be treated differently?
Regards,
Jonas
> * libcxx and libunwind libraries should always be placed in a
> Clang-dedicated, Clang-version-independent directory.
>
> * For each of those directories, Clang should specify `-L` earlier
> than any system library directory.
>
> * openmp, libcxx, and libunwind libraries should also be symlinked
> directly in `lib`, for backward compatibility at least.
>
> * `-DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=True` should be dropped and
> dependent projects updated. Alternatively, for backward
> compatibility, this option could revert the Clang-dedicated directory
> layout to the layout it currently produces (in particular, it places
> libcxx and libunwind libraries in Clang-version-specific directories).
>
> There are details like exact directory names to discuss, but does this
> high-level plan make sense?
>
> Thanks.
>
> Joel
>
> [1]:
https://reviews.llvm.org/D55725#1370823>
> [2]:
https://reviews.llvm.org/D55725>
> [3]:
https://reviews.llvm.org/D55725#1371807>
> [4]:
https://reviews.llvm.org/D30733#697781>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20190217/164ea928/attachment.sig>
More information about the cfe-dev
mailing list