\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]{example_conan.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, ...) \item ``target\_link\_libraries'' Specify library dependencies. \end{itemize} \end{frame} \begin{frame}{CMake: The basics, library} \lstinputlisting[language=make]{../src/log/CMakeLists.txt} \end{frame} \begin{frame}{CMake: The basics, library} \lstinputlisting[language=make,firstline=4,firstnumber=4,lastline=9]{../src/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=15,firstnumber=15,lastline=18]{../src/log/CMakeLists.txt} Add include directories, look for header files. Applicable for building the given target Applicable for building targets depending on this 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/hello_world_boost/CMakeLists.txt} \end{frame} \begin{frame}{CMake, 3rd-party packages} \lstinputlisting[language=make, firstline=2,firstnumber=2,lastline=4]{../src/hello_world_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=17,firstnumber=17,lastline=20]{../src/hello_world_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}{VERIFIED UNTIL HERE} \end{frame} \begin{frame}{CWorkshop time!} \begin{itemize} \item Open VS Code, build example applications \item Create your own application, using 3rd-party library of your choice (fmt,gtest) \end{itemize} \end{frame} \begin{frame}[fragile]{CMake: Integrate 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}{CWorkshop time!} \begin{itemize} \item Open VS Code, build example applications \item Create your own unittest, add testing in CMake \end{itemize} \end{frame} \begin{frame}{C++23 Modules is supported!} For C++23 we have a feature called ``modules''. This feature requires support not only by compilers, but also by build tools. The latest version of CMake in combination with Ninja does this. Included in provided material is an example FURTHER DEV NEEDED \end{frame} \begin{frame}{END OF THE PRESENTATION} \end{frame} \begin{frame}{CMake, where to find more info} \begin{itemize} \item https://cmake.org/ \item https://cmake.org/cmake/help/latest/ \end{itemize} \end{frame} \begin{frame}{Conan, in the background} \end{frame} \begin{frame}{Workshop} \end{frame} \begin{frame}{Uniform reproducable environment} There are a lot of factors that influence your C++ development environment \begin{itemize} \item The OS being used. \item Environment variables. \item Installed compilers. \item Libraries and tools. \end{itemize} Setting up a developer environment (1st day at new assignment) can involve a lot of steps! Dev containes is a small facility built on top of docker that allows all of the above factors to be contained and easilly created \end{frame} \begin{frame}{CMake, common variables} \begin{tabular}{| c | c |} \hline PROJECT\_NAME & Name of the project given to the project command. \\ \hline CMAKE\_CURRENT\_SOURCE\_DIR & Path to source directory currently being processed. \\ \hline CMAKE\_CURRENT\_BINARY\_DIR & Path to binary directory currently being processed. \\ \hline CMAKE\_COMMAND & Path to the cmake executable. \\ \hline \end{tabular} Variables can be used in CMake to navigate directories \footnote{\url{https://cmake.org/cmake/help/latest/manual/cmake-variables.7.html}} \end{frame} \begin{frame}{CMake, creating modules} \begin{columns} \begin{column}{0.45\textwidth} \lstinputlisting[language=make]{../src/math/CMakeLists.txt} \end{column} \begin{column}{0.45\textwidth} Requires recent CMake and Ninja packages. \end{column} \end{columns} \end{frame} \end{document}