CMake questions

Hi, so I’m looking at moving over to CMake and have some questions for those in the know.

  1. Is it possible to specify different paths for different systems, e.g. juce_set_vst2_sdk_path which will be different on Mac and Windows
  2. Is it possible to have differences between Debug and Release builds, e.g. different defines sometimes set for release build for example
  3. Is it possible to manage different schemes, for example in some of my projects I have V1 and V2 builds which contain different build defines
  4. Do I need to do anything special for my modules that I have or do I just include them in CMakeLists like I would a juce module?

thx

  1. Sure, you can use something like:
if (WIN32)
  juce_set_vst2_sdk_path (<win_path>)
elseif (APPLE)
    juce_set_vst2_sdk_path (<mac_path>)
endif()
  1. This depends on the build system you want to use, especially if you use a multi-config exporter (xcodebuild/msbuild) or a single-config exporter (ninja, nmake, make).
    The difference is that with single-config exporter the build-type is known when you invoke cmake, in that case you can simply query the CMAKE_BUILD_TYPE variable:
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
  target_compile_definitions (<target> PRIVATE "YOUR_DEBUG_FLAG")
elseif (CMAKE_BUILD_TYPE STREQUAL "Release")
    target_compile_definitions (<target> PRIVATE "YOUR_RELEASE_FLAG")
endif()

In case you’re using a multi-config exporter (default on windows), you need to use generator expressions, as the build type is not known when you invoke cmake. Then you’d probably use something like:

target_compile_definitions (<target> PRIVATE $<$<CONFIG:Debug>:"YOUR_DEBUG_FLAG">)
target_compile_definitions (<target> PRIVATE $<$<CONFIG:Release>:"YOUR_RELEASE_FLAG">)
  1. As you can use different compiler definitions depending on your build type, you can also define your own cmake-variables. E.g. you could configure a cmake option for you project version and change the flags like this:
...
option(YOUR_PROJECT_VERSION "Determins the version of the project" 1)
...
if (YOUR_PROJECT_VERSION STREQUAL "1")
    target_compile_definitions (<target> PRIVATE "BUILD_VERSION_1")
elseif (YOUR_PROJECT_VERSION STREQUAL "2")
    target_compile_definitions (<target> PRIVATE "BUILD_VERSION_2")
endif()

and change the option when invoking cmake:
cmake .. -D YOUR_PROJECT_VERSION=2

  1. No, just make sure that you incude juce first.
3 Likes

thanks for that - really helpful :slight_smile:

regarding 4, not quite sure what you mean.

I’m adding a module and then looking at the generated JuceHeader.h which is different to the one generated by producer, which contains includes for the module header file, whereas the cmake one doesn’t. is that to be expected? thx

Check this out, this is a full CMake-based template for a plugin with support for all formats (AAX, AU, AUv3, VST2, VST3), Mac and Windows, and it doesn’t even require a full installed version of XCode on Mac:

I discovered that recent JUCE bundles VST3 SDK, and only a few extra files are necessary to support VST2, so the vst2 SDK path is short-circuited to the same location where JUCE stores VST3.

Where possible, JUCE is configured and patched to generate binaries that should be still compatible with Mac OSX 10.9

1 Like

thx, looks interesting, will definitely explore.

No custom modules it seems though so not sure it’ll fix the problem I’m having… thx

I think that all you need is to call juce_add_module (<path>), and then link against the module as you are doing with the JUCE-modules. If you’re including the JuceHeader.h, then you can probably simply use your modules without any problems.
It is to be expected that the header-file looks different, since Projucer and CMake use different mechanisms to manage the includes!

1 Like

Note that in case you want to use the old JuceHeader.h approach, you have to explicitly enable it in CMake via

juce_generate_juce_header (<target>)

This is the case as it’s not recommended best practice anymore to use it if I got it right, but it should work just fine with that comment in case your project relies on it.

