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?
|