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 exp
functions. 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¶
MathFunctions/CMakeLists.txt
MathFunctions/mysqrt.cxx
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_EXP
as 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_LOG
and 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