Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Building fails on alpine: "libclang.so could not be opened: Dynamic loading not supported" #724

Open
chrysn opened this issue Nov 12, 2022 · 3 comments
Assignees

Comments

@chrysn
Copy link
Contributor

chrysn commented Nov 12, 2022

I've tried installing c2rust on Alpine Linux, and run into build failures that could not be fixed just by adding new packages.

Reproducing

by means of Docker (but should be the same on any other virtualization or native):

$ docker run --rm -it --network=host alpine
$ apk update
$ apk add clang clang-libs cmake make clang llvm g++ gcc llvm13-dev llvm13-static musl-dev patch clang-dev patch clang-static rustup                                                                              
$ apk add ncurses-dev zlib-dev libffi-dev
$ rustup-init
$ source $HOME/.cargo/env
$ cargo install --locked c2rust

The second apk line is not needed immediately, but at later stages after applying a patch.

(Alternatively, build from git -- same result).

Output

[...]
  thread 'main' panicked at 'Unable to find libclang: "the `libclang` shared library at /usr/lib/libclang.so.13.0.1 could not be opened: Dynamic loading not supported"', /root/.cargo/registry/src/github.com-1ecc6299db9ec823/bindgen-0.59.2/src/lib.rs:2144:31
[...]

Further references

There is ongoing work to package c2rust for alpine, and @maribu has experimental fixes in a patch at https://gitlab.alpinelinux.org/alpine/aports/-/merge_requests/41287/diffs#diff-content-e7a5df424a0722085783354ec4640b08da0b9312 (essentially, building the bindgen dependency statically). When applying these, building continues a bit further (the second apk add line above installed the relevant dependencies), but then segfaults -- possibly due to statically and dynamically linked symbols being present at the same time. Maybe what it'd need here is a more general switch that makes everything either staticlally or dynamically linked, but I don't know how complicated that'd be.

(By the way, the referenced patches also manually apply the latest fixes to LLVM-15 (which can be dropped once #690 is done hint hint); the package aims at the edge release of alpine, whereas the above reproducing lines work on Alpine 3.16, which still has clang 13.)

wasmer had similar troubles at wasmerio/wasmer#1766 and fixed them differently in wasmerio/wasmer@5962d3f. Maybe that's a more fruitful approach, but I haven't really found out whether that's a real fix or it just disables something that'd break on musl.

@maribu
Copy link

maribu commented Nov 13, 2022

When applying these, building continues a bit further (the second apk add line above installed the relevant dependencies), but then segfaults -- possibly due to statically and dynamically linked symbols being present at the same time.

Note: The segfault only occurs when using cargo / rust from rustup. With the versions packaged on Alpine, the build succeeds. I'm quite sure that with the patches applied that forces bindgen to link statically, that libclang is indeed only linked in statically.

Note that bindgen by default provides the runtime feature, which depends on clang-sys with the runtime feature. That in turn definitely depends on dynamic linking of libclang. I fear that the reason the build just works on glibc based distros is that the binary ends up being linked twice against libclang.

And yes, this is very much possible: I was once debugging an issue where two incompatible libudev implementations where linked in: The executable itself was linked dynamically against libudev and dynamically against a second lib, which as statically linked against a completely different libudev implementation. Passing data around with different expectations on how exactly the data should look like resulted in segfaults there.

I think it may be possible that something similar happens here when the build succeeds without disabling the runtime feature of bindgen while at the same time forcing static linking of libclang.)

@maribu
Copy link

maribu commented Nov 13, 2022

This is btw. the backtrace with debug symbols in libclang from build-script-build:

(gdb) bt
#0  0x000000000052d776 in ?? ()
#1  0x00007ffff6940c64 in llvm::StringMap<llvm::NoneType, llvm::MallocAllocator>::try_emplace<>(llvm::StringRef) (Key=..., this=0x7ffff7ffc770 <clang::format::FormatTokenLexer::CSharpAttributeTargets>)
    at /usr/lib/llvm15/include/llvm/ADT/StringMap.h:329
#2  llvm::StringSet<llvm::MallocAllocator>::insert (key=..., 
    this=0x7ffff7ffc770 <clang::format::FormatTokenLexer::CSharpAttributeTargets>)
    at /usr/lib/llvm15/include/llvm/ADT/StringSet.h:35
#3  llvm::StringSet<llvm::MallocAllocator>::StringSet (
    this=0x7ffff7ffc770 <clang::format::FormatTokenLexer::CSharpAttributeTargets>, initializer=...)
    at /usr/lib/llvm15/include/llvm/ADT/StringSet.h:30
#4  0x00007ffff5d8a722 in __static_initialization_and_destruction_0 (__initialize_p=<optimized out>, 
    __priority=<optimized out>)
    at /home/maribu/Repos/software/aports/main/clang15/src/clang-15.0.4.src/lib/Format/FormatTokenLexer.cpp:279
#5  _GLOBAL__sub_I_FormatTokenLexer.cpp(void) ()
    at /home/maribu/Repos/software/aports/main/clang15/src/clang-15.0.4.src/lib/Format/FormatTokenLexer.cpp:1200
#6  0x00007ffff76f7089 in libc_start_init () at ../src_musl/src/env/__libc_start_main.c:64
#7  0x00007ffff76f70ae in libc_start_main_stage2 () at ../src_musl/src/env/__libc_start_main.c:91
#8  0x00007ffff5d8a8ef in _start ()

I get the exact same backtrace when building RIOT apps from the build-script-build generated there, so this really seems to be an issue with upstream rust, libclang and musl not working together as intended.

However, the issues with forcing static linking of libclang conflicting with bingen without disabling the runtime feature is to my understanding something that needs to be fixed in c2rust.

@maribu
Copy link

maribu commented Nov 14, 2022

$ export RUSTFLAGS=-Ctarget-feature=-crt-static

fixes the issue with the rustup toolchain.

Update: It fixes the segfault. It doesn't fix the issue that libclang cannot be linked in both statically and dynamically on musl. And IMO this shouldn't be done on glibc either.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants