CMAKE_LINK_GROUP_USING_<FEATURE>¶
3.24 版中新增。
该变量定义了当使用 LINK_GROUP
生成器表达式时如何链接特定 <FEATURE>
的库组。此变量只有满足以下两个条件时才会生效
关联的
CMAKE_LINK_GROUP_USING_<FEATURE>_SUPPORTED
变量必须设置为 true。同一
<FEATURE>
没有面向语言的特定定义。这意味着CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>_SUPPORTED
对用以评估LINK_GROUP
生成器表达式的目标使用的链接语言无效。
对于依赖于链接语言的功能,应该定义 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
变量的值给出。
例如,"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 平台时使用。