【问题标题】:Building install packages with shared objects and symbolic links使用共享对象和符号链接构建安装包
【发布时间】:2014-11-04 01:18:07
【问题描述】:

我正在开发一个项目,我们正在开始发布二进制文件。我们使用 CMake 生成构建文件,使用 CPack 创建二进制文件。我们的二进制文件可以工作,但我们遇到了共享对象的问题。本质上,许多问题是由系统上的符号链接引起的,尤其是对于具有多个链接的共享对象。因此,假设某些可执行文件的 ldd(或 otool)的 RPATH 结果包括 libmpich.so.10 并且我已经从 cmake 链接了 /usr/lib/x86_64-linux-gnu/libmpich.so 并且这些文件是这样相关的:

/usr/lib/x86_64-linux-gnu/libmpich.so -> libmpich.so.10
/usr/lib/x86_64-linux-gnu/libmpich.so.10 -> libmpich.so.10.0.4
/usr/lib/x86_64-linux-gnu/libmpich.so.10.0.4

现在,由于某种原因,RPATH 使用中间链接 (so.10),但 libmpich.so 上的 readlink(或 get_filename_component(... REALPATH))返回 libmpich.so.10.0.4。因此,如果我以 libmpich.so 或 libmpich.so.10.0.4 的名称安装 libmpich.so.10.0.4(或创建从一个到另一个的符号链接),我仍然错过了 RPATH 中要求的库。

在处理这些问题和/或使用文件 glob 尝试获取中间链接时,我一直在玩 whack-a-mole,但我想做一些更强大的事情。有人为此使用了一个好的设计模式吗?

我一直在研究使用 GET_PREREQUISITES 之类的函数,但这些函数需要构建对象,所以我需要以某种方式将它们添加到安装脚本中……感觉它们应该是更好的方法。

-詹姆森

附:我也一直在寻找构建二进制文件的最佳实践指南,无论是使用 cmake 还是一般。我们在 windows、linux 和 mac 上生成二进制文件。如果您知道一些好的链接,请也发布它们。

【问题讨论】:

    标签: linux installation cmake


    【解决方案1】:

    我最近自己处理了这个问题。 cmake 命令 get_filename_component(... REALPATH) 在一次调用中解析符号链接的所有级别。

    要仅解析单个级别的符号链接,您可以直接从 cmake 调用“readlink”,因为它在您可能构建的每个启用符号链接的平台上都可用(Linux、Mac OS X 和 *BSD) .

    所以,如果你想重现完整的符号链接链, 你会在你的 cmake 脚本中编写这样的代码:

    #If given the following library path:
    set(lib  "/usr/lib/x86_64-linux-gnu/libmpich.so")
    
    #Make sure the initial path is absolute.
    get_filename_component(lib "${lib}" ABSOLUTE)
    
    #Store initial path as first element in list.
    set(symlist "${lib}")
    
    while(UNIX AND IS_SYMLINK "${lib}")
      #Grab path to directory containing the current symlink.
      get_filename_component(sym_path "${lib}" DIRECTORY)
    
      #Resolve one level of symlink, store resolved path back in lib.
      execute_process(COMMAND readlink "${lib}"
                      RESULT_VARIABLE errMsg
                      OUTPUT_VARIABLE lib
                      OUTPUT_STRIP_TRAILING_WHITESPACE)
    
      #Check to make sure readlink executed correctly.
      if(errMsg AND (NOT "${errMsg}" EQUAL "0"))
        message(FATAL_ERROR "Error calling readlink on library.")
      endif()
    
      #Convert resolved path to an absolute path, if it isn't one already.
      if(NOT IS_ABSOLUTE "${lib}")
        set(lib "${sym_path}/${lib}")
      endif()
    
      #Append resolved path to symlink resolution list.
      list(APPEND symlist "${lib}")
    endwhile()
    
    #Now symlist will contain the following:
    # [...]/libmpich.so;[...]/libmpich.so.10;[...]/libmpich.so.10.0.4
    

    【讨论】:

      猜你喜欢
      • 2017-03-11
      • 2012-05-31
      • 2013-09-12
      • 1970-01-01
      • 2017-01-25
      • 2019-10-31
      • 2012-08-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多