crossdev
crossdev is a set of bash scripts that utilize emerge to provide a system integrated cross-compilation capability.
A Gentoo host machine's toolchain is leveraged by compiling for the specified target; by overriding several environment variables.[1][2]
Installation
Emerge
root #
emerge --ask sys-devel/crossdev
Crossdev overlay
Improperly using crossdev may "pollute" ebuild repositories: crossdev operates by adding packages to an ebuild repository, so care must be taken to ensure crossdev adds packages to a separate repository. Follow one of the creation methods below to create a separate repository for crossdev.
eselect creation
To use eselect-repository to create the repository, first install the package.
root #
emerge --ask app-eselect/eselect-repository
Then, create the repository with:
root #
eselect repository create crossdev
Manual creation
To manually create a crossdev
repository:
root #
mkdir -p /var/db/repos/crossdev/{profiles,metadata}
root #
echo 'crossdev' > /var/db/repos/crossdev/profiles/repo_name
root #
echo 'masters = gentoo' > /var/db/repos/crossdev/metadata/layout.conf
root #
chown -R portage:portage /var/db/repos/crossdev
If the Gentoo ebuild repository is synchronized using Git, or any other method with Manifest files that do not include checksums for ebuilds, prevent "masked by: corruption" errors with:
/var/db/repos/crossdev/metadata/layout.conf
masters = gentoo
thin-manifests = true
Instruct Portage, and subsequently crossdev, to use the new ebuild repository by enabling it:
/etc/portage/repos.conf/crossdev.conf
[crossdev]
location = /var/db/repos/crossdev
priority = 10
masters = gentoo
auto-sync = no
Repository search order
In order of precedence, crossdev will make use of a Portage repository specified by:
- The command-line option:
--ov-output
(-oO
) ${CROSSDEV_OVERLAY}
- Repository with name
cross-${CTARGET}
- Repository with name
crossdev
Usage
The
-S
option (for stable) should not be used on arches with no stable keywords or a mixed (unstable, inconsistent) profile, e.g. mips or riscv.Invocation
user $
crossdev --help
To see the supported architectures, C libraries, and special targets:
user $
crossdev --target help
To build a cross toolchain, specify the target with the --target
flag, such as:
root #
crossdev --target aarch64-unknown-linux-gnu
To use the host LLVM toolchain as a cross compiler instead of compiling a target specific GCC toolchain, use the --llvm
flag.
root #
crossdev --llvm --target aarch64-gentoo-linux-musl
It is currently not possible to compile glibc with LLVM/Clang, therefore any -gnu triplet will fail with the
--llvm
flag. There are also several CPU architectures not fully supported by the compiler-rt builtins library, which is needed for LLVM crossdev.C++ and unwinding is currently not supported by LLVM crossdev, but it is planned for the near future. It is therefore recommended to set
USE="-cxx"
in the meantime.Build packages with crossdev
To cross compile packages it is now possible to use emerge-$CHOST, using an aarch64 glibc cross compiler it would look like emerge-aarch64-unknown-linux-gnu then use the Portage's commands as normal.
Set profiles
Profiles can be set like on normal system by doing the following.
First, list the available profiles:
root #
PORTAGE_CONFIGROOT=/usr/aarch64-unknown-linux-gnu eselect profile list
Then pick the required profile for the system needs.
root #
PORTAGE_CONFIGROOT=/usr/aarch64-unknown-linux-gnu eselect profile set default/linux/arm64/23.0
Setting emerge options
crossdev allows the same configuration as /etc/portage by editing make.conf, package.use, package.accept_keywords etc in the /usr/aarch64-unknown-linux-gnu/etc/portage directory. See Portage documentation for more information.
Set up the base system
Crossdev sets up only the cross compiler and runtime. By itself, it doesn't install the base system or any libraries, which are
There are two ways:
- Manual build of the base system. It works well for GCC-based environments, but has no guarantee to work with LLVM-based ones.
- Using a stage3 tarball.
Manual build
Manual build consists of installation of glibc and @system without recording them in @world.
root #
USE=build aarch64-unknown-linux-gnu-emerge -v1 baselayout
root #
aarch64-unknown-linux-gnu-emerge -v1 sys-libs/glibc
root #
aarch64-unknown-linux-gnu-emerge -v1 @system
Stage3 tarball
First, download a desired stage3 archive, which matches your architecture and environment. For aarch64-unknown-linux-musl, that would be:
root #
wget https://gentoo.osuosl.org/releases/arm64/autobuilds/current-stage3-arm64-musl-llvm/stage3-arm64-musl-llvm-XXXXXXXXXXXXXXXX.tar.xz -O stage3-arm64-musl-llvm-latest.tar.xz
Then unpack it into the target root directory:
root #
tar -xJpf stage3-arm64-musl-llvm-latest.tar.xz -C /usr/aarch64-unknown-linux-musl --exclude=dev --skip-old-files
Emerge a single package
To emerge a single package then just run:
root #
emerge-aarch64-unknown-linux-gnu --ask app-editors/nano
Replacing the package with the one required for the system.
Emerge all the packages in system set
To emerge all packages in @system then run:
root #
emerge-aarch64-unknown-linux-gnu --ask --verbose --oneshot @system
Binary packages
By default crossdev will create packages in /usr/aarch64-unknown-linux-gnu/var/cache/binpkgs which can be used to set up a Binary Host to install packages on a much weaker system which would take days, if not weeks otherwise.
User Patches
Because crossdev makes the ebuilds via symlinks, the default patch directory becomes /etc/portage/patches/cross-${CTARGET}/${PN}/. For example, to apply foobar.patch to sys-libs/glibc on the target system, the patch file should be placed in in /etc/portage/patches/cross-aarch64-unknown-linux-gnu/glibc/foobar.patch.
17.x to 23.0 migration
Users that have cross toolchain profiles created for 17.x profiles are recommend to delete the cross compiler and then recreate them again using a 23.0 profile to prevent multiple issues and assure the correct USE flags are set.
Please follow below for removal steps then see Crossdev#Usage on how to create them again.
Toolchains for architectures Gentoo doesn't officially support
Sometimes a user needs to build a cross compiler for a CPU arch which isn't supported by Gentoo however the toolchain does.
Visit packages.gentoo.org and find the current versions for the packages sys-devel/binutils, sys-devel/gcc and sys-libs/glibc or sys-libs/musl.
GCC | 14.1.1_p20240622 |
Binutils | 2.42-r2 |
Glibc | 2.39-r9 |
With these version we can force crossdev to use the required versions in this usage case with the following:
root #
ACCEPT_KEYWORDS="**" crossdev -s4 --binutils 2.42-r2 --libc 2.39-r9 --gcc 14.1.1_p20240622 sh4-unknown-linux-gnu
ACCEPT_KEYWORDS="**" Tells portage to temporailty accept any architeure keyword.
--binutils Explicitly set the binutils version
--gcc Explicitly set the GCC version
--libc Explicitly set the Glibc or musl version (crossdev selects the correct libc based on the triple provided.)
sh4-unknown-linux-gnu Triple required for cross compiler.
This will build a very basic cross compiler without profile support.
Removal
Specifying the same machine-vendor-kernel-operating system as the host utils during removal could result in breakages that are irrecoverable without a proper backup method!
To remove a LLVM/Clang crossdev target you need to explicitly pass
--llvm
.Optionally, please see make.conf for setting up regular backups via binpkg & Portage's built-in features!
To remove a crossdev-generated toolchain, set the --clean
flag before the --target
flag using the target tuple to remove, for example:
root #
crossdev --clean --target arm-none-eabi
* Uninstalling target 'arm-none-eabi' ... *** unmerging cross-arm-none-eabi/newlib-4.1.0-r1 *** unmerging cross-arm-none-eabi/binutils-2.37_p1-r1 *** unmerging cross-arm-none-eabi/gcc-11.2.1_p20211127 * gcc-config: Could not locate profile # ! Cleaning up masquerade for ccache ... removed 'arm-none-eabi-gcc' removed 'arm-none-eabi-gcc-11.2.1' * Removing last cross-compiler instance. Deleting dangling symlinks. rm: cannot remove '/usr/arm-none-eabi/usr': Is a directory /usr/arm-none-eabi: directory still exists; remove recursively? [y/N] y
Unmerge
root #
emerge --ask --depclean --verbose sys-devel/crossdev
Clang
To use Clang as a cross-compiler with `crossdev`, first ensure that `sys-devel/llvm` is installed with support for the necessary targets (e.g., `arm64`, `riscv64`):
emerge --ask sys-devel/llvm
Additionally, create a dedicated overlay for cross-compilation if it does not already exist:
eselect repository create crossdev
Note: `sys-devel/clang-crossdev-wrappers` is not meant to be installed directly. Instead, use `crossdev` to generate a toolchain.
To configure `crossdev` with Clang as the cross-compiler, use the `--llvm` flag when setting up a toolchain:
#!/bin/bash
CROSSDEV_OVERLAY=/usr/local/portage \
CROSSDEV_TARGET=aarch64-unknown-linux-gnu \
CBUILD=x86_64-pc-linux-gnu \
CC=clang \
CXX=clang++ \
crossdev --llvm --stable aarch64-unknown-linux-gnu
Replace `aarch64-unknown-linux-gnu` with your desired target architecture.
See also
- ARM — compiling code for an ARM processor, taking advantage of its FPU.
- Cross build environment — provides instructions on creating a cross build environment using crossdev.
- Catalyst — a tool to build stage files and live-images for Gentoo
- Creating a cross-compiler (Embedded Handbook)
- Joshua Kinard (kumba) - original crossdev author.
References
- ↑ Gentoo Gitweb: "Crossdev Script"
- ↑ crossdev was originally written by: Joshua Kinard (kumba)