我正在开发一个项目,我们正在开始发布二进制文件。我们使用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试图抓住中间链接时,我一直在玩打击鼹鼠,但我想做更强大的事情。有人为此使用了良好的设计模式吗?
我一直在研究使用像GET_PREREQUISITES这样的函数,但那些需要构建对象,所以我需要以某种方式将它们添加到安装脚本中......并且感觉它们应该是更好的方式。
-Jameson
P.S。我也在寻找建立二进制文件的最佳实践指南,无论是使用cmake还是通常。我们在windows,linux和mac上生成二进制文件。如果你知道一些好的链接,请发布它们。
答案 0 :(得分:4)
我最近刚刚处理了这个问题。 cmake命令get_filename_component(... REALPATH)在一次调用中恢复符号链接的所有级别。
要解决单个级别的符号链接问题,您可以调用“#readlink'直接来自cmake,因为它可以在你可能构建的每个符合链接的平台上使用(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