#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 с лишним лет, по крайней мере.