-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CMake 动态链接库绝对路径问题 #162
Comments
请问作者, FooConfig.cmake的内容是靠 install(export) 自动生成的吗? |
不是,上面的例子是给第三方没有实现 cmake 支持的库写的,如果是自己的项目就参考 #137 这个里面写的自动生成 |
拜读过 #137 ,但是那样生成的 cmake config 文件应该不支持区分静态库或者动态库, 而且动态库和静态库是两个 cmake config 文件. |
大概明白你意思了,我说个我们自己使用的方式: 从 target 名称进行区分,比如静态库是 |
比如静态库是 foo 而动态库是 fooShared,这样的话,编译一次就可以自动生成一个 find config install(TARGETS foo EXPORT myfooLib)
install(EXPORT myfooLib)
install(TARGETS fooShared EXPORT myfooSharedLib)
install(EXPORT myfooSharedLib) |
可以直接参考 #137 的导出部分来,我给个关键的部分 add_library(fooStatic STATIC foo.cpp)
set_target_properties(fooStatic PROPERTIES OUTPUT_NAME foo) # libfoo.a
add_library(fooShared SHARED foo.cpp)
set_target_properties(fooShared PROPERTIES OUTPUT_NAME foo) # libfoo.so
install(
TARGETS fooStatic fooShared
EXPORT Foo
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES
DESTINATION include)
install(
EXPORT Foo
FILE FooTargets.cmake
NAMESPACE Foo::
DESTINATION lib/cmake/Foo/) 在使用的时候: find_package(Foo)
target_link_libraries(bar PUBLIC Foo::fooShared)
# 或者
target_link_libraries(bar PUBLIC Foo::fooStatic) |
这两天我试了下, 按照您给的建议, 已经将动态库和静态库合一安装, 其他 project 也能正常引用到. 说来也巧, 真的是因为这篇文章独立的标题 我才能检索到这的, 再次感谢下. 另外, 关于安装部分有个问题想再请教下. 假设下面这种场景
我想了下, 要么停止 library A 的依赖库传染, 要么想办法把 target B 也传递给 binary B. 前者应该会导致依赖不完整,, 后者感觉应该是在您前面提到的
|
hh,挺巧 你说这个问题没遇到过,目前除了你说的,没有更好的办法了 |
周末检索各种资料确认了下, CMake官方的态度是这类第三方依赖应该downstream提前安装好, upstream在 |
今天这篇文章算是对 【CMake 系列】(五)安装、打包与导出 的一个补充。其实我本打算跟上篇文章放在一起,毕竟都属于动态链接库相关的知识,但是这样一来就不容易被出现问题的同学们检索到了(才不是为了再水一篇文章 doge)。
问题的由来
是因为这个问题困扰了我不少时间,在好几个项目里面都遇到了这个问题。
那就是链接动态库的时候,编译出来的可执行文件会带有编译时的绝对路径,于是你将程序拷贝到其它地方运行的时候,必须把动态库放到绝对路径里面去,而不是放在系统里面相关的 lib 路径下面。
举一个例子,假如我们要实现一个
FooConfig.cmake
,这个库中既有静态库也有动态库,那么如果我们要在项目中使用,大概的实现方式是:将它命名为
FooConfig.cmake
然后放在位于项目根目录的 cmake 文件夹下,并且在项目中这样使用:最后,假如我们查找的库在
/path/to/foo/home
下面,那么我们用在项目中得到的结果会是这样的:$ readelf -d a.out | grep NEEDED Dynamic section at offset 0xb5ddb4 contains 2 entries: Tag Type Name/Value 0x00000001 (NEEDED) Shared library: [/path/to/foo/home/lib/libfoo.so] 0x00000001 (NEEDED) Shared library: [/path/to/foo/home/lib/libbar.so]
这里就出现了绝对路径,当初这个问题折磨了我很久,一直以为是 RPATH 的问题,最后发现是 CMake 本身的问题。
如何解决
出现这个问题的原因就是库的 Package Find Config 不对,我研究了挺长时间,最后在官方的讨论中找到了原因以及答案:
IMPORTED_NO_SONAM
E 的属性;UNKNWON
类型的库;于是,将上面的代码改下即可:
The text was updated successfully, but these errors were encountered: