[Development] Using '#pragma once' instead of include guards?

Thiago Macieira thiago.macieira at intel.com
Mon Oct 10 21:27:51 CEST 2022


On Monday, 10 October 2022 08:43:53 PDT Christian Kandeler via Development 
wrote:
> On 10/10/22 17:13, Thiago Macieira wrote:
> > The biggest problem we used to have was installing builds that had
> > include
> > paths pointing to both the source and installation directory. With
> > preprocessor guards, only one of the two would actually get included; with
> > #pragma once, the files are actually different so both would get included,
> > causing a build error.
> 
> Was this really verified or just a guess? Use of #pragma once is rather
> wide-spread, and so is implementing header precedence via include path
> order, so one would think lots of project would have problems if that
> combination didn't work.

Anecdotal, because we don't use #pragma once so any such effects would be 
hidden.

But I do remember at some point in the last decade and a half seeing -I 
options pointing to both the install target path and the source path, so if 
you're doing a rebuild, you'd find yourself in this situation. The other 
problem was if people erroneously did make install for a non-installing build; 
if you did that, then the headers would be copied to include/ and you'd have 
stale copies.

Looking at my Qt build with an install prefix, I don't see any -I pointing to 
the install path, so there's no problem for me...

...but this build is one out of qt5.git. A split-module build WOULD have this 
problem for any module besides qtbase. For example, building QtQml must 
necessarily have the -I for the include dir containing the QtCore subdir. If 
you've already built and installed QtQml, then that same dir contains a QtQml 
subdir and all <QtQml/xxx> includes can resolve there, depending only on the 
order of -I flags.

Another example was when we had the CMake build copying headers for the 
bootstrap build, to avoid the issue of bootstrap recompiling itself and moc, 
and thus every single moc output, every time you modified a file that the 
bootstrap used. This was a short-lived solution and reverted because I 
promised that QtCore developers would simply use -DQT_FORCE_FIND_TOOLS=ON with 
another build to avoid the inconvenience.

This situation is annoying either way. With include guards, you will get a 
working build, but you may spend some time trying to figure out why the changes 
you're making to the headers aren't taking effect. With the pragma, you get 
hard build errors due to redefined types, probably with both paths so you'd 
notice easily that there are two copies.

The problem I have with switching to #pragma once is for whom the problem 
happens and who gets to fix it. Most people who build Qt from source are not 
developing or modifying it; they're simply building for use in their own 
content. So if the problem of incorrect include paths happens with 
preprocessor guards, most likely they will not see any ill effect because both 
copies of headers are the same. But if those headers use #pragma once, those 
people will get build errors despite the file contents being identical, because 
they are different files.

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Cloud Software Architect - Intel DCAI Cloud Engineering





More information about the Development mailing list