77

I have a cmake build in which I'm searching for a bunch of dependencies, i.e. I have many instances of:

FIND_PACKAGE(SomePackage)
if(SOMEPACKAGE_FOUND)
  include_directories(${SOMEPACKAGE_INCLUDE_DIR})
  link_libraries(${SOMEPACKAGE_LIBRARIES})
endif(SOMEPACKAGE_FOUND)

Now, I want to add a custom command to build a precompiled header file, but to do this I need to know all of the paths added by my include_directories calls. How can I get a list of these directories (preferably with the proper -I/path/to/directory format) so that I can add them to my custom command?

rcv
  • 6,078
  • 9
  • 43
  • 63

3 Answers3

130

You can use the get_property command to retrieve the value of the directory property INCLUDE_DIRECTORIES

Something like this:

get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
foreach(dir ${dirs})
  message(STATUS "dir='${dir}'")
endforeach()

The value of this directory property only tracks the include_directories commands that have occurred previously in the same CMakeLists file, or that have been inherited from previous occurrences in a parent CMakeLists file. If your find_package and include_directories commands are scattered about throughout many subdirectories, this becomes a challenging issue.

If you get to that point, you may consider overriding the include_directories command with your own function or macro and track the values passed to it yourself. Or, simply accumulate them in a global property or an internal cache variable alongside each call to include_directories.

See the documentation here:

https://cmake.org/cmake/help/latest/command/get_property.html

https://cmake.org/cmake/help/latest/prop_dir/INCLUDE_DIRECTORIES.html

starball
  • 20,030
  • 7
  • 43
  • 238
DLRdave
  • 13,876
  • 4
  • 53
  • 70
  • 1
    is there a way to get the system includes as opposed to every includes? example: `include_directories(SYSTEM system/include)` `include_directories(local/include)` `get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY ????)` – mchiasson Oct 28 '15 at 17:55
  • I do not know of a way, but there might be one. Might be worth a question of its own. I would have to dig into the CMake source code to see if I could find a way if the Googs does not easily reveal one... – DLRdave Oct 30 '15 at 13:45
  • 5
    ```GET_DIRECTORY_PROPERTY(output INCLUDE_DIRECTORIES) MESSAGE(WARNING ${output})``` This will print all ```-I``` dirs like: /usr/local/include/ – Gelldur Aug 23 '16 at 09:08
  • Some directories can be included through compiler flags, so it can be usefull to print additionally CMAKE_C_LINK_FLAGS variable (or the corresponding variable of your langage) : message(STATUS "CMAKE_C_LINK_FLAGS=${CMAKE_C_LINK_FLAGS}") – quent Dec 11 '20 at 10:31
  • @DLRdave "If your find_package and include_directories commands are scattered about throughout many subdirectories, this becomes a challenging issue." Could somebody please explain that in more detail? – John Jul 31 '21 at 08:00
1

Our solution to write include directories added by conan to a file

function(output_conan_include_dirs)
    set(include_dir_str "")
    foreach(DIR ${CONAN_INCLUDE_DIRS})
        set(include_dir_str "${include_dir_str}${DIR}\n")
    endforeach()

    set(pth "${CMAKE_BINARY_DIR}/conan-includes.txt")
    file(WRITE "${pth}" "${include_dir_str}")
    message(STATUS "Conan include directories written to: ${pth}")
endfunction()

output_conan_include_dirs()
radam
  • 11
  • 2
0

The code suggested in the answer by DLRdave works, thanks! Today I had the same problem, including the parentheses in the question: (preferably with the proper -I/path/to/directory format).

I did not find a direct solution in spite of the fact that cmake is bound to do this somewhere inside. The best thing I could come up with is

get_directory_property (inc_dirs INCLUDE_DIRECTORIES)
list(TRANSFORM inc_dirs PREPEND "-I ")
list(JOIN inc_dirs " " INCLUDE_STRING)

Is there a way to avoid the intermediate variable??