Linux 使用共享对象和符号链接构建安装包

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

我正在做一个项目,我们正在开始发布二进制文件。我们使用CMake生成构建文件,使用CPack创建二进制文件。我们的二进制文件可以工作,但是我们遇到了共享对象的问题。从本质上讲,许多问题都是由系统上的符号链接引起的,尤其是具有多个链接的共享对象。因此,假设某些可执行文件包括libmpich.So.10的ldd(或otool)的RPATH结果,我已经从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(或get_filename_组件(…REALPATH))上的readlink返回libmpich.so.10.0.4。因此,如果我以libmpich.So或libmpich.So.10.0.4的名称安装libmpich.So.10.0.4(或创建从一个到另一个的符号链接),我仍然错过了RPATH中要求的库

在处理这些问题和/或使用文件glob试图抓住中间链接时,我一直在打鼹鼠,但我想做一些更健壮的事情。有人用一个好的设计模式吗

我一直在研究如何使用诸如GET_Premissions之类的函数,但这些函数需要构建对象,因此我需要以某种方式将它们添加到安装脚本中。。。。感觉他们的方式应该更好

-詹姆逊


另外,我还一直在寻找构建二进制文件的最佳实践指南,可以是使用cmake,也可以是通用的。我们正在windows、linux和mac上生产二进制文件。如果你知道一些好的链接,请也发出来。

我最近刚刚处理了这个问题。cmake命令get_filename_组件(…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