ARM Crosscompiler
« | 09 Apr 2022 | »Wenn man jetzt schon dank MinGW unter Linux seine Windows Programme kompilieren lassen kann, warum soll man denn nicht auch unter X86 PCs die ARM Binaries für den Raspberry PI erstellen lassen können?
Und mit Debian geht das echt einfach … und am Ende klappt das Ganze sogar unter WSL in Windows 10.
Wenn man nach “Raspberry Pi crosscompile” sucht, findet man einige Beiträge, die einen alle Tools im Internet zusammentragen lassen, dann noch alle Raspberry Header und Libs per GIT klonen lassen, um endlich einen Build zu starten.
Zumindest seit Debian 9 (oder Ubuntu 18.04) geht das viel einfacher:
Debian: crossbuild-essential-armhf
Die Paketinstallation
apt install crossbuild-essential-armhf -y
legt den GCC ARM
Compiler und die meisten notwendigen Libs in
/usr/arm-linux-gnueabihf
ab.
Und mit einer .cmake
Toolchain-Datei leitet man einfach die Aufrufe
zum ARM Compiler um.
CMake: Toolchain Datei
Meine CMake Toolchain-Datei
arm-linux-gnueabihf.cmake
sieht in etwa so aus:
1set(CMAKE_SYSTEM_NAME "Linux") 2set(CMAKE_SYSTEM_PROCESSOR "arm") 3set(TOOLCHAIN_PREFIX "arm-linux-gnueabihf") 4 5set(CMAKE_C_COMPILER "${TOOLCHAIN_PREFIX}-gcc") 6set(CMAKE_CXX_COMPILER "${TOOLCHAIN_PREFIX}-g++") 7 8set(CMAKE_CROSSCOMPILING TRUE) 9set(THREADS_PTHREAD_ARG "2" CACHE STRING "THREADS_PTHREAD_ARG" FORCE) 10 11set(CMAKE_FIND_ROOT_PATH "/usr/${TOOLCHAIN_PREFIX}") 12 13set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 14set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 15set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
Ich brauchte den Eintrag THREADS_PTHREAD_ARG
, da ansonsten der Fehler:
CMake Error: TRY_RUN() invoked in cross-compiling mode, please set the following cache variables appropriately: THREADS_PTHREAD_ARG (advanced)
auftritt.
Schon kann man CMake
mit dem Kommando:
1cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/arm-linux-gnueabihf.cmake /path/to/sources
ausführen und erhält am Ende ARMv7
Binaries.
Diese wurden zu meinem alten Raspberry Pi 2B
kopiert und dieser konnte
sie sofort und ohne Probleme ausführen.
Andere Plattformen
Nachdem der Raspberry Pi Zero
und 1
den ARMv6
Befehlssatz nutzen, der
2
er den ARMv7
und die späteren ARMv8
, macht es Sinn, diese Info der
Toolchain mitzugeben, damit optimierter Code für die gewünschte Plattform
rauskommt.
Eine tolle Übersicht hat fm4dd
unter github.com
eingestellt.
Mit ein paar Zusatzzeilen
1#set(RPI_FLAGS "-mcpu=arm1176jzf-s -mfloat-abi=hard -mfpu=vfp" CACHE STRING "RPi Zero/1") 2set(RPI_FLAGS "-mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4" CACHE STRING "RPi 2") 3#set(RPI_FLAGS "-mcpu=cortex-a53 -mfloat-abi=hard -mfpu=neon-fp-armv8 -mneon-for-64bits" CACHE STRING "RPi 3") 4#set(RPI_FLAGS "-mcpu=cortex-a72 -mfloat-abi=hard -mfpu=neon-fp-armv8 -mneon-for-64bits" CACHE STRING "RPi 4") 5 6set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${RPI_FLAGS}" CACHE STRING "C CPU Flags") 7set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${RPI_FLAGS}" CACHE STRING "C++ CPU Flags")
lässt sich der generierte Code auf den gewünschten Raspberry Pi
anpassen.
Leider ist der ARMv6
Befehlssatz des RPi Zero
und 1
nicht mehr in
den Standardcompilern enthalten und man bekommt Fehler wie:
sorry, unimplemented: Thumb-1 hard-float VFP ABI
Aber auch hier hat ein pfiffiger User eine Lösung mit einer angepassten Toolchain eingestellt: github.com/Pro/raspi-toolchain
Fazit
Mit WSL
und Ubuntu oder Debian kann ich nun also GATE Builds für die ARM
Plattform bauen lassen und während mein Raspberry 4 oder 2 schon ganz schön
lange rechnen müsste, schafft das mein Intel i5 in unter einer Minute.
Vermutlich enthalten ältere Distros von vor 2015 ebenfalls noch den ARMv6
Befehlssatz, aber mir reicht der ARMv7
Teil vollkommen für Tests aus.
Sollte ich also wirklich mal einen RPi Zero
Build brauchen, werde ich die
alternative Toolchain bemühen müssen, oder direkt am R-PI bauen lassen.
Jedenfalls wieder mal “eine coole Sache”, dass ich nun eine weitere Plattform problemfrei abhaken kann.
Es gibt zwar meines Wissens auch eine native Windows-Toolchain für ARM-Linux,
doch wozu die Mühe machen, wenn es mit WSL
so unkompliziert läuft.