diff --git a/presentation/example_conan.txt b/presentation/example_conan.txt new file mode 100644 index 0000000..218cfb2 --- /dev/null +++ b/presentation/example_conan.txt @@ -0,0 +1,7 @@ +[requires] +boost/1.84.0 +gtest/1.14.0 + +[generators] +CMakeDeps +CMakeToolchain diff --git a/presentation/example_conan_py.txt b/presentation/example_conan_py.txt new file mode 100644 index 0000000..a11d27e --- /dev/null +++ b/presentation/example_conan_py.txt @@ -0,0 +1,19 @@ +import os +from conan import ConanFile +from conan.tools.files import copy +from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps + +class HelloConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + requires = "boost/1.84.0", "gtest/1.14.0", "libmagic/5.45" + generators = "CMakeDeps" + build_policy = "*" + + def generate(self): + # We need to find the folder of libmagic and supply it to cmake so that + # we can deploy the magic file. + libmagic = self.dependencies["libmagic"] + + tc = CMakeToolchain(self) + tc.variables["CONAN_LIBMAGIC_PACKAGE_FOLDER"] = libmagic.package_folder + tc.generate() diff --git a/presentation/presentation.tex b/presentation/presentation.tex new file mode 100644 index 0000000..79aa91c --- /dev/null +++ b/presentation/presentation.tex @@ -0,0 +1,462 @@ +\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} diff --git a/presentation/vscode_conan_done_cmake.png b/presentation/vscode_conan_done_cmake.png new file mode 100644 index 0000000..fa3b3ff Binary files /dev/null and b/presentation/vscode_conan_done_cmake.png differ diff --git a/presentation/vscode_conan_install.png b/presentation/vscode_conan_install.png new file mode 100644 index 0000000..bf4aa90 Binary files /dev/null and b/presentation/vscode_conan_install.png differ diff --git a/presentation/vscode_empty.png b/presentation/vscode_empty.png new file mode 100644 index 0000000..f4e2581 Binary files /dev/null and b/presentation/vscode_empty.png differ diff --git a/presentation/vscode_folder_contains_devcontainer.png b/presentation/vscode_folder_contains_devcontainer.png new file mode 100644 index 0000000..b1cbff5 Binary files /dev/null and b/presentation/vscode_folder_contains_devcontainer.png differ