Native, built-in CMake Support in JUCE

It works fine now.

My advice would be to drop the JuceHeader thingy and include directly Juce.
And using CMake you can propagate the required defined

Yes, I’d echo @otristan’s advice. Building a JUCE staticlib should work using the snippets from earlier in this thread, but this approach will not support generating a JUCE header. If you really need a single header for the library (which I don’t recommend!) you can just write your own JuceHeader.h which includes all the module headers from the staticlib, and then make sure that the path to this header is included in the staticlib’s INTERFACE include directories.

I’m really interested in doing this… a couple of questions about the status of this now…

platform

Id like to build VST plugins (only) for linux (arm) and macOS (intel) … already working on Juce 6 (master), they are GPL’d
good to go?

examples?

is there an example of how I can ‘migrate’ from my current projucer makefiles to this.
(Im familar with cmake for other projects, so its just a matter of how Id use juce)

@otristan is you last post, a good ‘example’ starting point?

Im guessing the defines shown in your CMake file are the same as used by projucer.

usage

I’d like to compile on the command line with cmake.
though on the mac, Id also like to import the CMake file into CLion - for normal Cmake projects this works fine - am i likely to face any issues for these juce cmake projects?

stability

anything I should be aware of?
I guess I can do this alongside my existing projucer build for now.
but wondering how much time this is going to take me to do, and if its likely to be a reasonable investment in time.
(I’d LOVE to be moved to cmake for juce… I respect the ideas behind Projucer, but its not really ‘my thing’… as I like to have my build systems in plain text :wink: )

Yes, although mac+intel is better-supported than linux+arm. If you run into any issues please let us know and we’ll investigate.

There’s no walkthrough of converting a Projucer project to a CMake project. However, there are well-documented example projects in examples/CMake in the JUCE repo, so I’d recommend starting there. There’s also a CMake API reference in the docs folder, which may be useful.

Probably not, using JUCE as a staticlib is quite an advanced use case which is quite different to the build configuration generated by the Projucer. Again, I’d recommend checking the example projects in the repo if you’re converting an existing Projucer project.

Building in Clion and on the commandline should both work.

If you’re already familiar with CMake, it won’t take long to get up and running - definitely hours rather than days.

1 Like

Yes, thank you, that’s what I did - I made my own JuceHeader.h with all includes and a use namespace, merely a refactoring help but I don’t want to touch 300 source files right now :wink:

I got one step further with the example above - the trick seems to be to “link” (include) JUCE into my lowest level library, so that all further static libs and executables get JUCE delivered with this. I will experiment further.

Still, it is unclear to me how the compiler defines get propagated into higher level libraries. If I do add a target_link_libraries(… juce::juce_core etc), then I get the compiler defines, but also have to compile juce again, and get a bloated static lib with JUCE included. I don’t necessarily want 15 JUCE copies, so a way to specify only include directoy (easy) and compiler defines (unknown how to) for subsequent libraries would be great. I think target_link_libraries() does too much?

Thanks Olivier as well, I read your comment this morning and it got me started again!

you just need to setup one lib with your custom juce setup which all your libs will depend on.
by linking in public to this lib, cmake will fwd the preprocessor def that you have defined on this lib

add_subdirectory(${PROJECT_SOURCE_DIR}/../JUCE ${CMAKE_CURRENT_BINARY_DIR}/JUCE)

target_link_libraries(myCustomJuceLib
    PRIVATE
    juce::juce_audio_basics juce::juce_audio_devices juce::juce_audio_formats
    juce::juce_audio_processors juce::juce_audio_utils juce::juce_core
    juce::juce_cryptography juce::juce_data_structures
    juce::juce_events juce::juce_graphics juce::juce_gui_basics
    juce::juce_gui_extra juce::juce_opengl juce::juce_video
)

target_include_directories(myCustomJuceLib
    INTERFACE
        $<TARGET_PROPERTY:myCustomJuceLib,INCLUDE_DIRECTORIES>)

target_compile_definitions(myCustomJuceLib PUBLIC
    JUCE_PLUGINHOST_VST=0
    JUCE_PLUGINHOST_AU=0
    DONT_SET_USING_JUCE_NAMESPACE=1
    JUCE_DISPLAY_SPLASH_SCREEN=0
    JUCE_REPORT_APP_USAGE=0
    JUCE_QUICKTIME=0
    JUCE_USE_DIRECTWRITE=1
    JUCE_COREGRAPHICS_DRAW_ASYNC=1
    JUCE_WIN_PER_MONITOR_DPI_AWARE=1
    JUCE_USE_FLAC=0
    SOME_OTHER_DEFINE_FOR_LIB
    INTERFACE
        $<TARGET_PROPERTY:myCustomJuceLib,COMPILE_DEFINITIONS>
)

