Way to detect if a module is present from another module

I am developing a juce module that depends on the juce_core module, but it could also provide more functionality if other modules are compiled in (but they are not mandatory). Is there a way i could detect if another module is present from my own module, in order to include and use it ?

I’ve tried using:

#include <juce_core/juce_core.h>

#if __has_include(<juce_gui_basics/juce_gui_basics.h>)
#include <juce_gui_basics/juce_gui_basics.h>

// ... Some more classes depending on juce::Component
#endif

But it seems i’m not lucky enough and those could always be found, because the selection of the modules to link is not affecting the include paths (for example not compiling in the juce_gui_basics module target in the CMakeLists.txt, but headers could be found still):

target_link_libraries (${PROJECT_NAME} PRIVATE
    juce::juce_core
    juce::juce_data_structures
    juce::juce_events
    juce::juce_graphics
    # juce::juce_gui_basics # <<<< Commented out here
    juce::juce_recommended_config_flags
    juce::juce_recommended_warning_flags)

Is there a way to achieve that ?

I was thinking of using weak symbols and dynamic_lookup, but it would require each juce modules to declare an extern “C” variable so to declare it weak in another module and determine at runtime if they are present. See for more info c++ - Is it possible to determine (at runtime) if a function has been implemented? - Stack Overflow

There are macros for that, I believe the naming pattern is JUCE_MODULE_AVAILABLE_<name>

1 Like

Oh nice ! wasn’t aware of those, thanks a lot. I’ve seen they are setup from cmake for each module target, but i assume from projucer i might need to include some header right ?

I’m not sure, but I think that the cmake support was just emulating the existing setup provided by the Projucer…

The Projucer should automatically add those defines to the project, it should “just work”, I’m not a huge fan of it but I also don’t have any better ideas.

I’m not a fan of a module changing its public interface based on what else the project is using. IMHO the better solution is to either have your module require these other modules, or to move the code that depends on these modules into another module that contains just that glue code and directly expresses a dependency on every module it uses

1 Like

I’m not changing any public interface, it’s just exposing more internal functionality. The alternative is to create a “shadow” module for each juce module, in practice doubling them, not very pretty either and more cumbersome to handle.

Personally to me this kind of approach is a bit error prone, as suddenly the code acts differently at runtime depends on different set of modules that are linked.

I’d probably prefer a compile definition the user is opting into, like ENABLE_FEATURE_XXX=1 which would then give an explicit linker/compiler error if required modules are missing.

1 Like

The module is just exposing bindings, so if you remove a module, it won’t be exposed to the scripting engine.