cmake knowledge sorting

Posted by batfink on Tue, 04 Jan 2022 22:18:13 +0100

cmake knowledge sorting

This paper adopts Creative Commons Attribution 4.0 international license agreement For permission, please indicate the original link when reprinting. Please keep all the contents of the picture when using it, which can be scaled appropriately, and attach the article link where the picture is located in the quotation.

CMake

CMakeLists.txt

cmake PATH
ccmake PATH
The difference between ccmake and cmake is that the former provides an interactive interface
PATH is cmakelists Txt directory
Compile using the make command.

Common predefined variables in CMake

Predefined variables for CMake

  • PROJECT_SOURCE_DIR: project root directory;
  • PROJECT_BINARY_DIR: the directory where the cmake command is run. The author suggests that it be defined as ${PROJECT_SOURCE_DIR}/ build. See the external compilation section below for specific reasons;
  • CMAKE_INCLUDE_PATH: environment variable, non cmake variable;
  • CMAKE_LIBRARY_PATH: environment variable;
  • CMAKE_CURRENT_SOURCE_DIR: currently processed cmakelists Txt file path;
  • CMAKE_CURRENT_BINARY_DIR: target compilation directory;
  • Use add_ The surdirectory instruction can change the value of the variable;
  • The set (executable_output_path < dir >) instruction does not affect this variable, but changes the storage path of the final target file;
  • CMAKE_CURRENT_LIST_FILE: output the cmakelists that call this variable Txt;
  • CMAKE_CURRENT_LIST_LINE: output the line where the variable is located;
  • CMAKE_MODULE_PATH: define the path of your cmake module;
  • EXECUTABLE_OUTPUT_PATH: redefine the storage location of the target binary executable file;
  • LIBRARY_OUTPUT_PATH: redefine the storage location of the target link library file;
  • PROJECT_NAME: returns the project name defined by the project directive;
  • CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS: used to control the writing method of IF... ELSE... Statements;

System information predefined variables

  • CMAKE_MAJOR_VERSION cmake major version number, such as 2 in 2.8.6
  • CMAKE_MINOR_VERSION cmake minor version number, such as 8 in 2.8.6
  • CMAKE_PATCH_VERSION cmake patch level, such as 6 in 2.8.6
  • CMAKE_SYSTEM system name, for example, Linux-2.6.22
  • CMAKE_SYSTEM_NAME does not contain the system name of the version, such as Linux
  • CMAKE_SYSTEM_VERSION system version, such as 2.6.22
  • CMAKE_SYSTEM_PROCESSOR processor name, such as i686
  • UNIX is TRUE on all UNIX like platforms, including OS X and cygwin
  • win32 is TRUE on all win32 platforms, including cygwin

Switch options

  • BUILD_SHARED_LIBS controls the default library compilation method.
    Note: if not set, use ADD_LIBRARY does not specify the library type. By default, the libraries generated by compilation are static libraries.
  • CMAKE_C_FLAGS setting C compilation options
  • CMAKE_CXX_FLAGS setting C + + compilation options

Common grammar

CMakeLists.txt syntax is relatively simple, composed of commands, comments and spaces, where commands are case insensitive. What # follows the symbol is considered a comment. The command consists of the command name, parentheses, and parameters, separated by spaces.

  1. Under each directory where cmake operation is required, there must be a file cmakelists txt .
  2. The cmake instruction is not case sensitive.
  3. The built-in variable cmake is case sensitive.
  4. The variable is valued in ${} mode, but the variable name is directly used in the IF control statement;
  5. Instruction (parameter 1, parameter 2...), the parameters are enclosed in parentheses, and the parameters are separated by spaces or semicolons;

CMAKE_MINIMUM_REQUIRED

This statement can generally be placed in cmakelists Txt is used to describe the minimum version requirements of CMake.
This line of command is optional. We can not write this sentence, but in some cases, if cmakelists When some commands unique to the higher version of cmake are used in the txt file, you need to add such a line to remind the user to upgrade to this version before executing cmake.

cmake_minimum_required (VERSION 2.6)

PROJECT

PROJECT(name)

Name: project name
This instruction is generally placed in cmakelists Txt, which defines the name of the project. However, the executable generated by the final compilation of the project is not necessarily the name of the project.

After the instruction is executed, two variables will be automatically created:

< projectname >_BINARY_DIR: Binary file saving path;
< projectname >_SOURCE_DIR: Source code path;
project(CRNode)

