Imported Upstream version 3.23.2
[platform/upstream/cmake.git] / Help / guide / tutorial / Adding a Library.rst
1 Step 2: Adding a Library
2 ========================
3
4 Now we will add a library to our project. This library will contain our own
5 implementation for computing the square root of a number. The executable can
6 then use this library instead of the standard square root function provided by
7 the compiler.
8
9 For this tutorial we will put the library into a subdirectory
10 called ``MathFunctions``. This directory already contains a header file,
11 ``MathFunctions.h``, and a source file ``mysqrt.cxx``. The source file has one
12 function called ``mysqrt`` that provides similar functionality to the
13 compiler's ``sqrt`` function.
14
15 Add the following one line ``CMakeLists.txt`` file to the ``MathFunctions``
16 directory:
17
18 .. literalinclude:: Step3/MathFunctions/CMakeLists.txt
19   :caption: MathFunctions/CMakeLists.txt
20   :name: MathFunctions/CMakeLists.txt
21   :language: cmake
22
23 To make use of the new library we will add an :command:`add_subdirectory`
24 call in the top-level ``CMakeLists.txt`` file so that the library will get
25 built. We add the new library to the executable, and add ``MathFunctions`` as
26 an include directory so that the ``MathFunctions.h`` header file can be found.
27 The last few lines of the top-level ``CMakeLists.txt`` file should now look
28 like:
29
30 .. code-block:: cmake
31         :caption: CMakeLists.txt
32         :name: CMakeLists.txt-add_subdirectory
33
34         # add the MathFunctions library
35         add_subdirectory(MathFunctions)
36
37         # add the executable
38         add_executable(Tutorial tutorial.cxx)
39
40         target_link_libraries(Tutorial PUBLIC MathFunctions)
41
42         # add the binary tree to the search path for include files
43         # so that we will find TutorialConfig.h
44         target_include_directories(Tutorial PUBLIC
45                                   "${PROJECT_BINARY_DIR}"
46                                   "${PROJECT_SOURCE_DIR}/MathFunctions"
47                                   )
48
49 Now let us make the ``MathFunctions`` library optional. While for the tutorial
50 there really isn't any need to do so, for larger projects this is a common
51 occurrence. The first step is to add an option to the top-level
52 ``CMakeLists.txt`` file.
53
54 .. literalinclude:: Step3/CMakeLists.txt
55   :caption: CMakeLists.txt
56   :name: CMakeLists.txt-option
57   :language: cmake
58   :start-after: # should we use our own math functions
59   :end-before: # add the MathFunctions library
60
61 This option will be displayed in the :manual:`cmake-gui <cmake-gui(1)>` and
62 :manual:`ccmake <ccmake(1)>`
63 with a default value of ``ON`` that can be changed by the user. This setting
64 will be stored in the cache so that the user does not need to set the value
65 each time they run CMake on a build directory.
66
67 The next change is to make building and linking the ``MathFunctions`` library
68 conditional. To do this,  we will create an ``if`` statement which checks the
69 value of the option.  Inside the ``if`` block, put the
70 :command:`add_subdirectory` command from above with some additional list
71 commands to store information needed to link to the library and add the
72 subdirectory as an include directory in the ``Tutorial`` target.
73 The end of the top-level ``CMakeLists.txt`` file will now look like the
74 following:
75
76 .. literalinclude:: Step3/CMakeLists.txt
77   :caption: CMakeLists.txt
78   :name: CMakeLists.txt-target_link_libraries-EXTRA_LIBS
79   :language: cmake
80   :start-after: # add the MathFunctions library
81
82 Note the use of the variable ``EXTRA_LIBS`` to collect up any optional
83 libraries to later be linked into the executable. The variable
84 ``EXTRA_INCLUDES`` is used similarly for optional header files. This is a
85 classic approach when dealing with many optional components, we will cover
86 the modern approach in the next step.
87
88 The corresponding changes to the source code are fairly straightforward.
89 First, in ``tutorial.cxx``, include the ``MathFunctions.h`` header if we
90 need it:
91
92 .. literalinclude:: Step3/tutorial.cxx
93   :caption: tutorial.cxx
94   :name: tutorial.cxx-ifdef-include
95   :language: c++
96   :start-after: // should we include the MathFunctions header
97   :end-before: int main
98
99 Then, in the same file, make ``USE_MYMATH`` control which square root
100 function is used:
101
102 .. literalinclude:: Step3/tutorial.cxx
103   :caption: tutorial.cxx
104   :name: tutorial.cxx-ifdef-const
105   :language: c++
106   :start-after: // which square root function should we use?
107   :end-before: std::cout << "The square root of
108
109 Since the source code now requires ``USE_MYMATH`` we can add it to
110 ``TutorialConfig.h.in`` with the following line:
111
112 .. literalinclude:: Step3/TutorialConfig.h.in
113   :caption: TutorialConfig.h.in
114   :name: TutorialConfig.h.in-cmakedefine
115   :language: c++
116   :lines: 4
117
118 **Exercise**: Why is it important that we configure ``TutorialConfig.h.in``
119 after the option for ``USE_MYMATH``? What would happen if we inverted the two?
120
121 Run the :manual:`cmake  <cmake(1)>` executable or the
122 :manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it
123 with your chosen build tool. Then run the built Tutorial executable.
124
125 Now let's update the value of ``USE_MYMATH``. The easiest way is to use the
126 :manual:`cmake-gui <cmake-gui(1)>` or  :manual:`ccmake <ccmake(1)>` if you're
127 in the terminal. Or, alternatively, if you want to change the option from the
128 command-line, try:
129
130 .. code-block:: console
131
132   cmake ../Step2 -DUSE_MYMATH=OFF
133
134 Rebuild and run the tutorial again.
135
136 Which function gives better results, ``sqrt`` or ``mysqrt``?