Imported Upstream version 3.25.0
[platform/upstream/cmake.git] / Help / guide / tutorial / Adding Usage Requirements for a Library.rst
1 Step 3: Adding Usage Requirements for a Library
2 ===============================================
3
4 Exercise 1 - Adding Usage Requirements for a Library
5 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6
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:
12
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`
20
21
22 Goal
23 ----
24
25 Add usage requirements for a library.
26
27 Helpful Materials
28 -----------------
29
30 * :variable:`CMAKE_CURRENT_SOURCE_DIR`
31
32 Files to Edit
33 -------------
34
35 * ``MathFunctions/CMakeLists.txt``
36 * ``CMakeLists.txt``
37
38 Getting Started
39 ---------------
40
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.
48
49 The starting source code is provided in the ``Step3`` directory. In this
50 exercise, complete ``TODO 1`` through ``TODO 3``.
51
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.
56
57 Then, update (and simplify!) the call to
58 :command:`target_include_directories` in the top-level ``CMakeLists.txt``.
59
60 Build and Run
61 -------------
62
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:
68
69 .. code-block:: console
70
71   mkdir Step3_build
72   cd Step3_build
73   cmake ../Step3
74   cmake --build .
75
76 Next, use the newly built ``Tutorial`` and verify that it is working as
77 expected.
78
79 Solution
80 --------
81
82 Let's update the code from the previous step to use the modern CMake
83 approach of usage requirements.
84
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.
89
90 At the end of ``MathFunctions/CMakeLists.txt``, use
91 :command:`target_include_directories` with the ``INTERFACE`` keyword, as
92 follows:
93
94 .. raw:: html
95
96   <details><summary>TODO 1: Click to show/hide answer</summary>
97
98 .. literalinclude:: Step4/MathFunctions/CMakeLists.txt
99   :caption: TODO 1: MathFunctions/CMakeLists.txt
100   :name: MathFunctions/CMakeLists.txt-target_include_directories-INTERFACE
101   :language: cmake
102   :start-after: # to find MathFunctions.h
103   :end-before: # TODO 3: Link to
104
105 .. raw:: html
106
107   </details>
108
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:
112
113 .. raw:: html
114
115   <details><summary>TODO 2: Click to show/hide answer</summary>
116
117 .. literalinclude:: Step4/CMakeLists.txt
118   :caption: TODO 2: CMakeLists.txt
119   :name: CMakeLists.txt-remove-EXTRA_INCLUDES
120   :language: cmake
121   :start-after: # add the MathFunctions library
122   :end-before: # add the executable
123
124 .. raw:: html
125
126   </details>
127
128 And here:
129
130 .. raw:: html
131
132   <details><summary>TODO 3: Click to show/hide answer</summary>
133
134 .. literalinclude:: Step4/CMakeLists.txt
135   :caption: TODO 3: CMakeLists.txt
136   :name: CMakeLists.txt-target_include_directories-remove-EXTRA_INCLUDES
137   :language: cmake
138   :start-after: # so that we will find TutorialConfig.h
139
140 .. raw:: html
141
142   </details>
143
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.