\documentclass[aspectratio=169]{beamer} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage{graphics} \usepackage{graphicx} \usepackage{verbatim} \usepackage{plantuml} \usepackage{listings} \usepackage{csquotes} \usepackage{multicol} \usepackage{menukeys} % Style related code % \setbeamerfont{footnote}{size=\tiny} % Code block style % \lstset{ basicstyle=\footnotesize\ttfamily, columns=fullflexible, frame=single, numbers=left } \title{Workshop Modern C++ build environment} \author{Bart Beumer (bart.beumer@alten.nl)} \institute{Alten} \date{2025-07-29} \begin{document} \begin{frame} \titlepage \end{frame} \begin{frame}{Rationale} Using modern tools in combination with C \& C++ we can describe the build environment, 3rd party libraries and executables to build. We will be able to create a highly reproducable build environment regardless of the OS running on the developer PC (as long as it can run docker). \vspace{5mm} This workshop aims to demonstrate how to create this build environment, how to use the tools, introduce ourselves to this way of working using included demonstration projects. \end{frame} \begin{frame}{Tools} We will be using a combination of tools, each having their own purpose. \begin{itemize} \item Dev containers \footnote{\url{https://containers.dev/}} \begin{quote} A development container (or dev container for short) allows you to use a container as a full-featured development environment. \end{quote} \item Conan \footnote{\url{https://conan.io/faq}} Open source, decentralized and multi-platform package manager. \item CMake \footnote{\url{https://cmake.org/about/}} \begin{quote} ... an open source, cross-platform family of tools designed to build, test, and package software. \end{quote} \end{itemize} \end{frame} \begin{frame}{Dev containers} Solves the problem of having an encapsulated environment containing all tools, files, configuration that makes up the development environment. \vspace{5mm} Supported by multiple tools like: \begin{itemize} \item Visual Studio Code \footnote{\url{https://containers.dev/supporting}} \item IntelliJ IDEA \footnote{\url{https://blog.jetbrains.com/idea/2024/07/using-dev-containers-in-jetbrains-ides-part-1/}} \item GitHub codespaces \footnote{\url{https://docs.github.com/en/codespaces/about-codespaces/what-are-codespaces}} \end{itemize} \end{frame} \begin{frame}{Dev containers} We need the following files: \begin{itemize} \item Dockerfile \item devcontainer.json \end{itemize} \end{frame} \begin{frame}{Dev containers} Using docker compose we create the entire container. \lstinputlisting[keepspaces,firstline=1, firstnumber=1]{../.devcontainer/Dockerfile} \end{frame} \begin{frame}{Dev containers} A devcontainer.json contains metadata used by tools. \lstinputlisting[firstline=1, firstnumber=1]{../.devcontainer/devcontainer.json} \end{frame} \begin{frame}{Dev containers} We will experiment with these files during the workshop. \end{frame} \begin{frame}{Conan} \begin{quotation} Conan is a package manager for C and C++ which aims to solve some very common and difficult challenges.\footnote{\url{https::/conan.io/faq}} \end{quotation} \begin{itemize} \item Conveniently depend on 3rd party packages and use them. \item Automates the process of downloading, building \& deploy for further use. \item Provide a mechanism to use libraries. \end{itemize} \end{frame} \begin{frame}{Conan} A simple text file can be used to configure dependencies on packages. \lstinputlisting[language=make]{../conanfile.txt} \end{frame} \begin{frame}{Conan} We will experiment with these files during the workshop. \end{frame} \begin{frame}{CMake} \begin{quote} CMake is an open source, cross-platform family of tools designed to build, test, and package software. CMake gives you control of the software compilation process using simple independent configuration files. Unlike many cross-platform systems, CMake is designed to be used in conjunction with the native build environment. \footnote{\url{https://cmake.org/about/}} \end{quote} \begin{itemize} \item Good documentation and tutorials provided.\footnote{\url{https://cmake.org/cmake/help/latest/guide/tutorial/index.html}} \item Tools run locally on a system. \end{itemize} \end{frame} \begin{frame}{CMake} Using files we can describe libraries, executables, the (external) dependencies they have. \lstinputlisting[language=make]{../src/hello_world/CMakeLists.txt} \end{frame} \begin{frame}{CMake} We will experiment with these files during the workshop. \end{frame} \begin{frame}{Workshop} \begin{multicols}{2} Lets start with opening our IDE and our project folder. \includegraphics[width=0.45\textwidth]{vscode_empty} Quickly after opening the folder we get the following question: \includegraphics[width=0.45\textwidth]{vscode_folder_contains_devcontainer} VS Code will build the container if needed and start using it. \end{multicols} \end{frame} \begin{frame}{Workshop} The dev container has been built, now we need to let conan work and fetch and build dependencies. \vspace{5mm} \keys{CTRL + SHIFT + P} ``conan install'' \vspace{5mm} \includegraphics[width=0.75\textwidth]{vscode_conan_install} \end{frame} \begin{frame}{Workshop} \begin{multicols}{2} We can now use CMake to build our software. \includegraphics[height=0.65\textheight]{vscode_conan_done_cmake} \begin{itemize} \item configure \item build \item debug/launch \end{itemize} \end{multicols} \end{frame} \begin{frame}{Workshop} Continuing with theory \end{frame} \begin{frame}[fragile]{Conan: important commands} \begin{verbatim} pip install conan \end{verbatim} We use the python package manager to install conan. (part of Dockerfile) \begin{verbatim} conan profile detect \end{verbatim} We let conan detect compilers and tools for which it can use. (part of Dockerfile) \begin{verbatim} conan install \end{verbatim} While in the project working directory, download packages, compile them, generate CMake environment. (was run using vs code) After that we can use CMake as we would normally. \end{frame} \begin{frame}{CMake} \end{frame} \begin{frame}{CMake: The basics} \lstinputlisting[language=make]{../src/hello_world/CMakeLists.txt} \end{frame} \begin{frame}{CMake: The basics} \lstinputlisting[language=make,firstline=1,lastline=2]{../src/hello_world/CMakeLists.txt} \begin{itemize} \item Sets the minimum required version of cmake for a project. \item Sets behavior of CMake as it was at a certain version (set policies)\footnote{\url{https://cmake.org/cmake/help/latest/command/cmake_minimum_required.html}} \end{itemize} \vspace{5mm} A mechanism to provide backwards compatibility while allowing future versions to change behavior of commands. \end{frame} \begin{frame}[fragile]{CMake: The basics} \lstinputlisting[language=make,firstline=2, firstnumber=2, lastline=9]{../src/hello_world/CMakeLists.txt} \begin{itemize} \item ``project'' Used to set the PROJECT\_NAME variable. \item ``add\_executable'' Adding executable by specifying the executable name and the source files. \end{itemize} \end{frame} \begin{frame}[fragile]{CMake: The basics} \lstinputlisting[language=make,firstline=9, firstnumber=9, lastline=18]{../src/hello_world/CMakeLists.txt} \begin{itemize} \item ``set\_property'' Enables us to set properties like language standard to use (C++, CUDA, ...) \end{itemize} \end{frame} \begin{frame}{CMake: The basics, library} \lstinputlisting[language=make, firstline=3,firstnumber=3, lastline=21]{../src/awesome_log/CMakeLists.txt} \end{frame} \begin{frame}{CMake: The basics, library} \lstinputlisting[language=make,firstline=5,firstnumber=5,lastline=11]{../src/awesome_log/CMakeLists.txt} Similar to ``add\_executable'' we can create a library, specifying the name of the library and the sources that form it. \end{frame} \begin{frame}{CMake: The basics, library} \lstinputlisting[language=make,firstline=18,firstnumber=18,lastline=21]{../src/awesome_log/CMakeLists.txt} Add include directories, for both creating the target itself AND targets depending on this target. \vspace{5mm} No need for consumers of the library to set include paths, they inherit from this library target. \end{frame} \begin{frame}{Using 3rd-party packages} \end{frame} \begin{frame}{Conan: 3rd-party packages} \lstinputlisting[language=make]{example_conan.txt} \begin{itemize} \item ``[requires]'' Declare the libraries that we want to use in our project. \item ``[generators]'' Tell Conan to generate files for given build system \end{itemize} \end{frame} \begin{frame}{Conan: 3rd-party packages the python way} \lstinputlisting[language=make]{example_conan_py.txt} \end{frame} \begin{frame}{CMake: Using 3rd-party packages} \lstinputlisting[language=make]{../src/example_boost/CMakeLists.txt} \end{frame} \begin{frame}{CMake, 3rd-party packages} \lstinputlisting[language=make, firstline=2,firstnumber=2,lastline=4]{../src/example_boost/CMakeLists.txt} Find a package (usually provided by something external to the project), and load its package-specific details.\footnote{\url{https://cmake.org/cmake/help/latest/command/find_package.html}} \lstinputlisting[language=make, firstline=15,firstnumber=15,lastline=18]{../src/example_boost/CMakeLists.txt} Using exposed target names we can use those packages. \begin{itemize} \item Affects libraries linked to target. \item Affects include paths to look for headers. \end{itemize} \end{frame} \begin{frame}[fragile]{CMake: Testing} \begin{verbatim} enable_testing() \end{verbatim} Use enable\_testing() at the top level CMakeLists.txt to enable cmake to generate things needed to support testing\footnote{\url{https://cmake.org/cmake/help/latest/command/enable_testing.html}}. \begin{verbatim} add_test() \end{verbatim} Use add\_test() inside your CMakeLists.txt to register the test\footnote{\url{https://cmake.org/cmake/help/latest/command/add_test.html}}. \begin{verbatim} ctest \end{verbatim} Commandline application to run all registered tests\footnote{\url{https://cmake.org/cmake/help/latest/manual/ctest.1.html}}. \end{frame} \begin{frame} Worshop time! Suggestions: \begin{itemize} \item Play around in the environment, have a look at some of the projects. \item Try and add a 3rd party package and use it (fmt, ...) \item Use a different compiler. \item Add a tool to your image (valgrind, ...). \end{itemize} \end{frame} \end{document}