CMake + Conan + VS Code
Avalie esse Tutorial
Olá, programadores de C e C++! Hoje, gostaria de falar sobre um tópico muito sensível para todos nós. Uma coisa que causou mágoa e confusão na comunidade. Algo que afetou nossa produtividade e, às vezes, até nossa saúde mental. Não estou me referindo a erros de compilador, mas a criar projetos complexos e usar dependências de terceiros neles.
Tradicionalmente, usamos Makefiles para construir nossos projetos C e C++ e dependemos de ter nossas dependências de terceiros instaladas em nossos sistemas de desenvolvimento ou suas fontes incluídas em nosso projeto de uma forma ou de outra. As ferramentas evoluíram muito nas últimas duas décadas, mas nem todo mundo as está usando completamente ou até mesmo para criar seus projetos.
A menos que você viva sob uma rocha, provavelmente já viu o que seus colegas desenvolvedores fazem quando usam outras linguagens de programação de back-end poderosas. A Golang tem suporte integrado para módulos de terceiros. Você apenas menciona a URL do repositório de terceiros e ele trata do resto. Ciúmes? A ferramenta de carga do Rust se encarrega de construir seu projeto e gerenciar todas as suas dependências, mesmo quando o projeto é distribuído em vários espaços de trabalho. Inveja? Não mais envergonhado! Deixe-me mostrar como usar o CMake e o Conan no VS Code.
Este artigo é destinado a desenvolvedores C ou C++ que trabalham em projetos que produzem binários ou bibliotecas e desejam poder usar dependências de terceiros. Em nosso caso, usaremos o driverdoMongoDB para C++.
Neste artigo, eu irei:
- Crie um projeto de exemplo do zero com uma estrutura de diretório que pode ser usada para trabalhar com uma ou mais bibliotecas e um binário.
- Escreva as instruções para construir as diferentes partes do projeto e vinculá-las.
- Crie a configuração para usar uma dependência de terceiros usando um gerenciador de pacotes.
- Junte todas essas peças e faça-as funcionar com o VS Code .
Vamos nos concentrar em um projeto que produz uma biblioteca que usa um pacote de terceiros. A biblioteca é então usada em conjunto com algum outro código-fonte para produzir um binário. A mesma estrutura pode ser estendida para ter mais bibliotecas ou até mesmo mais binários. Nesse caso, o pacote de terceiros é o driver MongoDB, que permite que você se conecte a um cluster MongoDB Atlas ou a um MongoDB database local.
- Esta é a estrutura básica de diretório:
1 ├── LibraryN 2 │ ├── include 3 │ │ └── LibraryN.h 4 │ └── src 5 │ └── LibraryN.cpp 6 └── src 7 └── main.cpp - No cabeçalho
libraryN.h
, adicionamos a proteção tradicional para evitar a inclusão múltipla:1 #ifndef _LIBRARY_N_H_ 2 #define _LIBRARY_N_H_ 3 4 #endif - Dentro das diretivas do pré-processador, vamos definir uma classe:
1 class MDBClient { 2 }; - E seu construtor:
1 public: 2 MDBClient(); - Agora, vamos escrever o código de implementação desta biblioteca no
libraryN.cpp
. Começamos incluindo o cabeçalho que acabamos de declarar:1 #include "libraryN.h" - Em seguida, definimos a implementação do construtor que declaramos no cabeçalho:
1 MDBClient::MDBClient() 2 { 3 } - Para poder usar o driver MongoDB aqui, precisamos incluir o cabeçalho para a parte desejada do driver. Neste caso, vamos criar uma instância:
1 #include <mongocxx/instance.hpp> - Agora podemos usar a instância no construtor:
1 mongocxx::instance inst{}; - E, finalmente, temos que escrever o código que utiliza a biblioteca a partir do executável. Incluímos o cabeçalho da biblioteca em
main.cpp
:1 #include "libraryN.h" - Declaramos a função principal aqui, que retorna 0:
1 int main(int argc, char const *argv[]) 2 { 3 return 0; 4 } - E finalizamos criando uma instância da classe que definimos na biblioteca:
1 auto mc = MDBClient{};
Vamos usar o CMake como o sistema de construção para o nosso projeto. As instruções para o CMake são fornecidas no
CMakeLists.txt
.- Começamos definindo a versão mínima do CMake que permitimos ser usada com nosso projeto.
1 cmake_minimum_required(VERSION 3.15) - Em seguida, definimos o projeto usando um nome, uma versão e o(s) idioma(s). Isso também funcionaria para um projeto C, mas, neste caso, vamos usar C++:
1 project(CoolProject VERSION 0.1 LANGUAGES CXX) - As primeiras instruções reais para construir o projeto serão usadas para dizer ao CMake que inclua nossa biblioteca. Primeiro, incluímos as fontes — um único arquivo, nesse caso — e depois fornecemos os arquivos de cabeçalho correspondentes.
1 add_library(libraryN STATIC LibraryN/src/LibraryN.cpp) 2 target_include_directories(libraryN PUBLIC LibraryN/include) - Por fim, adicionamos o código do executável e vinculamos a biblioteca que definimos na etapa anterior.
1 add_executable(${PROJECT_NAME} src/main.cpp) 2 target_link_libraries(${PROJECT_NAME} 3 PRIVATE 4 libraryN)
As instruções de construção que acabamos de escrever seriam adequadas para projetos com uma biblioteca e um executável. Você pode adicionar mais bibliotecas e outros executáveis usando os mesmos comandos do CMake com os dados correspondentes. Mas se você quiser trazer uma dependência de terceiros, suas opções com o CMake são mais dolorosas. É aqui que o Conan vem ao nosso resgate.
O Conan é um gerenciador de pacotes de código aberto para C e C++ que simplifica o processo de integração de dependências de terceiros em nosso projeto. É uma alternativa ao vocêpkgda Microsoft, mas eles têm abordagens ligeiramente diferentes. Ambos têm repositórios de dependências de terceiros e podem ser configurados para incluir as que você precisa em seu projeto. No entanto, enquanto o vspkg usa uma série de tags que definem as versões das dependências do repositório que são testadas para funcionar juntas, o Conan permite que você escolha versões independentes para cada dependência. Você pode escolher versões individuais com vpkg, mas isso exige algum esforço extra.
- A primeira coisa que precisamos fazer é verificar se o pacote que queremos usar –driver MongoDB C++– está disponível no Conan Center. Então visitamos essa página e digitamos “mongo” na caixa de pesquisa. O Conan Center oferece o
mongo-c-driver
e omongo-cxx-driver
. Usaremos o segundo, então clique nele. - Na página
mongo-cxx-driver
, ele sugere o uso de um simplesconanfile.txt
ouconanfile.py
. Iremos com o arquivo com extensão "txt", porque embora seja menos versátil que a configuração do Python, é suficiente para as nossas necessidades neste exemplo. Então, vamos criar umconanfile.txt
com este conteúdo:1 [requires] 2 mongo-cxx-driver/3.8.1 3 [generators] 4 CMakeDeps 5 CMakeToolchain 6 [layout] 7 cmake_layout
Além disso, a página da dependência sugere adicionar algumas linhas à nossa configuração do CMake.
- Adicionamos uma linha ao
CMakeLists.txt
, logo após a linha de declaração do projeto, para encontrar o pacote que Conan instalará.1 find_package(mongocxx REQUIRED) - Adicione uma linha na parte inferior do bloco para a biblioteca que instruirá o CMake a vincular a dependência a ela. Vinculamos a dependência à biblioteca e não ao executável porque é aqui que usamos a dependência.
1 target_link_libraries(libraryN 2 PRIVATE 3 mongo::mongocxx_static) - Usamos a linha de comando para concluir a configuração do projeto. Primeiro, criamos o perfil que contém informações sobre nossa cadeia de ferramentas e o tipo de compilação, que será "Release." Você pode criar um perfil de depuração copiando o arquivo que foi criado e alterando o
build_type
para "Debug" no novo arquivo.1 conan profile detect # If you don't have a conan profile yet - Em seguida, podemos instalar os pacotes e dizer ao Conan para produzir a configuração. Você pode usar o próximo comando novamente com
--profile=debug
(ou o nome do arquivo do seu perfil de depuração), se também quiser instalar a versão de depuração dos pacotes.1 conan install . --build=missing - Neste ponto, devemos ser capazes de construir o projeto a partir da linha de comando utilizando a predefinição criada pelo Conan. Podemos listar as predefinições do CMake usando o seguinte comando:
1 cmake --list-presets - Deve haver apenas uma predefinição de configuração disponível –ou duas se você também instalou a de depuração–, então vamos usá-la para configurar o projeto:
1 cmake --preset conan-release - E podemos construir o projeto utilizando a predefinição de construção correspondente:
1 cmake --build --preset conan-release - Abrace seu parceiro, seu amigo ou seu animal de estimação, porque você construiu o projeto com sucesso. Yippee ki-yay, meu amigo!
Vamos limpar a compilação para ver como isso funciona com o VS Code.
- Precisamos especificar o diretório que Conan usou para o cache.
1 cmake --build build/Release --target clean - E antes de tentarmos construir a partir do VS Code, precisamos estar cientes de que você precisará ter duas extensões instaladas: CMake e CMake Tools.
- Na paleta de comandos (
View -> Command Palette
ouCmd+S+P
), invocamos "Desenvolvedor: recarregamento de janela". O VS Code recarregará o diretório, verificará o conteúdo doCMakeLists.txt
e nos oferecerá a opção de um dos perfis disponíveis. Devemos escolher uma das predefinições fornecidas por Conan. - Para construir o projeto a partir do VS Code, clique nos ícones das Ferramentas do CMake na barra lateral.
- Devemos ser capazes de construir, executar e até depurar sem problemas.
Neste tutorial, exploramos algumas opções para aprimorar nossas ferramentas. Agora podemos usar o CMake para criar projetos de tamanho médio e o Conan para lidar com nossas dependências. Podemos usar esses dois para construir a partir da linha de comando, mas demos um passo além e usamos essa configuração do nosso favorito VS Code.
Fique curioso, hackeie seu código, até a próxima!
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.