¿Cómo se agregan las bibliotecas Boost en CMakeLists.txt?

125

Necesito agregar bibliotecas Boost en mi CMakeLists.txt. ¿Cómo lo haces o cómo lo agregas?

laksh
fuente
¿Qué hace esta línea rosbuild_add_boost_directories ()?
laksh
Consulte la documentación oficial aquí
adem

Respuestas:

171

Ponga esto en su CMakeLists.txtarchivo (cambie las opciones de OFF a ON si lo desea):

set(Boost_USE_STATIC_LIBS OFF) 
set(Boost_USE_MULTITHREADED ON)  
set(Boost_USE_STATIC_RUNTIME OFF) 
find_package(Boost 1.45.0 COMPONENTS *boost libraries here*) 

if(Boost_FOUND)
    include_directories(${Boost_INCLUDE_DIRS}) 
    add_executable(progname file1.cxx file2.cxx) 
    target_link_libraries(progname ${Boost_LIBRARIES})
endif()

Obviamente, debe colocar las bibliotecas que desee donde las coloco *boost libraries here*. Por ejemplo, si está utilizando la biblioteca filesystemy regex, escribiría:

find_package(Boost 1.45.0 COMPONENTS filesystem regex)
LainIwakura
fuente
2
Tenga en cuenta que no es necesario que especifique componentes para bibliotecas de solo encabezado, como lexical_cast. Por lo tanto, solo necesita el comando find_packagey include_directories.
miguel.martin
1
En Windows, también puede ser útil agregar esto a su archivo cmake: ADD_DEFINITIONS (-DBOOST_ALL_NO_LIB) de lo contrario, puede encontrarse con stackoverflow.com/questions/28887680/…
Stéphane
¿Es posible configurar BOOST_USE_STATIC_LIBS en ON y Boost_USE_STATIC_RUNTIME OFF? & viceversa.
calamar
5
¿Qué *boost libraries here*significa?
IgorGanapolsky
2
También puede usarlo FIND_PACKAGE(Boost REQUIRED COMPONENTS system)si no conoce la versión exacta de boost que debe usar
smac89
78

Puede usar find_package para buscar bibliotecas de impulso disponibles. Difiere la búsqueda de Boost a FindBoost.cmake , que se instala por defecto con CMake.

Al encontrar Boost, la find_package()llamada habrá llenado muchas variables (verifique la referencia de FindBoost.cmake ). Entre estos se encuentran BOOST_INCLUDE_DIRS, las variables Boost_LIBRARIES y Boost_XXX_LIBRARY, con XXX reemplazadas con bibliotecas específicas de Boost. Puede utilizarlos para especificar include_directories y target_link_libraries .

Por ejemplo, suponga que necesitaría boost :: program_options y boost :: regex, haría algo como:

find_package( Boost REQUIRED COMPONENTS program_options regex )
include_directories( ${Boost_INCLUDE_DIRS} )
add_executable( run main.cpp ) # Example application based on main.cpp

# Alternatively you could use ${Boost_LIBRARIES} here.
target_link_libraries( run ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_REGEX_LIBRARY} )

Algunos consejos generales:

  • Al buscar, FindBoost comprueba la variable de entorno $ ENV {BOOST_ROOT}. Puede establecer esta variable antes de llamar a find_package si es necesario.
  • Cuando tiene varias versiones de compilación de boost (multiproceso, estático, compartido, etc.) puede especificar la configuración deseada antes de llamar a find_package. Para ello, establezca algunas de las siguientes variables a On: Boost_USE_STATIC_LIBS, Boost_USE_MULTITHREADED,Boost_USE_STATIC_RUNTIME
  • Cuando busque Boost en Windows, tenga cuidado con el enlace automático. Lea la "NOTA para usuarios de Visual Studio" en la referencia .
    • Mi consejo es deshabilitar el enlace automático y usar el manejo de dependencias de cmake: add_definitions( -DBOOST_ALL_NO_LIB )
    • En algunos casos, es posible que deba especificar explícitamente que se utiliza un impulso dinámico: add_definitions( -DBOOST_ALL_DYN_LINK )
André
fuente
3
Gracias por los consejos generales. Me ayudaron mucho.
Tyler Long
¡Respuesta increíblemente útil! Me habría ahorrado mucho tiempo si hubiera encontrado esto hace dos años. Gran redacción.
Ela782
22

Adaptando la respuesta de @ LainIwakura para la sintaxis moderna de CMake con objetivos importados, esto sería:

set(Boost_USE_STATIC_LIBS OFF) 
set(Boost_USE_MULTITHREADED ON)  
set(Boost_USE_STATIC_RUNTIME OFF) 
find_package(Boost 1.45.0 COMPONENTS filesystem regex) 

if(Boost_FOUND)
    add_executable(progname file1.cxx file2.cxx) 
    target_link_libraries(progname Boost::filesystem Boost::regex)
endif()

