Cmake include_directories()

2019-01-13 05:12发布

问题:

This is my project tree:

project
| + src
| + external
| | + foo
| | | + include
| | | | - foo.hpp
| | | + src
| | | | - foo.cpp
| | | | - CMakeLists.txt
| | | - CMakeLists.txt 
| | + CMakeLists.txt 
| + src
| | - main.cpp
| - CMakeLists.txt

foo.cpp includes foo.hpp:

// foo.cpp
#include "foo.hpp"

Now the problem is that including the directory in the top CMake successfully find foo.hpp, but if I include in the subproject it doesn't. Any reason for it? (directories are included before the executable is compiled).

// project/CMakeLists.txt
include_directories(external/foo/include) //OK
add_subdirectory(external)

add_executable(main main.cpp)
target_link_libraries(main foo)

// project/external/CMakeLists.txt
add_subdirectory(foo)

// project/external/foo/CMakeLists.txt 
include_directories(include) // NOT WORKING
add_subdirectory(src)

// project/external/foo/src/CMakeLists.txt 
add_library(foo foo.cpp)

回答1:

Quoting the documentation for include_directories:

The include directories are added to the directory property INCLUDE_DIRECTORIES for the current CMakeLists file. They are also added to the target property INCLUDE_DIRECTORIES for each target in the current CMakeLists file. The target property values are the ones used by the generators.

The INCLUDE_DIRECTORIES directory property is inherited to all subdirectories and all targets in the directory.

  • Specifying ${CMAKE_CURRENT_SOURCE_DIR} for include_directories is redundant as relative paths are interpreted as relative to this directory by default. You should throw it out to increase readability.
  • Specifying an include directory in both a subdirectory and its parent is redundant. You should avoid this and settle on one location.
  • Use get_property and message to double-check that all directories and targets end up with the correct entries in their INCLUDE_DIRECTORIES property.
  • If you are free to require CMake 2.8.11 as a minimum requirement, consider abandoning include_directories completely and use target_include_directories instead. This has the advantage that include dependencies get resolved on a per-target basis exclusively which is usually the more desirable behavior.


回答2:

It maybe a scope problem. I feel what you are trying to do here is to propagate setting from the /project/external/foo/CMakeLists to /project/CMakeLists and such that this setting can be propagated to /project/src/CMakeLists. But unfortunately, propagation from lower-level to higher-level CMakeLists is not possible in cmake, except for cached values. This means you will also need to add include_directories(${CMAKE_SOURCE_DIR}/external/foo/include) in the /project/src/CMakeLists.txt. Or, as you already did, you can just add this line in the top-level CMakeLists.