Step 2: Adding a Library¶
At this point, we have seen how to create a basic project using CMake. In this step, we will learn how to create and use a library in our project. We will also see how to make the use of our library optional.
Exercise 1 - Creating a Library¶
To add a library in CMake, use the
add_library() command and specify
which source files should make up the library.
Rather than placing all of the source files in one directory, we can organize
our project with one or more subdirectories. In this case, we will create a
subdirectory specifically for our library. Here, we can add a new
CMakeLists.txt file and one or more source files. In the top level
CMakeLists.txt file, we will use the
to add the subdirectory to the build.
Add and use a library.
Files to Edit¶
In this exercise, we will add a library to our project that contains our own implementation for computing the square root of a number. The executable can then use this library instead of the standard square root function provided by the compiler.
For this tutorial we will put the library into a subdirectory called
MathFunctions. This directory already contains the header files
mysqrt.h. Their respective source files
mysqrt.cxx are also provided. We will not need
to modify any of these files.
mysqrt.cxx has one function called
mysqrt that provides similar functionality to the compiler's
MathFunctions.cxx contains one function
sqrt which serves
to hide the implementation details of
Help/guide/tutorial/Step2 directory, start with
TODO 1 and
First, fill in the one line
CMakeLists.txt in the
Next, edit the top level
Finally, use the newly created
MathFunctions library in
Build and Run¶
Below is a refresher of what that looks like from the command line:
cmake --build .
Try to use the newly built
Tutorial and ensure that it is still
producing accurate square root values.
CMakeLists.txt file in the
MathFunctions directory, we create
a library target called
source files for the library are passed as an argument to
add_library(). This looks like the following line:
TODO 1: Click to show/hide answer
add_library(MathFunctions MathFunctions.cxx mysqrt.cxx)
To make use of the new library we will add an
call in the top-level
CMakeLists.txt file so that the library will get
TODO 2: Click to show/hide answer
Next, the new library target is linked to the executable target using
TODO 3: Click to show/hide answer
Finally we need to specify the library's header file location.
Modify the existing
to add the
MathFunctions subdirectory as an include directory
so that the
MathFunctions.h header file can be found.
TODO 4: Click to show/hide answer
Now let's use our library. In
TODO 5: Click to show/hide answer
sqrt with the wrapper function
TODO 6: Click to show/hide answer
const double outputValue = mathfunctions::sqrt(inputValue);
Exercise 2 - Adding an Option¶
Now let us add an option in the MathFunctions library to allow developers to select either the custom square root implementation or the built in standard implementation. While for the tutorial there really isn't any need to do so, for larger projects this is a common occurrence.
CMake can do this using the
option() command. This gives users a
variable which they can change when configuring their cmake build. This
setting will be stored in the cache so that the user does not need to set
the value each time they run CMake on a build directory.
Add the option to build without
Files to Edit¶
Start with the resulting files from Exercise 1. Complete
TODO 7 through
First create a variable
USE_MYMATH using the
MathFunctions/CMakeLists.txt. In that same file, use that option
to pass a compile definition to the
MathFunctions.cxx to redirect compilation based on
mysqrt.cxx from being compiled when
USE_MYMATH is on
by making it its own library inside of the
USE_MYMATH block of
Build and Run¶
Since we have our build directory already configured from Exercise 1, we can rebuild by simply calling the following:
cmake --build .
Next, run the
Tutorial executable on a few numbers to verify that it's
Now let's update the value of
OFF. The easiest way is to
if you're in the terminal. Or, alternatively, if you want to change the
option from the command-line, try:
cmake ../Step2 -DUSE_MYMATH=OFF
Now, rebuild the code with the following:
cmake --build .
Then, run the executable again to ensure that it still works with
USE_MYMATH set to
OFF. Which function gives better results,
TODO 7: Click to show/hide answer
option(USE_MYMATH "Use tutorial provided math implementation" ON)
Next, make building and linking our library with
conditional using this new option.
TODO 8: Click to show/hide answer
target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
ON, the compile definition
be set. We can then use this compile definition to enable or disable
sections of our source code.
The corresponding changes to the source code are fairly straightforward.
MathFunctions.cxx, we make
USE_MYMATH control which square root
function is used:
TODO 9: Click to show/hide answer
Next, we need to include
USE_MYMATH is defined.
TODO 10: Click to show/hide answer
# include "mysqrt.h"
Finally, we need to include
cmath now that we are using
TODO 11: Click to show/hide answer
At this point, if
mysqrt.cxx would not be used
but it will still be compiled because the
MathFunctions target has
mysqrt.cxx listed under sources.
There are a few ways to fix this. The first option is to use
target_sources() to add
mysqrt.cxx from within the
block. Another option is to create an additional library within the
USE_MYMATH block which is responsible for compiling
the sake of this tutorial, we are going to create an additional library.
First, from within
USE_MYMATH create a library called
that has sources
TODO 12: Click to show/hide answer
# TODO 6: Link SqrtLibrary to tutorial_compiler_flags
target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
Next, we link
TODO 13: Click to show/hide answer
Finally, we can remove
mysqrt.cxx from our
source list because it will be pulled in when
SqrtLibrary is included.
TODO 14: Click to show/hide answer
With these changes, the
mysqrt function is now completely optional to
whoever is building and using the
MathFunctions library. Users can toggle
USE_MYMATH to manipulate what library is used in the build.