Я пишу библиотеку C ++ (только для заголовков) и использую CMake для создания моих (Visual Studio) проектов и файлов решений. Я также пишу набор тестов, который является частью того же проекта CMake.
Моя проблема возникает, когда я вызываю target_include_directories () для цели, представляющей мою библиотеку только для заголовков, чтобы потребители моей библиотеки могли найти ее заголовочные файлы. Я получаю следующее сообщение об ошибке (хотя генерация НЕ прерывается).
CMake Error in CMakeLists.txt:
Target "Fonts" INTERFACE_INCLUDE_DIRECTORIES property contains path:
"D:/Projects/GPC/fonts/include"
which is prefixed in the source directory.
(D: / Projects / GPC / Fonts является каталогом верхнего уровня моего библиотечного проекта. Между прочим, проблема остается, если я перемещаю заголовочные файлы в верхний каталог.)
Обидная строка в моем CMakeLists.txt такова (адаптировано для простоты):
target_include_directories(Fonts INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include")
Я не понимаю, что я делаю не так. Без target_include_directories () код потребительских проектов просто не может включать мои заголовочные файлы (если только в установленной форме, но я до сих пор не дошел до этого, и в любом случае я хочу иметь возможность использовать мою библиотеку из ее дерева сборки , без установки.)
Я чувствую, что мне здесь чего-то не хватает; все же я искал часы, не находя решения или объяснения.
Происхождение проблемы не в target_include_directories
сама команда, но попытка install
цель, которая имеет общедоступный или интерфейсный каталог с префиксом в исходном пути.
Хотя при создании библиотеки с нуля совершенно нормально и желательно использовать абсолютные пути, сторонняя библиотека, использующая предварительно собранную версию этой библиотеки, вероятно, захочет использовать другой путь включения. В конце концов, вы не хотите, чтобы все ваши пользователи отражали структуру каталогов вашей машины сборки, просто чтобы попасть в правильный путь включения.
Механизм упаковки CMake обеспечивает поддержку для обоих этих вариантов использования: вы можете извлечь библиотеку непосредственно из дерева сборки (то есть проверить источник, собрать его и указать find_package()
в каталог) или из каталога установки (запустите make INSTALL
скопировать собранный материал в каталог установки и указать find_package()
в тот каталог). Последний подход должен быть перемещаемым (то есть я собираю и устанавливаю на своем компьютере, отправляю вам полученный каталог, и вы сможете использовать его на своем компьютере из другой структуры каталогов), тогда как первый — нет.
Это очень удобная функция, но вы должны учитывать ее при настройке включаемых каталогов. Цитирование руководства для target_include_directories
:
Требования к использованию каталогов обычно различаются между
дерево сборки и дерево установки.BUILD_INTERFACE
а также
INSTALL_INTERFACE
выражения генератора могут быть использованы для описания
отдельные требования использования в зависимости от места использования. Родственник
пути разрешены в пределахINSTALL_INTERFACE
выражение и
интерпретируется относительно префикса установки. Например:target_include_directories(mylib PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/mylib> $<INSTALL_INTERFACE:include/mylib> # <prefix>/include/mylib )
BUILD_INTERFACE
а также INSTALL_INTERFACE
генератор выражений сделать всю магию:
$<INSTALL_INTERFACE:...>
Содержание
...
когда свойство экспортируется с помощьюinstall(EXPORT)
и пусто в противном случае.
$<BUILD_INTERFACE:...>
Содержание
...
когда свойство экспортируется с помощьюexport()
или когда цель используется другой целью в той же сборочной системе.
В противном случае расширяется до пустой строки.