Cross compiling JUCE 6.1.6 results in juceaide being compiled with target toolchain

Hi !

I’m having trouble x-compiling a JUCE plugin to raspberry pi 4 B. I’m using JUCE 6.1.6 and I followed these steps.

The problem seems to be that during cmake ../ -DCMAKE_BUILD_TYPE=Release, juceaide is compiled using the x-compiler (file JUCE/tools/extras/Build/juceaide/juceaide_artefacts/Debug/juceaide reveals an executable compiled for aarch64).
During the plugin compilation, the juceaide executable is called and results in an error since it’s not built for the host arch.

$ AR=aarch64-elk-linux-ar make -j `nproc` CONFIG=Release CFLAGS="-Wno-psabi" TARGET_ARCH="-mcpu=cortex-a72 -mtune=cortex-a72"
[  3%] Generating HelloPlugin_artefacts/JuceLibraryCode/JuceHeader.h
JUCE/tools/extras/Build/juceaide/juceaide_artefacts/Debug/juceaide: JUCE/tools/extras/Build/juceaide/juceaide_artefacts/Debug/juceaide: cannot execute binary file
make[2]: *** [CMakeFiles/HelloPlugin.dir/build.make:81: HelloPlugin_artefacts/JuceLibraryCode/JuceHeader.h] Error 126
make[1]: *** [CMakeFiles/Makefile2:228: CMakeFiles/HelloPlugin.dir/all] Error 2
make: *** [Makefile:149: all] Error 2

I tried sourcing the x-compile environment after the call to cmake but this results in an arm64 plugin since the generated makefile then uses the host native toolchain.

What am I missing to have juceaide compiled in the host architecture and the VST compiled in the target architecture ?

Cheers,
Val.

I found a very dirty workaround by copying the juceaide executable from the host build subdirectory to replace the one built in the x-build subdirectory. Still, it’s a bit weird that following your instructions, it gets built in the target arch…

Another thing I could try would be to entirely disable juceaide building during cmake configuration as explained here: Cmake support / JUCE_BUILD_HELPER_TOOLS - #3 by paulchana - General JUCE discussion - JUCE
I’m not sure however if disabling juceaide wouldn’t cause a problem.

Another idea, following the juceaide CMakeLists comments, would be to directly pass it the host compiler via CMAKE_<lang>_COMPILER.

Hi Val,
The problem is probably because juceaide is compiled for the target architecture, not the host architecture. One way to solve this problem could be to configure CMAKE_CROSSCOMPILING_EMULATOR to specify the path to the emulator that will be used to run the executables compiled for the target architecture on the host architecture. You can try adding the following line to the CMakeLists.txt file before calling add_subdirectory() for your plugin:
set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/qemu-aarch64-static)
This assumes that you have the qemu-user-static package installed, which contains an emulator to run aarch64 binaries on the x86_64 architecture. If you have a different emulator, replace the path with the appropriate one. This should force juceaide to compile for the host architecture and your plugin to compile for the target architecture. If that doesn’t work, you can try other emulators or workarounds, but keep in mind that this may lead to other problems or unwanted behavior. Good luck solving the problem!

1 Like

Thanks for the advice but, in the meantime, I’ve succeeded to set up a relatively clean cross-compile environment using extsdk. I’m posting it here in case it’s useful for people in the future:

Hardware setup

Flash the Raspberry Pi 4B with Elk OS: Release Elk Audio OS Image & Update 0.11.0 (RPi4) · elk-audio/elk-pi · GitHub
Set up communication with the raspberry pi: Working with Elk Board — Elk DevKit documentation
Set up HifiBerry DAC+ ADC Pro (in target): sudo elk_system_utils --set-audio-hat hifiberry-dac-plus-adc-pro

Install Docker

SDK setup

Create a directory to be shared as a volume with the container: mkdir workdir && cd workdir
Clone the patched JUCE in the volume directory: git clone git@github.com:valentinlageard/JUCE.git
Download the SDK in the volume directory: https://github.com/elk-audio/elkpi-sdk/releases/download/0.11.0/elk-glibc-x86_64-elkpi-audio-os-image-cortexa72-raspberrypi4-64-toolchain-0.11.0.sh
The first time, run the container with the sdk passed as a parameter: docker run --rm -it -v /home/valentin/Squarp/x-compile-test/workdir:/workdir crops/extsdk-container --url=/workdir/elk-glibc-x86_64-elkpi-audio-os-image-cortexa72-raspberrypi4-64-toolchain-0.11.0.sh
In subsequent runs you won’t need to pass the sdk: docker run --rm -it -v /home/valentin/Squarp/x-compile-test/workdir:/workdir crops/extsdk-container

JUCE project setup

Create a JUCE project using CMake in the volume directory.
In addition to your project specific configurations, modify your project CMakeList:

  • Add add_subdirectory("../JUCE" JUCE)
  • Check that VST3 is configured as an output target.
  • Comment out juce_generate_juce_header(YourPluginName)
  • Comment out juce::juce_recommended_lto_flags

Cross compilation

From inside the container, the first time, prepare to cross compile by creating a x-build subdirectory and initializing cmake:

  • mkdir x-build && cd x-build
  • cmake ../ -DCMAKE_BUILD_TYPE=Release
    From inside the container, in the x-build subdirectory of your JUCE project:
  • (Optional) Add compilation optimization flags: export CXXFLAGS="-O3 -pipe -ffast-math -feliminate-unused-debug-types -funroll-loops"
  • Build the plugin: AR=aarch64-elk-linux-ar make -j (enter number of cores) CONFIG=Release CFLAGS="-Wno-psabi" TARGET_ARCH="-mcpu=cortex-a72 -mtune=cortex-a72"

Upload and run

scp -r x-build/YourPluginName_artefacts/Release/VST3/ mind@your.raspberry.pi.ip:/udata
Start sushi with a proper sushi config !

Profit !

2 Likes