cmake 使用

简介

CMake是一个比make更高级的编译配置工具,它可以根据不同平台、不同的编译器,生成相应的Makefile或者vcproj项目。通过编写CMakeLists.txt,可以控制生成的Makefile,从而控制编译过程。CMake自动生成的Makefile不仅可以通过make命令构建项目生成目标文件,还支持安装(make install)、测试安装的程序是否能正确执行(make test,或者ctest)、生成当前平台的安装包(make package)、生成源码包(make package_source)、产生Dashboard显示数据并上传等高级功能,只要在CMakeLists.txt中简单配置,就可以完成很多复杂的功能,包括写测试用例。如果有嵌套目录,子目录下可以有自己的CMakeLists.txt。

步骤

  • 编写CMakeLists.txt
  • 执行命令cmake PATHccmake PATH 生成Makefile
  • 使用make命令编译,make -j4 指定编译并行度
  • 使用 make install 安装

编译

指定安装路径

参考 这里

1
2
3
4
5
6
# 3.15 +
$ cmake --install /path/to/build --prefix /path/to/install [--config <CONFIG>]

# < 3.15
$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX=/path/to/install -P cmake_install.cmake

指定编译类型

1
2
3
4
5
# 1
$ cmake -DCMAKE_INSTALL_PREFIX:PATH=/path/to/install -DCMAKE_BUILD_TYPE=Release /path/to/src

# 2
$ cmake --config Release --build . --target install

语法

CMakeLists.txt 的语法比较简单,由命令、注释和空格组成。# 后面的是注释。

commond (args ...)

  • commond为命令名,大小写不敏感
  • args为参数
    • 如果包含空格,使用双引号

变量引用

变量引用用 ${VAR} 语法

命令

set

set命令将多变量放在一起。

1
set (Foo a b c)
  • commond(${Foo}) 等价于 command(a b c)
  • commond("${Foo}") 等价于 command("a b c")

cmake_minimum_required

指定运行此配置文件所需的CMake的最低版本。

cmake_minimum_required (VERSION 2.8)

project

指定项目信息。

1
project (Demo)

add_executable

指定生成目标。

1
add_executable(Demo demo.cpp)

aux_source_directory

查找指定目录下的所有源文件,将结果存进指定变量名。

1
aux_source_directory(<dir> <variable>)
1
2
3
4
cmake_minimum_required (VERSION 2.8)
project (Demo)
aux_source_directory (. DIR_SRCS)
add_executable(Demo ${DIR_SRCS})

add_subdirectory

指明项目包含一个子目录,这样该目录下的CMakeLists.txt文件和源文件也会被处理。

1
add_subdirectory(math)

指明可执行文件需要链接的库。

1
target_link_libraries(Demo MathFunctions)

add_library

将指定的源文件生成链接文件,然后添加到工程中去

1
2
aux_source_directory(. DIR_LIB_SRCS)
add_library(MathFunctions ${DIR_LIB_SRCS})

指定连接器查找库的文件夹。此命令的相对路径被解释为相对于当前源目录。

格式

1
link_directories(directory1 directory2 ...)

示例

1
link_directories(${PROJECT_BINARY_DIR}/third_party/googletest/)

include_directories

将给定的目录添加到编译器用来搜索头文件的目录中。相对路径被解释为相对于当前源目录。

格式

1
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])

示例

1
2
include_directories(${PROJECT_SOURCE_DIR}/third_party/glog/)
include_directories(${PROJECT_SOURCE_DIR}/third_party/hdfs/)

find_package_handle_standard_args

用于 find_package 的实现。

变量

Cache

1
2
3
4
5
6
7
# CACHE, 不覆盖已有值. 
## 用途
### 1. 在命令行指定变量, 且不被覆盖
set(MY_CACHE_VARIABLE "VALUE" CACHE STRING "Description")

# FORCE, 强制设置
set(MY_CACHE_VARIABLE "VALUE" CACHE STRING "" FORCE)

常用变量

  • PROJECT_BINARY_DIR
    • Full path to build directory for project.
  • PROJECT_SOURCE_DIR
    • Top level source directory for the current project.
  • CMAKE_CURRENT_SOURCE_DIR
    • This the full path to the source directory that is currently being processed by cmake.

Scope

