Spec-Zone.ru › CMake 3.29

CMAKE_LINK_LIBRARY_USING_<FEATURE>

Новое в версии 3.24.

Эта переменная определяет, как подключать библиотеку или фреймворк для указанного <FEATURE> при использовании генератора выражений LINK_LIBRARY. Для того, чтобы эта переменная имела какой-либо эффект, должны быть выполнены оба следующих условия:

  • Соответствующая переменная CMAKE_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED должна быть установлена в значение true.
  • Нет специфичной для языка дефиниции для того же <FEATURE>. Это означает, что CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED не может быть true для языка линковки, используемого целевым объектом, для которого оценивается генератор выражения LINK_LIBRARY.

Имена функций чувствительны к регистру и могут содержать только буквы, цифры и символы нижнего подчеркивания. Имена функций, определённые в верхнем регистре, зарезервированы для встроенных функций CMake (см. Предопределённые функции ниже).

Определения функций

Определение функции библиотеки представляет собой список, содержащий один или три элемента:

[<PREFIX>] <LIBRARY_EXPRESSION> [<SUFFIX>]

Когда <PREFIX> и <SUFFIX> указаны, они соответственно предшествуют и следуют всему списку библиотек, указанных в выражении LINK_LIBRARY, а не каждому элементу списка библиотек индивидуально. Однако нет гарантии, что список указанных библиотек сохранит исходную группировку, поэтому <PREFIX> и <SUFFIX> могут появиться более одного раза, если список библиотек перегруппируется CMake для удовлетворения других ограничений. Это означает, что конструкции, подобные --start-group и --end-group, поддерживаемые линкером GNU ld, не могут быть использованы таким образом. Вместо этого следует использовать генератор выражений LINK_GROUP.

<LIBRARY_EXPRESSION> используется для указания шаблона для построения соответствующего фрагмента командной строки линкера для каждой библиотеки. В выражении можно использовать следующие плейсхолдеры:

  • <LIBRARY> расширяется до полного пути к библиотеке для целевых объектов CMake или до платформозависимого значения в другом случае (так же, как <LINK_ITEM> в Windows или имени базового файла библиотеки для других платформ).
  • <LINK_ITEM> расширяется до того, как библиотека обычно подключалась бы в командной строке линкера.
  • <LIB_ITEM> расширяется до полного пути к библиотеке для целевых объектов CMake или самого элемента точно так, как он указан в <LIBRARY_EXPRESSION> в ином случае.

Помимо вышеперечисленного, возможно иметь один шаблон для путей (целевые объекты CMake и внешние библиотеки, указанные с путями к файлам) и другой для других элементов, указанных только по имени. Обёртки PATH{} и NAME{} могут быть использованы для обеспечения расширения для этих двух случаев соответственно. При использовании обёрток обе должны быть присутствовать. Например:

set(CMAKE_LINK_LIBRARY_USING_weak_library
    "PATH{-weak_library <LIBRARY>}NAME{LINKER:-weak-l<LIB_ITEM>}"
)

Для всех трёх элементов этой переменной (<PREFIX>, <LIBRARY_EXPRESSION>, и <SUFFIX>) можно использовать префикс LINKER:.

Для передачи опций инструменту линковки у каждого драйвера компилятора своя синтаксис. Префикс LINKER: и разделитель , могут использоваться для указания, портативным способом, опций для передачи инструменту линковки. LINKER: заменяется соответствующей опцией драйвера, а , — соответствующим разделителем драйвера. Префикс и разделитель драйвера задаются значениями переменных CMAKE_<LANG>_LINKER_WRAPPER_FLAG и CMAKE_<LANG>_LINKER_WRAPPER_FLAG_SEP.

Например, "LINKER:-z,defs" становится -Xlinker -z -Xlinker defs для Clang и -Wl,-z,defs для GNU GCC.

Префикс LINKER: может быть указан как часть выражения префикса SHELL:.

Префикс LINKER: поддерживает, как альтернативный синтаксис, указание аргументов с использованием префикса SHELL: и пробела в качестве разделителя. Предыдущий пример тогда становится "LINKER:SHELL:-z defs".

Примечание

Указание префикса SHELL: в любом месте, кроме начала префикса LINKER:, не поддерживается.

Примеры

Загрузка всей статической библиотеки

