2014-10-08 104 views
2

嗯,這真的讓我現在有幾個小時:)C++可執行文件鏈接問題

我有一個C++項目,它使用cmake。我有鏈接問題,我無法解決。下面是隻有一個最終可執行文件的鏈接命令:

/usr/bin/c++ -std=c++0x CMakeFiles/calib_sfm.dir/calib_sfm.cpp.o \ 
    -o calib_sfm -rdynamic libviso.so -lboost_log -lboost_log_setup \ 
    -lboost_system -lboost_filesystem -lboost_thread -lpthread \ 
    /home/kreimer/opencv3.0/lib/libopencv_viz.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_videostab.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_video.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_ts.a \ 
    /home/kreimer/opencv3.0/lib/libopencv_superres.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_stitching.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_softcascade.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_shape.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_photo.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_optim.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_objdetect.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_nonfree.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_ml.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_legacy.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_imgproc.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_highgui.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_flann.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_features2d.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_cudawarping.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_cudastereo.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_cudaoptflow.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_cudaimgproc.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_cudafilters.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_cudafeatures2d.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_cudacodec.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_cudabgsegm.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_cudaarithm.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_cuda.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_core.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_contrib.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_calib3d.so.3.0.0 \ 
    -ldl -lm -lpthread -lrt \ 
    /home/kreimer/opencv3.0/share/OpenCV/3rdparty/lib/libippicv.a \ 
    /home/kreimer/opencv3.0/lib/libopencv_cudawarping.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_legacy.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_cudaimgproc.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_cudafilters.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_video.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_objdetect.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_nonfree.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_ml.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_cudaarithm.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_calib3d.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_features2d.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_highgui.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_imgproc.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_flann.so.3.0.0 \ 
    /home/kreimer/opencv3.0/lib/libopencv_core.so.3.0.0 \ 
    -Wl,-rpath,/home/kreimer/[email protected]/Technion/projects/robil/viso/debug/src:/home/kreimer/opencv3.0/lib 

產生這樣的:

libviso.so: undefined reference to `cv::DescriptorExtractor::compute(cv::_InputArray const&, std::vector<cv::KeyPoint, std::allocator<cv::KeyPoint> >&, cv::_OutputArray const&) const' 
libviso.so: undefined reference to `cv::calcHist(cv::Mat const*, int, int const*, cv::_InputArray const&, cv::_OutputArray const&, int, int const*, float const**, bool, bool)' 
libviso.so: undefined reference to `cv::DescriptorExtractor::~DescriptorExtractor()' 
libviso.so: undefined reference to `cv::namedWindow(cv::String const&, int)' 
libviso.so: undefined reference to `cv::flann::SearchParams::SearchParams(int, float, bool)' 
libviso.so: undefined reference to `cv::computeCorrespondEpilines(cv::_InputArray const&, int, cv::_InputArray const&, cv::_OutputArray const&)' 
libviso.so: undefined reference to `cv::DescriptorExtractor::~DescriptorExtractor()' 
libviso.so: undefined reference to `cv::destroyWindow(cv::String const&)' 
libviso.so: undefined reference to `cv::imwrite(cv::String const&, cv::_InputArray const&, std::vector<int, std::allocator<int> > const&)' 
libviso.so: undefined reference to `cv::imread(cv::String const&, int)' 
libviso.so: undefined reference to `cv::cornerHarris(cv::_InputArray const&, cv::_OutputArray const&, int, int, double, int)' 
libviso.so: undefined reference to `cv::FeatureDetector::detect(cv::_InputArray const&, std::vector<cv::KeyPoint, std::allocator<cv::KeyPoint> >&, cv::_InputArray const&) const' 
libviso.so: undefined reference to `cv::waitKey(int)' 
libviso.so: undefined reference to `cv::findEssentialMat(cv::_InputArray const&, cv::_InputArray const&, double, cv::Point_<double>, int, double, double, cv::_OutputArray const&)' 
libviso.so: undefined reference to `cv::cvtColor(cv::_InputArray const&, cv::_OutputArray const&, int, int)' 
libviso.so: undefined reference to `cv::FeatureDetector::~FeatureDetector()' 
libviso.so: undefined reference to `typeinfo for cv::FeatureDetector' 
libviso.so: undefined reference to `cv::Sobel(cv::_InputArray const&, cv::_OutputArray const&, int, int, int, int, double, double, int)' 
libviso.so: undefined reference to `cv::FeatureDetector::empty() const' 
libviso.so: undefined reference to `cv::undistortPoints(cv::_InputArray const&, cv::_OutputArray const&, cv::_InputArray const&, cv::_InputArray const&, cv::_InputArray const&, cv::_InputArray const&)' 
libviso.so: undefined reference to `cv::DescriptorExtractor::empty() const' 
libviso.so: undefined reference to `cv::FeatureDetector::~FeatureDetector()' 
libviso.so: undefined reference to `cv::FeatureDetector::~FeatureDetector()' 
libviso.so: undefined reference to `typeinfo for cv::DescriptorExtractor' 
libviso.so: undefined reference to `cv::imshow(cv::String const&, cv::_InputArray const&)' 
libviso.so: undefined reference to `cv::flann::IndexParams::~IndexParams()' 
libviso.so: undefined reference to `cv::DescriptorExtractor::~DescriptorExtractor()' 

鑑於缺少的標誌之一是CV :: namedWindow我這樣做:

nm -gC /home/kreimer/opencv3.0/lib/libopencv_highgui.so.3.0.0 | grep namedWindow 
000000000002df80 T cv::namedWindow(cv::String const&, int) 

所以符號出現在提供的共享庫中。當我閱讀圖書館的順序並不重要的動態構建,那麼可能是什麼問題?順便說一句,如果我將libviso的版本更改爲靜態而不是動態,如上所示,此可執行文件鏈接就好了。

回答

1

用Unix風格的鏈接器,鏈接命令行的順序總是很重要。所有目標文件,.a文件,.so文件和-l選項都嚴格按照從左到右的順序進行處理。每個項目只能爲其左側的項目解析未定義的符號。您可能誤解了文檔,這實際上是在討論鏈接器人員拒絕修復的相關錯誤(一直回到Solaris 2.0,iirc),其中共享庫是無條件包含的,而靜態庫不是。

但是,這不是唯一的問題,因爲libviso.so是命令行中的第一件事情之一。我懷疑你有什麼是錯誤消息,其中未定義的符號正在被libviso.so使用,並且在命令行上還有其他更多的內容,但是它們被歸於而僅歸於libviso.so

有一個簡單的大鐵錘的解決辦法:安排,讓您的命令行如下:

/usr/bin/c++ -std=c++0x CMakeFiles/calib_sfm.dir/calib_sfm.cpp.o -o calib_sfm \ 
    -rdynamic -Wl,--as-needed -Wl,--group \ 
    $(ALL_THE_LIBRARIES_HERE) \ 
    -Wl,--end-group \ 
    -Wl,-rpath,$(SAME_RPATH_AS_BEFORE) 

-Wl,--group ... -Wl,--end-group建設強制鏈接器掃描一遍又之間的一切之前,反覆它或者已經解決了所有的未定義的符號,或者可以確定地證明它不能完成。添加-Wl,--as-needed修復了我之前提到的錯誤,所以你不會吮吸你實際上沒有使用的庫。

+0

Fabio鏈接引用:「雖然對目標文件或動態庫的鏈接順序沒有要求。」我想我也在gcc文檔中看到過這個。我會嘗試你的建議,並讓你知道它是否解決了這個問題。謝謝你的努力。 – 2014-10-18 17:57:15

+0

危險,因爲它是說,萊特是錯誤的,實際上,萊布是錯誤的。他說無論是動態庫還是目標文件都被無條件地包含在最終的可執行文件中(這是我提到的錯誤,由' - needed'糾正),但是這並不意味着鏈接器將會在鏈接行中稍後從這些庫或其他庫中搜索未定義的符號。 – zwol 2014-10-18 18:58:23

+0

NP,會檢查出來。謝謝 – 2014-10-18 19:09:26

1

我以前遇到過幾個類似的問題;我不記得具體的例子,但我很清楚地記得圖書館的順序很重要;我結束了洗牌,直到我的項目最終適當建成。

+0

命令行上庫的順序絕對重要。 – zwol 2014-10-17 18:00:08

+1

構建靜態庫/可執行文件時非常重要,但不能動態鏈接。至少那是什麼建議 – 2014-10-17 18:02:52

+1

@AlexKreimer它總是很重要。任何其他說法都是錯誤的。 – zwol 2014-10-17 18:03:43