1
2
3
add_subdirectory : 建立新的 scope
include : 不会建立新的 scope
function : 建立新的 scope

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
bovenson@HP:~/Git/notes/C++/Code/CMake/test$ tree
.
├── CMakeLists.txt
└── t.cpp

0 directories, 2 files
bovenson@HP:~/Git/notes/C++/Code/CMake/test$ cat t.cpp
#include <iostream>

using namespace std;

int main() {
cout<<"Hello"<<endl;
return 0;
}
bovenson@HP:~/Git/notes/C++/Code/CMake/test$ cat CMakeLists.txt
project("test")
add_executable(Hello t.cpp)
bovenson@HP:~/Git/notes/C++/Code/CMake/test$ cmake .
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/bovenson/Git/notes/C++/Code/CMake/test
bovenson@HP:~/Git/notes/C++/Code/CMake/test$ tree
.
├── CMakeCache.txt
├── CMakeFiles
│ ├── 3.5.1
│ │ ├── CMakeCCompiler.cmake
│ │ ├── CMakeCXXCompiler.cmake
│ │ ├── CMakeDetermineCompilerABI_C.bin
│ │ ├── CMakeDetermineCompilerABI_CXX.bin
│ │ ├── CMakeSystem.cmake
│ │ ├── CompilerIdC
│ │ │ ├── a.out
│ │ │ └── CMakeCCompilerId.c
│ │ └── CompilerIdCXX
│ │ ├── a.out
│ │ └── CMakeCXXCompilerId.cpp
│ ├── cmake.check_cache
│ ├── CMakeDirectoryInformation.cmake
│ ├── CMakeOutput.log
│ ├── CMakeTmp
│ ├── feature_tests.bin
│ ├── feature_tests.c
│ ├── feature_tests.cxx
│ ├── Hello.dir
│ │ ├── build.make
│ │ ├── cmake_clean.cmake
│ │ ├── DependInfo.cmake
│ │ ├── depend.make
│ │ ├── flags.make
│ │ ├── link.txt
│ │ └── progress.make
│ ├── Makefile2
│ ├── Makefile.cmake
│ ├── progress.marks
│ └── TargetDirectories.txt
├── cmake_install.cmake
├── CMakeLists.txt
├── Makefile
└── t.cpp

6 directories, 31 files
bovenson@HP:~/Git/notes/C++/Code/CMake/test$ make
Scanning dependencies of target Hello
[ 50%] Building CXX object CMakeFiles/Hello.dir/t.cpp.o
[100%] Linking CXX executable Hello
[100%] Built target Hello
bovenson@HP:~/Git/notes/C++/Code/CMake/test$ tree
.
├── CMakeCache.txt
├── CMakeFiles
│ ├── 3.5.1
│ │ ├── CMakeCCompiler.cmake
│ │ ├── CMakeCXXCompiler.cmake
│ │ ├── CMakeDetermineCompilerABI_C.bin
│ │ ├── CMakeDetermineCompilerABI_CXX.bin
│ │ ├── CMakeSystem.cmake
│ │ ├── CompilerIdC
│ │ │ ├── a.out
│ │ │ └── CMakeCCompilerId.c
│ │ └── CompilerIdCXX
│ │ ├── a.out
│ │ └── CMakeCXXCompilerId.cpp
│ ├── cmake.check_cache
│ ├── CMakeDirectoryInformation.cmake
│ ├── CMakeOutput.log
│ ├── CMakeTmp
│ ├── feature_tests.bin
│ ├── feature_tests.c
│ ├── feature_tests.cxx
│ ├── Hello.dir
│ │ ├── build.make
│ │ ├── cmake_clean.cmake
│ │ ├── CXX.includecache
│ │ ├── DependInfo.cmake
│ │ ├── depend.internal
│ │ ├── depend.make
│ │ ├── flags.make
│ │ ├── link.txt
│ │ ├── progress.make
│ │ └── t.cpp.o
│ ├── Makefile2
│ ├── Makefile.cmake
│ ├── progress.marks
│ └── TargetDirectories.txt
├── cmake_install.cmake
├── CMakeLists.txt
├── Hello
├── Makefile
└── t.cpp

6 directories, 35 files
bovenson@HP:~/Git/notes/C++/Code/CMake/test$ ./Hello
Hello

参考