CMAKE_LINK_GROUP_USING_<FEATURE>¶
在 3.24 版本中添加。
当使用 LINK_GROUP 生成器表达式时,此变量定义了如何为指定的 <FEATURE> 链接一组库。要使此变量生效,必须满足以下两个条件:
关联的
CMAKE_LINK_GROUP_USING_<FEATURE>_SUPPORTED变量必须设置为 true。对于同一个
<FEATURE>,不存在特定于语言的定义。这意味着对于执行LINK_GROUP生成器表达式的目标所使用的链接语言,CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>_SUPPORTED不能为 true。
对于依赖于链接语言的功能,应改用 CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE> 变量。
功能名称区分大小写,并且只能包含字母、数字和下划线。所有大写字母的功能名称保留给 CMake 自身的内置功能(请参阅下面的 预定义功能)。
功能定义¶
组功能定义是一个恰好包含两个元素的列表
<PREFIX> <SUFFIX>
在链接器命令行上,<PREFIX> 将出现在组中库列表的前面,而 <SUFFIX> 将出现在后面。
对于此变量的元素,可以使用 LINKER: 前缀。
要将选项传递给链接器工具,每个编译器驱动程序都有其自己的语法。LINKER: 前缀和 , 分隔符可用于以可移植的方式指定传递给链接器工具的选项。LINKER: 会被替换为适当的驱动程序选项,, 会被替换为适当的驱动程序分隔符。驱动程序前缀和驱动程序分隔符由 CMAKE_<LANG>_LINKER_WRAPPER_FLAG 和 CMAKE_<LANG>_LINKER_WRAPPER_FLAG_SEP 变量的值给定。
例如,对于 Clang,"LINKER:-z,defs" 会变成 -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-groupSunPro:-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 平台时使用。