cmake/Help/guide/tutorial/Adding System Introspection.rst

164 lines
4.7 KiB
ReStructuredText
Raw Normal View History

2022-11-16 20:14:03 +01:00
Step 7: Adding System Introspection
2021-09-14 00:13:48 +02:00
===================================
Let us consider adding some code to our project that depends on features the
target platform may not have. For this example, we will add some code that
depends on whether or not the target platform has the ``log`` and ``exp``
functions. Of course almost every platform has these functions but for this
tutorial assume that they are not common.
2023-05-23 16:38:00 +02:00
Exercise 1 - Assessing Dependency Availability
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Goal
----
Change implementation based on available system dependencies.
Helpful Resources
-----------------
* :module:`CheckCXXSourceCompiles`
* :command:`target_compile_definitions`
Files to Edit
-------------
* ``MathFunctions/CMakeLists.txt``
* ``MathFunctions/mysqrt.cxx``
Getting Started
---------------
The starting source code is provided in the ``Step7`` directory. In this
exercise, complete ``TODO 1`` through ``TODO 5``.
Start by editing ``MathFunctions/CMakeLists.txt``. Include the
:module:`CheckCXXSourceCompiles` module. Then, use
``check_cxx_source_compiles`` to determine whether ``log`` and ``exp`` are
available from ``cmath``. If they are available, use
:command:`target_compile_definitions` to specify ``HAVE_LOG`` and ``HAVE_EXP``
as compile definitions.
In the ``MathFunctions/mysqrt.cxx``, include ``cmath``. Then, if the system has
``log`` and ``exp``, use them to compute the square root.
Build and Run
-------------
Make a new directory called ``Step7_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 and run the ``Tutorial`` executable.
This can look like the following:
.. code-block:: console
mkdir Step7_build
cd Step7_build
cmake ../Step7
cmake --build .
Which function gives better results now, ``sqrt`` or ``mysqrt``?
Solution
--------
In this exercise we will use functions from the
:module:`CheckCXXSourceCompiles` module so first we must include it in
2022-07-29 21:54:54 +02:00
``MathFunctions/CMakeLists.txt``.
2021-09-14 00:13:48 +02:00
2023-05-23 16:38:00 +02:00
.. raw:: html
<details><summary>TODO 1: Click to show/hide answer</summary>
2021-11-20 13:41:27 +01:00
2022-11-16 20:14:03 +01:00
.. literalinclude:: Step8/MathFunctions/CMakeLists.txt
2023-05-23 16:38:00 +02:00
:caption: TODO 1: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-include-check_cxx_source_compiles
:language: cmake
:start-after: # does this system provide the log and exp functions?
:end-before: check_cxx_source_compiles
.. raw:: html
</details>
Then test for the availability of
``log`` and ``exp`` using ``check_cxx_compiles_source``. This function
lets us try compiling simple code with the required dependency prior to
the true source code compilation. The resulting variables ``HAVE_LOG``
and ``HAVE_EXP`` represent whether those dependencies are available.
.. raw:: html
<details><summary>TODO 2: Click to show/hide answer</summary>
.. literalinclude:: Step8/MathFunctions/CMakeLists.txt
:caption: TODO 2: MathFunctions/CMakeLists.txt
2022-07-29 21:54:54 +02:00
:name: MathFunctions/CMakeLists.txt-check_cxx_source_compiles
2021-09-14 00:13:48 +02:00
:language: cmake
2023-05-23 16:38:00 +02:00
:start-after: include(CheckCXXSourceCompiles)
2021-09-14 00:13:48 +02:00
:end-before: # add compile definitions
2023-05-23 16:38:00 +02:00
.. raw:: html
</details>
Next, we need to pass these CMake variables to our source code. This way,
our source code can tell what resources are available. If both ``log`` and
``exp`` are available, use :command:`target_compile_definitions` to specify
2021-09-14 00:13:48 +02:00
``HAVE_LOG`` and ``HAVE_EXP`` as ``PRIVATE`` compile definitions.
2023-05-23 16:38:00 +02:00
.. raw:: html
<details><summary>TODO 3: Click to show/hide answer</summary>
2022-11-16 20:14:03 +01:00
.. literalinclude:: Step8/MathFunctions/CMakeLists.txt
2023-05-23 16:38:00 +02:00
:caption: TODO 3: MathFunctions/CMakeLists.txt
2021-09-14 00:13:48 +02:00
:name: MathFunctions/CMakeLists.txt-target_compile_definitions
:language: cmake
:start-after: # add compile definitions
2023-07-02 19:51:09 +02:00
:end-before: # state
2021-09-14 00:13:48 +02:00
2023-05-23 16:38:00 +02:00
.. raw:: html
2021-09-14 00:13:48 +02:00
2023-05-23 16:38:00 +02:00
</details>
Since we may be using ``log`` and ``exp``, we need to modify
``mysqrt.cxx`` to include ``cmath``.
.. raw:: html
2021-09-14 00:13:48 +02:00
2023-05-23 16:38:00 +02:00
<details><summary>TODO 4: Click to show/hide answer</summary>
2021-09-14 00:13:48 +02:00
2022-11-16 20:14:03 +01:00
.. literalinclude:: Step8/MathFunctions/mysqrt.cxx
2023-05-23 16:38:00 +02:00
:caption: TODO 4: MathFunctions/mysqrt.cxx
2021-09-14 00:13:48 +02:00
:name: MathFunctions/mysqrt.cxx-include-cmath
:language: c++
2023-07-02 19:51:09 +02:00
:start-after: #include "mysqrt.h"
:end-before: include <iostream>
2021-09-14 00:13:48 +02:00
2023-05-23 16:38:00 +02:00
.. raw:: html
2021-09-14 00:13:48 +02:00
2023-05-23 16:38:00 +02:00
</details>
If ``log`` and ``exp`` are available on the system, then use them to
compute the square root in the ``mysqrt`` function. The ``mysqrt`` function in
``MathFunctions/mysqrt.cxx`` will look as follows:
.. raw:: html
<details><summary>TODO 5: Click to show/hide answer</summary>
.. literalinclude:: Step8/MathFunctions/mysqrt.cxx
:caption: TODO 5: MathFunctions/mysqrt.cxx
:name: MathFunctions/mysqrt.cxx-ifdef
:language: c++
:start-after: // if we have both log and exp then use them
2023-07-02 19:51:09 +02:00
:end-before: return result;
2023-05-23 16:38:00 +02:00
.. raw:: html
</details>