Bagaimana Anda menambahkan pustaka Boost di CMakeLists.txt?

125

Saya perlu menambahkan pustaka Boost ke CMakeLists.txt saya. Bagaimana Anda melakukannya atau bagaimana Anda menambahkannya?

laksh
sumber
apa yang dilakukan baris rosbuild_add_boost_directories () ini?
laksh
Lihat dokumentasi resmi di sini
adem

Jawaban:

171

Taruh ini di CMakeLists.txtfile Anda (ubah opsi apa pun dari NONAKTIF ke AKTIF jika Anda mau):

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

Jelas Anda perlu meletakkan perpustakaan yang Anda inginkan di tempat saya meletakkan *boost libraries here*. Misalnya, jika Anda menggunakan perpustakaan filesystemand, regexAnda akan menulis:

find_package(Boost 1.45.0 COMPONENTS filesystem regex)
LainIwakura
sumber
2
Perhatikan bahwa Anda tidak perlu menentukan komponen untuk pustaka hanya header, seperti lexical_cast. Jadi Anda hanya perlu perintah find_packagedan include_directories.
miguel. Mulai
1
Pada Windows, menambahkan ini ke file cmake Anda juga dapat membantu: ADD_DEFINITIONS (-DBOOST_ALL_NO_LIB) jika tidak, Anda mungkin akan mengalami stackoverflow.com/questions/28887680/…
Stéphane
apakah mungkin untuk menyetel BOOST_USE_STATIC_LIBS ke ON dan Boost_USE_STATIC_RUNTIME OFF? & sebaliknya.
cumi
5
Apa *boost libraries here*maksudnya
IgorGanapolsky
2
Anda juga dapat menggunakan FIND_PACKAGE(Boost REQUIRED COMPONENTS system)jika Anda tidak tahu versi pasti dari peningkatan yang akan digunakan
smac89
78

Anda dapat menggunakan find_package untuk mencari perpustakaan pendorong yang tersedia. Ini menunda mencari Boost ke FindBoost.cmake , yang secara default diinstal dengan CMake.

Setelah menemukan Boost, find_package()panggilan tersebut akan mengisi banyak variabel (periksa referensi untuk FindBoost.cmake ). Diantaranya adalah BOOST_INCLUDE_DIRS, variabel Boost_LIBRARY dan Boost_XXX_LIBRARY, dengan XXX diganti dengan library Boost tertentu. Anda dapat menggunakan ini untuk menentukan include_directories dan target_link_libraries .

Misalnya, Anda memerlukan boost :: program_options dan boost :: regex, Anda akan melakukan sesuatu seperti:

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

Beberapa tip umum:

  • Saat menelusuri, FindBoost memeriksa variabel lingkungan $ ENV {BOOST_ROOT}. Anda dapat menyetel variabel ini sebelum memanggil find_package jika perlu.
  • Ketika Anda memiliki beberapa versi build dari boost (multi-threaded, static, shared, dll.), Anda dapat menentukan konfigurasi yang Anda inginkan sebelum memanggil find_package. Lakukan ini dengan menetapkan beberapa variabel berikut untuk On: Boost_USE_STATIC_LIBS, Boost_USE_MULTITHREADED,Boost_USE_STATIC_RUNTIME
  • Saat mencari Boost di Windows, berhati-hatilah dengan penautan otomatis. Baca "CATATAN untuk Pengguna Visual Studio" di referensi .
    • Saran saya adalah menonaktifkan penautan otomatis dan menggunakan penanganan ketergantungan cmake: add_definitions( -DBOOST_ALL_NO_LIB )
    • Dalam beberapa kasus, Anda mungkin perlu secara eksplisit menentukan bahwa Boost dinamis digunakan: add_definitions( -DBOOST_ALL_DYN_LINK )
André
sumber
3
Terima kasih atas tip umumnya. Mereka banyak membantu saya.
Tyler Long
Jawaban yang sangat membantu! Akan menghemat banyak waktu jika saya menemukan ini dua tahun lalu. Tulisan yang bagus.
Ela782
22

Mengadaptasi jawaban @ LainIwakura untuk sintaks CMake modern dengan target yang diimpor, ini akan menjadi:

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

Perhatikan bahwa tidak perlu lagi menetapkan direktori include secara manual, karena sudah ditangani melalui target yang diimpor Boost::filesystemdan Boost::regex.
regexdan filesystemdapat diganti dengan pustaka peningkatan apa pun yang Anda butuhkan.

oLen
sumber
1
Bagaimana tampilan ini jika Anda ingin mengatakan untuk menautkan ke semua peningkatan? Maksud saya tanpa mencantumkan semua perpustakaan yang ada dalam peningkatan.
Toby Brull
4
Jika Anda hanya menggunakan bagian penguat hanya header, 'Boost :: boost' sudah cukup. Semua pustaka peningkatan yang dikompilasi harus ditentukan secara eksplisit.
oLen
2
@oLen Di mana saya dapat menemukan daftar semua cmake Boost yang diimpor :: * target? Bagaimana saya tahu ke mana saya harus menautkan?
Markus
8

Semoga ini bisa bermanfaat bagi sebagian orang. Saya mengalami kesalahan nakal: referensi tidak ditentukan ke simbol '_ZN5boost6system15system_categoryEv' //usr/lib/x86_64-linux-gnu/libboost_system.so.1.58.0: kesalahan menambahkan simbol: DSO hilang dari baris perintah Ada beberapa masalah cmakeList.txt dan entah bagaimana saya kehilangan untuk secara eksplisit menyertakan pustaka "sistem" dan "sistem berkas". Jadi, saya menulis baris ini di CMakeLists.txt

Baris-baris ini ditulis di awal sebelum membuat proyek yang dapat dieksekusi, karena pada tahap ini kita tidak perlu menghubungkan perpustakaan pendorong ke proyek yang dapat dieksekusi.

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)

Sekarang di akhir file, saya menulis baris ini dengan mempertimbangkan "KeyPointEvaluation" sebagai proyek saya yang dapat dieksekusi.

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

Saya setuju dengan jawaban 1 dan 2 . Namun, saya lebih suka menentukan setiap perpustakaan secara terpisah. Ini membuat ketergantungan lebih jelas dalam proyek-proyek besar. Namun, ada bahaya salah ketik nama variabel (case-sensitive). Dalam hal ini tidak ada kesalahan cmake langsung tetapi beberapa masalah linker referensi yang tidak ditentukan nanti, yang mungkin memerlukan beberapa waktu untuk diselesaikan. Oleh karena itu saya menggunakan fungsi cmake berikut:

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)

Untuk contoh yang disebutkan di atas, ini terlihat seperti:

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

Jika saya telah menulis "BOOST_PROGRAM_OPTIONS_LIBRARY" akan ada kesalahan yang dipicu oleh cmake dan tidak lama kemudian dipicu oleh linker.

MarkusParker
sumber
2

Coba katakan dokumentasi 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()

Jangan lupa untuk mengganti foo ke nama dan komponen proyek Anda dengan milik Anda!

Nikolay Pakudin
sumber