# Contributing ## Getting started ## How to add a new image ? (With crosstool-ng) In this part, we will see how to add a new image, we will take example with `linux-arm64` for a raspberry pi 4, with [crosstool-ng](https://github.com/crosstool-ng/crosstool-ng). ### Build and config crosstool-ng To start, you need to download the source code of crosstool-ng: ```bash git clone --recurse-submodules --remote-submodules https://github.com/crosstool-ng/crosstool-ng.git ``` Go to crosstool-ng folder: ```bash cd crosstool-ng ``` Change git branch: ```bash git checkout crosstool-ng-1.25.0 ``` Once in the **crosstool-ng** folder, you must first run the **bootstrap** script: ```bash ./bootstrap ``` Then run the **configure** script: *Note: ***--enable-local*** Do a portable install of crosstool-ng.*: ```bash ./configure --enable-local ``` Finally, launch the building of crosstool-ng: ```bash make -j$(nproc) ``` Once the crosstool-ng build is complete, you can run this command to test crosstool-ng: ```bash ./ct-ng --version ``` Before starting the configuration of the toolchains, i recommend you to use one of the examples from crosstool-ng and then make your changes, the command to display the examples: ```bash ./ct-ng list-samples ``` We will take the example of **aarch64-rpi4-linux-gnu**, a **.config** file will be created: ```bash ./ct-ng aarch64-rpi4-linux-gnu ``` We will configure the toolchains according to our needs: ```bash ./ct-ng menuconfig ``` Once the modifications are made, we will display the name of the toolchains, it will be useful later: ```bash ./ct-ng show-tuple ``` ### Configuring docker image You must create a file with the **same** name of the docker image (**linux-arm64**). Copy the **.config** of crosstool-ng to this file (**linux-arm64**) and rename it to **crosstool-ng.config**. You need to create a file named **Toolchain.cmake** in **linux-arm64**. Copy text to **Toolchain.cmake** file: ```cmake set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_VERSION 1) set(CMAKE_SYSTEM_PROCESSOR ARM64) set(cross_triple $ENV{CROSS_TRIPLE}) set(cross_root $ENV{CROSS_ROOT}) set(CMAKE_C_COMPILER $ENV{CC}) set(CMAKE_CXX_COMPILER $ENV{CXX}) set(CMAKE_Fortran_COMPILER $ENV{FC}) set(CMAKE_CXX_FLAGS "-I ${cross_root}/include/") set(CMAKE_FIND_ROOT_PATH ${cross_root} ${cross_root}/${cross_triple}) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) set(CMAKE_SYSROOT ${cross_root}/${cross_triple}/sysroot) set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/qemu-arm64) ``` Then ou must change these lines according to the targeted architecture, here **ARM64**: ```cmake set(CMAKE_SYSTEM_PROCESSOR ARM64) set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/qemu-arm64) ``` Then you must create a file named **Dockerfile.in** in the image folder (**linux-arm64**). Copy text to **Dockerfile.in** file: ```docker FROM dockcross/base:latest LABEL maintainer="Matt McCormick matt.mccormick@kitware.com" # This is for 64-bit ARM Linux machine # Crosstool-ng crosstool-ng-1.25.0 2022-05-13 ENV CT_VERSION crosstool-ng-1.25.0 #include "common.crosstool" # The cross-compiling emulator RUN apt-get update \ && apt-get install -y \ qemu-user \ qemu-user-static \ && apt-get clean --yes # The CROSS_TRIPLE is a configured alias of the "aarch64-unknown-linux-gnu" target. ENV CROSS_TRIPLE aarch64-unknown-linux-gnu ENV CROSS_ROOT ${XCC_PREFIX}/${CROSS_TRIPLE} ENV AS=${CROSS_ROOT}/bin/${CROSS_TRIPLE}-as \ AR=${CROSS_ROOT}/bin/${CROSS_TRIPLE}-ar \ CC=${CROSS_ROOT}/bin/${CROSS_TRIPLE}-gcc \ CPP=${CROSS_ROOT}/bin/${CROSS_TRIPLE}-cpp \ CXX=${CROSS_ROOT}/bin/${CROSS_TRIPLE}-g++ \ LD=${CROSS_ROOT}/bin/${CROSS_TRIPLE}-ld \ FC=${CROSS_ROOT}/bin/${CROSS_TRIPLE}-gfortran ENV QEMU_LD_PREFIX "${CROSS_ROOT}/${CROSS_TRIPLE}/sysroot" ENV QEMU_SET_ENV "LD_LIBRARY_PATH=${CROSS_ROOT}/lib:${QEMU_LD_PREFIX}" COPY Toolchain.cmake ${CROSS_ROOT}/ ENV CMAKE_TOOLCHAIN_FILE ${CROSS_ROOT}/Toolchain.cmake ENV PKG_CONFIG_PATH /usr/lib/aarch64-linux-gnu/pkgconfig # Linux kernel cross compilation variables ENV PATH ${PATH}:${CROSS_ROOT}/bin ENV CROSS_COMPILE ${CROSS_TRIPLE}- ENV ARCH arm64 #include "common.label-and-env" ``` Then ou must change these lines according to the targeted architecture. Here you have to change the value according to the name of the toolchain (./ct-ng show-tuple): ```docker ENV CROSS_TRIPLE aarch64-unknown-linux-gnu ``` These lines also need to be changed: ```docker LABEL maintainer="Matt McCormick matt.mccormick@kitware.com" ENV PKG_CONFIG_PATH /usr/lib/aarch64-linux-gnu/pkgconfig ENV ARCH arm64 ``` Once this part is finished, there must be 3 files in the **linux-arm64** folder: - **crosstool-ng.config**, the configuration of the toolchain/crosstool-ng. - **Dockerfile.in**, the docker file. - **Toolchain.cmake**, the CMake file for the toolchains. ### Makefile and CI For this last part, we will see how to add the image to the [Makefile](Makefile) and to a github action. You need to add the image/folder name (**linux-arm64**) to the **STANDARD_IMAGES** variable in the [Makefile](Makefile): ```make # These images are built using the "build implicit rule" STANDARD_IMAGES = android-arm android-arm64 android-x86 android-x86_64 \ linux-x86 linux-x64 linux-x64-clang linux-arm64 linux-arm64-musl linux-arm64-full \ linux-armv5 linux-armv5-musl linux-armv5-uclibc linux-m68k-uclibc linux-s390x linux-x64-tinycc \ linux-armv6 linux-armv6-lts linux-armv6-musl linux-arm64-lts \ linux-armv7l-musl linux-armv7 linux-armv7a linux-armv7-lts linux-x86_64-full \ linux-mips linux-ppc64le linux-riscv64 linux-riscv32 linux-xtensa-uclibc \ web-wasi \ windows-static-x86 windows-static-x64 windows-static-x64-posix windows-armv7 \ windows-shared-x86 windows-shared-x64 windows-shared-x64-posix windows-arm64 ``` You need to add the image/folder name (**linux-arm64**) to the **GEN_IMAGES** variable in the [Makefile](Makefile): ```make # Generated Dockerfiles. GEN_IMAGES = android-arm android-arm64 \ linux-x86 linux-x64 linux-x64-clang linux-arm64 linux-arm64-musl linux-arm64-full \ manylinux2014-x64 manylinux2014-x86 \ manylinux2014-aarch64 linux-arm64-lts \ web-wasm web-wasi linux-mips windows-arm64 windows-armv7 \ windows-static-x86 windows-static-x64 windows-static-x64-posix \ windows-shared-x86 windows-shared-x64 windows-shared-x64-posix \ linux-armv7 linux-armv7a linux-armv7l-musl linux-armv7-lts linux-x86_64-full \ linux-armv6 linux-armv6-lts linux-armv6-musl \ linux-armv5 linux-armv5-musl linux-armv5-uclibc linux-ppc64le linux-s390x \ linux-riscv64 linux-riscv32 linux-m68k-uclibc linux-x64-tinycc linux-xtensa-uclibc ``` To finish, you have to add to [Github Action](.github/workflows/main.yml) the image/folder name: ```yml # Linux arm64/armv8 images - { image: "linux-arm64", stockfish: "yes", stockfish_arg: "ARCH=armv8", ninja: "yes", ninja_arg: "", openssl: "yes", openssl_arg: "linux-aarch64", C: "yes", C_arg: "", C-Plus-Plus: "yes", C-Plus-Plus_arg: "", fmt: "yes", fmt_arg: "", cpython: "yes", cpython_arg: "--host=aarch64-unknown-linux-gnu --target=aarch64-unknown-linux-gnu", } ``` You can disable and enable the build of certain tests which can cause problems with certain CPU architectures (eg. OpenSSL with Risc-V...).