CMake:从外部项目链接共享C++对象会生成具有相对路径的二进制文件,而不是绝对路径
CMake: Linking Shared C++ Object from ExternalProject Produces Binaries with Relative Path, not Absolute
>问题:我正在CMake中构建一个外部项目。该项目有一个最终生成共享对象的生成文件。我想在我的超级项目中链接并安装此对象,就像它是项目中的库之一一样。问题是 ExternalProject 库通过相对路径链接到我的应用程序和库中,而不是绝对路径,这在从 CMake 放置它之外的任何目录运行时会导致问题。
我创建了一个示例 SSCCE 示例项目来演示我的整体设置。如果需要,请随意阅读和编译(git clone https://github.com/calebwherry/cmake-SO-question-main --recursive && cd cmake-SO-question-main && mkdir build && cd build && cmake .. && make && cd src/app/testApp && ldd testApp
(。
每当我在可执行文件和库上运行ldd
时,我都会得到这样的输出:
linux-vdso.so.1 => (0x00007fff8b5a2000)
libTestLib.so => /home/jwherry3/repos/cmake-superprj-main-test/build/src/lib/TestLib/libTestLib.so (0x00007f592da57000)
../../lib/libExtLib.so (0x00007f592d855000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f592d539000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f592d2b7000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f592d0a0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f592cd14000)
/lib64/ld-linux-x86-64.so.2 (0x00007f592dc5a000)
我已经尝试了处理 RPATH 的各种事情,但无法让 ExtLib 正确链接。项目本地的库(libTestLib.so
(链接很好。
我还尝试在运行应用程序时将LD_LIBRARY_PATH
设置为覆盖相对路径,但即使我这样做,它仍然找不到库。我想因为它是相对的,所以它不遵循正常的链接顺序?结果是二进制文件不会运行,除非我在它所在的目录中。
我觉得我在使用 ExternalProject 创建依赖项时正在做一些非常愚蠢的事情,这是我的问题,但我已经打了 3 天,什么也没想出来。
系统设置:Debian Wheezy 64 位,CMake 3.0.2,g++-4.9.2。
花了一段时间,但我终于在CMake用户列表服务器的帮助下找到了答案,特别是@brad王。
主要问题是我没有在外部项目中正确编译我的共享对象。布拉德对我问题的回答:
感谢您提供完整/简单的示例。 问题是 外部项目生成的 libExtLib.so 文件不会 链接器设置DT_SONAME。 当链接器被赋予 没有 SoName 的共享库文件的路径,然后是路径 被复制到消费者的DT_NEEDED字段中,因为它 没有名字可以使用。
有两种解决方案:
确保外部构建系统正确设置DT_SONAME。
告诉 CMake 导入的库文件没有 soname:
set_property(TARGET ExtLib PROPERTY IMPORTED_NO_SONAME 1(
然后,CMake 将通过 -lExtLib 链接它,而链接器不会 将文件的路径存储在DT_NEEDED但仅文件名中。
其中任何一个都应该解决问题。 数字 1 更干净。
由于我可以控制外部库中的 Make 文件,因此我选择了更清洁的第一个解决方案,通过编译共享对象,如下所示:
$(SHARED_TARGET): $(OBJECTS)
$(CXX) $(CXXFLAGS) $(OBJECTS) -o $@ $(LDFLAGS) -Wl,-soname,$@
修改了我原来的例子,让它变得简单得多:https://github.com/calebwherry/cmake-SO-question-main。我将把它留给以后偶然发现这篇文章的人的参考。
附言
还有另一个次优修复。如果我没有执行上述任何操作,我就可以只target_link_library提供我所链接的库的完整路径,而不使用导入的库目标。我已经在存储库的 CMake 文件中注意到了这一点,并将其注释掉。不是一个很好的解决方案,但确实以另一种方式解决问题。
- 正在读取二进制文件(is_open)
- 在C++中将类(带有Vector成员)保存为二进制文件
- 如何从二进制文件中读取字符串
- 保存/加载大量短数组到二进制文件
- 从二进制文件中读取整数数组
- Android 在编译二进制文件时重建静态库
- 在 C++ 中将双精度变量写入二进制文件
- clang 的 libFuzzer 可以在同一二进制文件中测试超过 1 个 API 吗?
- C++:实际上不是从二进制文件中读取
- 如何从二进制文件中的给定符号中获取调用程序图
- 将内部带有矢量的结构保存/读取到二进制文件中
- 编译多个C++文件.调用二进制文件以运行代码
- 如何使用位字段将数据从二进制文件复制到结构中?
- uint8_t同一二进制文件的不同十进制值
- 获取 JAR 文件中二进制文件的路径
- gcc为不同路径的相同代码库生成的二进制文件中的差异
- CMake:从外部项目链接共享C++对象会生成具有相对路径的二进制文件,而不是绝对路径
- VS 中具有不同矢量化路径的二进制文件
- 如何避免iOS二进制文件中的符号和源路径
- 安装GCC-4.9没有根添加路径和二进制文件和额外的