CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>¶
在版本 3.24 中添加。
当使用 LINK_GROUP
生成器表达式且目标的链接语言为 <LANG>
时为指定的 <FEATURE>
变量定义此变量以链接一组库。此变量要产生任何效果,关联的 CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>_SUPPORTED
变量必需设定为 true。
对于独立于链接语言的特性,应定义 CMAKE_LINK_GROUP_USING_<FEATURE>
变量。
特性名称区分大小写并且仅可以包含字母、数字和下划线。在所有大写字母中定义的特性名称保留给 CMake 的内置特性(请参阅下文的 预定义特性)。
特性定义¶
组特性定义是一个恰好包含两个元素的列表
<PREFIX> <SUFFIX>
在链接器命令行中,<PREFIX>
将先于组中的库列表,而 <SUFFIX>
将后于库列表。
对于此变量的元素,可以使用 LINKER:
前缀。
为了向链接器工具传递选项,每个编译器驱动都有其自身的语法。LINKER:
前缀和 ,
分隔符可用于以可移植的方式指定传递给链接器工具的选项。LINKER:
由适当的驱动程序选项替换,,
由适当的驱动程序分隔符替换。驱动程序前缀和驱动程序分隔符由 CMAKE_<LANG>_LINKER_WRAPPER_FLAG
和 CMAKE_<LANG>_LINKER_WRAPPER_FLAG_SEP
变量给定。
例如,"LINKER:-z,defs"
对于 Clang
变成 -Xlinker -z -Xlinker defs
,对于 GNU GCC
变为 -Wl,-z,defs
。
LINKER:
前缀可以作为 SHELL:
前缀表达式的一部分指定。
LINKER:
前缀支持使用 SHELL:
前缀和空格进行分隔,作为一种替代语法来指定参数。之前的示例随后变成 "LINKER:SHELL:-z defs"
。
注意
除了在 LINKER:
前缀的开头,不支持在其他任何地方指定 SHELL:
前缀。
示例¶
解决两个静态库之间的交叉引用¶
一个项目可以定义两个或多个相互之间有循环依赖的静态库。为了让链接器在链接时解析所有符号,它可能需要在库中重复搜索,直到不再创建新的未定义引用。不同的链接器使用不同的语法来实现此功能。以下示例展示了如何针对一些链接器实现此功能。注意,这仅用于说明。相反,项目应该使用内置的 RESCAN
组功能(请参阅 预定义的功能),此功能提供了此功能更完整、更健壮的实现。
set(CMAKE_C_LINK_GROUP_USING_cross_refs_SUPPORTED TRUE)
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(CMAKE_C_LINK_GROUP_USING_cross_refs
"LINKER:--start-group"
"LINKER:--end-group"
)
elseif(CMAKE_C_COMPILER_ID STREQUAL "SunPro" AND CMAKE_SYSTEM_NAME STREQUAL "SunOS")
set(CMAKE_C_LINK_GROUP_USING_cross_refs
"LINKER:-z,rescan-start"
"LINKER:-z,rescan-end"
)
else()
# feature not yet supported for the other environments
set(CMAKE_C_LINK_GROUP_USING_cross_refs_SUPPORTED FALSE)
endif()
add_library(lib1 STATIC ...)
add_library(lib2 SHARED ...)
if(CMAKE_C_LINK_GROUP_USING_cross_refs_SUPPORTED)
target_link_libraries(lib2 PRIVATE "$<LINK_GROUP:cross_refs,lib1,external>")
else()
target_link_libraries(lib2 PRIVATE lib1 external)
endif()
链接 lib2
时,CMake 将生成以下链接器命令行片段
GNU
:-Wl,--start-group /path/to/lib1.a -lexternal -Wl,--end-group
SunPro
:-Wl,-z,rescan-start /path/to/lib1.a -lexternal -Wl,-z,rescan-end
预定义的功能¶
CMake 预定义了以下内置组功能
RESCAN
一些链接器仅为单遍链接器。对于此类链接器,库之间的循环引用通常会导致未解析符号。此功能指示链接器重复搜索指定的静态库,直到不再创建新的未定义引用为止。
通常,静态库仅按命令行中指定它们的顺序进行搜索一次。如果某个库中的符号用于解析位于命令行后面某个库中的某个对象引用的未定义符号,链接器将无法解析该引用。通过使用
RESCAN
功能对静态库进行分组,将重复搜索所有库,直到解析所有可能的引用为止。这将使用诸如--start-group
和--end-group
的链接器选项,或在 SunOS 上使用-z rescan-start
和-z rescan-end
。使用此功能会显著影响性能。最好仅在两个或更多个静态库之间存在不可避免的循环引用时使用此功能。
在使用针对 Linux、BSD 和 SunOS 的工具链时,此功能可用。在使用 GNU 工具链时,此功能也可用于针对 Windows 平台。