具有冲突的 .so 名称的 C++/CMake 可安装库
C++/CMake installable libraries with conflicting .so names
我在 linux 系统上安装的 c++ 包中遇到库名称冲突的问题。这两个包都使用 cpack 内置到可安装的 apt 包中。正在安装两个软件包(A
和 B
)。
请注意,虽然我可以控制这些包,所以我可以更改 CMake 等等,但它们将被编译成 debian 包并作为系统库安装,而不是安装在 /usr/local/
.
下
每个包都有自己的 utils
模块。
每个模块都安装了父项目的命名空间(所以 A::utils
和 B::utils
),库 .so 文件在项目名称的子文件夹中,而不是直接在 /usr/lib
- 所以 /usr/lib/A/libutils.so
和 /usr/lib/B/libutils.so
.
作为安装后脚本,带有项目名称(A
或 B
)的文件被添加到 /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
。
我在 linux 系统上安装的 c++ 包中遇到库名称冲突的问题。这两个包都使用 cpack 内置到可安装的 apt 包中。正在安装两个软件包(A
和 B
)。
请注意,虽然我可以控制这些包,所以我可以更改 CMake 等等,但它们将被编译成 debian 包并作为系统库安装,而不是安装在 /usr/local/
.
每个包都有自己的 utils
模块。
每个模块都安装了父项目的命名空间(所以 A::utils
和 B::utils
),库 .so 文件在项目名称的子文件夹中,而不是直接在 /usr/lib
- 所以 /usr/lib/A/libutils.so
和 /usr/lib/B/libutils.so
.
作为安装后脚本,带有项目名称(A
或 B
)的文件被添加到 /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
。