2013-04-12 28 views
1

我的軟件編譯的Linux精細幾個月前停止編譯在我的新的Ubuntu:鏈接失敗,CMake的,DSO-鏈路變化

Linking CXX executable myApp 
/usr/bin/ld: ../libMyLib/libMyLib.a(MyFile.cpp.o): undefined reference to symbol '_ZN2cv6resizeERKNS_11_InputArrayERKNS_12_OutputArrayENS_5Size_IiEEddi' 
/usr/bin/ld: note: '_ZN2cv6resizeERKNS_11_InputArrayERKNS_12_OutputArrayENS_5Size_IiEEddi' is defined in DSO /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../lib/libopencv_imgproc.so so try adding it to the linker command line 
/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../lib/libopencv_imgproc.so: could not read symbols: Invalid operation 
collect2: error: ld returned 1 exit status 
make[2]: *** [myApp/myApp] Error 1 
make[1]: *** [myApp/CMakeFiles/myApp.dir/all] Error 2 
make: *** [all] Error 2 

我想這是關係到https://fedoraproject.org/wiki/UnderstandingDSOLinkChange

我的項目(所有的cmake)包含幾個庫和一個應用程序,庫和應用程序都依賴於opencv和/或boost(每個都有一些不同的)。我自己的庫被構建爲.a文件,ocv/boost作爲共享庫被引入,然後應用程序的鏈接失敗,出現上述錯誤。

我也嘗試建立我自己的庫作爲SHARED,但這導致更多的錯誤。我的圖書館的CMakeLists樣子

FIND_PACKAGE(Boost REQUIRED) 
FIND_PACKAGE(OpenCV REQUIRED core) 
...stuff... 
include_directories(${OpenCV_INCLUDE_DIRS}) 
include_directories(${Boost_INCLUDE_DIRS}) 
add_library(${SUBPROJECT_NAME} ${SOURCE} ${HEADERS}) 

應用CMakeLists看起來像

FIND_PACKAGE(OpenCV REQUIRED core imgproc highgui) 
include_directories(${OpenCV_INCLUDE_DIRS}) 
TARGET_LINK_LIBRARIES(${SUBPROJECT_NAME} ${OpenCV_LIBS} MyLib) 

這是正確的,我一直以爲這是本DSO東西,我只是不能做到這一點,但現在的方式它繼續工作。

如果相關,我嘗試使用CMake 2.8.7和2.8.10以及g ++ 4.7.2和4.8,都會產生相同的錯誤。

+0

我不記得圖書館的順序是否在CMake中很重要(即它是否以正確的順序向GCC提供),但它肯定對GCC本身很重要。也許你應該把'MyLib'放在$ {OpenCV_LIBS}之前? –

+0

哦,你得開玩笑我......當MyLib依賴於$ {OpenCV_LIBS}時,它必須在cmdline之前進行嗎?對我來說,這是非常不直觀的,我的想法是,首先你必須鏈接到$ {OpenCV_LIBS}(然後它被「定義」),然後鏈接到取決於$ {OpenCV_LIBS}的MyLib,現在可以找到它... 但實際上你是對的,自從我使用gcc以來,我得到了這個錯誤...如果你將它作爲答案來制定,我會接受... :-)謝謝,這麼愚蠢...... – Ela782

回答

2

GCC是很合理的,你在鏈接階段指定庫的順序。例如,如果libA.a取決於libB.a和可執行App取決於兩個,那麼你就必須以下列方式來調用鏈接:

gcc main.o object1.o ... object2.o -lA -lB -o App 

注:注重的事實是,儘管A取決於B,仍然A之前B。作爲結論,最獨立的神器應該是最後一個鏈接。從某種意義上說,這確實是違反直覺的,但試着以與在C++中應用const限定符相同的方式對待它。 :)

+0

在上面鏈接行爲變化之前,似乎是這樣的,在我的情況中(除了不正確之外)並不重要,但現在鏈接器變得更加迂腐,並且確實很重要。 非常感謝:-) – Ela782

+0

@ Ela782:但可能有更好的解決方案。像CMake這樣的構建系統都是關於從編譯器和平臺上抽象出來的。因此,通常不鼓勵修改'CMakeLists'來適應特定的編譯器。最好將'target_link_libraries(MyLib $ {OpenCV_LIBS})'添加到'MyLib'對應的'CMakeLists'中。這樣你不僅可以明確地定義你的工件的依賴關係,這對於可讀性非常好,而且你也可以使用CMake的依賴關係跟蹤系統。換句話說,讓CMake通過巧妙地幫助它來處理鏈接順序。 –

+0

好的,但我一直認爲你所提出的是不好的做法,好的做法是隻讓應用程序做最後的連接。這是不是真的或曾經?我在一年前告訴了我自己,我在幾個主頁上閱讀了這個建議(也就是我想的)。 – Ela782

1

OpenCV_LIBS是否包含-lopencv_imgproc? 如果沒有,嘗試添加手動-lopencv_imgproc鏈接命令行(運行make V = 1) 是否行得通其添加到TARGET_LINK

+0

是當然它包含它,下面是連接失敗應用程序的完整命令: '/ usr/bin/C++ -std = C++ 11 -O3 -DNDEBUG CMakeFiles/myApp.dir/myApp.cpp.o - Ø對myApp -L/home/user中/ MCR/V81 /斌/ glnxa64 -rdynamic -lboost_program_options-MT -lmx -lmat -lopencv_gpu -lopencv_contrib -lopencv_legacy -lopencv_objdetect -lopencv_calib3d -lopencv_features2d -lopencv_video -lopencv_highgui -lopencv_ml -lopencv_imgproc -lopencv_flann -lopencv_core ../MyLib/MyLib。a -Wl,-rpath,/ home/user/MCR/v81/bin/glnxa64' – Ela782

+0

謝謝我有同樣的問題,包括修復它! –