I’m trying to cross-compile my JUCE audio plugin.
I’m using an x86_64 Linux Docker container to target Win32 x86_64, i686, arm64 architectures.
(and if that’s not bad enough: I’m doing this from an M1 Mac! )
I’m failing at an early hurdle, building juceaide.
You can reproduce this with the x86_64 Linux Docker image mstorsjo/llvm-mingw
:
docker run -it --rm --name win32-xcompile mstorsjo/llvm-mingw
# now you're in the container
git clone --branch 6.1.4 --depth 1 https://github.com/juce-framework/JUCE.git
cd JUCE
TOOLCHAIN=x86_64
TOOLCHAIN_FILE="${TOOLCHAIN}_toolchain.cmake"
REPO=clang64
cat <<EOF >"$TOOLCHAIN_FILE"
# the name of the target operating system
set(CMAKE_SYSTEM_NAME Windows)
# which compilers to use for C and C++
set(CMAKE_C_COMPILER $TOOLCHAIN-w64-mingw32-clang)
set(CMAKE_CXX_COMPILER $TOOLCHAIN-w64-mingw32-clang++)
# where is the target environment located
set(CMAKE_FIND_ROOT_PATH /$REPO)
# adjust the default behavior of the FIND_XXX() commands:
# search programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# search headers and libraries in the target environment
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
EOF
BUILD="build_$TOOLCHAIN"
# add (high on our PATH) a few more aliases to our cross-compile tools,
# to avoid accidentally getting a native tool from elsewhere on our path
ln -sf "/opt/llvm-mingw/bin/${TOOLCHAIN}-w64-mingw32-clang++" /opt/llvm-mingw/bin/c++
ln -sf "/opt/llvm-mingw/bin/${TOOLCHAIN}-w64-mingw32-clang" /opt/llvm-mingw/bin/cc
declare -a TOOLS=(addr2line ar ld nm objcopy objdump ranlib readelf strip)
for TOOL in ${TOOLS[@]}; do
ln -sf "/opt/llvm-mingw/bin/${TOOLCHAIN}-w64-mingw32-${TOOL}" "/opt/llvm-mingw/bin/$TOOL"
done
VERBOSE=1 PKG_CONFIG_PATH="/$REPO/lib/pkgconfig" cmake -B"$BUILD" \
-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \
-DCMAKE_INSTALL_PREFIX="/$REPO" \
-DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN_FILE" \
-DCMAKE_BUILD_TYPE=Debug
# we don't get this far:
# cmake --build "$BUILD" --target install
The verbose output I get is:
root@8c832a516d54:/build/JUCE# VERBOSE=1 PKG_CONFIG_PATH="/$REPO/lib/pkgconfig" cmake -B"$BUILD" \
> -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \
> -DCMAKE_INSTALL_PREFIX="/$REPO" \
> -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN_FILE" \
> -DCMAKE_BUILD_TYPE=Debug
Re-run cmake no build system arguments
-- The C compiler identification is Clang 13.0.0
-- The CXX compiler identification is Clang 13.0.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /opt/llvm-mingw/bin/x86_64-w64-mingw32-clang - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /opt/llvm-mingw/bin/x86_64-w64-mingw32-clang++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring juceaide
-- Building juceaide
CMake Error at extras/Build/juceaide/CMakeLists.txt:89 (message):
Failed to build juceaide
/opt/cmake/bin/cmake -P
/build/JUCE/build_x86_64/tools/CMakeFiles/VerifyGlobs.cmake
/opt/cmake/bin/cmake -S/build/JUCE -B/build/JUCE/build_x86_64/tools
--check-build-system CMakeFiles/Makefile.cmake 0
/opt/cmake/bin/cmake -E cmake_progress_start
/build/JUCE/build_x86_64/tools/CMakeFiles
/build/JUCE/build_x86_64/tools//CMakeFiles/progress.marks
/usr/bin/make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/build/JUCE/build_x86_64/tools'
/usr/bin/make -f extras/Build/juceaide/CMakeFiles/juceaide.dir/build.make
extras/Build/juceaide/CMakeFiles/juceaide.dir/depend
make[2]: Entering directory '/build/JUCE/build_x86_64/tools'
cd /build/JUCE/build_x86_64/tools && /opt/cmake/bin/cmake -E cmake_depends
"Unix Makefiles" /build/JUCE /build/JUCE/extras/Build/juceaide
/build/JUCE/build_x86_64/tools
/build/JUCE/build_x86_64/tools/extras/Build/juceaide
/build/JUCE/build_x86_64/tools/extras/Build/juceaide/CMakeFiles/juceaide.dir/DependInfo.cmake
--color=
make[2]: Leaving directory '/build/JUCE/build_x86_64/tools'
/usr/bin/make -f extras/Build/juceaide/CMakeFiles/juceaide.dir/build.make
extras/Build/juceaide/CMakeFiles/juceaide.dir/build
make[2]: Entering directory '/build/JUCE/build_x86_64/tools'
[ 12%] Building CXX object
extras/Build/juceaide/CMakeFiles/juceaide.dir/Main.cpp.o
cd /build/JUCE/build_x86_64/tools/extras/Build/juceaide &&
/opt/llvm-mingw/bin/c++ -DDEBUG=1 -DJUCE_DISABLE_JUCE_VERSION_PRINTING=1
-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1
-DJUCE_MODULE_AVAILABLE_juce_build_tools=1
-DJUCE_MODULE_AVAILABLE_juce_core=1
-DJUCE_MODULE_AVAILABLE_juce_data_structures=1
-DJUCE_MODULE_AVAILABLE_juce_events=1
-DJUCE_MODULE_AVAILABLE_juce_graphics=1
-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1 -DJUCE_STANDALONE_APPLICATION=1
-DJUCE_USE_CURL=0 -DLINUX=1 -D_DEBUG=1
-I/build/JUCE/build_x86_64/tools/extras/Build/juceaide/juceaide_artefacts/JuceLibraryCode
-I/build/JUCE/extras/Build -I/build/JUCE/modules -g -O0 -Wall -Wshadow-all
-Wshorten-64-to-32 -Wstrict-aliasing -Wuninitialized -Wunused-parameter
-Wconversion -Wsign-compare -Wint-conversion -Wconditional-uninitialized
-Wconstant-conversion -Wsign-conversion -Wbool-conversion -Wextra-semi
-Wunreachable-code -Wcast-align -Wshift-sign-overflow
-Wno-missing-field-initializers -Wnullable-to-nonnull-conversion
-Wno-ignored-qualifiers -Wswitch-enum -Wpedantic
-Wzero-as-null-pointer-constant -Wunused-private-field -Woverloaded-virtual
-Wreorder -Winconsistent-missing-destructor-override -MD -MT
extras/Build/juceaide/CMakeFiles/juceaide.dir/Main.cpp.o -MF
CMakeFiles/juceaide.dir/Main.cpp.o.d -o CMakeFiles/juceaide.dir/Main.cpp.o
-c /build/JUCE/extras/Build/juceaide/Main.cpp
The main point of note is that although I configured cmake correctly, it spawns child cmake processes and does not pass my options to them.
The end result is that the compiler is invoked with -DLINUX=1
, which is not appropriate for my target platform.
Would it be possible for you to please pass the -DCMAKE_TOOLCHAIN_FILE
option to your child cmake processes?
As for the environment variable PKG_CONFIG_PATH
… I suspect the child process inherits this already. But otherwise, it’d be good to have a way to pass environment too (I don’t want it to lookup packages installed on the host platform).
The broader work I’m doing is here (fetching my dependencies for x86_64, i686, arm64 Windows via MinGW-w64, to statically-link them):