The last instruction is executed, that is, an item name crnode is defined, and two variables will be generated accordingly: CRNode_BINARY_DIR, CRNode_SOURCE_DIR.
Two variables are predefined in cmake: PROJECT_BINARY_DIR and PROJECT_SOURCE_DIR.
In this example:

PROJECT_BINARY_DIR = CRNode_BINARY_DIR
PROJECT_SOURCE_DIR = CRNode_SOURCE_DIR  

It is recommended to use project directly_ BINARY_ Dir and PROJECT_SOURCE_DIR, so that if the project name changes, it will not affect cmakelists Txt file.
Whether the above two variables are the same involves whether the compilation method is internal compilation or external compilation. In case of internal compilation, the above two variables are the same; In case of external compilation, the two variables are different.

External construction and internal construction

Suppose you have completed cmakelists Txt, in cmakelists Txt directory, there are two methods to execute cmake:

cmake ./
make

And:

mkdir build
cd ./build
cmake ../
make

The first method is internal build, and the second method is external build. The biggest difference between the above two methods is that the working paths of cmake and make are different.
In the internal construction method, the intermediate files and executable files generated by cmake will be stored in the project directory; In the external construction method, the intermediate files and executable files are stored in the build directory.
External build methods are recommended. The advantages are obvious: the code directory is kept clean to the greatest extent. The generation, compilation and installation are in other directories different from the project directory. Under the external construction method, PROJECT_SOURCE_DIR points to the same directory as the internal build, cmakelists Txt root directory; And project_ BINARY_ Unlike dir, it points to cmakelists Txt under the root directory.

SET

SET(VAR [VALUE] [CACHE TYPEDOCSTRING [FORCE]])

eg:

SET(CMAKE_INSTALL_PREFIX /usr/local)

We explicitly put cmake_ INSTALL_ The value of prefix is defined as / usr/local, so when you execute the make install command in the case of external build, make will copy the generated executable file to the / usr/local/bin directory.
Of course, the installation path of the executable is CMAKE_INSTALL_PREFIX can also be specified when executing the cmake command. The cmake parameters are as follows:

cmake -DCMAKE_INSTALL_PREFIX=/usr ..

If cmake parameter and cmakelists If the value is not specified in the txt file, the value is the default / usr/local.

ADD_SUBDIRECTORY

ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
  • source_dir: source file path;
  • [binary_dir]: storage path of intermediate binary and target binary;
  • [EXECLUDE_FROM_ALL]: exclude this directory from the compilation process;

This instruction is used to add a subdirectory for storing source files to the current project, and specify the storage location of intermediate binary and target binary.
EXCLUDE_ FROM_ The all parameter means to exclude this directory from compilation. For example, sometimes there is an example in a project. After the project is built, you may need to enter the example directory to build it separately.

INCLUDE_DIRECTORIES

INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)
  • [AFTER|BEFORE]: append flag, which specifies whether to control append or set before;
  • [SYSTEM]: (I don't know why)
  • dir1,..., dir n: a series of header file search paths added;

Add multiple specific header file search paths to the project, separated by spaces. It is similar to the compilation parameter - l in gcc, which specifies the path for the compiler to search the header file during compilation. When the header file required by the project is not in the system default search path, specify the path.
AFTER/BEFORE parameter, which controls whether to append or set before. By default, the current header file search path is appended.
Note: if the path contains spaces, you can use double quotation marks to enclose it.
eg:

INCLUDE_DIRECTORIES(/usr/include/thrift)

ADD_EXECUTABLE

ADD_EXECUTABLE(exename srcname)
  • exename: executable name
  • srcname: the source file that generates the executable
    This command gives the name of the source file and indicates the name of the executable file to be compiled.
    eg:
ADD_EXECUTABLE(hello ${SRC_LIST})

The above routine describes Src_ The source file in the list variable needs to compile an executable file named hello.

eg:

SET(SRC_LIST main.cc
        rpc/CRNode.cpp 
        rpc/Schd_types.cpp 
        task/TaskExecutor.cpp
        task/TaskMoniter.cpp
        util/Const.cpp 
        util/Globals.cc
        )

ADD_EXECUTABLE(CRNode ${SRC_LIST})

In this routine, it is defined that the project will generate an executable file named CRNode, and the dependent source file is the variable SRC_LIST defines the list of source files.
Note: if the project name defined in the PROJECT() instruction above is also defined as CRNode, there is no problem, and there is no relationship between the two.

ADD_LIBRARY

ADD_LIBRARY(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 ... sourceN)
  • libname: library file name;
  • [SHARED|STATIC|MODULE]: generate library file type (shared library / static library)
  • [EXCLUDE_FROM_ALL]: indicates that the library will not be built by default
  • source1,..., sourceN: generate the source file that the library depends on
    eg:
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

Variable EXECUTABLE_OUTPUT_PATH, LIBRARY_OUTPUT_PATH

EXECUTABLE_OUTPUT_PATH is the path to generate executable files, LIBRARY_OUTPUT_PATH is the path to the generated library file.
We can SET the location of the final target binary through the SET instruction, that is, the final generated project executable file and the final shared library, without including the intermediate file generated by compilation.

SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)

