CMake: Creating 3rd Party JUCE Modules - Conventions

I just wanted to check if I’m configuring our 3rd party modules correctly to make them available to JUCE cmake. In the modules dir I add a CMakeLists.txt file with this content:

juce_add_modules(
    INSTALL_PATH "include/JUCE-${JUCE_VERSION}/modules"
    ALIAS_NAMESPACE tracktion
    tracktion_engine
    tracktion_graph)

Then in the project CMakeLists.txt file I add the module using these lines:

add_subdirectory(../../modules ./cmake_build_tracktion)
...
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
    tracktion::tracktion_engine
...

Does that all seem correct?
I just want to make sure before I add this to a bunch of other modules.

1 Like

The module-related code looks good to me!

The add_subdirectory call looks a bit suspicious - normally I’d try to avoid including parent/sibling directories with add_subdirectory. If you included modules directly from the top-level CMakeLists, you could avoid specifying a custom build output directory. Is there a reason this won’t work here?

Sorry, I’m not sure I follow… Do you mean I need to add a “top-level CMakeLists” or that the one in the module is this “top-level”?

If I don’t add this add_subdirectory call, how does CMake know where to look for my modules?

Sorry, yes I meant that normally I’d expect a CMakeLists in each directory, and for the add_subdirectory calls to only reference child directories, rather than siblings or parents. In this case, that would mean adding a CMakeLists to the directory which contains the modules directory.

Ok, I think I understand that part. I’ll add that.


It seems there’s some CMake magic going on that I don’t quite understand but I’ll trust that it “just works”. E.g. in the DemoRunner example CMakeLists.txt, what makes the JUCE functions and libraries (juce_add_gui_app etc.) available to it?
Does it recursively look up parent dirs until a suitable lists is found, like the one in the root dir?

If so, what you’re saying all makes sense.

The JUCE functionality is visible there because of inclusion order. When configuring a CMakeLists, the file is processed from top to bottom, but recursing into any directories included with add_subdirectory in a depth-first manner.

If our top-level CMakeLists.txt looks like this:

message("a")
add_subdirectory(inner)
message("c")

and inner/CMakeLists.txt looks like this:

message("b")

Then during configuration, we’ll see “a”, “b”, “c” printed in that order.

In JUCE’s top-level CMakeLists, we include JUCEUtils.cmake near the top of the file. This makes most of JUCE’s custom functions available. Then, we call add_subdirectory(modules) to make the modules available (these depend on the JUCE functions, but nothing else). Finally, we include the extras and examples subdirectories, which depend on both the modules and on the custom CMake functions.

1 Like

Ok, I think we’re talking at slightly cross purposes as I’ve structured my examples differently.
In mine, you can cd in to the examples dir and do a cmake -B build to generate the example project there.

It seems like you can’t do that with the juce DemoRunner example, it won’t be able to find those juce functions so you have to generate it using the parent directory, which includes the individual examples as you explained.


So back to the original point, I don’t think I can have this local example build without including parent directories. This might not be canonical CMake though.