Pamplejuce is a template lifestyle for creating and building JUCE plugins in 2021.
Out of the box, it supports:
- C++20
- JUCE 6.1 as a submodule, tracking develop
- CMake 3.18 (Latest bundled version in VS 2019 as of Jan 2021)
- Catch2 2.13.3
- Github Actions for both CI and artifact building
- Proper .gitignore given the above
- Building on Windows, Linux and Mac (including arm64 built with Xcode 12.2)
- MacOS code signing, packaging, notarization.
This is a template repo!
You can kickstart your new repo using this one as the base by clicking "Use this template" here or at the top of the page.
For an example of a plugin that uses this repo, check out Load Monster!.
After you've created a new repo:
-
git clone
your new repo (if you make it private, see the warning below about GitHub Actions minutes) -
Download CMAKE if you are on MacOs or Linux. VS 2019 has it bundled.
-
Populate the latest JUCE by running
git submodule update --init
in your repository directory. By default this will track JUCE'sdevelop
branch. -
Replace
Pamplejuce
with the name of your project in CMakeLists.txt line 5, where thePROJECT_NAME
variable is set. -
Pick which formats you want built on line 8.
-
Set the correct flags for your plugin under
juce_add_plugin
. Check out the API https://github.com/juce-framework/JUCE/blob/master/docs/CMake%20API.md and be sure to change things likePLUGIN_CODE
andPLUGIN_MANUFACTURER_CODE
-
Rename
AudioPluginAudioProcessor
to your plugin name in the code. -
Set
PROJECT_NAME
on line 6 of the github action to your project name.
- Your tests will be in "Tests"
- Your binary data target is called "Assets"
One might think that in 2021, files added to your Sources directory would automatically added to a target.
It's true, you could use globbing. But "Modern CMake" distinctly prohibits this — why? Because CMake has no way of reliabily knowing you've added a new file, so it won't be picked up.
The CMakeLists.txt
file describes how to configure and build the plugins as well as setup the IDE project.
Unfortunately, these different jobs are not clearly separated or delineated by CMake's config, CLI or options. In my opinion, this is why CMake has the reputation it has: there's a lot of complexity resulting from implicit coupling between these concerns.
JUCE provides CMake helpers, allowing plugin devs to call a small number of functions like juce_add_plugin
. It sets up our project much like JUCE's Projucer did in the past, generating the IDE project and setting up all the build config files.
GitHub Actions is running CMake on MacOS, Windows and Linux, therefore configuring, building and testing for each environment.
CMake does its job for us in multiple incantations:
The CMakeLists.txt
is parsed, processed and the project is configued.
This might look something like cmake -B Builds
The -B
option tells CMake what folder to perform the build in, where to stick all the resultant files, etc.
This outputs files for system specific build tooling and IDEs to read.
Generate a VS 2019 Project file:
cmake -B Builds -G "Visual Studio 16 2019"
Or an Xcode project:
cmake -B Builds -G Xcode
During local JUCE development, we'd run one of the above and then trigger actual builds from our IDE rather than CMake.
You can skip the IDE project generation but still build using the system specific build tools (such as Xcode) on the command line with:
cmake --build Builds --config Release
This is how GitHub Actions builds.
Again, things are messy and lines are blurred.
CTest is just a unit test runner. It doesn't know anything about unit test implementation or know anything about the executable that it will run.
So a test executable has to be created by CMake first, which we are doing with the help of the Catch2 CMake integration.
Testing is enabled with enable_testing()
in a CMakeLists.txt
file and then the ctest
command can be run in the Builds directory
When run, ctest barfs up logs in Testing/Temporary. Thanks, ctest!
Since tests are an executable target, they are built and run via Xcode schemes, with results showing up in the console:
TBD.
It's very confusing, as the documentation is a big framented.
- Things in double curly braces like
${{ matrix.artifact }}
are called "contexts or expressions" and can be used to get, set, or perform simple operations. - In "if" conditions you can omit the double curly braces, as the whole condition is evaluated as an expression:
if: contains(github.ref, 'tags/v')
- You can set variables for the whole workflow to use in "env"
- Reading those variables is done with the env context when you are inside a
with
,name
, orif
:${{ env.SOME_VARIABLE }}
- Inside of
run
, you have access to bash ENV variables in addition to contexts/expressions. That means$SOME_VARIABLE
or${SOME_VARIABLE}
will work but only when using bash and not while using powershell on windows. The version with curly braces (variable expansion) is often used when the variable is forming part of a larger string to avoid ambiguity. Be sure that the ENV variable was set properly in the workflow/job/step before you use it. And if you need the variable to be os-agnostic, use the env context.
- The "Modern CMake" gitbook which also has a section on https://cliutils.gitlab.io/modern-cmake/chapters/testing/catch.html.
- Effective Modern CMake
- JUCE's announcment of native CMake support
- Eyalamir Music's JUCE / CMake prototype repository
- Christian Adam's HelloWorld CMake and ccache repo
- Maxwell Pollack's JUCE CMake + GitHub Actions repo
- Oli Larkin's PDSynth iPlug2 template
- Running pluginval in CI
- Catch2's docs on CMake integration
- Roman Golyshev's Github Actions & Catch2 repo
- Matt Clarkson's CMakeCatch2 repo
- CMake Cookbook example
- Unit Testing With CTest
- Mark's Catch2 examples from his 2020 ADC talk
- iPlug Packages and Inno Setup scripts
- Surge's pkgbuild installer script
- Chris Randall's PackageBuilder script
- David Cramer's GA Workflow for signing and notarizing and his notarize-cli tool
I've been blowing away the Builds directory when altering the CMake.
rm -rf Builds && cmake -B Builds -G Xcode
rm -rf Builds && cmake -B Builds && cmake --build Builds --config Release
- Update with latest CMake version listed here. Note that VS 2019 has a bundled CMake and tends to run behind, so this might be the limiting factor for CMake versions.
- Update JUCE with
git submodule update --remote --merge
- Update Xcode to latest available version and change
DEVELOPER_DIR
env var in the GitHub action. - Change Catch2 version in CMakeLists.txt to latest tag