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