Jak dodać biblioteki Boost w CMakeLists.txt?

125

Muszę dodać biblioteki Boost do mojego CMakeLists.txt. Jak to robisz lub jak to dodajesz?

laksh
źródło
co robi ta linia rosbuild_add_boost_directories ()?
laksh
Zobacz oficjalną dokumentację tutaj
adem

Odpowiedzi:

171

Umieść to w swoim CMakeLists.txtpliku (zmień dowolne opcje z WYŁ. Na WŁ., Jeśli chcesz):

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

Oczywiście musisz umieścić wybrane biblioteki tam, gdzie ja *boost libraries here*. Na przykład, jeśli używasz biblioteki filesystemi regex, napisz:

find_package(Boost 1.45.0 COMPONENTS filesystem regex)
LainIwakura
źródło
2
Zwróć uwagę, że nie musisz określać komponentów dla bibliotek zawierających tylko nagłówki, takich jak lexical_cast. Dlatego potrzebujesz tylko polecenia find_packagei include_directories.
miguel.martin
1
W systemie Windows pomocne może być również dodanie tego do pliku cmake: ADD_DEFINITIONS (-DBOOST_ALL_NO_LIB) w przeciwnym razie możesz natknąć się na stackoverflow.com/questions/28887680/…
Stéphane
czy można ustawić BOOST_USE_STATIC_LIBS na ON i Boost_USE_STATIC_RUNTIME OFF? & vice versa.
kalmary
5
Co to *boost libraries here*znaczy?
Igor Ganapolsky
2
Możesz także użyć, FIND_PACKAGE(Boost REQUIRED COMPONENTS system)jeśli nie znasz dokładnej wersji wzmocnienia do użycia
smac89
78

Możesz użyć find_package, aby wyszukać dostępne biblioteki boost. Odracza wyszukiwanie Boost to FindBoost.cmake , który jest domyślnie instalowany z CMake.

Po znalezieniu Boost, find_package()wywołanie wypełni wiele zmiennych (sprawdź odniesienie do FindBoost.cmake ). Wśród nich są BOOST_INCLUDE_DIRSzmienne Boost_LIBRARIES i Boost_XXX_LIBRARY, przy czym XXX zastąpiono określonymi bibliotekami Boost. Możesz ich użyć do określenia include_directories i target_link_libraries .

Na przykład, załóżmy, że potrzebujesz boost :: program_options i boost :: regex, zrobiłbyś coś takiego:

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

Kilka ogólnych wskazówek:

  • Podczas wyszukiwania FindBoost sprawdza zmienną środowiskową $ ENV {BOOST_ROOT}. W razie potrzeby możesz ustawić tę zmienną przed wywołaniem find_package.
  • Jeśli masz wiele wersji kompilacji boost (wielowątkowych, statycznych, współdzielonych itp.), Możesz określić żądaną konfigurację przed wywołaniem find_package. Czy to poprzez ustawienie niektóre z następujących zmiennych On: Boost_USE_STATIC_LIBS, Boost_USE_MULTITHREADED,Boost_USE_STATIC_RUNTIME
  • Szukając Boost w systemie Windows, uważaj na automatyczne łączenie. Przeczytaj „UWAGA dla użytkowników programu Visual Studio” w odwołaniu .
    • Radzę wyłączyć automatyczne łączenie i skorzystać z obsługi zależności cmake: add_definitions( -DBOOST_ALL_NO_LIB )
    • W niektórych przypadkach może być konieczne wyraźne określenie, że używane jest dynamiczne wzmocnienie: add_definitions( -DBOOST_ALL_DYN_LINK )
André
źródło
3
Dziękuję za ogólne wskazówki. Bardzo mi pomogli.
Tyler Long
Niezwykle pomocna odpowiedź! Zaoszczędziłoby mi dużo czasu, gdybym znalazł to dwa lata temu. Świetny opis.
Ela782
22

Dostosowując odpowiedź @ LainIwakura do nowoczesnej składni CMake z zaimportowanymi celami, wyglądałoby to tak:

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

Zauważ, że nie jest już konieczne ręczne określanie katalogów dołączania, ponieważ jest to już obsługiwane przez zaimportowane cele Boost::filesystemi Boost::regex.
regexi filesystemmożna je zastąpić dowolnymi potrzebnymi bibliotekami boost.

oLen
źródło
1
Jak by to wyglądało, gdybyś chciał powiedzieć link przeciwko wszystkim wzmocnieniom? To znaczy bez wymieniania wszystkich bibliotek, które są w fazie przyspieszenia.
Toby Brull
4
Jeśli używasz tylko części wzmocnienia tylko z nagłówka, wystarczy „Boost :: boost”. Wszystkie skompilowane biblioteki boost muszą być jawnie określone.
oLen
2
@oLen Gdzie znajdę listę wszystkich zaimportowanych celów cmake Boost :: *? Skąd mam wiedzieć, do którego mam link?
Markus,
8

Może to mogłoby pomóc niektórym ludziom. Wystąpił niegrzeczny błąd: niezdefiniowane odniesienie do symbolu '_ZN5boost6system15system_categoryEv' //usr/lib/x86_64-linux-gnu/libboost_system.so.1.58.0: błąd dodawanie symboli: brak DSO w linii poleceń Wystąpił problem z cmakeList.txt i jakoś brakowało mi jawnego dołączenia bibliotek „system” i „system plików”. Tak więc napisałem te wiersze w CMakeLists.txt

Te wiersze są zapisywane na początku przed utworzeniem pliku wykonywalnego projektu, ponieważ na tym etapie nie musimy łączyć biblioteki boost z plikiem wykonywalnym projektu.

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)

Teraz na końcu pliku napisałem te wiersze, biorąc pod uwagę „KeyPointEvaluation” jako plik wykonywalny mojego projektu.

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
źródło
2

Zgadzam się z odpowiedziami 1 i 2 . Jednak wolę osobno określić każdą bibliotekę. To sprawia, że ​​zależności są wyraźniejsze w dużych projektach. Istnieje jednak niebezpieczeństwo błędnego wpisania nazw zmiennych (z uwzględnieniem wielkości liter). W takim przypadku nie ma bezpośredniego błędu cmake, ale później pojawiają się pewne problemy z nieokreślonymi odwołaniami, których rozwiązanie może zająć trochę czasu. Dlatego używam następującej funkcji 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)

W powyższym przykładzie wygląda to następująco:

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

Gdybym napisał „BOOST_PROGRAM_OPTIONS_LIBRARY”, wystąpiłby błąd wywołany przez cmake, a niewiele później wywołany przez linker.

MarkusParker
źródło
2

Spróbuj jak powiedzieć Dokumentacja doładowania :

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

Nie zapomnij zamienić foo na nazwę swojego projektu, a komponenty na swoje!

Nikolay Pakudin
źródło