24

I actually have a simple question, but couldn't find an answer. Maybe you can point me to a duplicate. So, the question is: is it possible to tell cmake to instruct a compiler to automatically include some header at the beginning of every source file, so there would be no need to put #include foo.h? Thanks!

Andrei Chernikov
  • 360
  • 1
  • 2
  • 12
  • could you clarify? I mean something like a -include filename directive of gcc. – Andrei Chernikov Sep 25 '15 at 01:18
  • 2
    Why don''t you do it the right way and `#include` the header in every file it uses any of its declarations? – too honest for this site Sep 25 '15 at 01:22
  • 1
    well, I have an internal header for a library with a bunch of defines in it, and many parts of the lib use it. So I thought instead of including it manually I could just do it in cmake... Well, you could do this in visual studio, in gcc, so it can't be exactly pointless, or why they support it anyway? – Andrei Chernikov Sep 25 '15 at 01:27
  • 1
    I hope people aren't downvoting this question just because they personally can't think of a good reason for doing this. – congusbongus Sep 25 '15 at 01:30
  • 1
    @congusbongus Yes, precompiled headers comes to mind as a good usage of forced include. – Johan Boulé Sep 18 '16 at 22:21
  • 2
    common guys, stop downvoting the question just because you think it's a bad practice. Think of the situation when you need to fix something in a third-party lib which you don't wanna modify. I need it for Hunspell on Windows which uses `ssize_t`, so I can redefine it to `size_t` without modifying the external source. – Roman Kruglov Feb 07 '17 at 16:03
  • 2
    Heck, this isn't bad practice. It *may be* a bad practice when you start a brand new code base and are in full control. But apparently the majority of folks here have never had to work with a.) third party libraries and/or b.) legacy code bases. Otherwise they'd not claim this to be a bad practice. Believe you me, rather than doing loads of invasive changes to a legacy code base, creating noise at the VCS level, I'll happily force an include as per this question ... and do the other more invasive parts of the refactoring at a more convenient time. – 0xC0000022L Jun 03 '17 at 19:07

2 Answers2

37

CMake doesn't have a feature for this specific use case, but as you've hinted, compilers such as GCC have the -include flag which acts as if there was an #include "foo.h" in the source file, and since CMake can pass arguments to compilers, you can do it via add_definitions.

This answer covers what the flag is for GCC, Clang and MSVC which should cover a lot of bases. So in CMake, detect what the compiler is and pass the appropriate flag.

Here's what the CMake code might look like:

if(MSVC)
    add_definitions(/FI"foo.h")
else()
    # GCC or Clang
    add_definitions(-include foo.h)
endif()

Comments

In general, doing this is a bad idea. Code inspection tools (like IDEs, or doxygen) will be confused by it, not to mention other humans looking at the code. If not all source files actually require the definition, adding extra #includes will slow down compile time. If you actually do need the same header (and it's not a system header) in all your source files, it may be symptomatic of high coupling in your code. And for what benefit? Not having to add one line to your files?

However, it's necessary to note that compilers support this for a reason; there are a few weird edge cases (example 1, example 2) where it's a useful thing to do.

Just be aware that you're doing this for the right reasons.

ceztko
  • 14,736
  • 5
  • 58
  • 73
congusbongus
  • 13,359
  • 7
  • 71
  • 99
  • 1
    This is actually a very bad thing, as you cannot see which headers a file uses. It also works against tools like doxygen which cannot generate a proper dependency tree. – too honest for this site Sep 25 '15 at 01:24
  • But this defeats the point of CMake, if I need to manually specify if for different compilers. Of course I could do this, but it would be much better if CMake did this for me. – Andrei Chernikov Sep 25 '15 at 01:25
  • 3
    @Olaf hey, I'm not suggesting people do this, but this is how it can be done if they really must. After all, why do compilers like GCC provide the `-include` flag at all? – congusbongus Sep 25 '15 at 01:26
  • So the authors just thought users to be children needing to be told what to do? I don't see a point why not support it, when compilers do. Anyway, thanks, I got it. It would probably be better to include it manually. – Andrei Chernikov Sep 25 '15 at 01:32
  • 1
    @congusbongus: "why do compilers like GCC provide the -include flag at all?" That is the question (sorry, I currently don't have a skull within reach;-). My point is just to make clear that is should not be done. – too honest for this site Sep 25 '15 at 01:33
  • Hm. What am I exactly missing? – Andrei Chernikov Sep 25 '15 at 01:33
  • @Aikei There will always be features that CMake doesn't support natively. Perhaps in the future, and if this feature is highly demanded (which I doubt), CMake can add support for it. Most of my CMakeLists.txt contain these compiler checks out of necessity. – congusbongus Sep 25 '15 at 01:35
  • 1
    @Aikei: I cannot (and will not) hold a tutorial about build tools. But just from your comments, it is clear. I'd recommend you do research on your own about the general idea and how these tools interact with the actual **building** (i.e. the tools performing the build actions) tools. Please do not understand this as an offence, just a message to learn. The current problem you have is you are trying to avoid some typing/editing at the cost of maintenance and (possibly) documentation. – too honest for this site Sep 25 '15 at 01:36
  • @Olaf I'm not being offended, I was just trying to understand what you mean. Their internal behavior is such that they cannot, by nature, tell compilers to include header files? I doubt. Because that's done in project configuration files, and that's what their output is. So I didn't exactly get why you said that. – Andrei Chernikov Sep 25 '15 at 01:41
  • 1
    @Aikei: (Last posting) Read what I wrote about "interacting" then think about. Then read the last part and forget about what think you want to do. – too honest for this site Sep 25 '15 at 01:44
7

as pointed out in the examples above, "force including" could be useful for pre-compiled headers.

this is actually what cmake's target_precompile_headers does. https://cmake.org/cmake/help/git-stage/command/target_precompile_headers.html

for this context-of-use:

  1. force including the header is actually a nice feature, since it allows you to use precompiled headers with MSVC, clang and gcc without changing your source.

  2. it is also a nice feature, because it allows you to switch on/off PCH with just a configuration change (e.g. in cmake). this allows you to test that your source builds also without the precompiled headers (e.g. for compilers/situations that don't support it). for instance clang-tidy gets confused about PCH (at least in combination with MSVC).

dyoll
  • 187
  • 2
  • 6