What is _PreComp_???

First of all, I am a total nooooob, so don’t expect that I know too much about precompiled libraries.

What I have noticed is that there are 1302 places in the code where PreComp is mentioned like this:

#include "PreCompiled.h"
#ifndef _PreComp_
# include <sstream>
# include <QCoreApplication>
# include <QMessageBox>
# include <QRegExp>
#endif

But what is PreComp? When should an include be inside PreComp?

I also noticed, that the definition of PreComp has been commented out since at least 2011 (GitHub doesn’t go further back): https://github.com/FreeCAD/FreeCAD/blob/42fbc0f58d5cef554e29ba4dfa670548138a39e1/src/FCConfig.h#L321. So are PreComp even still used or will ever come to use again?

I’m a noob too. But i like sometimes to dig around :wink:

check this: https://en.wikipedia.org/wiki/Precompiled_header

and check this: https://wiki.freecadweb.org/User:Ian.rees (under FreeCAD Design (in the sense of source code) Guide) (Don’t ask me why something is written about it in that and not in the developer wiki)

third good source (probably): https://raw.githubusercontent.com/qingfengxia/FreeCAD_Mod_Dev_Guide/master/pdf/FreeCAD_Mod_Dev_Guide__20190912.pdf

I am a total nooooob, so don’t expect that I know too much about precompiled libraries.

It is about pre-compiled headers (PCH). That’s a technique to speed up the compilation process.

Currently, PCH is only used for MSVC under Windows and for each target the compiler builds PreCompiled.cpp as very first file. It creates a big binary file that contains the content of all header files of the corresponding PreCompiled.h.

Remark:
Because the creation of this binary file is quite expensive it must be avoided to re-create it too often. This can only be achieved if files are added that almost never change. So, that’s why for PCH only 3rd party header files should be considered but not application header files.

If the compiler continues with the next source files then it replaces the “PreCompiled.h” with the content of the binary file. This avoids that the compiler has to open each header file separately that is listed in the PreCompiled.h and thus considerably speeds up the process. With activated PCH for MSVC we get a reduction of the build time of 40-50%.

But what is PreComp? When should an include be inside PreComp?

Because PCH is optional and not yet ready to be used for other compilers than MSVC it must be avoided to slow down the build process for them. Therefore it must be avoided that they had to include all headers of a PreCompiled.h and that’s why the PreCompiled.h files have a guard of this form:

#ifdef _PreComp_
...
include all needed headers for the target
#endif

However, when building a normal source file and the compiler needs the declaration of a used class or function then the header of this class or function has to go inside the #ifndef PreComp/#endif block.

To formulate this as a rule:
A header must be added inside an #ifndef PreComp/#endif block if the compiler requires a declaration that is provided by this file AND it’s not already included AND if this header is listed in the target’s PreCompiled.h file.

I also noticed, that the definition of PreComp has been commented out since at least 2011 (GitHub doesn’t go further back): > https://github.com/FreeCAD/FreeCAD/blob > … fig.h#L321. So are PreComp even still used or will ever come to use again?

If a header is already included by an application header file then it’s not needed to include again. That’s why some PreComp are empty or commented out.

But isn’t this the definition of PreComp that has been commented out? Isn’t PreComp undefined because of this? As far as I see, PreComp doesn’t get defined anywhere in the whole repository, so wouldn’t all #ifndef PreComp always turn out to be true - thereby having no meaning?

But isn’t this the definition of PreComp that has been commented out? Isn’t PreComp undefined because of this?

Didn’t get your point.

As far as I see, PreComp doesn’t get defined anywhere in the whole repository, so wouldn’t all #ifndef PreComp always turn out to be true - thereby having no meaning?

It’s defined in all the CMakeLists.txt files (example from src/App):

if(FREECAD_USE_PCH)
    add_definitions(-D_PreComp_)
    ADD_MSVC_PRECOMPILED_HEADER(FreeCADApp PreCompiled.h PreCompiled.cpp FreeCADApp_CPP_SRCS)
endif(FREECAD_USE_PCH)

Hm, does FreeCad not use PCH under gcc ?
Here it is implemented using
#pragma hdrstop
#pragma once
and I use this in my projects wherever possible, because (if used with caution) it will speed up compilation a lot.

Hm, does FreeCad not use PCH under gcc ?

No, it doesn’t. The PCH support for MSVC is hand-crafted because older CMake versions didn’t support it at all. Now CMake does it but you need a fairly new version that isn’t available on all supported distributions.

Here it is implemented using
#pragma hdrstop
#pragma once
and I use this in my projects wherever possible, because (if used with caution) it will speed up compilation a lot

Can you describe this in more details, please? Don’t you have to run the compiler with a special flag to create the PreCompiled.gch out of the PreCompiled.cpp?

Around 15 years ago I tested PCH with gcc and at that time it was totally useless because the creation of the gch file took almost as long as the actual build process without PCH and the generated file was more than 1 GB. Additionally, the build with PCH wasn’t significantly faster than the build without PCH.

wmayer

The mechanism is pretty simple.
#pragma once” is just a shortcut for the standard “sentry”, so not relevant here.

gcc will cache the content of all files included till it found a “#pragma hdrstop”.
If the next file that was compiled uses the same files & order, it use the cached content instead of reading the files again.
So there is no (visible) file that contains precompiled code. It is (re-)generated at every “make” and/or if needed because the include sequence changed.

So, usually I use a “Project-Include-file” that includes all (most of) the files need for the majority of the files of the project.

eg.: A Projekt “MyProject” uses a file “CommonIncludes.h” that looks like this:

#include <stdio>
#include <stream>
#include <string>
...
#pragma hdrstop

Now all Project files uses at the very beginning:

#include "CommonIncludes.h" 

#include <stream> // even that is no problem, caching already stopped, 2. include stoppt due to "sentry" or "#pragma once"

BTW.: That mechanism I use since Windows NT with “Borland C++Builder”. You see pretty old technique introduced by Borland, adopted by GNU :frowning:(

Just some remarks:
I am not familiar with cmake. My job during the last ~25 Years are “bare metal” programs for microprocessors and some support prgs running on a PC.
So I use make for the microprocessor projects.

Thanks for the details.

Here is a simple description how to use PCH with CMake (3.16+): https://edgarluque.com/blog/cmake-precompiled-headers/

Thank’s for the link, unfortunately that doesn’t describe how/if that will use PCH with gcc..
I don’t see how the compiler used is defined (kike inside a Makefle with cc = …).
So did that mean, that it will only work if the used copier supports “generating separate PCH files”. So, not working with gcc ?

unfortunately that doesn’t describe how/if that will use PCH with gcc

One has to check the CMake source code to see how it’s done. But I am pretty sure it doesn’t use the #pragma hdrstop but the -x compiler switch:
https://gcc.gnu.org/onlinedocs/gcc/Precompiled-Headers.html#Precompiled-Headers

Ah, Yes, that makes sense…
And it seams that this way is a better/moderner way of using PCH.
It didn’t need any modification of the source to use PCH, just some settings in the (C-)Makefile.
Maybe I missed this, because I mostly wrote “bare metal” software for microprocessors using a cross compiler mostly based on gcc and these compilers doesn’t support that kind of PCH.
Thanks for the explanation.