diff --git a/.nojekyll b/.nojekyll
new file mode 100644
index 0000000..e69de29
diff --git a/_downloads/1e955aa7952605b36c4491740042f7a7/environment.yml b/_downloads/1e955aa7952605b36c4491740042f7a7/environment.yml
new file mode 100644
index 0000000..4e10bd7
--- /dev/null
+++ b/_downloads/1e955aa7952605b36c4491740042f7a7/environment.yml
@@ -0,0 +1,15 @@
+name: intro-to-cmake
+channels:
+ - conda-forge
+dependencies:
+ - cffi
+ - cmake >=3.18
+ - compilers
+ - graphviz
+ - libblas
+ - liblapack
+ - libuuid
+ - openmpi
+ - ninja
+ - pkg-config
+ - python >=3.8
diff --git a/_images/build-systems.svg b/_images/build-systems.svg
new file mode 100644
index 0000000..67b66a7
--- /dev/null
+++ b/_images/build-systems.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/_images/cmake-times.jpg b/_images/cmake-times.jpg
new file mode 100644
index 0000000..8803635
Binary files /dev/null and b/_images/cmake-times.jpg differ
diff --git a/_images/graphviz-greeting-hello-world.svg b/_images/graphviz-greeting-hello-world.svg
new file mode 100644
index 0000000..669ffbf
--- /dev/null
+++ b/_images/graphviz-greeting-hello-world.svg
@@ -0,0 +1,145 @@
+
+
+
+
+
diff --git a/_images/graphviz-multiple-folder-project.svg b/_images/graphviz-multiple-folder-project.svg
new file mode 100644
index 0000000..0879757
--- /dev/null
+++ b/_images/graphviz-multiple-folder-project.svg
@@ -0,0 +1,169 @@
+
+
+
+
+
diff --git a/_images/target.svg b/_images/target.svg
new file mode 100644
index 0000000..59616e3
--- /dev/null
+++ b/_images/target.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/_images/target_inheritance.svg b/_images/target_inheritance.svg
new file mode 100644
index 0000000..be4fe8c
--- /dev/null
+++ b/_images/target_inheritance.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/_images/visibility-levels.png b/_images/visibility-levels.png
new file mode 100644
index 0000000..c9ceffc
Binary files /dev/null and b/_images/visibility-levels.png differ
diff --git a/_sources/additional-topics.rst.txt b/_sources/additional-topics.rst.txt
new file mode 100644
index 0000000..ce15d16
--- /dev/null
+++ b/_sources/additional-topics.rst.txt
@@ -0,0 +1,62 @@
+.. _additional-topics:
+
+
+
+Additional Topics
+=================
+
+
+.. objectives::
+
+ - Additional topics for CMake workshop.
+ - A short summary of what we have learned.
+
+
+
+Additional topics
+-----------------
+
+In addition to the contents covered in this ``Intro to CMake``, there are additional topics and advanced features of the CMake build system that may be of use on projects as they get larger. This is far from a comprehensive list, and information related to unlisted tasks may be found on official CMake documentation.
+
+These topics include:
+
+- `Creating and running tests with CTest `_.
+- `Automated dependency handling with FetchContent `_.
+- `Mixing C++ and Fortran `_.
+- `Mixing Python and compiled languages `_.
+- `Detecting your environment `_.
+
+
+
+Resources and books
+-------------------
+
+
+There are many free resources online regarding CMake:
+
+- The `CMake official documentation
+ `_.
+- The `CMake tutorial `_.
+- The `HEP Software Foundation `_ training course.
+- `An Introduction to Modern CMake `_.
+
+
+You can also consult the following books:
+
+- **Professional CMake: A Practical Guide** by Craig Scott.
+- **CMake Cookbook** by Radovan Bast and Roberto Di Remigio. The accompanying repository is on `GitHub `_.
+
+
+
+Summary of `Intro to CMake`
+---------------------------
+
+.. keypoints::
+
+ - CMake is a powerful cross-platform build systems generator.
+ - CMake provides a very good reference-style documentation.
+ - For larger projects you probably want to write a lightweight scaffold around CMake.
+ - Many projects use CMake in other words you are not alone if you look for a solution.
+ - `Stack Overflow `_ and `GitHub repositories `_ are a good resource for solutions.
+
+
diff --git a/_sources/cmake-syntax.rst.txt b/_sources/cmake-syntax.rst.txt
new file mode 100644
index 0000000..155fb9b
--- /dev/null
+++ b/_sources/cmake-syntax.rst.txt
@@ -0,0 +1,310 @@
+.. _cmake-syntax:
+
+
+CMake syntax
+============
+
+
+.. questions::
+
+ - How can we achieve more control over the build system generated by CMake?
+ - Is it possible to let the user decide what to generate?
+
+
+.. objectives::
+
+ - Learn how to define variables with ``set`` and use them with the ``${}`` operator for `variable references `_.
+ - Learn the syntax for conditionals in CMake: ``if`` - ``elseif`` - ``else`` - ``endif``.
+ - Learn the syntax for loops in CMake: ``foreach``.
+ - Learn how CMake structures build artifacts.
+ - Learn how to print helpful messages.
+ - Learn how to handle user-facing options: ``option`` and the role of CMake cache.
+
+
+CMake offers a **domain-specific language** (DSL) to describe how to generate a build system native to the specific platform you might be running on. In this episode, we will get acquainted with its syntax.
+
+
+The CMake DSL
+-------------
+
+
+Remember that the DSL is **case-insensitive**. We will now have a look at its main elements.
+
+
+
+Variables
++++++++++
+
+
+These are either CMake- or user-defined variables. You can obtain the list of CMake-defined variables with the command:
+
+.. code-block:: bash
+
+ $ cmake --help-variable-list
+
+You can create a new variable with the ``set`` command:
+
+.. signature:: ``set``
+
+ .. code-block:: cmake
+
+ set(... [PARENT_SCOPE])
+
+
+Variables in CMake are always of string type, but certain commands can interpret them as other types. If you want to declare a *list* variable, you will have to provide it as a ;-separated string. Lists can be manipulated with the ``list`` family of commands.
+
+You can inspect the value of any variable by *dereferencing* it with the ``${}`` operator, as in bash shell. For example, the following snippet sets the content of ``hello`` variable and then prints it:
+
+.. code-block:: cmake
+
+ set(hello "world")
+ message("hello ${hello}")
+
+
+Two notes about **variable references**:
+
+- if the variable within the ``${}`` operator is not set, you will get an empty string.
+- you can *nest* variable references: ``${outer_${inner_variable}_variable}``. They will be evaluated from the inside out.
+
+
+One of the most confusing aspects in CMake is the **scoping of variables**. There are three variable scopes in the DSL:
+
+- **Function**: In effect when a variable is ``set`` within a function, the variable will be visible within the function, but not outside.
+- **Directory**: In effect when processing a ``CMakeLists.txt`` in a directory, variables in the parent folder will be available, but any that is ``set`` in the current folder will not be propagated to the parent.
+- **Cache**: These variables are **persistent** across calls to ``cmake`` and available to all scopes in the project. Modifying a cache variable requires using a special form of the ``set`` function:
+
+ .. signature:: ``set``
+
+ .. code-block:: cmake
+
+ set(... CACHE [FORCE])
+
+
+Here is a list of few **CMake-defined variables**:
+
+- ``PROJECT_BINARY_DIR``. This is the build folder for the project.
+- ``PROJECT_SOURCE_DIR``. This is the location of the root ``CMakeLists.txt`` in the project.
+- ``CMAKE_CURRENT_LIST_DIR``. This is the folder for the ``CMakeLists.txt`` currently being processed.
+
+Help on a specific built-in variable can be obtained with:
+
+.. code-block:: bash
+
+ $ cmake --help-variable PROJECT_BINARY_DIR
+
+
+
+Commands
+++++++++
+
+
+These are provided by CMake and are essential building blocks of the DSL, as they allow you to manipulate variables. They include control flow constructs and the ``target_*`` family of commands.
+
+You can find a complete list of available commands with:
+
+.. code-block:: bash
+
+ $ cmake --help-command-list
+
+
+**Functions** and **macros** are built on top of the basic built-in commands and are either CMake- or user-defined. These prove useful to avoid repetition in your CMake scripts.
+
+The difference between a function and a macro is their *scope*:
+
+- **Functions** have their own scope: variables defined inside a function are not propagated back to the caller.
+- **Macros** do not have their own scope: variables from the parent scope can be modified and new variables in the parent scope can be set.
+
+
+Help on a specific built-in command, function or macro can be obtained with:
+
+.. code-block:: bash
+
+ $ cmake --help-command target_link_libraries
+
+
+
+Modules
++++++++
+
+
+These are collections of functions and macros and are either CMake- or user-defined. CMake comes with a rich ecosystem of modules and you will probably write a few of your own to encapulate frequently used functions or macros in your CMake scripts.
+
+You will have to include the module to use its contents, for example:
+
+.. code-block:: cmake
+
+ include(CMakePrintHelpers)
+
+
+The full list of built-in modules is available with:
+
+.. code-block:: bash
+
+ $ cmake --help-module-list
+
+Help on a specific built-in module can be obtained with:
+
+.. code-block:: bash
+
+ $ cmake --help-module CMakePrintHelpers
+
+
+
+Flow control
+------------
+
+
+The ``if`` and ``foreach`` commands are available as flow control constructs in the CMake DSL and you are surely familiar with their use in other programming languages.
+
+Since *all* variables in CMake are strings, the syntax for ``if`` and ``foreach`` appears in a few different variants.
+
+.. signature:: ``if``
+
+ .. code-block:: cmake
+
+ if()
+ #
+ elseif() # optional block, can be repeated
+ #
+ else() # optional block
+ #
+ endif()
+
+The truth value of the conditions in the ``if`` and ``elseif`` blocks is determined by boolean operators. In the CMake DSL:
+
+- True is any expression evaluating to: ``1``, ``ON``, ``TRUE``, ``YES``, and ``Y``.
+- False is any expression evaluating to: ``0``, ``OFF``, ``FALSE``, ``NO``, ``N``, ``IGNORE``, and ``NOTFOUND``.
+
+
+CMake offers boolean operator for string comparisons, such as ``STREQUAL`` for string equality, and for version comparisons, such as ``VERSION_EQUAL``.
+
+
+.. callout:: Variable expansions in conditionals
+
+ The ``if`` command expands the contents of variables before evaluating their truth value. See `official documentation `_ for further details.
+
+
+.. exercise:: Exercise 2: Conditionals in CMake
+
+ Modify the ``CMakeLists.txt`` from the previous exercise to build either a *static* or a *shared* library depending on the value of the boolean ``MAKE_SHARED_LIBRARY``:
+
+ 1. Define the ``MAKE_SHARED_LIBRARY`` variable.
+ 2. Write a conditional checking the variable. In each branch call ``add_library`` appropriately.
+
+ .. tabs::
+
+ .. tab:: C++
+
+ You can find a scaffold project in the ``content/code/02_conditionals-cxx`` folder. A working solution is in the ``solution`` subfolder.
+
+ .. tab:: Fortran
+
+ You can find a scaffold project in the ``content/code/02_conditionals-f`` folder. A working solution is in the ``solution`` subfolder.
+
+
+You can perform the same operation on a collection of items with ``foreach``:
+
+.. signature:: ``foreach``
+
+ .. code-block:: cmake
+
+ foreach()
+ #
+ endforeach()
+
+The list of items is either space- or ;-separated. ``break()`` and ``continue()`` are also available.
+
+
+.. typealong:: Loops in CMake
+
+ In this typealong, we will show how to use ``foreach`` and lists in CMake. We will work from a scaffold project in the ``content/code/03_loops-cxx`` folder.
+
+ The goal is to compile a library from a bunch of source files: some of them are to be compiled with ``-O3`` optimization level, while some others with ``-O2``. We will set the compilation flags as properties on the library target. Targets and properties will be discussed at greater length in :ref:`targets`.
+
+ A working solution is in the ``solution`` subfolder.
+
+ It is instructive to browse the build folder for the project:
+
+ .. code-block:: bash
+
+ $ tree -L 2 build
+
+ build
+ ├── CMakeCache.txt
+ ├── CMakeFiles
+ │ ├── 3.18.4
+ │ ├── cmake.check_cache
+ │ ├── CMakeDirectoryInformation.cmake
+ │ ├── CMakeOutput.log
+ │ ├── CMakeTmp
+ │ ├── compute-areas.dir
+ │ ├── geometry.dir
+ │ ├── Makefile2
+ │ ├── Makefile.cmake
+ │ ├── progress.marks
+ │ └── TargetDirectories.txt
+ ├── cmake_install.cmake
+ ├── compute-areas
+ ├── libgeometry.a
+ └── Makefile
+
+ We note that:
+
+ - The project was configured with ``Makefile`` generator.
+ - The cache is a plain-text file ``CMakeCache.txt``.
+ - For every target in the project, CMake will create a subfolder ``.dir`` under ``CMakeFiles``. The intermediate object files are stored in these folders, together with compiler flags and link line.
+ - The build artifacts, ``compute-areas`` and ``libgeometry.a``, are stored at the root of the build tree.
+
+
+
+Printing messages
+-----------------
+
+You will most likely have to engage in debugging your CMake scripts at some point. Print-based debugging is the most effective way and the main workhorse for this will be the ``message`` command:
+
+.. signature:: ``message``
+
+ .. code-block:: cmake
+
+ message([] "message to display")
+
+.. parameters::
+
+ ````
+ What type of message to display, for example:
+
+ - ``STATUS``, for incidental information.
+ - ``FATAL_ERROR``, to report an error that prevents further processing and generation.
+
+
+It should be noted that ``message`` can be a bit awkward to work with, especially when you want to print the name *and* value of a variable. Including the built-in module ``CMakePrintHelpers`` will make your life easier when debugging, since it provides the ``cmake_print_variables`` function:
+
+.. signature:: ``cmake_print_variables``
+
+ .. code-block:: cmake
+
+ cmake_print_variables(var1 var2 ... varN)
+
+ This command accepts an arbitrary number of variables and prints their name *and* value to standard output.
+ For example:
+
+ .. code-block:: cmake
+
+ include(CMakePrintHelpers)
+ cmake_print_variables(CMAKE_C_COMPILER CMAKE_MAJOR_VERSION DOES_NOT_EXIST)
+
+ gives:
+
+ .. code-block:: text
+
+ -- CMAKE_C_COMPILER="/usr/bin/gcc" ; CMAKE_MAJOR_VERSION="2" ; DOES_NOT_EXIST=""
+
+
+
+.. keypoints::
+
+ - CMake offers a full-fledged DSL which empowers you to write complex ``CMakeLists.txt``.
+ - Variables have scoping rules.
+ - The structure of the project is mirrored in the build folder.
+
+
diff --git a/_sources/dependencies.rst.txt b/_sources/dependencies.rst.txt
new file mode 100644
index 0000000..4bd6fd3
--- /dev/null
+++ b/_sources/dependencies.rst.txt
@@ -0,0 +1,210 @@
+.. _dependencies:
+
+
+Finding and using dependencies
+==============================
+
+.. questions::
+
+ - How can I use CMake to detect and use the dependencies of my project?
+
+.. objectives::
+
+ - Learn how to use ``find_package``.
+ - Learn what other detection alternatives exist.
+
+The vast majority of software projects do not happen in a vacuum: they will have
+dependencies on existing frameworks and libraries. Good documentation will
+instruct your users to ensure that these are satisfied in their programming
+environment. The build system is the appropriate place to check that these
+preconditions are met and that your project can be built correctly.
+In this episode, we will show you few examples of how to detect and use
+dependencies in your CMake build system.
+
+Finding dependencies
+--------------------
+
+CMake offers a family of commands to find artifacts installed on your system:
+
+- ``find_file`` to retrieve the full path to a file.
+- ``find_library`` to find a library, shared or static.
+- ``find_package`` to find and load settings from an external project.
+- ``find_path`` to find the directory containing a file.
+- ``find_program`` to find an executable.
+
+The workhorse of dependency discovery is ``find_package``, which will cover your
+needs in almost all use cases.
+
+.. signature:: `find_package `_
+
+ .. code-block:: cmake
+
+ find_package( [version] [EXACT] [QUIET] [MODULE]
+ [REQUIRED] [[COMPONENTS] [components...]]
+ [OPTIONAL_COMPONENTS components...]
+ [NO_POLICY_SCOPE])
+
+ This command will attempt finding the package with name ```` by
+ searching in a number of `predefined folders
+ `_.
+ It is possible to ask for a minimum or exact version. If ``REQUIRED`` is
+ given, a failed search will trigger a fatal error. The rules for the search
+ are obtained from modules named ``Find.cmake``.
+ Packages can also have *components* and you can ask to detect just a handful of them.
+
+
+We cannot stress this enough: you should **only** use the other commands in the
+``find_`` family in very special, very narrow circumstances. Why so?
+
+1. For a large selection of common dependencies, the ``Find.cmake``
+ modules shipped with CMake work flawlessly and are maintained by the CMake
+ developers. This lifts the burden of programming your own dependency
+ detection tricks.
+2. ``find_package`` will set up **imported targets**: targets defined *outside*
+ your project that you can use with your own targets. The properties on
+ imported targets defines *usage requirements* for the dependencies. A command
+ such as:
+
+ .. code-block:: cmake
+
+ target_link_libraries(your-target
+ PUBLIC
+ imported-target
+ )
+
+ will set compiler flags, definitions, include directories, and link libraries
+ from ``imported-target`` to ``your-target`` *and* to all other targets in
+ your project that will use ``your-target``.
+
+
+These two points simplify **enormously** the burden of dependency detection and
+consistent usage within a multi-folder project.
+
+
+Using ``find_package``
+++++++++++++++++++++++
+
+When attempting dependency detection with ``find_package``, you should make sure that:
+
+- A ``Find.cmake`` module exists,
+- Which components, if any, it provides, and
+- What imported targets it will set up.
+
+A complete list of ``Find.cmake`` can be found from the command-line interface:
+
+.. code-block:: bash
+
+ $ cmake --help-module-list | grep "Find"
+
+.. typealong:: Using OpenMP
+
+ We want to compile the following OpenMP sample code: [#omp]_
+
+ .. literalinclude:: code/09_taskloop/solution/taskloop.cpp
+ :language: c++
+
+ Note the usage of the ``taskloop`` construct, which was introduced in OpenMP
+ 4.5: we need to make sure our C++ compiler is suitably compatible with *at
+ least* that version of the standard.
+
+ From the documentation of the ``FindOpenMP.cmake`` module:
+
+ .. code-block:: bash
+
+ $ cmake --help-module FindOpenMP | less
+
+ we find that the module provides the components ``C``, ``CXX``, and
+ ``Fortran`` and that ``OpenMP::OpenMP_CXX`` target will be provided, if
+ detection is successful.
+ Thus, we do the following:
+
+ .. code-block:: cmake
+
+ find_package(OpenMP 4.5 REQUIRED COMPONENTS CXX)
+
+ target_link_libraries(task-loop PRIVATE OpenMP::OpenMP_CXX)
+
+ We can configure and build verbosely. [#verbose]_
+ Notice that compiler flags, include directories, and link libraries are properly resolved by CMake.
+
+ You can find the complete working example in ``content/code/10_taskloop/solution``.
+
+.. exercise:: Exercise 11: Using MPI
+
+ In this exercise, you will attempt compiling a "Hello, world" program that
+ uses the message passing interface (MPI).
+
+ 1. Check whether a ``FindMPI.cmake`` module exists in the built-in module
+ library.
+ 2. Get acquainted with its components and the variables and imported targets
+ it defines.
+
+ .. tabs::
+
+ .. tab:: C++
+
+ The scaffold project is in ``content/code/11_mpi-cxx``.
+
+ #. Compile the source file to an executable.
+ #. Link against the MPI imported target.
+ #. Invoke a verbose build and observe how CMake compiles and links.
+
+ A working example is in the ``solution`` subfolder.
+
+ .. tab:: Fortran
+
+ The scaffold project is in ``content/code/11_mpi-f``.
+
+ #. Compile the source file to an executable.
+ #. Link against the MPI imported target.
+ #. Invoke a verbose build and observe how CMake compiles and links.
+
+ A working example is in the ``solution`` subfolder.
+
+
+Alternatives: ``Config`` scripts and ``pkg-config``
++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+What to do when there is no built-in ``Find.cmake`` module for a package you depend on?
+The package developers might be already prepared to help you out:
+
+- They ship the CMake-specific file ``Config.cmake`` which
+ describes how the imported target should be made for their package.
+ In this case, you need to point CMake to the folder containing the ``Config`` file using the
+ special ``_DIR`` variable:
+
+ .. code-block:: bash
+
+ $ cmake -S. -Bbuild -D_DIR=/folder/containing/Config.cmake
+
+- They include a ``.pc`` file, which, on Unix-like platforms, can be detected
+ with the ``pkg-config`` utility. You can then leverage ``pkg-config`` through CMake:
+
+ .. code-block:: cmake
+
+ # find pkg-config
+ find_package(PkgConfig REQUIRED)
+ # ask pkg-config to find the UUID library and prepare an imported target
+ pkg_search_module(UUID REQUIRED uuid IMPORTED_TARGET)
+ # use the imported target
+ if(TARGET PkgConfig::UUID)
+ message(STATUS "Found libuuid")
+ endif()
+
+ This was the strategy adopted in :ref:`probing` when testing the use of the UUID library.
+
+
+.. keypoints::
+
+ - CMake has a rich ecosystem of modules for finding software dependencies. They are called ``Find.cmake``.
+ - The ``Find.cmake`` modules are used through ``find_package()``.
+ - You can also use the classic Unix tool ``pkg-config`` to find software dependencies, but this is not as robust as the CMake-native ``Find`` modules.
+
+
+
+.. rubric:: Footnotes
+
+
+.. [#omp] Example adapted from page 85 in `OpenMP 4.5 examples `_.
+
+.. [#verbose] The way in which to trigger a verbose build depends on the native build tool you are using. For Unix Makefiles: ``$ cmake --build build -- VERBOSE=1``, and for Ninja: ``$ cmake --build build -- -v``.
diff --git a/_sources/guide.rst.txt b/_sources/guide.rst.txt
new file mode 100644
index 0000000..89553fb
--- /dev/null
+++ b/_sources/guide.rst.txt
@@ -0,0 +1,37 @@
+Instructor's guide
+==================
+
+Why we teach this lesson
+------------------------
+
+
+
+Intended learning outcomes
+--------------------------
+
+
+
+Timing
+------
+
+
+
+Preparing exercises
+-------------------
+
+e.g. what to do the day before to set up common repositories.
+
+
+
+Other practical aspects
+-----------------------
+
+
+
+Interesting questions you might get
+-----------------------------------
+
+
+
+Typical pitfalls
+----------------
diff --git a/_sources/hello-cmake.rst.txt b/_sources/hello-cmake.rst.txt
new file mode 100644
index 0000000..f8e11b8
--- /dev/null
+++ b/_sources/hello-cmake.rst.txt
@@ -0,0 +1,311 @@
+.. _hello-cmake:
+
+
+From sources to executables
+===========================
+
+.. questions::
+
+ - How do we use CMake to compile source files to executables?
+
+.. objectives::
+
+ - Learn what tools are available in the CMake suite.
+ - Learn how to write a simple ``CMakeLists.txt``.
+ - Learn the difference between **build systems**, **build tools**, and **build system generator**.
+ - Learn to distinguish between *configuration*, *generation*, and **build* time.
+
+
+
+What is CMake and why should you care?
+--------------------------------------
+
+Software is everywhere and so are build systems. Whenever you run a piece of software, anything from calendar apps to computationally-intensive programs, there was a build system involved in transforming the plain-text source code into binary files that could run on the device you are using.
+
+CMake is a **build-system generator**: it provides a family of tools and a *domain-specific language* (DSL) to **describe** what the build system should achieve when the appropriate build tools are invoked. The DSL is platform- *and* compiler-agnostic: you can reuse the same CMake scripts to obtain **native** build systems on any platform.
+
+
+.. figure:: img/build-systems.svg
+ :align: center
+
+ On GNU/Linux, the native build system will be a collection of ``Makefile``-s. The ``make`` build tool uses these ``Makefile``-s to transform sources to executables and libraries.
+
+ CMake abstracts the process of generating the ``Makefile``-s away into a generic DSL.
+
+
+A CMake-based build system:
+
+- can bring your software closer to being platform- *and* compiler-agnostic.
+- has good support within many integrated development environments (IDEs).
+- automatically tracks and propagates internal dependencies in your project.
+- is built on top of well-maintained functionality for automated dependency detection.
+
+
+
+Hello, CMake!
+-------------
+
+
+.. typealong:: Compiling "Hello, world" with CMake
+
+ We will now proceed to compile a single source file to an executable. Choose your favorite language and start typing along!
+
+ .. tabs::
+
+ .. tab:: C++
+
+ You can find the file with the complete source code in the ``content/code/00_hello-world/cxx`` folder.
+
+ .. literalinclude:: code/00_hello-world/cxx/hello.cpp
+ :language: c++
+
+ A working solution is in the ``solution`` subfolder.
+
+ .. tab:: Fortran
+
+ You can find the file with the complete source code in the ``content/code/00_hello-world/fortran`` folder.
+
+ .. literalinclude:: code/00_hello-world/fortran/hello.f90
+ :language: fortran
+
+ A working solution is in the ``solution`` subfolder.
+
+ 1. The folder contains only the source code. We need to add a file called ``CMakeLists.txt`` to it. CMake reads the contents of these special files when generating the build system.
+
+ 2. The first thing we will do is declare the requirement on minimum version of CMake:
+
+ .. code-block:: cmake
+
+ cmake_minimum_required(VERSION 3.18)
+
+ 3. Next, we declare our project and its programming language:
+
+ .. code-block:: cmake
+
+ project(Hello LANGUAGES CXX)
+
+ 4. We create an *executable target*. CMake will generate rules in the build system to compile and link our source file into an executable:
+
+ .. code-block:: cmake
+
+ add_executable(hello hello.cpp)
+
+ 5. We are ready to call CMake and get our build system:
+
+ .. code-block:: bash
+
+ cmake -S. -Bbuild
+
+ 6. And finally build our executable:
+
+ .. code-block:: bash
+
+ cmake --build build
+
+
+
+Important issues for ``CMakeLists.txt`` file
+--------------------------------------------
+
+
+1. Any CMake build system will invoke the following commands in its **root** ``CMakeLists.txt``:
+
+ .. signature:: ``cmake_minimum_required``
+
+ .. code-block:: cmake
+
+ cmake_minimum_required(VERSION [...] [FATAL_ERROR])
+
+ .. parameters::
+
+ ``VERSION``: Minimum and, optionally, maximum version of CMake to use.
+
+ ``FATAL_ERROR``: Raise a fatal error if the version constraint is not satisfied. This option is ignored by CMake >=2.6
+
+ .. signature:: ``project``
+
+ .. code-block:: cmake
+
+ project(
+ [VERSION [.[.[.]]]]
+ [DESCRIPTION ]
+ [HOMEPAGE_URL ]
+ [LANGUAGES ...])
+
+ .. parameters::
+
+ ````: The name of the project.
+
+ ``LANGUAGES``: Languages in the project.
+
+
+2. The case of CMake commands does not matter: the DSL is case-insensitive. However, the plain-text files that CMake parses **must be called** ``CMakeLists.txt`` and the case matters! The variable names are also case sensitive!
+
+
+3. The command to add executables to the build system is ``add_executable``:
+
+ .. signature:: ``add_executable``
+
+ .. code-block:: cmake
+
+ add_executable( [WIN32] [MACOSX_BUNDLE]
+ [EXCLUDE_FROM_ALL]
+ [source1] [source2 ...])
+
+
+4. Using CMake you can abstract the generation of the build system and also the invocation of the build tools.
+
+
+.. callout:: Put your ``CMakeLists.txt`` under version control
+
+ All CMake-related files will evolve together with your codebase. It's a good idea to put them under version control. On the contrary, any of the *generated* native build-system files, *e.g.* ``Makefile``-s, should not be version-controlled.
+
+
+.. typealong:: The command-line interface to CMake
+
+ Let us get acquainted with the CMake and especially its command-line interface.
+
+ We can get help at any time with the command
+
+ .. code-block:: bash
+
+ cmake --help
+
+ This will output quite a number of options to your screen. We can analyze the last few lines first:
+
+ .. code-block:: text
+
+ Generators
+
+ The following generators are available on this platform (* marks default):
+ * Unix Makefiles = Generates standard UNIX makefiles.
+ Green Hills MULTI = Generates Green Hills MULTI files.
+ Ninja = Generates build.ninja files.
+ Ninja Multi-Config = Generates build-.ninja files.
+ Watcom WMake = Generates Watcom WMake makefiles.
+ CodeBlocks - Ninja = Generates CodeBlocks project files.
+ CodeBlocks - Unix Makefiles = Generates CodeBlocks project files.
+ CodeLite - Ninja = Generates CodeLite project files.
+ CodeLite - Unix Makefiles = Generates CodeLite project files.
+ Sublime Text 2 - Ninja = Generates Sublime Text 2 project files.
+ Sublime Text 2 - Unix Makefiles = Generates Sublime Text 2 project files.
+ Kate - Ninja = Generates Kate project files.
+ Kate - Unix Makefiles = Generates Kate project files.
+ Eclipse CDT4 - Ninja = Generates Eclipse CDT 4.0 project files.
+ Eclipse CDT4 - Unix Makefiles = Generates Eclipse CDT 4.0 project files.
+
+ In CMake terminology, the native build scripts and build tools are called **generators**. On any particular platform, the list will show which native build tools can be used through CMake. They can either be "plain", such as ``Makefile``-s or Ninja, or IDE-like projects.
+
+ The ``-S`` switch specifies which source directory CMake should scan: this is the folder containing the *root* ``CMakeLists.txt``, *i.e.*, the one containing the |project| command. By default, CMake will allow *in-source* builds, *i.e.* storing build artifacts alongside source files. This is **not** good practice: you should always keep build artifacts from sources separate. Fortunately, the ``-B`` switch helps with that, as it is used to give where to store build artifacts, including the generated build system. This is the minimal invocation of ``cmake``:
+
+ .. code-block:: bash
+
+ cmake -S. -Bbuild
+
+ To switch to another generator, we will use the ``-G`` switch (make sure that the Ninja is correctly built before running the command below):
+
+ .. code-block:: bash
+
+ cmake -S. -Bbuild -GNinja
+
+ Options to be used at build-system generation are passed with the ``-D`` switch. For example, to change compilers:
+
+ .. code-block:: bash
+
+ cmake -S. -Bbuild -GNinja -DCMAKE_CXX_COMPILER=clang++
+
+ Finally, you can access to the full CMake manual with:
+
+ .. code-block:: bash
+
+ cmake --help-full
+
+ You can also inquire about a specific module, command or variable:
+
+ .. code-block:: bash
+
+ cmake --help-variable CMAKE_GENERATOR
+
+
+
+A complete toolchain
+--------------------
+
+
+The family of tools provided with CMake offers a complete toolchain to manage the development cycle: from sources to build artifacts, testing, and deployment. We refer to these stages as *CMake times* and each tool is appropriate at a specific time. In this workshop, we will discuss:
+
+- **CMake time** or **configure time**. This is the stage when ``cmake`` is invoked to parse the ``CMakeLists.txt`` in your project, configure and generate the build system.
+- **Build time**. This is handled by the native build tools, but, as we have seen, these can be effectively wrapped by ``cmake`` itself.
+- **CTest time** or **test time**. At this stage, you will test your build artifacts.
+
+.. figure:: img/cmake-times.jpg
+ :align: center
+
+ You can manage all these stages of a software project's lifetime with tools provided by CMake. This figure shows all these stages (*times*) and which tool is appropriate for each. This figure is reproduced from `CMake Cookbook `_ and is licensed under the terms of the `CC-BY-SA `_.
+
+
+
+Producing libraries
+-------------------
+
+CMake can of course be used to produce libraries as well as executables. The relevant command is ``add_library``:
+
+.. signature:: ``add_library``
+
+ .. code-block:: cmake
+
+ add_library( [STATIC | SHARED | MODULE]
+ [EXCLUDE_FROM_ALL]
+ [