Utilisation de Docker pour créer et exécuter un projet C ++

Ce post expliquera comment créer un projet C ++ à l'aide de GTest et Boost à l'aide de Docker. L'article est une recette avec quelques commentaires explicatifs; la solution présentée dans l'article ne prétend pas être prête pour la production.


Pourquoi et qui pourrait en avoir besoin?


Supposons que vous, comme moi, appréciez vraiment le concept de Python venv , lorsque toutes les dépendances nécessaires sont situées dans un répertoire distinct et strictement défini; ou vous devez fournir une portabilité simple de l'environnement d'assemblage et de test pour le projet en cours de développement, ce qui est très pratique, par exemple, lorsque vous joignez un nouveau développeur à l'équipe.


Cet article sera particulièrement utile pour les développeurs débutants qui doivent effectuer des paramètres d'environnement de base pour créer et exécuter un projet C ++.


L'environnement présenté dans l'article peut être utilisé comme cadre pour des tâches de test ou des travaux de laboratoire.


Installer Docker


Tout ce dont vous avez besoin pour implémenter le projet présenté dans cet article est Docker et l'accès Internet.


Docker est disponible pour les plates-formes Windows, Linux et Mac. La documentation officielle .


Puisque j'utilise une machine Windows à bord, je n'ai eu qu'à télécharger le programme d'installation et l'exécuter.


Veuillez noter qu'en ce moment, Docker pour Windows utilise Hyper-V pour son travail.


Projet


En tant que projet, nous entendons une application CommandLine qui affiche la chaîne "Hello World!" au flux de sortie standard.


Le projet utilisera les bibliothèques minimales requises, ainsi que CMake comme système de construction.


La structure de notre projet sera la suivante:


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

Le fichier CMakeLists.txt contient une description du projet.
Code source du fichier:


 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) 

Le fichier sample_hello_world.h contient une description de la classe HelloWorld, en envoyant une instance au flux, la chaîne "Hello World!" Sera affichée. Cette complexité est due à la nécessité de tester le code de notre application.
Code source du fichier:


 #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 

Le fichier main.cpp contient le point d'entrée de notre application, nous ajouterons également Boost.Program_options pour simuler un vrai projet.


Code source du fichier:


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

Le fichier test.cpp contient le minimum nécessaire - un test de la fonctionnalité de la classe HelloWorld. Pour les tests, nous utilisons GoogleTest .
Code source du fichier:


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

Ensuite, passons à la partie la plus intéressante - configurer votre environnement de construction à l'aide de Dockerfile!


Dockerfile


Pour l'assemblage, nous utiliserons gcc de la dernière version.
Dockerfile contient deux étapes: la création et le lancement de notre application.
Pour exécuter, utilisez la dernière version d'Ubuntu.


Contenu 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"] 

Je suppose que pour l'instant, continuez à construire et exécuter l'application!


Assemblage et lancement


Pour construire notre application et créer une image Docker, il suffira d'exécuter la commande suivante:


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

Pour démarrer l'application, utilisez la commande:


 > docker run docker-cpp-sample 

Nous verrons les mots chéris:


 Hello World! 

Pour passer un paramètre, il suffira de l'ajouter à la commande ci-dessus:


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

Pour résumer


En conséquence, nous avons créé une application C ++ à part entière, configuré l'environnement pour sa création et son exécution sous Linux, et l'avons enveloppé dans un conteneur Docker. Ainsi, libérant les développeurs suivants de la nécessité de passer du temps à configurer un assembly local.

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


All Articles