FR: more compact JUCE module headers

We have quite a lot (30+) custom JUCE modules used in multiple products, unit tests, etc, and I noticed that adding any JUCE module include to a module can really inflate compile times, compared to the same module without any JUCE includes.

It would be great if some of these high level modules could be split into more compact modules.

For example: I’m fine with juce_gui_basics bringing in a bunch of widgets, and no backwards compatibility should be broken for that module.
But - in modules with just my custom Components, I’d just like to include the absolute minimum for juce::Component (and maybe primitives it needs, like Colour and Graphics) and limit the scope of what that module knows about and need to compile.

A few other important ones:

  1. I would have liked to be able to inherit from juce::AudioProcessor without also bringing in the plugin formats and plugin hosting.

  2. juce_audio_basics has quite a lot of higher level objects like ADSR, Reverb, MPESynthesiser, etc, which I don’t want to include most of the time.

  3. juce_core brings a bunch of rarely used things like JS parser, zip files… A lot of these can just be included whenever used.

Does that make sense? I believe most of these changes can be made without any breaking change for users of existing modules.

That would be great! Another use case is when hosting plugins but the host uses a different GUI framework, e.g. QT in my case.
Currently the juce_gui_basics pulls in a ton of GUI widgets, because the AudioProcessorEditor from AudioProcessor/PluginInstance requires the juce::Component.

Splitting that up into the actual basics and a juce_gui_widgets or whatever it will be called would help a lot

5 Likes

It sounds like what you’re asking for is to remove the module dependancy when including juce header files. I.e all juce header files should include the headers they depend on. You could then include just the juce headers you wanted, as long as you compiled the module at some point in your app.

I think this would be a good move but much harder to maintain.

On the other hand, C++20 modules might make this kind of organisation moot as it should be lightning fast to juce import juce. Apparently the quickest way to import the STL is all in one go with import std rather than each library individually or even grouped. That kind of support is probably a way off though (sounds like it might be coming to cmake later this year).

6 Likes

You’re totally right.
I would, in theory, just love to just include juce_component.h and be done with it.

But, since that would be a major change in the way JUCE builds, I’m trying to suggest a more pragmatic change, that wouldn’t require rewriting the whole framework differently.

For example, you can change juce_gui_basics so it’s just a container module for juce_gui_essentials and juce_widgets, and nothing will break in user code.

Edit: I believe that even in the future when C++20 modules are here and compile everywhere, the logical process of splitting juce_gui_basics into smaller libraries would be needed.

2 Likes

Another important note:
JUCE unfortunately doesn’t have explicit includes in the built in modules. That means that if I #include juce_Component.h directly, I will need to poke quite hard at the module to find all the “really needed” includes, which as @dave96 mentioned would also probably break whenever JUCE updates something.

In this thread:

We talked about the problem and I offered a solution (explicit includes). Doing that can certainly make single includes possible, but it would still force me to link against the the widgets library when all I wanted was the base classes.

2 Likes

sry for slightly offtopic but i’d appreciate if juce actually had c++20 modules to solve certain problems (like this one) in the future, because even though it can also be solved in a more backwards-compatible way i’d say it’s worth to use because
a) i looked into modules and they really seem to improve the whole c++ language, especially for people who are fans of header-only libs like me
b) when i learned c++ in the first place i learned a lot from just looking at juce’ code itself so it should include and sensibly showcase all language features that are really useful. a lot of people are like me and learn more from watching exciting audio framework-code than from abstract c++ tutorials on youtube or the actual API of things

pls mostly ignore this comment as i don’t want to hijack this thread!

1 Like

The problem with C++20 modules is the tool-chain support. Correct me if I’m wrong but the only way to build them at the moment is with VS2022 or custom makefiles (invoking the extra steps required in the compiler to generate the bmi files etc.)?
I’m hoping when CMake adds support for them this will be much easier.

The other problem with a library is backwards compatibility though. JUCE supports back to C++14(?) so I can’t see a way it could support modules without dropping support for anything pre-20 which would be a big change of direction (although not one I’m completely against…).

One outstanding question I have is if simply building your app code as modules and importing existing C++ header files will offer great speedups anyway. I had heard early on that the build systems can cache template instantiations* which could offer a decent speedup anyway. This all remains to be seen in practice though.

* This relies on the build configuration including all macros etc. being identical between compilation units. I.e. modules can not import macros from files, only the command line (and maybe config files).

1 Like

Yes, modules do bring up a lot of promises on compile time speed and a lot of questions, as well. I think integration will be difficult for at least a few years though.

I do think that regardless of when C++20 modules are viable option from a tool perspective, there is a big section of JUCE that in many projects I would like to never build and never link against, regardless if it’s using C++20 modules, JUCE modules, or static library.

C++20 Modules only solve the low level aspect of that, but the high level way to choose which parts of library are composable by users is not solved by it.

1 Like

Yep at least ; (i use C++14) (like many). C++11?

There used to be some modules that were C++11 and one or two that required 14 but I have a feeling 14 is the global minimum standard now (juce_core requires C++14).

It’s officially C++ 14 since this commit:

3 Likes