mirror of
https://github.com/Kitware/CMake.git
synced 2025-12-31 19:00:54 -06:00
Tutorial: Update step 5 style
This commit is contained in:
@@ -21,7 +21,7 @@ in ``MathFunctions/CMakeLists.txt`` to look like:
|
||||
:caption: MathFunctions/CMakeLists.txt
|
||||
:name: MathFunctions/CMakeLists.txt-install-TARGETS-EXPORT
|
||||
:language: cmake
|
||||
:start-after: # install rules
|
||||
:start-after: # install libs
|
||||
|
||||
Now that we have ``MathFunctions`` being exported, we also need to explicitly
|
||||
install the generated ``MathFunctionsTargets.cmake`` file. This is done by
|
||||
|
||||
@@ -158,6 +158,7 @@ and this:
|
||||
:name: MathFunctions-CMakeLists.txt-target_link_libraries-step4
|
||||
:language: cmake
|
||||
:start-after: # link our compiler flags interface library
|
||||
:end-before: # TODO 1
|
||||
|
||||
.. raw:: html
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ If available, use :command:`target_compile_definitions` to specify
|
||||
:name: MathFunctions/CMakeLists.txt-target_compile_definitions
|
||||
:language: cmake
|
||||
:start-after: # add compile definitions
|
||||
:end-before: # install rules
|
||||
:end-before: # install libs
|
||||
|
||||
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
|
||||
|
||||
@@ -62,7 +62,7 @@ directories so that ``Table.h`` can be found and included by ``mysqrt.cxx``.
|
||||
:name: MathFunctions/CMakeLists.txt-target_include_directories-Table.h
|
||||
:language: cmake
|
||||
:start-after: # state that we depend on our bin
|
||||
:end-before: # install rules
|
||||
:end-before: # install libs
|
||||
|
||||
Now let's use the generated table. First, modify ``mysqrt.cxx`` to include
|
||||
``Table.h``. Next, we can rewrite the ``mysqrt`` function to use the table:
|
||||
|
||||
@@ -56,7 +56,7 @@ target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
|
||||
set_property(TARGET MathFunctions PROPERTY VERSION "1.0.0")
|
||||
set_property(TARGET MathFunctions PROPERTY SOVERSION "1")
|
||||
|
||||
# install rules
|
||||
# install libs
|
||||
set(installable_libs MathFunctions tutorial_compiler_flags)
|
||||
if(TARGET SqrtLibrary)
|
||||
list(APPEND installable_libs SqrtLibrary)
|
||||
@@ -64,4 +64,5 @@ endif()
|
||||
install(TARGETS ${installable_libs}
|
||||
EXPORT MathFunctionsTargets
|
||||
DESTINATION lib)
|
||||
# install include headers
|
||||
install(FILES MathFunctions.h DESTINATION include)
|
||||
|
||||
@@ -1,50 +1,80 @@
|
||||
Step 5: Installing and Testing
|
||||
==============================
|
||||
|
||||
Now we can start adding install rules and testing support to our project.
|
||||
.. _`Tutorial Testing Support`:
|
||||
|
||||
Install Rules
|
||||
Exercise 1 - Install Rules
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Often, it is not enough to only build an executable, it should also be
|
||||
installable. With CMake, we can specify install rules using the
|
||||
:command:`install` command. Supporting local installations for your builds in
|
||||
CMake is often as simple as specifying an install location and the targets and
|
||||
files to be installed.
|
||||
|
||||
Goal
|
||||
----
|
||||
|
||||
Install the ``Tutorial`` executable and the ``MathFunctions`` library.
|
||||
|
||||
Helpful Materials
|
||||
-----------------
|
||||
|
||||
* :command:`install`
|
||||
|
||||
Files to Edit
|
||||
-------------
|
||||
|
||||
The install rules are fairly simple: for ``MathFunctions`` we want to install
|
||||
the library and header file and for the application we want to install the
|
||||
executable and configured header.
|
||||
* ``MathFunctions/CMakeLists.txt``
|
||||
* ``CMakeLists.txt``
|
||||
|
||||
So to the end of ``MathFunctions/CMakeLists.txt`` we add:
|
||||
Getting Started
|
||||
---------------
|
||||
|
||||
.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
|
||||
:caption: MathFunctions/CMakeLists.txt
|
||||
:name: MathFunctions/CMakeLists.txt-install-TARGETS
|
||||
:language: cmake
|
||||
:start-after: # install rules
|
||||
The starting code is provided in the ``Step5`` directory. In this
|
||||
exercise, complete ``TODO 1`` through ``TODO 4``.
|
||||
|
||||
And to the end of the top-level ``CMakeLists.txt`` we add:
|
||||
First, update ``MathFunctions/CMakeLists.txt`` to install the
|
||||
``MathFunctions`` and ``tutorial_compiler_flags`` libraries to the ``lib``
|
||||
directory. In that same file, specify the install rules needed to install
|
||||
``MathFunctions.h`` to the ``include`` directory.
|
||||
|
||||
.. literalinclude:: Step6/CMakeLists.txt
|
||||
:caption: CMakeLists.txt
|
||||
:name: CMakeLists.txt-install-TARGETS
|
||||
:language: cmake
|
||||
:start-after: # add the install targets
|
||||
:end-before: # enable testing
|
||||
Then, update the top level ``CMakeLists.txt`` to install
|
||||
the ``Tutorial`` executable to the ``bin`` directory. Lastly, any header files
|
||||
should be installed to the ``include`` directory. Remember that
|
||||
``TutorialConfig.h`` is in the :variable:`PROJECT_BINARY_DIR`.
|
||||
|
||||
That is all that is needed to create a basic local install of the tutorial.
|
||||
Build and Run
|
||||
-------------
|
||||
|
||||
Now run the :manual:`cmake <cmake(1)>` executable or the
|
||||
Make a new directory called ``Step5_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.
|
||||
|
||||
Then run the install step by using the ``install`` option of the
|
||||
Then, run the install step by using the ``install`` option of the
|
||||
:manual:`cmake <cmake(1)>` command (introduced in 3.15, older versions of
|
||||
CMake must use ``make install``) from the command line. For
|
||||
multi-configuration tools, don't forget to use the ``--config`` argument to
|
||||
specify the configuration. If using an IDE, simply build the ``INSTALL``
|
||||
target. This step will install the appropriate header files, libraries, and
|
||||
executables. For example:
|
||||
CMake must use ``make install``) from the command line. This step will
|
||||
install the appropriate header files, libraries, and executables. For example:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cmake --install .
|
||||
|
||||
For multi-configuration tools, don't forget to use the ``--config`` argument to
|
||||
specify the configuration.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cmake --install . --config Release
|
||||
|
||||
If using an IDE, simply build the ``INSTALL`` target. You can build the same
|
||||
install target from the command line like the following:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cmake --build . --target install --config Debug
|
||||
|
||||
The CMake variable :variable:`CMAKE_INSTALL_PREFIX` is used to determine the
|
||||
root of where the files will be installed. If using the ``cmake --install``
|
||||
command, the installation prefix can be overridden via the ``--prefix``
|
||||
@@ -54,42 +84,227 @@ argument. For example:
|
||||
|
||||
cmake --install . --prefix "/home/myuser/installdir"
|
||||
|
||||
Navigate to the install directory and verify that the installed Tutorial runs.
|
||||
Navigate to the install directory and verify that the installed ``Tutorial``
|
||||
runs.
|
||||
|
||||
.. _`Tutorial Testing Support`:
|
||||
Solution
|
||||
--------
|
||||
|
||||
Testing Support
|
||||
---------------
|
||||
The install rules for our project are fairly simple:
|
||||
|
||||
Next let's test our application. At the end of the top-level ``CMakeLists.txt``
|
||||
file we can enable testing and then add a number of basic tests to verify that
|
||||
the application is working correctly.
|
||||
* For ``MathFunctions``, we want to install the libraries and header file to
|
||||
the ``lib`` and ``include`` directories respectively.
|
||||
|
||||
* For the ``Tutorial`` executable, we want to install the executable and
|
||||
configured header file to the ``bin`` and ``include`` directories
|
||||
respectively.
|
||||
|
||||
So to the end of ``MathFunctions/CMakeLists.txt`` we add:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 1: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
|
||||
:caption: TODO 1: MathFunctions/CMakeLists.txt
|
||||
:name: MathFunctions/CMakeLists.txt-install-TARGETS
|
||||
:language: cmake
|
||||
:start-after: # install libs
|
||||
:end-before: # install include headers
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
and
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 2: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
|
||||
:caption: TODO 2: MathFunctions/CMakeLists.txt
|
||||
:name: MathFunctions/CMakeLists.txt-install-headers
|
||||
:language: cmake
|
||||
:start-after: # install include headers
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
The install rules for the ``Tutorial`` executable and configured header file
|
||||
are similar. To the end of the top-level ``CMakeLists.txt`` we add:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 3,4: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step6/CMakeLists.txt
|
||||
:caption: CMakeLists.txt
|
||||
:name: CMakeLists.txt-enable_testing
|
||||
:name: TODO 3,4: CMakeLists.txt-install-TARGETS
|
||||
:language: cmake
|
||||
:start-after: # enable testing
|
||||
:start-after: # add the install targets
|
||||
:end-before: # enable testing
|
||||
|
||||
The first test simply verifies that the application runs, does not segfault or
|
||||
otherwise crash, and has a zero return value. This is the basic form of a
|
||||
CTest test.
|
||||
.. raw:: html
|
||||
|
||||
The next test makes use of the :prop_test:`PASS_REGULAR_EXPRESSION` test
|
||||
property to verify that the output of the test contains certain strings. In
|
||||
this case, verifying that the usage message is printed when an incorrect number
|
||||
of arguments are provided.
|
||||
</details>
|
||||
|
||||
Lastly, we have a function called ``do_test`` that runs the application and
|
||||
verifies that the computed square root is correct for given input. For each
|
||||
invocation of ``do_test``, another test is added to the project with a name,
|
||||
input, and expected results based on the passed arguments.
|
||||
That is all that is needed to create a basic local
|
||||
install of the tutorial.
|
||||
|
||||
Rebuild the application and then cd to the binary directory and run the
|
||||
Exercise 2 - Testing Support
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
CTest offers a way to easily manage tests for your project. Tests can be
|
||||
added through the :command:`add_test` command. Although it is not
|
||||
explicitly covered in this tutorial, there is a lot of compatibility
|
||||
between CTest and other testing frameworks such as :module:`GoogleTest`.
|
||||
|
||||
Goal
|
||||
----
|
||||
|
||||
Create unit tests for our executable using CTest.
|
||||
|
||||
Helpful Materials
|
||||
-----------------
|
||||
|
||||
* :command:`enable_testing`
|
||||
* :command:`add_test`
|
||||
* :command:`function`
|
||||
* :command:`set_tests_properties`
|
||||
* :manual:`ctest <ctest(1)>`
|
||||
|
||||
Files to Edit
|
||||
-------------
|
||||
|
||||
* ``CMakeLists.txt``
|
||||
|
||||
Getting Started
|
||||
---------------
|
||||
|
||||
The starting source code is provided in the ``Step5`` directory. In this
|
||||
exercise, complete ``TODO 5`` through ``TODO 9``.
|
||||
|
||||
First, we need to enable testing. Next, begin adding tests to our project
|
||||
using :command:`add_test`. We will work through adding 3 simple tests and
|
||||
then you can add additional testing as you see fit.
|
||||
|
||||
Build and Run
|
||||
-------------
|
||||
|
||||
Navigate to the build directory and rebuild the application. Then, run the
|
||||
:manual:`ctest <ctest(1)>` executable: ``ctest -N`` and ``ctest -VV``. For
|
||||
multi-config generators (e.g. Visual Studio), the configuration type must be
|
||||
specified with the ``-C <mode>`` flag. For example, to run tests in Debug
|
||||
mode use ``ctest -C Debug -VV`` from the binary directory
|
||||
mode use ``ctest -C Debug -VV`` from the build directory
|
||||
(not the Debug subdirectory!). Release mode would be executed from the same
|
||||
location but with a ``-C Release``. Alternatively, build the ``RUN_TESTS``
|
||||
location but with a ``-C Release``. Alternatively, build the ``RUN_TESTS``
|
||||
target from the IDE.
|
||||
|
||||
Solution
|
||||
--------
|
||||
|
||||
Let's test our application. At the end of the top-level ``CMakeLists.txt``
|
||||
file we first need to enable testing with the
|
||||
:command:`enable_testing` command.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 5: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step6/CMakeLists.txt
|
||||
:caption: TODO 5: CMakeLists.txt
|
||||
:name: CMakeLists.txt-enable_testing
|
||||
:language: cmake
|
||||
:start-after: # enable testing
|
||||
:end-before: # does the application run
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
With testing enabled, we will add a number of basic tests to verify
|
||||
that the application is working correctly. First, we create a test using
|
||||
:command:`add_test` which runs the ``Tutorial`` executable with the
|
||||
parameter 25 passed in. For this test, we are not going to check the
|
||||
executable's computed answer. This test will verify that
|
||||
application runs, does not segfault or otherwise crash, and has a zero
|
||||
return value. This is the basic form of a CTest test.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 6: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step6/CMakeLists.txt
|
||||
:caption: TODO 6: CMakeLists.txt
|
||||
:name: CMakeLists.txt-test-runs
|
||||
:language: cmake
|
||||
:start-after: # does the application run
|
||||
:end-before: # does the usage message work
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
Next, let's use the :prop_test:`PASS_REGULAR_EXPRESSION` test property to
|
||||
verify that the output of the test contains certain strings. In this case,
|
||||
verifying that the usage message is printed when an incorrect number of
|
||||
arguments are provided.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 7: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step6/CMakeLists.txt
|
||||
:caption: TODO 7: CMakeLists.txt
|
||||
:name: CMakeLists.txt-test-usage
|
||||
:language: cmake
|
||||
:start-after: # does the usage message work?
|
||||
:end-before: # define a function to simplify adding tests
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
The next test we will add verifies the computed value is truly the
|
||||
square root.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 8: Click to show/hide answer</summary>
|
||||
|
||||
.. code-block:: cmake
|
||||
:caption: TODO 8: CMakeLists.txt
|
||||
:name: CMakeLists.txt-test-standard
|
||||
|
||||
add_test(NAME StandardUse COMMAND Tutorial 4)
|
||||
set_tests_properties(StandardUse
|
||||
PROPERTIES PASS_REGULAR_EXPRESSION "4 is 2"
|
||||
)
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
This one test is not enough to give us confidence that it will
|
||||
work for all values passed in. We should add more tests to verify this.
|
||||
To easily add more tests, we make a function called ``do_test`` that runs the
|
||||
application and verifies that the computed square root is correct for
|
||||
given input. For each invocation of ``do_test``, another test is added to
|
||||
the project with a name, input, and expected results based on the passed
|
||||
arguments.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details><summary>TODO 9: Click to show/hide answer</summary>
|
||||
|
||||
.. literalinclude:: Step6/CMakeLists.txt
|
||||
:caption: TODO 9: CMakeLists.txt
|
||||
:name: CMakeLists.txt-generalized-tests
|
||||
:language: cmake
|
||||
:start-after: # define a function to simplify adding tests
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
|
||||
@@ -41,7 +41,7 @@ Let's also add version numbering to the ``MathFunctions`` library. In
|
||||
:name: MathFunctions/CMakeLists.txt-VERSION-properties
|
||||
:language: cmake
|
||||
:start-after: # setup the version numbering
|
||||
:end-before: # install rules
|
||||
:end-before: # install libs
|
||||
|
||||
From the ``Step12`` directory, create ``debug`` and ``release``
|
||||
subdirectories. The layout will look like:
|
||||
|
||||
@@ -25,7 +25,8 @@ target_include_directories(MathFunctions
|
||||
# link our compiler flags interface library
|
||||
target_link_libraries(MathFunctions tutorial_compiler_flags)
|
||||
|
||||
# install rules
|
||||
# install libs
|
||||
set(installable_libs MathFunctions tutorial_compiler_flags)
|
||||
install(TARGETS ${installable_libs} DESTINATION lib)
|
||||
# install include headers
|
||||
install(FILES MathFunctions.h DESTINATION include)
|
||||
|
||||
@@ -50,10 +50,11 @@ target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
|
||||
# building on windows
|
||||
target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
|
||||
|
||||
# install rules
|
||||
# install libs
|
||||
set(installable_libs MathFunctions tutorial_compiler_flags)
|
||||
if(TARGET SqrtLibrary)
|
||||
list(APPEND installable_libs SqrtLibrary)
|
||||
endif()
|
||||
install(TARGETS ${installable_libs} DESTINATION lib)
|
||||
# install include headers
|
||||
install(FILES MathFunctions.h DESTINATION include)
|
||||
|
||||
@@ -52,7 +52,7 @@ target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
|
||||
# building on windows
|
||||
target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
|
||||
|
||||
# install rules
|
||||
# install libs
|
||||
set(installable_libs MathFunctions tutorial_compiler_flags)
|
||||
if(TARGET SqrtLibrary)
|
||||
list(APPEND installable_libs SqrtLibrary)
|
||||
@@ -60,4 +60,5 @@ endif()
|
||||
install(TARGETS ${installable_libs}
|
||||
EXPORT MathFunctionsTargets
|
||||
DESTINATION lib)
|
||||
# install include headers
|
||||
install(FILES MathFunctions.h DESTINATION include)
|
||||
|
||||
@@ -38,3 +38,27 @@ target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags)
|
||||
target_include_directories(Tutorial PUBLIC
|
||||
"${PROJECT_BINARY_DIR}"
|
||||
)
|
||||
|
||||
# TODO 3: Install Tutorial in the bin directory
|
||||
# Hint: Use the TARGETS and DESTINATION parameters
|
||||
|
||||
# TODO 4: Install Tutorial.h to the include directory
|
||||
# Hint: Use the FILES and DESTINATION parameters
|
||||
|
||||
# TODO 5: Enable testing
|
||||
|
||||
# TODO 6: Add a test called Runs which runs the following command:
|
||||
# $ Tutorial 25
|
||||
|
||||
# TODO 7: Add a test called Usage which runs the following command:
|
||||
# $ Tutorial
|
||||
# Make sure the expected output is displayed.
|
||||
# Hint: Use the PASS_REGULAR_EXPRESSION property with "Usage.*number"
|
||||
|
||||
# TODO 8: Add a test which runs the following command:
|
||||
# $ Tutorial 4
|
||||
# Make sure the result is correct.
|
||||
# Hint: Use the PASS_REGULAR_EXPRESSION property with "4 is 2"
|
||||
|
||||
# TODO 9: Add more tests. Create a function called do_test to avoid copy +
|
||||
# paste. Test the following values: 4, 9, 5, 7, 25, -25 and 0.00001.
|
||||
|
||||
@@ -8,3 +8,11 @@ target_include_directories(MathFunctions
|
||||
|
||||
# link our compiler flags interface library
|
||||
target_link_libraries(MathFunctions tutorial_compiler_flags)
|
||||
|
||||
# TODO 1: Create a variable called installable_libs that is a list of all
|
||||
# libraries we want to install (e.g. MathFunctions and tutorial_compiler_flags)
|
||||
# Then install the installable libraries to the lib folder.
|
||||
# Hint: Use the TARGETS and DESTINATION parameters
|
||||
|
||||
# TODO 2: Install the library headers to the include folder.
|
||||
# Hint: Use the FILES and DESTINATION parameters
|
||||
|
||||
@@ -9,7 +9,8 @@ target_include_directories(MathFunctions
|
||||
# link our compiler flags interface library
|
||||
target_link_libraries(MathFunctions tutorial_compiler_flags)
|
||||
|
||||
# install rules
|
||||
# install libs
|
||||
set(installable_libs MathFunctions tutorial_compiler_flags)
|
||||
install(TARGETS ${installable_libs} DESTINATION lib)
|
||||
# install include headers
|
||||
install(FILES MathFunctions.h DESTINATION include)
|
||||
|
||||
@@ -9,7 +9,8 @@ target_include_directories(MathFunctions
|
||||
# link our compiler flags interface library
|
||||
target_link_libraries(MathFunctions tutorial_compiler_flags)
|
||||
|
||||
# install rules
|
||||
# install libs
|
||||
set(installable_libs MathFunctions tutorial_compiler_flags)
|
||||
install(TARGETS ${installable_libs} DESTINATION lib)
|
||||
# install include headers
|
||||
install(FILES MathFunctions.h DESTINATION include)
|
||||
|
||||
@@ -32,7 +32,8 @@ if(HAVE_LOG AND HAVE_EXP)
|
||||
PRIVATE "HAVE_LOG" "HAVE_EXP")
|
||||
endif()
|
||||
|
||||
# install rules
|
||||
# install libs
|
||||
set(installable_libs MathFunctions tutorial_compiler_flags)
|
||||
install(TARGETS ${installable_libs} DESTINATION lib)
|
||||
# install include headers
|
||||
install(FILES MathFunctions.h DESTINATION include)
|
||||
|
||||
@@ -27,7 +27,8 @@ target_include_directories(MathFunctions
|
||||
# link our compiler flags interface library
|
||||
target_link_libraries(MathFunctions tutorial_compiler_flags)
|
||||
|
||||
# install rules
|
||||
# install libs
|
||||
set(installable_libs MathFunctions tutorial_compiler_flags)
|
||||
install(TARGETS ${installable_libs} DESTINATION lib)
|
||||
# install include headers
|
||||
install(FILES MathFunctions.h DESTINATION include)
|
||||
|
||||
Reference in New Issue
Block a user