我有一个构建系统,它使用 CMake 生成一个主守护进程和一些共享库,这些库是根据运行时的配置动态加载的(通过
dlopen
)。 然而,现在我需要支持另一个基于 Windows+exfat 的构建环境,它不支持符号链接(CMake Error: failed to create symbolic link 'libfoo.so.1': Operation not permitted
)。 我无法更改此构建要求,因为它来自公司的其他部门。 添加安装后清理步骤来删除异常符号链接将不起作用,因为生成符号链接时构建会失败。
在我的研究中,我发现了thisSO帖子,它准确地描述了我想要使用的
NAMELINK_SKIP
。 不幸的是,它似乎表明设置 VERSION
或 SOVERSION
会破坏此功能。 该项目确实使用了这两个变量,因为我们使用共享库修订来独立跟踪库的更改(每个库基本上提供了初始化特定硬件拓扑所需的供应商生成的配置 blob)。 库修订是我们需要保留的重要财产。
那么,简而言之,如何让 CMake 首先不为我的共享库生成符号链接,但仍保留完全版本化的库?
如果该库仅与
dlopen
机制一起使用,那么它的正确类型是 MODULE,而不是 SHARED:
add_library(foo MODULE <sources>)
对于此类库,CMake 不会将 SOVERSION 附加到文件名,也不会创建符号链接。 (SONAME 机制的全部目的是与 version-independent 文件名 link 并在 runtime 使用 version-dependent 文件。由于 MODULE 库未链接(在构建时),因此它们不会从该机制中受益)。
如果您希望库文件的名称包含版本字符串,那么您可以设置库的 OUTPUT_NAME:
add_library(foo MODULE <sources>)
# This will make the output file to be named as "libfoo.1.2.so",
# exactly that name should be used in 'dlopen' calls.
set_target_properties(foo PROPERTIES OUTPUT_NAME foo.1.2)
我有链接到库的测试用例(节省了大量构建时间)。不幸的是,如果您将库从
SHARED
转换为 MODULE
,您将无法再执行此操作。
令人痛苦的是,我有两个库,都声明为共享,其中一个执行 SO 版本的操作;还有一个没有。
在检查了两个模块之间的差异后,有问题的 CMake 行结果是:
set_target_properties(ToobAmp PROPERTIES VERSION ${PROJECT_VERSION})
set_target_properties(ToobAmp PROPERTIES SOVERSION 0)
删除这两行将禁用 SO 版本控制。
我现在可以将我的测试用例链接到该库,并且现在可以安装该库,而无需创建稍后必须清理的虚假链接。
这两个模块都是 LV2 插件,事实上,它们只能在构建机器之外使用 dlopen 加载。所以 SO 版本的链接只是虚假的混乱。