Могу ли я создать “псевдозадачу” CMake, которая будет устанавливать параметры компиляции/ссылки за меня?

Вопрос или проблема

В моем проекте есть смесь зависимостей, некоторые из которых имеют файлы cmake, которые я могу использовать с помощью target_link_libraries() (например, boost_program_options), а некоторые — нет (например, openssl; мне нужно скомпилировать собственную версию по причинам совместимости), и для них я вынужден использовать ExternalProject_Add, а затем мне нужно использовать смесь target_link_libraries(), target_compile_options() и target_link_options(), например:

# Это только для определенных библиотек.
target_compile_options(my_program
  PUBLIC
  -I${OPENSSL_INSTALL_DIR}/include
)

# Это только для определенных библиотек.
target_link_options(my_program
  PUBLIC
  -L${OPENSSL_INSTALL_DIR}/lib
)

# Это касается всего, но я должен помнить,
# добавляю ли я имя цели или фактические файлы библиотек.
target_link_libraries(my_program
  PUBLIC
  boost_program_options
  libssl.a libcrypto.a
)

Что я хотел бы сделать, так это заменить это на что-то вроде:

# Все в одном месте.
target_link_libraries(my_program
  PUBLIC
  boost_program_options
  openssl_pseudo_target
)

И в другом месте сделать так, чтобы openssl_pseudo_target сообщал cmake о соответствующих опциях компиляции/ссылки/библиотек, которые следует использовать.

Есть ли способ сделать это или достичь аналогичного эффекта?

Для этого предназначены интерфейсные библиотеки. Они также предоставляют пример, похожий на то, что вы хотите сделать:

Другим случаем использования является применение совершенно целевого подхода к требованиям использования:

add_library(pic_on INTERFACE)
set_property(TARGET pic_on PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)
add_library(pic_off INTERFACE)
set_property(TARGET pic_off PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE OFF)

add_library(enable_rtti INTERFACE)
target_compile_options(enable_rtti INTERFACE
  $<$<OR:$<COMPILER_ID:GNU>,$<COMPILER_ID:Clang>>:-rtti>
)

add_executable(exe1 exe1.cpp)
target_link_libraries(exe1 pic_on enable_rtti)

Таким образом, спецификация сборки exe1 выражается полностью через связанные цели, и сложность компилятор-специфичных флагов инкапсулирована в INTERFACE библиотечной цели.

П.С. Также есть find_package(OpenSSL), который предоставляет необходимые цели, так что вам не нужно создавать свои собственные.

Ответ или решение

Вам действительно можно создать "псевдо-таргет" в CMake для упрощения управления зависимостями, такими как OpenSSL. Для этого идеально подходят интерфейсные библиотеки (INTERFACE libraries), которые позволяют организовать и скрыть сложные зависимости в одном месте. Давайте рассмотрим, как это можно сделать.

Шаги по созданию псевдо-таргета для OpenSSL:

  1. Создайте интерфейсную библиотеку для OpenSSL:

    Сначала определите интерфейсную библиотеку, которая будет хранить необходимые параметры компиляции и ссылки для OpenSSL. Например:

    add_library(openssl_pseudo_target INTERFACE)
    
    # Установите параметры компиляции для целевой библиотеки
    target_compile_options(openssl_pseudo_target INTERFACE
     -I${OPENSSL_INSTALL_DIR}/include
    )
    
    # Установите параметры линковки для целевой библиотеки
    target_link_options(openssl_pseudo_target INTERFACE
     -L${OPENSSL_INSTALL_DIR}/lib
    )
    
    # Установите зависимости для линковки
    target_link_libraries(openssl_pseudo_target INTERFACE
     libssl.a
     libcrypto.a
    )
  2. Используйте созданную библиотеку в вашем проекте:

    Теперь, когда у вас есть интерфейсная библиотека openssl_pseudo_target, вы можете легко использовать ее в других шарах вашего проекта:

    add_executable(my_program main.cpp)
    
    target_link_libraries(my_program
     PUBLIC
     boost_program_options
     openssl_pseudo_target
    )

Преимущества данного подхода:

  • Упрощение управления зависимостями: Вы централизуете все параметры компиляции и линковки для OpenSSL в одном месте, что упрощает поддержку и понимание кода.
  • Меньше ошибок: Вам не нужно каждый раз помнить о необходимости указания различных флагов и библиотек для OpenSSL.
  • Гибкость: Если в будущем вам потребуется изменить версии или параметры, это можно сделать в одном месте, не затрагивая другие части проекта.

Альтернативный вариант:

Если вы используете pre-packaged версии OpenSSL, стоит рассмотреть возможность использования find_package(OpenSSL), что позволит вам избежать ручной настройки. Это обеспечит подключение уже настроенных таргетов OpenSSL:

find_package(OpenSSL REQUIRED)

add_executable(my_program main.cpp)

target_link_libraries(my_program
  PUBLIC
  boost_program_options
  OpenSSL::SSL
  OpenSSL::Crypto
)

Таким образом, использование интерфейсных библиотек в сочетании с find_package предоставляет мощные инструменты для управления зависимостями в Вашем CMake проекте, что значительно упрощает процесс разработки.

Оцените материал
Добавить комментарий

Капча загружается...