2011-07-08 8 views
6

estado buscando todo el día una solución, pero no hay alegría.CMake linking to boost. error LNK2005

Tengo una solución CMake con 2 proyectos. La una es una biblioteca estática que enlaza con boost, y la otra es un ejecutable que enlaza con boost y mi propia biblioteca estática. El problema es que: en Linux compila bien con gcc. Pero en VS2008 obtengo el siguiente tipo de errores de enlazador para program_options solamente.

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) 

parece que es vincular tanto a la lib estática y de la librería DLL ... pero ¿por qué?

así que tengo un directorio con una solución CMakeFile así:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 
    PROJECT(BBlockTools) 

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

Y entonces los dos directorios del proyecto. Utilities es una biblioteca estática y se crea siguiendo 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} 
) 

Y el segundo proyecto creado por este 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} 
) 

Soy nuevo en CMake por lo que podría estar haciendo algo muy malo, pero Realmente no puedo descubrir qué está pasando. Empecé a jugar con el Proyecto VS (Fixer) como eliminar la entrada de enlace a program_options que soluciona el problema (hasta que ejecute cmake nuevamente). Pero creo que esa no es la solución, ya que por lo que parece está vinculando tanto a la lib dll como a la lib estática por alguna razón ... Intenté eliminar $ {Boost_PROGRAM_OPTIONS_LIBRARY} de BBlockFixer de TARGET_LINK_LIBRARIES y program_options de FIND_PACKAGE pero no lo hice ayuda.

Por lo que entiendo en CMake, mi BBlockFixer hereda los enlaces a program_options de mi lib estática, que debería estar bien. ¿Pero dónde se vinculó este boost_program_options-vc90-mt-gd-1_46_1.lib (boost_program_options-vc90-mt-gd-1_46_1.dll) a mi proyecto?

Cualquier ayuda sería apreciada porque me estoy desesperando. Realmente no puede ser tan difícil ...

PS. este TopDir que configuré es para poder incluir el archivo .h de las Utilidades. Pero estoy seguro de que debe haber una forma más limpia de hacerlo o?

Respuesta

7

Supongo que todavía está autoenlace: en MSVC, boost utiliza algunos pragma para indicar automáticamente al compilador que establezca un enlace a las bibliotecas necesarias y no es necesario especificar todos los destinos de enlace manualmente en el enlazador . Por supuesto, esto muerde con la resolución de dependencia de CMake y especifica manualmente target_link_libraries.

Tome un vistazo a mi answer to a similar question, donde he sugerido la siguiente definición extra para desactivar el auto-linking:

add_definition(-DBOOST_ALL_NO_LIB) 

Es posible que tenga que añadir lo siguiente al vincular de forma dinámica y en función de la versión Boost y los componentes:

add_definitions(-DBOOST_ALL_DYN_LINK) 

Tenga en cuenta también que especifique los componentes de Boost que desee en la llamada find_package() y especifique de nuevo manualmente en sus target_link_libraries de llamadas().Dependiendo un poco de su necesidad, también puede reemplazar esto con

target_link_libraries(${Boost_LIBRARIES}) 
+0

Gracias por su respuesta! Hace un segundo resolví el problema moviendo las bibliotecas dinámicas de la carpeta boost libs. Lo que me di cuenta es que cmake (FindBoost.cmake?) Solo encontró las bibliotecas dinámicas en esa carpeta a pesar de que le dije que se vincule a las libs estáticas. Parece que tiene prioridad para seleccionar los dinámicos si los encuentra primero. En Linux, aparentemente, solo tenía las bibliotecas estáticas de impulso y es por eso que no se produjeron enfrentamientos. ¿Tengo razón en que este es el efecto de lo que me acabas de decir sobre el autoenlace? Voy a tratar de deshabilitar autolinking ahora :) gracias, Stefan – Stefan

+0

Hm Intenté poner add_definitions (-DBOOST_ALL_NO_LIB) en los 3 archivos de mi CMakeList pero no cambié el hecho de que CMake prefiera las bibliotecas dinámicas. Supongo que me atendré a mover las libs dinámicas de la carpeta de boost boost – Stefan

+0

Oho !!! De hecho, te oculté que también tenía otros proyectos en mi solución. En algunos de ellos había olvidado poner SET (Boost_USE_STATIC_LIBS ON). Por algún motivo, convencí a cmake para que seleccionara las bibliotecas dinámicas en lugar del paso estático en la configuración para todos mis proyectos. Estupendo. Ahora que lo puse en todos lados, está bien. – Stefan