2014-12-02 37 views
5

問題:我正在CMake中構建一個外部項目。該項目有一個Makefile,最終生成一個共享對象。我想鏈接並在我的超級項目中安裝此對象,就好像它是項目中的一個庫。問題在於ExternalProject庫通過相對路徑被鏈接到我的應用程序和庫中,而不是絕對路徑,這會導致從CMake放置它的任何目錄運行時出現問題。CMake:從ExternalProject鏈接共享的C++對象生成相對路徑的二進制文件,而不是絕對的

我有created a sample SSCCE example project來演示我的整體設置。如果需要,請隨時仔細閱讀並編譯(git clone https://github.com/calebwherry/cmake-SO-question-main --recursive && cd cmake-SO-question-main && mkdir build && cd build && cmake .. && make && cd src/app/testApp && ldd testApp)。

每當我對可執行文件和庫運行ldd,我得到的輸出是這樣的:

linux-vdso.so.1 => (0x00007fff8b5a2000) 
    libTestLib.so => /home/jwherry3/repos/cmake-superprj-main-test/build/src/lib/TestLib/libTestLib.so (0x00007f592da57000) 
    ../../lib/libExtLib.so (0x00007f592d855000) 
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f592d539000) 
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f592d2b7000) 
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f592d0a0000) 
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f592cd14000) 
    /lib64/ld-linux-x86-64.so.2 (0x00007f592dc5a000) 

我已經試過各種事情處理RPATHS但不能得到EXTLIB鏈接的權利。該項目本地的lib(libTestLib.so)鏈接就好了。

我也嘗試設置LD_LIBRARY_PATH覆蓋我運行應用程序時的相對路徑,但即使當我這樣做時,它仍然找不到該庫。我想因爲它是相對的,它不遵循正常的鏈接順序?結果是二進制文件不會運行,除非我在它所在的目錄中。

我覺得我正在做一些非常愚蠢的事情時,與ExternalProject創建依賴關係,這是我的問題,但我已經打了我的頭3天,並沒有拿出任何東西。

系統設置:Debian Wheezy 64位,CMake 3.0.2,g ++ - 4.9.2。

+0

還沒有命中,是吧? Whelp,我暫時通過讓外部項目建立靜態庫和鏈接來解決問題,而不是共享庫。不是一個長期的解決方案,但至少可以讓它正確運行。我已經更新了回購爲其他人提供這個選項,但你必須在ext/CMakeLists.txt中手動更改爲開啓它。 – Caleb 2014-12-04 20:02:09

+0

對不起,沒有注意到答案 – Slava 2016-02-02 12:12:19

回答

1

花了一段時間,但終於在CMake Users listserv的幫助下,特別是@ brad-king得到了答案。

主要問題是我沒有在我的外部項目中正確編譯我的共享對象。布拉德的回答我的問題:

感謝您的完整/簡單的例子。問題是 由外部項目建立的libExtLib.so文件不是 有鏈接器設置的DT_SONAME。當鏈接器被賦予一個 路徑到沒有soname的共享庫文件時,路徑 被複制到消費者的DT_NEEDED字段中,因爲它的 沒有soname用於此目的。

解決辦法有兩個:

  1. 確保DT_SONAME得到由外部編譯系統設置正確。

  2. 告訴CMake的導入的庫文件沒有SONAME:

    set_property(TARGET EXTLIB PROPERTY IMPORTED_NO_SONAME 1)

    然後CMake的將通過-lExtLib和鏈接器鏈接也不會 店的路徑該文件在DT_NEEDED中,但只有文件名。

其中之一應解決問題。 1號更清潔。

既然我能控制的外部庫中的make文件,我選擇了清洗劑中的解決方案通過編譯共享對象,像這樣:

$(SHARED_TARGET): $(OBJECTS) $(CXX) $(CXXFLAGS) $(OBJECTS) -o [email protected] $(LDFLAGS) -Wl,-soname,[email protected]

我已經修改了我原來的例子,使它簡單得多:https://github.com/calebwherry/cmake-SO-question-main。我會留下來作爲參考,以供任何人在以後的日子裏遇到這個帖子。

P.S.

還有另一個修復是次優的。如果我沒有完成上述任何操作,我可以只給target_link_library提供我鏈接的庫的完整路徑,而不使用導入的庫目標。我已經在回購的CMake文件中注意到了這一點,並對其進行了評論。這不是一個好的解決方案,但是解決問題的方式是另一種。

相關問題