2016-11-15 84 views
3

最近,我試圖構建一個應用程序,它使用一些庫,以共享對象文件的形式提供。我浪費了大量的時間來編譯CPP代碼,並沒有奏效。爲什麼傳遞參數的順序爲g ++重要

下面是命令,我以前試圖編譯代碼 -

g++ -I/opt/ros/indigo/include/ -I/usr/include/eigen3/ -L/opt/ros/indigo/lib/ -lorocos-kdl -lkdl_parser test.cpp -o test 

上面的命令總是顯示許多undefined references錯誤。爲了好奇,我改變了參數的順序。下面是命令,這是working-

g++ -L/opt/ros/indigo/lib -I/opt/ros/indigo/include -I/usr/include/eigen3 test.cpp -lorocos-kdl -lkdl_parser -o test 

我張貼的完整代碼和解決方案here

我的問題是爲什麼將參數傳遞給g ++的順序很重要?未來有沒有其他方法可以避免這些問題?

回答

5

通常參數的順序並不重要,但當然也有例外。例如,如果您提供多個-O標誌,它將是最後一個使用的標誌,對於其他標誌也是如此。

雖然圖書館有點不同,因爲對他們來說訂單很重要。如果目標文件或庫A取決於庫B,則A必須位於命令行上的B之前。這是因爲鏈接器掃描符號的方式:當您使用庫時,鏈接器將檢查是否有可以解析的符號。掃描結束後,庫將被丟棄,不會再次搜索。

這意味着,當你有-lorocos-kdl -lkdl_parser test.cpp鏈接器會掃描庫orocos-kdl和​​第一,注意有沒有對這些庫的依賴,不需要從庫中的符號,並繼續由源產生的目標文件文件。

當您將訂單更改爲test.cpp -lorocos-kdl -lkdl_parser時,鏈接器將能夠解析關於庫時引用的未定義符號test.cpp

+0

我感謝您的解釋。順便說一句,未來有沒有其他辦法可以避免這種複雜情況? –

+1

@RaviJoshi是的。始終將庫*最後*放在命令行上。 :) –

1

如果你不想關心順序,你可以(至少在某些版本的gcc中)在庫的周圍使用括號。

請參見:

Why does the order in which libraries are linked sometimes cause errors in GCC?

具體做法是:

如果靜態庫依賴於另一個庫,但其他圖書館 再次依賴於舊圖書館,有一個週期。你可以通過 - (和 - )封閉循環依賴庫來解決 這個問題,例如 爲 - (-la -lb-)(你可能需要轉義parens,比如 - (和 ))。鏈接器然後多次搜索那些封閉的lib以確保解決循環依賴關係。

相關問題