What is going on with including headers in the Juce Demo?


#1

I’ve noticed that every file in the juce demo is not including any header files of code it’s using. I’m a relative newbie to JUCE, how is this possible? What is going on and how do I do this?

An example:

How is the class in MainWindow.h (in the JUCE demo) able to inherit “public DocumentWindow” and “public AsyncUpdater” without including any header files? I would expect it to not find those classes without first including “DocumentWindow.h” and “AsyncUpdater.h”, or some equivalent header file that includes both of them.

WTF is going on here? I fully acknowledge I’m a c++ newbie.


#2

You may have noticed that during compilation the compiler only compiles .cpp files (not .h files).

When the compiler sees an #include statement, it literally inserts the .h file contents in that place, doing so recursively until all files are included (meaning it will also include every .h file included by the .h file and so on).

Eventually, the compiler ends up with a large .cpp file containing the original code plus all the included files on top of it.
This compilation step is called “preprocessing” and is also the time when all the macros are evaluated. Generally, instructions starting with ‘#’ are processed during the preprocessor step and are called “preprocessor directives”.

For example, to prevent including the same file multiple times, “one time include guards” are used in the form of

#ifndef SOMETHING_DOT_H
#define SOMETHING_DOT_H
	//File contents
#endif

The #ifndef is a preprocessor directive (“if not defined”) and is evaluated during the preprocessor step.

So anyway, back to your question.

MainWindow.cpp has one include statement:

#include "JuceDemoHeader.h"

If you look inside it, you’ll notice that it expands into

#include "../JuceLibraryCode/JuceHeader.h"
#include "MainWindow.h"
#include "DemoUtilities.h"

You can see that JuceHeader.h is included here, which contains all the JUCE classes, like DocumentWindow and AsyncUpdater.

This is why these are available without explicitly including them from the MainWindow.h file - they’ve already been included from the .cpp file.

This is a very incomplete (and wrong) explanation and I suggest that you do some more reading on C++.

Happy Coding !


#3

Thanks for your input! I do understand how headers work in c++ — I’m more confused about how the juce code is compiled without including anything!

For example, looking at the FileBasedDocument in juce_gui_extras, how is that able to inherit from “ChangeBroadcaster” without including any header files?

If you look at the corresponding cpp file (FileBasedDocument.cpp) you can see that it isn’t including anything on either the .h or the .cpp end.

How and why? How can I define a class in a .h file that can inherit from ChangeBroadcaster without including anything? (including any juce headers — there are no included files in FileBasedDocument.h or FileBasedDocument.cpp).

I get how preprocessors work. How is it that the vast majority of the juce library can rely on the core juce code without including any header files?

Edit #2 — I’ve been making c++ apps for a few years now, just recently got introduced to JUCE, so I think I can understand any c++ concepts you could throw at me that would answer the question.

Edit #3 — How do you suppress IDE errors like the JUCE demo does when using classes not explicitly included at the beginning? How can I make a class like MainAppWindow that in the header file inherits from a couple classes that are only defined by a header file included in the corresponding .cpp file? Every time I try I get all kinds of errors, but I know it’s possible given that the JUCE demo doesn’t give me any errors.

Edit #4 — just to make it clear, if I try to make a header file called MainAppComponent that doesn’t include any header files (aka is exactly the same as the JUCE demo MainAppComponent.h along with MainAppComponent.cpp), I can’t have that class inherit from any juce classes without including the juce header. Obviously the JUCE demo doesn’t include anything in the header file, but the MainAppWindow class still inherits from classes that I wouldn’t expect the preprocessor to be able to find. Do I just need to deal with the fact that xcode won’t let me do what the JUCE demo does? I can’t believe that is actually the answer.


#4

To your question: it’s all in the C++ code, you don’t need to add any magic to XCode.

Explanation: you are looking at a header file, which is not compiled at all. So there is no need to define any symbols or classes. If you look at the cpp file, where this header is included, you find exactly one include, called JuceDemoHeader.h (saw it on your screenshot). This starts with the #include "../JuceLibraryCode/JuceHeader.h" header, where all modules are included. This file is created by the Projucer, who knows which modules you selected (the only magic, but has nothing to do with compiling, it’s just how to set up your project).

So the header does not need any includes (and therefore circular dependencies are avoided), but the sources (cpp) need them and they include it in the correct order, so that each class and symbol are first defined and used later… (simplified)

To your EDIT 4: in the implementation (cpp file) add the include to the JuceHeader and then the include to your class header in that order, and you should be fine


#5

Once again, the header files are not compiled, it’s the .cpp files.

So looking at the header file doesn’t tell you the full story, you have to examine the .cpp file which includes that header file to see what other headers are included before it.

For example, let’s assume we have a .cpp file which does

#include "header1.h"
#include "header2.h"

The code in “header2.h” can reference symbols declared in “header1.h”, even though “header2.h” does not include “header1.h”.
If we were to only include “header2.h” in our .cpp file, then those symbols would be undefined.
Equivalently, we could #include “header1.h” from “header2.h” for the same effect.

So I’ll just to repeat it - header files don’t tell you the full compilation story. Look at the .cpp files.


#6

Each .cpp that wishes to use JUCE code needs to #include "JuceDemoHeader.h":

->

->

… which then includes the header for each module used.

Check that out, that is unbelievably cool. The forum technology handles GitHub links!

Could the original poster re-categorise this under “getting started”?

π


#7

Re-categorised.


#8

It turns out I was just asking what a unity build is.

For anyone else looking for this info, this is the link I didn’t know I was actually asking for 2 years ago: