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

我正在开发一个项目,我们正在开始发布二进制文件。 我们使用CMake来生成构build文件,并使用CPack来创build二进制文件。 我们的二进制工作,但我们遇到共享对象的问题。 从本质上讲,许多问题是由系统上的符号链接引起的,尤其是对于具有多个链接的共享对象。 所以,假设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(或get_filename_component(… REALPATH))上的readlink返回libmpich.so.10.0.4。 所以,如果我以名称libmpich.so.10.0.4或者libmpich.so.10.0.4安装libmpich.so.10.0.4(或者创build从一个到另一个的符号链接),我仍然错过了RPATH中要求的库。

在处理这些问题时,我一直在玩“重击”,并且/或者使用文件glob来尝试抓取中间链接,但是我想要做更强大的事情。 任何人都使用一个好的devise模式呢?

我一直在寻找使用像GET_PREREQUISITES这样的函数,但是那些需要被构build的对象,所以我需要将它们添加到安装脚本中……并且感觉它们应该是更好的方式。

-Jameson

PS我也喜欢用cmake或者一般的方法来寻找构build二进制文件的最佳实践指南。 我们正在Windows,Linux和Mac上生成二进制文件。 如果你知道一些好的链接,请将其发布。

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

为了解决符号链接的单一级别,您可以直接从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