Wie füge ich Boost-Bibliotheken in CMakeLists.txt hinzu?

123

Ich muss Boost-Bibliotheken zu meiner CMakeLists.txt hinzufügen. Wie machst du das oder wie fügst du es hinzu?

Laksh
quelle
Was macht diese Zeile rosbuild_add_boost_directories ()?
Laksh
Siehe offizielle Dokumentation hier
adem

Antworten:

171

Fügen Sie dies in Ihre CMakeLists.txtDatei ein (ändern Sie alle Optionen von AUS auf EIN, wenn Sie möchten):

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

Natürlich müssen Sie die gewünschten Bibliotheken dort platzieren, wo ich sie platziert habe *boost libraries here*. Wenn Sie beispielsweise die Bibliothek filesystemund regexverwenden, schreiben Sie:

find_package(Boost 1.45.0 COMPONENTS filesystem regex)
LainIwakura
quelle
2
Beachten Sie, dass Sie keine Komponenten nur für Header-Bibliotheken angeben müssen, z lexical_cast. Sie brauchen also nur den Befehl find_packageund include_directories.
miguel.martin
1
Unter Windows kann es auch hilfreich sein, dies zu Ihrer cmake-Datei hinzuzufügen: ADD_DEFINITIONS (-DBOOST_ALL_NO_LIB), andernfalls kann es sein, dass Sie
Stéphane
Ist es möglich, BOOST_USE_STATIC_LIBS auf ON und Boost_USE_STATIC_RUNTIME OFF zu setzen? & umgekehrt.
Tintenfisch
5
Was heißt *boost libraries here*das
IgorGanapolsky
2
Sie können auch verwenden, FIND_PACKAGE(Boost REQUIRED COMPONENTS system)wenn Sie die genaue Version des zu verwendenden
Boosts
78

Mit find_package können Sie nach verfügbaren Boost-Bibliotheken suchen. Die Suche nach Boost wird auf FindBoost.cmake verschoben , das standardmäßig mit CMake installiert ist.

Nach dem Auffinden von Boost hat der find_package()Aufruf viele Variablen gefüllt (überprüfen Sie die Referenz für FindBoost.cmake ). Dazu gehören die BOOST_INCLUDE_DIRSVariablen Boost_LIBRARIES und Boost_XXX_LIBRARY, wobei XXX durch bestimmte Boost-Bibliotheken ersetzt wird. Mit diesen können Sie include_directories und target_link_libraries angeben .

Angenommen, Sie benötigen boost :: program_options und boost :: regex. Sie würden Folgendes tun:

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

Einige allgemeine Tipps:

  • Bei der Suche überprüft FindBoost die Umgebungsvariable $ ENV {BOOST_ROOT}. Sie können diese Variable bei Bedarf festlegen, bevor Sie find_package aufrufen.
  • Wenn Sie mehrere Build-Versionen von Boost haben (Multithreading, statisch, gemeinsam genutzt usw.), können Sie die gewünschte Konfiguration angeben, bevor Sie find_package aufrufen. Tun Sie dies , indem Sie einige der folgenden Variablen einstellen On: Boost_USE_STATIC_LIBS, Boost_USE_MULTITHREADED,Boost_USE_STATIC_RUNTIME
  • Achten Sie bei der Suche nach Boost unter Windows auf die automatische Verknüpfung. Lesen Sie den "HINWEIS für Visual Studio-Benutzer" in der Referenz .
    • Mein Rat ist, die automatische Verknüpfung zu deaktivieren und die Abhängigkeitsbehandlung von cmake zu verwenden: add_definitions( -DBOOST_ALL_NO_LIB )
    • In einigen Fällen müssen Sie möglicherweise explizit angeben, dass ein dynamischer Boost verwendet wird: add_definitions( -DBOOST_ALL_DYN_LINK )
André
quelle
3
Vielen Dank für die allgemeinen Tipps. Sie haben mir sehr geholfen.
Tyler Long
Unglaublich hilfreiche Antwort! Hätte mir viel Zeit gespart, wenn ich das vor zwei Jahren gefunden hätte. Tolles Schreiben.
Ela782
22

Wenn Sie die Antwort von @ LainIwakura für die moderne CMake-Syntax mit importierten Zielen anpassen, lautet dies:

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

Beachten Sie, dass es nicht mehr erforderlich ist, die Include-Verzeichnisse manuell anzugeben, da dies bereits über die importierten Ziele Boost::filesystemund erledigt wird Boost::regex.
regexund filesystemkann durch alle benötigten Boost-Bibliotheken ersetzt werden.

oLen
quelle
1
Wie würde das aussehen, wenn Sie sagen wollten, gegen alle Boost zu verlinken? Ich meine, ohne alle Bibliotheken aufzulisten, gibt es Boost.
Toby Brull
4
Wenn Sie nur Header-Teile von Boost verwenden, ist 'Boost :: Boost' ausreichend. Alle kompilierten Boost-Bibliotheken müssen explizit angegeben werden.
oLen
2
@oLen Wo finde ich eine Liste aller importierten cmake Boost :: * -Ziele? Woher weiß ich, zu welchem ​​Link ich verlinken muss?
Markus
8

Möge dies für einige Leute hilfreich sein. Ich hatte einen ungezogenen Fehler: undefinierter Verweis auf das Symbol '_ZN5boost6system15system_categoryEv' //usr/lib/x86_64-linux-gnu/libboost_system.so.1.58.0: Fehler beim Hinzufügen von Symbolen: DSO fehlt in der Befehlszeile Es gab ein Problem mit cmakeList.txt und irgendwie fehlte es mir, die Bibliotheken "system" und "filesystem" explizit einzuschließen. Also habe ich diese Zeilen in CMakeLists.txt geschrieben

Diese Zeilen werden zu Beginn vor dem Erstellen der ausführbaren Datei des Projekts geschrieben, da wir zu diesem Zeitpunkt keine Boost-Bibliothek mit unserer ausführbaren Projektdatei verknüpfen müssen.

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)

Jetzt am Ende der Datei habe ich diese Zeilen geschrieben, indem ich "KeyPointEvaluation" als ausführbare Projektdatei betrachtet habe.

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
quelle
2

Ich stimme den Antworten 1 und 2 zu . Ich bevorzuge es jedoch, jede Bibliothek separat anzugeben. Dies macht die Abhängigkeiten bei großen Projekten klarer. Es besteht jedoch die Gefahr, dass die (zwischen Groß- und Kleinschreibung beachteten) Variablennamen falsch eingegeben werden. In diesem Fall gibt es keinen direkten cmake-Fehler, aber später einige undefinierte Referenz-Linker-Probleme, deren Behebung einige Zeit in Anspruch nehmen kann. Deshalb benutze ich folgende cmake-Funktion:

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)

Für das oben erwähnte Beispiel sieht dies so aus:

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

Wenn ich "BOOST_PROGRAM_OPTIONS_LIBRARY" geschrieben hätte, wäre ein Fehler von cmake und nicht viel später vom Linker ausgelöst worden.

MarkusParker
quelle
2

Versuchen Sie, Boost-Dokumentation zu sagen :

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

Vergessen Sie nicht, foo durch Ihren Projektnamen und Komponenten durch Ihren zu ersetzen!

Nikolay Pakudin
quelle