Cmake (cmake)
Cmake Use tutorial (1) – start
Cmake Tutorial 2 – Adding libraries
Cmake use tutorial (3) – installation, testing, system self – check
Cmake Use tutorial (4) – file generator
Cmake Use tutorial (5) -cpack generate installation package
Cmake Use tutorial (6) – lousy syntax
Cmake Use Tutorial (7) – Processes and loops
Cmake: Macro and Function
This series of articles was translated from the official Cmake tutorial: CMake Tutorial.
Example program address: github.com/rangaofei/t…
It will not stop at the official tutorial. I as an Android developer, is really no Linux C program development experience, hope big guys forgive. The tutorial is done on MacOS, and I’ve tested most Linux as well, so IF there are special instructions, I’ll note them. This tutorial is based on cmake-3.10.2 and assumes that you have cmake installed.
This section adds installation rules and test support for our project. Here are just a few of the rules that were added in the tutorial; there will be a detailed section on customizing your own installation rules. Macos and Linux only.
Setting installation Rules
The installation rules are fairly simple. For mathFunction library, let’s say we have added this library, and install the header file and static library by adding the following two lines to mathFunction’s cMakelists.txt:
install (TARGETS MathFunctions DESTINATION bin)
install (FILES MathFunctions.h DESTINATION include)
Copy the code
Then add the following line to the cMakelusts.txt file in the root directory to install the executable and configuration files:
# add the install targets
install (TARGETS Tutorial DESTINATION bin)
install (FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
DESTINATION include)
Copy the code
Notice the first and third arguments in the above install.
TARGETS include six forms: ARCHIVE, LIBRARY, RUNTIME, OBJECTS, FRAMEWORK and BUNDLE. Note that Mathfunction installs LIBRARY, and the executable in the root directory is RUNTIME.
FILE Copies the given FILE to the specified directory. If no permission parameter is given, the default files installed by this form are OWNER_WRITE, OWNER_READ, GROUP_READ, and WORLD_READ.
TARGETS and FILE can be specified as relative and absolute directories.
DESTINATION is a relative path here, so take the default. C :/Program Files/${PROJECT_NAME} on Windows.
You can also set the installation path by setting the CMAKE_INSTALL_PREFIX variable, so that the installation location points not to /usr/local, but to the directory you specified.
cmake .
make
makeinstall
Copy the code
After the execution, the software is installed.
The installation addresses pointed to in the example are shown in the following table:
File/library | Installation position |
---|---|
MathFunctions | /usr/local/bin/ |
MathFunctions.h | /usr/local/include/ |
Tutorial | /usr/local/bin/ |
TutorialConfig.h | /usr/local/include |
Add test
Adding tests is as simple as adding the following code at the end of the cMakelists.txt file in the root directory to test whether the results generated by the input parameters are correct.
include(CTest)
# does the application run
add_test (TutorialRuns Tutorial 25)
# does it sqrt of 25
add_test (TutorialComp25 Tutorial 25)
set_tests_properties (TutorialComp25 PROPERTIES PASS_REGULAR_EXPRESSION "25 is 5")
# does it handle negative numbers
add_test (TutorialNegative Tutorial -25)
set_tests_properties (TutorialNegative PROPERTIES PASS_REGULAR_EXPRESSION "-25 is 0")
# does it handle small numbersAdd_test (TutorialSmall PROPERTIES 0.0001) set_tests_properties (TutorialSmall PROPERTIES PASS_REGULAR_EXPRESSION"0.0001 is 0.01")
# does the usage message work?
add_test (TutorialUsage Tutorial)
set_tests_properties (TutorialUsage PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number")
Copy the code
Once the build project is complete, you can run the ctest command line tool to run the tests. The first test simply verifies that the application is working properly, that no crash has occurred, and that the return value is 0. This is the basic form of a CTest test. The next several tests use the PASS_REGULAR_EXPRESSION test property to verify that the output of the test contains a particular string.
If you want to add many tests to test different input values, you might consider creating a macro (equivalent to a function) like this:
#define a macro to simplify adding tests, then use it
macro (do_test arg result)
add_test (TutorialComp${arg} Tutorial ${arg})
set_tests_properties (TutorialComp${arg}
PROPERTIES PASS_REGULAR_EXPRESSION ${result})
endmacro (do_test)
# do a bunch of result based tests
do_test (25 "25 is 5")
do_test (-25 "-25 is 0")
Copy the code
After building the project, run ctest to get the following results:
~ / Desktop/Tutorial/Step3 / build/ctest Test project/Users/saka/Desktop/Tutorial/Step3 / build Start 1: TutorialRuns 1/5 Test#1: TutorialRuns ..................... Passed 0.00 SEC
Start 2: TutorialComp25
2/5 Test #2: TutorialComp25 ................... Passed 0.01 SEC
Start 3: TutorialNegative
3/5 Test #3: TutorialNegative ................. Passed 0.00 SEC
Start 4: TutorialSmall
4/5 Test #4: TutorialSmall .................... Passed 0.00 SEC
Start 5: TutorialUsage
5/5 Test #5: TutorialUsage .................... Passed 0.00 SEC100% tests passed, 0 tests failed out of 5 Total Test time (real) = 0.03 SECCopy the code
As you can see, all tests pass.
Add a system self-check
Sometimes we might be developing for multiple platforms, some of which include a library, and some of which do not, so we can use a system self-check to determine whether to use a library provided by the platform or one written by ourselves.
Next we’ll add some code that depends on whether the target platform has log and exp functions. Of course, almost every platform has these features, but this tutorial assumes that they are less common. If the platform has a log library, we will use it to compute square roots, not functions in mysqrt.
The first to use CheckFunctionExists. Cmake macro to test the function exists. Write the code in the top-level cMakelists.txt file as follows:
# does this system provide the log and exp functions?
include (CheckFunctionExists)
check_function_exists (log HAVE_LOG)
check_function_exists (exp HAVE_EXP)
Copy the code
Then add code to tutorialconfig.h.id that uses the variables defined above:
// does the platform provide exp and log functions?
#cmakedefine HAVE_LOG
#cmakedefine HAVE_EXP
Copy the code
One caveat: the test code for log and exp must precede the configure_file command in tutorialconfig.h. The configure.file command immediately uses the current Settings configuration file in CMake. Finally, in the mysqrt function, we can provide an alternative implementation based on log and exp if they are available on the system:
// if we have both log and exp then use them
#if defined (HAVE_LOG) && defined (HAVE_EXP)
result = exp(log(x) * 0.5);#else // otherwise use an iterative approach.Copy the code