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