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:
@@ -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``?
|
|
||||||
|
@@ -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)
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user