cross/crossdirect: improve rust handling (MR 4234)

Add a cargo wrapper which appends a --target argument to the command
line. This makes cargo pass the --target argument to rustc for crates
being built for the target architecture, even if the target is the same
as the host. It will omit the --target argument for build scripts and
crates used in macros.

Check for this --target argument in the rustc wrapper and adjust the
library paths depending on its presence. The fallback that runs rustc
under qemu is no longer needed because macros are now built for the
native architecture and can be loaded into the native compiler without
any problems.

Also check if the arguments passed to rustc are "-vV". If this is the
case, we still need to fall back to the target rustc because the native
rustc will return the wrong architecture. If the wrong host architecture
is passed to a build script, it might try to look for a cross-compiler
or do something else that doesn't work.

[ci:skip-build]: already built successfully in CI
This commit is contained in:
Affe Null 2023-07-06 10:20:23 +02:00 committed by Oliver Smith
parent 042d577de4
commit f0286576e7
No known key found for this signature in database
GPG key ID: 5AE7F5513E0885CB
3 changed files with 103 additions and 57 deletions

View file

@ -16,14 +16,14 @@
# version is implemented as simple shell wrappers. # version is implemented as simple shell wrappers.
pkgname=crossdirect pkgname=crossdirect
pkgver=4 pkgver=5
pkgrel=3 pkgrel=0
pkgdesc="Wrappers to launch native cross compilers in foreign chroots" pkgdesc="Wrappers to launch native cross compilers in foreign chroots"
url="https://postmarketOS.org" url="https://postmarketOS.org"
arch="all" arch="all"
license="MIT" license="MIT"
options="!check" options="!check"
source="crossdirect.c rustc.sh rust-qemu-linker.sh" source="cargo.sh crossdirect.c rustc.sh rust-qemu-linker.sh"
build() { build() {
cd "$srcdir" cd "$srcdir"
@ -40,9 +40,6 @@ build() {
-Werror \ -Werror \
-DHOSTSPEC="\"$_hostspec\"" \ -DHOSTSPEC="\"$_hostspec\"" \
crossdirect.c crossdirect.c
# rustc
sed "s/@ARCH@/$_arch/g" rustc.sh >rustc-"$_arch"
done done
} }
@ -51,9 +48,11 @@ package() {
_archs="x86_64 armhf armv7 aarch64" _archs="x86_64 armhf armv7 aarch64"
_bins="c++ cc cpp g++ gcc clang clang++" _bins="c++ cc cpp g++ gcc clang clang++"
# Rust: qemu-linker # Rust wrappers
install -Dm755 "$srcdir/rust-qemu-linker.sh" \ install -Dm755 "$srcdir/rust-qemu-linker.sh" \
"$pkgdir/usr/lib/crossdirect/rust-qemu-linker" "$pkgdir/usr/lib/crossdirect/rust-qemu-linker"
install -Dm755 "$srcdir/cargo.sh" "$pkgdir/usr/lib/crossdirect/cargo.sh"
install -Dm755 "$srcdir/rustc.sh" "$pkgdir/usr/lib/crossdirect/rustc.sh"
# Iterate over architectures # Iterate over architectures
for _arch in $_archs; do for _arch in $_archs; do
@ -73,10 +72,13 @@ package() {
ln -s "crossdirect-$_arch" "$_hostspec-$_bin" ln -s "crossdirect-$_arch" "$_hostspec-$_bin"
done done
# Rust: arch-specific rustc wrapper ln -s ../cargo.sh cargo
install -Dm755 "$srcdir/rustc-$_arch" "$_bindir/rustc" ln -s ../rustc.sh rustc
done done
} }
sha512sums="500107e5aff8b34e74b54982ebcd447fc41bc8283956d506561b031a055cb30ec12698047c2604918b4b6d8560fe03db427a63dff2b83c907e8494b7f5233f29 crossdirect.c sha512sums="
6be16ba88720e628a3ecc8fa53f8e7a21d2af268b0509745d989139874d6b94b640bfcff09575eaa19073810be6ef91169c1f83e94f5cf8e6819f2670d9408de rustc.sh 0f4b48f250425dc57f63955fc8b38477d23db793bee367c3fbe03c3d2a559ba576434d07518310db4cae9d90d501af4051b80038b10fae94b980e537fc9374ad cargo.sh
ea9bf8db3810d03d0a7395057f3d6e57f7127d87c55deaedc171c255288f5f3cc6fbcc680a5a1b92786cf573875d5dc22521173799fe2639acc97d0715ff905b rust-qemu-linker.sh" 500107e5aff8b34e74b54982ebcd447fc41bc8283956d506561b031a055cb30ec12698047c2604918b4b6d8560fe03db427a63dff2b83c907e8494b7f5233f29 crossdirect.c
2c41410a9ef2dab31403545e55e2464f2ee4e7056ffbcd3bc5810d582311801496b88d55307f17ce6acf766e9c867d30d05f2b0d8d46bf77a5e8f0495d6bc24e rustc.sh
ea9bf8db3810d03d0a7395057f3d6e57f7127d87c55deaedc171c255288f5f3cc6fbcc680a5a1b92786cf573875d5dc22521173799fe2639acc97d0715ff905b rust-qemu-linker.sh
"

View file

@ -0,0 +1,66 @@
#!/bin/sh -e
if [ -n "$CROSSDIRECT_DEBUG" ]; then
set -x
fi
native_version=$(LD_LIBRARY_PATH=/native/lib:/native/usr/lib /native/usr/bin/rustc -V)
target_version=$(/usr/bin/rustc -V)
if [ "$target_version" != "$native_version" ]; then
echo "ERROR: crossdirect: rustc version mismatch between native and build chroot. Please update your chroots and try again." >&2
exit 1
fi
triplet=$(/usr/bin/rustc -vV | sed -n 's/host: //p')
cmd=$1
shift
case "$cmd" in
build|test|run)
;;
*)
echo "WARNING: crossdirect: 'cargo $cmd $*' command not supported, running in QEMU (slow!)" >&2
export PATH="$(echo "$PATH" | sed 's,/native/usr/lib/crossdirect/[^:]*:,,')"
exec /usr/bin/cargo "$cmd" "$@"
;;
esac
target_dir=${CARGO_TARGET_DIR:-target}
target_already_specified=${CARGO_BUILD_TARGET:+1}
if [ -z "$target_specified" ]; then
for arg in "$@"; do
if [ "$arg_target_dir" = 1 ]; then
target_dir=$arg
arg_target_dir=0
fi
case "$arg" in
--target|--target=*)
target_already_specified=1
break
;;
--target-dir)
arg_target_dir=1
;;
--target-dir=*)
target_dir=${arg##--target-dir=}
;;
esac
done
fi
if [ -n "$target_already_specified" ]; then
exec /usr/bin/cargo "$cmd" "$@"
fi
/usr/bin/cargo "$cmd" --target=$triplet "$@"
# copy target/$triplet/{release,debug,...} to target/{release,debug,...}
if [ -d "$target_dir/$triplet" ]; then
for dir in "$target_dir/$triplet"/*/; do
build=$(basename "$dir")
rm -rf "$target_dir/$build"
cp -r "$target_dir/$triplet/$build" "$target_dir/$build"
done
fi

View file

@ -1,48 +1,26 @@
#!/bin/sh -e #!/bin/sh -e
rust_triplet() { if [ -n "$CROSSDIRECT_DEBUG" ]; then
# Find the triplets in Alpine's rust APKBUILD or with: set -x
# pmbootstrap chroot -barmhf --add=rust -- ls /usr/lib/rustlib fi
case "$1" in
x86_64) # return the correct host architecture when cargo requests it
echo "x86_64-alpine-linux-musl" if [ "$*" = "-vV" ]; then
;; exec /usr/bin/rustc -vV
armhf) fi
echo "armv6-alpine-linux-musleabihf"
;; # We expect the right target to be set in the arguments if compiling for the
armv7) # target architecture. Our cargo wrapper passes the right "--target" argument
echo "armv7-alpine-linux-musleabihf" # automatically. If no target is provided, this is probably a macro or a
;; # build script, so it should be compiled for the native architecture.
aarch64) if echo "$*" | grep -qFe "--target"; then
echo "aarch64-alpine-linux-musl" LD_LIBRARY_PATH=/native/lib:/native/usr/lib /native/usr/bin/rustc \
;; -Clinker=/native/usr/lib/crossdirect/rust-qemu-linker \
*) --sysroot=/usr \
echo "ERROR: don't know the rust triple for $1!" >&2 "$@"
exit 1 else
;; PATH=/native/usr/bin:/native/bin LD_LIBRARY_PATH=/native/lib:/native/usr/lib \
esac /native/usr/bin/rustc \
} -Clink-arg=-Wl,-rpath,/native/lib:/native/usr/lib \
"$@"
arch="@ARCH@" # filled in by APKBUILD
if ! LD_LIBRARY_PATH=/native/lib:/native/usr/lib \
/native/usr/bin/rustc \
-Clinker=/native/usr/lib/crossdirect/rust-qemu-linker \
--target=$(rust_triplet "$arch") \
--sysroot=/usr \
"$@"; then
echo "---" >&2
echo "WARNING: crossdirect: cross compiling with rustc failed, trying"\
"again with rustc + qemu" >&2
echo "---" >&2
# Usually the crossdirect approach works; however, when passing
# --extern to rustc with a dynamic library (.so), it fails with an
# error like 'can't find crate for `serde_derive`' (although the crate
# does exist). I think it fails to parse the metadata of the so file
# for some reason. We probably need to adjust rustc's
# librustc_metadata/locator.rs or something (and upstream that
# change!), but I've spent enough time on this already. Let's simply
# fall back to compiling in qemu in the very few cases where this is
# necessary.
/usr/bin/rustc "$@"
fi fi