Introduction
cargo-reaper
is a Cargo plugin designed to streamline the development of REAPER extension plugins with Rust.
It serves as a companion for the reaper-rs
library,
which provides Rust bindings and tools for creating REAPER plugins -- including a procedural macro that bootstraps your plugin as a native REAPER extension.
Motivation
Developing REAPER extension plugins requires intimate knowledge about REAPER and its behavior on each platform that it supports.
This information is somewhat esoteric and not listed in the development docs, making extension plugin development a trial-and-error ordeal.
cargo-reaper
aims to simplify the learning curve by providing an easy-to-use, intuitive interface for initializing, building,
testing and publishing REAPER extension plugins.
Throughout this book are references to REAPER specific terminology, most of which you may safely ignore since cargo-reaper
handles it for you, however, if you wish to know more the Glossary
section contains detailed documentation
that may aid you in understanding how cargo-reaper
works. It is recommended to have a once-over for anyone creating a non-trivial
extension plugin.
Platform Support
Any platform which is both supported by Rust and REAPER should work.
Important: extension plugins built for Windows must be built with MSVC.
The following are the canonical sources of truth for REAPER platform support:
Which can then be cross referenced against the Rust target list:
Or via rustc
from the terminal:
rustc --print target-list
Configuration File
cargo-reaper
requires a configuration file in the project root that conforms to the following
naming convention (in precedence order):
reaper.toml
.reaper.toml
This file is created automatically for projects initialized by
cargo-reaper-new
.
Declaring Extension Plugins
cargo-reaper
expects a key-value pair mapping of reaper extension plugins, where the key is the finalized name of the
plugin and the value is the path to a directory containing a cargo manifest. All other information cargo-reaper
needs
is gathered from the manifest file.
A minimal reaper.toml
, for a single cargo package could look like the following:
[extension_plugins]
reaper_hello_world_extension = "./."
Important: REAPER requires that extension plugins be prefixed by
reaper_
, otherwise REAPER will not recognize it.
cargo-reaper
will throw an error and refuse to compile if an extension plugin listed does not meet this condition.
Plugin Manifest
There are a few necessities for cargo-reaper
to recognize an extension plugin that is declared in a configuration file.
- The cargo manifest must be a package.
- The package must include a library target.
- The library target must include a
name
field. - The library target must include
cdylib
in thecrate-type
field.
The above should be true whether the project is a single package, workspace with multiple packages or workspace package.
Package Manifest
An example of a single package manifest and its corresponding configuration file.
# Cargo.toml
[package]
name = "my_package"
version = "0.1.0"
edition = "2024"
[lib]
name = "my_extension_plugin"
crate-type = ["cdylib"]
# reaper.toml
[extension_plugins]
reaper_my_plugin = "./."
Workspace Manifests
Examples of acceptable workspace patterns and their corresponding configuration files.
Workspace Manifest
An example of a virtual workspace that does not contain a package attribute, but consists of multiple members, each of which being a package manifest meeting the plugin manifest criteria.
# Cargo.toml
[workspace]
resolver = "2"
members = ["crates/*"]
# reaper.toml
[extension_plugins]
reaper_my_plugin_1 = "./crates/my_plugin_1"
reaper_my_plugin_2 = "./crates/my_plugin_2"
Workspace Package Manifest
An example of a workspace package manifest and its corresponding configuration file.
# Cargo.toml
[workspace]
resolver = "2"
members = ["crates/*"]
[package]
name = "my_workspace_package"
version = "0.1.0"
edition = "2024"
[lib]
name = "my_extension_plugin"
crate-type = ["cdylib"]
# reaper.toml
[extension_plugins]
reaper_my_plugin = "./."
cargo-reaper
NAME
cargo-reaper -- A Cargo plugin for developing REAPER extension plugins with Rust.
SYNOPSIS
cargo-reaper
command
DESCRIPTION
cargo-reaper
is a convenience wrapper around Cargo that adds a post-build hook to streamline REAPER extension development. It automatically renames the compiled plugin to include the required reaper_
prefix and symlinks it to REAPER’s UserPlugins
directory.
By default, Cargo prefixes dynamic libraries with lib
, which REAPER does not recognize. Manually renaming the plugin and keeping the UserPlugins
directory up-to-date can be tedious -- cargo-reaper
takes care of all that for you, across all supported platforms.
COMMANDS
Each command is documented in its own section:
stdout
.UserPlugins
directory.help
OPTIONS
-h
--help
--help
).-V
--version
cargo-reaper-new
NAME
cargo-reaper-new -- Create a new REAPER extension plugin.
SYNOPSIS
cargo-reaper new
path
DESCRIPTION
This command will create a new Cargo package in the given directory that is set up for use with cargo-reaper
.
This includes a simple template with a Cargo.toml
manifest, sample source file, reaper.toml
configuration file, and a .gitignore
file.
OPTIONS
-h
--help
EXAMPLES
cargo reaper new reaper_my_plugin
Important: REAPER requires that extension plugins be prefixed by
reaper_
, otherwise REAPER will not recognize it.The
reaper_
prefix is added by default in thecargo-reaper
configuration file that is generated bycargo-reaper-new
, however,cargo-reaper
will throw an error and refuse to compile if an extension plugin listed does not meet this condition.
cargo-reaper-list
NAME
cargo-reaper-list -- List all detected REAPER plugin packages in a cargo-reaper
project.
SYNOPSIS
cargo-reaper list
DESCRIPTION
This command prints a list of available plugins and their version, description and author information
in a human-readable format to the terminal via stdout
.
OPTIONS
-h
--help
EXAMPLES
cargo reaper list
cargo-reaper-build
NAME
cargo-reaper-build -- Compile REAPER extension plugin(s).
SYNOPSIS
cargo-reaper build
[options] [cargo_build_args]...
DESCRIPTION
Compiles, renames and symlinks REAPER extension plugins, forwarding trailing arguments to the cargo-build
invocation.
The resulting target
is renamed to its corresponding key specified in the cargo-reaper
configuration file.
Symlinks to plugins in REAPER's UserPlugins
directory are managed automatically, unless specified otherwise. This ensures that a new plugin
that is built with the release
profile, does not fail to be symlinked if a symlink with the same name already exists for the debug
profile.
If for whatever reason symlinking fails, and the build command is unable to remove a stale symlink, use cargo-reaper-clean
.
OPTIONS
--no-symlink
UserPlugins
directory.-h
--help
EXAMPLES
- Build a package or workspace containing a REAPER extension plugin, and all of its dependencies.
cargo reaper build
- Build a package or workspace containing a REAPER extension plugin and all of its dependencies, but do not create symlinks to the
UserPlugins
directory.
cargo reaper build --no-symlink
- Build only the specified package in a workspace containing a REAPER extension plugin with optimizations for x86_64 Windows.
cargo reaper build -p reaper_my_plugin --lib --release --target x86_64-pc-windows-msvc
cargo reaper build -- -p reaper_my_plugin --lib --release --target x86_64-pc-windows-msvc
Note that arguments passed to the
cargo-build
invocation must be trailing. These may be passed directly, or as positional arguments.
cargo-reaper-link
NAME
cargo-reaper-link -- Manually symlink extension plugin(s) to REAPER's UserPlugins
directory.
SYNOPSIS
cargo-reaper link
[path]...
DESCRIPTION
Manually symlink one or more extension plugins to REAPER's UserPlugins
directory.
This may be useful in circumstances where finer grain control is necessary between building and symlinking the plugin, for instance, in CI or when using build tools like Nix or Docker.
By default
cargo-reaper-build
will symlink extension plugins automatically, unless specified otherwise.
OPTIONS
-h
--help
EXAMPLES
- Create a symlink from an absolute path to a compiled REAPER extension plugin to REAPER's
UserPlugins
directory.
cargo reaper link /absolute/path/to/target/release/reaper_my_plugin.{so|dylib|dll}
- Create a symlink from a relative path to a compiled REAPER extension plugin to REAPER's
UserPlugins
directory, using shell scripting (Linux and MacOS only).
cargo reaper link $(realpath target/release/reaper_my_plugin.*)
REAPER extension plugins are dynamically linked libraries, which have differing extension names depending on their target platform. Below is a list of platforms and their corresponding extension names, though in most cases, a regex catchall will suffice (
reaper_my_plugin.*
).
- Linux --
.so
- Darwin (MacOS) --
.dylib
- Windows --
.dll
cargo-reaper-run
NAME
cargo-reaper-run -- Run REAPER extension plugin(s).
SYNOPSIS
cargo-reaper run
[options] [cargo_build_args]...
DESCRIPTION
Compile extension plugins and open REAPER.
This is effectively shorthand for running cargo-reaper-build
then opening REAPER, which will make
changes to your extension plugins take immediate effect.
cargo-reaper-run
will attempt to use the REAPER binary executable on $PATH
if it's available, otherwise falling
back to the platform specific default global installation path. If for some reason the default installation is not
working, please see the options below for manually specifying a path to a REAPER binary executable.
OPTIONS
-e
path
--exec
path
-o
path
--open
path
--open-project
path
--no-build
-t
duration
--timeout
duration
--stdin
stdio
--stdout
stdio
--stderr
stdio
-h
--help
ADDITIONAL LINUX OPTIONS
The following options require xserver
to be configured and have Xvfb
and xdotool
installed.
These options are intended to enable testing in headless environments and to make it easier to
assert the state an extension plugin reaches.
--headless
-D
display
--display
display
DISPLAY
environment variable, e.g. DISPLAY=:99
.-w
title
--locate-window
title
--keep-going
EXAMPLES
- Build a package or workspace containing a REAPER extension plugin and all of its dependencies, and open REAPER.
cargo reaper run
- Build only the specified package in a workspace containing a REAPER extension plugin with optimizations for x86_64 Windows, and open REAPER.
cargo reaper run -p reaper_my_plugin --lib --release --target x86_64-pc-windows-msvc
cargo reaper run -- -p reaper_my_plugin --lib --release --target x86_64-pc-windows-msvc
Note that arguments passed to the
cargo-build
invocation must be trailing. These may be passed directly, or as positional arguments.
- Run REAPER in a headless environment through
Xvfb
on Linux, and attempt to locate a window.
DISPLAY=:99 cargo-reaper run --headless \ # open REAPER on Xvfb display 99
--no-build \ # but don't build any plugins
--open /path/to/my_project.RPP \ # open a pre-saved project (maybe with state that affects how the plugin behaves)
--locate-window "error: expected ..." \ # and locate an error window and exit successfully
--timeout 15s \ # but only run REAPER for a maximum of 15 seconds
--keep-going \ # and don't exit until the timeout is reached (even if the window is found)
--stdout null \ # do not print Xvfb or REAPER info to stdout
--stderr null # do not print Xvfb or REAPER errors to stderr
TIP: The above assumes the extension plugin is already installed, skipping the build phase. This can be particularly useful since it doesn't require configuring a rust toolchain in order to build the plugin prior to testing it.
cargo-reaper-clean
NAME
cargo-reaper-clean -- Remove plugin(s) from the UserPlugins
directory that cargo-reaper
has generated in the past.
SYNOPSIS
cargo-reaper clean
[options]
DESCRIPTION
Clean plugin symlinks from REAPER's UserPlugins
directory, and optionally artifacts generated by cargo-reaper
.
OPTIONS
-p
key
--plugin
key
-n
--dry-run
-a
--remove-artifacts
-h
--help
EXAMPLES
- Remove all plugin symlinks whose keys exist in the
cargo-reaper
configuration file.
cargo reaper clean
- Remove specific plugin symlinks by referencing its key in the
cargo-reaper
configuration file.
cargo reaper clean -p reaper_my_plugin
- Display cargo artifacts generated by
cargo-reaper
and symlinks for plugins whose keys exist in thecargo-reaper
configuration file without removing them.
cargo reaper clean --remove-artifacts --dry-run
Glossary
Default Global Installation Path
This is the system-wide path where the REAPER binary executable is installed. This is different for each supported platform:
- Linux:
- A global default is not predictable since Linux does not have a canonical package manager. Instead,
cargo-reaper
uses thewhich
crate'swhich::which_global
function to determine its location.
- A global default is not predictable since Linux does not have a canonical package manager. Instead,
- Darwin (MacOS) --
/Applications/REAPER.app
- Windows:
- x86 (32bit) --
C:\Program Files (x86)\REAPER\reaper.exe
- x86_64 (64bit) --
C:\Program Files\REAPER (x64)\reaper.exe
- aarch64 (ARM) --
C:\Program Files\REAPER (ARM64)\reaper.exe
- x86 (32bit) --
Extension Plugin
A C/C++ dynamically linked library that when placed in REAPER's UserPlugins
directory, is loaded as part of the REAPER
application thread on launch, adding additional functionality to the program.
Dynamically Linked Library
A compiled collection of code and data that is loaded into a program at runtime, rather than being statically included in the final executable during compilation.
REAPER extension plugins are dynamically linked libraries, which have differing extension names depending on their target platform:
- Linux --
.so
- Darwin (MacOS) --
.dylib
- Windows --
.dll
User Plugins
The UserPlugins
directory is the file system location created the first time REAPER is launched that the REAPER application thread loads extension plugins from.
This is different for each supported platform:
- Linux --
~/.config/REAPER/UserPlugins
- Darwin (MacOS) --
~/Library/Application\ Support/REAPER/UserPlugins
- Windows --
%APPDATA%\REAPER\UserPlugins
Plugin Manifest
A plugin manifest, in the context of cargo-reaper
, is the same as a Cargo manifest, which contains
a package with a library target of crate-type
cdylib
.
See the Plugin Manifest
section for detailed information on configuring a cargo-reaper
plugin manifest.