70 lines
2.6 KiB
Plaintext
70 lines
2.6 KiB
Plaintext
# Adding System Introspection #
|
||
|
||
Let us consider adding some code to our project that depends on features the
|
||
target platform may not have. For this example, we will add some code that
|
||
depends on whether or not the target platform has the log and exp functions. Of
|
||
course almost every platform has these functions but for this tutorial assume
|
||
that they are not common.
|
||
|
||
If the platform has log and exp then we will use them to compute the square
|
||
root in the mysqrt function. We first test for the availability of these
|
||
functions using the CheckSymbolExists.cmake macro in the top-level CMakeLists
|
||
file as follows:
|
||
|
||
# does this system provide the log and exp functions?
|
||
include(CheckSymbolExists)
|
||
set(CMAKE_REQUIRED_LIBRARIES "m")
|
||
check_symbol_exists(log "math.h" HAVE_LOG)
|
||
check_symbol_exists(exp "math.h" HAVE_EXP)
|
||
|
||
Now let's add these defines to TutorialConfig.h.in so that we can use them
|
||
from mysqrt.cxx:
|
||
|
||
// does the platform provide exp and log functions?
|
||
#cmakedefine HAVE_LOG
|
||
#cmakedefine HAVE_EXP
|
||
|
||
Modify mysqrt.cxx to include math.h. Next, in the mysqrt function we can
|
||
provide an alternate implementation based on log and exp if they are available
|
||
on the system using the following code:
|
||
|
||
// if we have both log and exp then use them
|
||
#if defined(HAVE_LOG) && defined (HAVE_EXP)
|
||
double result = exp(log(x)*0.5);
|
||
std::cout << "Computing sqrt of " << x << " to be " << result << " using log" << std::endl;
|
||
#else
|
||
...
|
||
|
||
Run cmake or cmake-gui to configure the project and then build it with your
|
||
chosen build tool.
|
||
|
||
You will notice that even though HAVE_LOG and HAVE_EXP are both defined mysqrt
|
||
isn't using them. We should realize quickly that we have forgotten to include
|
||
TutorialConfig.h in mysqrt.cxx. We will also need to update
|
||
MathFunctions/CMakeLists.txt with where it is located.
|
||
|
||
So let's go ahead and update MathFunctions/CMakeLists.txt to look like:
|
||
|
||
add_library(MathFunctions mysqrt.cxx)
|
||
|
||
target_include_directories(MathFunctions
|
||
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
|
||
PRIVATE ${Tutorial_BINARY_DIR}
|
||
)
|
||
|
||
install(TARGETS MathFunctions DESTINATION lib)
|
||
install(FILES MathFunctions.h DESTINATION include)
|
||
|
||
Now all we need to do is include TutorialConfig.h in mysqrt.cxx
|
||
|
||
At this point you should go ahead and build the project again.
|
||
|
||
Run the built Tutorial executable. Which function gives better results now,
|
||
Step1’s sqrt or Step5’s mysqrt?
|
||
|
||
Exercise: Why is it important that we configure TutorialConfig.h.in after the
|
||
checks for HAVE_LOG and HAVE_EXP? What would happen if we inverted the two?
|
||
|
||
Exercise: Is there a better place for us to save the HAVE_LOG and HAVE_EXP
|
||
values other than in TutorialConfig.h?
|