I recently converted one of my projects to CMake, and everything was going fine, until I decided to switch to using “#include <JuceHeader.h>”, so that I could update ProjectInfo at compile-time (e.g. to have access to a build-time string).
Inspecting the output of a build, I see that JuceHeader.h is generated and put into PROJECTNAME_artefacts/JuceHeader.h - but the rest of the targets are not updated to include (-I) that path, and therefore cannot find the JuceHeader.h file.
The weird thing is that this works fine in CLion, but it doesn’t work fine when I try to use ninja to build at a command-line (on my build server). I’m a little befuddled as to how to get the PROJECTNAME_artefacts/ directory to be included in all following targets as an INCLUDE directory … has anyone else run into this, and if so, whats the solution?
I thought of doing that, but I don’t like the idea of having to maintain it and it seems … weird … to have to do something manually like that, when the whole point of converting to CMake was to be able to get clean/safe builds done automatically.
Here’s my CMakeLists.txt, in case someone sees something obvious:
# 3.24.1 is bundled in Visual Studio 2022 v17.4
# 3.24.1 is also bundled in CLion as of 2023
cmake_minimum_required(VERSION 3.24.1)
# This tells cmake we have goodies in the /cmake folder
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include (PamplejuceVersion)
# Change me!
# This is the internal name of the project and the name of JUCE's shared code "target"
# Note: This cannot have spaces (it may be 2023, but you can't have it all!)
# Worry not, JUCE's PRODUCT_NAME can have spaces (and is DAWs display)
set(PROJECT_NAME "broombroomPlugin")
# Worry not, JUCE's PRODUCT_NAME can have spaces (and is what DAWs will display)
# You can also just have it be the same thing as PROJECT_NAME
# You may want to append the major version on the end of this (and PROJECT_NAME) ala:
# set(PROJECT_NAME "MyPlugin_v${MAJOR_VERSION}")
# Doing so enables major versions to show up in IDEs and DAWs as separate plugins
# allowing you to change parameters and behavior without breaking existing user projects
set(PRODUCT_NAME "broombroomPlugin")
# Change me! Used for the MacOS bundle name and Installers
set(COMPANY_NAME "broombroomPluginCo")
# Change me! Used for the MacOS bundle identifier (and signing)
set(BUNDLE_ID "com.w1xer.software.plugins.broombroomPlugin")
# Change me! Set the plugin formats you want built
# Valid choices: AAX Unity VST VST3 AU AUv3 Standalone
set(FORMATS Standalone AU VST3 AUv3)
# For simplicity, the name of the CMake project is also the name of the target
project(${PROJECT_NAME} VERSION ${CURRENT_VERSION})
# Configures universal binaries in CI
include(PamplejuceMacOS)
# Couple tweaks that IMO should be JUCE defaults
include(JUCEDefaults)
# JUCE is setup as a submodule in the /JUCE folder
# Locally, you must run `git submodule update --init --recursive` once
# and later `git submodule update --remote --merge` to keep it up to date
# On Github Actions, this is done as a part of actions/checkout
add_subdirectory(JUCE)
# Add any other modules you want modules here, before the juce_add_plugin call
# juce_add_module(modules/my_module)
# This adds the melatonin inspector module
# add_subdirectory (modules/melatonin_inspector)
# See `docs/CMake API.md` in the JUCE repo for all config options
juce_add_plugin("${PROJECT_NAME}"
# Icons for the standalone app
ICON_BIG "${CMAKE_CURRENT_SOURCE_DIR}/packaging/icon.png"
# Change me!
COMPANY_NAME "${COMPANY_NAME}"
BUNDLE_ID "${BUNDLE_ID}"
# On MacOS, plugin is copied to ~/Users/yourname/Library/Audio/Plug-Ins/
COPY_PLUGIN_AFTER_BUILD TRUE
# Change me!
# A four-character plugin id
# First character MUST be uppercase for AU formats
PLUGIN_MANUFACTURER_CODE OIDA
# Change me!
# A unique four-character plugin id
# Note: this must have at least one upper-case character
PLUGIN_CODE AAPD
FORMATS "${FORMATS}"
# The name of your final executable
# This is how it's listed in the DAW
# This can be different from PROJECT_NAME and can have spaces!
# You might want to use v${MAJOR_VERSION} here once you go to v2...
PRODUCT_NAME "${PRODUCT_NAME} v${MAJOR_VERSION}")
message(WARNING "The JUCE HEADERS WILL BE GENERATED FOR ${PROJECT_NAME}")
juce_generate_juce_header(${PROJECT_NAME})
# This lets us use our code in both the JUCE targets and our Test target
# Without running into ODR violations
add_library(SharedCode INTERFACE)
# C++20, please
# Use cxx_std_23 for C++23 (as of CMake v 3.20)
target_compile_features(SharedCode INTERFACE cxx_std_20)
# Manually list all .h and .cpp files for the plugin
# If you are like me, you'll use globs for your sanity.
# Just ensure you employ CONFIGURE_DEPENDS so the build system picks up changes
# If you want to appease the CMake gods and avoid globs, manually add files like so:
# set(SourceFiles Source/PluginEditor.h Source/PluginProcessor.h Source/PluginEditor.cpp Source/PluginProcessor.cpp)
file(GLOB_RECURSE SourceFiles CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/source/*.h")
file(GLOB_RECURSE SourceLookAndFeelFiles CONFIGURE_DEPENDS" ${CMAKE_CURRENT_SOURCE_DIR}/resources/lookAndFeel/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/resources/lookAndFeel/*.cpp")
target_sources(SharedCode INTERFACE ${SourceFiles} ${SourceLookAndFeelFiles})
# We intend to only use BinaryData.h from JuceLibraryCode
#juce_add_binary_data("${PROJECT_NAME}")
# Adds a BinaryData target for embedding assets into the binary
include(Assets)
# MacOS only: Cleans up folder and target organization on Xcode.
include(XcodePrettify)
# This is where you can set preprocessor definitions for JUCE and your plugin
target_compile_definitions(SharedCode
INTERFACE
# JUCE_WEB_BROWSER and JUCE_USE_CURL off by default
JUCE_WEB_BROWSER=0 # If you set this to 1, add `NEEDS_WEB_BROWSER TRUE` to the `juce_add_plugin` call
JUCE_USE_CURL=0 # If you set this to 1, add `NEEDS_CURL TRUE` to the `juce_add_plugin` call
JUCE_VST3_CAN_REPLACE_VST2=0
JUCE_MODAL_LOOPS_PERMITTED=1
# Uncomment if you are paying for a an Indie/Pro license or releasing under GPLv3
# JUCE_DISPLAY_SPLASH_SCREEN=0
# lets the app known if we're Debug or Release
CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}"
VERSION="${CURRENT_VERSION}"
# JucePlugin_Name is for some reason doesn't use the nicer PRODUCT_NAME
PRODUCT_NAME_WITHOUT_VERSION="broombroomPlugin"
)
# Link to any other modules you added (with juce_add_module) here!
# Usually JUCE modules must have PRIVATE visibility
# See https://github.com/juce-framework/JUCE/blob/master/docs/CMake%20API.md#juce_add_module
# However, with broombroomPlugin, you'll link modules to SharedCode with INTERFACE visibility
# This allows the JUCE plugin targets and the Tests target to link against it
target_link_libraries(SharedCode
INTERFACE
Assets
melatonin_inspector
juce_audio_basics
juce_audio_devices
juce_audio_formats
juce_audio_processors
juce_audio_utils
juce_core
juce_dsp
juce_events
juce_graphics
juce_gui_basics
juce_gui_extra
juce_opengl
juce::juce_recommended_config_flags
juce::juce_recommended_lto_flags
juce::juce_recommended_warning_flags)
add_custom_target(host_header DEPENDS
$<TARGET_PROPERTY:${PROJECT_NAME},JUCE_GENERATED_SOURCES_DIRECTORY>/JuceHeader.h
)
# Link the JUCE plugin targets our SharedCode target
target_link_libraries("${PROJECT_NAME}" PRIVATE SharedCode)
# IPP support, comment out to disable
include(PamplejuceIPP)
# Everything related to the tests target
include(Tests)
# A separate target keeps the Tests target fast!
include(Benchmarks)
# Pass some config to GA (like our PRODUCT_NAME)
include(GitHubENV)