Right now, there are no prebuilt packages for Rust on ppc-musl and ppc64-musl, and bootstrap on the host machines (ppc or ppc64) cannot be done, because the Rust project doesn't publish the necessary prerequisite binary stage0s.
These targets are, however, supported by Rust, and it is possible to build binary packages of rustc by cross-compiling from a build system with a working Rust installation. After such bootstrap, Rust can be maintained on host systems by using the existing installation as a stage0.
After following this guide, you will have ready-made binary packages of dev-lang/rust that you can install onto ppc and ppc64 systems. All commands are to be entered on the build system (e.g. amd64).
This guide was tested with =dev-lang/rust-1.74.1 on the build system
and =dev-lang/rust-1.75.0-r1 in the ppc and ppc64 cross environments.
Many thanks go to sam, matoro, leio and others for making this all possible.
-
Create cross build environments for powerpc-gentoo-linux-musl and/or powerpc64-gentoo-linux-musl (see instructions on the Gentoo Wiki: https://wiki.gentoo.org/wiki/Cross_build_environment). Set your CFLAGS and USE flags (see below) and don't forget to set the desired binpkg type if the default is not what you want.
-
Ensure that the cross build environments only use “universal” CFLAGS, that is, they don't use
-mcpu=...or-maltivecor similar ppc-specific flags, because the Rust build confuses build and host CFLAGS and will attempt to pass the host-system ones to the build-system-specific gcc. -
Ensure that the cross compilation environments have GCC built without USE=ssp. Stack protector doesn't work on ppc, resulting in build failures in both rust and libunwind. With libunwind, it can be circumvented by setting
-fno-stack-protectorin the host CFLAGS, but rust doesn't honor the flags in all cases and resetting the defaults is the only way. -
(This step is might not be needed?) Setup the mapping from Gentoo
CHOSTs to rust targets. In/etc/portage/env/dev-lang/rust/env.conf:
# Needed to support cross-compilation.
RUST_CROSS_TARGETS=( "PowerPC:powerpc-unknown-linux-musl:powerpc-gentoo-linux-musl" "PowerPC:powerpc64-unknown-linux-musl:powerpc64-gentoo-linux-musl" )
- Patch the Rust ebuild to support musl hosts, probably in
/var/db/repos/gentoo/dev-lang/rust/:
cd /var/db/repos/gentoo/dev-lang/rust/ && patch -p1 <<END
--- a/rust-1.75.0-r1.ebuild 2024-02-10 09:10:50.000000000 +0100
+++ b/rust-1.75.0-r1.ebuild 2024-03-05 16:08:53.102075278 +0100
@@ -502,6 +502,7 @@
if use elibc_musl; then
cat <<- _EOF_ >> "${S}"/config.toml
crt-static = false
+ musl-root = "$($(tc-getCC) -print-sysroot)/usr"
_EOF_
fi
done
END-
Digest the ebuild. (Sorry, I can't help you here. The patched ebuild should of course go into an overlay. Nobody said that following this guide is a good idea.)
-
Patch the rust-toolchain eclass to add support for the musl Rust targets.
cd /var/db/repos/gentoo/eclass/ && patch -p1 <<END
--- a/rust-toolchain.eclass 2024-03-10 16:11:31.671251969 +0100
+++ b/rust-toolchain.eclass 2024-03-05 15:58:41.320325094 +0100
@@ -46,8 +46,10 @@
mipsel*) echo mipsel-unknown-linux-gnu;;
mips*) echo mips-unknown-linux-gnu;;
powerpc64le*) echo powerpc64le-unknown-linux-gnu;;
- powerpc64*) echo powerpc64-unknown-linux-gnu;;
- powerpc*) echo powerpc-unknown-linux-gnu;;
+ powerpc64*gnu) echo powerpc64-unknown-linux-gnu;;
+ powerpc64*musl) echo powerpc64-unknown-linux-musl;;
+ powerpc*gnu) echo powerpc-unknown-linux-gnu;;
+ powerpc*musl) echo powerpc-unknown-linux-musl;;
riscv64*) echo riscv64gc-unknown-linux-gnu;;
s390x*) echo s390x-unknown-linux-gnu;;
x86_64*gnu) echo x86_64-unknown-linux-gnu;;
END- Emerge
dev-lang/rust[rust-src](on the build system) with support for cross-compilation:
USE=rust-src LLVM_TARGETS=PowerPC emerge -av dev-lang/rust- For ppc64, patch Rust's data layout to match LLVM's (already fixed upstream):
in
/usr/powerpc64-gentoo-linux-musl/etc/portage/patches/dev-lang/rust/fix-ppc64-musl-data-layout.patch:
--- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs 2024-03-10 00:04:54.689910480 +0100
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs 2024-03-10 00:05:12.376947849 +0100
@@ -11,7 +11,7 @@
Target {
llvm_target: "powerpc64-unknown-linux-musl".into(),
pointer_width: 64,
- data_layout: "E-m:e-Fi64-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
+ data_layout: "E-m:e-Fn32-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
arch: "powerpc64".into(),
options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..base },
}
- For ppc, patch libunwind to support musl's version of ucontext (see
libunwind/libunwind#709 for patch source):
in
/usr/powerpc-gentoo-linux-musl/etc/portage/patches/sys-libs/libunwind/enable-ppc-musl.patch:
--- a/src/ppc32/Ginit.c 2024-03-03 07:41:35.493657627 +0100
+++ b/src/ppc32/Ginit.c 2024-03-03 07:58:02.930718316 +0100
@@ -49,7 +49,11 @@
if ((unsigned) (reg - UNW_PPC32_R0) < 32)
#if defined(__linux__)
+# if defined(__GLIBC__)
addr = &uc->uc_mcontext.uc_regs->gregs[reg - UNW_PPC32_R0];
+# else
+ addr = &uc->uc_regs->gregs[reg - UNW_PPC32_R0];
+# endif
#elif defined(__FreeBSD__)
addr = &uc->uc_mcontext.mc_gpr[reg - UNW_PPC32_R0];
#endif
@@ -58,8 +62,12 @@
if ( ((unsigned) (reg - UNW_PPC32_F0) < 32) &&
((unsigned) (reg - UNW_PPC32_F0) >= 0) )
#if defined(__linux__)
+# if defined(__GLIBC__)
addr = &uc->uc_mcontext.uc_regs->fpregs.fpregs[reg - UNW_PPC32_F0];
- #elif defined(__FreeBSD__)
+# else
+ addr = &uc->uc_regs->fpregs.fpregs[reg - UNW_PPC32_F0];
+# endif
+#elif defined(__FreeBSD__)
addr = &uc->uc_mcontext.mc_fpreg[reg - UNW_PPC32_F0];
#endif
@@ -85,7 +93,11 @@
return NULL;
}
#if defined(__linux__)
+# if defined(__GLIBC__)
addr = &uc->uc_mcontext.uc_regs->gregs[gregs_idx];
+# else
+ addr = &uc->uc_regs->gregs[gregs_idx];
+# endif
#elif defined(__FreeBSD__)
addr = &uc->uc_mcontext.mc_gpr[gregs_idx];
#endif
--- a/src/ppc32/ucontext_i.h 2024-03-03 07:42:00.685665028 +0100
+++ b/src/ppc32/ucontext_i.h 2024-03-03 08:00:31.287984295 +0100
@@ -44,8 +44,13 @@
//#define MQ_IDX 36
#define LINK_IDX 36
+#if defined(__GLIBC__)
#define _UC_MCONTEXT_GPR(x) ( ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[x] - (void *)&dmy_ctxt) )
#define _UC_MCONTEXT_FPR(x) ( ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[x] - (void *)&dmy_ctxt) )
+#else
+#define _UC_MCONTEXT_GPR(x) ( ((void *)&dmy_ctxt.uc_regs->gregs[x] - (void *)&dmy_ctxt) )
+#define _UC_MCONTEXT_FPR(x) ( ((void *)&dmy_ctxt.uc_regs->fpregs.fpregs[x] - (void *)&dmy_ctxt) )
+#endif
/* These are dummy structures used only for obtaining the offsets of the
various structure members. */
- Compile Rust for the host systems (see matoro's instructions for mips at gentoo/gentoo#35314 for source):
USE='dist system-bootstrap' LLVM_TARGETS='PowerPC X86' powerpc-gentoo-linux-musl-emerge --buildpkg=y -av virtual/rust
USE='dist system-bootstrap' LLVM_TARGETS='PowerPC X86' powerpc64-gentoo-linux-musl-emerge --buildpkg=y -av virtual/rust- If you want to build librsvg for ppc, try version 2.57.2, older ones need manual patching that can't be done through userpatches.
Congratulations, you now have prebuilt Rust packages sitting in
/usr/powerpc{,64}-gentoo-linux-musl/var/cache/binpkgs/.
If this guide doesn't work for you, visit IRC channel #gentoo-powerpc
at Libera.chat and tell me (jonys), I'll try to help.