Testing Other Targets

It’s often possible to test targets other than your host tuple.

Windows and macOS hosts can test Linux hosts using Lima (macOS/Linux) or WSL2 (Windows). While Lima supports other instruction set architectures, WSL2 users must rely on QEMU.

Additionally, Ferrocene supports testing a number of targets which are not supported by upstream. When testing locally, special tools or configuration may be required.

In general, any “bare-metal” target listed in Compilation targets overview requires special setup inside a Linux based environment, native or one supporting nested virtualization (such as Lima or WSL2.)

Host Setup

Unless otherwise noted, all bare-metal targets are tested via QEMU on a Linux host. On macOS, a tool like Lima or Docker must be used. On Windows, WSL2 must be used.

x86-64 Linux (glibc) (x86_64-unknown-linux-gnu)

You need to have all the normal prerequisites from Setting up a local development environment installed, as well as a few extras:

sudo apt install qemu-user-static binfmt-support

Apple Silicon macOS (aarch64-apple-darwin)

Install Lima, if you don’t have it:

brew install lima

You can create a guest with the following:

cat <<- EOF | limactl create --name=ferrocene
    minimumLimaVersion: "1.0.0"
    images:
    - location: "https://cloud-images.ubuntu.com/releases/24.10/release-20241212/ubuntu-24.10-server-cloudimg-arm64.img"
        arch: "aarch64"
        digest: "sha256:fb39312ffd2b47b97eaef6ff197912eaa3e0a215eb3eecfbf2a24acd96ee1125"
    - location: "https://cloud-images.ubuntu.com/releases/24.10/release/ubuntu-24.10-server-cloudimg-arm64.img"
        arch: "aarch64"
    mounts:
    - location: "~"
    - location: "/tmp/lima"
    writable: true
    ssh:
    forwardAgent: true
    cpus: 8
    memory: "8GiB"
    mountTypesUnsupported: ["9p"]
EOF

Start the guest:

limactl start ferrocene

Shell into the guest:

limactl shell ferrocene

You can also point Visual Studio Code’s SSH extension at it using these steps.

Finally, ensure the guest is configured according to Setting up a local development environment as well as the x86-64 Linux (glibc) (x86_64-unknown-linux-gnu) on this page.

Warning

It is recommended to not share build/ directories between multiple hosts, both for performance and correctness. To avoid this, you should cd ~ in the guest and clone a new copy of the Ferrocene repository into the dedicated guest storage.

Please ensure you always work from the guest-local repository.

x86-64 Windows (x86_64-pc-windows-msvc)

Setup WSL2, if you don’t have it:

wsl --install --distribution Ubuntu-24.04

Ensure `nestedVirtualization is set in the guest /etc/wsl.conf, here is an example configuration:

[user]
default=ana

[boot]
systemd=true

[wsl2]
nestedVirtualization=true

If you changed your configuration, make sure to restart the environment with wsl --shutdown.

Shell into the guest:

wsl

You can also point Visual Studio Code WSL extension at it.

Finally, ensure the guest is configured according to Setting up a local development environment as well as the x86-64 Linux (glibc) (x86_64-unknown-linux-gnu) on this page.

Warning

It is recommended to not share build/ directories between multiple hosts, both for performance and correctness. To avoid this, you should cd ~ in the guest and clone a new copy of the Ferrocene repository into the dedicated guest storage.

Please ensure you always work from the guest-local repository.

Target Procedures

Currently bare metal targets have a similar procedure for testing.

Note

Currently, these targets use our secret sauce. This will eventually be an open source component, but for now, it’s our little bit of arcane magic.

Armv8-A bare-metal (aarch64-unknown-none)

Warning

In a Armv8-A Linux (glibc) environment – such as a guest on Apple Silicon macOS or x86-64 Windows – you must skip to the final step, running the tests using:

export QEMU_CPU=cortex-a53
./x test --stage 1 --target aarch64-unknown-ferrocenecoretest library/core

Incorrectly configuring your Armv8-A Linux (glibc) environment using the other steps will damage to the environment and result in “Too many levels of symbolic links” errors.

Install the necessary packages:

sudo apt install g++-aarch64-linux-gnu gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu libc6-dev-arm64-cross qemu-system-aarch64

If you don’t already have a /usr/share/binfmts/qemu-aarch64 file, create one:

package qemu-aarch64
interpreter /usr/bin/qemu-aarch64-static
magic \x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00
mask \xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff
credentials no
preserve no
fix_binary no

Then make sure it’s imported:

sudo update-binfmts --import qemu-aarch64

In order to avoid build errors such as “--fix-cortex-a53-843419 is only supported on AArch64 targets,” ensure the following is in your config.toml:

[target.aarch64-unknown-ferrocenecoretest]
cc = "aarch64-linux-gnu-gcc"
profiler = false

After, you can run the tests:

export QEMU_CPU=cortex-a53
./x test --stage 1 --target aarch64-unknown-ferrocenecoretest library/core

Armv7E-M bare-metal (hard-float) (thumbv7em-none-eabihf) & Armv7E-M bare-metal (soft-float) (thumbv7em-none-eabi)

Install the necessary packages:

sudo apt install gcc-arm-none-eabi qemu-system-arm

If you don’t already have a /usr/share/binfmts/qemu-arm file, create one:

package qemu-arm
interpreter /usr/bin/qemu-arm-static
magic \x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00
mask \xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff
credentials no
preserve no
fix_binary no

Then make sure it’s imported:

sudo update-binfmts --import qemu-arm

Now set the target:

export TARGET="thumbv7em-ferrocenecoretest-eabihf"
# or
export TARGET="thumbv7em-ferrocenecoretest-eabi"

In order to test this target, the build process will acquire a copy of our secret sauce from AWS. Ensure you’re authenticated, following the section in Setting up a local development environment if your environment is not yet set up.

Ensure the following is in your config.toml:

[target.thumbv7em-ferrocenecoretest-eabi]
cc = 'arm-none-eabi-gcc'
profiler = false

[target.thumbv7em-ferrocenecoretest-eabihf]
cc = 'arm-none-eabi-gcc'
profiler = false

You can now run the tests:

export QEMU_CPU=cortex-m4
./x test --stage 1 --target $TARGET library/core