The repo from @gyohng1 looks quite detailed. From my experience a lot less lines of cmake are needed to create a usual plugin, that should just work with macOS 10.9 by just setting the CMAKE_OSX_DEPLOYMENT_TARGET cache variable right. You might want to start simple with the JUCE example as a template JUCE/CMakeLists.txt at master · juce-framework/JUCE · GitHub. In case it’s helpful here is the CMakeLists.txt of an open source plugin by me, although there are also a few special solutions that are probably not relevant to your project, so I don’t recommend this as a template, just as some kind of inspiration Schrammel_OJD/CMakeLists.txt at master · JanosGit/Schrammel_OJD · GitHub

2 Likes

Very interesting topic, thanks!

Let me add one such question myself about CMake: is it possible to specify pre- and post- build scripts?

In my projects, I have cross-platform python scripts that take care of several operations that must happen before and after each build, and it would be absolutely a pain to re-implement them in “native” CMake. Transition would be much easier if I could simply tell CMake to execute them for me.

For post-build scripts you can use custom commands:

add_custom_command (TARGET <target> POST_BUILD COMMAND <command>)

Pre-built scripts are slightly more annoying. While you can use add_custom_command with a PRE_BUILD argument, with all build systems except for msbuild this will actually be post-compile pre-link, so probably not what you want.
Therefore the usual way is to add a custom target and add it as dependency to your actual target:

add_custom_target (<target>_PrebuiltScript COMMAND <command>)
add_dependency (<target> <target>_PrebuiltScript)
2 Likes

Thanks for all the input from everyone - will be giving this a good go tomorrow

Hi, things going pretty well but for some reason get this unresolved:

Undefined symbols for architecture arm64:
“juce::OnlineUnlockStatus::MachineIDUtilities::getUniqueMachineID()”, referenced from:

I’ve included the juce::juce_cryptography target in target_link_libraries. Obvs finding the headers ok, but not linking. Any suggestions? thx

I think that class is in the juce_product_unlocking module?

1 Like

ah, yes, thx - thought it was part of cryptography

thx - I’m after a post-build step to copy the generated application folder into /Applications. Can this be done?

Sure, for example you could use the CMake command-line tool mode:

get_target_property (OUTPUT_DIR <target> RUNTIME_OUTPUT_DIRECTORY)
add_custom_command (TARGET <target> POST_BUILD COMMAND ${CMAKE_COMMAND} -R copy_directory ${OUTPUT_DIR} /Applications)

Note that it might be necessary to adapt the command since macOS is using bundles instead of plain executables like windows.

1 Like

thanks for everyone’s help and tips - now have cmake build up and running for Mac.

I’m working on getting this working for Windows also and having issues. Please note this is a Windows 11 arm VM running under Parallels, and this is when trying to install JUCE. Normal builds run under Vis Studio 2022. Any tips? thx

C:\Users\lee\dev\JUCE\modules\juce_core\native/juce_win32_SystemStats.cpp(27,10):
warning C4163: ‘__cpuid’: not available as an intrinsic function (compiling
source file C:\Users\lee\dev\JUCE\modules\juce_core\juce_core.cpp)
[C:\Users\lee\dev\JUCE\cmake-build-install\tools\extras\Build\juceaide\juceaide.vcxproj]

I believe the error regarding __cpuid has something to do with building for ARM, see here (there are proposed solutions at the end of the topic, don’t know if they work):

1 Like

thx - will check it out!

Is there any reason why building a VST3 with Projuder just installs a .vst3 file to the destination directory, whereas with cmake it copies a whole folder across?

also CMAKE_BUILD_TYPE isn’t being used on Windows - seems ok on Mac

I also had that question when we switched to CMake back then.

The folder is a vst3 bundle, which is the newer version of how vst3 should be distributed – similar to AU and AAX and is recommended by Steinberg for new plugins. The non-bundle format is still allowed for legacy compatibility reasons though.

I think as the CMake system was implemented later, they wanted to take the recommended route there while the Projucer solution with a plain file was created earlier and is left like that for backwards compatibility?

2 Likes