AUDIO
Source snapshot · 6 November 2026

Build and bundle a plug-in product

python3 scripts/bundle-plugin.py builds any trusted Cargo product which declares one cdylib target and calls ravet_plugin::export_plugin! with clap and native features. It uses that product for every selected format. No reference-product allow-list or product-specific C++ wrapper is needed. See plug-in export for the product contract and Foundry for project creation.

From a RAVET checkout, with Python 3.11+, Cargo/Rust, CMake 3.22+ and a C++17 compiler (individual SDKs may require newer tools):

python3 scripts/bundle-plugin.py --package ravet-delay-plugin \
  --formats clap,vst3,au,aax,lv2 --release --validate

# Independent product workspace; generate and retain its Cargo.lock first.
python3 scripts/bundle-plugin.py --package my-product \
  --manifest-path ../my-product/Cargo.toml --formats clap,vst3,lv2

The command builds only the named package. Debug is the default; --release selects release. One cargo rustc --locked --jobs 2 invocation per Rust target emits a cdylib and, when AAX is selected, a staticlib in the same compilation. A small executable loads the trusted product table for its name, version and identity; running a build therefore executes trusted consumer code. The adapters receive these already built libraries and reuse their existing importable Python builders. No SDK is downloaded or redistributed. There is no global plug-in installation except the explicitly requested temporary AU validation below.

Outputs share <cargo-target>/plugins/<debug|release>/, or <cargo-target>/plugins/windows/<debug|release>/ for a cross-build. An explicit macOS --arch selects <cargo-target>/plugins/macos-<arch>/<debug|release>/; omitting it preserves the native output path above. Cargo's CARGO_TARGET_DIR is respected. Filenames use the Cargo package name, with .clap, .vst3, .component, .aaxplugin and .lv2 suffixes; display names and format identities come from the product. --output-dir /absolute/directory selects another destination. An existing selected bundle is replaced; unselected formats are left alone. Intermediate builds remain in Cargo's target directory. A failed command exits nonzero and may leave earlier formats from that run.

Other options:

The existing per-format scripts and their explicit SDK options still work for format-focused development and historical reference fixtures. The unified command always selects the generic adapters.

Topics in this guide

SDK settings and precedence

Settings contain paths, never SDK source or signing credentials:

[sdks]
vst3 = "/SDKs/vst3"
audio_unit = "/SDKs/AudioUnitSDK"
aax = "/SDKs/AAX"
lv2 = "/SDKs/lv2"
webview2 = "/SDKs/Microsoft.Web.WebView2"

Use a project ravet-sdks.toml beside the product's Cargo.toml or in an ancestor (the nearest file wins), or the per-user file:

Platform User settings
macOS ~/Library/Application Support/ravet/ravet-sdks.toml
Linux ~/.config/ravet/ravet-sdks.toml
Windows %APPDATA%/ravet/ravet-sdks.toml

$XDG_CONFIG_HOME/ravet/ravet-sdks.toml overrides the platform config location when set. Project paths override user paths individually; omitted keys inherit. Relative settings paths resolve against the file's directory; ~ expands to the user's home. Explicit --settings replaces automatic project-file selection. Unknown settings keys and malformed paths/commands reject.

For each SDK, precedence is explicit flag → environment variable → project file → user file. Environment variables are RAVET_VST3_SDK, RAVET_AUDIO_UNIT_SDK, RAVET_AAX_SDK, and RAVET_LV2_SDK. Prefer absolute paths for flags and environment variables. No sibling checkout, package-manager prefix or developer-specific path is guessed. Missing SDK errors name the key, environment variable or missing file. Only selected formats need SDKs: AU and AAX do not need VST3. LV2 accepts official include/lv2 or flat lv2 headers, including COPYING. Format SDK licence notices are added to the bundles.

Foundry's saved SDK fields are passed as explicit flags, so they override the same shared discovery layers. Empty fields allow environment/project/user settings to supply a path. Keep machine-specific SDK settings out of public consumer source control when appropriate.

Signing

On native macOS, the default signs nested Mach-O images first, then the enclosing bundle, using codesign --force --sign -. LV2 signs its individual images. This is development ad hoc signing; production distribution remains vendor-owned. The AU builder also signs its staging dylib before loading it for metadata.

