CMake ссылки для повышения.ошибка LNK2005 - PullRequest
7 голосов
/ 08 июля 2011

Весь день искал решение, но не радости.

У меня есть решение CMake с 2 проектами. Одна представляет собой статическую библиотеку, которая ссылается на 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 *)" (??Roptions_description_easy_init@program_options@boost@@QAEAAV012@PBD0@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 ... но почему?

Итак, у меня есть каталог решений с 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 и статической библиотекой ... Я пытался удалить $ {Boost_PROGRAM_OPTIONS_LIBRARY} из BBlockFixer из TARGET_LINK_LIBRARIES и program_options из FIND_PACKAGE, но это не помогло.

Из того, что я понимаю в CMake, мой BBlockFixer наследует ссылки на program_options из моей статической библиотеки, которая должна быть в порядке. Но где этот boost_program_options-vc90-mt-gd-1_46_1.lib (boost_program_options-vc90-mt-gd-1_46_1.dll) был связан с моим проектом?

Любая помощь будет признательна, потому что я впадаю в отчаяние. Это не может быть так сложно ...

PS. этот TopDir, который я установил, так, чтобы я мог включить .h файл из утилит. Но я уверен, что должен быть более чистый способ сделать это?

1 Ответ

7 голосов
/ 08 июля 2011

Я предполагаю, что вы все еще используете автоматическую компоновку: в MSVC boost использует некоторые прагмы для автоматического указания компилятору ссылки на необходимые библиотеки, и тогда нет необходимости указывать все цели компоновки вручную для компоновщика.Конечно, это кусается с разрешением зависимости CMake, и вы вручную указываете target_link_libraries.

Посмотрите на мой ответ на аналогичный вопрос , где я предложил следующее дополнительное определение для отключения авто-linking:

add_definition( -DBOOST_ALL_NO_LIB )

При динамическом связывании и в зависимости от версии Boost и компонентов может потребоваться добавить следующее:

add_definitions( -DBOOST_ALL_DYN_LINK )

Также обратите внимание, что вы указываете компоненты Boost, которые выхотите в вызове find_package (), а затем снова укажите их вручную в вызове target_link_libraries ().В зависимости от ваших потребностей, вы также можете заменить это на

target_link_libraries( ${Boost_LIBRARIES} )
...