-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Description
I've been attempting to use a Linux Docker container to cross-compile my audio plugin for Windows x86_64, using Clang and MinGW.
The problem only occurs when you use JUCE_VST3_CAN_REPLACE_VST2=1 (so, to repro this you'll need a VST2 SDK).
It fails at link-time; juce_VST3_Wrapper.cpp fails to find symbol getUUIDForVST2ID.
/opt/llvm-mingw/bin/x86_64-w64-mingw32-clang++ -DJUCE_DISABLE_ASSERTIONS -g -shared -o "AudioPluginExample_artefacts/Debug/VST3/Audio Plugin Example.vst3/Contents/x86_64-win/Audio Plugin Example.vst3" -Wl,--major-image-version,0,--minor-image-version,0 -Wl,--whole-archive CMakeFiles/AudioPluginExample_VST3.dir/objects.a -Wl,--no-whole-archive @CMakeFiles/AudioPluginExample_VST3.dir/linklibs.rsp
ld.lld: error: undefined symbol: juce::getUUIDForVST2ID(bool, unsigned char*)
>>> referenced by /linux_native/include/JUCE-6.1.2/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp:3572
>>> objects.a(juce_audio_plugin_client_VST3.cpp.obj):(juce::getFUIDForVST2ID(bool))
clang-13: error: linker command failed with exit code 1 (use -v to see invocation)
CMakeFiles/AudioPluginExample_VST3.dir/build.make:256: recipe for target 'AudioPluginExample_artefacts/Debug/VST3/Audio Plugin Example.vst3/Contents/x86_64-win/Audio Plugin Example.vst3' failed
The symbol is supposed to be created in juce_PluginUtilities.cpp, provided JucePlugin_Build_VST3 is defined.
But juce_CheckSettingMacros.h undefines it since our toolchain is not whitelisted.
As a result: juce_audio_plugin_client_utils.cpp.obj (the file responsible for including juce_PluginUtilities.cpp) gets created without the symbol juce::getUUIDForVST2ID(bool, unsigned char*) .
here's how to reproduce the problem inside a Linux Docker container (cross-compiling for Windows):
# I assume that you have a VST2_SDK installed at ~/SDKs/VST_SDK/VST2_SDK/, and mount it into the container
docker run -it --rm --name=mingw-repro -v "$HOME/SDKs/VST_SDK/VST2_SDK/:/VST2_SDK/:ro" mstorsjo/llvm-mingw
# now you're inside the container
# install juceaide dependencies:
apt-get update -qq && \
apt-get install -qqy --no-install-recommends libx11-dev libxrandr-dev libxinerama-dev libxcursor-dev libfreetype6-dev && \
apt-get clean -y && \
rm -rf /var/lib/apt/lists/*
TOOLCHAIN=x86_64
TOOLCHAIN_FILE="/${TOOLCHAIN}_toolchain.cmake"
MINGW_REPO=clang64
# define CMake toolchain for cross-compiling to x86_64 Windows via MinGW:
cat >"$TOOLCHAIN_FILE" <<EOF
# 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
# https://cmake.org/cmake/help/latest/command/find_library.html
set(CMAKE_FIND_ROOT_PATH /$MINGW_REPO;/opt/llvm-mingw/$TOOLCHAIN-w64-mingw32)
# 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
# clone last-known-good JUCE
# we cannot use a newer JUCE due to https://github.com/juce-framework/JUCE/issues/985
git clone --branch 6.1.2 --depth 1 https://github.com/juce-framework/JUCE.git
cd JUCE
# build juceaide (we will *not* cross-compile this for Windows; we build natively for the build machine)
cmake -B build -DCMAKE_INSTALL_PREFIX="/linux_native"
cmake --build build --target install
cd examples/CMake/AudioPlugin
# uncomment find_package line
sed -i '/^# find_package(JUCE/ s/# //' CMakeLists.txt
# enable JUCE_VST3_CAN_REPLACE_VST2
sed -i '/JUCE_VST3_CAN_REPLACE_VST2=0/ s/0/1/' CMakeLists.txt
# set VST2_SDK path
sed -i '/^juce_add_plugin/i juce_set_vst2_sdk_path(/VST2_SDK)' CMakeLists.txt
# I've disabled assertions because of an unrelated issue (compiling asm on Clang):
# https://github.com/juce-framework/JUCE/issues/986
VERBOSE=1 cmake -Bbuild \
-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \
-DCMAKE_PREFIX_PATH="/linux_native" \
-DCMAKE_INSTALL_PREFIX="/$MINGW_REPO" \
-DCMAKE_CXX_FLAGS='-DJUCE_DISABLE_ASSERTIONS' \
-DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN_FILE" \
-DCMAKE_BUILD_TYPE=Debug
# will encounter link failure in juce_VST3_Wrapper.cpp
cmake --build build --target AudioPluginExample_VST3
cd build
# the reason for the link failure is because the symbol is missing:
llvm-nm -gU CMakeFiles/AudioPluginExample.dir/linux_native/include/JUCE-6.1.2/modules/juce_audio_plugin_client/juce_audio_plugin_client_utils.cpp.obj
# no symbols printed at all!I'm currently working around this with the following patch:
Birch-san@7182e6e
In my branch (Birch-san/juicysfplugin#32), build and link succeed. I get the following symbols returned:
llvm-nm -gU CMakeFiles/JuicySFPlugin.dir/linux_native/include/JUCE-6.1.2/modules/juce_audio_plugin_client/juce_audio_plugin_client_utils.cpp.obj
00001200 T _ZN4juce16getUUIDForVST2IDEbPh
000019c0 T _ZN4juce36handleManufacturerSpecificVST2OpcodeEixPvf
00000000 T _ZN4juce9ByteOrder12bigEndianIntEPKv
00000000 T _ZN4juce9ByteOrder7makeIntEhhhh
With my patch: this successfully builds & links a VST3 plugin, which runs fine in FL Studio.
perhaps Clang+MinGW should be added to the whitelist of supported toolchains in juce_CheckSettingMacros.h?