Bootstrapping Rust via stage file
This article covers bootstraping Rust for a LLVM profile using a (non-LLVM) Stage 3 file.
Precondition
On LLVM-based systems using musl, packages may break if dev-lang/rust-bin is the active Rust installation, and it is therefore masked (bug #912154). Emerge dev-lang/rust requires a Rust installation, which leads to a circular dependency that cannot be resolved.
Verify that the profile is a musl/llvm profile:
root #
eselect profile list
Available profile symlink targets: [46] default/linux/arm64/23.0/musl/llvm (exp) *
Setting up a Build-Environment
Getting a Stage File
Choose a Stage 3 file that matches the architecture and profile, but does not use LLVM: e.g.
default/linux/arm64/23.0/musl/llvm
->default/linux/arm64/23.0/musl
default/linux/amd64/23.0/musl/llvm
->default/linux/amd64/23.0/musl
- ...
Before downloading the stage file, the current directory should be set to the location where the environment shall be set up:
user $
mkdir ~/gentoo-rootfs
user $
cd ~/gentoo-rootfs
Once downloaded, extract the stage file:
user $
fakeroot tar xpvf stage3-*.tar.xz --xattrs-include='*.*' --numeric-owner
Entering the Environment
One thing still remains to be done before entering the new environment and that is copying over the DNS information in /etc/resolv.conf.
user $
cp --dereference /etc/resolv.conf ./etc
Option 1: via Chroot
As described in the Chrooting section in the handbook.
Option 2: via Podman
user $
podman run -it --rootfs $(pwd) /bin/bash
Configuring Portage
Install a snapshot of the Gentoo ebuild repository
root #
emerge-webrsync
Veryfing the Profile
Verify that the profile is a musl, non-llvm profile:
root #
eselect profile list
Available profile symlink targets: [45] default/linux/arm64/23.0/musl (dev) *
Building Rust
Building Rust with stdlibc++
First a working setup with rust and llvm is built.
root #
emerge --ask llvm-core/clang llvm-core/llvm llvm-runtimes/compiler-rt llvm-runtimes/libunwind llvm-core/lld dev-lang/rust
Building Rust with libc++
Then switch the toolchain to default-libcxx
.
Select the corresponding llvm profile
root #
eselect profile list
[45] default/linux/arm64/23.0/musl (dev) * [46] default/linux/arm64/23.0/musl/llvm (exp)
root #
profile set 46
!!! Warning: Profile default/linux/arm64/23.0/musl/llvm is experimental
Emerge llvm-core/clang-runtime
The USE-flags default-compiler-rt
, default-libcxx
, default-lld
and llvm-libunwind
are set by the profile.
root #
emerge --ask llvm-core/clang-runtime
[ebuild R ] llvm-runtimes/libunwind USE="static-libs*" [ebuild N ] llvm-runtimes/libcxxabi USE="(clang) static-libs -test -verify-sig" [ebuild N ] llvm-runtimes/libcxx USE="(clang) (libcxxabi) static-libs -test -verify-sig" [ebuild R ] llvm-core/clang-runtime USE="(default-compiler-rt*) (default-libcxx*) (default-lld*) libcxx* (llvm-libunwind*) -sanitize*"
If there is no profile or switching profile is not possible, follow Bootstrapping the LLVM toolchain
Confirm working default-libcxx
user $
cat > test.cpp <<'EOF'#include <iostream>
int main() { std::cout << "LLVM profile OK\n"; }
EOF
user $
clang++ test.cpp
user $
ldd ./a.out | grep -E 'libc\+\+|libstdc\+\+'
libc++.so.1 => /lib/libc++.so.1 (0xffff95926000) libc++abi.so.1 => /lib/libc++abi.so.1 (0xffff958d5000)
If you see
libstdc++.so.6
the toolchain is still using stdlibc++Rebuild the toolchain
root #
emerge --ask llvm-core/clang llvm-core/llvm llvm-runtimes/libcxx llvm-runtimes/libcxxabi llvm-runtimes/compiler-rt llvm-runtimes/compiler-rt-sanitizers llvm-runtimes/libunwind llvm-core/lld
Rebuild Rust & create a binary package
Emerge Rust with the new toolchain and USE-flags and build a binary package:
root #
emerge --ask --buildpkg dev-lang/rust
[ebuild R ] dev-lang/rust USE="(llvm-libunwind*)"
Installing Rust
Leave the build environment
root #
exit
Backup the hosts package cache
root #
[ -d /var/cache/binpkgs ] && mv /var/cache/binpkgs /var/cache/binpkgs-tmp
Copy the build environment package cache to the host
root #
cp -r ./var/cache/binpkgs /var/cache/binpkgs
Install Rust
root #
emerge --ask --usepkgonly dev-lang/rust
Remove the cache
root #
rm -r /var/cache/binpkgs
Restore the hosts package cache
root #
[ -d /var/cache/binpkgs-tmp ] && mv /var/cache/binpkgs-tmp /var/cache/binpkgs
Optional: Rebuilding with custom USE-flags
Once installed, rebuild Rust with the desired USE-flags.
See Also
- Rust — a general-purpose, multi-paradigm, compiled, programming language.
- LLVM — a collection of modular and reusable compiler and toolchain technologies
- Musl — a standard C library implementation that strives to be lightweight and correct in the sense of standards
- Bootstrapping_Rust_via_cross_compilation — covers using crossdev to bootstrap Rust for a specific architecture