Como você adiciona bibliotecas Boost em CMakeLists.txt?

125

Preciso adicionar bibliotecas Boost em meu CMakeLists.txt. Como você faz ou como você adiciona?

Laksh
fonte
o que esta linha rosbuild_add_boost_directories () faz?
laksh
Veja a documentação oficial aqui
adem

Respostas:

171

Coloque isso em seu CMakeLists.txtarquivo (altere as opções de DESATIVADO para ATIVADO, se desejar):

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

Obviamente, você precisa colocar as bibliotecas que deseja onde eu coloco *boost libraries here*. Por exemplo, se você estiver usando a biblioteca filesysteme, regexescreveria:

find_package(Boost 1.45.0 COMPONENTS filesystem regex)
LainIwakura
fonte
2
Observe que você não precisa especificar componentes para bibliotecas apenas de cabeçalho, como lexical_cast. Portanto, você só precisa do comando find_packagee include_directories.
miguel.martin
1
No Windows, também pode ajudar adicionar isso ao seu arquivo cmake: ADD_DEFINITIONS (-DBOOST_ALL_NO_LIB), caso contrário, você pode executar stackoverflow.com/questions/28887680/…
Stéphane
é possível definir BOOST_USE_STATIC_LIBS para ON e Boost_USE_STATIC_RUNTIME OFF? & vice-verso.
lula de
5
O que isso *boost libraries here*significa?
IgorGanapolsky
2
Você também pode usar FIND_PACKAGE(Boost REQUIRED COMPONENTS system)se não souber a versão exata do impulso a ser usado
smac89
78

Você pode usar find_package para pesquisar por bibliotecas boost disponíveis. Ele adia a busca por Boost para FindBoost.cmake , que é instalado por padrão com o CMake.

Ao encontrar Boost, a find_package()chamada terá preenchido muitas variáveis ​​(verifique a referência para FindBoost.cmake ). Entre eles estão as BOOST_INCLUDE_DIRSvariáveis ​​Boost_LIBRARIES e Boost_XXX_LIBRARY, com XXX substituído por bibliotecas Boost específicas. Você pode usá-los para especificar include_directories e target_link_libraries .

Por exemplo, suponha que você precise boost :: program_options e boost :: regex, você faria algo como:

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

Algumas dicas gerais:

  • Ao pesquisar, FindBoost verifica a variável de ambiente $ ENV {BOOST_ROOT}. Você pode definir essa variável antes de chamar find_package, se necessário.
  • Quando você tem várias versões de build do boost (multi-threaded, estático, compartilhado, etc.), você pode especificar a configuração desejada antes de chamar find_package. Fazer isso definindo algumas das seguintes variáveis para On: Boost_USE_STATIC_LIBS, Boost_USE_MULTITHREADED,Boost_USE_STATIC_RUNTIME
  • Ao pesquisar Boost no Windows, tome cuidado com a vinculação automática. Leia a "NOTA para usuários do Visual Studio" na referência .
    • Meu conselho é desabilitar o link automático e usar o tratamento de dependência do cmake: add_definitions( -DBOOST_ALL_NO_LIB )
    • Em alguns casos, você pode precisar especificar explicitamente que um Boost dinâmico é usado: add_definitions( -DBOOST_ALL_DYN_LINK )
André
fonte
3
Obrigado pelas dicas gerais. Eles me ajudaram muito.
Tyler Long de
Resposta incrivelmente útil! Teria me poupado muito tempo se tivesse encontrado isso há dois anos. Ótimo artigo.
Ela782 de
22

Adaptando a resposta de @LainIwakura para a sintaxe moderna do CMake com destinos importados, isso seria:

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

Observe que não é mais necessário especificar os diretórios de inclusão manualmente, uma vez que isso já é feito através dos destinos importados Boost::filesysteme Boost::regex.
regexe filesystempode ser substituído por qualquer biblioteca de impulso que você precisar.

oLen
fonte
1
Como isso ficaria se você quisesse dizer para vincular a todo impulso? Quer dizer, sem listar todas as bibliotecas que existem no boost.
Toby Brull
4
Se você usar apenas partes do boost, apenas 'Boost :: boost' será suficiente. Todas as bibliotecas de reforço compiladas devem ser especificadas explicitamente.
oLen
2
@oLen Onde encontro uma lista de todos os destinos cmake Boost :: * importados? Como posso saber para qual devo vincular?
Markus
8

Isso pode ser útil para algumas pessoas. Eu tive um erro impertinente: referência indefinida ao símbolo '_ZN5boost6system15system_categoryEv' //usr/lib/x86_64-linux-gnu/libboost_system.so.1.58.0: erro ao adicionar símbolos: DSO ausente na linha de comando Houve algum problema de cmakeList.txt e de alguma forma estava faltando incluir explicitamente as bibliotecas "sistema" e "sistema de arquivos". Então, eu escrevi essas linhas em CMakeLists.txt

Essas linhas são escritas no início, antes de criar o executável do projeto, pois neste estágio não precisamos vincular a biblioteca boost ao executável do nosso projeto.

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)

Agora, no final do arquivo, escrevi essas linhas considerando "KeyPointEvaluation" como o executável do meu projeto.

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

Eu concordo com as respostas 1 e 2 . No entanto, prefiro especificar cada biblioteca separadamente. Isso torna as dependências mais claras em grandes projetos. No entanto, existe o perigo de erros de digitação dos nomes das variáveis ​​(diferenciando maiúsculas de minúsculas). Nesse caso, não há erro cmake direto, mas alguns problemas do linker de referências indefinidas posteriormente, que podem levar algum tempo para serem resolvidos. Portanto, uso a seguinte função 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)

Para o exemplo mencionado acima, isso se parece com:

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

Se eu tivesse escrito "BOOST_PROGRAM_OPTIONS_LIBRARY", teria ocorrido um erro acionado por cmake e não muito depois acionado pelo vinculador.

MarkusParker
fonte
2

Tente dizer a documentação do 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ão se esqueça de substituir foo pelo nome do projeto e componentes pelo seu!

Nikolay Pakudin
fonte