Claude Code Plugins

Community-maintained marketplace

Feedback

cross-platform-builds

@yebot/rad-cc-plugins
1
0

Comprehensive guide to building JUCE plugins for macOS, Windows, and Linux with CMake, code signing, notarization, and CI/CD. Use when configuring builds, setting up CI/CD pipelines, troubleshooting cross-platform compilation, implementing code signing, or creating installers for multiple platforms.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name cross-platform-builds
description Comprehensive guide to building JUCE plugins for macOS, Windows, and Linux with CMake, code signing, notarization, and CI/CD. Use when configuring builds, setting up CI/CD pipelines, troubleshooting cross-platform compilation, implementing code signing, or creating installers for multiple platforms.
allowed-tools Read, Grep, Glob

Cross-Platform Builds for JUCE Plugins

Comprehensive guide to building JUCE audio plugins across macOS, Windows, and Linux with proper configuration, code signing, and continuous integration.

Overview

JUCE audio plugins must be built for multiple platforms and plugin formats:

  • macOS: VST3, AU (Audio Unit), AAX
  • Windows: VST3, AAX
  • Linux: VST3

Each platform has specific requirements for build tools, code signing, and packaging. This skill covers:

  1. CMake configuration for all platforms and formats
  2. Platform-specific build instructions
  3. Code signing and notarization
  4. Continuous integration setup
  5. Reproducible builds

1. CMake Configuration

Root CMakeLists.txt Structure

cmake_minimum_required(VERSION 3.22)

project(MyPlugin VERSION 1.0.0)

# C++17 minimum for JUCE 7+
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Export compile_commands.json for IDEs
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# Add JUCE
add_subdirectory(JUCE)

# Plugin formats to build
set(PLUGIN_FORMATS VST3 AU Standalone)

# Add AAX if PACE SDK is available
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/SDKs/AAX")
    list(APPEND PLUGIN_FORMATS AAX)
    juce_set_aax_sdk_path("${CMAKE_CURRENT_SOURCE_DIR}/SDKs/AAX")
endif()

# Define the plugin
juce_add_plugin(MyPlugin
    COMPANY_NAME "YourCompany"
    PLUGIN_MANUFACTURER_CODE Manu  # 4-character code
    PLUGIN_CODE Plug                # 4-character code (unique!)
    FORMATS ${PLUGIN_FORMATS}
    PRODUCT_NAME "MyPlugin"

    # Bundle IDs
    BUNDLE_ID com.yourcompany.myplugin

    # Plugin characteristics
    IS_SYNTH FALSE
    NEEDS_MIDI_INPUT FALSE
    NEEDS_MIDI_OUTPUT FALSE
    IS_MIDI_EFFECT FALSE
    EDITOR_WANTS_KEYBOARD_FOCUS FALSE

    # Copy plugin to system folder after build
    COPY_PLUGIN_AFTER_BUILD TRUE

    # VST3 category
    VST3_CATEGORIES Fx

    # AU type (aufx = effect, aumu = instrument)
    AU_MAIN_TYPE kAudioUnitType_Effect
)

# Source files
target_sources(MyPlugin PRIVATE
    Source/PluginProcessor.cpp
    Source/PluginEditor.cpp
    Source/DSP/Filter.cpp
    Source/DSP/Modulation.cpp
)

# Public compile definitions
target_compile_definitions(MyPlugin PUBLIC
    JUCE_WEB_BROWSER=0
    JUCE_USE_CURL=0
    JUCE_VST3_CAN_REPLACE_VST2=0
    JUCE_DISPLAY_SPLASH_SCREEN=0  # Commercial license only!
)

# Link JUCE modules
target_link_libraries(MyPlugin PRIVATE
    juce::juce_audio_utils
    juce::juce_dsp
    juce::juce_recommended_config_flags
    juce::juce_recommended_lto_flags
    juce::juce_recommended_warning_flags
)

# Platform-specific settings
if(APPLE)
    # macOS deployment target
    set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13" CACHE STRING "Minimum macOS version")

    # Universal binary (Apple Silicon + Intel)
    set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "macOS architectures")

    # Hardened runtime for notarization
    target_compile_options(MyPlugin PUBLIC
        -Wall -Wextra -Wpedantic
    )
