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
|
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
|
ctest_run_script([NEW_PROCESS] script_file_name script_file_name1
|
||||||
script_file_name2 ... [RETURN_VALUE var])
|
script_file_name2 ... [RETURN_VALUE var])
|
||||||
|
|
||||||
Runs a script or scripts much like if it was run from ctest -S. If no
|
Runs a script or scripts much like if it was run from :option:`ctest -S`.
|
||||||
argument is provided then the current script is run using the current
|
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
|
settings of the variables. If ``NEW_PROCESS`` is specified then each
|
||||||
script will be run in a separate process.If ``RETURN_VALUE`` is specified
|
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``.
|
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
|
Visual Studio 10 2010
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
Deprecated. Generates Visual Studio 10 (VS 2010) project files.
|
Removed. This once generated Visual Studio 10 2010 project files, but
|
||||||
|
the generator has been removed since CMake 3.25. It is still possible
|
||||||
.. note::
|
to build with VS 10 2010 tools using the :generator:`Visual Studio 12 2013`
|
||||||
This generator is deprecated and will be removed in a future version
|
(or above) generator with :variable:`CMAKE_GENERATOR_TOOLSET` set to
|
||||||
of CMake. It will still be possible to build with VS 10 2010 tools
|
``v100``, or by using the :generator:`NMake Makefiles` generator.
|
||||||
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.
|
|
||||||
|
@ -1,52 +1,147 @@
|
|||||||
Step 3: Adding Usage Requirements for a Library
|
Step 3: Adding Usage Requirements for a Library
|
||||||
===============================================
|
===============================================
|
||||||
|
|
||||||
Usage requirements allow for far better control over a library or executable's
|
Exercise 1 - Adding Usage Requirements for a Library
|
||||||
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:
|
:ref:`Usage requirements <Target Usage Requirements>` of a target parameters
|
||||||
|
allow for far better control over a library or executable's link and include
|
||||||
- :command:`target_compile_definitions`
|
line while also giving more control over the transitive property of targets
|
||||||
- :command:`target_compile_options`
|
inside CMake. The primary commands that
|
||||||
- :command:`target_include_directories`
|
leverage usage requirements are:
|
||||||
- :command:`target_link_libraries`
|
|
||||||
|
* :command:`target_compile_definitions`
|
||||||
Let's refactor our code from :guide:`tutorial/Adding a Library` to use the
|
* :command:`target_compile_options`
|
||||||
modern CMake approach of usage requirements. We first state that anybody
|
* :command:`target_include_directories`
|
||||||
linking to ``MathFunctions`` needs to include the current source directory,
|
* :command:`target_link_directories`
|
||||||
while ``MathFunctions`` itself doesn't. So this can become an ``INTERFACE``
|
* :command:`target_link_options`
|
||||||
usage requirement.
|
* :command:`target_precompile_headers`
|
||||||
|
* :command:`target_sources`
|
||||||
Remember ``INTERFACE`` means things that consumers require but the producer
|
|
||||||
doesn't. Add the following lines to the end of
|
|
||||||
``MathFunctions/CMakeLists.txt``:
|
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
|
.. literalinclude:: Step4/MathFunctions/CMakeLists.txt
|
||||||
:caption: MathFunctions/CMakeLists.txt
|
:caption: TODO 1: MathFunctions/CMakeLists.txt
|
||||||
:name: MathFunctions/CMakeLists.txt-target_include_directories-INTERFACE
|
:name: MathFunctions/CMakeLists.txt-target_include_directories-INTERFACE
|
||||||
:language: cmake
|
:language: cmake
|
||||||
:start-after: # to find MathFunctions.h
|
: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
|
Now that we've specified usage requirements for ``MathFunctions`` we can
|
||||||
remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level
|
safely remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level
|
||||||
``CMakeLists.txt``, here:
|
``CMakeLists.txt``, here:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<details><summary>TODO 2: Click to show/hide answer</summary>
|
||||||
|
|
||||||
.. literalinclude:: Step4/CMakeLists.txt
|
.. literalinclude:: Step4/CMakeLists.txt
|
||||||
:caption: CMakeLists.txt
|
:caption: TODO 2: CMakeLists.txt
|
||||||
:name: CMakeLists.txt-remove-EXTRA_INCLUDES
|
:name: CMakeLists.txt-remove-EXTRA_INCLUDES
|
||||||
:language: cmake
|
:language: cmake
|
||||||
:start-after: # add the MathFunctions library
|
:start-after: # add the MathFunctions library
|
||||||
:end-before: # add the executable
|
:end-before: # add the executable
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
And here:
|
And here:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<details><summary>TODO 3: Click to show/hide answer</summary>
|
||||||
|
|
||||||
.. literalinclude:: Step4/CMakeLists.txt
|
.. literalinclude:: Step4/CMakeLists.txt
|
||||||
:caption: CMakeLists.txt
|
:caption: TODO 3: CMakeLists.txt
|
||||||
:name: CMakeLists.txt-target_include_directories-remove-EXTRA_INCLUDES
|
:name: CMakeLists.txt-target_include_directories-remove-EXTRA_INCLUDES
|
||||||
:language: cmake
|
:language: cmake
|
||||||
:start-after: # so that we will find TutorialConfig.h
|
:start-after: # so that we will find TutorialConfig.h
|
||||||
|
|
||||||
Once this is done, run the :manual:`cmake <cmake(1)>` executable or the
|
.. raw:: html
|
||||||
: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
|
</details>
|
||||||
directory.
|
|
||||||
|
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
|
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
|
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
|
then use this library instead of the standard square root function provided by
|
||||||
the compiler.
|
the compiler.
|
||||||
|
|
||||||
For this tutorial we will put the library into a subdirectory
|
For this tutorial we will put the library into a subdirectory called
|
||||||
called ``MathFunctions``. This directory already contains a header file,
|
``MathFunctions``. This directory already contains a header file,
|
||||||
``MathFunctions.h``, and a source file ``mysqrt.cxx``. The source file has one
|
``MathFunctions.h``, and a source file ``mysqrt.cxx``. We will not need to
|
||||||
function called ``mysqrt`` that provides similar functionality to the
|
modify either of these files. The source file has one function called
|
||||||
compiler's ``sqrt`` function.
|
``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``
|
.. raw:: html
|
||||||
directory:
|
|
||||||
|
<details><summary>TODO 1: Click to show/hide answer</summary>
|
||||||
|
|
||||||
.. literalinclude:: Step3/MathFunctions/CMakeLists.txt
|
.. literalinclude:: Step3/MathFunctions/CMakeLists.txt
|
||||||
:caption: MathFunctions/CMakeLists.txt
|
:caption: TODO 1: MathFunctions/CMakeLists.txt
|
||||||
:name: MathFunctions/CMakeLists.txt
|
:name: MathFunctions/CMakeLists.txt-add_library
|
||||||
:language: cmake
|
:language: cmake
|
||||||
|
:end-before: # TODO 1
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
To make use of the new library we will add an :command:`add_subdirectory`
|
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
|
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
|
built.
|
||||||
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
|
.. raw:: html
|
||||||
like:
|
|
||||||
|
<details><summary>TODO 2: Click to show/hide answer</summary>
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
:caption: TODO 2: CMakeLists.txt
|
||||||
|
:name: CMakeLists.txt-add_subdirectory
|
||||||
|
|
||||||
|
add_subdirectory(MathFunctions)
|
||||||
|
|
||||||
|
.. 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)
|
||||||
|
|
||||||
|
.. 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
|
.. code-block:: cmake
|
||||||
:caption: CMakeLists.txt
|
:caption: TODO 4: CMakeLists.txt
|
||||||
:name: CMakeLists.txt-add_subdirectory
|
:name: CMakeLists.txt-target_include_directories-step2
|
||||||
|
|
||||||
|
target_include_directories(Tutorial PUBLIC
|
||||||
|
"${PROJECT_BINARY_DIR}"
|
||||||
|
"${PROJECT_SOURCE_DIR}/MathFunctions"
|
||||||
|
)
|
||||||
|
|
||||||
|
.. 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>
|
||||||
|
|
||||||
# add the MathFunctions library
|
.. code-block:: c++
|
||||||
add_subdirectory(MathFunctions)
|
:caption: TODO 5 : tutorial.cxx
|
||||||
|
:name: tutorial.cxx-include_MathFunctions.h
|
||||||
|
|
||||||
# add the executable
|
#include "MathFunctions.h"
|
||||||
add_executable(Tutorial tutorial.cxx)
|
|
||||||
|
|
||||||
target_link_libraries(Tutorial PUBLIC MathFunctions)
|
.. raw:: html
|
||||||
|
|
||||||
# add the binary tree to the search path for include files
|
</details>
|
||||||
# so that we will find TutorialConfig.h
|
|
||||||
target_include_directories(Tutorial PUBLIC
|
|
||||||
"${PROJECT_BINARY_DIR}"
|
|
||||||
"${PROJECT_SOURCE_DIR}/MathFunctions"
|
|
||||||
)
|
|
||||||
|
|
||||||
Now let us make the ``MathFunctions`` library optional. While for the tutorial
|
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
|
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
|
occurrence.
|
||||||
``CMakeLists.txt`` file.
|
|
||||||
|
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
|
.. literalinclude:: Step3/CMakeLists.txt
|
||||||
:caption: CMakeLists.txt
|
:caption: TODO 7: CMakeLists.txt
|
||||||
:name: CMakeLists.txt-option
|
:name: CMakeLists.txt-option
|
||||||
:language: cmake
|
:language: cmake
|
||||||
:start-after: # should we use our own math functions
|
: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
|
.. raw:: html
|
||||||
:manual:`ccmake <ccmake(1)>`
|
|
||||||
with a default value of ``ON`` that can be changed by the user. This setting
|
</details>
|
||||||
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.
|
Next, make building and linking the ``MathFunctions`` library
|
||||||
|
conditional.
|
||||||
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
|
Start by creating a :command:`list` of the optional library targets for our
|
||||||
value of the option. Inside the ``if`` block, put the
|
project. At the moment, it is just ``MathFunctions``. Let's name our list
|
||||||
:command:`add_subdirectory` command from above with some additional list
|
``EXTRA_LIBS``.
|
||||||
commands to store information needed to link to the library and add the
|
|
||||||
subdirectory as an include directory in the ``Tutorial`` target.
|
Similarly, we need to make a :command:`list` for the optional includes which
|
||||||
The end of the top-level ``CMakeLists.txt`` file will now look like the
|
we will call ``EXTRA_INCLUDES``. In this list, we will ``APPEND`` the path of
|
||||||
following:
|
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
|
.. literalinclude:: Step3/CMakeLists.txt
|
||||||
:caption: CMakeLists.txt
|
:caption: TODO 8: CMakeLists.txt
|
||||||
:name: CMakeLists.txt-target_link_libraries-EXTRA_LIBS
|
:name: CMakeLists.txt-USE_MYMATH
|
||||||
:language: cmake
|
:language: cmake
|
||||||
:start-after: # add the MathFunctions library
|
: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
|
Now that we have these two lists, we need to update
|
||||||
libraries to later be linked into the executable. The variable
|
:command:`target_link_libraries` and :command:`target_include_directories` to
|
||||||
``EXTRA_INCLUDES`` is used similarly for optional header files. This is a
|
use them. Changing them is fairly straightforward.
|
||||||
classic approach when dealing with many optional components, we will cover
|
|
||||||
the modern approach in the next step.
|
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.
|
The corresponding changes to the source code are fairly straightforward.
|
||||||
First, in ``tutorial.cxx``, include the ``MathFunctions.h`` header if we
|
First, in ``tutorial.cxx``, we include the ``MathFunctions.h`` header if
|
||||||
need it:
|
``USE_MYMATH`` is defined.
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<details><summary>TODO 11: Click to show/hide answer</summary>
|
||||||
|
|
||||||
.. literalinclude:: Step3/tutorial.cxx
|
.. literalinclude:: Step3/tutorial.cxx
|
||||||
:caption: tutorial.cxx
|
:caption: TODO 11 : tutorial.cxx
|
||||||
:name: tutorial.cxx-ifdef-include
|
:name: tutorial.cxx-ifdef-include
|
||||||
:language: c++
|
:language: c++
|
||||||
:start-after: // should we include the MathFunctions header
|
:start-after: // should we include the MathFunctions header
|
||||||
:end-before: int main
|
: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:
|
function is used:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<details><summary>TODO 12: Click to show/hide answer</summary>
|
||||||
|
|
||||||
.. literalinclude:: Step3/tutorial.cxx
|
.. literalinclude:: Step3/tutorial.cxx
|
||||||
:caption: tutorial.cxx
|
:caption: TODO 12 : tutorial.cxx
|
||||||
:name: tutorial.cxx-ifdef-const
|
:name: tutorial.cxx-ifdef-const
|
||||||
:language: c++
|
:language: c++
|
||||||
:start-after: // which square root function should we use?
|
:start-after: // which square root function should we use?
|
||||||
:end-before: std::cout << "The square root of
|
:end-before: std::cout << "The square root of
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
Since the source code now requires ``USE_MYMATH`` we can add it to
|
Since the source code now requires ``USE_MYMATH`` we can add it to
|
||||||
``TutorialConfig.h.in`` with the following line:
|
``TutorialConfig.h.in`` with the following line:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<details><summary>TODO 13: Click to show/hide answer</summary>
|
||||||
|
|
||||||
.. literalinclude:: Step3/TutorialConfig.h.in
|
.. literalinclude:: Step3/TutorialConfig.h.in
|
||||||
:caption: TutorialConfig.h.in
|
:caption: TODO 13 : TutorialConfig.h.in
|
||||||
:name: TutorialConfig.h.in-cmakedefine
|
:name: TutorialConfig.h.in-cmakedefine
|
||||||
:language: c++
|
:language: c++
|
||||||
:lines: 4
|
: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?
|
after the option for ``USE_MYMATH``? What would happen if we inverted the two?
|
||||||
|
|
||||||
Run the :manual:`cmake <cmake(1)>` executable or the
|
Answer
|
||||||
: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.
|
|
||||||
|
|
||||||
Now let's update the value of ``USE_MYMATH``. The easiest way is to use the
|
.. raw:: html
|
||||||
: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
|
<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
|
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
|
* ``MathFunctions/CMakeLists.txt``
|
||||||
the library and header file and for the application we want to install the
|
* ``CMakeLists.txt``
|
||||||
executable and configured header.
|
|
||||||
|
|
||||||
So to the end of ``MathFunctions/CMakeLists.txt`` we add:
|
Getting Started
|
||||||
|
---------------
|
||||||
|
|
||||||
.. literalinclude:: Step5/MathFunctions/CMakeLists.txt
|
The starting code is provided in the ``Step5`` directory. In this
|
||||||
:caption: MathFunctions/CMakeLists.txt
|
exercise, complete ``TODO 1`` through ``TODO 4``.
|
||||||
:name: MathFunctions/CMakeLists.txt-install-TARGETS
|
|
||||||
:language: cmake
|
|
||||||
:start-after: # install rules
|
|
||||||
|
|
||||||
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
|
Then, update the top level ``CMakeLists.txt`` to install
|
||||||
:caption: CMakeLists.txt
|
the ``Tutorial`` executable to the ``bin`` directory. Lastly, any header files
|
||||||
:name: CMakeLists.txt-install-TARGETS
|
should be installed to the ``include`` directory. Remember that
|
||||||
:language: cmake
|
``TutorialConfig.h`` is in the :variable:`PROJECT_BINARY_DIR`.
|
||||||
:start-after: # add the install targets
|
|
||||||
:end-before: # enable testing
|
|
||||||
|
|
||||||
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
|
:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it
|
||||||
with your chosen build tool.
|
with your chosen build tool.
|
||||||
|
|
||||||
Then run the install step by using the ``install`` option of the
|
Then, run the install step by using the :option:`--install <cmake --install>`
|
||||||
:manual:`cmake <cmake(1)>` command (introduced in 3.15, older versions of
|
option of the :manual:`cmake <cmake(1)>` command (introduced in 3.15, older
|
||||||
CMake must use ``make install``) from the command line. For
|
versions of CMake must use ``make install``) from the command line. This step
|
||||||
multi-configuration tools, don't forget to use the ``--config`` argument to
|
will install the appropriate header files, libraries, and executables.
|
||||||
specify the configuration. If using an IDE, simply build the ``INSTALL``
|
For example:
|
||||||
target. This step will install the appropriate header files, libraries, and
|
|
||||||
executables. For example:
|
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
cmake --install .
|
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
|
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``
|
root of where the files will be installed. If using the :option:`cmake --install`
|
||||||
command, the installation prefix can be overridden via the ``--prefix``
|
command, the installation prefix can be overridden via the
|
||||||
argument. For example:
|
:option:`--prefix <cmake--install --prefix>` argument. For example:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
cmake --install . --prefix "/home/myuser/installdir"
|
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``
|
* For ``MathFunctions``, we want to install the libraries and header file to
|
||||||
file we can enable testing and then add a number of basic tests to verify that
|
the ``lib`` and ``include`` directories respectively.
|
||||||
the application is working correctly.
|
|
||||||
|
|
||||||
.. 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
|
:caption: CMakeLists.txt
|
||||||
:name: CMakeLists.txt-enable_testing
|
:name: TODO 3,4: CMakeLists.txt-install-TARGETS
|
||||||
:language: cmake
|
: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
|
That is all that is needed to create a basic local
|
||||||
otherwise crash, and has a zero return value. This is the basic form of a
|
install of the tutorial.
|
||||||
CTest test.
|
|
||||||
|
|
||||||
The next test makes use of the :prop_test:`PASS_REGULAR_EXPRESSION` test
|
Exercise 2 - Testing Support
|
||||||
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.
|
|
||||||
|
|
||||||
Lastly, we have a function called ``do_test`` that runs the application and
|
CTest offers a way to easily manage tests for your project. Tests can be
|
||||||
verifies that the computed square root is correct for given input. For each
|
added through the :command:`add_test` command. Although it is not
|
||||||
invocation of ``do_test``, another test is added to the project with a name,
|
explicitly covered in this tutorial, there is a lot of compatibility
|
||||||
input, and expected results based on the passed arguments.
|
between CTest and other testing frameworks such as :module:`GoogleTest`.
|
||||||
|
|
||||||
Rebuild the application and then cd to the binary directory and run the
|
Goal
|
||||||
:manual:`ctest <ctest(1)>` executable: ``ctest -N`` and ``ctest -VV``. For
|
----
|
||||||
|
|
||||||
|
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
|
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
|
specified with the :option:`-C \<mode\> <ctest -C>` flag. For example, to run tests in Debug
|
||||||
mode use ``ctest -C Debug -VV`` from the binary directory
|
mode use ``ctest -C Debug -VV`` from the build directory
|
||||||
(not the Debug subdirectory!). Release mode would be executed from the same
|
(not the Debug subdirectory!). Release mode would be executed from the same
|
||||||
location but with a ``-C Release``. Alternatively, build the ``RUN_TESTS``
|
location but with a ``-C Release``. Alternatively, build the ``RUN_TESTS``
|
||||||
target from the IDE.
|
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