Uso de Docker para compilar y ejecutar un proyecto C ++

Esta publicación hablará sobre cómo construir un proyecto C ++ usando GTest y Boost usando Docker. El artículo es una receta con algunos comentarios explicativos; la solución presentada en el artículo no pretende estar lista para producción.


¿Por qué y quién podría necesitarlo?


Supongamos que, como yo, realmente le gusta el concepto de Python venv , cuando todas las dependencias necesarias se encuentran en un directorio separado, estrictamente definido; o debe proporcionar una portabilidad simple del entorno de ensamblaje y prueba para el proyecto en desarrollo, lo cual es muy conveniente, por ejemplo, cuando se une un nuevo desarrollador al equipo.


Este artículo será especialmente útil para los desarrolladores principiantes que necesitan realizar configuraciones de entorno básicas para crear y ejecutar un proyecto C ++.


El entorno presentado en el artículo puede usarse como marco para tareas de prueba o trabajo de laboratorio.


Instalar Docker


Todo lo que necesita para implementar el proyecto presentado en este artículo es Docker y acceso a Internet.


Docker está disponible para plataformas Windows, Linux y Mac. La documentación oficial .


Como uso una máquina Windows a bordo, solo tuve que descargar el instalador y ejecutarlo.


Tenga en cuenta que en este momento, Docker para Windows utiliza Hyper-V para su trabajo.


Proyecto


Como proyecto, nos referiremos a una aplicación CommandLine que muestra la cadena "¡Hola Mundo!" a flujo de salida estándar.


El proyecto utilizará las bibliotecas mínimas requeridas, así como CMake como sistema de compilación.


La estructura de nuestro proyecto será la siguiente:


project | Dockerfile | \---src CMakeLists.txt main.cpp sample_hello_world.h test.cpp 

El archivo CMakeLists.txt contiene una descripción del proyecto.
Código fuente del archivo:


 cmake_minimum_required(VERSION 3.2) project(HelloWorldProject) #  C++17 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") #  Boost.Program_options #   ,     set(Boost_USE_STATIC_LIBS ON) find_package(Boost COMPONENTS program_options REQUIRED) include_directories(${BOOST_INCLUDE_DIRS}) #     add_executable(hello_world_app main.cpp sample_hello_world.h) target_link_libraries(hello_world_app ${Boost_LIBRARIES}) #  CTest enable_testing() #       GoogleTest find_package(GTest REQUIRED) include_directories(${GTEST_INCLUDE_DIRS}) #    add_executable(hello_world_test test.cpp sample_hello_world.h) target_link_libraries(hello_world_test ${GTEST_LIBRARIES} pthread) #       CTest add_test(NAME HelloWorldTest COMMAND hello_world_test) 

El archivo sample_hello_world.h contiene una descripción de la clase HelloWorld, enviando una instancia de la cual a la secuencia, se mostrará la cadena "Hello World!". Esta complejidad se debe a la necesidad de probar el código de nuestra aplicación.
Código fuente del archivo:


 #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 

El archivo main.cpp contiene el punto de entrada de nuestra aplicación, también agregaremos Boost.Program_options para simular un proyecto real.


Código fuente del archivo:


 #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; } 

El archivo test.cpp contiene el mínimo necesario: una prueba de la funcionalidad de la clase HelloWorld. Para las pruebas usamos GoogleTest .
Código fuente del archivo:


 #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(); } 

A continuación, pasemos a la parte más interesante: ¡configurar su entorno de compilación usando Dockerfile!


Dockerfile


Para el montaje usaremos gcc de la última versión.
Dockerfile contiene dos etapas: construcción y lanzamiento de nuestra aplicación.
Para ejecutar, use la última versión de Ubuntu.


Contenido de 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"] 

Supongo que por ahora, ¡vaya a construir y ejecutar la aplicación!


Montaje y lanzamiento


Para construir nuestra aplicación y crear una imagen Docker, será suficiente ejecutar el siguiente comando:


 #  docker-cpp-sample    # . -    ,  Dockerfile docker build -t docker-cpp-sample . 

Para iniciar la aplicación, use el comando:


 > docker run docker-cpp-sample 

Veremos las queridas palabras:


 Hello World! 

Para pasar un parámetro, será suficiente agregarlo al comando anterior:


 > docker run docker-cpp-sample --help Allowed options: -h [ --help ] Produce this message 

Para resumir


Como resultado, creamos una aplicación C ++ completa, configuramos el entorno para compilarla y ejecutarla en Linux, y la envolvimos en un contenedor Docker. Por lo tanto, libera a los desarrolladores posteriores de la necesidad de pasar tiempo configurando un ensamblaje local.

Source: https://habr.com/ru/post/es414109/


All Articles