| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 | Step 7: Adding System Introspection===================================Let us consider adding some code to our project that depends on features thetarget platform may not have. For this example, we will add some code thatdepends on whether or not the target platform has the ``log`` and ``exp``functions. Of course almost every platform has these functions but for thistutorial assume that they are not common.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 thisexercise, 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`` areavailable 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 itwith 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``MathFunctions/CMakeLists.txt``... raw:: html  <details><summary>TODO 1: Click to show/hide answer</summary>.. literalinclude:: Step8/MathFunctions/CMakeLists.txt  :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 functionlets us try compiling simple code with the required dependency prior tothe 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  :name: MathFunctions/CMakeLists.txt-check_cxx_source_compiles  :language: cmake  :start-after: include(CheckCXXSourceCompiles)  :end-before: # add compile definitions.. 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``HAVE_LOG`` and ``HAVE_EXP`` as ``PRIVATE`` compile definitions... raw:: html  <details><summary>TODO 3: Click to show/hide answer</summary>.. literalinclude:: Step8/MathFunctions/CMakeLists.txt  :caption: TODO 3: MathFunctions/CMakeLists.txt  :name: MathFunctions/CMakeLists.txt-target_compile_definitions  :language: cmake  :start-after: # add compile definitions  :end-before: # state.. raw:: html  </details>Since we may be using ``log`` and ``exp``, we need to modify``mysqrt.cxx`` to include ``cmath``... raw:: html  <details><summary>TODO 4: Click to show/hide answer</summary>.. literalinclude:: Step8/MathFunctions/mysqrt.cxx  :caption: TODO 4: MathFunctions/mysqrt.cxx  :name: MathFunctions/mysqrt.cxx-include-cmath  :language: c++  :start-after: #include "mysqrt.h"  :end-before: include <iostream>.. raw:: html  </details>If ``log`` and ``exp`` are available on the system, then use them tocompute 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  :end-before: return result;.. raw:: html  </details>
 |