Note: instruction add_ EXECUTABLE, ADD_ The location where library appears. If you need to change the target storage path, add the above definition there.

LINK_DIRECTORIES

LINK_DIRECTORIES(directory1 directory2 ...)

This directive is used to add a search path for an external library.

TARGET_LINK_LIBRARIES

TARGET_LINK_LIBRARIES(target library1 <debug | optimized> library2 ..)
  • Target: target file;
  • library1,..., libraryN: link external library files;
    Specify the external library that needs to be linked when linking the target file. The effect is similar to the gcc compilation parameter - L, which solves the problem of external library dependency.

MESSAGE

MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display" ...)

Output user-defined information or variable values to the terminal

  • SEND_ERROR: an error is generated and the generation process is skipped;
  • STATUS: output information prefixed with -;
  • FATAL_ERROR: immediately terminate all cmake processes;

SET_TARGET_PROPERTIES

SET_TARGET_PROPERTIES(target1 target2 ...
            PROPERTIES prop1 value1 prop2 value2 ...)

Set some properties of goals and change how they are built.

AUX_SOURCE_DIRECTORY

Basic control grammar

actual combat

Single source file

# CMake minimum version number requirements
# cmake_minimum_required: Specifies the minimum version of CMake required to run this profile
cmake_minimum_required (VERSION 2.8)

# Project information
# Project: the parameter value is Demo1. This command indicates that the name of the project is Demo1
project (Demo1)

# Specify build target
# add_executable: name it main The source file of CC is compiled into an executable file named Demo
add_executable(Demo main.cc)

cmake .

Multiple source files

Multiple source files in the same directory

# CMake minimum version number requirements
cmake_minimum_required (VERSION 2.8)

# Project information
project (Demo2)

# Specify build target
add_executable(Demo main.cc MathFunctions.cc)

aux_source_directory: find all source files in the specified directory, and then save the results into the specified variable name.

 aux_source_directory(<dir> <variable>)
# CMake minimum version number requirements
cmake_minimum_required (VERSION 2.8)

# Project information
project (Demo2)

# Find all source files in the current directory
# And save the name to DIR_SRCS variable
aux_source_directory(. DIR_SRCS)

# Specify build target
add_executable(Demo ${DIR_SRCS})

Multiple directories, multiple source files

add_subdirectory: the project contains a subdirectory math, so that cmakelists in the math directory Txt files and source code will also be processed.
target_link_libraries: indicates that the executable main needs to be connected to a linked library called MathFunctions.

# CMake minimum version number requirements
cmake_minimum_required (VERSION 2.8)

# Project information
project (Demo3)

# Find all source files in the current directory
# And save the name to DIR_SRCS variable
aux_source_directory(. DIR_SRCS)

# Add math subdirectory
add_subdirectory(math)

# Specify build target 
add_executable(Demo main.cc)

# Add link library
target_link_libraries(Demo MathFunctions)

Cmakelists. In the subdirectory txt:

# Find all source files in the current directory
# And save the name to DIR_LIB_SRCS variable
aux_source_directory(. DIR_LIB_SRCS)

# Generate link library
add_library (MathFunctions ${DIR_LIB_SRCS})

The command add is used in this file_ Compile the library as a statically linked source file in the src Library Directory.

Custom compilation options

CMake allows you to add compilation options to the project, so that you can select the most appropriate compilation scheme according to your environment and needs.

# CMake minimum version number requirements
cmake_minimum_required (VERSION 2.8)

# Project information
project (Demo4)

# Add a configuration header file to handle CMake's settings for the source code
configure_file (
  "${PROJECT_SOURCE_DIR}/config.h.in"
  "${PROJECT_BINARY_DIR}/config.h"
  )