elseif(WIN32)
    # Static runtime for standalone distribution
    set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

    # Windows-specific definitions
    target_compile_definitions(MyPlugin PRIVATE
        _CRT_SECURE_NO_WARNINGS
    )
elseif(UNIX)
    # Linux-specific flags
    target_compile_options(MyPlugin PRIVATE
        -Wall -Wextra
    )

    # Link against ALSA, JACK, etc.
    find_package(PkgConfig REQUIRED)
    pkg_check_modules(ALSA REQUIRED alsa)
    target_link_libraries(MyPlugin PRIVATE ${ALSA_LIBRARIES})
endif()

# Tests (optional)
option(BUILD_TESTS "Build unit tests" ON)
if(BUILD_TESTS)
    enable_testing()
    add_subdirectory(Tests)
endif()

Key Configuration Options

Plugin Codes

PLUGIN_MANUFACTURER_CODE Manu  # Your unique 4-character manufacturer ID
PLUGIN_CODE Plug                # Unique 4-character plugin ID

Important: Register manufacturer code at Steinberg to avoid conflicts.

Bundle Identifiers

BUNDLE_ID com.yourcompany.myplugin  # Reverse domain notation

Must be unique and consistent across versions for AU validation.

Plugin Characteristics

IS_SYNTH TRUE                   # Instrument vs effect
NEEDS_MIDI_INPUT TRUE          # Accept MIDI input
NEEDS_MIDI_OUTPUT FALSE        # Send MIDI output
IS_MIDI_EFFECT FALSE           # MIDI-only processing (no audio)

VST3 Categories

VST3_CATEGORIES Fx              # Effect
VST3_CATEGORIES Instrument      # Instrument
VST3_CATEGORIES Fx Dynamics     # Multiple categories

Available categories: Fx, Instrument, Analyzer, Delay, Distortion, Dynamics, EQ, Filter, Mastering, Modulation, Restoration, Reverb, Spatial, Synth, Tools

AU Types

AU_MAIN_TYPE kAudioUnitType_Effect           # Effect
AU_MAIN_TYPE kAudioUnitType_MusicDevice      # Instrument
AU_MAIN_TYPE kAudioUnitType_MIDIProcessor    # MIDI effect

2. macOS Builds

Prerequisites

  1. Xcode (latest version recommended)

    xcode-select --install
    
  2. CMake (3.22+)

    brew install cmake
    
  3. Developer ID Certificate (for distribution)

    • Enroll in Apple Developer Program ($99/year)
    • Create "Developer ID Application" certificate in Xcode

Building

# Configure
cmake -B build-mac -G Xcode \
      -DCMAKE_BUILD_TYPE=Release \
      -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 \
      -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64"

# Build all formats
cmake --build build-mac --config Release --parallel

# Or build with Xcode
open build-mac/MyPlugin.xcodeproj

Universal Binaries (Apple Silicon + Intel)

# In CMakeLists.txt
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64")

Or at build time:

cmake -B build-mac -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64"

Verify architectures:

lipo -info build-mac/MyPlugin_artefacts/Release/VST3/MyPlugin.vst3/Contents/MacOS/MyPlugin

# Output: Architectures in the fat file: MyPlugin are: x86_64 arm64

Code Signing

Manual Signing

# Sign VST3
codesign --force \
         --sign "Developer ID Application: Your Name (TEAM_ID)" \
         --options runtime \
         --entitlements Resources/Entitlements.plist \
         --timestamp \
         --deep \
         MyPlugin.vst3

# Sign AU
codesign --force \
         --sign "Developer ID Application: Your Name (TEAM_ID)" \
         --options runtime \
         --timestamp \
         --deep \
         MyPlugin.component

# Verify signature
codesign --verify --deep --strict --verbose=2 MyPlugin.vst3

Entitlements File (Resources/Entitlements.plist)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
         "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <!-- Allow JIT for DSP optimization -->
    <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
    <true/>

    <!-- Allow loading unsigned plugins (for VST3 presets, etc.) -->
    <key>com.apple.security.cs.disable-library-validation</key>
    <true/>

    <!-- For networked plugins (optional) -->
    <key>com.apple.security.network.client</key>
    <true/>
