diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..9fc6dd5 --- /dev/null +++ b/.clang-format @@ -0,0 +1,37 @@ +--- +AlignAfterOpenBracket: Align +AllowAllArgumentsOnNextLine: 'false' +AllowAllConstructorInitializersOnNextLine: 'false' +AllowAllParametersOfDeclarationOnNextLine: 'false' +AllowShortBlocksOnASingleLine: 'false' +AllowShortCaseLabelsOnASingleLine: 'false' +AllowShortFunctionsOnASingleLine: InlineOnly +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: None +AllowShortLoopsOnASingleLine: 'false' +AlwaysBreakTemplateDeclarations: 'Yes' +BinPackArguments: 'false' +BinPackParameters: 'false' +BreakBeforeBraces: Allman +BreakConstructorInitializers: BeforeComma +ColumnLimit: '120' +Cpp11BracedListStyle: 'true' +FixNamespaceComments: 'true' +IncludeBlocks: Merge +IndentCaseLabels: 'true' +IndentWidth: '4' +Language: Cpp +MaxEmptyLinesToKeep: '2' +NamespaceIndentation: Inner +PointerAlignment: Left +SortUsingDeclarations: 'true' +SpaceAfterTemplateKeyword: 'false' +SpacesInAngles: 'false' +SpacesInCStyleCastParentheses: 'false' +SpacesInContainerLiterals: 'false' +SpacesInSquareBrackets: 'false' +Standard: Cpp11 +TabWidth: '4' +UseTab: Never + +... diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index e615f0c..5edf558 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -3,18 +3,9 @@ FROM alpine:3.21.3 # Install tools required for building. RUN apk update && \ apk add --no-cache \ - autoconf \ - bash \ - build-base \ - cmake \ - gdb \ - git \ - libstdc++ \ - libtool \ - linux-headers \ - m4 \ - perl \ - python3 \ - py3-pip && \ + autoconf bash build-base cmake gdb \ + git libstdc++ libtool linux-headers \ + m4 perl python3 py3-pip\ + && \ pip install --break-system-packages conan && \ conan profile detect diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 1e64a64..eb5df40 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,5 +1,5 @@ { - "name": "C++", + "name": "Workshop Modern C++ Dev", "build": { "dockerfile": "Dockerfile" }, 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.pdf b/presentation/presentation.pdf new file mode 100644 index 0000000..ade0d51 Binary files /dev/null and b/presentation/presentation.pdf differ diff --git a/presentation/presentation.tex b/presentation/presentation.tex new file mode 100644 index 0000000..2222b73 --- /dev/null +++ b/presentation/presentation.tex @@ -0,0 +1,366 @@ +\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} 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 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4c95bae..f0e6ed4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,3 +1,6 @@ cmake_minimum_required(VERSION 3.20) add_subdirectory(example_boost) +add_subdirectory(hello_world) +add_subdirectory(hello_world_awesome) +add_subdirectory(awesome_log) diff --git a/src/awesome_log/CMakeLists.txt b/src/awesome_log/CMakeLists.txt new file mode 100644 index 0000000..533fa9b --- /dev/null +++ b/src/awesome_log/CMakeLists.txt @@ -0,0 +1,48 @@ +cmake_minimum_required(VERSION 3.20) + +project(awesome_log) + +add_library( + ${PROJECT_NAME} + ./src/console_writer.cpp + ./src/log.cpp + ./src/null_writer.cpp + ./src/scoped_log.cpp +) + +set_property( + TARGET ${PROJECT_NAME} + PROPERTY CXX_STANDARD 20 +) + +target_include_directories( + ${PROJECT_NAME} + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include +) + +find_package(GTest REQUIRED) + +project(awesome_log_test) +add_executable( + ${PROJECT_NAME} + ./test/test_scoped_log.cpp +) + +set_property( + TARGET ${PROJECT_NAME} + PROPERTY CXX_STANDARD 20 +) + +target_link_libraries( + ${PROJECT_NAME} + PUBLIC + awesome_log + GTest::gtest_main + GTest::gmock +) + +add_test( + NAME ${PROJECT_NAME} + COMMAND ${PROJECT_NAME} +) + diff --git a/src/awesome_log/include/awesome_log/console_writer.hpp b/src/awesome_log/include/awesome_log/console_writer.hpp new file mode 100644 index 0000000..4470678 --- /dev/null +++ b/src/awesome_log/include/awesome_log/console_writer.hpp @@ -0,0 +1,14 @@ + +#pragma once + +#include "writer_interface.hpp" + +namespace awesome_log +{ +class console_writer : public writer_interface +{ + public: + ~console_writer() override; + void log(std::string_view msg) override; +}; +} // namespace awesome_log diff --git a/src/awesome_log/include/awesome_log/log.hpp b/src/awesome_log/include/awesome_log/log.hpp new file mode 100644 index 0000000..d43d4b3 --- /dev/null +++ b/src/awesome_log/include/awesome_log/log.hpp @@ -0,0 +1,12 @@ + +#pragma once + +#include + +namespace awesome_log +{ +class writer_interface; + +writer_interface& get_writer(); +void set_writer(const std::shared_ptr& writer); +} // namespace awesome_log \ No newline at end of file diff --git a/src/awesome_log/include/awesome_log/null_writer.hpp b/src/awesome_log/include/awesome_log/null_writer.hpp new file mode 100644 index 0000000..88c033a --- /dev/null +++ b/src/awesome_log/include/awesome_log/null_writer.hpp @@ -0,0 +1,14 @@ + +#pragma once + +#include "writer_interface.hpp" + +namespace awesome_log +{ +class null_writer : public writer_interface +{ + public: + ~null_writer() override; + void log(std::string_view msg) override; +}; +} // namespace awesome_log diff --git a/src/awesome_log/include/awesome_log/scoped_log.hpp b/src/awesome_log/include/awesome_log/scoped_log.hpp new file mode 100644 index 0000000..445e959 --- /dev/null +++ b/src/awesome_log/include/awesome_log/scoped_log.hpp @@ -0,0 +1,27 @@ + +#pragma once + +#include +#include + +namespace awesome_log +{ +class scoped_log +{ + public: + scoped_log(std::string_view msg); + ~scoped_log(); + + scoped_log() = delete; + + // No copying or moving allowed. + scoped_log(const scoped_log&) = delete; + scoped_log(scoped_log&&) = delete; + scoped_log& operator=(const scoped_log&) = delete; + scoped_log& operator=(scoped_log&&) = delete; + + private: + std::string m_msg; + int m_uncaught_exceptions; +}; +} // namespace awesome_log \ No newline at end of file diff --git a/src/awesome_log/include/awesome_log/writer_interface.hpp b/src/awesome_log/include/awesome_log/writer_interface.hpp new file mode 100644 index 0000000..667229f --- /dev/null +++ b/src/awesome_log/include/awesome_log/writer_interface.hpp @@ -0,0 +1,15 @@ + +#pragma once + +#include + +namespace awesome_log +{ +class writer_interface +{ + public: + virtual ~writer_interface() = default; + + virtual void log(std::string_view msg) = 0; +}; +} // namespace awesome_log diff --git a/src/awesome_log/src/console_writer.cpp b/src/awesome_log/src/console_writer.cpp new file mode 100644 index 0000000..9d6a221 --- /dev/null +++ b/src/awesome_log/src/console_writer.cpp @@ -0,0 +1,12 @@ + +#include +#include + +using namespace awesome_log; + +console_writer::~console_writer() = default; + +void console_writer::log(std::string_view msg) +{ + std::cout << msg << std::endl; +} diff --git a/src/awesome_log/src/log.cpp b/src/awesome_log/src/log.cpp new file mode 100644 index 0000000..370e515 --- /dev/null +++ b/src/awesome_log/src/log.cpp @@ -0,0 +1,23 @@ +#include +#include + +using awesome_log::writer_interface; + +namespace +{ +std::shared_ptr g_instance; +} + +writer_interface& awesome_log::get_writer() +{ + if (!g_instance) + { + g_instance = std::make_shared(); + } + return *g_instance; +} + +void awesome_log::set_writer(const std::shared_ptr& writer) +{ + g_instance = writer; +} diff --git a/src/awesome_log/src/null_writer.cpp b/src/awesome_log/src/null_writer.cpp new file mode 100644 index 0000000..32da4f7 --- /dev/null +++ b/src/awesome_log/src/null_writer.cpp @@ -0,0 +1,10 @@ + +#include + +using namespace awesome_log; + +null_writer::~null_writer() = default; + +void null_writer::log(std::string_view) +{ +} diff --git a/src/awesome_log/src/scoped_log.cpp b/src/awesome_log/src/scoped_log.cpp new file mode 100644 index 0000000..ac40eb4 --- /dev/null +++ b/src/awesome_log/src/scoped_log.cpp @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include + +using namespace awesome_log; + +scoped_log::scoped_log(std::string_view msg) + : m_msg(msg) + , m_uncaught_exceptions(std::uncaught_exceptions()) +{ + std::stringstream ss; + ss << "> " << m_msg; + + get_writer().log(ss.str()); +} + +scoped_log::~scoped_log() +{ + bool is_stack_unwinding = (m_uncaught_exceptions != std::uncaught_exceptions()); + + std::stringstream ss; + ss << "< " << m_msg; + + if (is_stack_unwinding) + { + ss << " (stack unwinding)"; + } + + get_writer().log(ss.str()); +} diff --git a/src/awesome_log/test/mock_writer.hpp b/src/awesome_log/test/mock_writer.hpp new file mode 100644 index 0000000..aceeef4 --- /dev/null +++ b/src/awesome_log/test/mock_writer.hpp @@ -0,0 +1,13 @@ + +#pragma once + +#include +#include + +class mock_writer : public awesome_log::writer_interface +{ + public: + ~mock_writer() override = default; + + MOCK_METHOD(void, log, (std::string_view), (override)); +}; \ No newline at end of file diff --git a/src/awesome_log/test/test_scoped_log.cpp b/src/awesome_log/test/test_scoped_log.cpp new file mode 100644 index 0000000..806198a --- /dev/null +++ b/src/awesome_log/test/test_scoped_log.cpp @@ -0,0 +1,47 @@ +#include "mock_writer.hpp" +#include +#include +#include +#include +#include + +class test_scoped_log : public ::testing::Test +{ + public: + void SetUp() override + { + m_writer = std::make_shared(); + awesome_log::set_writer(m_writer); + } + + void TearDown() override { awesome_log::set_writer(std::shared_ptr()); } + + protected: + std::shared_ptr m_writer; +}; + +TEST_F(test_scoped_log, log_normal_flow) +{ + EXPECT_CALL(*m_writer, log("> log")); + EXPECT_CALL(*m_writer, log("< log")); + + { + awesome_log::scoped_log a("log"); + } +} + +TEST_F(test_scoped_log, log_stack_unwind) +{ + EXPECT_CALL(*m_writer, log("> log")); + EXPECT_CALL(*m_writer, log("< log (stack unwinding)")); + + try + { + awesome_log::scoped_log a("log"); + throw std::runtime_error(""); + } + catch (const std::exception& e) + { + // Not doing anything + } +} \ No newline at end of file diff --git a/src/example_boost/CMakeLists.txt b/src/example_boost/CMakeLists.txt index f8133ed..76cf0e1 100644 --- a/src/example_boost/CMakeLists.txt +++ b/src/example_boost/CMakeLists.txt @@ -2,18 +2,16 @@ cmake_minimum_required(VERSION 3.20) find_package(Boost 1.88.0 REQUIRED COMPONENTS serialization) -project(hello_world_boost) +project(example_boost) add_executable( ${PROJECT_NAME} ./src/main.cpp ) - set_property( TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20 ) - target_link_libraries( ${PROJECT_NAME} Boost::serialization diff --git a/src/example_boost/src/main.cpp b/src/example_boost/src/main.cpp index d17a699..5cf33dc 100644 --- a/src/example_boost/src/main.cpp +++ b/src/example_boost/src/main.cpp @@ -1,31 +1,27 @@ -#include -#include -#include #include +#include +#include +#include struct position { - double x; - double y; + int x; + int y; template - void serialize(Archive & ar, const unsigned int /*version*/) + void serialize(Archive& ar, const unsigned int /*version*/) { ar & x; ar & y; } - bool operator==(const position& rhs) const - { - return x == rhs.x - && y == rhs.y; - } + bool operator==(const position& rhs) const { return x == rhs.x && y == rhs.y; } }; int main(int argc, char* argv[]) { - position myposition{.x=123.0, .y=456.0}; + position myposition{.x = 123, .y = 456}; std::stringstream ss; { @@ -44,5 +40,4 @@ int main(int argc, char* argv[]) { std::cout << "positions are the same" << std::endl; } - } \ No newline at end of file diff --git a/src/hello_world/CMakeLists.txt b/src/hello_world/CMakeLists.txt new file mode 100644 index 0000000..4925946 --- /dev/null +++ b/src/hello_world/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.20) + +project(hello_world) + +add_executable( + ${PROJECT_NAME} + src/main.cpp +) + +set_property( + TARGET ${PROJECT_NAME} + PROPERTY CXX_STANDARD 20 +) diff --git a/src/hello_world/src/main.cpp b/src/hello_world/src/main.cpp new file mode 100644 index 0000000..13c5192 --- /dev/null +++ b/src/hello_world/src/main.cpp @@ -0,0 +1,7 @@ + +#include + +int main(int argc, char* argv[]) +{ + std::cout << "Hello world" << std::endl; +} \ No newline at end of file diff --git a/src/hello_world_awesome/CMakeLists.txt b/src/hello_world_awesome/CMakeLists.txt new file mode 100644 index 0000000..d9464e7 --- /dev/null +++ b/src/hello_world_awesome/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.20) + +project(hello_world_awesome) + +add_executable( + ${PROJECT_NAME} + src/main.cpp +) + +target_link_libraries( + ${PROJECT_NAME} + awesome_log +) + +set_property( + TARGET ${PROJECT_NAME} + PROPERTY CXX_STANDARD 20 +) diff --git a/src/hello_world_awesome/src/main.cpp b/src/hello_world_awesome/src/main.cpp new file mode 100644 index 0000000..4470aa0 --- /dev/null +++ b/src/hello_world_awesome/src/main.cpp @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include + +using awesome_log::scoped_log; + +int main(int argc, char* argv[]) +{ + awesome_log::set_writer(std::make_shared()); + + { + scoped_log scoped("main.cpp, printing text"); + std::cout << "Hello world" << std::endl; + } + + try + { + scoped_log scoped("main.cpp, playing with exceptions"); + throw std::runtime_error("Let's play!"); + // ... unreachable code goes here. + } + catch (const std::exception& e) + { + std::cout << "Caught an exception, as expected in this example" << std::endl; + } +} \ No newline at end of file