Adding System Introspection.rst 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. Step 7: Adding System Introspection
  2. ===================================
  3. Let us consider adding some code to our project that depends on features the
  4. target platform may not have. For this example, we will add some code that
  5. depends on whether or not the target platform has the ``log`` and ``exp``
  6. functions. Of course almost every platform has these functions but for this
  7. tutorial assume that they are not common.
  8. Exercise 1 - Assessing Dependency Availability
  9. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  10. Goal
  11. ----
  12. Change implementation based on available system dependencies.
  13. Helpful Resources
  14. -----------------
  15. * :module:`CheckCXXSourceCompiles`
  16. * :command:`target_compile_definitions`
  17. Files to Edit
  18. -------------
  19. * ``MathFunctions/CMakeLists.txt``
  20. * ``MathFunctions/mysqrt.cxx``
  21. Getting Started
  22. ---------------
  23. The starting source code is provided in the ``Step7`` directory. In this
  24. exercise, complete ``TODO 1`` through ``TODO 5``.
  25. Start by editing ``MathFunctions/CMakeLists.txt``. Include the
  26. :module:`CheckCXXSourceCompiles` module. Then, use
  27. ``check_cxx_source_compiles()`` to determine whether ``log`` and ``exp`` are
  28. available from ``cmath``. If they are available, use
  29. :command:`target_compile_definitions` to specify ``HAVE_LOG`` and ``HAVE_EXP``
  30. as compile definitions.
  31. In the ``MathFunctions/mysqrt.cxx``, include ``cmath``. Then, if the system has
  32. ``log`` and ``exp``, use them to compute the square root.
  33. Build and Run
  34. -------------
  35. Make a new directory called ``Step7_build``. Run the
  36. :manual:`cmake <cmake(1)>` executable or the
  37. :manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it
  38. with your chosen build tool and run the ``Tutorial`` executable.
  39. This can look like the following:
  40. .. code-block:: console
  41. mkdir Step7_build
  42. cd Step7_build
  43. cmake ../Step7
  44. cmake --build .
  45. Which function gives better results now, ``sqrt`` or ``mysqrt``?
  46. Solution
  47. --------
  48. In this exercise we will use functions from the
  49. :module:`CheckCXXSourceCompiles` module so first we must include it in
  50. ``MathFunctions/CMakeLists.txt``.
  51. .. raw:: html
  52. <details><summary>TODO 1: Click to show/hide answer</summary>
  53. .. literalinclude:: Step8/MathFunctions/CMakeLists.txt
  54. :caption: TODO 1: MathFunctions/CMakeLists.txt
  55. :name: MathFunctions/CMakeLists.txt-include-check_cxx_source_compiles
  56. :language: cmake
  57. :start-after: # does this system provide the log and exp functions?
  58. :end-before: check_cxx_source_compiles
  59. .. raw:: html
  60. </details>
  61. Then test for the availability of
  62. ``log`` and ``exp`` using ``check_cxx_compiles_source``. This function
  63. lets us try compiling simple code with the required dependency prior to
  64. the true source code compilation. The resulting variables ``HAVE_LOG``
  65. and ``HAVE_EXP`` represent whether those dependencies are available.
  66. .. raw:: html
  67. <details><summary>TODO 2: Click to show/hide answer</summary>
  68. .. literalinclude:: Step8/MathFunctions/CMakeLists.txt
  69. :caption: TODO 2: MathFunctions/CMakeLists.txt
  70. :name: MathFunctions/CMakeLists.txt-check_cxx_source_compiles
  71. :language: cmake
  72. :start-after: include(CheckCXXSourceCompiles)
  73. :end-before: # add compile definitions
  74. .. raw:: html
  75. </details>
  76. Next, we need to pass these CMake variables to our source code. This way,
  77. our source code can tell what resources are available. If both ``log`` and
  78. ``exp`` are available, use :command:`target_compile_definitions` to specify
  79. ``HAVE_LOG`` and ``HAVE_EXP`` as ``PRIVATE`` compile definitions.
  80. .. raw:: html
  81. <details><summary>TODO 3: Click to show/hide answer</summary>
  82. .. literalinclude:: Step8/MathFunctions/CMakeLists.txt
  83. :caption: TODO 3: MathFunctions/CMakeLists.txt
  84. :name: MathFunctions/CMakeLists.txt-target_compile_definitions
  85. :language: cmake
  86. :start-after: # add compile definitions
  87. :end-before: # state
  88. .. raw:: html
  89. </details>
  90. Since we may be using ``log`` and ``exp``, we need to modify
  91. ``mysqrt.cxx`` to include ``cmath``.
  92. .. raw:: html
  93. <details><summary>TODO 4: Click to show/hide answer</summary>
  94. .. literalinclude:: Step8/MathFunctions/mysqrt.cxx
  95. :caption: TODO 4: MathFunctions/mysqrt.cxx
  96. :name: MathFunctions/mysqrt.cxx-include-cmath
  97. :language: c++
  98. :start-after: #include "mysqrt.h"
  99. :end-before: include <iostream>
  100. .. raw:: html
  101. </details>
  102. If ``log`` and ``exp`` are available on the system, then use them to
  103. compute the square root in the ``mysqrt`` function. The ``mysqrt`` function in
  104. ``MathFunctions/mysqrt.cxx`` will look as follows:
  105. .. raw:: html
  106. <details><summary>TODO 5: Click to show/hide answer</summary>
  107. .. literalinclude:: Step8/MathFunctions/mysqrt.cxx
  108. :caption: TODO 5: MathFunctions/mysqrt.cxx
  109. :name: MathFunctions/mysqrt.cxx-ifdef
  110. :language: c++
  111. :start-after: // if we have both log and exp then use them
  112. :end-before: return result;
  113. .. raw:: html
  114. </details>