</dict>
</plist>

Automated Signing in CMake

# Add to CMakeLists.txt
if(APPLE AND CMAKE_BUILD_TYPE STREQUAL "Release")
    set(CODESIGN_IDENTITY "Developer ID Application: Your Name")

    add_custom_command(TARGET MyPlugin POST_BUILD
        COMMAND codesign --force
                --sign "${CODESIGN_IDENTITY}"
                --options runtime
                --entitlements "${CMAKE_SOURCE_DIR}/Resources/Entitlements.plist"
                --timestamp
                $<TARGET_BUNDLE_DIR:MyPlugin>
        COMMENT "Code signing ${TARGET}"
    )
endif()

Notarization

Required for macOS 10.15+ (Catalina and later).

Setup

  1. Create app-specific password at appleid.apple.com
  2. Store credentials in keychain:
    xcrun notarytool store-credentials "notary-profile" \
          --apple-id "developer@example.com" \
          --team-id "TEAM_ID" \
          --password "xxxx-xxxx-xxxx-xxxx"
    

Notarize Plugin

# 1. Create ZIP for notarization
ditto -c -k --keepParent MyPlugin.vst3 MyPlugin-vst3.zip

# 2. Submit to notary service
xcrun notarytool submit MyPlugin-vst3.zip \
      --keychain-profile "notary-profile" \
      --wait

# 3. If successful, staple the ticket
xcrun stapler staple MyPlugin.vst3

# 4. Verify
spctl -a -vvv -t install MyPlugin.vst3
xcrun stapler validate MyPlugin.vst3

Troubleshooting Notarization

Check submission status:

xcrun notarytool info <submission-id> --keychain-profile "notary-profile"

View detailed log:

xcrun notarytool log <submission-id> --keychain-profile "notary-profile"

Common issues:

  • Missing entitlements: Add to Entitlements.plist
  • Unsigned nested binaries: Sign all frameworks before parent bundle
  • Invalid bundle structure: Verify with pkgutil --check-signature

AU Validation

# Validate AU (required for App Store distribution)
auval -v aufx Plug Manu

# Output should end with "PASSED"

Fix common AU validation errors:

  • "Could not open component": Check bundle ID and AU type
  • "Plugin crash": Debug in Xcode, check for exceptions in initialization
  • "Latency reporting": Implement getTailLengthSeconds() correctly

3. Windows Builds

Prerequisites

  1. Visual Studio 2022 (Community, Professional, or Enterprise)

    • Install "Desktop development with C++" workload
    • Includes Windows 10 SDK
  2. CMake (3.22+)

    # Via Chocolatey
    choco install cmake
    
    # Or download from cmake.org
    
  3. Code Signing Certificate (optional, for distribution)

    • EV or standard code signing certificate
    • From vendors: DigiCert, Sectigo, GlobalSign

Building

# Configure for Visual Studio 2022
cmake -B build-win -G "Visual Studio 17 2022" -A x64

# Build Release
cmake --build build-win --config Release --parallel

# Or open in Visual Studio
start build-win/MyPlugin.sln

MSVC Runtime Linking

Static Runtime (recommended for plugins):

# Statically link MSVC runtime (no DLL dependencies)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

Dynamic Runtime (smaller binary, requires MSVC redistributable):

set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")

Code Signing

Manual Signing with signtool

