Adding System Introspection — CMake 4.0.2 Documentation (original) (raw)

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 expfunctions. Of course almost every platform has these functions but for this tutorial assume that they are not common.

Exercise 1 - Assessing Dependency Availability

Goal

Change implementation based on available system dependencies.

Helpful Resources

Files to Edit

Getting Started

The starting source code is provided in the Step7 directory. In this exercise, complete TODO 1 through TODO 5.

Start by editing MathFunctions/CMakeLists.txt. Include theCheckCXXSourceCompiles module. Then, usecheck_cxx_source_compiles to determine whether log and exp are available from cmath. If they are available, usetarget_compile_definitions() to specify HAVE_LOG and HAVE_EXPas compile definitions.

In the MathFunctions/mysqrt.cxx, include cmath. Then, if the system haslog and exp, use them to compute the square root.

Build and Run

Make a new directory called Step7_build. Run thecmake executable or thecmake-gui to configure the project and then build it with your chosen build tool and run the Tutorial executable.

This can look like the following:

mkdir Step7_build cd Step7_build cmake ../Step7 cmake --build .

Which function gives better results now, sqrt or mysqrt?

Solution

In this exercise we will use functions from theCheckCXXSourceCompiles module so first we must include it inMathFunctions/CMakeLists.txt.

TODO 1: Click to show/hide answer

TODO 1: MathFunctions/CMakeLists.txt

include(CheckCXXSourceCompiles)

Then test for the availability oflog and exp using check_cxx_compiles_source. This function lets us try compiling simple code with the required dependency prior to the true source code compilation. The resulting variables HAVE_LOGand HAVE_EXP represent whether those dependencies are available.

TODO 2: Click to show/hide answer

TODO 2: MathFunctions/CMakeLists.txt

check_cxx_source_compiles(" #include int main() { std::log(1.0); return 0; } " HAVE_LOG) check_cxx_source_compiles(" #include int main() { std::exp(1.0); return 0; } " HAVE_EXP)

Next, we need to pass these CMake variables to our source code. This way, our source code can tell what resources are available. If both log andexp are available, use target_compile_definitions() to specifyHAVE_LOG and HAVE_EXP as PRIVATE compile definitions.

TODO 3: Click to show/hide answer

TODO 3: MathFunctions/CMakeLists.txt

if(HAVE_LOG AND HAVE_EXP) target_compile_definitions(SqrtLibrary PRIVATE "HAVE_LOG" "HAVE_EXP" ) endif()

target_link_libraries(MathFunctions PRIVATE SqrtLibrary) endif()

Since we may be using log and exp, we need to modifymysqrt.cxx to include cmath.

TODO 4: Click to show/hide answer

TODO 4: MathFunctions/mysqrt.cxx

If log and exp are available on the system, then use them to compute the square root in the mysqrt function. The mysqrt function inMathFunctions/mysqrt.cxx will look as follows:

TODO 5: Click to show/hide answer

TODO 5: MathFunctions/mysqrt.cxx

#if defined(HAVE_LOG) && defined(HAVE_EXP) double result = std::exp(std::log(x) * 0.5); std::cout << "Computing sqrt of " << x << " to be " << result << " using log and exp" << std::endl; #else double result = x;

// do ten iterations for (int i = 0; i < 10; ++i) { if (result <= 0) { result = 0.1; } double delta = x - (result * result); result = result + 0.5 * delta / result; std::cout << "Computing sqrt of " << x << " to be " << result << std::endl; } #endif