Skip to main content
iPlug2 supports building macOS audio plugins using Xcode, with support for both Intel and Apple Silicon (Universal binaries).

Prerequisites

1

Install Xcode

Download from the Mac App StoreMinimum version: Xcode 13+ (Xcode 15+ for visionOS)
2

Install Command Line Tools

xcode-select --install
3

Download SDKs (optional)

For VST3, AAX, and other plugin formats:
cd iPlug2/Dependencies
./download-iplug-sdks.sh

Project Structure

Each plugin has an Xcode project containing multiple targets:
MyPlugin/
├── MyPlugin.xcworkspace/           # Workspace (optional)
├── config/
│   └── MyPlugin-mac.xcconfig       # Build configuration
└── projects/
    └── MyPlugin-macOS.xcodeproj/   # Xcode project
        └── xcshareddata/
            └── xcschemes/
                ├── VST2.xcscheme
                ├── VST3.xcscheme
                ├── AU.xcscheme          # AUv2
                ├── AUv3.xcscheme        # AUv3
                ├── CLAP.xcscheme
                ├── AAX.xcscheme
                └── APP.xcscheme

Building with Xcode

Opening the Project

  1. Double-click MyPlugin-macOS.xcodeproj
  2. Or open workspace: MyPlugin.xcworkspace

Building in Xcode

1

Select scheme

Choose target from the scheme menu:
  • VST3 - VST3 plugin
  • AU - Audio Unit v2
  • AUv3 - Audio Unit v3 (modern)
  • CLAP - CLAP plugin
  • AAX - AAX plugin (requires SDK)
  • APP - Standalone application
2

Select configuration

Product > Scheme > Edit SchemeChoose build configuration:
  • Debug - Development with debug symbols
  • Release - Optimized for distribution
  • Tracer - Performance profiling
3

Build

Product > Build or press ⌘B

Building from Command Line

# Build specific target
xcodebuild -project projects/MyPlugin-macOS.xcodeproj \
  -scheme VST3 \
  -configuration Release

# Build all targets
xcodebuild -project projects/MyPlugin-macOS.xcodeproj \
  -alltargets \
  -configuration Release

Universal Binaries

iPlug2 supports building Universal binaries that run natively on both Intel and Apple Silicon Macs.

Intel (x86_64)

Runs on Intel-based MacsCompatible with all macOS versions

Apple Silicon (arm64)

Runs natively on M1/M2/M3 MacsSignificantly better performance

Building Universal Binaries

  1. Product > Scheme > Edit Scheme
  2. Run > Info > Build Configuration > Release
  3. Product > Destination > Any Mac
  4. Build Settings > Architectures
    • Set to: arm64 x86_64
    • Or: $(ARCHS_STANDARD) (default)
  5. Product > Build
Universal binaries are recommended for distribution to support all Macs with a single file.

Verifying Universal Binaries

# Check architectures in a binary
lipo -info build-mac/MyPlugin.vst3/Contents/MacOS/MyPlugin

# Expected output:
# Architectures in the fat file: MyPlugin are: x86_64 arm64

# Extract specific architecture
lipo build-mac/MyPlugin.vst3/Contents/MacOS/MyPlugin \
  -extract arm64 -output MyPlugin-arm64

Build Output

Built plugins are placed in build-mac/:
MyPlugin/build-mac/
├── MyPlugin.app/                   # Standalone app (contains AUv3)
│   └── Contents/
│       ├── MacOS/MyPlugin
│       ├── Frameworks/
│       │   └── MyPluginAU.framework/  # AUv3 framework
│       └── PlugIns/
│           └── MyPlugin.appex/        # AUv3 app extension
├── MyPlugin.vst3/                  # VST3 plugin
├── MyPlugin.clap/                  # CLAP plugin
├── MyPlugin.component/             # AUv2 plugin
├── MyPlugin.aaxplugin/             # AAX plugin
├── MyPluginAU.framework/           # AUv3 framework (standalone)
└── MyPlugin.appex/                 # AUv3 app extension (standalone)
AUv3 is embedded inside the standalone app and also built as a standalone framework/appex for use in other hosts.

Deployment Paths

