1 Step 3: Adding Usage Requirements for a Library
2 ===============================================
4 Exercise 1 - Adding Usage Requirements for a Library
5 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7 :ref:`Usage requirements <Target Usage Requirements>` of a target parameters
8 allow for far better control over a library or executable's link and include
9 line while also giving more control over the transitive property of targets
10 inside CMake. The primary commands that
11 leverage usage requirements are:
13 * :command:`target_compile_definitions`
14 * :command:`target_compile_options`
15 * :command:`target_include_directories`
16 * :command:`target_link_directories`
17 * :command:`target_link_options`
18 * :command:`target_precompile_headers`
19 * :command:`target_sources`
25 Add usage requirements for a library.
30 * :variable:`CMAKE_CURRENT_SOURCE_DIR`
35 * ``MathFunctions/CMakeLists.txt``
41 In this exercise, we will refactor our code from
42 :guide:`tutorial/Adding a Library` to use the modern CMake approach. We will
43 let our library define its own usage requirements so they are passed
44 transitively to other targets as necessary. In this case, ``MathFunctions``
45 will specify any needed include directories itself. Then, the consuming target
46 ``Tutorial`` simply needs to link to ``MathFunctions`` and not worry about
47 any additional include directories.
49 The starting source code is provided in the ``Step3`` directory. In this
50 exercise, complete ``TODO 1`` through ``TODO 3``.
52 First, add a call to :command:`target_include_directories` in
53 ``MathFunctions/CMakeLists``. Remember that
54 :variable:`CMAKE_CURRENT_SOURCE_DIR` is the path to the source directory
55 currently being processed.
57 Then, update (and simplify!) the call to
58 :command:`target_include_directories` in the top-level ``CMakeLists.txt``.
63 Make a new directory called ``Step3_build``, run the :manual:`cmake
64 <cmake(1)>` executable or the :manual:`cmake-gui <cmake-gui(1)>` to
65 configure the project and then build it with your chosen build tool or by
66 using :option:`cmake --build . <cmake --build>` from the build directory.
67 Here's a refresher of what that looks like from the command line:
69 .. code-block:: console
76 Next, use the newly built ``Tutorial`` and verify that it is working as
82 Let's update the code from the previous step to use the modern CMake
83 approach of usage requirements.
85 We want to state that anybody linking to ``MathFunctions`` needs to include
86 the current source directory, while ``MathFunctions`` itself doesn't. This
87 can be expressed with an ``INTERFACE`` usage requirement. Remember
88 ``INTERFACE`` means things that consumers require but the producer doesn't.
90 At the end of ``MathFunctions/CMakeLists.txt``, use
91 :command:`target_include_directories` with the ``INTERFACE`` keyword, as
96 <details><summary>TODO 1: Click to show/hide answer</summary>
98 .. literalinclude:: Step4/MathFunctions/CMakeLists.txt
99 :caption: TODO 1: MathFunctions/CMakeLists.txt
100 :name: MathFunctions/CMakeLists.txt-target_include_directories-INTERFACE
102 :start-after: # to find MathFunctions.h
103 :end-before: # TODO 3: Link to
109 Now that we've specified usage requirements for ``MathFunctions`` we can
110 safely remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level
111 ``CMakeLists.txt``, here:
115 <details><summary>TODO 2: Click to show/hide answer</summary>
117 .. literalinclude:: Step4/CMakeLists.txt
118 :caption: TODO 2: CMakeLists.txt
119 :name: CMakeLists.txt-remove-EXTRA_INCLUDES
121 :start-after: # add the MathFunctions library
122 :end-before: # add the executable
132 <details><summary>TODO 3: Click to show/hide answer</summary>
134 .. literalinclude:: Step4/CMakeLists.txt
135 :caption: TODO 3: CMakeLists.txt
136 :name: CMakeLists.txt-target_include_directories-remove-EXTRA_INCLUDES
138 :start-after: # so that we will find TutorialConfig.h
144 Notice that with this technique, the only thing our executable target does to
145 use our library is call :command:`target_link_libraries` with the name
146 of the library target. In larger projects, the classic method of specifying
147 library dependencies manually becomes very complicated very quickly.