CMake/Help/guide/tutorial/Adding System Introspection.rst
Brad King 5c84eca210 Tutorial: Simplify logic checking for cmath functions
Since commit 07223c5c27 (Tutorial: Update Step 5 to work on Windows,
2020-02-18, v3.18.0-rc1~655^2) the logic does not work on non-Windows
platforms when cmake is re-run on an existing build tree.  It is also
more complicated than we'd like for a tutorial example.  Avoid the need
to consider the `m` library case by performing the check as C++.

Since `check_cxx_symbol_exists` cannot handle overloaded functions
like `exp` and `log`, check with `check_cxx_source_compiles` instead.
This also presents a more general-purpose example in the tutorial.

Fixes: #23524
2022-06-01 13:57:47 -04:00

60 lines
2.4 KiB
ReStructuredText

Step 5: Adding System Introspection
===================================
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.
If the platform has ``log`` and ``exp`` then we will use them to compute the
square root in the ``mysqrt`` function. We first test for the availability of
these functions using the :module:`CheckCXXSourceCompiles` module in
``MathFunctions/CMakeLists.txt``.
Add the checks for ``log`` and ``exp`` to ``MathFunctions/CMakeLists.txt``,
after the call to :command:`target_include_directories`:
.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-check_cxx_source_compiles
:language: cmake
:start-after: # to find MathFunctions.h, while we don't.
:end-before: # add compile definitions
If available, use :command:`target_compile_definitions` to specify
``HAVE_LOG`` and ``HAVE_EXP`` as ``PRIVATE`` compile definitions.
.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-target_compile_definitions
:language: cmake
:start-after: # add compile definitions
:end-before: # install rules
If ``log`` and ``exp`` are available on the system, then we will use them to
compute the square root in the ``mysqrt`` function. Add the following code to
the ``mysqrt`` function in ``MathFunctions/mysqrt.cxx`` (don't forget the
``#endif`` before returning the result!):
.. literalinclude:: Step6/MathFunctions/mysqrt.cxx
:caption: MathFunctions/mysqrt.cxx
:name: MathFunctions/mysqrt.cxx-ifdef
:language: c++
:start-after: // if we have both log and exp then use them
:end-before: // do ten iterations
We will also need to modify ``mysqrt.cxx`` to include ``cmath``.
.. literalinclude:: Step6/MathFunctions/mysqrt.cxx
:caption: MathFunctions/mysqrt.cxx
:name: MathFunctions/mysqrt.cxx-include-cmath
:language: c++
:end-before: #include <iostream>
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.
Which function gives better results now, ``sqrt`` or ``mysqrt``?