123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805 |
- Step 1: Getting Started with CMake
- ==================================
- This first step in the CMake tutorial is intended as a quick-start into writing
- useful builds for small projects with CMake. By the end, you will be able to
- describe executables, libraries, source and header files, and the linkage
- relationships between them using CMake.
- Each exercise in this step will start with a discussion of the concepts and
- commands needed for the exercise. Then, a goal and list of helpful resources are
- provided. Each file in the ``Files to Edit`` section is in the ``Step1``
- directory and contains one or more ``TODO`` comments. Each ``TODO`` represents
- a line or two of code to change or add. The ``TODOs`` are intended to be
- completed in numerical order, first complete ``TODO 1`` then ``TODO 2``, etc.
- .. note::
- Each step in the tutorial builds on the previous, but the steps are not
- strictly contiguous. Code not relevant to learning CMake, such as C++
- function implementations or CMake code outside the scope of the tutorial,
- will sometimes be added between steps.
- The ``Getting Started`` section will give some helpful hints and guide you
- through the exercise. Then the ``Build and Run`` section will walk step-by-step
- through how to build and test the exercise. Finally, at the end of each exercise
- the intended solution is reviewed.
- Background
- ^^^^^^^^^^
- Typical usage of CMake revolves around one or more files named
- ``CMakeLists.txt``. This file is sometimes referred to as a "lists file" or
- "CML". Within a given software project, a ``CMakeLists.txt`` will exist within
- any directory where we want to provide instructions to CMake on how to handle
- files and operations local to that directory or subdirectories. Each consists of
- a set of commands which describe some information or actions relevant to
- building the software project.
- Not every directory in a software project needs a CML, but it's strongly
- recommended that the project root contains one. This will serve as the entry
- point for CMake for its initial setup during configuration. This *root* CML
- should always contain the same two commands at or near the top the file.
- .. code-block:: cmake
- cmake_minimum_required(VERSION 3.23)
- project(MyProjectName)
- The :command:`cmake_minimum_required` is a compatibility guarantee provided by
- CMake to the project developer. When called, it ensures that CMake will adopt
- the behavior of the listed version. If a later version of CMake is invoked on a
- CML containing the above code, it will act exactly as if it were CMake 3.23.
- The :command:`project` command is a conceptually simple command which provides a
- complex function. It informs CMake that what follows is the description of a
- distinct software project of a given name (as opposed to a shell-like script).
- When CMake sees the :command:`project` command it performs various checks to
- ensure the environment is suitable for building software; such as checking for
- compilers and other build tooling, and discovering properties like the
- endianness of the host and target machines.
- .. note::
- While links to complete documentation are provided for every command, it is
- not intended the reader understand the full semantics of each CMake command
- they use. Effectively learning CMake, like any piece of software, is an
- incremental process.
- The rest of this tutorial step will be chiefly concerned with the usage of four
- more commands. The :command:`add_executable` and :command:`add_library` commands
- for describing output artifacts the software project wants to produce, the
- :command:`target_sources` command for associating input files with their
- respective output artifacts, and the :command:`target_link_libraries` command
- for associating output artifacts with one another.
- These four commands are the backbone of most CMake usage. As we'll learn, they
- are sufficient for describing the majority of a typical project's requirements.
- Exercise 1 - Building an Executable
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- The most basic CMake project is an executable built from a single source code
- file. For simple projects like this, a ``CMakeLists.txt`` file with only
- four commands is needed.
- .. note::
- Although upper, lower and mixed case commands are supported by CMake,
- lower case commands are preferred and will be used throughout the tutorial.
- The first two commands we have already introduced, :command:`cmake_minimum_required`
- and :command:`project`. There is no usage of CMake where the first command in a
- root CML will be anything other than :command:`cmake_minimum_required`. There
- are some advanced usages where :command:`project` might not be the second
- command in a CML, but for our purposes it always will be.
- The next command we need is :command:`add_executable`.
- This command creates a *target*. In CMake lingo, a target is a name the
- developer gives to a collection of properties.
- Some examples of properties a target might want to keep track of are:
- - The artifact kind (executable, library, header collection, etc)
- - Source files
- - Include directories
- - Output name of an executable or library
- - Dependencies
- - Compiler and linker flags
- The mechanisms of CMake are often best understood as describing and manipulating
- targets and their properties. There are many more properties than those listed
- here. Documentation of CMake commands will often discuss their function in terms
- of the target properties they operate on.
- Targets themselves are simply names, a handle to this collection of properties.
- Using the :command:`add_executable` command is as easy as specifying the name
- we want to use for the target.
- .. code-block:: cmake
- add_executable(MyProgram)
- Now that we have a name for our target, we can start associating properties
- with it like source files we want to build and link. The primary command for
- this is :command:`target_sources`, which takes as arguments a target name
- followed by one or more collections of files.
- .. code-block:: cmake
- target_sources(MyProgram
- PRIVATE
- main.cxx
- )
- .. note::
- Paths in CMake are generally either absolute, or relative to the
- :variable:`CMAKE_CURRENT_SOURCE_DIR`. We haven't talked about variables like
- that yet, so you can read this as "relative to the location of the current
- CML".
- Each collection of files is prefixed by a :ref:`scope keyword <Target Command Scope>`.
- We'll discuss the complete semantics of these keywords when we talk about
- linking targets together, but the quick explanation is these describe how a
- property should be inherited by dependents of our target.
- Typically, nothing depends on an executable. Other programs and libraries don't
- need to link to an executable, or inherit headers, or anything of that nature.
- So the appropriate scope to use here is ``PRIVATE``, which informs CMake that
- this property only belongs to ``MyProgram`` and is not inheritable.
- .. note::
- This rule is true almost everywhere. Outside advanced and esoteric usages,
- the scope keyword for executables should *always* be ``PRIVATE``. The same
- holds for implementation files generally, regardless of whether the target
- is an executable or a library. The only target which needs to "see" the
- ``.cxx`` files is the target building them.
- Goal
- ----
- Understand how to create a simple CMake project with a single executable.
- Helpful Resources
- -----------------
- * :command:`project`
- * :command:`cmake_minimum_required`
- * :command:`add_executable`
- * :command:`target_sources`
- Files to Edit
- -------------
- * ``CMakeLists.txt``
- Getting Started
- ----------------
- The source code for ``Tutorial.cxx`` is provided in the
- ``Help/guide/tutorial/Step1/Tutorial`` directory and can be used to compute the
- square root of a number. This file does not need to be edited in this exercise.
- In the parent directory, ``Help/guide/tutorial/Step1``, is a ``CMakeLists.txt``
- file which you will complete. Start with ``TODO 1`` and work through ``TODO 4``.
- Build and Run
- -------------
- Once ``TODO 1`` through ``TODO 4`` have been completed, we are ready to build
- and run our project! First, run the :manual:`cmake <cmake(1)>` executable or the
- :manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it
- with your chosen build tool.
- For example, from the command line we could navigate to the
- ``Help/guide/tutorial/Step1`` directory and invoke CMake for configuration
- as follows:
- .. code-block:: console
- cmake -B build
- The :option:`-B <cmake -B>` flag tells CMake to use the given relative
- path as the location to generate files and store artifacts during the build
- process. If it is omitted, the current working directory is used. It is
- generally considered bad practice to do "in-source" builds, placing these
- generated files in the source tree itself.
- Next, tell CMake to build the project with
- :option:`cmake --build <cmake --build>`, passing it the same relative path
- we did with the :option:`-B <cmake -B>` flag.
- .. code-block:: console
- cmake --build build
- The ``Tutorial`` executable will be built into the ``build`` directory. For
- multi-config generators (e.g. Visual Studio), it might be placed in a
- subdirectory such as ``build/Debug``.
- Finally, try to use the newly built ``Tutorial``:
- .. code-block:: console
- Tutorial 4294967296
- Tutorial 10
- Tutorial
- .. note::
- Depending on the shell, the correct syntax may be ``Tutorial``,
- ``./Tutorial``, ``.\Tutorial``, or even ``.\Tutorial.exe``. For simplicity,
- the exercises will use ``Tutorial`` throughout.
- Solution
- --------
- As mentioned above, a four command ``CMakeLists.txt`` is all that we need to get
- up and running. The first line should be :command:`cmake_minimum_required`, to
- set the CMake version as follows:
- .. raw:: html
- <details><summary>TODO 1: Click to show/hide answer</summary>
- .. literalinclude:: Step3/CMakeLists.txt
- :caption: TODO 1: CMakeLists.txt
- :name: CMakeLists.txt-cmake_minimum_required
- :language: cmake
- :start-at: cmake_minimum_required
- :end-at: cmake_minimum_required
- .. raw:: html
- </details>
- The next step to make a basic project is to use the :command:`project`
- command as follows to set the project name and inform CMake we intend to build
- software with this ``CMakeLists.txt``.
- .. raw:: html
- <details><summary>TODO 2: Click to show/hide answer</summary>
- .. literalinclude:: Step3/CMakeLists.txt
- :caption: TODO 2: CMakeLists.txt
- :name: CMakeLists.txt-project
- :language: cmake
- :start-at: project
- :end-at: project
- .. raw:: html
- </details>
- Now we can setup our executable target for the Tutorial with :command:`add_executable`.
- .. raw:: html
- <details><summary>TODO 3: Click to show/hide answer</summary>
- .. literalinclude:: Step3/Tutorial/CMakeLists.txt
- :caption: TODO 3: CMakeLists.txt
- :name: CMakeLists.txt-add_executable
- :language: cmake
- :start-at: add_executable
- :end-at: add_executable
- .. raw:: html
- </details>
- Finally, we can associate our source file with the Tutorial executable target
- using :command:`target_sources`.
- .. raw:: html
- <details><summary>TODO 4: Click to show/hide answer</summary>
- .. code-block:: cmake
- :caption: TODO 4: CMakeLists.txt
- :name: CMakeLists.txt-target_sources
- target_sources(Tutorial
- PRIVATE
- Tutorial/Tutorial.cxx
- )
- .. raw:: html
- </details>
- Exercise 2 - Building a Library
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- We only need to introduce one more command to build a library,
- :command:`add_library`. This works exactly like :command:`add_executable`, but
- for libraries.
- .. code-block:: cmake
- add_library(MyLibrary)
- However, now is a good time to introduce header files. Header files are not
- directly built as translation units, which is to say they are not a *build*
- requirement. They are a *usage* requirement. We need to know about header files
- in order to build other parts of a given target.
- As such, header files are described slightly differently than implementation
- files like ``tutorial.cxx``. They're also going to need different
- :ref:`scope keywords <Target Command Scope>` than the ``PRIVATE`` keyword we
- have used so far.
- To describe a collection of header files, we're going to use what's known as a
- ``FILE_SET``.
- .. code-block:: cmake
- target_sources(MyLibrary
- PRIVATE
- library_implementation.cxx
- PUBLIC
- FILE_SET myHeaders
- TYPE HEADERS
- BASE_DIRS
- include
- FILES
- include/library_header.h
- )
- This is a lot of complexity, but we'll go through it point by point. First,
- note that we have our implementation file as a ``PRIVATE`` source, same as
- with the executable previously. However, we now use ``PUBLIC`` for our
- header file. This allows consumers of our library to "see" the library's
- header files.
- .. note::
- We're not quite ready to discuss the full semantics of scope keywords. We'll
- cover them more completely in Exercise 3.
- Following the scope keyword is a ``FILE_SET``, a collection of files to be
- described as a single unit. A ``FILE_SET`` consists of the following parts:
- * ``FILE_SET <name>`` is the name of the ``FILE_SET``. This is a handle which
- we can use to describe the collection in other contexts.
- * ``TYPE <type>`` is the kind of files we are describing. Most commonly this
- will be headers, but newer versions of CMake support other types like C++20
- modules.
- * ``BASE_DIRS`` is the "base" locations for the files. This can be most easily
- understood as the locations that will be described to compilers for header
- discovery via ``-I`` flags.
- * ``FILES`` is the list of files, same as with the implementation sources list
- earlier.
- This is a lot of information to describe, so there are some useful shortcuts
- we can take. Notably, if the ``FILE_SET`` name is the same as the type, we
- don't need to provide the ``TYPE`` field.
- .. code-block:: cmake
- target_sources(MyLibrary
- PRIVATE
- library_implementation.cxx
- PUBLIC
- FILE_SET HEADERS
- BASE_DIRS
- include
- FILES
- include/library_header.h
- )
- There are other shortcuts we can take, but we'll discuss those more in later
- steps.
- Goal
- ----
- Build a library.
- Helpful Resources
- -----------------
- * :command:`add_library`
- * :command:`target_sources`
- Files to Edit
- -------------
- * ``CMakeLists.txt``
- Getting Started
- ---------------
- Continue editing files in the ``Step1`` directory. Start with ``TODO 5`` and
- complete through ``TODO 6``.
- Build and Run
- -------------
- Let's build our project again. Since we already created a build directory and
- ran CMake for Exercise 1, we can skip to the build step:
- .. code-block:: console
- cmake --build build
- We should be able to see our library created alongside the Tutorial executable.
- Solution
- --------
- We start by adding the library target in the same manner as the the Tutorial
- executable.
- .. raw:: html
- <details><summary>TODO 5: Click to show/hide answer</summary>
- .. literalinclude:: Step3/MathFunctions/CMakeLists.txt
- :caption: TODO 5: CMakeLists.txt
- :name: CMakeLists.txt-add_library
- :language: cmake
- :start-at: add_library
- :end-at: add_library
- .. raw:: html
- </details>
- Next we need to describe the source files. For the implementation file,
- ``MathFunctions.cxx``, this is straight-forward; for the header file
- ``MathFunctions.h`` we will need to use a ``FILE_SET``.
- We can either give this ``FILE_SET`` its own name, or use the shortcut of naming
- it ``HEADERS``. For this tutorial, we'll be using the shortcut, but either
- solution is valid.
- For ``BASE_DIRS`` we need to determine the directory which will allow for the
- desired ``#include <MathFunctions.h>`` directive. To achieve this, the
- ``MathFunctions`` folder itself will be a base directory. We would make a
- different choice if the desired include directive were
- ``#include <MathFunctions/MathFunctions.h>`` or similar.
- .. raw:: html
- <details><summary>TODO 6: Click to show/hide answer</summary>
- .. code-block:: cmake
- :caption: TODO 6: CMakeLists.txt
- :name: CMakeLists.txt-library_sources
- target_sources(MathFunctions
- PRIVATE
- MathFunctions/MathFunctions.cxx
- PUBLIC
- FILE_SET HEADERS
- BASE_DIRS
- MathFunctions
- FILES
- MathFunctions/MathFunctions.h
- )
- .. raw:: html
- </details>
- Exercise 3 - Linking Together Libraries and Executables
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- We're ready to combine our library with our executable, for this we must
- introduce a new command, :command:`target_link_libraries`. The name of this
- command can be somewhat misleading, as it does a great deal more than just
- invoke linkers. It describes relationships between targets generally.
- .. code-block:: cmake
- target_link_libraries(MyProgram
- PRIVATE
- MyLibrary
- )
- We're finally ready to discuss the :ref:`scope keywords <Target Command Scope>`.
- There are three of them, ``PRIVATE``, ``INTERFACE``, and ``PUBLIC``. These
- describe how properties are made available to targets.
- * A ``PRIVATE`` property (also called a "non-interface" property) is only
- available to the target which owns it, for example ``PRIVATE`` headers will
- only be visible to the target they're attached to.
- * An ``INTERFACE`` property is only available to targets *which link* the
- owning target. The owning target does not have access to these properties. A
- header-only library is an example of a collection of ``INTERFACE`` properties,
- as header-only libraries do not build anything themselves and do not need to
- access their own files.
- * ``PUBLIC`` is not a distinct kind of property, but rather is the union of the
- ``PRIVATE`` and ``INTERFACE`` properties. Thus requirements described with
- ``PUBLIC`` are available to both the owning target and consuming targets.
- Consider the following concrete example:
- .. code-block:: cmake
- target_sources(MyLibrary
- PRIVATE
- FILE_SET internalOnlyHeaders
- TYPE HEADERS
- FILES
- InternalOnlyHeader.h
- INTERFACE
- FILE_SET consumerOnlyHeaders
- TYPE HEADERS
- FILES
- ConsumerOnlyHeader.h
- PUBLIC
- FILE_SET publicHeaders
- TYPE HEADERS
- FILES
- PublicHeader.h
- )
- .. note::
- We excluded ``BASE_DIRS`` for each file set here, that's another shortcut.
- When excluded, ``BASE_DIRS`` defaults to the current source directory.
- The ``MyLibrary`` target has several properties which will be modified by this
- call to :command:`target_sources`. Until now we've used the term "properties"
- generically, but properties are themselves named values we can reason about.
- Two specific properties which will be modified here are :prop_tgt:`HEADER_SETS`
- and :prop_tgt:`INTERFACE_HEADER_SETS`, which both contain lists of header file
- sets added via :command:`target_sources`.
- The value ``internalOnlyHeaders`` will be added to :prop_tgt:`HEADER_SETS`,
- ``consumerOnlyHeaders`` to :prop_tgt:`INTERFACE_HEADER_SETS`, and
- ``publicHeaders`` will be added to both.
- When a given target is being built, it will use its own *non-interface*
- properties (eg, :prop_tgt:`HEADER_SETS`), combined with the *interface*
- properties of any targets it links to (eg, :prop_tgt:`INTERFACE_HEADER_SETS`).
- .. note::
- **It is not necessary to reason about CMake properties at this level of
- detail.** The above is described for completeness. Most of the time you don't
- need to be concerned with the specific properties a command is modifying.
- Scope keywords have a simple intuition associated with them, when considering
- a command from the point of view of the target it is being applied to:
- **PRIVATE** is for me, **INTERFACE** is for others, **PUBLIC** is for all of
- us.
- Goal
- ----
- In the Tutorial executable, use the ``sqrt()`` function provided by the
- ``MathFunctions`` library.
- Helpful Resources
- -----------------
- * :command:`target_link_libraries`
- Files to Edit
- -------------
- * ``CMakeLists.txt``
- * ``Tutorial/Tutorial.cxx``
- Getting Started
- ---------------
- Continue to edit files from ``Step1``. Start on ``TODO 7`` and complete through
- ``TODO 9``. In this exercise, we need to add the ``MathFunctions`` target to
- the ``Tutorial`` target's linked libraries using :command:`target_link_libraries`.
- After modifying the CML, update ``tutorial.cxx`` to use the
- ``mathfunctions::sqrt()`` function instead of ``std::sqrt``.
- Build and Run
- -------------
- Let's build our project again. As before, we already created a build directory
- and ran CMake so we can skip to the build step:
- .. code-block:: console
- cmake --build build
- Verify that the output matches what you would expect from the ``MathFunctions``
- library.
- Solution
- --------
- In this exercise, we are describing the ``Tutorial`` executable as a consumer
- of the ``MathFunctions`` target by adding ``MathFunctions`` to the linked
- libraries of the ``Tutorial``.
- To achieve this, we modify ``CMakeLists.txt`` file to use the
- :command:`target_link_libraries` command, using ``Tutorial`` as the target to
- be modified and ``MathFunctions`` as the library we want to add.
- .. raw:: html
- <details><summary>TODO 7: Click to show/hide answer</summary>
- .. literalinclude:: Step3/Tutorial/CMakeLists.txt
- :caption: TODO 7: CMakeLists.txt
- :name: CMakeLists.txt-target_link_libraries
- :language: cmake
- :start-at: target_link_libraries(Tutorial
- :end-at: )
- .. raw:: html
- </details>
- .. note::
- The order here is only loosely relevant. That we call
- :command:`target_link_libraries` prior to defining ``MathFunctions`` with
- :command:`add_library` doesn't matter to CMake. We are recording that
- ``Tutorial`` has a dependency on something named ``MathFunctions``, but what
- ``MathFunctions`` means isn't resolved at this stage.
- The only target which needs to be defined when calling a CMake command like
- :command:`target_sources` or :command:`target_link_libraries` is the target
- being modified.
- Finally, all that's left to do is modify ``Tutorial.cxx`` to use the newly
- provided ``mathfunctions::sqrt`` function. That means adding the appropriate
- header file and modifying our ``sqrt()`` call.
- .. raw:: html
- <details><summary>TODO 8-9: Click to show/hide answer</summary>
- .. literalinclude:: Step3/Tutorial/Tutorial.cxx
- :caption: TODO 8: Tutorial/Tutorial.cxx
- :name: Tutorial/Tutorial.cxx-MathFunctions-headers
- :language: c++
- :start-at: iostream
- :end-at: MathFunctions.h
- .. literalinclude:: Step3/Tutorial/Tutorial.cxx
- :caption: TODO 9: Tutorial/Tutorial.cxx
- :name: Tutorial/Tutorial.cxx-MathFunctions-code
- :language: c++
- :start-at: calculate square root
- :end-at: mathfunctions::sqrt
- :dedent: 2
- .. raw:: html
- </details>
- Exercise 4 - Subdirectories
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- As we move through the tutorial, we will be adding more commands to manipulate
- the ``Tutorial`` executable and the ``MathFunctions`` library. We want to make
- sure we keep commands local to the files they are dealing with. While not a
- major concern for a small project like this, it can be very useful for large
- projects with many targets and thousands of files.
- The :command:`add_subdirectory` command allows us to incorporate CMLs located
- in subdirectories of the project.
- .. code-block:: cmake
- add_subdirectory(SubdirectoryName)
- When a ``CMakeLists.txt`` in a subdirectory is being processed by CMake all
- relative paths described in the subdirectory CML are relative to that
- subdirectory, not the top-level CML.
- Goal
- ----
- Use :command:`add_subdirectory` to organize the project.
- Helpful Resources
- -----------------
- * :command:`add_subdirectory`
- Files to Edit
- -------------
- * ``CMakeLists.txt``
- * ``Tutorial/CMakeLists.txt``
- * ``MathFunctions/CMakeLists.txt``
- Getting Started
- ---------------
- The ``TODOs`` for this step are spread across three ``CMakeLists.txt`` files.
- Be sure to pay attention to the path changes necessary when moving the
- :command:`target_sources` commands into subdirectories.
- .. note::
- Previously we said that ``BASE_DIRS`` defaults to the current source
- directory. As the desired include directory for ``MathFunctions`` will now be
- the same directory as the CML calling :command:`target_sources`, we should
- remove the ``BASE_DIRS`` keyword and argument entirely.
- Complete ``TODO 10`` through ``TODO 13``.
- Build and Run
- -------------
- Because of the reorganization, we'll need to clean the original build
- directory prior to rebuilding (otherwise our new ``Target`` build folder would
- conflict with our previously created ``Target`` executable). We can achieve
- this with the :option:`--clean-first <cmake--build --clean-first>` flag.
- There's no need for a reconfiguration. CMake will automatically
- re-configure itself due to the changes in the CMLs.
- .. code-block:: console
- cmake --build build --clean-first
- .. note::
- Our executable and library will be output to a new location in the build tree.
- A subdirectory which mirrors where :command:`add_executable` and
- :command:`add_library` were called in the source tree. You will need to
- navigate to this subdirectory in the build tree to run the tutorial
- executable in future steps.
- You can verify this behavior by deleting the old ``Tutorial`` executable,
- and observing that the new one is produced at ``Tutorial/Tutorial``.
- Solution
- --------
- We need to move all the commands concerning the ``Tutorial`` executable into
- ``Tutorial/CMakeLists.txt``, and replace them with an
- :command:`add_subdirectory` command. We also need to update the path for
- ``Tutorial.cxx``.
- .. raw:: html
- <details><summary>TODO 10-11: Click to show/hide answer</summary>
- .. literalinclude:: Step3/Tutorial/CMakeLists.txt
- :caption: TODO 10: Tutorial/CMakeLists.txt
- :name: Tutorial/CMakeLists.txt-moved
- :language: cmake
- .. code-block:: cmake
- :caption: TODO 11: CMakeLists.txt
- :name: CMakeLists.txt-add_subdirectory-Tutorial
- add_subdirectory(Tutorial)
- .. raw:: html
- </details>
- We need to do the same with the commands for ``MathFunctions``, changing the
- relative paths as appropriate and removing ``BASE_DIRS`` as it is no longer
- necessary, the default value will work.
- .. raw:: html
- <details><summary>TODO 12-13: Click to show/hide answer</summary>
- .. literalinclude:: Step3/MathFunctions/CMakeLists.txt
- :caption: TODO 12: MathFunctions/CMakeLists.txt
- :name: MathFunctions/CMakeLists.txt-moved
- :language: cmake
- .. literalinclude:: Step3/CMakeLists.txt
- :caption: TODO 13: CMakeLists.txt
- :name: CMakeLists.txt-add_subdirectory-MathFunctions
- :language: cmake
- :start-at: add_subdirectory(MathFunctions
- :end-at: add_subdirectory(MathFunctions
- .. raw:: html
- </details>
|