1 Step 2: Adding a Library
2 ========================
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
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.
15 Add the following one line ``CMakeLists.txt`` file to the ``MathFunctions``
18 .. literalinclude:: Step3/MathFunctions/CMakeLists.txt
19 :caption: MathFunctions/CMakeLists.txt
20 :name: MathFunctions/CMakeLists.txt
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
31 :caption: CMakeLists.txt
32 :name: CMakeLists.txt-add_subdirectory
34 # add the MathFunctions library
35 add_subdirectory(MathFunctions)
38 add_executable(Tutorial tutorial.cxx)
40 target_link_libraries(Tutorial PUBLIC MathFunctions)
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"
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.
54 .. literalinclude:: Step3/CMakeLists.txt
55 :caption: CMakeLists.txt
56 :name: CMakeLists.txt-option
58 :start-after: # should we use our own math functions
59 :end-before: # add the MathFunctions library
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.
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
76 .. literalinclude:: Step3/CMakeLists.txt
77 :caption: CMakeLists.txt
78 :name: CMakeLists.txt-target_link_libraries-EXTRA_LIBS
80 :start-after: # add the MathFunctions library
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.
88 The corresponding changes to the source code are fairly straightforward.
89 First, in ``tutorial.cxx``, include the ``MathFunctions.h`` header if we
92 .. literalinclude:: Step3/tutorial.cxx
93 :caption: tutorial.cxx
94 :name: tutorial.cxx-ifdef-include
96 :start-after: // should we include the MathFunctions header
99 Then, in the same file, make ``USE_MYMATH`` control which square root
102 .. literalinclude:: Step3/tutorial.cxx
103 :caption: tutorial.cxx
104 :name: tutorial.cxx-ifdef-const
106 :start-after: // which square root function should we use?
107 :end-before: std::cout << "The square root of
109 Since the source code now requires ``USE_MYMATH`` we can add it to
110 ``TutorialConfig.h.in`` with the following line:
112 .. literalinclude:: Step3/TutorialConfig.h.in
113 :caption: TutorialConfig.h.in
114 :name: TutorialConfig.h.in-cmakedefine
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?
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.
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
130 .. code-block:: console
132 cmake ../Step2 -DUSE_MYMATH=OFF
134 Rebuild and run the tutorial again.
136 Which function gives better results, ``sqrt`` or ``mysqrt``?