DEV Community

Ronaldd Pinho
Ronaldd Pinho

Posted on • Edited on

2

Carregando dependências em projetos C++ usando o CMake

Com as linguagens de programação modernas é muito comum possuir-se um meio de obter e gerenciar dependências, seja usando o pip, cargo, npm ou yarn, esse processo se torna extremamente simples. Contudo, quando se trata de linguagens como C e C++ isso é um pouco diferente, não existe um único meio padronizado de obter bibliotecas externas. Pensando nisso, pensei em escrever esse post mostrando como automatizo a obtenção de bibliotecas de repositórios Git remotos usando o CMake.

Existem soluções criadas pela comunidade como o conan e o
vcpkg mas elas carregam outra dependência na máquina e
requerem que a biblioteca que você quer esteja indexada por eles.

O módulo FetchContent

O CMake é sistema de build que atomatiza a geração de Makefiles que definem o processo de compilação de um projeto de código-fonte. Ele fornece vários módulos que ajudam na configuração de várias formas. Um desses módulos é o FetchContent, que ajuda a obter conteúdo externo em tempo de configuração, ou seja, quando o CMake está gerando o Makefile.

É bastante simples de usá-lo, no exemplo abaixo adicionamos o GoogleTest ao nosso projeto:

include(FetchContent)
FetchContent_Declare(GoogleTest
    GIT_REPOSITORY https://github.com/google/googletest.git
    GIT_TAG        master
)
FetchContent_MakeAvailable(GoogleTest)
Enter fullscreen mode Exit fullscreen mode

Depois disso, temos o projeto do GoogleTest bem como suas bibliotecas acessíveis em tempo de configuração, então podemos vincular qualquer executável/biblioteca com o GoogleTest, por exemplo:

add_executable(mytests "test/main.cpp" "test/awesome_test.cpp")
target_link_libraries(mytests gtest_main)
Enter fullscreen mode Exit fullscreen mode

Criando uma função CMake

Para automatizar esse processo, eu costumo criar uma função simples que concentra o código que usa o FetchContent, isso torna o script CMake mais legível e fácil de adicionar novas dependências.

function(GET_DEPENDENCY D_NAME D_URL D_TAG)
    message(CHECK_START "Configuring ${D_NAME}")
    FetchContent_Declare(${D_NAME}
        GIT_REPOSITORY ${D_URL}
        GIT_TAG        ${D_TAG}
    )
    FetchContent_MakeAvailable(${D_NAME})
endfunction()
Enter fullscreen mode Exit fullscreen mode

Assim consigo usar a funcção get_dependecy passando o nome, a URL e a versão (ou tag) da biblioteca.

get_dependency(GoogleTest "https://github.com/google/googletest.git" master)
Enter fullscreen mode Exit fullscreen mode

Para adicionar mais dependências...

get_dependency(spdlog "https://github.com/gabime/spdlog" v1.8.5)
get_dependency(CLI11 "https://github.com/CLIUtils/CLI11" v1.9.1)
get_dependency(GoogleTest "https://github.com/google/googletest" master)
Enter fullscreen mode Exit fullscreen mode

Quando uso essa configuração, se torna muito mais fácil adicionar e remover dependências de bibliotecas externas, principalmente por usar bibliotecas abertas com código-fonte no Github. Isso também ajuda em projeto em equipes permitindo que não seja necessário um conjunto de passos complexos para configurar o ambiente de desenvolvimento nas diferentes máquinas dos desenvolvedores. Também traz um benefício para o uso CI (Continous Integration).

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more