Comment ajouter des bibliothèques Boost dans CMakeLists.txt?

125

J'ai besoin d'ajouter des bibliothèques Boost dans mon CMakeLists.txt. Comment faites-vous cela ou comment l'ajouter?

laksh
la source
que fait cette ligne rosbuild_add_boost_directories ()?
laksh le
Voir la documentation officielle ici
adem

Réponses:

171

Mettez ceci dans votre CMakeLists.txtfichier (changez les options de OFF à ON si vous le souhaitez):

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()

De toute évidence, vous devez placer les bibliothèques que vous voulez là où je les place *boost libraries here*. Par exemple, si vous utilisez la bibliothèque filesystemand regex, vous écrirez:

find_package(Boost 1.45.0 COMPONENTS filesystem regex)
LainIwakura
la source
2
Notez que vous n'avez pas besoin de spécifier des composants pour les bibliothèques d'en-tête uniquement, telles que lexical_cast. Ainsi, vous n'avez besoin que de la commande find_packageet include_directories.
miguel.martin
1
Sous Windows, cela peut également aider à ajouter ceci à votre fichier cmake: ADD_DEFINITIONS (-DBOOST_ALL_NO_LIB) sinon vous risquez de rencontrer stackoverflow.com/questions/28887680/…
Stéphane
est-il possible de régler BOOST_USE_STATIC_LIBS sur ON et Boost_USE_STATIC_RUNTIME OFF? & vice versa.
calmar
5
Que veut *boost libraries here*dire?
IgorGanapolsky
2
Vous pouvez également utiliser FIND_PACKAGE(Boost REQUIRED COMPONENTS system)si vous ne connaissez pas la version exacte de boost à utiliser
smac89
78

Vous pouvez utiliser find_package pour rechercher les bibliothèques boost disponibles. Il reporte la recherche de Boost à FindBoost.cmake , qui est installé par défaut avec CMake.

Lors de la recherche de Boost, l' find_package()appel aura rempli de nombreuses variables (vérifiez la référence pour FindBoost.cmake ). Parmi ceux-ci BOOST_INCLUDE_DIRS, citons les variabels Boost_LIBRARIES et Boost_XXX_LIBRARY, avec XXX remplacés par des bibliothèques Boost spécifiques. Vous pouvez les utiliser pour spécifier include_directories et target_link_libraries .

Par exemple, supposons que vous ayez besoin de boost :: program_options et boost :: regex, vous feriez quelque chose comme:

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} )

Quelques conseils généraux:

  • Lors de la recherche, FindBoost vérifie la variable d'environnement $ ENV {BOOST_ROOT}. Vous pouvez définir cette variable avant d'appeler find_package si nécessaire.
  • Lorsque vous avez plusieurs versions de build de boost (multi-thread, statique, partagée, etc.), vous pouvez spécifier la configuration souhaitée avant d'appeler find_package. Pour ce faire, définissez certaines des variables suivantes sur On:Boost_USE_STATIC_LIBS , Boost_USE_MULTITHREADED,Boost_USE_STATIC_RUNTIME
  • Lorsque vous recherchez Boost sur Windows, faites attention à la liaison automatique. Lisez la «REMARQUE pour les utilisateurs de Visual Studio» dans le référence .
    • Mon conseil est de désactiver la liaison automatique et d'utiliser la gestion des dépendances de cmake: add_definitions( -DBOOST_ALL_NO_LIB )
    • Dans certains cas, vous devrez peut-être spécifier explicitement qu'un Boost dynamique est utilisé: add_definitions( -DBOOST_ALL_DYN_LINK )
André
la source
3
Merci pour les conseils généraux. Ils m'ont beaucoup aidé.
Tyler Long
Réponse incroyablement utile! Cela m'aurait fait gagner beaucoup de temps si j'avais trouvé ça il y a deux ans. Excellente rédaction.
Ela782
22

En adaptant la réponse de @ LainIwakura pour la syntaxe CMake moderne avec des cibles importées, ce serait:

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()

Notez qu'il n'est plus nécessaire de spécifier manuellement les répertoires d'inclusion, car cela est déjà pris en charge via les cibles importées Boost::filesystemet Boost::regex.
regexet filesystempeut être remplacé par toutes les bibliothèques boost dont vous avez besoin.

oLen
la source
1
À quoi cela ressemblerait-il si vous vouliez dire de lier à tous les boost? Je veux dire sans énumérer toutes les bibliothèques, il y a en boost.
Toby Brull
4
Si vous n'utilisez que des parties d'en-tête de boost, 'Boost :: boost' sera suffisant. Toutes les bibliothèques boost compilées doivent être spécifiées explicitement.
oLen
2
@oLen Où puis-je trouver une liste de toutes les cibles cmake Boost :: * importées? Comment savoir vers lequel je dois me connecter?
Markus
8

Que cela puisse être utile pour certaines personnes. J'ai eu une erreur vilaine: référence non définie au symbole '_ZN5boost6system15system_categoryEv' //usr/lib/x86_64-linux-gnu/libboost_system.so.1.58.0: erreur d'ajout de symboles: DSO manquant dans la ligne de commande Il y avait un problème de cmakeList.txt et d'une manière ou d'une autre, il me manquait d'inclure explicitement les bibliothèques «système» et «système de fichiers». Donc, j'ai écrit ces lignes dans CMakeLists.txt

Ces lignes sont écrites au début avant de créer l'exécutable du projet, car à ce stade, nous n'avons pas besoin de lier la bibliothèque boost à l'exécutable de notre projet.

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)

Maintenant, à la fin du fichier, j'ai écrit ces lignes en considérant "KeyPointEvaluation" comme exécutable de mon projet.

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
la source
2

Je suis d'accord avec les réponses 1 et 2 . Cependant, je préfère spécifier chaque bibliothèque séparément. Cela rend les dépendances plus claires dans les grands projets. Pourtant, il y a le risque de mal saisir les noms de variables (sensibles à la casse). Dans ce cas, il n'y a pas d'erreur cmake directe, mais certains problèmes liés à l'éditeur de liens de références non définies plus tard, ce qui peut prendre un certain temps à résoudre. Par conséquent, j'utilise la fonction cmake suivante:

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)

Pour l'exemple mentionné ci-dessus, cela ressemble à:

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

Si j'avais écrit "BOOST_PROGRAM_OPTIONS_LIBRARY", il y aurait eu une erreur déclenchée par cmake et pas beaucoup plus tard déclenchée par l'éditeur de liens.

MarkusParker
la source
2

Essayez de dire la documentation 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()

N'oubliez pas de remplacer foo par le nom de votre projet et les composants par le vôtre!

Nikolay Pakudin
la source