A product can replace final signing with a command argument array:

[signing]
command = ["/absolute/vendor-tools/sign-plugin", "--profile", "my-product"]

Or pass --sign-command '["/absolute/vendor-tools/sign-plugin","--profile","my-product"]'. The CLI command overrides settings. RAVET appends the absolute bundle path and sets RAVET_BUNDLE_FORMAT and RAVET_BUNDLE_PATH; it runs the command once per final assembled bundle from the product directory, without a shell. The vendor script owns nested signing, Developer ID identities, notarization, PACE wrapping and any required credentials/configuration. Store secrets with that vendor tool, not in RAVET or a command line. Hook failures stop the command. Hooks also run on Windows/Linux when supplied; those platforms have no default signing command. Validation follows signing on the final copied bundle. RAVET never configures production credentials or infers shipping readiness from a successful hook.

Validation

--validate runs adapter contracts where available and validates the final signed bundles. A missing required validator or failed check is an error:

Format Validation
CLAP clap-validator validate, from --clap-validator, PATH or RAVET target/tools
VST3 Steinberg validator, built from the selected external SDK
AUv2 Native component contracts; auval -v with the table's identity
AAX RAVET synthetic-host bundle check; no Avid/PACE validator
LV2 CTest contracts/product smoke/lilv when available, then lv2_validate from PATH

On macOS, validation explicitly runs the requested architecture; universal runs both arm64 and x86_64 validators. clap-validator must contain those slices. lv2_validate checks architecture-independent Turtle on the build host; the final LV2 module contracts execute separately in each requested slice.

For x86_64 AU validation, the tool ad hoc signs a private build-directory copy of Apple's /usr/bin/auvaltool, then loads RAVET's registration helper into that process. The helper registers the exact final signed component's factory and original identity with AudioComponentRegister. This avoids installed-product identity collisions and Apple silicon's omission of Intel-only components from system registration. No component is installed and no Apple binary is shipped. Only trusted product libraries should be validated, as with metadata loading.

The arm64 AU path retains system auval -v: Apple's arm64e validator cannot load an arm64 registration constructor. It temporarily copies the component to ~/Library/Audio/Plug-Ins/Components/ravet-validation-<package>.component, refuses to overwrite an existing path and removes its copy in finally. An installed product with the same identity can affect arm64 registrar lookup; use a clean user environment to qualify that lookup. Exact-bundle native contracts run in both slices regardless. Killing an arm64 validation process without cleanup may require removing its temporary component. No devices or DAWs are opened.

Cross-build validation uses Wine for CLAP/VST3/AAX contracts; supply a Windows clap-validator.exe with --clap-validator, PATH or target/tools. LV2 validates Turtle on the build host. Missing target validators reject validation. A build/validator result is limited to the recorded machine and format; it does not establish DAW, editor, production signing or real-time support. The unified command's current executed evidence is in work status.

Licence notices

Every bundle the tool assembles carries RAVET's licence, the product's third-party notices (THIRD-PARTY-NOTICES.txt) and the Rust standard library notice, written before signing: inside Contents/Resources/notices for CLAP on macOS, VST3, AUv2 and AAX, at the root of an LV2 bundle, and in a <package> notices folder beside a single-file .clap on Windows and Linux, which installers must ship with it. See dependency notices.

For ravet-synth-plugin, VST3 --validate additionally builds and runs the real-product instrument adapter fixture (CMake RAVET_VST3_INSTRUMENT_TESTS=ON), before validating the final module. It checks hidden MIDI controller assignments, note IDs/output offsets, exact audio/tail and latency notification. See the instrument guide. AU validation retries only temporary registrar discovery failures, then removes its exclusive temporary component installation on either success or failure.

Recorded macOS architecture run

On 5 November 2026, the Delay built in all five formats as thin x86_64 and universal bundles on one Apple M4 Pro/macOS 27.0.1. Every shipped image contained the selected slices. x86_64 validator execution and REAPER 7.82 checks used Rosetta 2 on Apple silicon, not native Intel hardware. CLAP/VST3/LV2 REAPER renders passed; AU discovery/edits/recall passed but its strict render timing failed. AAX has synthetic checker evidence only for this slice. See the receipt, support matrix and harness instructions.