parent
65bb68f1e7
commit
1d5f9d1e05
@ -0,0 +1,76 @@
|
||||
block
|
||||
-----
|
||||
|
||||
.. versionadded:: 3.25
|
||||
|
||||
Evaluate a group of commands with a dedicated variable and/or policy scope.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
block([SCOPE_FOR [POLICIES] [VARIABLES] ] [PROPAGATE <var-name>...])
|
||||
<commands>
|
||||
endblock()
|
||||
|
||||
All commands between ``block()`` and the matching :command:`endblock` are
|
||||
recorded without being invoked. Once the :command:`endblock` is evaluated, the
|
||||
recorded list of commands is invoked inside the requested scopes, then the
|
||||
scopes created by the ``block()`` command are removed.
|
||||
|
||||
``SCOPE_FOR``
|
||||
Specify which scopes must be created.
|
||||
|
||||
``POLICIES``
|
||||
Create a new policy scope. This is equivalent to
|
||||
:command:`cmake_policy(PUSH)`.
|
||||
|
||||
``VARIABLES``
|
||||
Create a new variable scope.
|
||||
|
||||
If ``SCOPE_FOR`` is not specified, this is equivalent to:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
block(SCOPE_FOR VARIABLES POLICIES)
|
||||
|
||||
``PROPAGATE``
|
||||
When a variable scope is created by the :command:`block` command, this
|
||||
option sets or unsets the specified variables in the parent scope. This is
|
||||
equivalent to :command:`set(PARENT_SCOPE)` or :command:`unset(PARENT_SCOPE)`
|
||||
commands.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
set(var1 "INIT1")
|
||||
set(var2 "INIT2")
|
||||
|
||||
block(PROPAGATE var1 var2)
|
||||
set(var1 "VALUE1")
|
||||
unset(var2)
|
||||
endblock()
|
||||
|
||||
# Now var1 holds VALUE1, and var2 is unset
|
||||
|
||||
This option is only allowed when a variable scope is created. An error will
|
||||
be raised in the other cases.
|
||||
|
||||
When the ``block()`` is inside a :command:`foreach` or :command:`while`
|
||||
command, the :command:`break` and :command:`continue` commands can be used
|
||||
inside the block.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
while(TRUE)
|
||||
block()
|
||||
...
|
||||
# the break() command will terminate the while() command
|
||||
break()
|
||||
endblock()
|
||||
endwhile()
|
||||
|
||||
|
||||
See Also
|
||||
^^^^^^^^
|
||||
|
||||
* :command:`endblock`
|
||||
* :command:`return`
|
||||
* :command:`cmake_policy`
|
@ -1,15 +1,15 @@
|
||||
ctest_run_script
|
||||
----------------
|
||||
|
||||
runs a ctest -S script
|
||||
runs a :option:`ctest -S` script
|
||||
|
||||
::
|
||||
|
||||
ctest_run_script([NEW_PROCESS] script_file_name script_file_name1
|
||||
script_file_name2 ... [RETURN_VALUE var])
|
||||
|
||||
Runs a script or scripts much like if it was run from ctest -S. If no
|
||||
argument is provided then the current script is run using the current
|
||||
Runs a script or scripts much like if it was run from :option:`ctest -S`.
|
||||
If no argument is provided then the current script is run using the current
|
||||
settings of the variables. If ``NEW_PROCESS`` is specified then each
|
||||
script will be run in a separate process.If ``RETURN_VALUE`` is specified
|
||||
the return value of the last script run will be put into ``var``.
|
||||
|
@ -0,0 +1,11 @@
|
||||
endblock
|
||||
--------
|
||||
|
||||
.. versionadded:: 3.25
|
||||
|
||||
Ends a list of commands in a :command:`block` and removes the scopes
|
||||
created by the :command:`block` command.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
endblock()
|
@ -0,0 +1,6 @@
|
||||
CMake uses this environment variable value, in combination with its own
|
||||
builtin default flags for the toolchain, to initialize and store the
|
||||
|CMAKE_LANG_FLAGS| cache entry.
|
||||
This occurs the first time a build tree is configured for language |LANG|.
|
||||
For any configuration run (including the first), the environment variable
|
||||
will be ignored if the |CMAKE_LANG_FLAGS| variable is already defined.
|
@ -0,0 +1,9 @@
|
||||
SSL_CERT_DIR
|
||||
------------
|
||||
|
||||
.. versionadded:: 3.25
|
||||
|
||||
.. include:: ENV_VAR.txt
|
||||
|
||||
Specify default directory containing CA certificates. It overrides
|
||||
the default CA directory used.
|
@ -0,0 +1,9 @@
|
||||
SSL_CERT_FILE
|
||||
-------------
|
||||
|
||||
.. versionadded:: 3.25
|
||||
|
||||
.. include:: ENV_VAR.txt
|
||||
|
||||
Specify the file name containing CA certificates. It overrides the
|
||||
default, os-specific CA file used.
|
@ -1,52 +1,8 @@
|
||||
Visual Studio 10 2010
|
||||
---------------------
|
||||
|
||||
Deprecated. Generates Visual Studio 10 (VS 2010) project files.
|
||||
|
||||
.. note::
|
||||
This generator is deprecated and will be removed in a future version
|
||||
of CMake. It will still be possible to build with VS 10 2010 tools
|
||||
using the :generator:`Visual Studio 11 2012` (or above) generator
|
||||
with :variable:`CMAKE_GENERATOR_TOOLSET` set to ``v100``, or by
|
||||
using the :generator:`NMake Makefiles` generator.
|
||||
|
||||
For compatibility with CMake versions prior to 3.0, one may specify this
|
||||
generator using the name ``Visual Studio 10`` without the year component.
|
||||
|
||||
Project Types
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
Only Visual C++ and C# projects may be generated (and Fortran with
|
||||
Intel compiler integration). Other types of projects (Database,
|
||||
Website, etc.) are not supported.
|
||||
|
||||
Platform Selection
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The default target platform name (architecture) is ``Win32``.
|
||||
|
||||
.. versionadded:: 3.1
|
||||
The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
|
||||
via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
|
||||
name (architecture). For example:
|
||||
|
||||
* ``cmake -G "Visual Studio 10 2010" -A Win32``
|
||||
* ``cmake -G "Visual Studio 10 2010" -A x64``
|
||||
* ``cmake -G "Visual Studio 10 2010" -A Itanium``
|
||||
|
||||
For compatibility with CMake versions prior to 3.1, one may specify
|
||||
a target platform name optionally at the end of the generator name.
|
||||
This is supported only for:
|
||||
|
||||
``Visual Studio 10 2010 Win64``
|
||||
Specify target platform ``x64``.
|
||||
|
||||
``Visual Studio 10 2010 IA64``
|
||||
Specify target platform ``Itanium``.
|
||||
|
||||
Toolset Selection
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
The ``v100`` toolset that comes with Visual Studio 10 2010 is selected by
|
||||
default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps
|
||||
via the :manual:`cmake(1)` ``-T`` option, to specify another toolset.
|
||||
Removed. This once generated Visual Studio 10 2010 project files, but
|
||||
the generator has been removed since CMake 3.25. It is still possible
|
||||
to build with VS 10 2010 tools using the :generator:`Visual Studio 12 2013`
|
||||
(or above) generator with :variable:`CMAKE_GENERATOR_TOOLSET` set to
|
||||
``v100``, or by using the :generator:`NMake Makefiles` generator.
|
||||
|
@ -1,52 +1,147 @@
|
||||
Step 3: Adding Usage Requirements for a Library
|
||||
===============================================
|
||||
|
||||
Usage requirements allow for far better control over a library or executable's
|
||||
link and include line while also giving more control over the transitive
|
||||
property of targets inside CMake. The primary commands that leverage usage
|
||||
requirements are:
|
||||
|
||||
- :command:`target_compile_definitions`
|
||||
- :command:`target_compile_options`
|
||||
- :command:`target_include_directories`
|
||||
- :command:`target_link_libraries`
|
||||
|
||||
Let's refactor our code from :guide:`tutorial/Adding a Library` to use the
|
||||
modern CMake approach of usage requirements. We first state that anybody
|
||||
linking to ``MathFunctions`` needs to include the current source directory,
|
||||
while ``MathFunctions`` itself doesn't. So this can become an ``INTERFACE``
|
||||
usage requirement.
|
||||
|
||||
Remember ``INTERFACE`` means things that consumers require but the producer
|
||||
doesn't. Add the following lines to the end of
|
||||
``MathFunctions/CMakeLists.txt``:
|
||||
Exercise 1 - Adding Usage Requirements for a Library
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:ref:`Usage requirements <Target Usage Requirements>` of a target parameters
|
||||
allow for far better control over a library or executable's link and include
|
||||
line while also giving more control over the transitive property of targets
|
||||
inside CMake. The primary commands that
|
||||
leverage usage requirements are:
|
||||
|
||||
* :command:`target_compile_definitions`
|
||||
* :command:`target_compile_options`
|
||||
* :command:`target_include_directories`
|
||||
* :command:`target_link_directories`
|
||||
* :command:`target_link_options`
|
||||
* :command:`target_precompile_headers`
|
||||
* :command:`target_sources`
|
||||
|
||||
|
||||
Goal
|
||||
----
|
||||
|
||||
Add usage requirements for a library.
|
||||
|
||||
Helpful Materials
|
||||
-----------------
|
||||
|
||||
* :variable:`CMAKE_CURRENT_SOURCE_DIR`
|
||||
|
||||
Files to Edit
|
||||
-------------
|
||||
|
||||
* ``MathFunctions/CMakeLists.txt``
|
||||
* ``CMakeLists.txt``
|
||||
|
||||
Getting Started
|
||||
---------------
|
||||
|
||||
In this exercise, we will refactor our code from
|
||||
:guide:`tutorial/Adding a Library` to use the modern CMake approach. We will
|
||||
let our library define its own usage requirements so they are passed
|
||||
transitively to other targets as necessary. In this case, ``MathFunctions``
|
||||
will specify any needed include directories itself. Then, the consuming target
|
||||
``Tutorial`` simply needs to link to ``MathFunctions`` and not worry about
|
||||
any additional include directories.
|
||||
|
||||
The starting source code is provided in the ``Step3`` directory. In this
|
||||
exercise, complete ``TODO 1`` through ``TODO 3``.
|
||||
|
||||
First, add a call to :command:`target_include_directories` in
|
||||
``MathFunctions/CMakeLists``. Remember that
|
||||
:variable:`CMAKE_CURRENT_SOURCE_DIR` is the path to the source directory
|
||||
currently being processed.
|
||||
|
||||
Then, update (and simplify!) the call to
|
||||
:command:`target_include_directories` in the top-level ``CMakeLists.txt``.
|
||||
|
||||
Build and Run
|
||||
-------------
|
||||
|
||||
Make a new directory called ``Step3_build``, 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 or by
|
||||
using :option:`cmake --build . <cmake --build>` from the build directory.
|
||||
Here's a refresher of what that looks like from the command line:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
mkdir Step3_build
|
||||
cd Step3_build
|
||||
cmake ../Step3
|
||||
cmake --build .
|
||||
|
||||
Next, use the newly built ``Tutorial`` and verify that it is working as
|
||||
expected.
|
||||
|
||||
Solution
|
||||
--------
|
||||
|
||||
Let's update the code from the previous step to use the modern CMake
|
||||
approach of usage requirements.
|
||||
|
||||
We want to state that anybody linking to ``MathFunctions`` needs to include
|
||||
the current source directory, while ``MathFunctions`` itself doesn't. This
|
||||
can be expressed with an ``INTERFACE`` usage requirement. Remember
|
||||
``INTERFACE`` means things that consumers require but the producer doesn't.
|
||||
|
||||
At the end of ``MathFunctions/CMakeLists.txt``, use
|
||||
:command:`target_include_directories` with the ``INTERFACE`` keyword, as
|
||||
follows:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 1: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step4/MathFunctions/CMakeLists.txt
|
||||
:caption: MathFunctions/CMakeLists.txt
|
||||
:caption: TODO 1: MathFunctions/CMakeLists.txt
|
||||
:name: MathFunctions/CMakeLists.txt-target_include_directories-INTERFACE
|
||||
:language: cmake
|
||||
:start-after: # to find MathFunctions.h
|
||||
:end-before: # TODO 3: Link to
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
Now that we've specified usage requirements for ``MathFunctions`` we can safely
|
||||
remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level
|
||||
Now that we've specified usage requirements for ``MathFunctions`` we can
|
||||
safely remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level
|
||||
``CMakeLists.txt``, here:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 2: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step4/CMakeLists.txt
|
||||
:caption: CMakeLists.txt
|
||||
:caption: TODO 2: CMakeLists.txt
|
||||
:name: CMakeLists.txt-remove-EXTRA_INCLUDES
|
||||
:language: cmake
|
||||
:start-after: # add the MathFunctions library
|
||||
:end-before: # add the executable
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
And here:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 3: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step4/CMakeLists.txt
|
||||
:caption: CMakeLists.txt
|
||||
:caption: TODO 3: CMakeLists.txt
|
||||
:name: CMakeLists.txt-target_include_directories-remove-EXTRA_INCLUDES
|
||||
:language: cmake
|
||||
:start-after: # so that we will find TutorialConfig.h
|
||||
|
||||
Once this is done, 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 or by using ``cmake --build .`` from the build
|
||||
directory.
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
Notice that with this technique, the only thing our executable target does to
|
||||
use our library is call :command:`target_link_libraries` with the name
|
||||
of the library target. In larger projects, the classic method of specifying
|
||||
library dependencies manually becomes very complicated very quickly.
|
||||
|
@ -1,136 +1,459 @@
|
||||
Step 2: Adding a Library
|
||||
========================
|
||||
|
||||
Now we will add a library to our project. This library will contain our own
|
||||
At this point, we have seen how to create a basic project using CMake. In this
|
||||
step, we will learn how to create and use a library in our project. We will
|
||||
also see how to make the use of our library optional.
|
||||
|
||||
Exercise 1 - Creating a Library
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To add a library in CMake, use the :command:`add_library` command and specify
|
||||
which source files should make up the library.
|
||||
|
||||
Rather than placing all of the source files in one directory, we can organize
|
||||
our project with one or more subdirectories. In this case, we will create a
|
||||
subdirectory specifically for our library. Here, we can add a new
|
||||
``CMakeLists.txt`` file and one or more source files. In the top level
|
||||
``CMakeLists.txt`` file, we will use the :command:`add_subdirectory` command
|
||||
to add the subdirectory to the build.
|
||||
|
||||
Once the library is created, it is connected to our executable target with
|
||||
:command:`target_include_directories` and :command:`target_link_libraries`.
|
||||
|
||||
Goal
|
||||
----
|
||||
|
||||
Add and use a library.
|
||||
|
||||
Helpful Resources
|
||||
-----------------
|
||||
|
||||
* :command:`add_library`
|
||||
* :command:`add_subdirectory`
|
||||
* :command:`target_include_directories`
|
||||
* :command:`target_link_libraries`
|
||||
* :variable:`PROJECT_SOURCE_DIR`
|
||||
|
||||
Files to Edit
|
||||
-------------
|
||||
|
||||
* ``CMakeLists.txt``
|
||||
* ``tutorial.cxx``
|
||||
* ``MathFunctions/CMakeLists.txt``
|
||||
|
||||
Getting Started
|
||||
---------------
|
||||
|
||||
In this exercise, we will add a library to our project that contains our own
|
||||
implementation for computing the square root of a number. The executable can
|
||||
then use this library instead of the standard square root function provided by
|
||||
the compiler.
|
||||
|
||||
For this tutorial we will put the library into a subdirectory
|
||||
called ``MathFunctions``. This directory already contains a header file,
|
||||
``MathFunctions.h``, and a source file ``mysqrt.cxx``. The source file has one
|
||||
function called ``mysqrt`` that provides similar functionality to the
|
||||
compiler's ``sqrt`` function.
|
||||
For this tutorial we will put the library into a subdirectory called
|
||||
``MathFunctions``. This directory already contains a header file,
|
||||
``MathFunctions.h``, and a source file ``mysqrt.cxx``. We will not need to
|
||||
modify either of these files. The source file has one function called
|
||||
``mysqrt`` that provides similar functionality to the compiler's ``sqrt``
|
||||
function.
|
||||
|
||||
From the ``Help/guide/tutorial/Step2`` directory, start with ``TODO 1`` and
|
||||
complete through ``TODO 6``.
|
||||
|
||||
First, fill in the one line ``CMakeLists.txt`` in the ``MathFunctions``
|
||||
subdirectory.
|
||||
|
||||
Next, edit the top level ``CMakeLists.txt``.
|
||||
|
||||
Finally, use the newly created ``MathFunctions`` library in ``tutorial.cxx``
|
||||
|
||||
Build and Run
|
||||
-------------
|
||||
|
||||
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.
|
||||
|
||||
Below is a refresher of what that looks like from the command line:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
mkdir Step2_build
|
||||
cd Step2_build
|
||||
cmake ../Step2
|
||||
cmake --build .
|
||||
|
||||
Try to use the newly built ``Tutorial`` and ensure that it is still
|
||||
producing accurate square root values.
|
||||
|
||||
Solution
|
||||
--------
|
||||
|
||||
In the ``CMakeLists.txt`` file in the ``MathFunctions`` directory, we create
|
||||
a library target called ``MathFunctions`` with :command:`add_library`. The
|
||||
source file for the library is passed as an argument to
|
||||
:command:`add_library`. This looks like the following line:
|
||||
|
||||
Add the following one line ``CMakeLists.txt`` file to the ``MathFunctions``
|
||||
directory:
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 1: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step3/MathFunctions/CMakeLists.txt
|
||||
:caption: MathFunctions/CMakeLists.txt
|
||||
:name: MathFunctions/CMakeLists.txt
|
||||
:caption: TODO 1: MathFunctions/CMakeLists.txt
|
||||
:name: MathFunctions/CMakeLists.txt-add_library
|
||||
:language: cmake
|
||||
:end-before: # TODO 1
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
To make use of the new library we will add an :command:`add_subdirectory`
|
||||
call in the top-level ``CMakeLists.txt`` file so that the library will get
|
||||
built. We add the new library to the executable, and add ``MathFunctions`` as
|
||||
an include directory so that the ``MathFunctions.h`` header file can be found.
|
||||
The last few lines of the top-level ``CMakeLists.txt`` file should now look
|
||||
like:
|
||||
built.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 2: Click to show/hide answer</summary>
|
||||
|
||||
.. code-block:: cmake
|
||||
:caption: CMakeLists.txt
|
||||
:caption: TODO 2: CMakeLists.txt
|
||||
:name: CMakeLists.txt-add_subdirectory
|
||||
|
||||
# add the MathFunctions library
|
||||
add_subdirectory(MathFunctions)
|
||||
|
||||
# add the executable
|
||||
add_executable(Tutorial tutorial.cxx)
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
Next, the new library target is linked to the executable target using
|
||||
:command:`target_link_libraries`.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 3: Click to show/hide answer</summary>
|
||||
|
||||
.. code-block:: cmake
|
||||
:caption: TODO 3: CMakeLists.txt
|
||||
:name: CMakeLists.txt-target_link_libraries
|
||||
|
||||
target_link_libraries(Tutorial PUBLIC MathFunctions)
|
||||
|
||||
# add the binary tree to the search path for include files
|
||||
# so that we will find TutorialConfig.h
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
Finally we need to specify the library's header file location. Modify
|
||||
:command:`target_include_directories` to add the ``MathFunctions`` subdirectory
|
||||
as an include directory so that the ``MathFunctions.h`` header file can be
|
||||
found.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 4: Click to show/hide answer</summary>
|
||||
|
||||
.. code-block:: cmake
|
||||
:caption: TODO 4: CMakeLists.txt
|
||||
:name: CMakeLists.txt-target_include_directories-step2
|
||||
|
||||
target_include_directories(Tutorial PUBLIC
|
||||
"${PROJECT_BINARY_DIR}"
|
||||
"${PROJECT_SOURCE_DIR}/MathFunctions"
|
||||
)
|
||||
|
||||
Now let us make the ``MathFunctions`` library optional. While for the tutorial
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
Now let's use our library. In ``tutorial.cxx``, include ``MathFunctions.h``:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 5: Click to show/hide answer</summary>
|
||||
|
||||
.. code-block:: c++
|
||||
:caption: TODO 5 : tutorial.cxx
|
||||
:name: tutorial.cxx-include_MathFunctions.h
|
||||
|
||||
#include "MathFunctions.h"
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
Lastly, replace ``sqrt`` with our library function ``mysqrt``.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 6: Click to show/hide answer</summary>
|
||||
|
||||
.. code-block:: c++
|
||||
:caption: TODO 6 : tutorial.cxx
|
||||
:name: tutorial.cxx-call_mysqrt
|
||||
|
||||
const double outputValue = mysqrt(inputValue);
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
Exercise 2 - Making Our Library Optional
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Now let us make the MathFunctions library optional. While for the tutorial
|
||||
there really isn't any need to do so, for larger projects this is a common
|
||||
occurrence. The first step is to add an option to the top-level
|
||||
``CMakeLists.txt`` file.
|
||||
occurrence.
|
||||
|
||||
CMake can do this using the :command:`option` command. This gives users a
|
||||
variable which they can change when configuring their cmake build. This
|
||||
setting will be stored in the cache so that the user does not need to set
|
||||
the value each time they run CMake on a build directory.
|
||||
|
||||
Goal
|
||||
----
|
||||
|
||||
Add the option to build without ``MathFunctions``.
|
||||
|
||||
|
||||
Helpful Resources
|
||||
-----------------
|
||||
|
||||
* :command:`if`
|
||||
* :command:`list`
|
||||
* :command:`option`
|
||||
* :command:`cmakedefine <configure_file>`
|
||||
|
||||
Files to Edit
|
||||
-------------
|
||||
|
||||
* ``CMakeLists.txt``
|
||||
* ``tutorial.cxx``
|
||||
* ``TutorialConfig.h.in``
|
||||
|
||||
Getting Started
|
||||
---------------
|
||||
|
||||
Start with the resulting files from Exercise 1. Complete ``TODO 7`` through
|
||||
``TODO 13``.
|
||||
|
||||
First create a variable ``USE_MYMATH`` using the :command:`option` command
|
||||
in the top-level ``CMakeLists.txt`` file. In that same file, use that option
|
||||
to determine whether to build and use the ``MathFunctions`` library.
|
||||
|
||||
Then, update ``tutorial.cxx`` and ``TutorialConfig.h.in`` to use
|
||||
``USE_MYMATH``.
|
||||
|
||||
Build and Run
|
||||
-------------
|
||||
|
||||
Since we have our build directory already configured from Exercise 1, we can
|
||||
rebuild by simply calling the following:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cd ../Step2_build
|
||||
cmake --build .
|
||||
|
||||
Next, run the ``Tutorial`` executable on a few numbers to verify that it's
|
||||
still correct.
|
||||
|
||||
Now let's update the value of ``USE_MYMATH`` to ``OFF``. The easiest way is to
|
||||
use the :manual:`cmake-gui <cmake-gui(1)>` or :manual:`ccmake <ccmake(1)>`
|
||||
if you're in the terminal. Or, alternatively, if you want to change the
|
||||
option from the command-line, try:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cmake ../Step2 -DUSE_MYMATH=OFF
|
||||
|
||||
Now, rebuild the code with the following:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cmake --build .
|
||||
|
||||
Then, run the executable again to ensure that it still works with
|
||||
``USE_MYMATH`` set to ``OFF``. Which function gives better results, ``sqrt``
|
||||
or ``mysqrt``?
|
||||
|
||||
Solution
|
||||
--------
|
||||
|
||||
The first step is to add an option to the top-level ``CMakeLists.txt`` file.
|
||||
This option will be displayed in the :manual:`cmake-gui <cmake-gui(1)>` and
|
||||
:manual:`ccmake <ccmake(1)>` with a default value of ``ON`` that can be
|
||||
changed by the user.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 7: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step3/CMakeLists.txt
|
||||
:caption: CMakeLists.txt
|
||||
:caption: TODO 7: CMakeLists.txt
|
||||
:name: CMakeLists.txt-option
|
||||
:language: cmake
|
||||
:start-after: # should we use our own math functions
|
||||
:end-before: # add the MathFunctions library
|
||||
:end-before: # configure a header file to pass some of the CMake settings
|
||||
|
||||
This option will be displayed in the :manual:`cmake-gui <cmake-gui(1)>` and
|
||||
:manual:`ccmake <ccmake(1)>`
|
||||
with a default value of ``ON`` that can be changed by the user. This setting
|
||||
will be stored in the cache so that the user does not need to set the value
|
||||
each time they run CMake on a build directory.
|
||||
|
||||
The next change is to make building and linking the ``MathFunctions`` library
|
||||
conditional. To do this, we will create an ``if`` statement which checks the
|
||||
value of the option. Inside the ``if`` block, put the
|
||||
:command:`add_subdirectory` command from above with some additional list
|
||||
commands to store information needed to link to the library and add the
|
||||
subdirectory as an include directory in the ``Tutorial`` target.
|
||||
The end of the top-level ``CMakeLists.txt`` file will now look like the
|
||||
following:
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
Next, make building and linking the ``MathFunctions`` library
|
||||
conditional.
|
||||
|
||||
Start by creating a :command:`list` of the optional library targets for our
|
||||
project. At the moment, it is just ``MathFunctions``. Let's name our list
|
||||
``EXTRA_LIBS``.
|
||||
|
||||
Similarly, we need to make a :command:`list` for the optional includes which
|
||||
we will call ``EXTRA_INCLUDES``. In this list, we will ``APPEND`` the path of
|
||||
the header file needed for our library.
|
||||
|
||||
Next, create an :command:`if` statement which checks the value of
|
||||
``USE_MYMATH``. Inside the :command:`if` block, put the
|
||||
:command:`add_subdirectory` command from Exercise 1 with the additional
|
||||
:command:`list` commands.
|
||||
|
||||
When ``USE_MYMATH`` is ``ON``, the lists will be generated and will be added to
|
||||
our project. When ``USE_MYMATH`` is ``OFF``, the lists stay empty. With this
|
||||
strategy, we allow users to toggle ``USE_MYMATH`` to manipulate what library is
|
||||
used in the build.
|
||||
|
||||
The top-level CMakeLists.txt file will now look like the following:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 8: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step3/CMakeLists.txt
|
||||
:caption: CMakeLists.txt
|
||||
:name: CMakeLists.txt-target_link_libraries-EXTRA_LIBS
|
||||
:caption: TODO 8: CMakeLists.txt
|
||||
:name: CMakeLists.txt-USE_MYMATH
|
||||
:language: cmake
|
||||
:start-after: # add the MathFunctions library
|
||||
:end-before: # add the executable
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
Note the use of the variable ``EXTRA_LIBS`` to collect up any optional
|
||||
libraries to later be linked into the executable. The variable
|
||||
``EXTRA_INCLUDES`` is used similarly for optional header files. This is a
|
||||
classic approach when dealing with many optional components, we will cover
|
||||
the modern approach in the next step.
|
||||
Now that we have these two lists, we need to update
|
||||
:command:`target_link_libraries` and :command:`target_include_directories` to
|
||||
use them. Changing them is fairly straightforward.
|
||||
|
||||
For :command:`target_link_libraries`, we replace the written out
|
||||
library names with ``EXTRA_LIBS``. This looks like the following:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 9: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step3/CMakeLists.txt
|
||||
:caption: TODO 9: CMakeLists.txt
|
||||
:name: CMakeLists.txt-target_link_libraries-EXTRA_LIBS
|
||||
:language: cmake
|
||||
:start-after: add_executable(Tutorial tutorial.cxx)
|
||||
:end-before: # TODO 3
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
Then, we do the same thing with :command:`target_include_directories` and
|
||||
``EXTRA_INCLUDES``.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 10: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step3/CMakeLists.txt
|
||||
:caption: TODO 10 : CMakeLists.txt
|
||||
:name: CMakeLists.txt-target_link_libraries-EXTRA_INCLUDES
|
||||
:language: cmake
|
||||
:start-after: # so that we will find TutorialConfig.h
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
Note that this is a classic approach when dealing with many components. We
|
||||
will cover the modern approach in the Step 3 of the tutorial.
|
||||
|
||||
The corresponding changes to the source code are fairly straightforward.
|
||||
First, in ``tutorial.cxx``, include the ``MathFunctions.h`` header if we
|
||||
need it:
|
||||
First, in ``tutorial.cxx``, we include the ``MathFunctions.h`` header if
|
||||
``USE_MYMATH`` is defined.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 11: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step3/tutorial.cxx
|
||||
:caption: tutorial.cxx
|
||||
:caption: TODO 11 : tutorial.cxx
|
||||
:name: tutorial.cxx-ifdef-include
|
||||
:language: c++
|
||||
:start-after: // should we include the MathFunctions header
|
||||
:end-before: int main
|
||||
|
||||
Then, in the same file, make ``USE_MYMATH`` control which square root
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
Then, in the same file, we make ``USE_MYMATH`` control which square root
|
||||
function is used:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 12: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step3/tutorial.cxx
|
||||
:caption: tutorial.cxx
|
||||
:caption: TODO 12 : tutorial.cxx
|
||||
:name: tutorial.cxx-ifdef-const
|
||||
:language: c++
|
||||
:start-after: // which square root function should we use?
|
||||
:end-before: std::cout << "The square root of
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
Since the source code now requires ``USE_MYMATH`` we can add it to
|
||||
``TutorialConfig.h.in`` with the following line:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 13: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step3/TutorialConfig.h.in
|
||||
:caption: TutorialConfig.h.in
|
||||
:caption: TODO 13 : TutorialConfig.h.in
|
||||
:name: TutorialConfig.h.in-cmakedefine
|
||||
:language: c++
|
||||
:lines: 4
|
||||
|
||||
**Exercise**: Why is it important that we configure ``TutorialConfig.h.in``
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
With these changes, our library is now completely optional to whoever is
|
||||
building and using it.
|
||||
|
||||
Bonus Question
|
||||
--------------
|
||||
|
||||
Why is it important that we configure ``TutorialConfig.h.in``
|
||||
after the option for ``USE_MYMATH``? What would happen if we inverted the two?
|
||||
|
||||
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. Then run the built Tutorial executable.
|
||||
Answer
|
||||
------
|
||||
|
||||
Now let's update the value of ``USE_MYMATH``. The easiest way is to use the
|
||||
:manual:`cmake-gui <cmake-gui(1)>` or :manual:`ccmake <ccmake(1)>` if you're
|
||||
in the terminal. Or, alternatively, if you want to change the option from the
|
||||
command-line, try:
|
||||
.. raw:: html
|
||||
|
||||
.. code-block:: console
|
||||
<details><summary>Click to show/hide answer</summary>
|
||||
|
||||
cmake ../Step2 -DUSE_MYMATH=OFF
|
||||
We configure after because ``TutorialConfig.h.in`` uses the value of
|
||||
``USE_MYMATH``. If we configure the file before
|
||||
calling :command:`option`, we won't be using the expected value of
|
||||
``USE_MYMATH``.
|
||||
|
||||
Rebuild and run the tutorial again.
|
||||
.. raw:: html
|
||||
|
||||
Which function gives better results, ``sqrt`` or ``mysqrt``?
|
||||
</details>
|
||||
|
@ -1,2 +1,2 @@
|
||||
This is the open source License.txt file introduced in
|
||||
CMake/Tutorial/Step7...
|
||||
CMake/Tutorial/Step9...
|
||||
|
@ -1,95 +1,311 @@
|
||||
Step 4: Installing and Testing
|
||||
Step 5: Installing and Testing
|
||||
==============================
|
||||
|
||||
Now we can start adding install rules and testing support to our project.
|
||||
.. _`Tutorial Testing Support`:
|
||||
|
||||
Exercise 1 - Install Rules
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Often, it is not enough to only build an executable, it should also be
|
||||
installable. With CMake, we can specify install rules using the
|
||||
:command:`install` command. Supporting local installations for your builds in
|
||||
CMake is often as simple as specifying an install location and the targets and
|
||||
files to be installed.
|
||||
|
||||
Goal
|
||||
----
|
||||
|
||||
Install the ``Tutorial`` executable and the ``MathFunctions`` library.
|
||||
|
||||
Helpful Materials
|
||||
-----------------
|
||||
|
||||
* :command:`install`
|
||||
|
||||
Install Rules
|
||||
Files to Edit
|
||||
-------------
|
||||
|
||||
The install rules are fairly simple: for ``MathFunctions`` we want to install
|
||||
the library and header file and for the application we want to install the
|
||||
executable and configured header.
|
||||
* ``MathFunctions/CMakeLists.txt``
|
||||
* ``CMakeLists.txt``
|
||||
|
||||
So to the end of ``MathFunctions/CMakeLists.txt`` we add:
|
||||
Getting Started
|
||||
---------------
|
||||
|
||||
.. literalinclude:: Step5/MathFunctions/CMakeLists.txt
|
||||
:caption: MathFunctions/CMakeLists.txt
|
||||
:name: MathFunctions/CMakeLists.txt-install-TARGETS
|
||||
:language: cmake
|
||||
:start-after: # install rules
|
||||
The starting code is provided in the ``Step5`` directory. In this
|
||||
exercise, complete ``TODO 1`` through ``TODO 4``.
|
||||
|
||||
And to the end of the top-level ``CMakeLists.txt`` we add:
|
||||
First, update ``MathFunctions/CMakeLists.txt`` to install the
|
||||
``MathFunctions`` and ``tutorial_compiler_flags`` libraries to the ``lib``
|
||||
directory. In that same file, specify the install rules needed to install
|
||||
``MathFunctions.h`` to the ``include`` directory.
|
||||
|
||||
.. literalinclude:: Step5/CMakeLists.txt
|
||||
:caption: CMakeLists.txt
|
||||
:name: CMakeLists.txt-install-TARGETS
|
||||
:language: cmake
|
||||
:start-after: # add the install targets
|
||||
:end-before: # enable testing
|
||||
Then, update the top level ``CMakeLists.txt`` to install
|
||||
the ``Tutorial`` executable to the ``bin`` directory. Lastly, any header files
|
||||
should be installed to the ``include`` directory. Remember that
|
||||
``TutorialConfig.h`` is in the :variable:`PROJECT_BINARY_DIR`.
|
||||
|
||||
That is all that is needed to create a basic local install of the tutorial.
|
||||
Build and Run
|
||||
-------------
|
||||
|
||||
Now run the :manual:`cmake <cmake(1)>` executable or the
|
||||
Make a new directory called ``Step5_build``. 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.
|
||||
|
||||
Then run the install step by using the ``install`` option of the
|
||||
:manual:`cmake <cmake(1)>` command (introduced in 3.15, older versions of
|
||||
CMake must use ``make install``) from the command line. For
|
||||
multi-configuration tools, don't forget to use the ``--config`` argument to
|
||||
specify the configuration. If using an IDE, simply build the ``INSTALL``
|
||||
target. This step will install the appropriate header files, libraries, and
|
||||
executables. For example:
|
||||
Then, run the install step by using the :option:`--install <cmake --install>`
|
||||
option of the :manual:`cmake <cmake(1)>` command (introduced in 3.15, older
|
||||
versions of CMake must use ``make install``) from the command line. This step
|
||||
will install the appropriate header files, libraries, and executables.
|
||||
For example:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cmake --install .
|
||||
|
||||
For multi-configuration tools, don't forget to use the
|
||||
:option:`--config <cmake--build --config>` argument to specify the configuration.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cmake --install . --config Release
|
||||
|
||||
If using an IDE, simply build the ``INSTALL`` target. You can build the same
|
||||
install target from the command line like the following:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cmake --build . --target install --config Debug
|
||||
|
||||
The CMake variable :variable:`CMAKE_INSTALL_PREFIX` is used to determine the
|
||||
root of where the files will be installed. If using the ``cmake --install``
|
||||
command, the installation prefix can be overridden via the ``--prefix``
|
||||
argument. For example:
|
||||
root of where the files will be installed. If using the :option:`cmake --install`
|
||||
command, the installation prefix can be overridden via the
|
||||
:option:`--prefix <cmake--install --prefix>` argument. For example:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cmake --install . --prefix "/home/myuser/installdir"
|
||||
|
||||
Navigate to the install directory and verify that the installed Tutorial runs.
|
||||
Navigate to the install directory and verify that the installed ``Tutorial``
|
||||
runs.
|
||||
|
||||
.. _`Tutorial Testing Support`:
|
||||
Solution
|
||||
--------
|
||||
|
||||
Testing Support
|
||||
---------------
|
||||
The install rules for our project are fairly simple:
|
||||
|
||||
Next let's test our application. At the end of the top-level ``CMakeLists.txt``
|
||||
file we can enable testing and then add a number of basic tests to verify that
|
||||
the application is working correctly.
|
||||
* For ``MathFunctions``, we want to install the libraries and header file to
|
||||
the ``lib`` and ``include`` directories respectively.
|
||||
|
||||
.. literalinclude:: Step5/CMakeLists.txt
|
||||
* For the ``Tutorial`` executable, we want to install the executable and
|
||||
configured header file to the ``bin`` and ``include`` directories
|
||||
respectively.
|
||||
|
||||
So to the end of ``MathFunctions/CMakeLists.txt`` we add:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 1: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
|
||||
:caption: TODO 1: MathFunctions/CMakeLists.txt
|
||||
:name: MathFunctions/CMakeLists.txt-install-TARGETS
|
||||
:language: cmake
|
||||
:start-after: # install libs
|
||||
:end-before: # install include headers
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
and
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 2: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
|
||||
:caption: TODO 2: MathFunctions/CMakeLists.txt
|
||||
:name: MathFunctions/CMakeLists.txt-install-headers
|
||||
:language: cmake
|
||||
:start-after: # install include headers
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
The install rules for the ``Tutorial`` executable and configured header file
|
||||
are similar. To the end of the top-level ``CMakeLists.txt`` we add:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 3,4: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step6/CMakeLists.txt
|
||||
:caption: CMakeLists.txt
|
||||
:name: CMakeLists.txt-enable_testing
|
||||
:name: TODO 3,4: CMakeLists.txt-install-TARGETS
|
||||
:language: cmake
|
||||
:start-after: # enable testing
|
||||
:start-after: # add the install targets
|
||||
:end-before: # enable testing
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
The first test simply verifies that the application runs, does not segfault or
|
||||
otherwise crash, and has a zero return value. This is the basic form of a
|
||||
CTest test.
|
||||
That is all that is needed to create a basic local
|
||||
install of the tutorial.
|
||||
|
||||
The next test makes use of the :prop_test:`PASS_REGULAR_EXPRESSION` test
|
||||
property to verify that the output of the test contains certain strings. In
|
||||
this case, verifying that the usage message is printed when an incorrect number
|
||||
of arguments are provided.
|
||||
Exercise 2 - Testing Support
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Lastly, we have a function called ``do_test`` that runs the application and
|
||||
verifies that the computed square root is correct for given input. For each
|
||||
invocation of ``do_test``, another test is added to the project with a name,
|
||||
input, and expected results based on the passed arguments.
|
||||
CTest offers a way to easily manage tests for your project. Tests can be
|
||||
added through the :command:`add_test` command. Although it is not
|
||||
explicitly covered in this tutorial, there is a lot of compatibility
|
||||
between CTest and other testing frameworks such as :module:`GoogleTest`.
|
||||
|
||||
Rebuild the application and then cd to the binary directory and run the
|
||||
:manual:`ctest <ctest(1)>` executable: ``ctest -N`` and ``ctest -VV``. For
|
||||
Goal
|
||||
----
|
||||
|
||||
Create unit tests for our executable using CTest.
|
||||
|
||||
Helpful Materials
|
||||
-----------------
|
||||
|
||||
* :command:`enable_testing`
|
||||
* :command:`add_test`
|
||||
* :command:`function`
|
||||
* :command:`set_tests_properties`
|
||||
* :manual:`ctest <ctest(1)>`
|
||||
|
||||
Files to Edit
|
||||
-------------
|
||||
|
||||
* ``CMakeLists.txt``
|
||||
|
||||
Getting Started
|
||||
---------------
|
||||
|
||||
The starting source code is provided in the ``Step5`` directory. In this
|
||||
exercise, complete ``TODO 5`` through ``TODO 9``.
|
||||
|
||||
First, we need to enable testing. Next, begin adding tests to our project
|
||||
using :command:`add_test`. We will work through adding 3 simple tests and
|
||||
then you can add additional testing as you see fit.
|
||||
|
||||
Build and Run
|
||||
-------------
|
||||
|
||||
Navigate to the build directory and rebuild the application. Then, run the
|
||||
``ctest`` executable: :option:`ctest -N` and :option:`ctest -VV`. For
|
||||
multi-config generators (e.g. Visual Studio), the configuration type must be
|
||||
specified with the ``-C <mode>`` flag. For example, to run tests in Debug
|
||||
mode use ``ctest -C Debug -VV`` from the binary directory
|
||||
specified with the :option:`-C \<mode\> <ctest -C>` flag. For example, to run tests in Debug
|
||||
mode use ``ctest -C Debug -VV`` from the build directory
|
||||
(not the Debug subdirectory!). Release mode would be executed from the same
|
||||
location but with a ``-C Release``. Alternatively, build the ``RUN_TESTS``
|
||||
target from the IDE.
|
||||
|
||||
Solution
|
||||
--------
|
||||
|
||||
Let's test our application. At the end of the top-level ``CMakeLists.txt``
|
||||
file we first need to enable testing with the
|
||||
:command:`enable_testing` command.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 5: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step6/CMakeLists.txt
|
||||
:caption: TODO 5: CMakeLists.txt
|
||||
:name: CMakeLists.txt-enable_testing
|
||||
:language: cmake
|
||||
:start-after: # enable testing
|
||||
:end-before: # does the application run
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
With testing enabled, we will add a number of basic tests to verify
|
||||
that the application is working correctly. First, we create a test using
|
||||
:command:`add_test` which runs the ``Tutorial`` executable with the
|
||||
parameter 25 passed in. For this test, we are not going to check the
|
||||
executable's computed answer. This test will verify that
|
||||
application runs, does not segfault or otherwise crash, and has a zero
|
||||
return value. This is the basic form of a CTest test.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 6: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step6/CMakeLists.txt
|
||||
:caption: TODO 6: CMakeLists.txt
|
||||
:name: CMakeLists.txt-test-runs
|
||||
:language: cmake
|
||||
:start-after: # does the application run
|
||||
:end-before: # does the usage message work
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
Next, let's use the :prop_test:`PASS_REGULAR_EXPRESSION` test property to
|
||||
verify that the output of the test contains certain strings. In this case,
|
||||
verifying that the usage message is printed when an incorrect number of
|
||||
arguments are provided.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 7: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step6/CMakeLists.txt
|
||||
:caption: TODO 7: CMakeLists.txt
|
||||
:name: CMakeLists.txt-test-usage
|
||||
:language: cmake
|
||||
:start-after: # does the usage message work?
|
||||
:end-before: # define a function to simplify adding tests
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
The next test we will add verifies the computed value is truly the
|
||||
square root.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 8: Click to show/hide answer</summary>
|
||||
|
||||
.. code-block:: cmake
|
||||
:caption: TODO 8: CMakeLists.txt
|
||||
:name: CMakeLists.txt-test-standard
|
||||
|
||||
add_test(NAME StandardUse COMMAND Tutorial 4)
|
||||
set_tests_properties(StandardUse
|
||||
PROPERTIES PASS_REGULAR_EXPRESSION "4 is 2"
|
||||
)
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
This one test is not enough to give us confidence that it will
|
||||
work for all values passed in. We should add more tests to verify this.
|
||||
To easily add more tests, we make a function called ``do_test`` that runs the
|
||||
application and verifies that the computed square root is correct for
|
||||
given input. For each invocation of ``do_test``, another test is added to
|
||||
the project with a name, input, and expected results based on the passed
|
||||
arguments.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 9: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step6/CMakeLists.txt
|
||||
:caption: TODO 9: CMakeLists.txt
|
||||
:name: CMakeLists.txt-generalized-tests
|
||||
:language: cmake
|
||||
:start-after: # define a function to simplify adding tests
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
@ -0,0 +1,16 @@
|
||||
# TODO 1: Set the minimum required version of CMake to be 3.10
|
||||
|
||||
# TODO 2: Create a project named Tutorial
|
||||
|
||||
# TODO 7: Set the project version number as 1.0 in the above project command
|
||||
|
||||
# TODO 6: Set the variable CMAKE_CXX_STANDARD to 11
|
||||
# and the variable CMAKE_CXX_STANDARD_REQUIRED to True
|
||||
|
||||
# TODO 8: Use configure_file to configure and copy TutorialConfig.h.in to
|
||||
# TutorialConfig.h
|
||||
|
||||
# TODO 3: Add an executable called Tutorial to the project
|
||||
# Hint: Be sure to specify the source file as tutorial.cxx
|
||||
|
||||
# TODO 9: Use target_include_directories to include ${PROJECT_BINARY_DIR}
|
@ -0,0 +1,2 @@
|
||||
// the configured options and settings for Tutorial
|
||||
// TODO 10: Define Tutorial_VERSION_MAJOR and Tutorial_VERSION_MINOR
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue