Esta postagem falará sobre como criar um projeto C ++ usando o GTest e o Boost usando o Docker. O artigo é uma receita com alguns comentários explicativos; a solução apresentada no artigo não pretende estar pronta para a produção.
Por que e quem pode precisar?
Suponha que você, como eu, realmente goste do conceito de Python venv , quando todas as dependências necessárias estiverem localizadas em um diretório separado e estritamente definido; ou você precisa fornecer portabilidade simples do ambiente de montagem e teste para o projeto em desenvolvimento, o que é muito conveniente, por exemplo, ao ingressar um novo desenvolvedor na equipe.
Este artigo será especialmente útil para desenvolvedores iniciantes que precisam executar configurações básicas do ambiente para criar e executar um projeto C ++.
O ambiente apresentado no artigo pode ser usado como uma estrutura para tarefas de teste ou trabalho de laboratório.
Instalar o Docker
Tudo o que você precisa para implementar o projeto apresentado neste artigo é Docker e acesso à Internet.
O Docker está disponível para plataformas Windows, Linux e Mac. A documentação oficial .
Desde que eu uso uma máquina Windows a bordo, eu apenas tive que baixar o instalador e executá-lo.
Observe que, no momento, o Docker para Windows usa o Hyper-V para o seu trabalho.
Projeto
Como projeto, queremos dizer um aplicativo CommandLine que exibe a string "Hello World!" para o fluxo de saída padrão.
O projeto usará as bibliotecas mínimas necessárias, bem como o CMake como um sistema de construção.
A estrutura do nosso projeto será a seguinte:
project | Dockerfile | \---src CMakeLists.txt main.cpp sample_hello_world.h test.cpp
O arquivo CMakeLists.txt contém uma descrição do projeto.
Código fonte do arquivo:
cmake_minimum_required(VERSION 3.2) project(HelloWorldProject)
O arquivo sample_hello_world.h contém uma descrição da classe HelloWorld, enviando uma instância para o fluxo, a sequência "Hello World!" Será exibida. Essa complexidade se deve à necessidade de testar o código do nosso aplicativo.
Código fonte do arquivo:
#ifndef SAMPLE_HELLO_WORLD_H #define SAMPLE_HELLO_WORLD_H namespace sample { struct HelloWorld { template<class OS> friend OS& operator<<(OS& os, const HelloWorld&) { os << "Hello World!"; return os; } }; } // sample #endif // SAMPLE_HELLO_WORLD_H
O arquivo main.cpp contém o ponto de entrada do nosso aplicativo, também adicionaremos Boost.Program_options para simular um projeto real.
Código fonte do arquivo:
#include "sample_hello_world.h" #include <boost/program_options.hpp> #include <iostream> // - "--help" auto parseArgs(int argc, char* argv[]) { namespace po = boost::program_options; po::options_description desc("Allowed options"); desc.add_options() ("help,h", "Produce this message"); auto parsed = po::command_line_parser(argc, argv) .options(desc) .allow_unregistered() .run(); po::variables_map vm; po::store(parsed, vm); po::notify(vm); // C++17 std::make_pair return std::pair(vm, desc); } int main(int argc, char* argv[]) try { auto [vm, desc] = parseArgs(argc, argv); if (vm.count("help")) { std::cout << desc << std::endl; return 0; } std::cout << sample::HelloWorld{} << std::endl; return 0; } catch (std::exception& e) { std::cerr << "Unhandled exception: " << e.what() << std::endl; return -1; }
O arquivo test.cpp contém o mínimo necessário - um teste da funcionalidade da classe HelloWorld. Para testar, usamos o GoogleTest .
Código fonte do arquivo:
#include "sample_hello_world.h" #include <sstream> #include <gtest/gtest.h> // , HelloWorld , TEST(HelloWorld, Test) { std::ostringstream oss; oss << sample::HelloWorld{}; ASSERT_EQ("Hello World!", oss.str()); } // int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }
Em seguida, vamos para a parte mais interessante - configurando seu ambiente de construção usando o Dockerfile!
Dockerfile
Para montagem, usaremos o gcc da versão mais recente.
O Dockerfile contém dois estágios: construindo e iniciando nosso aplicativo.
Para executar, use a versão mais recente do Ubuntu.
Conteúdo do Dockerfile:
# --------------------------------------- # gcc:latest FROM gcc:latest as build # GoogleTest WORKDIR /gtest_build # GoogleTest # , # Docker RUN , # , , RUN apt-get update && \ apt-get install -y \ libboost-dev libboost-program-options-dev \ libgtest-dev \ cmake \ && \ cmake -DCMAKE_BUILD_TYPE=Release /usr/src/gtest && \ cmake --build . && \ mv lib*.a /usr/lib # /src ADD ./src /app/src # WORKDIR /app/build # , RUN cmake ../src && \ cmake --build . && \ CTEST_OUTPUT_ON_FAILURE=TRUE cmake --build . --target test # --------------------------------------- # ubuntu:latest FROM ubuntu:latest # , Docker root # root' :) RUN groupadd -r sample && useradd -r -g sample sample USER sample # WORKDIR /app # COPY --from=build /app/build/hello_world_app . # ENTRYPOINT ["./hello_world_app"]
Acho que, por enquanto, continue criando e executando o aplicativo!
Montagem e lançamento
Para criar nosso aplicativo e criar uma imagem do Docker, basta executar o seguinte comando:
Para iniciar o aplicativo, use o comando:
> docker run docker-cpp-sample
Veremos as palavras queridas:
Hello World!
Para passar um parâmetro, basta adicioná-lo ao comando acima:
> docker run docker-cpp-sample --help Allowed options: -h [ --help ] Produce this message
Resumir
Como resultado, criamos um aplicativo C ++ completo, configuramos o ambiente para compilar e executá-lo no Linux e o envolvemos em um contêiner Docker. Assim, liberando os desenvolvedores subseqüentes da necessidade de gastar tempo configurando uma montagem local.