2017-05-24 33 views
1

我的問題與.so共享庫有關。我正在構建一個在一臺Ubuntu機器上使用cmake的項目,但在另一臺Ubuntu機器上運行該應用程序。在所有情況下運行時是否需要存在.so庫

在的CMakeLists.txt文件,我有以下行:

project (clientapp) 

add_executable(${PROJECT_NAME} ${SOURCES} ${WAKAAMA_SOURCES} ${SHARED_SOURCES}) 

LINK_DIRECTORIES(/home/user//mraa-master-built/build/src) 
target_link_libraries (clientapp libmraa.so) 
target_link_libraries(clientapp m) 

這些線路增加兩個庫libmraa.so和數學庫的可執行文件,它的另一臺機器上成功運行。

我對共享庫的理解是,它們必須在編譯時和應用程序啓動時出現。但是在另一臺機器上沒有libmraa.so文件,應用程序運行正常。我預計它不會工作。

我的假設是否正確?

+0

請問您的程序撥打電話在那個例程中,你試過的用法是?我想知道,如果他們只在訪問時才需要,而不是在應用程序啓動時。 – Scooter

+1

也可能是您的程序實際上並不需要該庫,儘管它存在於構建文件中。 – Scooter

+1

@Scooter對不起,但圖書館實際上是在機器上(我沒有安裝它的庫)。對不起,因爲一個愚蠢的問題而浪費你的時間。但是,應用程序如何知道在機器上的哪個位置找到共享庫,因爲我沒有指定路徑? –

回答

1

我的假設是否正確?

是的。

有爲什麼在應用程序運行兩種可能的解釋呢:

  1. 你錯了,並有libmraa.so某處的機器上(儘管也許不是在你看的地方),或
  2. 默認情況下,您的編譯器默認爲-Wl,--as-needed,而您的二進制文件實際上不是依賴於libmraa.so,儘管它出現在您的鏈接行上。

您可以平凡地確認或反駁上述猜測。

爲了證實猜測2,這樣做:

readelf -d clientapp | grep NEED | grep libmraa 
# if there is no output, guess 2 is correct 

如果猜測2是錯誤的,確認的猜測1,做這個(機器上沒有libmrra.so):

ldd clientapp | grep libmraa.so 
# if guess 2 is incorrect, and this command produces no output, then 
# your dynamic loader is broken, which is very unlikely. 
2

一般來說,gcc and clang support lazy linking/binding of symbols, but not for entire libraries。這意味着所有的共享對象(即:.so文件)應該至少在應用程序啓動時出現。 的一個例外是,如果你修改了生成文件不針對這些庫鏈接,你通過dlopen()/dlsym()手動調用庫函數等

這些庫中各符號的結合可以被推遲,直到他們是需要的,或者您可以強制所有符號在啓動時解決,using -z lazy or -z now, respectively

奇怪的是,您的應用程序在沒有libmraa.so的情況下運行。這兩個最有可能的原因,你的應用程序在沒有圖書館的運行是:

  • 您的應用程序沒有使用在庫中定義的任何符號,所以鏈接器將忽略在構建時庫(嘗試ldd app_name看看如果您的圖書館出現在由ldd提供的圖書館列表中)。
  • 您的構建腳本中存在某些問題,並且您正在靜態鏈接庫的一個.a存檔。

編輯:針對應用程序如何知道如何找到庫,鏈接器(ld在這種情況下)將使用rpath查找,以決定哪些目錄在其搜索相應的庫使用。您可以通過從命令行執行類似LD_DEBUG=libs app_name的操作來了解其工作方式。您還可以通過LD_LIBRARY_PATH=/some/path app_name添加額外的路徑。

相關問題