From f10409ad1e4ef9789291bc541192f058731d1b03 Mon Sep 17 00:00:00 2001 From: Igor Barcik Date: Wed, 9 Sep 2026 13:24:09 +0200 Subject: [PATCH] build: extract CMake plugin/harness modules and add platform build scripts Split CMakeLists.txt into cmake/Plugin.cmake (production formats and MinGW link flags) and cmake/Harness.cmake (console test harness with CTest registration). Add SERUMALT_BUILD_PLUGIN and SERUMALT_BUILD_TESTS options so production and harness builds are mutually exclusive and each omits the other's targets. Add build_linux.sh, build_macos.sh, and build_harness.sh with host validation, env-overridable build dirs, and explicit option flags. Rewrite build_windows.sh to use the checked-in mingw64-toolchain.cmake instead of regenerating it, validate all required tools, and stage with cmake -E copy_directory. Broaden .gitignore to cover all build_*/ directories. --- .gitignore | 2 +- CMakeLists.txt | 90 ++++++++++++-------------------------- build_harness.sh | 50 +++++++++++++++++++++ build_linux.sh | 32 ++++++++++++++ build_macos.sh | 41 +++++++++++++++++ build_windows.sh | 104 +++++++++++++++++++++----------------------- cmake/Harness.cmake | 7 +++ cmake/Plugin.cmake | 52 ++++++++++++++++++++++ 8 files changed, 260 insertions(+), 118 deletions(-) create mode 100755 build_harness.sh create mode 100755 build_linux.sh create mode 100755 build_macos.sh create mode 100644 cmake/Harness.cmake create mode 100644 cmake/Plugin.cmake diff --git a/.gitignore b/.gitignore index 0749a49..2718d79 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ # CMake build directories /build/ -/build_windows/ +/build_*/ /cmake-build-*/ # Windows output staging diff --git a/CMakeLists.txt b/CMakeLists.txt index 25b315a..862124c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,43 +9,20 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) +option(SERUMALT_BUILD_PLUGIN "Build production plugin and standalone formats" ON) +option(SERUMALT_BUILD_TESTS "Build the headless QA harness" OFF) + +if(NOT SERUMALT_BUILD_PLUGIN AND NOT SERUMALT_BUILD_TESTS) + message(FATAL_ERROR "Enable SERUMALT_BUILD_PLUGIN or SERUMALT_BUILD_TESTS") +endif() + # --------------------------------------------------------------------------- # JUCE # --------------------------------------------------------------------------- if(NOT DEFINED JUCE_ROOT) set(JUCE_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/third_party/JUCE") endif() -add_subdirectory("${JUCE_ROOT}") - -# --------------------------------------------------------------------------- -# Plugin target -# --------------------------------------------------------------------------- -# JUCE 7.0.12 builds its VST3 manifest helper (juce_vst3_helper) with the same -# toolchain as the plugin itself. When cross-compiling, that produces a Windows -# .exe which cannot run on the Linux build host, so we disable the automatic -# manifest step and inject a platform-independent moduleinfo.json afterwards -# (see build_windows.sh). Native builds keep the automatic step. -set(SERUMALT_VST3_AUTO_MANIFEST TRUE) -if(CMAKE_CROSSCOMPILING) - set(SERUMALT_VST3_AUTO_MANIFEST FALSE) -endif() - -juce_add_plugin(SerumAlt - VERSION 1.0.0 - COMPANY_NAME "SerumAlt Audio" - IS_SYNTH TRUE - NEEDS_MIDI_INPUT TRUE - NEEDS_MIDI_OUTPUT FALSE - IS_MIDI_EFFECT FALSE - EDITOR_WANTS_KEYBOARD_FOCUS FALSE - PLUGIN_MANUFACTURER_CODE Salt - PLUGIN_CODE Sera - BUNDLE_ID com.serumalt.SerumAlt - FORMATS VST3 AU Standalone - PRODUCT_NAME "SerumAlt" - VST3_AUTO_MANIFEST ${SERUMALT_VST3_AUTO_MANIFEST}) - -juce_generate_juce_header(SerumAlt) +add_subdirectory("${JUCE_ROOT}" "${CMAKE_CURRENT_BINARY_DIR}/third_party/JUCE") set(SERUMALT_SOURCES Source/PluginProcessor.cpp @@ -86,46 +63,33 @@ set(SERUMALT_SOURCES Source/GUI/Panel.cpp Source/Presets/FactoryPresets.cpp) -target_sources(SerumAlt PRIVATE ${SERUMALT_SOURCES}) - -target_compile_definitions(SerumAlt - PUBLIC - JUCE_WEB_BROWSER=0 - JUCE_USE_CURL=0 - JUCE_VST3_CAN_REPLACE_VST2=0) - -target_link_libraries(SerumAlt - PRIVATE - juce::juce_audio_utils - juce::juce_dsp - PUBLIC - juce::juce_recommended_config_flags - juce::juce_recommended_warning_flags) - -# --------------------------------------------------------------------------- -# Headless QA harness (console app that drives the processor and checks output) -# --------------------------------------------------------------------------- -option(SERUMALT_BUILD_TESTS "Build the headless QA harness" ON) - -if(SERUMALT_BUILD_TESTS) - juce_add_console_app(SerumAltTest) - juce_generate_juce_header(SerumAltTest) - target_sources(SerumAltTest PRIVATE ${SERUMALT_SOURCES} Source/Tests/TestMain.cpp) - target_compile_definitions(SerumAltTest +function(serumalt_configure_target target) + juce_generate_juce_header(${target}) + target_sources(${target} PRIVATE ${SERUMALT_SOURCES}) + target_compile_definitions(${target} PUBLIC JUCE_WEB_BROWSER=0 - JUCE_USE_CURL=0) - target_link_libraries(SerumAltTest + JUCE_USE_CURL=0 + JUCE_VST3_CAN_REPLACE_VST2=0) + target_link_libraries(${target} PRIVATE juce::juce_audio_utils juce::juce_dsp PUBLIC juce::juce_recommended_config_flags juce::juce_recommended_warning_flags) + if(MSVC) + target_compile_options(${target} PRIVATE /W4) + else() + target_compile_options(${target} PRIVATE -Wall -Wextra) + endif() +endfunction() + +if(SERUMALT_BUILD_PLUGIN) + include(cmake/Plugin.cmake) endif() -if(MSVC) - target_compile_options(SerumAlt PRIVATE /W4) -else() - target_compile_options(SerumAlt PRIVATE -Wall -Wextra) +if(SERUMALT_BUILD_TESTS) + enable_testing() + include(cmake/Harness.cmake) endif() diff --git a/build_harness.sh b/build_harness.sh new file mode 100755 index 0000000..6a71fb4 --- /dev/null +++ b/build_harness.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR" + +BUILD_DIR="${BUILD_DIR:-$SCRIPT_DIR/build_harness}" +BUILD_TYPE="${BUILD_TYPE:-Release}" +export CMAKE_BUILD_PARALLEL_LEVEL="${CMAKE_BUILD_PARALLEL_LEVEL:-2}" + +if [[ $# -gt 1 || ( $# -eq 1 && "$1" != --run ) ]]; then + echo "Usage: $0 [--run]" >&2 + exit 1 +fi + +TOOLS=(cmake ninja "${CC:-cc}" "${CXX:-c++}") +case "$(uname -s)" in + Linux) TOOLS+=(pkg-config) ;; + Darwin) TOOLS+=(xcrun) ;; + *) echo "ERROR: build_harness.sh requires a native Linux or macOS host." >&2; exit 1 ;; +esac +if [[ $# -eq 1 ]]; then + TOOLS+=(ctest) +fi +for tool in "${TOOLS[@]}"; do + if ! command -v "$tool" >/dev/null 2>&1; then + echo "ERROR: $tool not found. See README.md prerequisites." >&2 + exit 1 + fi +done + +if [[ "$(uname -s)" == Darwin ]]; then + xcrun --sdk macosx --show-sdk-path +fi + +echo "Configuring the native QA harness only in $BUILD_DIR ($BUILD_TYPE)..." +cmake -S "$SCRIPT_DIR" -B "$BUILD_DIR" -G Ninja \ + -DCMAKE_BUILD_TYPE="$BUILD_TYPE" \ + -DSERUMALT_BUILD_PLUGIN=OFF \ + -DSERUMALT_BUILD_TESTS=ON + +echo "Building SerumAltTest..." +cmake --build "$BUILD_DIR" --config "$BUILD_TYPE" --target SerumAltTest + +if [[ $# -eq 1 ]]; then + echo "Running the QA harness with CTest..." + ctest --test-dir "$BUILD_DIR" --build-config "$BUILD_TYPE" --output-on-failure --no-tests=error +fi + +echo "Done. QA harness: $BUILD_DIR/SerumAltTest_artefacts/$BUILD_TYPE/SerumAltTest" diff --git a/build_linux.sh b/build_linux.sh new file mode 100755 index 0000000..9579f50 --- /dev/null +++ b/build_linux.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR" + +BUILD_DIR="${BUILD_DIR:-$SCRIPT_DIR/build_linux}" +BUILD_TYPE="${BUILD_TYPE:-Release}" +export CMAKE_BUILD_PARALLEL_LEVEL="${CMAKE_BUILD_PARALLEL_LEVEL:-2}" + +if [[ "$(uname -s)" != Linux ]]; then + echo "ERROR: build_linux.sh requires a Linux host." >&2 + exit 1 +fi + +for tool in cmake ninja pkg-config "${CC:-cc}" "${CXX:-c++}"; do + if ! command -v "$tool" >/dev/null 2>&1; then + echo "ERROR: $tool not found. See README.md prerequisites." >&2 + exit 1 + fi +done + +echo "Configuring Linux production targets in $BUILD_DIR ($BUILD_TYPE)..." +cmake -S "$SCRIPT_DIR" -B "$BUILD_DIR" -G Ninja \ + -DCMAKE_BUILD_TYPE="$BUILD_TYPE" \ + -DSERUMALT_BUILD_PLUGIN=ON \ + -DSERUMALT_BUILD_TESTS=OFF + +echo "Building Linux VST3 and standalone..." +cmake --build "$BUILD_DIR" --config "$BUILD_TYPE" --target SerumAlt_VST3 SerumAlt_Standalone + +echo "Done. Linux artifacts: $BUILD_DIR/SerumAlt_artefacts/$BUILD_TYPE" diff --git a/build_macos.sh b/build_macos.sh new file mode 100755 index 0000000..0e6d75e --- /dev/null +++ b/build_macos.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR" + +BUILD_DIR="${BUILD_DIR:-$SCRIPT_DIR/build_macos}" +BUILD_TYPE="${BUILD_TYPE:-Release}" +export CMAKE_BUILD_PARALLEL_LEVEL="${CMAKE_BUILD_PARALLEL_LEVEL:-2}" + +if [[ "$(uname -s)" != Darwin ]]; then + echo "ERROR: build_macos.sh requires macOS and the Apple SDK." >&2 + exit 1 +fi + +for tool in cmake ninja xcrun "${CC:-clang}" "${CXX:-clang++}"; do + if ! command -v "$tool" >/dev/null 2>&1; then + echo "ERROR: $tool not found. See README.md prerequisites." >&2 + exit 1 + fi +done +xcrun --sdk macosx --show-sdk-path + +OSX_OPTIONS=("-DCMAKE_BUILD_TYPE=$BUILD_TYPE") +if [[ -n "${CMAKE_OSX_ARCHITECTURES:-}" ]]; then + OSX_OPTIONS+=("-DCMAKE_OSX_ARCHITECTURES=$CMAKE_OSX_ARCHITECTURES") +fi +if [[ -n "${CMAKE_OSX_DEPLOYMENT_TARGET:-}" ]]; then + OSX_OPTIONS+=("-DCMAKE_OSX_DEPLOYMENT_TARGET=$CMAKE_OSX_DEPLOYMENT_TARGET") +fi + +echo "Configuring macOS production targets in $BUILD_DIR ($BUILD_TYPE)..." +cmake -S "$SCRIPT_DIR" -B "$BUILD_DIR" -G Ninja \ + "${OSX_OPTIONS[@]}" \ + -DSERUMALT_BUILD_PLUGIN=ON \ + -DSERUMALT_BUILD_TESTS=OFF + +echo "Building macOS VST3, AU, and standalone..." +cmake --build "$BUILD_DIR" --config "$BUILD_TYPE" --target SerumAlt_VST3 SerumAlt_AU SerumAlt_Standalone + +echo "Done. macOS artifacts: $BUILD_DIR/SerumAlt_artefacts/$BUILD_TYPE" diff --git a/build_windows.sh b/build_windows.sh index f577d76..1987844 100755 --- a/build_windows.sh +++ b/build_windows.sh @@ -7,60 +7,60 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" -TOOLCHAIN_FILE="mingw64-toolchain.cmake" -BUILD_DIR="build_windows" -OUTPUT_DIR="SerumAlt_Windows" +TOOLCHAIN_FILE="$SCRIPT_DIR/mingw64-toolchain.cmake" +BUILD_DIR="${BUILD_DIR:-$SCRIPT_DIR/build_windows}" +BUILD_TYPE="${BUILD_TYPE:-Release}" +OUTPUT_DIR="${OUTPUT_DIR:-$SCRIPT_DIR/SerumAlt_Windows}" PLUGIN_NAME="SerumAlt" +export CMAKE_BUILD_PARALLEL_LEVEL="${CMAKE_BUILD_PARALLEL_LEVEL:-2}" -# 1. Check for the MinGW-w64 cross-compiler and exit if it is not found. -if ! command -v x86_64-w64-mingw32-g++ >/dev/null 2>&1; then - echo "ERROR: x86_64-w64-mingw32-g++ not found." >&2 - echo "Please install the MinGW-w64 cross-compiler first, e.g.:" >&2 - echo " sudo pacman -S mingw-w64-gcc" >&2 +if [[ "$(uname -s)" != Linux ]]; then + echo "ERROR: build_windows.sh cross-compiles from Linux using MinGW-w64." >&2 exit 1 fi +# 1. Check for the host tools and MinGW-w64 cross-compiler. +for tool in cmake ninja pkg-config "${CC:-cc}" "${CXX:-c++}" \ + x86_64-w64-mingw32-gcc x86_64-w64-mingw32-g++ \ + x86_64-w64-mingw32-windres x86_64-w64-mingw32-ar \ + x86_64-w64-mingw32-ranlib x86_64-w64-mingw32-strip; do + if ! command -v "$tool" >/dev/null 2>&1; then + echo "ERROR: $tool not found. See README.md prerequisites." >&2 + exit 1 + fi +done + echo "Found: $(command -v x86_64-w64-mingw32-g++)" -# 2. Generate the CMake toolchain file. -cat > "$TOOLCHAIN_FILE" <<'EOF' -set(CMAKE_SYSTEM_NAME Windows) -set(CMAKE_SYSTEM_PROCESSOR x86_64) - -set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) -set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) -set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) -set(CMAKE_AR x86_64-w64-mingw32-ar) -set(CMAKE_RANLIB x86_64-w64-mingw32-ranlib) -set(CMAKE_STRIP x86_64-w64-mingw32-strip) - -set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) -EOF - -echo "Wrote toolchain file: $TOOLCHAIN_FILE" +# 2. Use the checked-in CMake toolchain file without overwriting it. +if [[ ! -f "$TOOLCHAIN_FILE" ]]; then + echo "ERROR: Toolchain file not found: $TOOLCHAIN_FILE" >&2 + exit 1 +fi +echo "Using toolchain file: $TOOLCHAIN_FILE" # 3. Configure with CMake + Ninja (VST3-only cross build, no test harness). -cmake -S . -B "$BUILD_DIR" -G Ninja \ - -DCMAKE_BUILD_TYPE=Release \ +echo "Configuring Windows VST3 in $BUILD_DIR ($BUILD_TYPE)..." +cmake -S "$SCRIPT_DIR" -B "$BUILD_DIR" -G Ninja \ + -DCMAKE_BUILD_TYPE="$BUILD_TYPE" \ -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN_FILE" \ + -DSERUMALT_BUILD_PLUGIN=ON \ -DSERUMALT_BUILD_TESTS=OFF # 4. Build the VST3 target. -cmake --build "$BUILD_DIR" --target SerumAlt_VST3 +echo "Building Windows VST3..." +cmake --build "$BUILD_DIR" --config "$BUILD_TYPE" --target SerumAlt_VST3 # 5. Inject the VST3 moduleinfo.json. # The automatic manifest step is disabled when cross-compiling (see -# CMakeLists.txt), because JUCE's manifest helper is a host tool that would +# cmake/Plugin.cmake), because JUCE's manifest helper is a host tool that would # otherwise be built as a Windows executable. The moduleinfo content is -# deterministic and platform-independent: it depends only on the plugin's -# name, manufacturer/plugin codes, and version, so we write the identical -# file that the native helper generates. Keep it in sync with the metadata -# in CMakeLists.txt (PLUGIN_CODE, PLUGIN_MANUFACTURER_CODE, VERSION). -VST3_BUNDLE="$BUILD_DIR/${PLUGIN_NAME}_artefacts/Release/VST3/$PLUGIN_NAME.vst3" +# deterministic for this Windows plugin: it depends on the plugin's +# name, manufacturer/plugin codes, and version, so we write the same metadata +# that the native Windows helper generates. Keep it in sync with the metadata +# in CMakeLists.txt and cmake/Plugin.cmake, including the vendored VST3 SDK version. +VST3_BUNDLE="$BUILD_DIR/${PLUGIN_NAME}_artefacts/$BUILD_TYPE/VST3/$PLUGIN_NAME.vst3" +echo "Writing Windows VST3 manifest..." mkdir -p "$VST3_BUNDLE/Contents/Resources" cat > "$VST3_BUNDLE/Contents/Resources/moduleinfo.json" <<'EOF' { @@ -73,8 +73,8 @@ cat > "$VST3_BUNDLE/Contents/Resources/moduleinfo.json" <<'EOF' "Flags": { "Unicode": true, "Classes Discardable": false, - "Component Non Discardable": false, - }, + "Component Non Discardable": false + } }, "Classes": [ { @@ -86,12 +86,11 @@ cat > "$VST3_BUNDLE/Contents/Resources/moduleinfo.json" <<'EOF' "SDKVersion": "VST 3.7.8", "Sub Categories": [ "Instrument", - "Synth", + "Synth" ], "Class Flags": 2, "Cardinality": 2147483647, - "Snapshots": [ - ], + "Snapshots": [] }, { "CID": "ABCDEF011234ABCD53616C7453657261", @@ -102,12 +101,11 @@ cat > "$VST3_BUNDLE/Contents/Resources/moduleinfo.json" <<'EOF' "SDKVersion": "VST 3.7.8", "Sub Categories": [ "Instrument", - "Synth", + "Synth" ], "Class Flags": 2, "Cardinality": 2147483647, - "Snapshots": [ - ], + "Snapshots": [] }, { "CID": "ABCDEF01C0DEF00D53616C7453657261", @@ -118,17 +116,15 @@ cat > "$VST3_BUNDLE/Contents/Resources/moduleinfo.json" <<'EOF' "SDKVersion": "VST 3.7.8", "Class Flags": 0, "Cardinality": 2147483647, - "Snapshots": [ - ], - }, - ], + "Snapshots": [] + } + ] } EOF -# 6. Copy the resulting .vst3 bundle to SerumAlt_Windows/. -mkdir -p "$OUTPUT_DIR" -rm -rf "$OUTPUT_DIR/$PLUGIN_NAME.vst3" -cp -R "$BUILD_DIR/${PLUGIN_NAME}_artefacts/Release/VST3/$PLUGIN_NAME.vst3" "$OUTPUT_DIR/" +# 6. Copy the resulting .vst3 bundle to SerumAlt_Windows/ without deleting files. +echo "Staging Windows VST3 in $OUTPUT_DIR..." +cmake -E copy_directory "$VST3_BUNDLE" "$OUTPUT_DIR/$PLUGIN_NAME.vst3" echo -echo "Done. Windows VST3 plugin at: $SCRIPT_DIR/$OUTPUT_DIR/$PLUGIN_NAME.vst3" +echo "Done. Windows VST3 plugin at: $OUTPUT_DIR/$PLUGIN_NAME.vst3" diff --git a/cmake/Harness.cmake b/cmake/Harness.cmake new file mode 100644 index 0000000..b21ac13 --- /dev/null +++ b/cmake/Harness.cmake @@ -0,0 +1,7 @@ +# --------------------------------------------------------------------------- +# Headless QA harness (console app that drives the processor and checks output) +# --------------------------------------------------------------------------- +juce_add_console_app(SerumAltTest) +serumalt_configure_target(SerumAltTest) +target_sources(SerumAltTest PRIVATE Source/Tests/TestMain.cpp) +add_test(NAME SerumAltTest COMMAND SerumAltTest) diff --git a/cmake/Plugin.cmake b/cmake/Plugin.cmake new file mode 100644 index 0000000..45bdf01 --- /dev/null +++ b/cmake/Plugin.cmake @@ -0,0 +1,52 @@ +# --------------------------------------------------------------------------- +# Plugin target +# --------------------------------------------------------------------------- +# JUCE 7.0.12 builds its VST3 manifest helper (juce_vst3_helper) with the same +# toolchain as the plugin itself. When cross-compiling, that produces a Windows +# .exe which cannot run on the Linux build host, so we disable the automatic +# manifest step and inject a Windows moduleinfo.json afterwards +# (see build_windows.sh). Native builds keep the automatic step. +set(SERUMALT_VST3_AUTO_MANIFEST TRUE) +if(CMAKE_CROSSCOMPILING) + set(SERUMALT_VST3_AUTO_MANIFEST FALSE) +endif() + +set(SERUMALT_FORMATS VST3) +if(NOT WIN32) + list(APPEND SERUMALT_FORMATS Standalone) +endif() +if(APPLE) + list(APPEND SERUMALT_FORMATS AU) +endif() + +juce_add_plugin(SerumAlt + VERSION ${PROJECT_VERSION} + COMPANY_NAME "SerumAlt Audio" + IS_SYNTH TRUE + NEEDS_MIDI_INPUT TRUE + NEEDS_MIDI_OUTPUT FALSE + IS_MIDI_EFFECT FALSE + EDITOR_WANTS_KEYBOARD_FOCUS FALSE + PLUGIN_MANUFACTURER_CODE Salt + PLUGIN_CODE Sera + BUNDLE_ID com.serumalt.SerumAlt + FORMATS ${SERUMALT_FORMATS} + PRODUCT_NAME "SerumAlt" + VST3_AUTO_MANIFEST ${SERUMALT_VST3_AUTO_MANIFEST}) + +serumalt_configure_target(SerumAlt) + +# --------------------------------------------------------------------------- +# MinGW cross-build: static C++/threading runtime +# --------------------------------------------------------------------------- +# When cross-compiling for Windows with MinGW, link libgcc / libstdc++ / +# winpthread statically so the VST3 DLL is self-contained. Otherwise the DLL +# imports libgcc_s_seh-1.dll, libstdc++-6.dll and libwinpthread-1.dll, none of +# which ship with the bundle (or exist on a stock Windows host), so the host's +# scan would fail to load the plugin. Native (Linux) builds are unaffected. +if(MINGW) + target_link_options(SerumAlt_VST3 PRIVATE + -static-libgcc + -static-libstdc++ + -static) +endif()