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