set_target_properties(myCustomJuceLib PROPERTIES
    POSITION_INDEPENDENT_CODE TRUE
    VISIBILITY_INLINES_HIDDEN TRUE
    C_VISIBILITY_PRESET hidden
    CXX_VISIBILITY_PRESET hidden)

Awesome, will try that!

ok, giving it a go :slight_smile:

one thing thats unclear from the juce build/examples is how to include juce
(i.e my projects are not going to be under a sub director of juce)

so my project is
projectdir/juce <-- this is a submodule from git
projectdir/vsts
projectdir/vsts/vst1project
projectdir/vsts/vst2project

so, I have my cmake files doing subdir as normal
but how do I include juce?

something like? (in projectdir/cmakelist.txt)

add_subdirectory(${PROJECT_SOURCE_DIR}/juce ${CMAKE_CURRENT_BINARY_DIR}/juce)

but that seems to start building juce…
I just want to include it…

also…
do I remove
projectdir/vsts/vst1project/JuceLibraryCode

that projucer created?! I assume this is no longer needed…
as they are replaced with

target_link_libraries(VST1 PRIVATE
    # AudioPluginData           # If we'd created a binary data target, we'd link to it here
    juce::juce_audio_utils)

also the _juce_add_pips is this needed, or just something about the JUCE build?

the rest looks straightforward …
I guess its just knowing how the example cmakefiles related to a project that is using juce rather than part of juce.

EDIT: oops, sorry, didn’t see docs/CMake API.md.
Im sure that answers the above :slight_smile:

Just call add_subdirectory(path/to/juce) before calling any of the juce_ CMake functions.

The first time you configure the project, it will build a little helper tool named juceaide which is used to generate files such as icons, plists, entitlements, and binarydata sources. This could be the thing you see being built. The CMake configuration process should complete shortly after juceaide finishes building.

This isn’t strictly necessary, but it’s recommended as these files aren’t used in the CMake build.

If you’re porting a plugin project, you should use examples/CMake/AudioPlugin/CMakeLists.txt as a template.

Any function that begins with a leading underscore (e.g. _juce) is private and may be removed/changed in the future. You should not call such functions in your own CMakeLists.

2 Likes

ok, excellent…
so far very easy to do, took me less than an hour to get first one building under macOS.
(ready to go on unix, just need to test it … then it’ll be quick to do all the other VSTs)

one question, its GPL’d so how do I get rid of the ‘splash logo’ when it starts?

If your JUCE license allows you to disable the splash screen, you may add JUCE_DISPLAY_SPLASH_SCREEN=0 in your target’s compile definitions. This will turn off the splash screen for that target.

1 Like

thanks… test on my arm target, and its working well there too…
so think, Im going to over wholesale over to this - I love cmake , very happy day :slight_smile:

one small question,
so vsts are being built as ‘libvstname.so’ on linux

id like this as just vstname.so
I tried using

set (CMAKE_SHARED_LIBRARY_PREFIX "") 

that didn’t seem to work.

i also tried set_target_properties() , but that also didn’t work ?!

thoughts?

its not a big deal, I could create a step to rename vst at the end, but I thought the above would workd?!

have you tried ?

set_target_properties(${PROJECT_NAME}_VST PROPERTIES OUTPUT_NAME "vstname")

Have you tried the PRODUCT_NAME argument to juce_add_plugin?

yeah PRODUCT_NAME is there, and its add ‘lib’ as a prefix
(in fairness, this is pretty normal cmake/linux behaviour)

@otristan ah… thats it, missing the _VST

I was using

set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")

but I needed :

set_target_properties(${PROJECT_NAME}_VST PROPERTIES PREFIX "")

thanks for that… I should have watch better what targets add_plugin is generating!

You can’t make a GPL VST plugin, the VST SDK prevents that.
Did you mean to make a VST3 plugin?

yeah, im talking vst rather than au or standalone
I’m building vst3… but of course user can build vst2 (assuming the go get the sdk off steinberg)

this is great! was able to convert a simple plugin that used Projucer to CMake without much prior knowledge about CMake. still have one question tho:

what’s the preferred way to define global paths to eg. VST2 or AAX SDKs without Projucer? do they always have be passed via the CLI when invoking cmake? or should the CMake cache system be used somehow?

Definitely no need to pass those via CLI.

Personally I like to have “Super Build” projects that define everything that project needs that is ‘constant’, so that the developer doesn’t have to remember all these configurations when just working on the project or building it.

So that would look something like:

add_subdirectory(SDKs/JUCE)
juce_set_vst2_sdk_path(${CMAKE_CURRENT_LIST_DIR}/SDKs/VST2)
juce_set_aax_sdk_path(${CMAKE_CURRENT_LIST_DIR}/SDKs/AAX)
add_subdirectory(MyPlugin)

Great job adding CMake building support.
I’m curious, if there is an ability to generate an Android Studio project from project CMakeLists.txt, or it’s still only Projucer-backed functionality?