-
Notifications
You must be signed in to change notification settings - Fork 81
Add LIB_SYS_TRY_SHARED ENV var to try to link with shared library #206
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
base: main
Are you sure you want to change the base?
Add LIB_SYS_TRY_SHARED ENV var to try to link with shared library #206
Conversation
On cross-compilation libz-sys is always building static zlib library, except for Apple platforms. If target has an installed zlib shared library, this is problem, because: 1. the binary is increased, because we are including a static zlib as well 2. it may cause build issues if the pkg-config sets the linker arguments, like this: /tmp/rustc0ZqD0F/liblibz_sys-84983a050a121d20.rlib(inflate.o): relocation R_AARCH64_ADR_PREL_PG_HI21 against symbol '__stack_chk_guard' which may bind externally can not be used when making a shared object; recompile with -fPIC To workaround the issue, add a LIB_SYS_TRY_SHARED=1 ENV var (similarly to LIBZ_SYS_STATIC=1) to force the use of the shared library, recognized by the pkg-config. fixes rust-lang#201
612984b
to
2422982
Compare
Thanks a lot for tackling this. @jongiddy I feel that Thanks everyone for your help. |
Neither option is ideal. Using an environment variable means there is a hidden dependency that affects the build. When anyone needs support, it is an extra relevant piece of information they need to supply. And it is easy to not be aware whether it is set or not. Using a feature is painful when a transitive dependency is deeply nested, and Pragmatically, since there is already an environment variable for controlling static vs dynamic, I'd accept using an environment variable here. However, I suggest that the existing variable is reused, so that setting |
FWIW there is precedent in other
|
Thanks a lot for the summary, it's good to know the standards. This PR is at a stage where the question remains if |
This one is interesting. Matches the proposed one variable model with 0 meaning force dynamic and 1 meaning force static. |
I'm hitting this when trying to cross-compile a project. |
I think this patch is stuck on this question along with the implementation lacking discoverability as there are no docs at all. |
Is there something I can do in the meanwhile to be able to cross-compile the project I'm looking at? |
One could tell Cargo to use the patched version of the dependency (with |
In my case this does not seem to help.
with zlib manually installed, just in case - and this in a Debian image:
and I patch libz-sys by:
but it seems to not understand, and the aarch64 compiler is called with invalid flags
The project I'm trying to cross-compile (from amd64) is this one: https://github.com/BoltzExchange/boltz-backend.git |
Maybe a different issue? The local override can also point to a local checkout of the crate, which might help to make adjustments to |
Yes, this was related to something else. I managed to cross-compile by overriding the dependency. Thanks. :) |
UPDATE: PR: #244 TL;DR: The correct solution would be to remove it entirely, since contributions after Feb 2016 have made that much more viable:
NOTE: Remainder of this response is for reference/context to justify the change, with an abundance of links for traceability. The forced build for cross-compilation was added in Feb 2016 with this Sep 2018 PR adding the following comment:
Which is presumably more about building for a different OS, rather than architecture given the target conditions? (and technically musl/glibc targets on linux). Having attempted cross-compiling for a foreign arch in the past I do recall that having more friction, but I'd chalk that up partially to inexperience and tooling options available at the time. In Mar 2016 Lines 25 to 31 in 9c453d3
After potentially building zlib, there's even a function to test searching for zlib library to link (implemented in Sep 2018 too from this earlier discussion + later related fix for debug builds (Feb 2024) bundled with a cross-compile fix of a fix for the apple target exception): Lines 93 to 102 in 9c453d3
That'd be valid in a cross-compilation scenario and verify the library is available 🤔 The I guess it's a bit late to address this concern without the risk of some breakage? But since not all For consistency regarding cross-compiling, when would it make sense for someone to build for their native arch and foreign arch, but have the linking differ?
If I am building and want dynamic linking or static linking, I'd want consistency (except when it's not viable), not troubleshooting why builds cross-compiled aren't linking as expected, but are when I run them through QEMU / native host for that arch. Your build environment should not need to be a native arch for linking to be supported, remove the constraint entirely? Those that want static builds can do so via the ENV that's been available since 2016. Features can be useful for crates as was discussed earlier in this PR feedback by @jongiddy , but when transitive deps do this it can be problematic especially as an end user building a project/crate and you want to have control over your build. ENV is much more useful there so I agree that The proposal to leverage a feature for opt-in that conflicts with
|
@tsjk you can more easily cross-compile via Zig (with Here's a full example within a Docker container (Fedora 42) as an example, but you should be able to adapt to your equivalent environment rather easily: # Fedora container for a reproducible build environment, running on an amd64 / x86_64 host:
$ docker run --rm -it --workdir /example fedora:42
# Install base deps:
# Boltz specific deps needed to compile from host arch: npm + protobuf-compiler
dnf install -yq gcc git-core npm protobuf-compiler rustup zig
# Setup Rust with Zig:
rustup-init -y --profile minimal --default-toolchain stable
export PATH="/root/.cargo/bin:${PATH}"
cargo install cargo-zigbuild
# Add cross-compilation support (libs needed for linking + arm64 target):
# NOTE: `openssl-sys` additionally needs to parse headers and since the host vs target arch differs,
# you will need to use `OPENSSL_DIR` or `PKG_CONFIG_SYSROOT_DIR` ENV.
export SYSROOT_ARM64=/opt/sysroot/aarch64-gnu
dnf --installroot ${SYSROOT_ARM64} --use-host-config --setopt=install_weak_deps=0 --forcearch=aarch64 \
install -yq libpq-devel openssl-devel
rustup target add aarch64-unknown-linux-gnu
# Grab the project source:
git clone --recurse-submodules https://github.com/BoltzExchange/boltz-backend .
# Rust build relies upon files generated from `node_modules`:
# NOTE: Using lock file fails due to outdated `[email protected]` requirement, where Python 3.13 no longer providing a distutils module
npm install --no-package-lock
# Now you can build the rust project for the foreign arch:
# - `PKG_CONFIG_SYSROOT_DIR` is only needed for cross-compilation for `openssl`,
# alternatively skip the need for `pkg-config` via `OPENSSL_DIR="${CROSS_ROOT_ARM64}/usr"`
# - `RUSTFLAGS` must be set to the aarch64 sysroot for correctly linking to the arm64 `.so` files
cd boltzr
PKG_CONFIG_SYSROOT_DIR="${SYSROOT_ARM64}" RUSTFLAGS="-L ${SYSROOT_ARM64}/usr/lib64" cargo zigbuild --release --target aarch64-unknown-linux-gnu I think that is simpler than using Cargo to cross-compile without Zig 😅 The PR was not used in my example for a successful build via Zig, so it would have built from source successfully? (EDIT: Seems that it was a build-dep, whereas your linked libz for OpenSSL is runtime, thus no conflict) Verification:
# Required as not running via `chroot` or via an aarch64 container/host:
# - `ld-linux-aarch64.so.1 --list` is the equivalent to `ldd` (which is often a shell script wrapper).
# - `LD_LIBRARY_PATH` to add libs from the aarch64 sysroot to the search path for resolving libs.
$ LD_LIBRARY_PATH=/opt/sysroot/aarch64-gnu/usr/lib64 /opt/sysroot/aarch64-gnu/lib/ld-linux-aarch64.so.1 --list target/aarch64*/release/boltzr
linux-vdso.so.1 (0x0000400000810000)
libpq.so.5 => /opt/sysroot/aarch64-gnu/usr/lib64/libpq.so.5 (0x0000400003d30000)
libssl.so.3 => /opt/sysroot/aarch64-gnu/usr/lib64/libssl.so.3 (0x0000400003da0000)
libcrypto.so.3 => /opt/sysroot/aarch64-gnu/usr/lib64/libcrypto.so.3 (0x0000400003e90000)
libm.so.6 => /opt/sysroot/aarch64-gnu/usr/lib64/libm.so.6 (0x0000400004290000)
libpthread.so.0 => /opt/sysroot/aarch64-gnu/usr/lib64/libpthread.so.0 (0x0000400004360000)
libc.so.6 => /opt/sysroot/aarch64-gnu/usr/lib64/libc.so.6 (0x0000400004390000)
libdl.so.2 => /opt/sysroot/aarch64-gnu/usr/lib64/libdl.so.2 (0x0000400004560000)
/lib/ld-linux-aarch64.so.1 => /opt/sysroot/aarch64-gnu/lib/ld-linux-aarch64.so.1 (0x00007cf124eb0000)
libgssapi_krb5.so.2 => /opt/sysroot/aarch64-gnu/usr/lib64/libgssapi_krb5.so.2 (0x0000400004590000)
libldap.so.2 => /opt/sysroot/aarch64-gnu/usr/lib64/libldap.so.2 (0x0000400004600000)
libz.so.1 => /opt/sysroot/aarch64-gnu/usr/lib64/libz.so.1 (0x0000400004690000)
libkrb5.so.3 => /opt/sysroot/aarch64-gnu/usr/lib64/libkrb5.so.3 (0x00004000046d0000)
libk5crypto.so.3 => /opt/sysroot/aarch64-gnu/usr/lib64/libk5crypto.so.3 (0x00004000047b0000)
libcom_err.so.2 => /opt/sysroot/aarch64-gnu/usr/lib64/libcom_err.so.2 (0x00004000047f0000)
libkrb5support.so.0 => /opt/sysroot/aarch64-gnu/usr/lib64/libkrb5support.so.0 (0x0000400004820000)
libkeyutils.so.1 => /opt/sysroot/aarch64-gnu/usr/lib64/libkeyutils.so.1 (0x0000400004850000)
libresolv.so.2 => /opt/sysroot/aarch64-gnu/usr/lib64/libresolv.so.2 (0x0000400004880000)
liblber.so.2 => /opt/sysroot/aarch64-gnu/usr/lib64/liblber.so.2 (0x00004000048b0000)
libevent-2.1.so.7 => /opt/sysroot/aarch64-gnu/usr/lib64/libevent-2.1.so.7 (0x00004000048f0000)
libsasl2.so.3 => /opt/sysroot/aarch64-gnu/usr/lib64/libsasl2.so.3 (0x0000400004970000)
libselinux.so.1 => /opt/sysroot/aarch64-gnu/usr/lib64/libselinux.so.1 (0x00004000049b0000)
libcrypt.so.2 => /opt/sysroot/aarch64-gnu/usr/lib64/libcrypt.so.2 (0x0000400004a00000)
libpcre2-8.so.0 => /opt/sysroot/aarch64-gnu/usr/lib64/libpcre2-8.so.0 (0x0000400004a50000) But as # Alternatively... chroot in:
$ cp target/aarch64*/release/boltzr /opt/sysroot/aarch64-gnu/tmp/boltzr
$ dnf --installroot /opt/sysroot/aarch64-gnu --use-host-config --forcearch=aarch64 install patchelf
$ chroot /opt/sysroot/aarch64-gnu
# Direct deps linked (zlib from ldd was implicit from openssl link):
$ patchelf --print-needed /tmp/boltzr
libpq.so.5
libssl.so.3
libcrypto.so.3
libm.so.6
libpthread.so.0
libc.so.6
libdl.so.2
ld-linux-aarch64.so.1
$ patchelf --print-needed /usr/lib64/libcrypto.so.3
libz.so.1
libc.so.6
ld-linux-aarch64.so.1
# `libcrypto` is the only dep requiring `libz`:
$ exit
$ cargo install lddtree
$ lddtree target/aarch64*/release/boltzr /opt/sysroot/aarch64-gnu | grep -B1 libz
# Output omitted
# Here we can see that boltzr project uses `libz-sys` crate as a build-dep:
$ cargo tree -i libz-sys
libz-sys v1.1.20
└── libgit2-sys v0.18.0+1.9.0
└── git2 v0.20.0
└── built v0.8.0
[build-dependencies]
└── boltzr v3.11.0 (/example/boltzr) So in your case |
On cross-compilation libz-sys is always building static zlib library, except for Apple platforms. If target has an installed zlib shared library, this is problem, because:
the binary is increased, because we are including a static zlib as well
it may cause build issues if the pkg-config sets the linker arguments, like this:
/tmp/rustc0ZqD0F/liblibz_sys-84983a050a121d20.rlib(inflate.o): relocation R_AARCH64_ADR_PREL_PG_HI21 against symbol '__stack_chk_guard' which may bind externally can not be used when making a shared object; recompile with -fPIC
To workaround the issue, add a LIB_SYS_TRY_SHARED=1 ENV var (similarly to LIBZ_SYS_STATIC=1) to force the use of the shared library, recognized by the pkg-config.
fixes #201