At the moment, the CMake support focuses on building plugins, gui apps, and console apps, using the JUCE ābuild everything directly into the final binaryā model. Unfortunately we donāt have android or library examples, yet.
There are good reasons in both cases:
The Android/Gradle build system expects to āownā the build, and will itself invoke CMake. That means itās not really possible to write a CMake-only Android build - Gradle is required too. Thereās also a lot of stuff that the Projucer normally does (like modifying and copying boilerplate Java files into the Gradle project) that we canāt easily recreate from a CMake build, because that stuff needs to happen before Gradle is invoked. Itās a bit of a circular problem, with no clear solution at the moment. That being said, it should be possible to create a new ānativeā project which includes a JUCE-dependent shared library in its CMake portion. This leads onto JUCE-dependent librariesā¦
Due to the way JUCE modules work, itās important that every module sees exactly the same set of JUCE_MODULE_AVAILABLE_* flags during the build, which in turn means that the final set of JUCE modules that end up in the build must be known ahead of time. When building JUCE into a library, itās very easy to run into situations where a JUCE module gets included twice in the build, sometimes with different flags, which is likely to introduce subtle bugs. We donāt really want to encourage this build model, because itās too easy to get it wrong.
With that out of the way, it should be possible to build a JUCE staticlib using a setup a bit like this:
This will build the audio_utils and dsp modules (along with all their dependencies) into a staticlib, which exports the recommended warning/config/lto flags in its interface. Note that if you choose to use an approach like this, the staticlib should be the one and only source of JUCE modules in the project. That means, all juce-dependent targets in the project should link against the same juce_plugin_modules target, and they should avoid linking any additional JUCE modules directly.
Regarding libraries: I would like to build libraries of my own code (not juce modules). My applications will use these libraries.
The projucer has static library project that could do that. How can this be replicated using the new CMke flow?
To create a custom library containing your own code, you can use the add_library function, which is a CMake built-in. A simple library might look like this:
# Tell CMake to add a static library target
add_library(custom_lib STATIC)
# Add sources to the target
target_sources(custom_lib PRIVATE
src_0.cpp src_0.hpp
src_1.cpp src_1.hpp) # etc.
# Tell CMake where our library's headers are located
target_include_directories(custom_lib PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}")
If you plan to use the library in a plugin, you may also need to set the following properties on the library:
Thanks.
Last question: when building the GUI example using CMake, I notice that I see the JUCE splash screen on startup, even though I have an indie license.
How do I should set the project so this splash screen will not be shown?
Is there an example CMakeFile example to that can be used to build and Audio Application?
I tried starting from the GUI app, but I get many errors along the wayā¦
There isnāt, but it shouldnāt be all too different to the gui app example. The AudioPluginHost also has a CMake build, so you could check that out to see how it works.
Sorry it took a bit of time to get back to you.
I was able to create an audio application using CMake. It took a bit.
Iām building now quite a large application, and it makes sense to ma to partition it to several static libraries, test console apps, and the final application (this is the method I have been using a lot to develop large scale programs using other frameworks, like Qt.
I believe it would be very useful if the JUCE CMake could have additional commands to add static or dynamic library targets. Just using add_library() command, requires to add a lot of other CMake directives to allow it to build correctly and link agains the other applications.
I agree it would be great to simplify the flow of static library creation with Cmake.
I do have to say, @YairAtRoli, that developing using JUCE modules can achieve a similar flow to what youāre after - this is exactly how weāre structuring things and have quite a lot of modules as well as apps/plugins/tests that call functions from those shared libs.
Indeed, using JUCE modules (or user modules) can achieve the same thing. However, for my application, Iām using proprietary (US Patented) algorithm we have developed. I assume that at a certain point, Iāll have to use some third party developers/company to work on the UI (as Iām not the greatest UI designer in the world ;-).
Having all the IP code as library, can enable that in a secure way (as I can not expose the source code).
So, what Iād do in your case is to build libraries that link with your juce-based code but donāt export any of the JUCE functions.
@reuk correct me if Iām wrong, but I think if youāre only exporting your own interface (and not JUCE) via DLL/static libs you shouldnāt have any problems, similar to how multiple DLL/VST files can live in a host environment while each one links to a different implementation of JUCE.
Thatās not what I meant - what youāre suggesting will not work (unless you use JUCE modules/interface libraries and expose your code).
What I think you should do is link your closed source part privately with JUCE, not exposing to the caller your internal library use.
Instead, only export your own functions like process() or calculateAlgorithm(). I believe that way you can accomplish what you wanted and hide code from your users (which could also link with a different version of JUCE if they want to).
I believe that this would be true for a dynamic library built with hidden symbol visibility. I think itās untrue for static libraries. Static libraries only support visibility in the plain C++ sense (internal/external linkage), and the bulk of JUCEās functions have external linkage. Statically linking two copies of JUCE into the same binary will result in ODR violations for this reason.
The recipe at the top of this post for adding a static lib of juce modules looks very handy, but Iām not sure how downstream dependencies should be configured w.r.t the juce headers. For example, if I create another static library which depends on juce_plugin_modules, how should I generate a juce header file for it? Generating a header works for juce_add_*-specific targets created using juce_generate_juce_header(), but if a target has been created with add_library(), itās not possible to use juce_generate_juce_header(). My current CMake recipe for a static lib is:
add_library(my_juce_lib STATIC)
# try to initialise the target as a JUCE target; also used for the juce_add_* targets, probably not the right way to do it though
_juce_initialise_target(my_juce_lib)
# this does work, but it doesn't detect the dependencies from the juce_modules linker target, so the header doesn't #include any juce headers
juce_generate_juce_header(my_juce_lib)
target_sources(my_juce_lib PRIVATE mysrc.cpp)
target_include_directories(my_juce_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(my_juce_lib INTERFACE juce_modules)
My use case is I want to break my logic out from my GUI code into its own lib so I can write tests against the lib (using gtest), but also still use juce code in my lib. Itās hard/impossible to do that if the logic is contained in the GUI app, because I canāt link the tests to an executable target.
Youāre right that itās currently not possible to generate a JuceHeader for a library. Iād recommend against directly calling any CMake function that starts with _juce - these should be treated as āprivateā functions, and they might change or disappear between releases.
Could you just include the necessary module headers directly, instead of using a JuceHeader? If you are using the ProjectInfo declarations, perhaps you can isolate these dependencies to the app target itself, which can generate a JuceHeader.
FWIW Iāve got something like this working (staticlibs depending on JUCE) with the following sort of setup:
# Set up JUCE library
add_library(juce_plugin_modules OBJECT)
target_link_libraries(juce_plugin_modules
PRIVATE
juce::juce_audio_utils
juce::juce_dsp
PUBLIC
juce::juce_recommended_config_flags
juce::juce_recommended_warning_flags)
target_compile_definitions(juce_plugin_modules
PUBLIC
JucePlugin_Build_Standalone=1
JUCE_STANDALONE_APPLICATION=JucePlugin_Build_Standalone
INTERFACE
$<TARGET_PROPERTY:juce_plugin_modules,COMPILE_DEFINITIONS>)
target_include_directories(juce_plugin_modules
INTERFACE
$<TARGET_PROPERTY:juce_plugin_modules,INCLUDE_DIRECTORIES>)
set_default_properties(juce_plugin_modules) # function defined elsewhere. enables PIC, hidden symbols
# Add dependent library
# Library includes JUCE module headers directly, rather than using a JuceHeader.h
add_library(foo STATIC)
target_sources(foo PRIVATE ${sources}) # sources set previously
target_include_directories(foo PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
target_link_libraries(foo PUBLIC juce_plugin_modules)
set_default_properties(foo) # function defined elsewhere. enables PIC, hidden symbols
# Do something similar for library 'bar'...
# Add plugin target
juce_add_plugin(plug
# etc.
)
target_sources(plug PRIVATE ${plug_sources})
target_include_directories(plug PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
target_link_libraries(plug PRIVATE foo bar)
target_compile_definitions(plug PUBLIC JUCE_VST3_CAN_REPLACE_VST2=0)