CMake:从ExternalProject链接共享C ++对象生成具有相对路径的二进制文件,而不是绝对

时间:2014-12-02 23:58:49

标签: c++ build cmake

问题:我正在CMake中构建一个外部项目。该项目有一个Makefile,最终生成一个共享对象。我想链接并在我的超级项目中安装此对象,就像它是项目中的一个库一样。问题是,ExternalProject lib通过相对路径链接到我的应用程序和库,而不是从CMake放置的任何目录运行时导致问题的绝对路径。

我有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)。

每当我在可执行文件和库中运行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。

1 个答案:

答案 0 :(得分:5)

花了一段时间,但我终于在CMake Users listserv的帮助下得到了答案,特别是@ brad-king。

主要问题是我没有在外部项目中正确编译我的共享对象。布拉德回答了我的问题:

  

感谢完整/简单的例子。问题是   由外部项目构建的libExtLib.so文件没有   由链接器设置DT_SONAME。给链接器一个   到没有soname然后路径的共享库文件的路径   被复制到消费者的DT_NEEDED字段中   没有使用的soname。

     

有两种解决方案:

     
      
  1. 确保外部构建系统正确设置DT_SONAME。

  2.   
  3. 告诉CMake导入的库文件没有soname:

         

    set_property(TARGET ExtLib PROPERTY IMPORTED_NO_SONAME 1)

         

    然后CMake将通过-lExtLib链接它,而链接器则不会   以DT_NEEDED存储文件的路径,但仅存储文件名。

  4.         

    其中任何一个都应解决问题。 1号更清洁。

由于我可以控制外部库中的Make文件,因此我通过编译共享对象选择了更清洁的第一个解决方案:

$(SHARED_TARGET): $(OBJECTS) $(CXX) $(CXXFLAGS) $(OBJECTS) -o $@ $(LDFLAGS) -Wl,-soname,$@

我修改了原始示例并使其更加简单:https://github.com/calebwherry/cmake-SO-question-main。我将把它作为参考,以便日后在这篇文章中绊倒。

<强> P.S。

还有另一个次优解决方案。如果我没有完成上述任何一项,我可以给target_link_library指向我链接的库的完整路径,而不是使用导入的库目标。我已在回购中的CMake文件中注明了这一点并对其进行了评论。不是一个很好的解决方案,但确实以另一种方式解决了问题。