I'm compiling a large, multi-file project which has over a dozen external libraries and their associated header files. I put those header files into one large "project" header file which also includes function prototypes and extern declarations. At the top of the header file I have:
#ifndef BEENHERE #define BEENHERE #endif
Then, at the top of each cpp file I have:
#ifndef BEENHERE #include "project.h" #endif
The goal is to read the project header file only once. My question is: Does the compiler read the header only once anyway or not? It seems that you must have the #include directive in each source file or you get unresolved externals for each file. I've had others tell me that the compiler reads the header files first, then the ino file, then the support files. However, if that was true, I wouldn't be getting the scoping errors. So, it appears that the #include directive is needed in each source. How does the compiler read the headers?
First, the compiler doesn't read anything. The Pre-processor simply inserts the content of each file at the point of the #include directive. When the Pre-processor is done, it hands the entire compilation unit (.cpp file + all #include(s) + macro substitutions + conditional compilation decisions) to the compiler.
You don't need that. All you need is include guards in each .h file.
I don't really get exactly what you did, but AFAIK the #if preprocessor directives are read and replaced (i.e. including or excluding portions based in the conditions) then the #includes are processed in the given order, starting from the main .ino/.cpp module.
So in my projects if I ave a "master header" to be included I do it as first inside main .ino:
// Start of main module: this must come FIRST
#include "master.h"
// then...
#include "another.h"
... and so on
...
But that header should have the whole code inside the #ifndef before the #endif (you did that?):
This way, each sub-module, defined at the top of the after the master.h, can have the plain #include:
#include "master.h"
I don't know if my projects are smaller than the one you're talking about, but that's what I sometimes do: if something still goes wrong I'd investigate on some library incompatibility...
This is a known approach, but you are using it incorrectly.
If you want the file to be included once, these lines should not just be placed at the beginning of the file, but cover all its contents, like this:
file project.h
#ifndef PROJECT_H
#define PROJECT_H
// contents of the project.h
....
#endif // this line MUST BE the last line of the file
i read a book about development of very large applications. it was written about some CAD software.
one of the first things discussed was putting the #ifndef not in the include but in the file #including the header.
the .h file is completely read (by the preprocessor) with the #ifndef in the .h file regardless of the #def. the author of the book said each .h file could be read dozens(?) of times and there are many .h file references in each .cpp that it cost them too much time.
i think he said it could take a week to fully recompile their app (this was back in the 90s)
Every library I know has the #ifndef directive just inside its main header file, thus programs just need to #include such *h and nothing more (e.g. no #ifndef), and everything works fine.
Yes, I got it, but your question was about "unresolved externals", asking "How does the compiler read the headers?": did you understand my answer was just answering that question? I told you I did someting similar (for smaller project, but with the same "global" header file) and it works exactly like any library, provided you use #ifndef on your global header to let the compiler do the work one single time.
Obviously you need to #include it in every *.ino and *.cpp files (the compiling sequence IMHO depends on the other *.cpp and libraries *.h #include lines sequence you put inside the main *.ino file), but as I don't know how your project is structured (e.g. ino and cpp files, local and/or stored libraries, etc...), I can't say anything more than that, sorry.