Now we will add a library to our project. This library will contain 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 calledMathFunctions
.
在教程中,咱們把這個庫放到一個子目錄文件MathFunctions
中。
This directory already contains a header file,MathFunctions.h
, and a source filemysqrt.cxx
.
The source file has one function calledmysqrt
that provides similar functionality to the compiler’ssqrt
function.app
Add the following one lineCMakeLists.txt
file to theMathFunctions
directory:ide
add_library(MathFunctions mysqrt.cxx)
To make use of the new library we will add anadd_subdirectory
call in the top-levelCMakeLists.txt
file so that the library will get built.
We add the new library to the executable, and addMathFunctions
as an include directory so that themqsqrt.h
header file can be found. The last few lines of the top-levelCMakeLists.txt
file should now look like:ui
# add the MathFunctions library add_subdirectory(MathFunctions) # add the executable add_executable(Tutorial tutorial.cxx) target_link_libraries(Tutorial PUBLIC MathFunctions) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}MathFunctions" )
Now let us make the MathFunctions library optional. While for the tutorial there really isn’t any need to do so, for larger projects this is a common occurrence.
The first step is to add an option to the top-levelCMakeLists.txt
file.this
option(USE_MYMATH "Use tutorial provided math implementation" ON) # configure a header file to pass some of the CMake settings # to the source code configure_file(TutorialConfig.h.in TutorialConfig.h)
This option will be displayed in the CMake GUI and ccmake with a default value of ON that can be changed by the user. 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.code
The next change is to make building and linking the MathFunctions library conditional. To do this we change the end of the top-levelCMakeLists.txt
file to look like the following:component
if(USE_MYMATH) add_subdirectory(MathFunctions) list(APPEND EXTRA_LIBS MathFunctions) list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}MathFunctions") endif() # add the executable add_executable(Tutorial tutorial.cxx) target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS}) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}" ${EXTRA_INCLUDES} )
Note the use of the variableEXTRA_LIBS
to collect up any optional libraries to later be linked into the executable. The variableEXTRA_INCLUDES
is used similarly for optional header files. This is a classic approach when dealing with many optional components, we will cover the modern approach in the next step.教程
The corresponding changes to the source code are fairly straightforward. First, intutorial.cxx
, include theMathFunctions.h
header if we need it:ci
#ifdef USE_MYMATH #include "MathFunctions.h" #endif
Then, in the same file, makeUSE_MYMATH
control which square root function is used:get
#ifdef USE\_MYMATH const double outputValue \= mysqrt(inputValue); #else const double outputValue \= sqrt(inputValue); #endif
Since the source code now requiresUSE_MYMATH
we can add it toTutorialConfig.h.in
with the following line:input
#cmakedefine USE_MYMATH
Exercise: Why is it important that we configureTutorialConfig.h.in
after the option forUSE_MYMATH
? What would happen if we inverted the two?
Runcmakeorcmake-guito configure the project and then build it with your chosen build tool. Then run the built Tutorial executable.
Use ccmake or the CMake GUI to update the value ofUSE_MYMATH
. Rebuild and run the tutorial again. Which function gives better results, sqrt or mysqrt?