[Qt5-feedback] The #include directives for Qt Essentials and Qt Add-on modules

Craig.Scott at csiro.au Craig.Scott at csiro.au
Fri Jul 1 00:45:26 CEST 2011


On 01/07/2011, at 4:26 AM, Charley Bay wrote:

// ARE YOU SURE YOU WANT TO DO THIS?
#include <some/path/SomeFile.hpp>

...is really pretty dangerous.  It's a general nightmare for build systems
and configuration management, since the "INCLUDE_PATH" is no
longer "in-charge":

WARNING: I have to very much disagree with this assertion and all your reasons below. ;)


(1) Many more directories are considered beyond "INCLUDE_PATH"
(it explodes subdirectories off EVERY directory in your "INCLUDE_PATH")

Whether you have the path to the header in the source file or as compiler flags (eg -Isome/path), it will result in the same thing. The compiler will end up searching the same sets of files/directories! You gain nothing by moving the path from the source to the compiler flags. Not sure if that's what you are advocating, but let's at least make this point clear to start with.


(2) It slows the build, especially searching every path for subdirs, even
though you may not want those directories in your "INCLUDE_PATH"
to be searched for subdirs.

Seriously? Can you provide measurements for that? I'd be *very* surprised if you could measure a detectable difference between having the paths specified in the source files or as INCLUDE_PATHS specified by compiler flags. If you are talking about the difference between using a directory structure as opposed to a flat structure with many files in the same directory, again I don't see how you would get much of a measurable difference. I'm happy to be shown evidence to the contrary though.


(3) Your build is no longer documented.  "INCLUDE_PATH" no longer
reflects the directories from which files are included.  Accidental
location of files can violate the build target, and you would NEVER
KNOW (e.g., you can't reproduce it on different machines, or on the
same machine on different days, unless you *always* started
with a "virgin build".)

I'd argue the opposite. The source files document exactly where you expect the files to be. If you are using this arrangement, you are typically saying that you expect to use a relatively limited number of INCLUDE_PATH search locations. These INCLUDE_PATH locations would define the base points of the search and the paths you use in your source files specify the directory structure. This becomes particularly important when you are writing libraries and you expect others to use your headers. You don't want them to have to know all the different directories that need to be searched and therefore added to their build system too. Rather, your library would be better off specifying a single INCLUDE_PATH as a base and then your own headers do the rest. Much simpler and more robust for people using your library. Also consider that putting the paths in the source makes it a simpler task if you want to switch build systems and/or mix different build systems (not everyone has the good fortune of being in complete control over all people who use their code and over what else they might use with it!).

As for the comments regarding accidental location of files, if you are choosing appropriately unique directory names (as proposed by the Qt5ProductDefinition wiki page), then this should not be an issue. The feared cases of different behaviour on different machines, etc. would only arise if someone is mixing two different installations of the headers, and if they are doing that, then they already have to be careful with the way they specify their INCLUDE_PATH and the addition of a directory structure in the source files will not make that any harder than it already is. Think of converting every slash into a . or underscore and you see what I mean. Whether it is a path or a long-and-hopefully-unique file name makes no difference.


(4) These "auto-include-subdirs" would be sprinkled in the source,
which means developers must not violate a "virgin build system"
directory structure, but the user will never know if they *did*
violate that structure.  For example, "#include<abc/SomeFile.hpp>"
means the user should be VERY careful about EVER creating
a directory called "abc", especially if it is accidentally in a directory
that may accidentally be placed into an "INCLUDE_PATH".  Thus,
each "some/path" creates global namespace collision problems
that are NOT remedied merely through which version of the module
you placed in your "INCLUDE_PATH".

How is this different from the user having to be careful not to create a header with the same name which appears somewhere earlier in the INCLUDE_PATH? The directory names are here acting just like part of a monolithic file name. There really is no difference when it comes to avoiding clashes.


I recognize that some products do this "#include<some/path/SomeFile.hpp>",
but due to the dangers, we are very careful when we integrate them
into our code base (and builds).  However, we DO NOT allow those
constructs in *our* code base.

We have a very large code base with many build targets and inter-build dependencies. When including files from somewhere other than the current directory, we use the convention of specifying the path below some standardised point in our build tree(s). This has not only made it much easier for people using our headers, it has also considerably improved the robustness of our builds. I rarely need to look at the include path specified in the build system and we pretty much never have problems with clashes. I respect your choice to avoid paths in your source files, but I wanted to offer a counterpoint where it has worked very well too.


So, I'll use whatever Qt5 requires, but I'm not convinced it's a good
idea.

In contrast, I rather like the current Qt distribution model that
"standardizes" includes:

#include <QWidget.hxx> // Did I find it?
#include <QWidget.hpp> // Did I find it?
#include <QWidget.hh> // Did I find it?
#include <QWidget.H> // Did I find it?
...plus the above with different case...

#include <QWidget>  // Found it!  (Good convention!)

For these plugins, I really think there is very low likelihood of
name collisions across packages:

#include <Foo>  // for QtAddOn/Foo

...But, if we wanted explicit namespaces, I'd prefer:

#include <QtAddOn.Foo>

This way, we are looking for an *explicit* file, and the packaging/distribution
would merely need to standardize the file exports in the distribution
(like we already do with "#include<QWidget>").

Users are not really used to seeing directory names in QtAddOn.Foo form. It looks too much like a file with the file extension "Foo", especially if the user is simply doing a directory listing at a command line. There's nothing wrong with a name like QtAddOn.Foo, but as explained above, it isn't buying you anything that QtAddOn/Foo would not provide, but the latter would look and feel more natural to most people.


--
Dr Craig Scott
Computational Software Engineering Team Leader, CSIRO (CMIS)
Melbourne, Australia





More information about the Qt5-feedback mailing list