How to I include_directories() and/or target_include_directories() with GCC's/Clang's -iquote/-idirafter

Hi there,

I am wondering how to wield include_directories() and/or target_include_directories() to tell the preprocessor directly to use -iquote or -idirafter as opposed to a mere -I or -isystem. It’s a question I raised in ticket 12928 and I was referred here.

I would like to avoid having to set COMPILE_OPTIONS or similar explicitly via set().

To clarify: the SYSTEM option appears to correspond to -isystem, but there doesn’t appear to be a mapping of the other options.

1 Like

I can’t provide an official answer, but to me these two options fall outside the abstractions CMake currently does or should potentially offer. The -iquote and -idirafter are very specialised, and to my knowledge very rarely used. To me, they are a sign that you’re probably doing something wrong. Code shouldn’t be so fragile that they need such fine-grained control over the header search path ordering. If the -I and -isystem flags are insufficient, you’re setting up your developers and any consumers of your project for future pain if you need -iquote or -idirafter to get a working build.

I took the time to sift through the code at 9be8198bcca330ba0810ab26cc9ae93712c63b8e and it turns out that -iquote and -isystem are not a thing in CMake, whereas -isystem is (243 matches in 49 files) as well as -isysroot.

Sorry, but I emphatically disagree with that assertion.

The lax handling and mashing up of quoted and angle-bracketed includes is a bad practice and the old-fashioned way. Making sure to only include system headers with angle brackets and others with quotes is the way to go. Making it impossible to represent this in CMake is unfortunate, but not the first time I hit these limitations over the years.

If you look at toolchain releases over the years you will also notice that transient includes are vanishing. So code that may have built on a previous release, now won’t, because header so-and-so doesn’t include another header that it previously did. In order to get cleaner this way, -iquote and -idirafter are tools you can’t work without.

But there’s a workaround, so it’s fine. Even though it’s not canonical or idiomatic CMake that comes out of it :slight_smile:

Note that there are various other “include directory” flavors in the wild. D has -J for “textual include” directories (as opposed to module search roots that -I provide). An abstraction would be nice, but also very non-trivial as CMake doesn’t really provide fine-grained control over the final ordering of such directories.

1 Like

Hi, I want to upvote this as well. There is nothing ‘fragile’ about using -iquote. As a matter of fact, I want to use it for very efficient lookup of my header files. I work on a large codebase with a root CMakeLists.txt and I want to specify -iquote ${CMAKE_SOURCE_DIR} once. All my #include lines then look like:

#include “a.hpp” // Something in root folder
#include “f1/b.hpp” // Something in f1 folder
// So on and so forth

The compiler can then very efficiently look up my includes. I have even upvoted the request for iquote with Microsoft:

https://developercommunity.visualstudio.com/t/How-Can-I-Emulate-the-GCC-Compiler-Optio/419914

and I encourage others who are interested in this to upvote this issue at Microsoft. The quotes in Microsoft are extremely broken. There is a ‘grand-fathering’ effect in the Microsoft compiler, wherein a quoted include is first looked up in the current folder, then the current folder of the parent file which includes this include file, so on and so forth. It would be very nice if Microsoft can provide a way to override this ‘grand-fathering’ effect with -iquote.

At this point, this is a chicken and egg problem. Tools such as CMake do not want to provide support because it is really only used by GCC. And vendors like Microsoft see no incentive in implementing it.

1 Like

Would appreciate if someone from the CMake team could share an update on this. Thanks in advance!

1 Like

I’m relatively new to the CMake team so here are just my thoughts. This sounds like a similar situation to SYSTEM.

For a while target_include_directories(foo SYSTEM PRIVATE .) would just use -isystem on platforms that supported that it (EX: GCC) and it fall back to regular includes on MSVC. That was the case for quite a while until MSVC recently added support for -external:I. Which CMake then incorporated (https://gitlab.kitware.com/cmake/cmake/-/merge_requests/4766).

Perhaps a similar approach could be done for -iquote?

target_include_directories(foo QUOTE PRIVATE .) which would use -iquote functionality when available and fallback to regular include directories if it isn’t supported. Similar to SYSTEM. If this gets enough usage it may encourage vendors like Microsoft to implement it.

But this does raise further questions:

EX: How would QUOTE work with package managers? Many users have the expectation to use angle bracket includes for packaged libraries. Should QUOTE be translated to system when the library is installed then? If so that makes including the library different when using find_package vs add_subdirectory. Perhaps it could be limited to PRIVATE includes? It creates a lot of questions IMHO. Which in turn is a fair amount of maintenance / testing. Agreed with @ben.boeckel it looks non trivial.

You bring up valid points. It’s just a matter of limited developer resources. If you feel you have a good design on how to make this work and are willing to put in the time to help we would appreciate it.

Hi buildSystemPerson,

Many thanks for your prompt reply. For my usecase, something as simple as the following would work:

include_directories(QUOTE <Path>)

which causes <Path> to be included automatically for all projects with -iquote if available, otherwise reverts back to /I. I don’t actually have a usecase for how target_include_directories(QUOTE …) would be used. Once you make include_directories available, I am sure people will give you feedback and that will help you refine the feature further.

Does this still look like too much work? If you don’t have enough developer resources, then at a high level, could you point out places in the source code where modifications would be needed?

Here would be a good starting point. From there start looking at how SYSTEM is implemented. It should give you an idea how to get started.

If you are going to contribute see CONTRIBUTING.rst as well. Please note that for a feature like this to be accepted new tests will be required. Also updating the include_directories documentation appropriately.

A new argument to include_directories is how the defunct D support branch did it for -J (“text includes”). It is completely orthogonal to -I in D-land, so a lot of the questions of “what if a directory is specified with multiple keywords?” never came up. It was also long before I understood usage requirements enough to ask things like “what happens when installed?”, though it is trivial in that case since it is orthogonal.