From dbeb158b4b9d4a99a2355d9bd076d4b57c392b2e Mon Sep 17 00:00:00 2001 From: Oli Larkin Date: Fri, 2 Aug 2024 00:23:51 +0200 Subject: [PATCH] Add CMake scripts --- .claude/skills/build-cmake/SKILL.md | 175 +++++++ .github/workflows/build-cmake.yml | 720 ++++++++++++++++++++++++++++ .vscode/settings.json | 4 +- CMakeLists.txt | 9 + CMakePresets.json | 254 ++++++++++ TemplateProject/CMakeLists.txt | 18 + iPlug2 | 2 +- 7 files changed, 1180 insertions(+), 2 deletions(-) create mode 100644 .claude/skills/build-cmake/SKILL.md create mode 100644 .github/workflows/build-cmake.yml create mode 100644 CMakeLists.txt create mode 100644 CMakePresets.json create mode 100644 TemplateProject/CMakeLists.txt diff --git a/.claude/skills/build-cmake/SKILL.md b/.claude/skills/build-cmake/SKILL.md new file mode 100644 index 00000000..1ba9bb53 --- /dev/null +++ b/.claude/skills/build-cmake/SKILL.md @@ -0,0 +1,175 @@ +--- +name: build-cmake +description: Build an iPlug2 plugin project using CMake (Ninja or Xcode generator) +--- + +# Build iPlug2 Plugin with CMake + +Use this skill when the user wants to build their plugin project using CMake. + +## Workflow + +1. **Identify the project:** + - Look for `CMakeLists.txt` in project directories + +2. **Choose a preset** based on platform and build requirements + +## Using CMake Presets + +The project uses CMake presets for standardized builds. Prefer `--preset` instead of manual `-G` flags. + +### List Available Presets + +```bash +cmake --list-presets +``` + +### macOS Builds + +```bash +# Configure with Ninja (fast builds) +cmake --preset macos-ninja -S [ProjectName] + +# Build +cmake --build build/macos-ninja --target [ProjectName]-app + +# Or with Xcode (for debugging) +cmake --preset macos-xcode -S [ProjectName] +cmake --build build/macos-xcode --config Release --target [ProjectName]-app + +# Universal binary (arm64 + x86_64) +cmake --preset macos-xcode-universal -S [ProjectName] +cmake --build build/macos-xcode-universal --config Release +``` + +### iOS Builds + +```bash +# iOS Device +cmake --preset ios-xcode -S [ProjectName] +cmake --build build/ios-xcode --config Release + +# iOS Simulator +cmake --preset ios-sim-xcode -S [ProjectName] +cmake --build build/ios-sim-xcode --config Release +``` + +For running in Simulator, use the `run-ios-simulator` skill. + +### visionOS Builds + +```bash +# visionOS Device +cmake --preset visionos-xcode -S [ProjectName] +cmake --build build/visionos-xcode --config Release + +# visionOS Simulator +cmake --preset visionos-sim-xcode -S [ProjectName] +cmake --build build/visionos-sim-xcode --config Release +``` + +### Windows Builds + +```bash +# Visual Studio 2022 (x64) +cmake --preset windows-vs2022 -S [ProjectName] +cmake --build build/windows-vs2022 --config Release + +# ARM64EC +cmake --preset windows-vs2022-arm64ec -S [ProjectName] +cmake --build build/windows-vs2022-arm64ec --config Release +``` + +### Web/WAM Build (Emscripten) + +```bash +# Configure (requires EMSDK environment) +cmake --preset wam -S [ProjectName] + +# Build +cmake --build build/wam --target [ProjectName]-wam + +# Create distribution +cmake --build build/wam --target [ProjectName]-wam-dist +``` + +Output in `build/wam/out/[ProjectName]-wam/` + +## Available Configure Presets + +| Preset | Platform | Generator | Description | +|--------|----------|-----------|-------------| +| `macos-ninja` | macOS | Ninja | Fast command-line builds (NanoVG/Metal) | +| `macos-make` | macOS | Make | Unix Makefiles (NanoVG/Metal) | +| `macos-xcode` | macOS | Xcode | IDE builds with debugging | +| `macos-xcode-universal` | macOS | Xcode | Universal binary (arm64+x86_64) | +| `ios-xcode` | iOS | Xcode | iOS device builds | +| `ios-sim-xcode` | iOS | Xcode | iOS Simulator builds | +| `visionos-xcode` | visionOS | Xcode | visionOS device builds | +| `visionos-sim-xcode` | visionOS | Xcode | visionOS Simulator builds | +| `windows-ninja` | Windows | Ninja | Fast Windows command-line builds | +| `windows-vs2022` | Windows | VS2022 | Windows x64 builds | +| `windows-vs2022-arm64ec` | Windows | VS2022 | Windows ARM64EC builds | +| `wam` | Web | Ninja | Emscripten/WebAssembly builds | + +## Available Targets + +- `[ProjectName]-app` - Standalone application +- `[ProjectName]-vst3` - VST3 plugin +- `[ProjectName]-au` - Audio Unit (AUv2) +- `[ProjectName]-clap` - CLAP plugin +- `[ProjectName]AU-framework` - AUv3 framework +- `[ProjectName]AUv3-appex` - AUv3 app extension +- `[ProjectName]-ios-app` - iOS standalone app +- `[ProjectName]-wam` - Web Audio Module + +## Graphics Backend and Renderer + +Default configuration uses NanoVG with Metal (macOS/iOS) or GL2 (Windows). + +To use Skia backend, add cache variables: + +```bash +cmake --preset macos-ninja -S [ProjectName] \ + -DIGRAPHICS_BACKEND=SKIA \ + -DIGRAPHICS_RENDERER=METAL +``` + +Valid combinations: +- **NanoVG**: GL2, GL3, METAL +- **Skia**: GL3, METAL, CPU + +**Note:** Skia requires prebuilt libraries: +```bash +./iPlug2/Dependencies/download-prebuilt-libs.sh mac +``` + +## Build Locations (symlinked on macOS) + +- APP: `~/Applications/[ProjectName].app` +- VST3: `~/Library/Audio/Plug-Ins/VST3/` +- AU: `~/Library/Audio/Plug-Ins/Components/` +- CLAP: `~/Library/Audio/Plug-Ins/CLAP/` + +## Clean Build + +```bash +# Remove build directory and reconfigure +rm -rf build/macos-ninja +cmake --preset macos-ninja -S [ProjectName] +``` + +## Example + +```bash +# Quick build of standalone app +cmake --preset macos-ninja -S MySynth +cmake --build build/macos-ninja --target MySynth-app + +# Open the built app +open ~/Applications/MySynth.app + +# Build for iOS Simulator +cmake --preset ios-sim-xcode -S MySynth +cmake --build build/ios-sim-xcode --config Release +``` diff --git a/.github/workflows/build-cmake.yml b/.github/workflows/build-cmake.yml new file mode 100644 index 00000000..78879778 --- /dev/null +++ b/.github/workflows/build-cmake.yml @@ -0,0 +1,720 @@ +name: Build CMake + +on: + push: + paths: + - 'iPlug2/Scripts/cmake/**' + - 'iPlug2/iPlug2.cmake' + - '**/CMakeLists.txt' + - 'CMakePresets.json' + - '.github/workflows/build-cmake.yml' + pull_request: + paths: + - 'iPlug2/Scripts/cmake/**' + - 'iPlug2/iPlug2.cmake' + - '**/CMakeLists.txt' + - 'CMakePresets.json' + issue_comment: + types: [created] + workflow_dispatch: + inputs: + all_generators: + description: 'Test all generators (Ninja, Make)' + type: boolean + default: false + ios: + description: 'Include iOS build' + type: boolean + default: false + wam: + description: 'Include WAM/Emscripten build' + type: boolean + default: false + universal: + description: 'Include macOS Universal build (arm64+x86_64)' + type: boolean + default: false + backends: + description: 'Include IGraphics backends matrix' + type: boolean + default: false + arm64ec: + description: 'Include Windows ARM64EC build' + type: boolean + default: false + +# Cancel in-progress runs for the same PR/branch +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + PROJECT_NAME: TemplateProject + +jobs: + # ============================================================================ + # Parse PR commands from comments + # ============================================================================ + parse-commands: + name: Parse Commands + runs-on: ubuntu-latest + if: >- + github.event_name != 'issue_comment' || + (github.event.issue.pull_request && + startsWith(github.event.comment.body, '/ci')) + outputs: + all_generators: ${{ steps.parse.outputs.all_generators }} + ios: ${{ steps.parse.outputs.ios }} + wam: ${{ steps.parse.outputs.wam }} + universal: ${{ steps.parse.outputs.universal }} + backends: ${{ steps.parse.outputs.backends }} + arm64ec: ${{ steps.parse.outputs.arm64ec }} + should_run: ${{ steps.parse.outputs.should_run }} + pr_ref: ${{ steps.get-pr.outputs.ref }} + pr_sha: ${{ steps.get-pr.outputs.sha }} + steps: + - name: Parse CI commands from comment + id: parse + env: + COMMENT_BODY: ${{ github.event.comment.body }} + run: | + if [[ "${{ github.event_name }}" == "issue_comment" ]]; then + COMMENT=$(echo "$COMMENT_BODY" | tr -cd '[:alnum:][:space:]/=,_-') + echo "Parsing comment: $COMMENT" + + if [[ "$COMMENT" == *"/ci all"* ]]; then + echo "all_generators=true" >> $GITHUB_OUTPUT + echo "ios=true" >> $GITHUB_OUTPUT + echo "wam=true" >> $GITHUB_OUTPUT + echo "universal=true" >> $GITHUB_OUTPUT + echo "backends=true" >> $GITHUB_OUTPUT + echo "arm64ec=true" >> $GITHUB_OUTPUT + else + [[ "$COMMENT" == *"/ci all-generators"* || "$COMMENT" == *"/ci generators"* ]] && echo "all_generators=true" >> $GITHUB_OUTPUT || echo "all_generators=false" >> $GITHUB_OUTPUT + [[ "$COMMENT" == *"/ci ios"* ]] && echo "ios=true" >> $GITHUB_OUTPUT || echo "ios=false" >> $GITHUB_OUTPUT + [[ "$COMMENT" == *"/ci wam"* ]] && echo "wam=true" >> $GITHUB_OUTPUT || echo "wam=false" >> $GITHUB_OUTPUT + [[ "$COMMENT" == *"/ci universal"* ]] && echo "universal=true" >> $GITHUB_OUTPUT || echo "universal=false" >> $GITHUB_OUTPUT + [[ "$COMMENT" == *"/ci backends"* ]] && echo "backends=true" >> $GITHUB_OUTPUT || echo "backends=false" >> $GITHUB_OUTPUT + [[ "$COMMENT" == *"/ci arm64ec"* ]] && echo "arm64ec=true" >> $GITHUB_OUTPUT || echo "arm64ec=false" >> $GITHUB_OUTPUT + fi + echo "should_run=true" >> $GITHUB_OUTPUT + elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + echo "all_generators=${{ inputs.all_generators }}" >> $GITHUB_OUTPUT + echo "ios=${{ inputs.ios }}" >> $GITHUB_OUTPUT + echo "wam=${{ inputs.wam }}" >> $GITHUB_OUTPUT + echo "universal=${{ inputs.universal }}" >> $GITHUB_OUTPUT + echo "backends=${{ inputs.backends }}" >> $GITHUB_OUTPUT + echo "arm64ec=${{ inputs.arm64ec }}" >> $GITHUB_OUTPUT + echo "should_run=true" >> $GITHUB_OUTPUT + else + # push or pull_request - use defaults + echo "all_generators=false" >> $GITHUB_OUTPUT + echo "ios=false" >> $GITHUB_OUTPUT + echo "wam=false" >> $GITHUB_OUTPUT + echo "universal=false" >> $GITHUB_OUTPUT + echo "backends=false" >> $GITHUB_OUTPUT + echo "arm64ec=false" >> $GITHUB_OUTPUT + echo "should_run=true" >> $GITHUB_OUTPUT + fi + + - name: Get PR ref for comment trigger + id: get-pr + if: github.event_name == 'issue_comment' + env: + GH_TOKEN: ${{ github.token }} + run: | + PR_DATA=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.issue.number }}) + echo "ref=$(echo $PR_DATA | jq -r .head.ref)" >> $GITHUB_OUTPUT + echo "sha=$(echo $PR_DATA | jq -r .head.sha)" >> $GITHUB_OUTPUT + + # ========================================================================== + # macOS - Xcode Generator (Default) + # ========================================================================== + macos-xcode: + name: macOS (Xcode) + needs: parse-commands + if: needs.parse-commands.outputs.should_run == 'true' + runs-on: macos-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ needs.parse-commands.outputs.pr_sha || github.sha }} + submodules: recursive + + - name: Cache IPlug SDKs + id: cache-sdks + uses: actions/cache@v4 + with: + path: | + iPlug2/Dependencies/IPlug/VST3_SDK + iPlug2/Dependencies/IPlug/CLAP_SDK + iPlug2/Dependencies/IPlug/CLAP_HELPERS + key: iplug-sdks-${{ hashFiles('iPlug2/Dependencies/IPlug/download-iplug-sdks.sh') }} + + - name: Get SDKs + if: steps.cache-sdks.outputs.cache-hit != 'true' + run: | + cd iPlug2/Dependencies/IPlug + ./download-iplug-sdks.sh + + - name: CMake Configure + run: cmake --preset=macos-xcode + + - name: Build + run: cmake --build --preset=macos-xcode + + - name: Verify Bundles + run: | + test -d build/macos-xcode/out/Release/${{env.PROJECT_NAME}}.app + test -d build/macos-xcode/out/Release/${{env.PROJECT_NAME}}.vst3 + test -d build/macos-xcode/out/Release/${{env.PROJECT_NAME}}.clap + test -d build/macos-xcode/out/Release/${{env.PROJECT_NAME}}.component + echo "All bundles exist" + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: macos-xcode-artifacts + path: build/macos-xcode/out/ + if-no-files-found: warn + + # ========================================================================== + # Windows - Visual Studio 2022 (Default) + # ========================================================================== + windows-vs2022: + name: Windows (VS2022) + needs: parse-commands + if: needs.parse-commands.outputs.should_run == 'true' + runs-on: windows-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ needs.parse-commands.outputs.pr_sha || github.sha }} + submodules: recursive + + - name: Cache IPlug SDKs + id: cache-sdks + uses: actions/cache@v4 + with: + path: | + iPlug2/Dependencies/IPlug/VST3_SDK + iPlug2/Dependencies/IPlug/CLAP_SDK + iPlug2/Dependencies/IPlug/CLAP_HELPERS + key: iplug-sdks-${{ hashFiles('iPlug2/Dependencies/IPlug/download-iplug-sdks.sh') }} + + - name: Get SDKs + if: steps.cache-sdks.outputs.cache-hit != 'true' + shell: bash + run: | + cd iPlug2/Dependencies/IPlug + ./download-iplug-sdks.sh + + - name: CMake Configure + run: cmake --preset=windows-vs2022 + + - name: Build + run: cmake --build --preset=windows-vs2022 + + - name: Verify Bundles + shell: pwsh + run: | + if (!(Test-Path "build\windows-vs2022\out\${{env.PROJECT_NAME}}.exe")) { exit 1 } + if (!(Test-Path "build\windows-vs2022\out\${{env.PROJECT_NAME}}.vst3")) { exit 1 } + if (!(Test-Path "build\windows-vs2022\out\${{env.PROJECT_NAME}}.clap")) { exit 1 } + echo "All bundles exist" + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: windows-vs2022-artifacts + path: build/windows-vs2022/out/ + if-no-files-found: warn + + # ========================================================================== + # Windows - Visual Studio 2022 ARM64EC - Optional: /ci arm64ec + # ========================================================================== + windows-arm64ec: + name: Windows (ARM64EC) + needs: parse-commands + if: needs.parse-commands.outputs.arm64ec == 'true' + runs-on: windows-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ needs.parse-commands.outputs.pr_sha || github.sha }} + submodules: recursive + + - name: Cache IPlug SDKs + id: cache-sdks + uses: actions/cache@v4 + with: + path: | + iPlug2/Dependencies/IPlug/VST3_SDK + iPlug2/Dependencies/IPlug/CLAP_SDK + iPlug2/Dependencies/IPlug/CLAP_HELPERS + key: iplug-sdks-${{ hashFiles('iPlug2/Dependencies/IPlug/download-iplug-sdks.sh') }} + + - name: Get SDKs + if: steps.cache-sdks.outputs.cache-hit != 'true' + shell: bash + run: | + cd iPlug2/Dependencies/IPlug + ./download-iplug-sdks.sh + + - name: CMake Configure + run: cmake --preset=windows-vs2022-arm64ec + + - name: Build + run: cmake --build --preset=windows-vs2022-arm64ec + + - name: Verify Bundles + shell: pwsh + run: | + if (!(Test-Path "build\windows-vs2022-arm64ec\out\${{env.PROJECT_NAME}}.exe")) { exit 1 } + if (!(Test-Path "build\windows-vs2022-arm64ec\out\${{env.PROJECT_NAME}}.vst3")) { exit 1 } + if (!(Test-Path "build\windows-vs2022-arm64ec\out\${{env.PROJECT_NAME}}.clap")) { exit 1 } + echo "All bundles exist" + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: windows-arm64ec-artifacts + path: build/windows-vs2022-arm64ec/out/ + if-no-files-found: warn + + # ========================================================================== + # macOS - Xcode Generator (Universal) - Optional: /ci universal + # ========================================================================== + macos-xcode-universal: + name: macOS (Universal) + needs: parse-commands + if: needs.parse-commands.outputs.universal == 'true' + runs-on: macos-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ needs.parse-commands.outputs.pr_sha || github.sha }} + submodules: recursive + + - name: Cache IPlug SDKs + id: cache-sdks + uses: actions/cache@v4 + with: + path: | + iPlug2/Dependencies/IPlug/VST3_SDK + iPlug2/Dependencies/IPlug/CLAP_SDK + iPlug2/Dependencies/IPlug/CLAP_HELPERS + key: iplug-sdks-${{ hashFiles('iPlug2/Dependencies/IPlug/download-iplug-sdks.sh') }} + + - name: Get SDKs + if: steps.cache-sdks.outputs.cache-hit != 'true' + run: | + cd iPlug2/Dependencies/IPlug + ./download-iplug-sdks.sh + + - name: CMake Configure + run: cmake --preset=macos-xcode-universal + + - name: Build + run: cmake --build --preset=macos-xcode-universal + + - name: Verify Universal Binaries + run: | + APP_EXEC="build/macos-xcode-universal/out/Release/${{env.PROJECT_NAME}}.app/Contents/MacOS/${{env.PROJECT_NAME}}" + ARCHS=$(lipo -archs "$APP_EXEC") + echo "APP architectures: $ARCHS" + [[ "$ARCHS" == *"arm64"* ]] && [[ "$ARCHS" == *"x86_64"* ]] || exit 1 + echo "Universal binary verified" + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: macos-universal-artifacts + path: build/macos-xcode-universal/out/ + if-no-files-found: warn + + # ========================================================================== + # macOS - Ninja Generator - Optional: /ci all-generators + # ========================================================================== + macos-ninja: + name: macOS (Ninja) + needs: parse-commands + if: needs.parse-commands.outputs.all_generators == 'true' + runs-on: macos-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ needs.parse-commands.outputs.pr_sha || github.sha }} + submodules: recursive + + - name: Install Ninja + run: brew install ninja + + - name: Cache IPlug SDKs + id: cache-sdks + uses: actions/cache@v4 + with: + path: | + iPlug2/Dependencies/IPlug/VST3_SDK + iPlug2/Dependencies/IPlug/CLAP_SDK + iPlug2/Dependencies/IPlug/CLAP_HELPERS + key: iplug-sdks-${{ hashFiles('iPlug2/Dependencies/IPlug/download-iplug-sdks.sh') }} + + - name: Get SDKs + if: steps.cache-sdks.outputs.cache-hit != 'true' + run: | + cd iPlug2/Dependencies/IPlug + ./download-iplug-sdks.sh + + - name: CMake Configure + run: cmake --preset=macos-ninja + + - name: Build + run: cmake --build --preset=macos-ninja + + - name: Verify Bundles + run: | + test -d build/macos-ninja/out/${{env.PROJECT_NAME}}.app + test -d build/macos-ninja/out/${{env.PROJECT_NAME}}.vst3 + test -d build/macos-ninja/out/${{env.PROJECT_NAME}}.clap + test -d build/macos-ninja/out/${{env.PROJECT_NAME}}.component + echo "All bundles exist" + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: macos-ninja-artifacts + path: build/macos-ninja/out/ + if-no-files-found: warn + + # ========================================================================== + # macOS - Unix Makefiles Generator - Optional: /ci all-generators + # ========================================================================== + macos-make: + name: macOS (Make) + needs: parse-commands + if: needs.parse-commands.outputs.all_generators == 'true' + runs-on: macos-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ needs.parse-commands.outputs.pr_sha || github.sha }} + submodules: recursive + + - name: Cache IPlug SDKs + id: cache-sdks + uses: actions/cache@v4 + with: + path: | + iPlug2/Dependencies/IPlug/VST3_SDK + iPlug2/Dependencies/IPlug/CLAP_SDK + iPlug2/Dependencies/IPlug/CLAP_HELPERS + key: iplug-sdks-${{ hashFiles('iPlug2/Dependencies/IPlug/download-iplug-sdks.sh') }} + + - name: Get SDKs + if: steps.cache-sdks.outputs.cache-hit != 'true' + run: | + cd iPlug2/Dependencies/IPlug + ./download-iplug-sdks.sh + + - name: CMake Configure + run: cmake --preset=macos-make + + - name: Build + run: cmake --build --preset=macos-make -- -j$(sysctl -n hw.ncpu) + + - name: Verify Bundles + run: | + test -d build/macos-make/out/${{env.PROJECT_NAME}}.app + test -d build/macos-make/out/${{env.PROJECT_NAME}}.vst3 + test -d build/macos-make/out/${{env.PROJECT_NAME}}.clap + test -d build/macos-make/out/${{env.PROJECT_NAME}}.component + echo "All bundles exist" + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: macos-make-artifacts + path: build/macos-make/out/ + if-no-files-found: warn + + # ========================================================================== + # macOS - IGraphics Backends Matrix - Optional: /ci backends + # ========================================================================== + macos-backends: + name: macOS ${{ matrix.backend }}/${{ matrix.renderer }} + needs: parse-commands + if: needs.parse-commands.outputs.backends == 'true' + runs-on: macos-latest + strategy: + fail-fast: false + matrix: + include: + - backend: NANOVG + renderer: GL3 + needs_skia: false + - backend: SKIA + renderer: METAL + needs_skia: true + - backend: SKIA + renderer: GL3 + needs_skia: true + - backend: SKIA + renderer: CPU + needs_skia: true + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ needs.parse-commands.outputs.pr_sha || github.sha }} + submodules: recursive + + - name: Install Ninja + run: brew install ninja + + - name: Cache IPlug SDKs + id: cache-sdks + uses: actions/cache@v4 + with: + path: | + iPlug2/Dependencies/IPlug/VST3_SDK + iPlug2/Dependencies/IPlug/CLAP_SDK + iPlug2/Dependencies/IPlug/CLAP_HELPERS + key: iplug-sdks-${{ hashFiles('iPlug2/Dependencies/IPlug/download-iplug-sdks.sh') }} + + - name: Get SDKs + if: steps.cache-sdks.outputs.cache-hit != 'true' + run: | + cd iPlug2/Dependencies/IPlug + ./download-iplug-sdks.sh + + - name: Cache Skia Prebuilt Libs + if: matrix.needs_skia + id: cache-skia + uses: actions/cache@v4 + with: + path: | + iPlug2/Dependencies/Build/mac + iPlug2/Dependencies/Build/src/skia + key: skia-prebuilt-mac-${{ hashFiles('iPlug2/Dependencies/download-prebuilt-libs.sh') }} + + - name: Get Skia Prebuilt Libs + if: matrix.needs_skia && steps.cache-skia.outputs.cache-hit != 'true' + run: | + cd iPlug2/Dependencies + ./download-prebuilt-libs.sh mac + + - name: CMake Configure + run: | + cmake --preset=macos-ninja \ + -DIGRAPHICS_BACKEND=${{ matrix.backend }} \ + -DIGRAPHICS_RENDERER=${{ matrix.renderer }} + + - name: Build + run: ninja -C build/macos-ninja ${{env.PROJECT_NAME}}-app + + - name: Verify App Bundle + run: | + test -d build/macos-ninja/out/${{env.PROJECT_NAME}}.app + echo "${{ matrix.backend }}/${{ matrix.renderer }} build successful" + + # ========================================================================== + # Windows - IGraphics Backends Matrix - Optional: /ci backends + # ========================================================================== + windows-backends: + name: Windows ${{ matrix.backend }}/${{ matrix.renderer }} + needs: parse-commands + if: needs.parse-commands.outputs.backends == 'true' + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + include: + - backend: NANOVG + renderer: GL2 + needs_skia: false + - backend: NANOVG + renderer: GL3 + needs_skia: false + # Note: Skia only supports GL3, CPU on Windows (no GL2, no METAL) + - backend: SKIA + renderer: GL3 + needs_skia: true + - backend: SKIA + renderer: CPU + needs_skia: true + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ needs.parse-commands.outputs.pr_sha || github.sha }} + submodules: recursive + + - name: Cache IPlug SDKs + id: cache-sdks + uses: actions/cache@v4 + with: + path: | + iPlug2/Dependencies/IPlug/VST3_SDK + iPlug2/Dependencies/IPlug/CLAP_SDK + iPlug2/Dependencies/IPlug/CLAP_HELPERS + key: iplug-sdks-${{ hashFiles('iPlug2/Dependencies/IPlug/download-iplug-sdks.sh') }} + + - name: Get SDKs + if: steps.cache-sdks.outputs.cache-hit != 'true' + shell: bash + run: | + cd iPlug2/Dependencies/IPlug + ./download-iplug-sdks.sh + + - name: Cache Skia Prebuilt Libs + if: matrix.needs_skia + id: cache-skia + uses: actions/cache@v4 + with: + path: | + iPlug2/Dependencies/Build/win + iPlug2/Dependencies/Build/src/skia + key: skia-prebuilt-win-${{ hashFiles('iPlug2/Dependencies/download-prebuilt-libs.sh') }} + + - name: Get Skia Prebuilt Libs + if: matrix.needs_skia && steps.cache-skia.outputs.cache-hit != 'true' + shell: bash + run: | + cd iPlug2/Dependencies + ./download-prebuilt-libs.sh win + + - name: CMake Configure + run: | + cmake --preset=windows-vs2022 ` + -DIGRAPHICS_BACKEND=${{ matrix.backend }} ` + -DIGRAPHICS_RENDERER=${{ matrix.renderer }} + + - name: Build + run: cmake --build build/windows-vs2022 --config Release --target ${{env.PROJECT_NAME}}-app + + - name: Verify App + shell: pwsh + run: | + if (!(Test-Path "build\windows-vs2022\out\${{env.PROJECT_NAME}}.exe")) { exit 1 } + echo "${{ matrix.backend }}/${{ matrix.renderer }} build successful" + + # ========================================================================== + # macOS - iOS (Xcode) - Optional: /ci ios + # ========================================================================== + macos-ios: + name: iOS (Xcode) + needs: parse-commands + if: needs.parse-commands.outputs.ios == 'true' + runs-on: macos-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ needs.parse-commands.outputs.pr_sha || github.sha }} + submodules: recursive + + - name: Cache IPlug SDKs + id: cache-sdks + uses: actions/cache@v4 + with: + path: | + iPlug2/Dependencies/IPlug/VST3_SDK + iPlug2/Dependencies/IPlug/CLAP_SDK + iPlug2/Dependencies/IPlug/CLAP_HELPERS + key: iplug-sdks-${{ hashFiles('iPlug2/Dependencies/IPlug/download-iplug-sdks.sh') }} + + - name: Get SDKs + if: steps.cache-sdks.outputs.cache-hit != 'true' + run: | + cd iPlug2/Dependencies/IPlug + ./download-iplug-sdks.sh + + - name: CMake Configure + run: cmake --preset=ios-sim-xcode + + - name: Build (iOS Simulator) + run: cmake --build --preset=ios-sim-xcode + + - name: Verify iOS App + run: | + test -d "build/ios-sim-xcode/out/Release-iphonesimulator/${{env.PROJECT_NAME}}.app" + echo "iOS app bundle exists" + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: ios-artifacts + path: build/ios-sim-xcode/out/ + if-no-files-found: warn + + # ========================================================================== + # Emscripten - WAM Build - Optional: /ci wam + # ========================================================================== + emscripten-wam: + name: WAM (Emscripten) + needs: parse-commands + if: needs.parse-commands.outputs.wam == 'true' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ needs.parse-commands.outputs.pr_sha || github.sha }} + submodules: recursive + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Setup Emscripten + uses: mymindstorm/setup-emsdk@v14 + + - name: Patch emcc.py for iPlug2 EXPORT_NAME + # iPlug2 WAM modules use EXPORT_NAME values like "AWP_WAM_WASM_PluginName" which + # contain underscores that pass Emscripten's identifier validation. However, some + # project names with special characters may fail. This patch disables the strict + # identifier check. A cleaner solution would be to ensure EXPORT_NAME is always + # a valid JS identifier in the CMake configuration. + run: | + sed -i.bak 's/if not js_manipulation.isidentifier(settings.EXPORT_NAME):/if False:/g' $EMSDK/upstream/emscripten/emcc.py + + - name: Cache WAM SDK + id: cache-wam + uses: actions/cache@v4 + with: + path: iPlug2/Dependencies/IPlug/WAM_SDK + key: wam-sdk-${{ hashFiles('iPlug2/Dependencies/IPlug/download-iplug-sdks.sh') }} + + - name: Get WAM SDK + if: steps.cache-wam.outputs.cache-hit != 'true' + run: | + cd iPlug2/Dependencies/IPlug + ./download-iplug-sdks.sh + + - name: CMake Configure + run: cmake --preset=wam + + - name: Build WAM + run: cmake --build --preset=wam + + - name: Verify WAM Output + run: | + test -f build/wam/out/${{env.PROJECT_NAME}}/index.html + test -f build/wam/out/${{env.PROJECT_NAME}}/scripts/${{env.PROJECT_NAME}}-wam.js + test -f build/wam/out/${{env.PROJECT_NAME}}/scripts/${{env.PROJECT_NAME}}-web.js + test -f build/wam/out/${{env.PROJECT_NAME}}/scripts/${{env.PROJECT_NAME}}-web.wasm + echo "WAM distribution verified" + + - name: Upload WAM Artifact + uses: actions/upload-artifact@v4 + with: + name: ${{env.PROJECT_NAME}}-wam + path: build/wam/out/${{env.PROJECT_NAME}} diff --git a/.vscode/settings.json b/.vscode/settings.json index d3f5af5c..a96ee50a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,5 +4,7 @@ "grunt.autoDetect": "off", "jake.autoDetect": "off", "gulp.autoDetect": "off", - "npm.autoDetect": "off" + "npm.autoDetect": "off", + "cmake.useCMakePresets": "always", + "cmake.configureOnOpen": false } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..b6c3ac5c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.25) +project(iPlug2OOS) + +set(IPLUG2_DIR ${CMAKE_SOURCE_DIR}/iPlug2) +include(${IPLUG2_DIR}/iPlug2.cmake) + +find_package(iPlug2 REQUIRED) + +add_subdirectory(TemplateProject) diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 00000000..5143303a --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,254 @@ +{ + "version": 6, + "cmakeMinimumRequired": { + "major": 3, + "minor": 25, + "patch": 0 + }, + "configurePresets": [ + { + "name": "base", + "hidden": true, + "binaryDir": "${sourceDir}/build/${presetName}", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + } + }, + { + "name": "base-macos", + "hidden": true, + "inherits": "base", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Darwin" + }, + "cacheVariables": { + "CMAKE_OSX_DEPLOYMENT_TARGET": "10.15" + } + }, + { + "name": "base-windows", + "hidden": true, + "inherits": "base", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + }, + { + "name": "macos-ninja", + "displayName": "macOS (Ninja)", + "description": "macOS build with Ninja generator (NanoVG/Metal)", + "inherits": "base-macos", + "generator": "Ninja" + }, + { + "name": "macos-make", + "displayName": "macOS (Make)", + "description": "macOS build with Unix Makefiles generator (NanoVG/Metal)", + "inherits": "base-macos", + "generator": "Unix Makefiles" + }, + { + "name": "macos-xcode", + "displayName": "macOS (Xcode)", + "description": "macOS build with Xcode generator (NanoVG/Metal)", + "inherits": "base-macos", + "generator": "Xcode" + }, + { + "name": "macos-xcode-universal", + "displayName": "macOS Universal (Xcode)", + "description": "macOS Universal (arm64+x86_64) build with Xcode generator", + "inherits": "base-macos", + "generator": "Xcode", + "cacheVariables": { + "CMAKE_OSX_ARCHITECTURES": "arm64;x86_64" + } + }, + { + "name": "ios-xcode", + "displayName": "iOS (Xcode)", + "description": "iOS device build with Xcode generator (NanoVG/Metal)", + "inherits": "base", + "generator": "Xcode", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Darwin" + }, + "cacheVariables": { + "CMAKE_SYSTEM_NAME": "iOS", + "CMAKE_OSX_DEPLOYMENT_TARGET": "15.0" + } + }, + { + "name": "ios-sim-xcode", + "displayName": "iOS Simulator (Xcode)", + "description": "iOS simulator build with Xcode generator (NanoVG/Metal)", + "inherits": "base", + "generator": "Xcode", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Darwin" + }, + "cacheVariables": { + "CMAKE_SYSTEM_NAME": "iOS", + "CMAKE_OSX_DEPLOYMENT_TARGET": "15.0", + "CMAKE_OSX_SYSROOT": "iphonesimulator" + } + }, + { + "name": "visionos-xcode", + "displayName": "visionOS (Xcode)", + "description": "visionOS device build with Xcode generator (NanoVG/Metal)", + "inherits": "base", + "generator": "Xcode", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Darwin" + }, + "cacheVariables": { + "CMAKE_SYSTEM_NAME": "visionOS", + "CMAKE_OSX_DEPLOYMENT_TARGET": "1.0", + "CMAKE_OSX_SYSROOT": "xros" + } + }, + { + "name": "visionos-sim-xcode", + "displayName": "visionOS Simulator (Xcode)", + "description": "visionOS simulator build with Xcode generator (NanoVG/Metal)", + "inherits": "base", + "generator": "Xcode", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Darwin" + }, + "cacheVariables": { + "CMAKE_SYSTEM_NAME": "visionOS", + "CMAKE_OSX_DEPLOYMENT_TARGET": "1.0", + "CMAKE_OSX_SYSROOT": "xrsimulator" + } + }, + { + "name": "windows-ninja", + "displayName": "Windows (Ninja)", + "description": "Windows build with Ninja generator (NanoVG/GL2)", + "inherits": "base-windows", + "generator": "Ninja" + }, + { + "name": "windows-vs2022", + "displayName": "Windows (VS2022)", + "description": "Windows x64 build with Visual Studio 2022 (NanoVG/GL2)", + "inherits": "base-windows", + "generator": "Visual Studio 17 2022", + "architecture": { + "value": "x64", + "strategy": "set" + } + }, + { + "name": "windows-vs2022-arm64ec", + "displayName": "Windows ARM64EC (VS2022)", + "description": "Windows ARM64EC build with Visual Studio 2022 (NanoVG/GL2)", + "inherits": "base-windows", + "generator": "Visual Studio 17 2022", + "architecture": { + "value": "ARM64EC", + "strategy": "set" + } + }, + { + "name": "wam", + "displayName": "WAM (Emscripten)", + "description": "Web Audio Module build with Emscripten/WebAssembly", + "inherits": "base", + "generator": "Ninja", + "toolchainFile": "$env{EMSDK}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake", + "cacheVariables": { + "CMAKE_CROSSCOMPILING_EMULATOR": "$env{EMSDK_NODE}" + } + } + ], + "buildPresets": [ + { + "name": "macos-ninja", + "configurePreset": "macos-ninja" + }, + { + "name": "macos-make", + "configurePreset": "macos-make" + }, + { + "name": "macos-xcode", + "configurePreset": "macos-xcode", + "configuration": "Release" + }, + { + "name": "macos-xcode-universal", + "configurePreset": "macos-xcode-universal", + "configuration": "Release" + }, + { + "name": "ios-xcode", + "configurePreset": "ios-xcode", + "configuration": "Release", + "nativeToolOptions": [ + "-destination", "generic/platform=iOS", + "CODE_SIGNING_ALLOWED=NO" + ] + }, + { + "name": "ios-sim-xcode", + "configurePreset": "ios-sim-xcode", + "configuration": "Release", + "nativeToolOptions": [ + "-destination", "generic/platform=iOS Simulator", + "CODE_SIGNING_ALLOWED=NO" + ] + }, + { + "name": "visionos-xcode", + "configurePreset": "visionos-xcode", + "configuration": "Release", + "nativeToolOptions": [ + "-destination", "generic/platform=visionOS", + "CODE_SIGNING_ALLOWED=NO" + ] + }, + { + "name": "visionos-sim-xcode", + "configurePreset": "visionos-sim-xcode", + "configuration": "Release", + "nativeToolOptions": [ + "-destination", "generic/platform=visionOS Simulator", + "CODE_SIGNING_ALLOWED=NO" + ] + }, + { + "name": "windows-ninja", + "configurePreset": "windows-ninja" + }, + { + "name": "windows-vs2022", + "configurePreset": "windows-vs2022", + "configuration": "Release" + }, + { + "name": "windows-vs2022-arm64ec", + "configurePreset": "windows-vs2022-arm64ec", + "configuration": "Release" + }, + { + "name": "wam", + "configurePreset": "wam" + } + ] +} diff --git a/TemplateProject/CMakeLists.txt b/TemplateProject/CMakeLists.txt new file mode 100644 index 00000000..fd83d12a --- /dev/null +++ b/TemplateProject/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.25) +project(TemplateProject VERSION 1.0.0) + +set(IPLUG2_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../iPlug2 CACHE PATH "iPlug2 root directory") +include(${IPLUG2_DIR}/iPlug2.cmake) + +find_package(iPlug2 REQUIRED) + +iplug_add_plugin(${PROJECT_NAME} + SOURCES + TemplateProject.cpp + TemplateProject.h + resources/resource.h + RESOURCES + resources/fonts/Roboto-Regular.ttf + FORMATS + MINIMAL_PLUGINS APP +) \ No newline at end of file diff --git a/iPlug2 b/iPlug2 index 526d53cf..007f52f9 160000 --- a/iPlug2 +++ b/iPlug2 @@ -1 +1 @@ -Subproject commit 526d53cf622e10365c5fcb86540365f61e80883f +Subproject commit 007f52f928b612a2a58c5b205992b7e0e69c8d66