1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-23 00:48:55 +08:00

Tutorial: Update step 7 style

This commit is contained in:
Markus Ferrell
2022-10-07 10:03:55 -04:00
parent 2954a810ce
commit f9ef15f3dc
3 changed files with 159 additions and 26 deletions

View File

@@ -7,53 +7,156 @@ 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 functions. Of course almost every platform has these functions but for this
tutorial assume that they are not common. tutorial assume that they are not common.
If the platform has ``log`` and ``exp`` then we will use them to compute the Exercise 1 - Assessing Dependency Availability
square root in the ``mysqrt`` function. We first test for the availability of ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
these functions using the :module:`CheckCXXSourceCompiles` module in
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
``MathFunctions/CMakeLists.txt``. ``MathFunctions/CMakeLists.txt``.
Add the checks for ``log`` and ``exp`` to ``MathFunctions/CMakeLists.txt``, .. raw:: html
after the call to :command:`target_include_directories`:
<details><summary>TODO 1: Click to show/hide answer</summary>
.. literalinclude:: Step8/MathFunctions/CMakeLists.txt .. literalinclude:: Step8/MathFunctions/CMakeLists.txt
:caption: 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 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
:name: MathFunctions/CMakeLists.txt-check_cxx_source_compiles :name: MathFunctions/CMakeLists.txt-check_cxx_source_compiles
:language: cmake :language: cmake
:start-after: # to find MathFunctions.h, while we don't. :start-after: include(CheckCXXSourceCompiles)
:end-before: # add compile definitions :end-before: # add compile definitions
If available, use :command:`target_compile_definitions` to specify .. 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. ``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 .. literalinclude:: Step8/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt :caption: TODO 3: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-target_compile_definitions :name: MathFunctions/CMakeLists.txt-target_compile_definitions
:language: cmake :language: cmake
:start-after: # add compile definitions :start-after: # add compile definitions
:end-before: # install libs :end-before: # install libs
If ``log`` and ``exp`` are available on the system, then we will use them to .. raw:: html
compute the square root in the ``mysqrt`` function. Add the following code to
the ``mysqrt`` function in ``MathFunctions/mysqrt.cxx`` (don't forget the </details>
``#endif`` before returning the result!):
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 .. literalinclude:: Step8/MathFunctions/mysqrt.cxx
:caption: MathFunctions/mysqrt.cxx :caption: TODO 4: MathFunctions/mysqrt.cxx
:name: MathFunctions/mysqrt.cxx-include-cmath
:language: c++
:end-before: #include <iostream>
.. raw:: html
</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 :name: MathFunctions/mysqrt.cxx-ifdef
:language: c++ :language: c++
:start-after: // if we have both log and exp then use them :start-after: // if we have both log and exp then use them
:end-before: // do ten iterations :end-before: // do ten iterations
We will also need to modify ``mysqrt.cxx`` to include ``cmath``. .. raw:: html
.. literalinclude:: Step8/MathFunctions/mysqrt.cxx </details>
: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``?

View File

@@ -9,6 +9,26 @@ target_include_directories(MathFunctions
# link our compiler flags interface library # link our compiler flags interface library
target_link_libraries(MathFunctions tutorial_compiler_flags) target_link_libraries(MathFunctions tutorial_compiler_flags)
# TODO 1: Include CheckCXXSourceCompiles
# TODO 2: Use check_cxx_source_compiles with simple C++ code to verify
# availability of:
# * std::log
# * std::exp
# Store the results in HAVE_LOG and HAVE_EXP respectively.
# Hint: Sample C++ code which uses log:
# #include <cmath>
# int main() {
# std::log(1.0);
# return 0;
# }
# TODO 3: Conditionally on HAVE_LOG and HAVE_EXP, add private compile
# definitions "HAVE_LOG" and "HAVE_EXP" to the MathFunctions target.
#Hint: Use target_compile_definitions()
# install libs # install libs
set(installable_libs MathFunctions tutorial_compiler_flags) set(installable_libs MathFunctions tutorial_compiler_flags)
install(TARGETS ${installable_libs} DESTINATION lib) install(TARGETS ${installable_libs} DESTINATION lib)

View File

@@ -1,5 +1,6 @@
#include <iostream> #include <iostream>
// TODO 4: include cmath
#include "MathFunctions.h" #include "MathFunctions.h"
// a hack square root calculation using simple operations // a hack square root calculation using simple operations
@@ -9,6 +10,14 @@ double mysqrt(double x)
return 0; return 0;
} }
// TODO 5: If both HAVE_LOG and HAVE_EXP are defined, use the following:
//// double result = std::exp(std::log(x) * 0.5);
//// std::cout << "Computing sqrt of " << x << " to be " << result
//// << " using log and exp" << std::endl;
// else, use the existing logic.
// Hint: Don't forget the #endif before returning the result!
double result = x; double result = x;
// do ten iterations // do ten iterations
@@ -20,5 +29,6 @@ double mysqrt(double x)
result = result + 0.5 * delta / result; result = result + 0.5 * delta / result;
std::cout << "Computing sqrt of " << x << " to be " << result << std::endl; std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
} }
return result; return result;
} }