คุณจะเพิ่มไลบรารี Boost ใน CMakeLists.txt ได้อย่างไร?


125

ฉันต้องการเพิ่มไลบรารี Boost ใน CMakeLists.txt ของฉัน คุณทำได้อย่างไรหรือจะเพิ่มอย่างไร


rosbuild_add_boost_directories () บรรทัดนี้ทำอะไร
laksh

ดูเอกสารอย่างเป็นทางการที่นี่
Adem

คำตอบ:


171

ใส่สิ่งนี้ในCMakeLists.txtไฟล์ของคุณ(เปลี่ยนตัวเลือกใด ๆ จากปิดเป็นเปิดหากคุณต้องการ):

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

*boost libraries here*เห็นได้ชัดว่าคุณจะต้องใส่ห้องสมุดที่คุณต้องการที่ผมใส่ ตัวอย่างเช่นหากคุณกำลังใช้filesystemและregexไลบรารีคุณจะเขียน:

find_package(Boost 1.45.0 COMPONENTS filesystem regex)

2
โปรดทราบว่าคุณไม่จำเป็นต้องระบุส่วนประกอบสำหรับไลบรารีส่วนหัวเท่านั้นเช่นlexical_cast. ดังนั้นคุณต้องใช้find_packageและinclude_directoriesคำสั่งเท่านั้น
miguel.martin

1
ใน Windows คุณสามารถเพิ่มสิ่งนี้ลงในไฟล์ cmake ของคุณได้เช่นกัน: ADD_DEFINITIONS (-DBOOST_ALL_NO_LIB) มิฉะนั้นคุณอาจเข้าสู่stackoverflow.com/questions/28887680/…
Stéphane

เป็นไปได้ไหมที่จะตั้ง BOOST_USE_STATIC_LIBS เป็นเปิดและ Boost_USE_STATIC_RUNTIME OFF & รองกลอน
ปลาหมึก

5
อะไร*boost libraries here*หมายถึง?
IgorGanapolsky

2
นอกจากนี้คุณยังสามารถใช้FIND_PACKAGE(Boost REQUIRED COMPONENTS system)หากคุณไม่ทราบเวอร์ชันที่แน่นอนของการเพิ่มที่จะใช้
smac89

78

คุณสามารถใช้find_packageเพื่อค้นหาไลบรารีเพิ่มที่มีอยู่ มันเลื่อนการค้นหา Boost ไปที่FindBoost.cmakeซึ่งเป็นค่าเริ่มต้นที่ติดตั้งกับ CMake

เมื่อพบ Boost การfind_package()เรียกจะมีตัวแปรมากมาย (ตรวจสอบข้อมูลอ้างอิงสำหรับFindBoost.cmake ) ในจำนวนนี้คือBOOST_INCLUDE_DIRSตัวแปร Boost_LIBRARIES และ Boost_XXX_LIBRARY โดย XXX จะถูกแทนที่ด้วยไลบรารี Boost เฉพาะ คุณสามารถใช้สิ่งเหล่านี้เพื่อระบุinclude_directoriesและtarget_link_libraries target_link_libraries

ตัวอย่างเช่นสมมติว่าคุณต้องการ boost :: program_options และ boost :: regex คุณจะต้องทำสิ่งต่อไปนี้

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

เคล็ดลับทั่วไปบางประการ:

  • เมื่อค้นหา FindBoost จะตรวจสอบตัวแปรสภาพแวดล้อม $ ENV {BOOST_ROOT} คุณสามารถตั้งค่าตัวแปรนี้ก่อนเรียก find_package ได้หากจำเป็น
  • เมื่อคุณมีการเพิ่มเวอร์ชันบิวด์หลายเวอร์ชัน (มัลติเธรดแบบคงที่แชร์ ฯลฯ ) คุณสามารถระบุการกำหนดค่าที่คุณต้องการก่อนที่จะเรียกใช้ find_package ทำได้โดยตั้งค่าตัวแปรต่อไปนี้เป็นOn: Boost_USE_STATIC_LIBS,Boost_USE_MULTITHREADED ,Boost_USE_STATIC_RUNTIME
  • เมื่อค้นหา Boost บน Windows ให้ระมัดระวังด้วยการเชื่อมโยงอัตโนมัติ อ่าน "หมายเหตุสำหรับผู้ใช้ Visual Studio" ในข้อมูลอ้างอิงการอ้างอิง
    • คำแนะนำของฉันคือปิดใช้งานการเชื่อมโยงอัตโนมัติและใช้การจัดการการพึ่งพาของ cmake: add_definitions( -DBOOST_ALL_NO_LIB )
    • ในบางกรณีคุณอาจต้องระบุอย่างชัดเจนว่าใช้บูสต์แบบไดนามิก: add_definitions( -DBOOST_ALL_DYN_LINK )

3
ขอบคุณสำหรับเคล็ดลับทั่วไป พวกเขาช่วยฉันมาก
Tyler Long

คำตอบที่เป็นประโยชน์อย่างเหลือเชื่อ! จะช่วยฉันได้มากถ้าฉันพบสิ่งนี้เมื่อสองปีก่อน การเขียนที่ยอดเยี่ยม
Ela782

22

คำตอบของ Adapting @ LainIwakura สำหรับไวยากรณ์ CMake สมัยใหม่พร้อมเป้าหมายที่นำเข้าสิ่งนี้จะเป็น:

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

โปรดทราบว่าไม่จำเป็นอีกต่อไปในการระบุไดเร็กทอรีรวมด้วยตนเองเนื่องจากได้รับการดูแลผ่านเป้าหมายที่นำเข้าBoost::filesystemและBoost::regex.
regexและfilesystemสามารถแทนที่ได้ด้วยไลบรารีเพิ่มประสิทธิภาพที่คุณต้องการ


1
สิ่งนี้จะเป็นอย่างไรหากคุณต้องการบอกว่าเชื่อมโยงกับการเพิ่มทั้งหมด? ฉันหมายถึงไม่มีการแสดงรายการห้องสมุดทั้งหมดที่มีอยู่ในการเพิ่ม
Toby Brull

4
หากคุณใช้การเพิ่มเฉพาะส่วนหัวเท่านั้น 'Boost :: boost' ก็เพียงพอแล้ว ต้องระบุไลบรารีบูสต์ที่คอมไพล์ทั้งหมดไว้อย่างชัดเจน
oLen

2
@oLen ฉันจะหารายการ cmake Boost :: * ที่นำเข้าทั้งหมดได้ที่ไหน? ฉันจะรู้ได้อย่างไรว่าฉันต้องเชื่อมโยงไปถึง?
Markus

8

อาจเป็นประโยชน์สำหรับบางคน ฉันมีข้อผิดพลาดที่ซุกซน: การอ้างอิงที่ไม่ได้กำหนดสัญลักษณ์ '_ZN5boost6system15system_categoryEv' //usr/lib/x86_64-linux-gnu/libboost_system.so.1.58.0: ข้อผิดพลาดในการเพิ่มสัญลักษณ์: DSO หายไปจากบรรทัดคำสั่ง cmakeList.txt มีปัญหาบางอย่าง และอย่างใดฉันก็พลาดที่จะรวมไลบรารี "system" และ "filesystem" ไว้อย่างชัดเจน ดังนั้นฉันจึงเขียนบรรทัดเหล่านี้ใน CMakeLists.txt

บรรทัดเหล่านี้เขียนไว้ที่จุดเริ่มต้นก่อนที่จะสร้างไฟล์ปฏิบัติการของโปรเจ็กต์เนื่องจากในขั้นตอนนี้เราไม่จำเป็นต้องเชื่อมโยงไลบรารีบูสต์กับโปรเจ็กต์ของเรา

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)

ในตอนท้ายของไฟล์ฉันเขียนบรรทัดเหล่านี้โดยพิจารณาว่า "KeyPointEvaluation" เป็นโปรเจ็กต์ที่สามารถเรียกใช้งานได้

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

2

ฉันเห็นด้วยกับคำตอบ1และ2 อย่างไรก็ตามฉันต้องการระบุแต่ละไลบรารีแยกกัน สิ่งนี้ทำให้การอ้างอิงชัดเจนขึ้นในโครงการขนาดใหญ่ อย่างไรก็ตามยังมีอันตรายจากการพิมพ์ชื่อตัวแปร (ตามตัวพิมพ์เล็กและใหญ่) ผิดพลาด ในกรณีนี้ไม่มีข้อผิดพลาด cmake โดยตรง แต่มีปัญหาตัวเชื่อมโยงการอ้างอิงที่ไม่ได้กำหนดบางอย่างในภายหลังซึ่งอาจใช้เวลาสักครู่ในการแก้ไข ดังนั้นฉันจึงใช้ฟังก์ชัน 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)

สำหรับตัวอย่างที่กล่าวมาข้างต้นจะมีลักษณะดังนี้:

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

ถ้าฉันเขียน "BOOST_PROGRAM_OPTIONS_LIBRARY" จะมีข้อผิดพลาดเกิดขึ้นโดย cmake และไม่มากนักในภายหลังโดยตัวเชื่อมโยง


2

ลองพูดเอกสาร 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()

อย่าลืมแทนที่ foo เป็นชื่อโครงการและส่วนประกอบของคุณ!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.