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 your@email.com \
  --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" \
  "your@email.com" \
  "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 your@email.com \
      --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