Plugins are automatically symlinked to standard locations:
FormatDefault Path
VST3~/Library/Audio/Plug-Ins/VST3/
VST2~/Library/Audio/Plug-Ins/VST/
CLAP~/Library/Audio/Plug-Ins/CLAP/
AUv2~/Library/Audio/Plug-Ins/Components/
AAX/Library/Application Support/Avid/Audio/Plug-Ins/
APP~/Applications/
MacOS uses symlinks by default for faster development. Symlinks update automatically when you rebuild.

Customizing Deployment

Edit common-mac.xcconfig:
// Custom deployment paths
VST3_PATH = $(HOME)/MyPlugins/VST3
AU_PATH = $(HOME)/MyPlugins/Components

Code Signing

Code signing is required for AUv3 plugins and distribution.

Development Signing (Ad-hoc)

For local development only:
# Sign from innermost to outermost
codesign -s - --deep --force build-mac/MyPlugin.app/Contents/Frameworks/MyPluginAU.framework
codesign -s - --deep --force build-mac/MyPlugin.app/Contents/PlugIns/MyPlugin.appex
codesign -s - --deep --force build-mac/MyPlugin.app

# Verify signature
codesign -vvv --deep --strict build-mac/MyPlugin.app
Ad-hoc signing (-s -) is for local development only. These plugins:
  • Cannot be distributed to other users
  • Will not run on other machines
  • Are blocked by Gatekeeper

Distribution Signing

For public distribution, sign with a Developer ID certificate:
1

Get Developer ID certificate

  1. Enroll in Apple Developer Program
  2. Certificates, Identifiers & Profiles > Certificates
  3. Create Developer ID Application certificate
  4. Download and install in Keychain
2

Configure code signing

Edit common-mac.xcconfig:
CERTIFICATE_ID = Developer ID Application: Your Name (TEAM_ID)
DEVELOPMENT_TEAM = TEAM_ID  // Found at end of developer.apple.com URL
3

Sign with hardened runtime

codesign --force --timestamp --options runtime \
  -s "Developer ID Application: Your Name (TEAM_ID)" \
  -v build-mac/MyPlugin.app --deep --strict
The --options runtime flag enables hardened runtime, required for notarization.
4

Verify signature

# Check code signature
codesign -dvv build-mac/MyPlugin.app

# Verify signature is valid
codesign -vvv --deep --strict build-mac/MyPlugin.app

# Check Gatekeeper assessment
spctl -vvv --assess --type exec build-mac/MyPlugin.app

Notarization

Notarization is required for macOS 10.15+ to avoid Gatekeeper warnings.
1

Create app-specific password

  1. Go to appleid.apple.com
  2. Sign In > App-Specific Passwords
  3. Generate a new password
  4. Save it securely
2

Notarize the app

# Create a ZIP for notarization
ditto -c -k --keepParent build-mac/MyPlugin.app MyPlugin.zip

# Submit for notarization
xcrun notarytool submit MyPlugin.zip \
  --apple-id [email protected] \
  --team-id TEAM_ID \
  --password app-specific-password \
  --wait
Use --wait to wait for notarization to complete (takes 5-15 minutes).
3

Staple the ticket

After successful notarization:
# Staple notarization ticket to app
xcrun stapler staple build-mac/MyPlugin.app

# Verify stapling
xcrun stapler validate build-mac/MyPlugin.app
Stapling embeds the notarization ticket, allowing the app to run offline.
iPlug2 includes a helper script: Scripts/notarise.sh for automated notarization.

Using notarise.sh

cd Scripts
./notarise.sh \
  "$(pwd)/.." \
  "$(pwd)/../MyPlugin/build-mac/MyPlugin.app" \
  "com.yourcompany.myplugin" \
  "[email protected]" \
  "app-specific-password"
Arguments:
  1. Root directory
  2. Path to app/plugin
  3. Bundle ID
  4. Apple ID email
  5. App-specific password

Debugging

Setting Up Debugger

1

Edit scheme

Product > Scheme > Edit Scheme > Run > Info
  • Executable: Choose your DAW (e.g., /Applications/REAPER.app)
  • Or select Ask on Launch to choose at runtime
2

Set breakpoints

Click in the gutter to add breakpoints in your code
3

Run debugger

