From f329c8f5ac69641787b296819f1977077552c3be Mon Sep 17 00:00:00 2001 From: Oliver Smith Date: Thu, 2 Jan 2020 16:16:20 +0100 Subject: [PATCH] cross/crossdirect: support rust (!845) Use the native rustc cross compiler where possible, and fall back to the qemu rustc if necessary. This should improve speed and reliability. Without this patch, building squeekbox 1.4.0 for aarch64 with the pmbootstrap stack just hangs forever. Related: pmbootstrap#1861 --- cross/crossdirect/APKBUILD | 32 +++++++++++++----- cross/crossdirect/rust-qemu-linker.sh | 8 +++++ cross/crossdirect/rustc.sh | 48 +++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 cross/crossdirect/rust-qemu-linker.sh create mode 100644 cross/crossdirect/rustc.sh diff --git a/cross/crossdirect/APKBUILD b/cross/crossdirect/APKBUILD index 48491777b..734f95ed1 100644 --- a/cross/crossdirect/APKBUILD +++ b/cross/crossdirect/APKBUILD @@ -5,22 +5,25 @@ # # /native/usr/lib/crossdirect/armhf/gcc # -> /native/usr/bin/armv6-alpine-linux-muslgnueabihf-gcc +# /native/usr/lib/crossdirect/armhf/rustc +# -> /native/usr/bin/rustc --target=armv6-alpine-linux-musleabihf ... # # When building packages in the armhf chroot, PATH will get prepended with # "/native/usr/lib/crossdirect/armhf". The end game is of course invoking the # cross compiler from the native chroot, running at native speed, whenever # calling the compiler from the foreign arch chroot. See crossdirect.c for -# implementation details (llvm, fakeroot, rpath). +# implementation details of the C version (llvm, fakeroot, rpath). The rust +# version is implemented as simple shell wrappers. pkgname=crossdirect -pkgver=3 -pkgrel=1 +pkgver=4 +pkgrel=0 pkgdesc="Wrappers to launch native cross compilers in foreign chroots" url="https://postmarketOS.org" arch="all" license="MIT" -options="" -source="crossdirect.c" +options="!check" +source="crossdirect.c rustc.sh rust-qemu-linker.sh" build() { cd "$srcdir" @@ -37,6 +40,9 @@ build() { -Werror \ -DHOSTSPEC="\"$_hostspec\"" \ crossdirect.c + + # rustc + sed "s/@ARCH@/$_arch/g" rustc.sh >rustc-"$_arch" done } @@ -45,22 +51,32 @@ package() { _archs="x86_64 armhf armv7 aarch64" _bins="c++ cc cpp g++ gcc clang clang++" + # Rust: qemu-linker + install -Dm755 "$srcdir/rust-qemu-linker.sh" \ + "$pkgdir/usr/lib/crossdirect/rust-qemu-linker" + # Iterate over architectures for _arch in $_archs; do [ "$_arch" == "$CARCH" ] && continue - # Put arch-specific crossdirect wrapper in arch-specific bin folder + # GCC: put arch-specific crossdirect wrapper in arch-specific + # bin folder _bindir="$pkgdir/usr/lib/crossdirect/$_arch" _hostspec="$(arch_to_hostspec $_arch)" mkdir -p "$_bindir" cd "$_bindir" cp "$srcdir/crossdirect-$_arch" "./" - # Create compiler symlinks + # GCC: create compiler symlinks for _bin in $_bins; do ln -s "crossdirect-$_arch" "$_bin" ln -s "crossdirect-$_arch" "$_hostspec-$_bin" done + + # Rust: arch-specific rustc wrapper + install -Dm755 "$srcdir/rustc-$_arch" "$_bindir/rustc" done } -sha512sums="20b963322820de038257304c1eefa85767b78e242eda7459f06d70a1cfae5540a445aa7d5587024bf4d88a4bee28120ef9f5c2d24a648e71b542b9618318deb2 crossdirect.c" +sha512sums="20b963322820de038257304c1eefa85767b78e242eda7459f06d70a1cfae5540a445aa7d5587024bf4d88a4bee28120ef9f5c2d24a648e71b542b9618318deb2 crossdirect.c +c3492cf2bbf282d22585fb485a8a8950ddbd6e47faff472931072defa9c33ea757b72d455b2d608304c7e40f9c736fac2b9101b65accd48ad896bc7055ef0436 rustc.sh +ea9bf8db3810d03d0a7395057f3d6e57f7127d87c55deaedc171c255288f5f3cc6fbcc680a5a1b92786cf573875d5dc22521173799fe2639acc97d0715ff905b rust-qemu-linker.sh" diff --git a/cross/crossdirect/rust-qemu-linker.sh b/cross/crossdirect/rust-qemu-linker.sh new file mode 100644 index 000000000..7f0136101 --- /dev/null +++ b/cross/crossdirect/rust-qemu-linker.sh @@ -0,0 +1,8 @@ +#!/bin/sh -e +# This wrapper gets called from the native rustc, and runs the qemu gcc for +# linking, with LD_LIBRARY_PATH reset so it does not point to /native anymore. +# It isn't possible to use the native cross compiler's linker with crossdirect +# currently (pmaports#233). + +LD_LIBRARY_PATH=/lib:/usr/lib \ + gcc "$@" diff --git a/cross/crossdirect/rustc.sh b/cross/crossdirect/rustc.sh new file mode 100644 index 000000000..f3249077f --- /dev/null +++ b/cross/crossdirect/rustc.sh @@ -0,0 +1,48 @@ +#!/bin/sh -e + +rust_triplet() { + # Find the triplets in Alpine's rust APKBUILD or with: + # pmbootstrap chroot -barmhf --add=rust -- ls /usr/lib/rustlib + case "$1" in + x86_64) + echo "x86_64-alpine-linux-musl" + ;; + armhf) + echo "arm-unknown-linux-musleabihf" + ;; + armv7) + echo "armv7-unknown-linux-musleabihf" + ;; + aarch64) + echo "aarch64-unknown-linux-musl" + ;; + *) + echo "ERROR: don't know the rust triple for $1!" >&2 + exit 1 + ;; + esac +} + +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