我有created a sample SSCCE example project来演示我的整体设置.如果需要,请随意仔细阅读和编译(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).
每当我在可执行文件和libs上运行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)
我已尝试过处理RPATHS的各种事情,但无法将ExtLib链接到正确的位置.项目本地的lib(libTestLib.so)链接得很好.
我还尝试设置LD_LIBRARY_PATH以覆盖运行应用程序时的相对路径,但即使我这样做,它仍然找不到库.我想因为它是相对的,它不遵循正常的链接顺序?结果是二进制文件不会运行,除非我在它所在的目录中.
我觉得在使用ExternalProject创建依赖项时,我正在做一些非常愚蠢的事情,这是我的问题,但我已经打了3天,并没有想出任何东西.
系统设置:Debian Wheezy 64位,CMake 3.0.2,g -4.9.2.
解决方法
主要问题是我没有在我的外部项目中正确编译我的共享对象.布拉德回答我的问题:
Thanks for the complete/simple example. The problem is that
the libExtLib.so file built by the external project does not
have DT_SONAME set by the linker. When a linker is given a
path to a shared library file that has no soname then the path
is copied into the DT_NEEDED field of the consumer since it
has no soname to use for that.There are two solutions:
Make sure DT_SONAME gets set properly by the external build system.
Tell CMake that the imported library file has no soname:
set_property(TARGET ExtLib PROPERTY IMPORTED_NO_SONAME 1)
CMake will then link it via -lExtLib and the linker will not
store the path to the file in DT_NEEDED but only the file name.Either of these should resolve the issue. Number 1 is cleaner.
由于我可以控制外部库中的Make文件,因此我通过编译共享对象选择了更清洁的第一个解决方案,如下所示:
$(SHARED_TARGET):$(OBJECTS)
$(CXX)$(CXXFLAGS)$(OBJECTS)-o $@ $(LDFLAGS)-Wl,-soname,$@
我已经修改了我的原始示例并使其更加简单:https://github.com/calebwherry/cmake-SO-question-main.我将把它作为参考,以便日后在这篇文章中绊倒的人.
附:
还有另一个次优解决方案.如果我没有完成上述任何操作,我可以给target_link_library指向我链接的库的完整路径,而不是使用导入的库目标.我在回购中的CMake文件中注意到了这一点并对其进行了评论.不是一个好的解决方案,但确实以另一种方式解决了问