Project Structure
Follow these guidelines to ensure your plugin repository works smoothly with BeatConnect’s build system.
Recommended Structure
your-plugin/
├── CMakeLists.txt # Root CMake configuration
├── CMakePresets.json # Build presets (optional)
├── .gitmodules # Git submodule definitions
├── README.md # Project documentation
├── LICENSE # Your license file
│
├── external/ # Third-party dependencies
│ ├── JUCE/ # JUCE as submodule
│ └── other-lib/ # Any other dependencies
│
├── Source/ # Your plugin source code
│ ├── PluginProcessor.h
│ ├── PluginProcessor.cpp
│ ├── PluginEditor.h
│ ├── PluginEditor.cpp
│ └── DSP/ # DSP-specific code
│ ├── Filter.h
│ ├── Filter.cpp
│ ├── Oscillator.h
│ └── Oscillator.cpp
│
├── Resources/ # Binary resources
│ ├── Logo.png
│ ├── Background.jpg
│ └── Presets/
│ ├── Default.xml
│ └── Factory/
│
├── Tests/ # Unit tests (optional)
│ ├── CMakeLists.txt
│ └── PluginTests.cpp
│
└── .github/ # GitHub configuration
└── workflows/ # Your own CI (optional)
Required Files
CMakeLists.txt
The root CMakeLists.txt is required. At minimum:
cmake_minimum_required(VERSION 3.22)
project(YourPlugin VERSION 1.0.0)
add_subdirectory(external/JUCE)
juce_add_plugin(YourPlugin
PLUGIN_MANUFACTURER_CODE Xxxx
PLUGIN_CODE Yyyy
FORMATS VST3 AU
PRODUCT_NAME "Your Plugin"
)
target_sources(YourPlugin PRIVATE
Source/PluginProcessor.cpp
Source/PluginEditor.cpp
)
target_link_libraries(YourPlugin PRIVATE
juce::juce_audio_basics
juce::juce_audio_processors
juce::juce_gui_basics
).gitmodules
If using JUCE as a submodule:
[submodule "external/JUCE"]
path = external/JUCE
url = https://github.com/juce-framework/JUCE.gitSource File Organization
Simple Plugin (< 5 files)
Source/
├── PluginProcessor.h
├── PluginProcessor.cpp
├── PluginEditor.h
└── PluginEditor.cpp
Medium Plugin (5-20 files)
Source/
├── PluginProcessor.h
├── PluginProcessor.cpp
├── PluginEditor.h
├── PluginEditor.cpp
├── Parameters.h # Parameter definitions
├── DSP/
│ ├── Filter.h
│ ├── Filter.cpp
│ ├── Delay.h
│ └── Delay.cpp
└── UI/
├── CustomLookAndFeel.h
├── CustomLookAndFeel.cpp
├── MainComponent.h
└── MainComponent.cpp
Large Plugin (20+ files)
Source/
├── Core/
│ ├── PluginProcessor.h
│ ├── PluginProcessor.cpp
│ ├── Parameters.h
│ └── Parameters.cpp
├── DSP/
│ ├── Effects/
│ │ ├── Filter.h
│ │ ├── Delay.h
│ │ └── Reverb.h
│ ├── Synthesis/
│ │ ├── Oscillator.h
│ │ └── Envelope.h
│ └── Utils/
│ ├── SmoothValue.h
│ └── RingBuffer.h
├── UI/
│ ├── PluginEditor.h
│ ├── PluginEditor.cpp
│ ├── Components/
│ │ ├── CustomSlider.h
│ │ ├── XYPad.h
│ │ └── Visualizer.h
│ └── LookAndFeel/
│ └── CustomLookAndFeel.h
└── Presets/
├── PresetManager.h
└── PresetManager.cpp
CMake Source Inclusion
Simple (few files)
target_sources(YourPlugin PRIVATE
Source/PluginProcessor.cpp
Source/PluginEditor.cpp
)With file globbing (many files)
file(GLOB_RECURSE PLUGIN_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/Source/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Source/*.h"
)
target_sources(YourPlugin PRIVATE ${PLUGIN_SOURCES})Note: GLOB_RECURSE requires CMake reconfiguration when adding new files. Some prefer explicit listing for this reason.
With source groups (IDE organization)
# Organize files in IDE (Xcode, Visual Studio)
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/Source"
PREFIX "Source"
FILES ${PLUGIN_SOURCES})Resources
Binary Resources
Include images, fonts, and data files:
juce_add_binary_data(YourPluginResources
NAMESPACE Resources
SOURCES
Resources/Logo.png
Resources/Background.jpg
Resources/CustomFont.ttf
)
target_link_libraries(YourPlugin PRIVATE YourPluginResources)Access in code:
#include "BinaryData.h"
// Use in your code
auto logoImage = ImageCache::getFromMemory(
Resources::Logo_png,
Resources::Logo_pngSize
);Presets
For factory presets:
juce_add_binary_data(YourPluginPresets
NAMESPACE Presets
SOURCES
Resources/Presets/Default.xml
Resources/Presets/Warm.xml
Resources/Presets/Bright.xml
)Dependencies
JUCE as Submodule (Recommended)
git submodule add https://github.com/juce-framework/JUCE.git external/JUCE
git submodule update --initPin to specific version:
cd external/JUCE
git checkout 7.0.9
cd ../..
git add external/JUCE
git commit -m "Pin JUCE to 7.0.9"Using FetchContent
include(FetchContent)
FetchContent_Declare(
juce
GIT_REPOSITORY https://github.com/juce-framework/JUCE.git
GIT_TAG 7.0.9
)
FetchContent_MakeAvailable(juce)Other Dependencies
Header-only libraries
# Add include directory
target_include_directories(YourPlugin PRIVATE external/header-only-lib/include)Compiled libraries
add_subdirectory(external/other-lib)
target_link_libraries(YourPlugin PRIVATE other-lib)Version Control
.gitignore
# Build directories
build/
cmake-build-*/
# IDE files
.idea/
*.xcodeproj/
*.xcworkspace/
# Generated files
Builds/
JuceLibraryCode/
# OS files
.DS_Store
Thumbs.db
# Dependencies (if not using submodules)
# external/JUCE/Submodule Initialization
Ensure builds initialize submodules:
# BeatConnect does this automatically, but for local builds:
git submodule update --init --recursiveMulti-Plugin Repositories
Shared code structure
my-plugins/
├── CMakeLists.txt # Root configuration
├── external/
│ └── JUCE/
├── shared/ # Shared code
│ ├── DSP/
│ │ ├── Filter.h
│ │ └── Filter.cpp
│ └── UI/
│ └── CommonLookAndFeel.h
├── PluginA/
│ ├── CMakeLists.txt
│ └── Source/
├── PluginB/
│ ├── CMakeLists.txt
│ └── Source/
└── PluginC/
├── CMakeLists.txt
└── Source/
Root CMakeLists.txt:
cmake_minimum_required(VERSION 3.22)
project(MyPlugins)
add_subdirectory(external/JUCE)
# Shared library
add_library(SharedCode STATIC
shared/DSP/Filter.cpp
shared/UI/CommonLookAndFeel.cpp
)
target_include_directories(SharedCode PUBLIC shared/)
# Plugins
add_subdirectory(PluginA)
add_subdirectory(PluginB)
add_subdirectory(PluginC)Plugin CMakeLists.txt:
juce_add_plugin(PluginA
PLUGIN_CODE PlgA
...
)
target_link_libraries(PluginA PRIVATE
SharedCode
juce::juce_audio_processors
)Build Configuration
CMakePresets.json
{
"version": 6,
"configurePresets": [
{
"name": "default",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "debug",
"inherits": "default",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "macos-release",
"inherits": "default",
"generator": "Xcode",
"cacheVariables": {
"CMAKE_OSX_ARCHITECTURES": "x86_64;arm64",
"CMAKE_OSX_DEPLOYMENT_TARGET": "10.13"
}
},
{
"name": "windows-release",
"inherits": "default",
"generator": "Visual Studio 17 2022",
"architecture": "x64"
}
],
"buildPresets": [
{
"name": "release",
"configurePreset": "default",
"configuration": "Release"
}
]
}Testing Your Structure
Local Verification
# Clean clone test
cd /tmp
git clone --recursive YOUR_REPO_URL test-clone
cd test-clone
# CMake configuration test
cmake -B build -DCMAKE_BUILD_TYPE=Release
# Build test
cmake --build build --config Release
# Check output
ls build/YourPlugin_artefacts/Release/Checklist
- Repository clones with all dependencies
- CMake configures without errors
- Build completes for Release configuration
- Plugin binaries are in expected location
- All resources are embedded
Common Structure Issues
Missing Submodules
Error:
CMake Error: add_subdirectory given source "external/JUCE" which is not a directory.
Fix:
git submodule update --init --recursiveWrong File Paths
Error:
CMake Error: Cannot find source file: Source/PluginProcessor.cpp
Fix: Verify paths in target_sources() match actual file locations.
Missing Resources
Error:
error: 'BinaryData.h' file not found
Fix: Ensure juce_add_binary_data() is called and linked:
juce_add_binary_data(Resources SOURCES ...)
target_link_libraries(YourPlugin PRIVATE Resources)