具有冲突的 .so 名称的 C++/CMake 可安装库

C++/CMake installable libraries with conflicting .so names

我在 linux 系统上安装的 c++ 包中遇到库名称冲突的问题。这两个包都使用 cpack 内置到可安装的 apt 包中。正在安装两个软件包(AB)。 请注意,虽然我可以控制这些包,所以我可以更改 CMake 等等,但它们将被编译成 debian 包并作为系统库安装,而不是安装在 /usr/local/.

每个包都有自己的 utils 模块。 每个模块都安装了父项目的命名空间(所以 A::utilsB::utils),库 .so 文件在项目名称的子文件夹中,而不是直接在 /usr/lib - 所以 /usr/lib/A/libutils.so/usr/lib/B/libutils.so.

作为安装后脚本,带有项目名称(AB)的文件被添加到 /etc/ld.so.conf.d,其中包含已安装库的路径(/usr/lib/A 例如)到库路径。

除了utils项目A还有一个依赖于A::utils

的库foo

我有第三个项目 C,它有一个依赖于 A::foo 的可执行文件,但是(据我所知)没有 利用B 完全没有。

构建 C 时,我遇到错误,指出存在未定义的引用。通过进一步调查,我确定当 C 构建并且 A::foo 必须解析 utils 时,它发现 B::utils 而不是 A::utils 导致错误。我希望得到一些解释,说明为什么要 happening/how 来修复它?据我了解,命名空间(除了将库放在子文件夹中以使文件本身不冲突)将解决库命名冲突的问题。

下面是其中一个 CMakeLists 的安装部分示例

set(PROJECT_NAME A)
set(component utils)

add_library(${component} SHARED
        src/UtilsExample.cpp
        )
add_library(${PROJECT_NAME}::${component} ALIAS ${component})
#... stuff with the libraries and whatnot
install(TARGETS ${component} EXPORT ${component}Targets
  COMPONENT ${component}
  LIBRARY DESTINATION lib/${PROJECT_NAME}
  ARCHIVE DESTINATION lib/${PROJECT_NAME}
  RUNTIME DESTINATION bin
  )
install(EXPORT ${component}Targets
  FILE "${PROJECT_NAME}-${component}Targets.cmake"
  NAMESPACE ${PROJECT_NAME}::
  DESTINATION lib/cmake/${PROJECT_NAME}
  COMPONENT ${component}
  )

为确保库名称是唯一的,我是否需要在项目名称前添加项目名称或类似名称?所以图书馆会被命名为A_utils?这似乎会使外部项目的别名变得很奇怪,A::A_utils

Linux 动态库解析纯粹是靠所需要的库名。检查所有搜索路径,直到找到匹配的文件名,因此您不能有重复的 .so 文件名。

但是,实际上只有库文件名必须是唯一的。您可以为所有内部目的保留 CMake 命名空间名称,只需将输出文件名设置为 A_utils:

set_target_properties(A::utils PROPERTIES LIBRARY_OUTPUT_NAME A_utils)

在整个项目中继续为 target_link_libraries() 和类似使用 A::utils