Вопрос:

CMake и комментарий #pragma (lib)

c++ windows dll cmake .lib

518 просмотра

4 ответа

3604 Репутация автора

Для моего проекта CMake у меня есть внешняя библиотека, состоящая из заголовочного файла и нескольких пар .lib / .dll.

Заголовочный файл выборочно ссылается на одну из пар .lib / .dll, возьмем этот пример:

#ifdef DEBUG
    #pragma comment(lib "exampled.lib")
#elif
    #pragma comment(lib "example.lib")
#endif

В целом, есть .lib и соответствующие .dll для 32/64 бит и Debug / Release, итого 4 пары. Внутри заголовочного файла есть правильная #ifdefлогика для ссылки на нужную библиотеку. Как я уже сказал, это внешняя библиотека, поэтому я не хочу менять этот заголовок.

Как правильно преподавать это CMake?

Для времени компиляции (то есть, включить каталоги) я могу использовать, target_include_directories()который работает отлично. Я также могу создать импортированную цель с помощью каталога include, это также отлично работает.

Проблема начинается во время соединения:

  • target_link_libraries()заставляет меня указать один из файлов .lib / .dll. Я мог бы дублировать #ifdefлогику, но это неправильно. Добавление всех файлов также некорректно, так как всегда нужен только один.
  • Импортированные цели позволяют мне также добавлять файлы .dll и .lib, но опять же, мне придется либо дублировать логику, либо связать все библиотеки.
  • link_directories()работает в глобальном масштабе. Который чувствует себя ненужным, если на самом деле только несколько целей нуждаются в этом.
  • добавление данного каталога в PATHтакже кажется «глобальным», т. е. поскольку библиотека в настоящее время распространяется вместе с кодом.

Так что я ищу что-то вроде target_link_directories()или похожие решения. Очевидно, что для фактической загрузки .dll во время выполнения я должен был бы предпринять дальнейшие шаги, поэтому, если ваше решение включает это, было бы очень желательно.

Автор: Anedar Источник Размещён: 12.01.2018 06:22

Ответы (4)


1 плюс

942 Репутация автора

target_link_libraries () заставляет меня указать один из файлов .lib / .dll

Это неправда. Вы можете предоставить ключевые слова, чтобы указать, к какому типу сборки принадлежат библиотеки.

Из документации CMake по target_link_libraries

Ключевое слово debug, optimized или general указывает, что библиотека, следующая непосредственно за ней, должна использоваться только для соответствующей конфигурации сборки. Ключевое слово debug соответствует конфигурации Debug (или конфигурациям, указанным в глобальном свойстве DEBUG_CONFIGURATIONS, если оно установлено)

Пример: target_link_libraries( my_target optimized example.lib debug exampled.lib

Затем это контролируется CMAKE_BUILD_TYPEпеременной. Смотрите документацию по cmake для получения дополнительной информации об этой переменной.

Что касается 32-битных и 64-битных систем, вам нужно добавить блоки if, проверяющие архитектуру, я признаю, что это ограничение.

Автор: mascoj Размещён: 12.01.2018 06:31

1 плюс

1808 Репутация автора

Чтобы проверить 32 или 64-битные вариации, вы можете использовать CMAKE_SIZEOF_VOID_P EQUAL 8

if(CMAKE_SIZEOF_VOID_P EQUAL 8)
// Set 64 bit stuff
else()
// Set 32 bit stuff
endif(CMAKE_SIZEOF_VOID_P EQUAL 8)

А так как mascoj уже указывалось , что я собирался, что target_link_libraries принимает general, optimizedи debugключевые слова , и это должно помочь получить все библиотеки , которые вам нужны.

Автор: Chris Размещён: 12.01.2018 08:02

0 плюса

34530 Репутация автора

Хранение #pragmas требует неприятностей. Вы должны деактивировать их, если это возможно.

Есть много библиотек, которые делают это (например, Boost на Windows), но это не имеет смысла при использовании с CMake. Эти прагмы нестандартны и не будут работать на большинстве компиляторов. Однако весь смысл сборки CMake заключается в том, чтобы быть переносимым на все платформы, поэтому вам все равно придется перенести логику для связи с CMake, если вы хотите быть переносимым. Даже если вы не заботитесь о переносимости, сборки CMake обычно не очень хорошо работают с такими файлами (как вы сами испытали). CMake отвечает за сборку, поэтому вам следует перенести все вопросы, связанные с ссылками на CMake.

Поэтому первым делом нужно найти способ дезактивировать прагмы. Обычно это можно сделать с помощью определения препроцессора или аналогичного (для Boost вы можете target_link_libraries(... Boost::disable_autolinking )установить требуемые определения препроцессора).

Вам будет нужно дублировать логику , которая теперь есть в файле заголовка, да. Вот как это работает, система сборки должна знать, с чем связываться. Используя выражения генератора , вы все равно можете скрыть все это в одной импортированной цели, так что по крайней мере это будет удобно использовать.

Нет хорошего решения .dllпроблемы. Если вы хотите, чтобы dll были доступны в каталоге сборки, вам нужно вручную скопировать их туда. CMake не предлагает никакой специальной поддержки здесь, но если вы уже нашли .libs для линковки, найти .dlls обычно просто.

Автор: ComicSansMS Размещён: 15.01.2018 09:06

0 плюса

1 Репутация автора

link_directories () у меня вообще не работает для #pragma comment (lib)

Для поиска lib прагмы я использую

if (MSVC)
 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}"
     "/LIBPATH:<path to my libs>")
endif()

Например

if (MSVC)
     set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" 
         "/LIBPATH:${CMAKE_CURRENT_BINARY_DIR}/../src_lib/")
endif()
Автор: Rodion Rodionov Размещён: 20.05.2019 08:41
Вопросы из категории :
32x32