Press ⌘R or Product > RunXcode will:
  1. Build the plugin
  2. Deploy to plugin folder
  3. Launch your DAW
  4. Attach the debugger
4

Load plugin in DAW

Create a track and load your pluginBreakpoints will trigger when code is executed

LLDB Debugging

For advanced debugging:
# Launch DAW with LLDB
lldb /Applications/REAPER.app/Contents/MacOS/REAPER

# Set breakpoints
(lldb) breakpoint set --name MyPlugin::ProcessBlock
(lldb) breakpoint set --file MyPlugin.cpp --line 42

# Run
(lldb) run

# When breakpoint hits
(lldb) bt           # Backtrace
(lldb) frame variable  # Local variables
(lldb) continue     # Continue execution

Audio Unit Validation

Validate AUv2 plugins with auval:
# List all registered Audio Units
auval -a

# Validate effect (aufx)
auval -v aufx <subtype> <manufacturer>

# Validate instrument (aumu)
auval -v aumu <subtype> <manufacturer>

# Example: Validate IPlugEffect
auval -v aufx Ipef Acme
<subtype> and <manufacturer> are 4-character codes defined in config.h.

Common auval Errors

Cause: Plugin not properly registered or has errorsSolution:
  • Ensure plugin is code-signed
  • Run the standalone app once to register AUv3
  • Clear Audio Unit cache: killall -9 AudioComponentRegistrar
  • Check Console.app for crash logs
Cause: UI not initialized properlySolution:
  • Usually benign, but verify UI appears correctly in DAW
  • Check IGraphics initialization in plugin constructor

Build Settings

Common Settings (from common-mac.xcconfig)

// Deployment target
MACOSX_DEPLOYMENT_TARGET = 10.13  // Minimum macOS version

// Architectures
ARCHS = arm64 x86_64  // Universal binary

// C++ standard
CLANG_CXX_LANGUAGE_STANDARD = c++17
CLANG_CXX_LIBRARY = libc++

// Code signing
CERTIFICATE_ID = Developer ID Application: Your Name (TEAM_ID)
DEVELOPMENT_TEAM = TEAM_ID

Preprocessor Defines

NOMINMAX                 // Disable min/max macros
SWELL_CLEANUP_ON_UNLOAD  // Clean up SWELL resources

// Format-specific
VST3_API                 // VST3 plugin
AU_API                   // Audio Unit v2
AUv3_API                 // Audio Unit v3
CLAP_API                 // CLAP plugin
AAX_API                  // AAX plugin
APP_API                  // Standalone app

// Audio APIs (APP only)
__MACOSX_CORE__          // CoreAudio

// IPlug defines
IPLUG_EDITOR=1           // Has UI
IPLUG_DSP=1              // Has DSP

Troubleshooting

Cause: Architecture mismatch, code signing, or registrationSolution:
  • Check DAW architecture matches plugin (Intel vs Apple Silicon)
  • Verify plugin is code-signed: codesign -vv MyPlugin.component
  • Clear Audio Unit cache: killall -9 AudioComponentRegistrar
  • For AUv3: Run standalone app once to register
Cause: Missing SDKs or incorrect pathsSolution:
  • Run Dependencies/download-iplug-sdks.sh
  • Check paths in common-mac.xcconfig:
    VST3_SDK = $(DEPS_PATH)/IPlug/VST3_SDK
    AAX_SDK = $(DEPS_PATH)/IPlug/AAX_SDK
    
Cause: Hardened runtime not enabled or unsigned binariesSolution:
  • Sign with --options runtime flag
  • Ensure all frameworks and executables are signed
  • Check notarization log for details:
    xcrun notarytool log <submission-id> \
      --apple-id [email protected] \
      --team-id TEAM_ID \
      --password app-specific-password
    
Cause: AUv3 not registered or code signing issueSolution:
  • Run standalone app at least once
  • Ensure app is properly code-signed (ad-hoc or Developer ID)
  • Check Console.app for errors
  • Verify entitlements are correct

Next Steps

iOS Build

Build AUv3 plugins for iOS

Code Signing

Deep dive into signing and notarization

CMake Build

Alternative build system

Installers

Create DMG installers

Build docs developers (and LLMs) love