A08 - Manipulação de dependência automatizada com FetchContent

Questão

  • Existe uma maneira de satisfazer automaticamente as dependências do nosso código?

Objetivos

  • Aprenda como baixar suas dependências em tempo de configuração com FetchContent.

  • Saiba como o conteúdo buscado pode ser usado de forma nativa em seu sistema de compilação.

O CMake oferece dois módulos para satisfazer as dependências ausentes em tempo real: os módulos ExternalProject e FetchContent.

Usando ExternalProject
Usando FetchContent
  • A etapa de download acontece em tempo de configuração do projeto.

  • Você só pode gerenciar dependências que usam CMake.

  • É uma alteração bem delimitada em um sistema de compilação CMake existente.

Ambos são mecanismos extremamente poderosos, mas você deve usá-los com cuidado. Muitas vezes, uma documentação abrangente será suficiente para ajudar os usuários a configurar seu ambiente para construir seu código com sucesso! Nesta atividade, discutiremos o módulo FetchContent.

O modulo FetchContent

Para buscar dependências dinamicamente no momento da configuração, você incluirá o módulo interno do CMake FetchContent. Este módulo faz parte do CMake desde sua versão 3.11 e vem sendo aprimorado constantemente desde então.

Há duas etapas em um fluxo de trabalho baseado em FetchContent:

  1. Declarando o conteúdo a ser buscado com FetchContent_Declare.

    Pode ser um tarball (local ou remoto), uma pasta local ou um repositório de controle de versão (Git, SVN, etc.).

  2. Populando o conteúdo com FetchContent_MakeAvailable.

    Este comando adiciona os alvos declarados no conteúdo externo ao seu sistema de compilação.

    Como os alvos do projeto externo são adicionados ao seu próprio projeto, você poderá usá-los da mesma maneira que faria ao obtê-los por meio de uma chamada para find_package: você pode usar o conteúdo found e fetched na mesma maneira. Se você precisa definir opções para criar o projeto externo, você as definirá como variáveis CMake antes de chamar FetchContent_MakeAvailable.

Testes unitários com Catch2

O teste de unidade é uma técnica valiosa em engenharia de software: ele pode ajudar a identificar regressões funcionais com um nível muito fino de controle, pois cada teste de unidade destina-se a exercitar componentes isolados em sua base de código. Equipar sua base de código com integração e testes de unidade é uma prática muito boa.

Existem muitas estruturas de teste de unidade para a linguagem C++. Cada um deles enfatiza uma abordagem ligeiramente diferente para testes de unidade e vem com suas próprias peculiaridades na configuração e uso.

Nesta atividade, mostraremos como usar Catch2 uma estrutura de teste de unidade muito popular que enfatiza um fluxo de trabalho de desenvolvimento orientado a testes. Catch2 é distribuído como um arquivo de cabeçalho único, que é uma de suas características mais atraentes: pode ser facilmente incluído em qualquer projeto. Em vez de baixar o arquivo de cabeçalho e adicioná-lo à nossa base de código, podemos usar FetchContent para satisfazer essa dependência para nós quando necessário.

Exercício 26: Catch2 recarregado

Queremos usar a estrutura de teste de unidade Catch2 em nosso código. Neste exercício, faremos o download do projeto Catch2 no momento da configuração de seu repositório GitHub.

O projeto base está em source/code/day-2/26_more-catch2.

  1. Crie um projeto C++.

  2. Defina o padrão C++ para C++14. Catch2 também funcionará com C++11.

  3. Crie uma biblioteca a partir do arquivo fonte sum_integers.cpp.

  4. Vincule a biblioteca em um executável sum_up.

  5. Inclua o módulo FetchContent e declare o conteúdo Catch2. Queremos baixar a tag v2.13.4 do repositório oficial do Git.

  6. Faça o conteúdo Catch2 disponível.

  7. Crie o executável cpp_test.

  8. Habilite o teste e adicione um teste. Você terá que verificar como chamar um executável Catch2 na documentação.

  9. Tente rodar seus testes.

  • Que diferenças você observa na etapa de configuração?

  • O que acontece se você esquecer de emitir o comando FetchContent_MakeAvailable?

  • Quais alvos são construídos no projeto? Quais são do Catch2? Você pode usar o seguinte comando para obter uma lista de todos os destinos disponíveis:

    $ cmake --build build --target help
    

Uma solução funcional está na subpasta solution.

Warning

Atençao

FetchContent é um módulo poderoso em sua caixa de ferramentas CMake. Cuidado! Satisfazer todas as dependências do seu código dessa forma fará com que a duração dos estágios de configuração e construção aumentem.

Resumo

  • CMake permite que você satisfaça dependências on-the-fly.

  • Você pode fazer isso em tempo de compilação com ExternalProject, mas você precisa adotar um framework superbuild.

  • No momento da configuração, você pode usar o módulo FetchContent: ele só pode ser aplicado com dependências que também usam CMake.