Tenga en cuenta que ya no es necesario especificar los directorios de inclusión manualmente, ya que ya se realiza a través de los destinos importados Boost::filesystemy Boost::regex.
regexy filesystempuede ser reemplazado por cualquier biblioteca de impulso que necesite.

oLen
fuente
1
¿Cómo se vería esto si quisiera decir que se vincule contra todos los impulsores? Quiero decir, sin enumerar todas las bibliotecas que hay en boost.
Toby Brull
4
Si solo usa partes de boost de solo encabezado, 'Boost :: boost' será suficiente. Todas las bibliotecas de refuerzo compiladas deben especificarse explícitamente.
oLen
2
@oLen ¿Dónde puedo encontrar una lista de todos los objetivos de cmake Boost :: * importados? ¿Cómo sé a cuál tengo que vincularme?
Markus
8

Que esto pueda ser útil para algunas personas. Tuve un error travieso: referencia indefinida al símbolo '_ZN5boost6system15system_categoryEv' //usr/lib/x86_64-linux-gnu/libboost_system.so.1.58.0: error al agregar símbolos: DSO falta en la línea de comando Hubo algún problema con cmakeList.txt y de alguna manera me faltaba incluir explícitamente las bibliotecas de "sistema" y "sistema de archivos". Entonces, escribí estas líneas en CMakeLists.txt

Estas líneas se escriben al principio antes de crear el ejecutable del proyecto, ya que en esta etapa no necesitamos vincular la biblioteca boost a nuestro ejecutable del proyecto.

set(Boost_USE_STATIC_LIBS OFF) 
set(Boost_USE_MULTITHREADED ON)  
set(Boost_USE_STATIC_RUNTIME OFF) 
set(Boost_NO_SYSTEM_PATHS TRUE) 

if (Boost_NO_SYSTEM_PATHS)
  set(BOOST_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../3p/boost")
  set(BOOST_INCLUDE_DIRS "${BOOST_ROOT}/include")
  set(BOOST_LIBRARY_DIRS "${BOOST_ROOT}/lib")
endif (Boost_NO_SYSTEM_PATHS)


find_package(Boost COMPONENTS regex date_time system filesystem thread graph program_options) 

find_package(Boost REQUIRED regex date_time system filesystem thread graph program_options)
find_package(Boost COMPONENTS program_options REQUIRED)

Ahora, al final del archivo, escribí estas líneas considerando "KeyPointEvaluation" como el ejecutable de mi proyecto.

if(Boost_FOUND)
    include_directories(${BOOST_INCLUDE_DIRS})
    link_directories(${Boost_LIBRARY_DIRS})
    add_definitions(${Boost_DEFINITIONS})

    include_directories(${Boost_INCLUDE_DIRS})  
    target_link_libraries(KeyPointEvaluation ${Boost_LIBRARIES})
    target_link_libraries( KeyPointEvaluation ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${Boost_REGEX_LIBRARY} ${Boost_SYSTEM_LIBRARY})
endif()
Spandan
fuente
2

Estoy de acuerdo con las respuestas 1 y 2 . Sin embargo, prefiero especificar cada biblioteca por separado. Esto hace que las dependencias sean más claras en los grandes proyectos. Sin embargo, existe el peligro de escribir mal los nombres de las variables (que distinguen entre mayúsculas y minúsculas). En ese caso, no hay ningún error de cmake directo, sino algunos problemas con el vinculador de referencias indefinidas más adelante, que pueden tardar algún tiempo en resolverse. Por lo tanto, uso la siguiente función cmake:

function(VerifyVarDefined)
  foreach(lib ${ARGV}) 
    if(DEFINED ${lib})
    else(DEFINED ${lib})
      message(SEND_ERROR "Variable ${lib} is not defined")
    endif(DEFINED ${lib})
  endforeach()
endfunction(VerifyVarDefined)

Para el ejemplo mencionado anteriormente, esto se ve así:

VerifyVarDefined(Boost_PROGRAM_OPTIONS_LIBRARY Boost_REGEX_LIBRARY)
target_link_libraries( run ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_REGEX_LIBRARY} )

Si hubiera escrito "BOOST_PROGRAM_OPTIONS_LIBRARY", habría habido un error provocado por cmake y no mucho más tarde por el enlazador.

MarkusParker
fuente
2

Intente decir la documentación de Boost :

set(Boost_USE_STATIC_LIBS        ON)  # only find static libs
set(Boost_USE_DEBUG_LIBS         OFF) # ignore debug libs and 
set(Boost_USE_RELEASE_LIBS       ON)  # only find release libs 
set(Boost_USE_MULTITHREADED      ON)
set(Boost_USE_STATIC_RUNTIME    OFF) 
find_package(Boost 1.66.0 COMPONENTS date_time filesystem system ...)
if(Boost_FOUND)   
    include_directories(${Boost_INCLUDE_DIRS})
    add_executable(foo foo.cc)   
    target_link_libraries(foo ${Boost_LIBRARIES})
endif()

¡No olvide reemplazar foo por el nombre de su proyecto y los componentes por el suyo!

Nikolay Pakudin
fuente