I see two potential problems.
The main problem is that you’re linking storage like so:
target_link_libraries(storage PUBLIC juce::juce_core ...)
Then, later you link the app target like so:
target_link_libraries(app PUBLIC storage juce::juce_audio_processors)
JUCE modules are CMake “interface” targets, which means that their source files get separately built into each target that links against them privately or publicly. So, the lines above will build juce_core once for storage, and again for app. The linker will end up seeing two copies of all definitions in juce_core, which breaks the One Definition Rule and results in undefined behaviour, such as crashes.
I can think of a couple of solutions to this first problem:
- Recommended: restructure your “storage” code as a JUCE module, using the docs in
docs/JUCE Module Format.md. You can make CMake aware of the module by callingjuce_add_module. Then, link yourapptargetPRIVATEly against yourstoragemodule and any other JUCE modules. This addresses the problem by ensuring that each module will be built, once, directly into the final executable. - Advanced: Use the approach described in this post to build the JUCE modules used by your app (juce_audio_processors and its dependencies) into a single static library. Then,
storageandappcan both linkPUBLICly against this static library. If you follow this approach, make sure that the new static library is the only target that links directly against any JUCE modules. All other targets must link only against this new static library target. This addresses the problem by building all JUCE modules once into a static library, on which other libraries may depend.
The second problem I see is that you’re using add_executable instead of juce_add_console_app or juce_add_gui_app to define your executable target. This is generally not recommended, as the juce functions do some useful work including setting up necessary preprocessor definitions on the executable target.
