Проблемы в подкаталоге CMake включают

#cmake

#cmake

Вопрос:

У меня есть проект, структурированный как:

 .
├── CMakeLists.txt
├── src
│   └── temp.cpp
└── thirdparty
    ├── build
    ├── CMakeLists.txt
    ├── include
    │   └── thirdparty.h
    └── src
        └── thirdparty.cpp
  

CMakeLists.txt Файл в thirdparty папке выглядит следующим образом:

 cmake_minimum_required(VERSION 3.10)
project(thirdparty LANGUAGES CXX VERSION 0.0.1)
add_library(thirdparty SHARED "${PROJECT_SOURCE_DIR}/src/thirdparty.cpp")
target_include_directories(thirdparty PRIVATE "${PROJECT_SOURCE_DIR}/include/")
  

CMakeLists.txt Файл в корне проекта выглядит следующим образом:

 cmake_minimum_required(VERSION 3.10)
project(temp LANGUAGES CXX VERSION 0.0.1)
add_subdirectory("${PROJECT_SOURCE_DIR}/thirdparty"
                 "${PROJECT_SOURCE_DIR}/thirdparty/build"
                 EXCLUDE_FROM_ALL)
#include_directories ("${PROJECT_SOURCE_DIR}/thirdparty/include")
add_executable(temp "${PROJECT_SOURCE_DIR}/src/temp.cpp")
target_link_libraries(temp PRIVATE thirdparty)
  

Проблема заключается в попытке включить файл заголовка из thirdparty библиотеки:

 .../temp/src/temp.cpp:1:10: fatal error: thirdparty.h: No such file or directory
  

target_include_directories(thirdparty PRIVATE "${PROJECT_SOURCE_DIR}/include/") Директива отлично работает внутри thirdparty библиотеки. Однако путь к включению заголовка не отображается с помощью add_subdirectory команды. И наоборот, libthirdparty.so файл генерирует ссылки нормально, пока я делаю add_subdirectory и target_link_libraries(temp PRIVATE thirdparty) .

Все это будет работать нормально, если я отменю комментирование #include_directories ("${PROJECT_SOURCE_DIR}/thirdparty/include") строки в корне CMakeLists.txt , но я не хочу иметь глобальную директиву include.

Есть ли способ сделать thirdparty заголовки видимыми, изменив только CMakeLists.txt в thirdpary (вместе с add_subdirectory и target_link_libraries в root)?

Ответ №1:

Вы должны указать включаемые каталоги как ОБЩЕДОСТУПНЫЕ или ИНТЕРФЕЙСНЫЕ в библиотеке, встроенной в thirdparty , а затем ссылаться на эту библиотеку, используя имя целевого объекта (а не имя файла и т.д.) Из других целевых объектов. Это позволит использовать целевую систему свойств cmake. Проблема в том, что thirdparty полученный вами проект может быть устаревшим (в стиле cmake 2.8 или аналогичном) и, следовательно, может не поддерживать это должным образом. Часто бывает, что списки CMakeLists проекта «третьей стороны» слегка нарушены, что делает их бесполезными в многомодульных проектах, и их приходится изменять или полностью переписывать.

Ни при каких обстоятельствах вам не понадобятся какие-либо явные директивы включения каталога и т.д. Для cmake достаточно простой ссылки на целевую библиотеку, созданную в подкаталоге, чтобы при необходимости включить все общедоступные и интерфейсные зависимости. Это механизм, который делает cmake «нормальным». Вы не должны использовать какие-либо переменные, такие как FOOBAR_LIBRARY_INCLUDES и т.д. — это древний материал и совершенно неуместный в любом современном проекте cmake, и под современным я подразумеваю все, что было сделано за последние 5 с лишним лет, по крайней мере.