0

I have precompiled header file stdafx.h which is specific to each target. My CMake project roughly looks like below:

include_directories(<prefix>/include_a)
include_directories(<prefix>/include_b)  #<---- contains stdafx.h that should NOT be used
include_directories(<project_dir>/)  #<----- contains stdafx.h that should be used

add_executable(<project_name> <sources>)

Problem: I want to exclude precompiled header that comes as part of <prefix>/include_b directory. If thats not possible then specify header files explicitly. I know gcc supports -include option but is there any cleaner option with CMake that fits my requirement?

JamesWebbTelescopeAlien
  • 3,547
  • 2
  • 30
  • 51
  • If you don't want to force an include file (which is not explicitly supported by CMake; see e.g. [here](http://stackoverflow.com/questions/32773283/cmake-include-header-into-every-source-file)), I think the answer lays in the order of your include paths. An example for this in hidden in the ["CMake Build System: Transitive Usage Requirements" documentation](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#transitive-usage-requirements): see "For example, if the linked libraries for a target must be specified in the order lib1 lib2 lib3 , but the include directories ...". – Florian Sep 18 '16 at 20:38
  • `stdafx.h` smells like Visual Studio, but you didn't put a msvc tag? – Johan Boulé Sep 18 '16 at 22:21
  • @Florian forgot to update this, yes in-fact thats what I ended up doing changing the order. – JamesWebbTelescopeAlien Sep 19 '16 at 17:47
  • @JohanBoule yes because I'm cross compiling for other platform – JamesWebbTelescopeAlien Sep 19 '16 at 17:47

1 Answers1

0

Turning my comment into an answer

If you don't want to force an include file (which is not explicitly supported by CMake), I think the answer lays in the order of your include paths.

First here is the test code I used to reproduce your problem:

cmake_minimum_required(VERSION 3.0)
project(IncDirOrder)

file(WRITE "prefix/include_a/stdafx.h" "#error include_a/stdafx.h")
file(WRITE "prefix/include_b/stdafx.h" "#error include_b/stdafx.h")
file(WRITE "include/stdafx.h" "")
file(WRITE "main.cpp" "#include \"stdafx.h\"\nint main() { return 0; }")

include_directories(prefix/include_a)
include_directories(prefix/include_b)  
include_directories(include)  

add_executable(${PROJECT_NAME} main.cpp)

Possible Solutions to Influence the Order of Include Paths

  1. Reorder the include_directories() calls (if possible):

    include_directories(include)  
    include_directories(prefix/include_a)
    include_directories(prefix/include_b)  
    
  2. The use of the BEFORE keyword:

    include_directories(BEFORE include)  
    

    or

    target_include_directories(${PROJECT_NAME} BEFORE PUBLIC include)
    
  3. Going by the assumption that the other pre-compiled headers are also accompanied by a library, I would generally recommend the use of target_include_directories(). Then you automatically have the desired behavior (local includes do come first before interface includes):

    cmake_minimum_required(VERSION 3.0)
    project(IncDirOrderWithLibs)
    
    file(WRITE "prefix/source_a/stdafx.cpp" "#define LibA\n#include \"stdafx.h\"")
    file(WRITE "prefix/include_a/stdafx.h" "#ifndef LibA\n#error include_a/stdafx.h\n#endif")
    file(WRITE "prefix/source_b/stdafx.cpp" "#define LibB\n#include \"stdafx.h\"")
    file(WRITE "prefix/include_b/stdafx.h" "#ifndef LibB\n#error include_b/stdafx.h\n#endif")
    file(WRITE "include/stdafx.h" "")
    file(WRITE "main.cpp" "#include \"stdafx.h\"\nint main() { return 0; }")
    
    add_library(LibA "prefix/source_a/stdafx.cpp")
    target_include_directories(LibA PUBLIC prefix/include_a)
    
    add_library(LibB "prefix/source_b/stdafx.cpp")
    target_link_libraries(LibB LibA)
    target_include_directories(LibB PUBLIC prefix/include_b)
    
    add_executable(${PROJECT_NAME} main.cpp)
    target_link_libraries(${PROJECT_NAME} LibB)
    target_include_directories(${PROJECT_NAME} PRIVATE include)
    

References

Community
  • 1
  • 1
Florian
  • 39,996
  • 9
  • 133
  • 149