How to create a static library that use JUCE in official CMake?

We’ve been using JUCE since version 3. At that time, we made a self-written CMake system that compiles JUCE into a static library, then use it everywhere. By using that, we’ve created lots of JUCE-dependent codes that compiles into static libraries.

Recently I noticed JUCE have provided official CMake support. However it seems I can’t make JUCE-dependent static libraries with it? Instead, I must make my library codes into JUCE modules via juce_add_module? This would break a lot of our existing code.

Note that it isn’t officially supported to create static libs from the juce-modules (see here).

Having said that- this could work for you:

add_library (juce_staticlib)
target_link_libraries (juce_staticlib PRIVATE juce::juce_core)

Note that its necessary to use private linking here, otherwise the juce-modules would be recompiled when consuming the juce_staticlib, since they are interface targets. On the other hand, compiler flags and include directories ect. are not propagated correctly when using private linkage.

We’ve faced this problems when trying to link a plugin-shared-code-target against a console application for unit testing. We’re using some dirty trickery to work around this:

# add console app
add_executable (unit_test_target)

# use the same C++ standard
get_target_property (PLUGIN_TARGET_CXX_STANDARD plugin_target CXX_STANDARD)
set_target_properties (unit_test_target PROPERTIES CXX_STANDARD ${PLUGIN_TARGET_CXX_STANDARD})

# use the same include directories
target_include_directories (unit_test_target PRIVATE $<TARGET_PROPERTY:plugin_target,INCLUDE_DIRECTORIES>)

# use the same compiler flags
target_compile_options (unit_test_target PRIVATE $<TARGET_PROPERTY:plugin_target,COMPILE_OPTIONS>)

# use the same macros
target_compile_definitions (unit_test_target PRIVATE $<TARGET_PROPERTY:plugin_target,COMPILE_DEFINITIONS>)

This works fine in our case, but I’m not sure whether this will produce the correct results in every situation.

The new CMake support was intended to make it easy for people to migrate from Projucer projects, while allowing users to write idiomatic modern(ish) CMake scripts. Before we added CMake support, the overwhelming majority of our users consume JUCE code through JUCE Modules, rather than using custom static/dynamic libraries, so this is the use-case for which we optimised.

Additionally, it can be dangerous to reuse the same JUCE object files across multiple projects if each project requires different module options. When sharing a JUCE static library between targets, you must make sure that all dependent targets use exactly the same set of JUCE modules and module configuration flags.

All of that being said, if you’re aware of the dangers then you could use an approach such as the one described in the following post to create a JUCE staticlib:

From there, it’s straightforward to make your own staticlib targets that depend on the custom JUCE staticlib.

3 Likes