Cmake include_directories()

Это мое дерево проектов:

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

foo.cpp включает foo.hpp:

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

Теперь проблема заключается в том, что включение каталога в верхнем CMake успешно находит foo.hpp, но если я включу в подпроект, это не так. Любые причины для этого? (каталоги включены до компиляции исполняемого файла).

// 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

Указание документации для include_directories:

Каталоги include добавляются в свойство каталога INCLUDE_DIRECTORIES для текущего файла CMakeLists. Они также добавлено к целевому свойству INCLUDE_DIRECTORIES для каждой цели в текущий файл CMakeLists. Значения целевых свойств являются значениями используемые генераторами.

include_directories свойство каталога наследуется ко всем подкаталогам и всем целям в каталоге.

  • Указание ${CMAKE_CURRENT_SOURCE_DIR} для include_directories избыточно, поскольку относительные пути интерпретируются как относительные по отношению к этому каталогу по умолчанию. Вы должны выбросить его, чтобы повысить удобочитаемость.
  • Указание каталога include как в подкаталоге, так и в его родительском элементе является избыточным. Вам следует избегать этого и поселиться в одном месте.
  • Используйте get_property и message, чтобы дважды проверьте, что все каталоги и целевые объекты содержат правильные записи в свойстве include_directories.
  • Если вы свободны требовать CMake 2.8.11 в качестве минимального требования, рассмотрите полностью отказаться от include_directories и вместо этого используйте target_include_directories. Это имеет то преимущество, что включение зависимостей разрешается исключительно на основе каждой цели, что обычно является более желательным.

Ответ 2

Это может быть проблема с областью. Я чувствую, что вы пытаетесь сделать здесь, это распространять настройки с /project/external/foo/CMakeLists на /project/CMakeLists и таким образом, чтобы этот параметр можно было распространить на /project/src/CMakeLists. Но, к сожалению, распространение с CMakeLists более низкого уровня на более высокий уровень невозможно в cmake, за исключением кешированных значений. Это означает, что вам также необходимо добавить include_directories (${CMAKE_SOURCE_DIR}/external/foo/include) в /project/src/CMakeLists.txt. Или, как вы уже это сделали, вы можете просто добавить эту строку в CMakeLists верхнего уровня.