Skip to content

Baking CMake toolchain files like they were cookies

License

Notifications You must be signed in to change notification settings

Devolutions/CBake

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

60 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CBake

CBake (cross-bake) is a project meant to simplify the creation of cross-compilation environments between major platforms using a combination of clang+llvm and common developer tools.

Prerequisites

Clone this repository anywhere you like, and then set the CBAKE_HOME environment variable to point to it.

Linux sysroot creation

The first step is to create cross-compilation sysroots for major Linux distributions using Docker buildx. This part should be done on a Linux filesystem, so either use a Linux host or WSL2 on Windows. The recipes are nothing more than Dockerfiles installing the packages you want to be part of the target sysroot.

Import-Module $Env:CBAKE_HOME/cbake.psm1 -Force
$distros = Get-ChildItem $(Get-CbakePath 'recipes') | Select-Object -ExpandProperty Name
$distros | ForEach-Object { New-CBakeSysroot -Distro $_ -Arch 'arm64' }
$distros | ForEach-Object { Import-CBakeSysroot -Distro $_ -Arch 'arm64' }

The packaged sysroots are packaged in the "packages" directory, after which they can be reused without having to rebuild them from source. The sysroots are imported under the "sysroots" directory for cross-compilation.

Linux cross-compilation

Once you have built and imported a few sysroots, you can try cross-compiling the Ninja build system executable to all targets using the provided Linux CMake toolchain file. Clone the ninja sources and then move into the directory:

git clone https://github.com/ninja-build/ninja.git
cd "ninja"

In a Linux environment, one can generate makefiles for a given target (Ubuntu 18.04 arm64) using CMake:

export CMAKE_TOOLCHAIN_FILE="$CBAKE_HOME/cmake/linux.toolchain.cmake"
mkdir build-cross && cd build-cross
cmake -DCMAKE_TOOLCHAIN_FILE="$CMAKE_TOOLCHAIN_FILE" -DSYSROOT_NAME="ubuntu-18.04-arm64" ..
make

If the project generation and compilation succeeded, you can then verify that the ninja executable is indeed cross-compiled to ARM64:

$ file ninja
ninja: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, not stripped

Congratulations! You have successfully cross-compiled your first project. The CMAKE_TOOLCHAIN_FILE command-line parameter is not required with CMake 3.21 or later if the CMAKE_TOOLCHAIN_FILE environment variable is set - this can save a lot of typing.

You can go a step further and automate the cross-compilation of to all targets in PowerShell with this more elaborate sample:

New-Item -Path "build" -ItemType 'Directory' -ErrorAction 'SilentlyContinue' | Out-Null
Set-Location "build"
$SysrootNames = Get-ChildItem $(Get-CbakePath 'sysroots') | Select-Object -ExpandProperty Name
foreach ($SysrootName in $SysrootNames) {
    New-Item -Path $SysrootName -ItemType 'Directory' -ErrorAction 'SilentlyContinue' | Out-Null
    Set-Location $SysrootName
    $ToolchainFile = Join-Path $(Get-CBakePath 'cmake') "linux.toolchain.cmake"
    $CMakeOptions = @("-G", "Ninja",
        "-DCMAKE_TOOLCHAIN_FILE=\"$ToolchainFile\"",
        "-DSYSROOT_NAME=$SysrootName",
        "-DCMAKE_BUILD_TYPE=Release")
    Write-Host 'cmake' $CMakeOptions "../.."
    & 'cmake' $CMakeOptions "../.."
    & 'cmake' '--build' '.'
    Set-Location ".."
}
Set-Location ".."