2011-07-08 114 views
6

一直在尋找一個解決方案,但沒有喜悅。CMake鏈接提升。錯誤LNK2005

我有2個項目的CMake解決方案。一個是靜態庫,它鏈接到boost,另一個是可執行文件,鏈接到boost和我自己的靜態庫。 問題是:在Linux中,它使用gcc編譯得很好。但在VS2008中,我只能得到以下類型的program_options鏈接器錯誤。

libboost_program_options-vc90-mt-gd-1_46_1.lib(options_description.obj) : error LNK2005: "public: class boost::program_options::options_description_easy_init & __thiscall boost::program_options::options_description_easy_init::operator()(char const *,char const *)" ([email protected][email protected]@@[email protected]@Z) already defined in boost_program_options-vc90-mt-gd-1_46_1.lib(boost_program_options-vc90-mt-gd-1_46_1.dll) 

看起來它是鏈接到靜態庫和DLL的lib ...但爲什麼?

所以我有一個解決方案目錄與CMakeFile這樣的:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 
    PROJECT(BBlockTools) 

    SET(TopDir ${CMAKE_CURRENT_SOURCE_DIR}) 
    ADD_SUBDIRECTORY(Utilities) 
    ADD_SUBDIRECTORY(BBlockFixer) 

,然後將兩個項目目錄。公用事業是一個靜態庫,並通過以下CMakeFile創建:

PROJECT(Utilities) 

SET(Boost_USE_STATIC_LIBS ON) 
FIND_PACKAGE(Boost COMPONENTS system program_options REQUIRED) 
LINK_DIRECTORIES (${Boost_LIBRARY_DIRS}) 
INCLUDE_DIRECTORIES (${Boost_INCLUDE_DIRS}) 

SET(src_h Utilities.h) 
SET(src_cpp Utilities.cpp) 

ADD_LIBRARY(Utilities STATIC ${src_h} ${src_cpp}) 

TARGET_LINK_LIBRARIES(Utilities 
    ${Boost_SYSTEM_LIBRARY} 
    ${Boost_PROGRAM_OPTIONS_LIBRARY} 
    ${Boost_LIBRARIES} 
) 

並以此CMakeFile創建的第二個項目:

PROJECT(BBlockFixer) 

SET(Boost_USE_STATIC_LIBS ON) 
FIND_PACKAGE(Boost COMPONENTS system filesystem program_options REQUIRED) 
LINK_DIRECTORIES (${BBlockTools_BINARY_DIR}/Utilities/Debug ${Boost_LIBRARY_DIRS}) 
INCLUDE_DIRECTORIES (${TopDir} ${Boost_INCLUDE_DIRS}) 

SET(src_cpp fixerMain.cpp) 

ADD_EXECUTABLE(BBlockFixer ${src_cpp}) 

TARGET_LINK_LIBRARIES(BBlockFixer 
    Utilities 
    ${Boost_FILESYSTEM_LIBRARY} 
    ${Boost_PROGRAM_OPTIONS_LIBRARY} 
    ${Boost_SYSTEM_LIBRARY} 
    ${Boost_LIBRARIES} 
) 

我是新來的CMake,所以我可能會做一些非常糟糕,但我真的不知道發生了什麼事。我開始玩弄VS Project(Fixer),就像移除了修復問題的program_options的鏈接輸入(直到我再次運行cmake)。但我認爲這不是解決方案,因爲它看起來是連接到dll庫和靜態庫,出於某種原因... 我試圖從TARGET_LINK_LIBRARIES中從BBlockFixer中刪除$ {Boost_PROGRAM_OPTIONS_LIBRARY},而從FIND_PACKAGE中刪除了program_options幫幫我。

從我在CMake中理解的我的BBlockFixer繼承了從我的靜態庫中的program_options的鏈接,應該都很好。但是,boost_program_options-vc90-mt-gd-1_46_1.lib(boost_program_options-vc90-mt-1_46_1.dll)在哪裏鏈接到我的項目中?

任何幫助將不勝感激,因爲我變得絕望。它不可能真的那麼難...

PS。我設置的這個TopDir是我可以從Utilities中包含.h文件。但我確定必須有一個更乾淨的方法來做到這一點或?

回答

7

我的猜測是你仍然是自動鏈接:在MSVC上,boost使用一些編譯指示來自動指示編譯器鏈接到必要的庫,然後不需要手動指定所有鏈接目標到鏈接器。當然,這會伴隨着CMake的依賴解析以及手動指定target_link_libraries。

看看我的answer to a similar question,我提出了以下額外的定義來禁用自動鏈接:

add_definition(-DBOOST_ALL_NO_LIB) 

您可能需要添加動態鏈接並根據加速版本和組件時,以下幾點:

add_definitions(-DBOOST_ALL_DYN_LINK) 

還請注意,您指定的find_package()調用所需的升壓組件,然後在target_link_libraries()調用再次手動指定它們。根據你的需要,你也可以用

替換
target_link_libraries(${Boost_LIBRARIES}) 
+0

謝謝你的回答!一秒鐘前,我通過將動態庫移出boost庫文件夾解決了這個問題。 我意識到cmake(FindBoost.cmake?)只發現該文件夾中的動態庫,即使我告訴它鏈接到靜態庫。似乎它有優先選擇動態的,如果它首先找到它們。 在Linux顯然我只有靜態庫的提升,這就是爲什麼沒有發生衝突。 我說得對,這是你告訴我有關自動鏈接的效果嗎? 我會嘗試禁用自動鏈接:) 謝謝,Stefan – Stefan

+0

嗯我試着把所有3我的CMakeList文件中添加add_definitions(-DBOOST_ALL_NO_LIB),但沒有改變CMake喜歡動態庫的事實。我想我會堅持我的動態庫移出boost lib文件夾 – Stefan

+0

哦!我其實隱瞞了事實,我的解決方案中也有其他項目。在其中一些人中,我忘記了放置SET(Boost_USE_STATIC_LIBS ON)。出於某種原因,說服cmake選擇動態庫,而不是在我的所有項目的配置步驟靜態。大。現在我把它放在任何地方都沒問題。 – Stefan