Частая потребность — предотвратить отбрасывание линкером любых символов из статической библиотеки. Разные линковщики используют различный синтаксис для достижения этого. Следующий пример показывает, как это может быть реализовано для некоторых линковщиков. Обратите внимание, что это только для иллюстративных целей. Проекты должны использовать встроенную функцию WHOLE_ARCHIVE вместо этого (см. Предопределённые функции), которая обеспечивает более полную и более надёжную реализацию этой функциональности.

set(CMAKE_C_LINK_LIBRARY_USING_load_archive_SUPPORTED TRUE)
if(CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
  set(CMAKE_C_LINK_LIBRARY_USING_load_archive "-force_load <LIB_ITEM>")
elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
  set(CMAKE_C_LINK_LIBRARY_USING_load_archive
    "LINKER:--push-state,--whole-archive"
    "<LINK_ITEM>"
    "LINKER:--pop-state"
  )
elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
  set(CMAKE_C_LINK_LIBRARY_USING_load_archive "/WHOLEARCHIVE:<LIBRARY>")
else()
  # feature not yet supported for the other environments
  set(CMAKE_C_LINK_LIBRARY_USING_load_archive_SUPPORTED FALSE)
endif()

add_library(lib1 STATIC ...)
add_library(lib2 SHARED ...)

if(CMAKE_C_LINK_LIBRARY_USING_load_archive_SUPPORTED)
  # The -force_load Apple linker option requires a file name
  set(external_lib
    "$<IF:$<LINK_LANG_AND_ID:C,AppleClang>,libexternal.a,external>"
  )
  target_link_libraries(lib2 PRIVATE
    "$<LINK_LIBRARY:load_archive,lib1,${external_lib}>"
  )
else()
  target_link_libraries(lib2 PRIVATE lib1 external)
endif()

CMake сгенерирует следующие выражения линковки:

  • AppleClang: -force_load /path/to/lib1.a -force_load libexternal.a
  • GNU: -Wl,--push-state,--whole-archive /path/to/lib1.a -lexternal -Wl,--pop-state
  • MSVC: /WHOLEARCHIVE:/path/to/lib1.lib /WHOLEARCHIVE:external.lib

Подключение библиотеки как слабой

В macOS возможно подключение библиотеки в слабом режиме (библиотека и все ссылки помечены как слабые импорты). Для библиотеки, указанной по пути к файлу, должны использоваться другие флаги по сравнению с библиотекой, указанной по имени. Это ограничение может быть решено с помощью обёрток PATH{} и NAME{}. Опять же, следующий пример демонстрирует, как это может быть реализовано для некоторых линковщиков, но он только для иллюстративных целей. Проекты должны использовать встроенные функции WEAK_FRAMEWORK или WEAK_LIBRARY вместо этого (см. Предопределённые функции), которые предоставляют более полные и надёжные реализации этой функциональности.

if (CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
  set(CMAKE_LINK_LIBRARY_USING_weak_library
      "PATH{-weak_library <LIBRARY>}NAME{LINKER:-weak-l<LIB_ITEM>}"
  )
  set(CMAKE_LINK_LIBRARY_USING_weak_library_SUPPORTED TRUE)
endif()

add_library(lib SHARED ...)
add_executable(main ...)
if(CMAKE_LINK_LIBRARY_USING_weak_library_SUPPORTED)
  target_link_libraries(main PRIVATE "$<LINK_LIBRARY:weak_library,lib,external>")
else()
  target_link_libraries(main PRIVATE lib external)
endif()

CMake сгенерирует следующий фрагмент командной строки линкера при подключении main с помощью инструментальной цепочки AppleClang:

-weak_library /path/to/lib -Xlinker -weak-lexternal.

Предопределённые функции

Следующие встроенные функции библиотек определены CMake по умолчанию:

DEFAULT

Эта функция соответствует стандартному связыванию, по сути, эквивалентному отсутствию каких-либо дополнительных настроек. Она обычно используется только с целевыми свойствами LINK_LIBRARY_OVERRIDE и LINK_LIBRARY_OVERRIDE_<LIBRARY>.

WHOLE_ARCHIVE

Принудительное включение всех элементов статической библиотеки. Эта функция поддерживается только для следующих платформ с указанными ограничениями:

  • Linux.
  • Все варианты BSD.
  • SunOS.
  • Все варианты Apple. Библиотека должна быть указана как имя целевого объекта CMake, имя файла библиотеки (например, libfoo.a) или путь к файлу библиотеки (например, /path/to/libfoo.a). Из-за ограничения Apple Linker, она не может быть указана как просто имя библиотеки, например, foo, где foo не является целевым объектом CMake.
  • Windows. При использовании MSVC или подобной инструментальной цепочки, версия MSVC должна быть больше 1900.
  • Cygwin.
  • MSYS.
FRAMEWORK

Этот параметр сообщает линковщику искать указанную фреймворк-библиотеку, используя опцию линковщика -framework. Он может использоваться только на платформах Apple и только с линковщиком, понимающим используемую опцию (например, линковщик, предоставленный Xcode, или совместимый с ним).

Фреймворк может быть указан как целевой объект CMake фреймворка, как простое имя фреймворка или как путь к файлу. Если указан целевой объект, то для него должно быть установлено свойство целевого объекта FRAMEWORK со значением true. Для пути к файлу, если он содержит часть каталога, то этот каталог будет добавлен в пути поиска фреймворков.

add_library(lib SHARED ...)
target_link_libraries(lib PRIVATE "$<LINK_LIBRARY:FRAMEWORK,/path/to/my_framework>")

# The constructed linker command line will contain:
#   -F/path/to -framework my_framework

Пути к файлам должны соответствовать одному из следующих шаблонов (* — подстановочный знак, а необязательные части показаны как [...]):

  • [/path/to/]FwName[.framework]
  • [/path/to/]FwName.framework/FwName[suffix]
  • [/path/to/]FwName.framework/Versions/*/FwName[suffix]

Обратите внимание, что CMake распознаёт и автоматически обрабатывает целевые объекты фреймворков, даже без использования выражения $<LINK_LIBRARY:FRAMEWORK,...>. Генераторское выражение всё же может быть использовано с целевым объектом CMake, если проект хочет быть явным в этом, но это не обязательно. Командная строка линковщика может иметь некоторые отличия при использовании генераторского выражения или без него, но конечный результат должен быть одинаковым. С другой стороны, если указан путь к файлу, CMake будет автоматически распознавать некоторые пути, но не все. Проект может использовать $<LINK_LIBRARY:FRAMEWORK,...> для путей к файлам, чтобы ожидаемое поведение было ясным.

В версии 3.25: Свойство целевого объекта FRAMEWORK_MULTI_CONFIG_POSTFIX_<CONFIG>, а также suffix имени библиотеки фреймворка теперь поддерживаются функциями FRAMEWORK.

NEEDED_FRAMEWORK

Это аналогично функции FRAMEWORK, за исключением того, что она принуждает линковщик связаться с фреймворком, даже если из него не используются никакие символы. Она использует опцию -needed_framework и имеет те же ограничения линковщика, что и FRAMEWORK.

REEXPORT_FRAMEWORK

Это аналогично функции FRAMEWORK, за исключением того, что она сообщает линковщику, что фреймворк должен быть доступен клиентам, связывающимся с создаваемой библиотекой. Она использует опцию -reexport_framework и имеет те же ограничения линковщика, что и FRAMEWORK.

WEAK_FRAMEWORK

Это аналогично функции FRAMEWORK, за исключением того, что она принуждает линковщик пометить фреймворк и все ссылки на него как слабые импорты. Она использует опцию -weak_framework и имеет те же ограничения линковщика, что и FRAMEWORK.

NEEDED_LIBRARY

Это аналогично функции NEEDED_FRAMEWORK, за исключением того, что она предназначена для использования с целевыми объектами или библиотеками, не являющимися фреймворками (только платформы Apple). Она использует опцию -needed_library или -needed-l соответственно и имеет те же ограничения линковщика, что и NEEDED_FRAMEWORK.

REEXPORT_LIBRARY

Это аналогично функции REEXPORT_FRAMEWORK, за исключением того, что она предназначена для использования с целевыми объектами или библиотеками, не являющимися фреймворками (только платформы Apple). Она использует опцию -reexport_library или -reexport-l соответственно и имеет те же ограничения линковщика, что и REEXPORT_FRAMEWORK.

WEAK_LIBRARY

Это аналогично функции WEAK_FRAMEWORK, за исключением того, что она предназначена для использования с целевыми объектами или библиотеками, не являющимися фреймворками (только платформы Apple). Она использует опцию -weak_library или -weak-l соответственно и имеет те же ограничения линковщика, что и WEAK_FRAMEWORK.

© 2000–2024 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.29/variable/CMAKE_LINK_LIBRARY_USING_FEATURE.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API