# Do you want to use your own MathFunctions library
option (USE_MYMATH
       "Use provided math implementation" ON)

# Add MathFunctions library
if (USE_MYMATH)
  include_directories ("${PROJECT_SOURCE_DIR}/math")
  add_subdirectory (math)  
  set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (USE_MYMATH)

# Find all source files in the current directory
# And save the name to DIR_SRCS variable
aux_source_directory(. DIR_SRCS)

# Specify build target
add_executable(Demo ${DIR_SRCS})
target_link_libraries (Demo  ${EXTRA_LIBS})

Of which:
Configure on line 7_ The file command is used to add a configuration header file config h. This file is created by CMake from config. Exe h. In generation, through such a mechanism, the generation of code can be controlled by predefined parameters and variables.
The option command ON line 13 adds a USE_MYMATH option, and the default value is ON.
Line 17 according to use_ The value of the mymath variable determines whether to use the MathFunctions library written by ourselves.

config.h.in

#cmakedefine USE_MYMATH

CMake will automatically generate config.config according to the settings in the CMakeLists configuration file H file.

You can find the use you just defined_ For the mymath option, press the direction key on the keyboard to jump between different option windows, and press the enter key to modify the option. After modification, you can press option c to complete the configuration, and then press key g to confirm the generation of Makefile. For other operations of ccmake, please refer to the instruction prompt given at the bottom of the window.

Installation and testing

CMake can also specify installation rules and add tests. These two functions can be performed by using make install and make test after generating the makefile. In the previous GNU Makefile, you may need to write two pseudo targets and corresponding rules for install and test, but in CMake, such work also requires only a few simple commands.

Custom installation rules

math/CMakeLists.txt indicates the installation path of the MathFunctions library

 # Specify the installation path of the MathFunctions library
 install (TARGETS MathFunctions DESTINATION bin)
 install (FILES MathFunctions.h DESTINATION include)

Change the CMakeLists file in the root directory

# Specify the installation path
install (TARGETS Demo DESTINATION bin)
install (FILES "${PROJECT_BINARY_DIR}/config.h"
         DESTINATION include)

Through the above customization, the generated Demo file and MathFunctions library libmathfunctions O files will be copied to / usr/local/bin, and MathFunctions H and generated config The H file is copied to / usr/local/include. (here, / usr/local / is the root directory of the default installation. You can specify which root directory these files should be copied to by modifying the value of the CMAKE_INSTALL_PREFIX variable).

Add tests to the project

Adding tests is also simple. CMake provides a testing tool called CTest. All we have to do is to call a series of add_ in the CMakeLists file of the project root directory. Test command.

# enable test
enable_testing()

# Test whether the program runs successfully
add_test (test_run Demo 5 2)

# Test whether the help information can be prompted normally
add_test (test_usage Demo)
set_tests_properties (test_usage
  PROPERTIES PASS_REGULAR_EXPRESSION "Usage: .* base exponent")

# Square of test 5
add_test (test_5_2 Demo 5 2)

set_tests_properties (test_5_2
PROPERTIES PASS_REGULAR_EXPRESSION "is 25")

# Test 10 to the 5th power
add_test (test_10_5 Demo 10 5)

set_tests_properties (test_10_5
PROPERTIES PASS_REGULAR_EXPRESSION "is 100000")

# 10 times of test
add_test (test_2_10 Demo 2 10)

set_tests_properties (test_2_10
PROPERTIES PASS_REGULAR_EXPRESSION "is 1024")

The above code contains four tests. First test_run is used to test whether the program runs successfully and returns a value of 0. The remaining three tests are used to test whether the square of 5, the 5th power of 10 and the 10th power of 2 can get the correct results. Where PASS_REGULAR_EXPRESSION is used to test whether the output contains the following string.

You can do this by writing macros

# Define a macro to simplify testing
macro (do_test arg1 arg2 result)
  add_test (test_${arg1}_${arg2} Demo ${arg1} ${arg2})
  set_tests_properties (test_${arg1}_${arg2}
    PROPERTIES PASS_REGULAR_EXPRESSION ${result})
endmacro (do_test)
 
# Use this macro for a series of data tests
do_test (5 2 "is 25")
do_test (10 5 "is 100000")
do_test (2 10 "is 1024")

reference material

CMake introduction practice
CMake entry actual combat source code
CMake syntax

Topics: cmake