Address: http://www.ibm.com/developerworks/cn/linux/l-cn-cmake/index.html
This article describes how to use cmake, a cross-platform automated build system, on Linux. Cmake is a tool easier to use than automake, which can free programmers from complicated compilation and connection processes. This article describes how to use cmake to process multi-source file directories, how to find and use other development kits, and how to Generate debug and release programs.
Cmake Introduction
Cmake is a cross-platform automated construction system. It uses a file named cmakelists.txt to describe the building process and generate standard building files, for example, makefile of Unix or projects/workspaces of Windows visual c ++. The file cmakelists.txt needs to be manually written. You can also write a script to generate it semi-automatically. Cmake provides more concise syntax than AutoConfig. The process for generating and compiling makefile using cmake on Linux is as follows:
Write
CmakeLists.txt
。
Execute Command
“
cmake PATH
”
Or
“
ccmake PATH
”
Generate
Makefile ( PATH
Yes
CMakeLists.txt
Directory
)
。
Use
make
Command to compile.
First Project
Assume that only one of our projects is available.Source files
main.cpp
Listing 1 source file main. cpp
1 #include<iostream>2 3 int main()4 {5 std::cout<<"Hello word!"<<std::endl;6 return 0;7 } |
To build this project, we need to write the file cmakelists.txt and put it in the same directory as main. cpp:
Listing 2 cmakelists.txt
1 PROJECT(main)2 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)3 AUX_SOURCE_DIRECTORY(. DIR_SRCS)4 ADD_EXECUTABLE(main ${DIR_SRCS}) |
The syntax of cmakelists.txt is simple and consists of commands, comments, and spaces. commands are case-insensitive and the content after the symbol "#" is considered as comments. The command consists of the command name, Parentheses, and parameters. The parameters are separated by spaces. For example, for the cmakelists.txt file in Listing 2, the first line is a command named project and the parameter is main. This command indicates that the project name is main. The command line 2 limits the cmake version. The third line uses the command aux_source_directory to assign the source file name in the current directory to the variable dir_srcs. The description of the command aux_source_directory in the cmake manual is as follows:
aux_source_directory(<dir> <variable>) |
This command assigns the <dir> all source file names to the <variable> parameter. The fourth line uses the command add_executable to indicate that the source file in the dir_srcs variable needs to be compiled into an executable file named main.
After compiling the file cmakelists.txt, you must use the cmake or ccmake command to generate the makefile. The difference between ccmake and cmake is that ccmake provides a graphical operation interface. The cmake command is executed as follows:
cmake [options] <path-to-source> |
Here we enter the directory where main. cpp is located and run "cmake." To Get The makefile and compile it using make, as shown in.
Figure 1. camke running result
How to process multiple source file directories
CMake
Process source code points
It is also very simple to deploy in different directories. Now let's assume that our source codeThe distribution is as follows:
:
Figure 2. source code distribution
The files under the src directory must be compiled into a Linked Library.
Step 1: cmakelists.txt in the main directory of the project
Create the file cmakelists.txt in step 2. The file content is as follows:
Cmakelists.txt in step 2 in listing 3
1 PROJECT(main)2 CMAKE_MINIMUM_REQUIRED(VERSION 2.6) 3 ADD_SUBDIRECTORY( src )4 AUX_SOURCE_DIRECTORY(. DIR_SRCS)5 ADD_EXECUTABLE(main ${DIR_SRCS} )6 TARGET_LINK_LIBRARIES( main Test ) |
Compared with listing 2, this file adds the following content: the third line, use the command add_subdirectory to indicate that this project contains a sub-directory SRC. Line 6: run the target_link_libraries command to specify that the executable file main needs to connect to a linked library named test.
Step 2: cmakelists.txt In the subdirectory
Create cmakelists.txt In the SRC subdirectory. The file content is as follows:
Listing 4. cmakelists.txt In the src directory
1 AUX_SOURCE_DIRECTORY(. DIR_TEST1_SRCS)2 ADD_LIBRARY ( Test ${DIR_TEST1_SRCS}) |
Use the add_library command in this file to compile the source files in the src directory into a shared library.
Step 3: Execute cmake
Now we have completed the compilation of all the cmakelists.txt files in the project. Go to the directory Step 2 and execute the commands "cmake." and "make" in sequence. The result is as follows:
Figure 3. cmake execution result when processing multiple source file directories
During cmake execution, the cmakelists.txt in step 2 is parsed first. When the program executes the add_subdirectory (SRC) command, the src directory is used to parse the cmakelists.txt.
Find and use other library methods in the project
We will use some function libraries when developing software. These function libraries may be installed in different systems in different locations, during compilation, you must first find the header file of these software packages and the directory of The Link Library to generate compilation options. For example, if you want to use a bokeli database project, you need the header file db_cxx.h and the Link Library libdb_cxx.so. Now there is a source code file main. cpp in the project's root directory.
Step 1: Library description file
Create the directory cmake/modules/in the root directory of the project, and create the findlibdb_cxx.cmake file under cmake/modules/. The content is as follows:
Listing 5. File findlibdb_cxx.cmake
01 MESSAGE(STATUS "Using bundled Findlibdb.cmake...")02 03 FIND_PATH(04 LIBDB_CXX_INCLUDE_DIR05 db_cxx.h 06 /usr/include/ 07 /usr/local/include/ 08 )09 10 FIND_LIBRARY(11 LIBDB_CXX_LIBRARIES NAMES db_cxx12 PATHS /usr/lib/ /usr/local/lib/13 ) |
The findlibdb_cxx.cmake file name must comply with the specification: findlibname. cmake, where name is the name of the function library. The findlibdb_cxx.cmake syntax is the same as that of cmakelists.txt. Three commands are used: Message, find_path, and find_library.
Command
MESSAGE
Yes
Set parameters
Content
Output to Terminal
。
Command
FIND_PATH
Specifies the path to search for header files,
The prototype is as follows:
:
find_path(<VAR> name1 [path1 path2 ...])
The command in the Parameter
path*
Search for files in the specified directory
name1
And save the searched path in the Variable
VAR
. List
5
The
3
-
8
The line indicates
/usr/include/
And
/usr/local/include/
Searching for files
db_cxx.h ,
And set
db_cxx.h
The path is saved in
LIBDB_CXX_INCLUDE_DIR
.
Command
FIND_LIBRARY
Same
FIND_PATH
Similar
,
Used to find the Linked Library and save the result in the variable. List
5
The
10
-
13
The line indicates the Directory
/usr/lib/
And
/usr/local/lib/
Search
db_cxx
Link Library
,
And save the result in
LIBDB_CXX_LIBRARIES
。
Step 2: cmakelist.txt in the project root directory
Create cmakelist.txt in the project root directory:
Listing 6. You can find the cmakelist.txt
01 PROJECT(main)02 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)03 SET(CMAKE_SOURCE_DIR .)04 SET(CMAKE_MODULE_PATH ${CMAKE_ROOT}/Modules ${CMAKE_SOURCE_DIR}/cmake/modules) 05 AUX_SOURCE_DIRECTORY(. DIR_SRCS)06 ADD_EXECUTABLE(main ${DIR_SRCS})07 08 FIND_PACKAGE( libdb_cxx REQUIRED)09 MARK_AS_ADVANCED(10 LIBDB_CXX_INCLUDE_DIR11 LIBDB_CXX_LIBRARIES12 )13 IF (LIBDB_CXX_INCLUDE_DIR AND LIBDB_CXX_LIBRARIES)14 MESSAGE(STATUS "Found libdb libraries")15 INCLUDE_DIRECTORIES(${LIBDB_CXX_INCLUDE_DIR})16 MESSAGE( ${LIBDB_CXX_LIBRARIES} )17 TARGET_LINK_LIBRARIES(main ${LIBDB_CXX_LIBRARIES}18 )19 ENDIF (LIBDB_CXX_INCLUDE_DIR AND LIBDB_CXX_LIBRARIES) |
In this file, lines 4th indicate the findlibdb_cxx.cmake in the directory./cmake/modules, and lines 8-19 indicate the process of searching the Link Library and header files. Run the find_package command to find the findlibdb_cxx.cmake file in the directory indicated by cmake_module_path. Row 13-19 is a condition judgment statement, indicating that if libdb_cxx_include_dir and libdb_cxx_libraries are both assigned values, you need to set the header file to the keystore during compilation and set the executable file main to be connected to the libdb_cxx_libraries.
Step 3: Execute cmake
After findlibdb_cxx.cmake and cmakelist.txt are compiled, execute "cmake." and "make" in the root directory of the project. The result is shown in:
Figure 4. cmake execution results when other libraries are used
Use cmake to Generate debug and release programs
In Visual Studio, we can generate the debug and release programs, and use cmake to achieve the above results. Debugging information is required for the executable files generated by the project of the debug version, and optimization is not required for the release version. These features are determined by the compilation parameters in gcc/g ++. If the optimization degree is adjusted to the highest level, you need to set the parameter-O3. The lowest parameter is-O0, which means no optimization is performed; the parameter for adding debugging information is-g-ggdb. If this parameter is not added, the debugging information will not be included in the generated binary file.
Cmake has a variable cmake_build_type, which can be debug release relwithdebinfo and minsizerel. When the value of this variable is debug, cmake uses the strings in the variables cmake_cxx_flags_debug and cmake_c_flags_debug as the compilation options to generate makefile. When the value of this variable is release, the project uses the cmake_cxx_flags_release and cmake_c_flags_release variables to generate makefile.
Assume that there is only one file main. cpp in the project. Below is a cmakelist.txt program that can generate the debug and release versions:
Listing 7
1 PROJECT(main)2 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)3 SET(CMAKE_SOURCE_DIR .)4 5 SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")6 SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")7 8 AUX_SOURCE_DIRECTORY(. DIR_SRCS)9 ADD_EXECUTABLE(main ${DIR_SRCS}) |
Two variables cmake_cxx_flags_debug and cmake_cxx_flags_release are set in lines 5th and 6, which are the compilation options for debug and release respectively. After editing cmakelist.txt, run the ccmake command to generate the makefile. Enter "ccmake." In the root directory of the project to enter a graphical interface, as shown in:
Figure 5. ccmake Interface
Follow the prompts on the page and press "c" to perform Configure. The page displays the cmake_build_type configuration variable. As shown in:
Figure 6. ccmake interface after configure is executed
Next, we will first generate the makefile for Debug: Set the variable cmake_build_type to debug, perform configure by "C", generate makefile by "g", and exit. Run the find * | xargs grep "O0" command and the result is as follows:
Listing 8 find * | xargs grep "O0" execution result
CMakeFiles/main.dir/flags.make:CXX_FLAGS = -O0 -Wall -g -ggdb CMakeFiles/main.dir/link.txt:/usr/bin/c++ -O0 -Wall -g -ggdb CMakeFiles/main.dir/main.cpp.o -o main -rdynamic CMakeLists.txt:SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb") |
The result shows that the generated makefile uses the variable cmake_cxx_flags_debug as the compile-time parameter.
Next we will generate the release makefile: Execute the "ccmake." command again to set the variable cmake_build_type to release, generate the makefile, and exit. Run the find * | xargs grep "O0" command and the result is as follows:
Listing 9 find * | xargs grep "O0" execution result
CMakeLists.txt:SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb") |
The result of executing the find * | xargs grep "O3" command is as follows:
Listing 10. Find * | xargs grep "O3" execution result
CMakeCache.txt:CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUGCMakeCache.txt:CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUGCMakeFiles/main.dir/flags.make:CXX_FLAGS = -O3 -Wall CMakeFiles/main.dir/link.txt:/usr/bin/c++ -O3 -Wall CMakeFiles/main.dir/main.cpp.o -o main -rdynamic CMakeLists.txt:SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall") |
The two results indicate that the generated makefile uses the variable cmake_cxx_flags_release as the compile-time parameter.