2014-11-04 79 views
2

我正在開發一個項目,並且正在啓動發佈二進制文件。我們使用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),但在執行的readlink libmpich.so(或get_filename_component(...真實路徑))返回libmpich.so.10.0.4。因此,如果我以名稱libmpich.so.10.0.4或libmpich.so.10.0.4(或創建從一個到另一個的符號鏈接)安裝libmpich.so.10.0.4,我仍然錯過了RPATH中要求的庫。

我一直在玩捶打一個摩爾在處理這些和/或使用文件glob來嘗試抓取中間鏈接,但我想做更強大的事情。任何人都使用一個好的設計模式呢?

我一直在尋找使用像GET_PREREQUISITES這樣的函數,但那些需要構建的對象,所以我需要將它們添加到安裝腳本中......並且感覺它們應該是更好的方法。

-Jameson

P.S.我也正在尋找建立二進制文件的最佳實踐指南,無論是使用cmake還是一般。我們正在Windows,Linux和Mac上生成二進制文件。如果你知道一些好的鏈接,請將它們發佈。

回答

1

我剛剛自己處理了這個問題。 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