[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