# Sign with PFX file
signtool sign /f certificate.pfx /p <password> `
              /tr http://timestamp.digicert.com `
              /td sha256 /fd sha256 `
              MyPlugin.vst3

# Sign with certificate store
signtool sign /n "Your Company Name" `
              /tr http://timestamp.digicert.com `
              /td sha256 /fd sha256 `
              MyPlugin.vst3

# Verify signature
signtool verify /pa /v MyPlugin.vst3

Automated Signing in CMake

if(WIN32 AND CMAKE_BUILD_TYPE STREQUAL "Release")
    find_program(SIGNTOOL_EXECUTABLE signtool
        PATHS "C:/Program Files (x86)/Windows Kits/10/bin/*/x64"
    )

    if(SIGNTOOL_EXECUTABLE)
        add_custom_command(TARGET MyPlugin POST_BUILD
            COMMAND ${SIGNTOOL_EXECUTABLE} sign
                    /f "${CMAKE_SOURCE_DIR}/certificate.pfx"
                    /p "$ENV{CERT_PASSWORD}"
                    /tr http://timestamp.digicert.com
                    /td sha256 /fd sha256
                    $<TARGET_FILE:MyPlugin>
            COMMENT "Code signing ${TARGET}"
        )
    endif()
endif()

Visual Studio Configuration

Optimization Settings

if(MSVC)
    # Enable whole program optimization (Release)
    target_compile_options(MyPlugin PRIVATE
        $<$<CONFIG:Release>:/GL>  # Whole program optimization
        /MP                        # Multi-processor compilation
    )

    target_link_options(MyPlugin PRIVATE
        $<$<CONFIG:Release>:/LTCG>  # Link-time code generation
    )
endif()

Suppress Warnings

target_compile_definitions(MyPlugin PRIVATE
    _CRT_SECURE_NO_WARNINGS      # Disable CRT security warnings
    NOMINMAX                     # Prevent min/max macros
)

4. Linux Builds

Prerequisites

Ubuntu/Debian:

sudo apt-get update
sudo apt-get install -y \
    build-essential \
    cmake \
    libasound2-dev \
    libjack-jackd2-dev \
    libfreetype6-dev \
    libx11-dev \
    libxrandr-dev \
    libxinerama-dev \
    libxcursor-dev \
    libgl1-mesa-dev \
    libcurl4-openssl-dev

Fedora/RHEL:

sudo dnf install -y \
    gcc-c++ \
    cmake \
    alsa-lib-devel \
    jack-audio-connection-kit-devel \
    freetype-devel \
    libX11-devel \
    libXrandr-devel \
    libXinerama-devel \
    libXcursor-devel \
    mesa-libGL-devel \
    libcurl-devel

Building

# Configure
cmake -B build-linux -DCMAKE_BUILD_TYPE=Release

# Build
cmake --build build-linux --config Release --parallel

# Install to system (optional)
sudo cmake --install build-linux

Packaging

Create .tar.gz

tar -czf MyPlugin-1.0.0-Linux-x86_64.tar.gz \
    -C build-linux/MyPlugin_artefacts/Release/VST3 \
    MyPlugin.vst3

Create .deb Package

# Install packaging tools
sudo apt-get install checkinstall

# Create .deb
sudo checkinstall \
    --pkgname=myplugin \
    --pkgversion=1.0.0 \
    --pkgrelease=1 \
    --pkggroup=sound \
    --maintainer="you@example.com" \
    cmake --install build-linux

5. AAX Format (Pro Tools)

Prerequisites

  1. AAX SDK (requires iLok account)

  2. PACE Licensing (for distribution)

    • Create account at paceap.com
    • Use PACE Eden for signing (replaces codesign for AAX)

CMake Configuration

# Set AAX SDK path
juce_set_aax_sdk_path("${CMAKE_CURRENT_SOURCE_DIR}/SDKs/AAX")

# Add AAX to plugin formats
set(PLUGIN_FORMATS VST3 AU AAX Standalone)

Building AAX

# macOS
cmake -B build-mac -DAAX_SDK_PATH=SDKs/AAX
cmake --build build-mac --config Release

# Windows
cmake -B build-win -DAAX_SDK_PATH=SDKs/AAX
cmake --build build-win --config Release

AAX Signing with PACE Eden

AAX plugins must be signed with PACE Eden (not regular codesign).

# Sign AAX (macOS/Windows)
wraptool sign \
    --account <your-pace-account> \
    --password <password> \
    --signid <signid> \
    --in MyPlugin.aaxplugin \
    --out MyPlugin-signed.aaxplugin

# Verify
wraptool verify --verbose MyPlugin-signed.aaxplugin

Note: Keep AAX signing credentials secure. Never commit to version control.


6. Continuous Integration

GitHub Actions Workflow

.github/workflows/build.yml:

name: Build Plugin

on: [push, pull_request]

jobs:
  build:
    name: ${{ matrix.name }}
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: macOS
            os: macos-latest
            cmake_args: -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64"

          - name: Windows
            os: windows-latest
            cmake_args: -G "Visual Studio 17 2022" -A x64

          - name: Linux
            os: ubuntu-latest
            cmake_args: ""

    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          submodules: recursive

      - name: Install Linux dependencies
        if: runner.os == 'Linux'
        run: |
          sudo apt-get update
          sudo apt-get install -y libasound2-dev libjack-jackd2-dev \
              libfreetype6-dev libx11-dev libxrandr-dev libxinerama-dev \
              libxcursor-dev libgl1-mesa-dev

      - name: Configure
        run: cmake -B build ${{ matrix.cmake_args }} -DCMAKE_BUILD_TYPE=Release

      - name: Build
        run: cmake --build build --config Release --parallel

      - name: Test
        run: ctest --test-dir build -C Release --output-on-failure

      - name: Upload Artifacts
        uses: actions/upload-artifact@v3
        with:
          name: ${{ matrix.name }}
          path: |
            build/*_artefacts/Release/VST3/*.vst3
            build/*_artefacts/Release/AU/*.component

Secrets for Code Signing

Store signing credentials in GitHub Secrets:

  1. Go to repository Settings → Secrets → Actions
  2. Add secrets:
    • MACOS_CERTIFICATE_BASE64: Base64-encoded .p12 file
    • MACOS_CERTIFICATE_PASSWORD: Certificate password
    • APPLE_ID: Apple ID for notarization
    • APPLE_TEAM_ID: Developer team ID
    • APPLE_APP_PASSWORD: App-specific password
    • WINDOWS_CERTIFICATE_BASE64: Base64-encoded .pfx file
    • WINDOWS_CERTIFICATE_PASSWORD: Certificate password

Automated Code Signing in CI

macOS:

- name: Import Certificate
  env:
    CERTIFICATE_BASE64: ${{ secrets.MACOS_CERTIFICATE_BASE64 }}
    CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
  run: |
    echo $CERTIFICATE_BASE64 | base64 --decode > certificate.p12
    security create-keychain -p temp build.keychain
    security import certificate.p12 -k build.keychain -P $CERTIFICATE_PASSWORD -T /usr/bin/codesign
    security set-keychain-settings -lut 21600 build.keychain
    security unlock-keychain -p temp build.keychain
    security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k temp build.keychain

- name: Sign and Notarize
  env:
    APPLE_ID: ${{ secrets.APPLE_ID }}
    APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
    APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
  run: |
    codesign --force --sign "Developer ID Application" --options runtime MyPlugin.vst3
    xcrun notarytool submit MyPlugin.vst3.zip --apple-id $APPLE_ID --team-id $APPLE_TEAM_ID --password $APPLE_APP_PASSWORD --wait
    xcrun stapler staple MyPlugin.vst3

Windows:

- name: Import Certificate
  env:
    CERTIFICATE_BASE64: ${{ secrets.WINDOWS_CERTIFICATE_BASE64 }}
    CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
  run: |
    [System.Convert]::FromBase64String($env:CERTIFICATE_BASE64) | Set-Content -Path certificate.pfx -Encoding Byte
    certutil -importpfx -p $env:CERTIFICATE_PASSWORD certificate.pfx

- name: Sign Binary
  run: |
    signtool sign /f certificate.pfx /p $env:CERTIFICATE_PASSWORD /tr http://timestamp.digicert.com /td sha256 /fd sha256 MyPlugin.vst3

7. Reproducible Builds

Deterministic Builds

Ensure builds are reproducible across machines:

  1. Pin JUCE version (use git submodule or specific release)

    git submodule add https://github.com/juce-framework/JUCE.git
    cd JUCE && git checkout 7.0.9
    
  2. Lock dependency versions (CMake FetchContent)

    FetchContent_Declare(
        googletest
        GIT_REPOSITORY https://github.com/google/googletest.git
        GIT_TAG v1.14.0  # Specific version
    )
    
  3. Document toolchain versions (README.md)

    Build Requirements:
    - CMake 3.22+
    - JUCE 7.0.9
    - macOS: Xcode 14.3+
    - Windows: Visual Studio 2022
    - Linux: GCC 11+ or Clang 14+
    
  4. Disable timestamp embedding

    # Remove __DATE__ and __TIME__ macros
    target_compile_definitions(MyPlugin PRIVATE
        NO_BUILD_TIMESTAMP=1
    )
    

Build Verification

Generate checksums for reproducibility:

# macOS/Linux
shasum -a 256 MyPlugin.vst3 > checksums.txt

# Windows
certutil -hashfile MyPlugin.vst3 SHA256 >> checksums.txt

8. Troubleshooting

Common Build Errors

"JUCE modules not found"

Solution:
git submodule update --init --recursive

"Symbol not found" (macOS)

Solution:
- Check deployment target matches minimum system requirement
- Verify all symbols are available in target SDK
- Use `nm` to inspect missing symbols:
  nm -gU MyPlugin.vst3/Contents/MacOS/MyPlugin | grep <symbol>

"Unresolved external symbol" (Windows)

Solution:
- Ensure all .cpp files are in CMakeLists.txt
- Check library linking order
- Verify static/dynamic runtime consistency (/MT vs /MD)

"Undefined reference" (Linux)

Solution:
- Install missing libraries (libasound2-dev, etc.)
- Add libraries to target_link_libraries()
- Check pkg-config: pkg-config --libs alsa

Plugin Doesn't Load in DAW

macOS:

  1. Check signing: codesign --verify --deep --strict MyPlugin.vst3
  2. Verify notarization: spctl -a -vvv -t install MyPlugin.vst3
  3. Check Gatekeeper: xattr -l MyPlugin.vst3 (remove quarantine if needed)
  4. AU validation: auval -v aufx Plug Manu

Windows:

  1. Check dependencies: Use Dependency Walker
  2. Verify signature: signtool verify /pa MyPlugin.vst3
  3. Check registry (for VST3): Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\VST3

Linux:

  1. Check shared library dependencies: ldd MyPlugin.vst3
  2. Verify VST3 path: ~/.vst3/ or /usr/lib/vst3/
  3. Check permissions: chmod 755 MyPlugin.vst3

9. Best Practices

Version Management

project(MyPlugin VERSION 1.2.3)

# Access in code
target_compile_definitions(MyPlugin PRIVATE
    PLUGIN_VERSION="${CMAKE_PROJECT_VERSION}"
)

Conditional Compilation

#if JUCE_MAC
    // macOS-specific code
#elif JUCE_WINDOWS
    // Windows-specific code
#elif JUCE_LINUX
    // Linux-specific code
#endif

#if JUCE_DEBUG
    // Debug-only code
#endif

Minimize Plugin Size

  • Strip symbols in Release builds
  • Enable LTO (link-time optimization)
  • Remove unused JUCE modules
  • Compress resources (images, fonts)

Cross-Platform File Paths

// Use JUCE File class for portability
juce::File presetFolder = juce::File::getSpecialLocation(
    juce::File::userApplicationDataDirectory
).getChildFile("MyPlugin").getChildFile("Presets");

// Not hardcoded paths like:
// "C:\\Users\\...\\Presets"  ❌

Summary

Key Takeaways:

  1. Use CMake for cross-platform builds - single configuration for all platforms
  2. Code signing is essential for distribution (macOS requires notarization)
  3. Test on all platforms - behavior can differ (especially AU vs VST3)
  4. Automate in CI/CD - GitHub Actions, GitLab CI, or Jenkins
  5. Reproducible builds - pin dependency versions, document toolchain

Platform Checklist:

  • macOS: Universal binary (arm64 + x86_64)
  • macOS: Code signed with Developer ID
  • macOS: Notarized (10.15+ requirement)
  • macOS: AU validation passes (auval)
  • Windows: Code signed (recommended)
  • Windows: Static runtime linked (/MT)
  • Linux: Dependencies documented
  • All: Tested in major DAWs on each platform

Related Resources:

  • /release-build command - Automated release workflow
  • BUILD_GUIDE.md - Detailed build procedures
  • RELEASE_CHECKLIST.md - Pre-release validation steps
  • @build-engineer - CI/CD and build automation expert