持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第19天,点击查看活动详情。你可以简单浏览一下目录,有需要的阅读,写文章不易,阅读之前请给我点个赞吧~
一、why CMake?
对于跨平台项目,如果不使用 CMake ,在不同平台将需要使用不同的build工具,不同的构建命令,最后生成二进制可执行文件
| Windows | Mac | Linux | |
|---|---|---|---|
| 构建工具 | Visual Studio | Xcode | Makefile |
| 构建命令 | msbuild | xcodebuild | make |
| 最终生成 | 二进制可执行文件 |
一旦需要更改源文件,我们要同时修改不同平台下的构建文件,很繁琐。
使用CMake的话,他们可以使用同一份 CMakeList.txt 根据环境生成不同的构建工具,然后我们再使用对应平台下的构建命令,就可以完成构建,生成同一份二进制文件。
此时,一旦需要更改源文件,我们只需要修改 CMakeList.txt ,后续过程不变,简化的不同平台的构建过程。
二、CMake 语法特性
前面我们通过直接灌输,模仿学习了很多CMake的实例,对于一些细节我们把握的还不是十分准确,这里我们来一起看一下细节。
1. 基本语法格式:指令(参数1 参数2 ...)
参数需要使用括号 参数之间使用空格或者分号分开
2. 指令是大小写无关的
3. 参数和变量是大小相关的
4. 变量使用${}方式取值
注意:但是在IF控制语句中直接使用变量名字
三、重要指令
1. cmake_minimum_required
指定CMake的最小版本要求
# 设置cmake最小版本号
cmake_minimum_required (VERSION 2.8)
2. project
指定工程名称
# 设置项目名称
project (learncmake)
3. set
显示的定义变量
# 设置 SRC 为 hello.cpp world.cpp 这两个文件
set(SRC hello.cpp world.cpp)
我们需要深入理解 cmake targets,你将遇到两种 targets
(1)executables
(2)libraries
下面通过4、5来深入理解一下他们
4. add_library
生成库文件
add_library(<name> [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
[<source>...])
有许多种 library 都可以使用这个命令,我们给定一个<name>,运行它将生成一个由源码<source>生成的叫做 <name> library target 。
实际生成的文件名,根据原生平台生成例如lib<name>.a 或者 <name>.lib。
具体的你还可以指定这些库的类型,默认是 STATIC 的;MODULE 在 Windows 上是更常见的,它可以生成 .dll 和 .lib 跨平台编译的时候不要使用
STATIC(静态库) | SHARED(动态库) | MODULE
例子
# 将 SRC 也就是上面的hello.cpp world.cpp生成共享库
add_library(hello SHARED ${SRC})
5. add_executable
生成可执行文件
add_executable(<name> [WIN32] [MACOSX_BUNDLE]
[EXCLUDE_FROM_ALL]
[source1] [source2 ...])
运行它的时候,由一些c++程序 [source1] 生成一个可执行程序( an executable target called <name> )。
根据不同的平台可能生成 <name>.exe 或者 <name>。
例子
# 编译main.cpp生成可执行文件main
add_executable(main main.cpp)
6.target_link_libraries
为 target 添加需要链接的共享库
# 将 hello 动态库文件链接到可执行文件 main
target_link_libraries(main hello)
target_link_libraries的对象必须是可执行文件或者库
7. add_subdirectory
向当前工程添加存放源文件的子目录
# 添加src子目录,src中需要有一个CMakeLists.txt
add_subdirectory(src)
添加子目录,子目录需要有一个CMakeLists.txt
8.aux_source_directory
发现一个目录下所有的源代码文件,并将列表存储在一个变量中,这个指令临时被用来自动构建源文件列表。
语法:aux_source_directory(dir VARIABLE)
# 定义SRC变量,其值为当前目录下所有的源代码文件
aux_source_directory(. SRC)
# 编译SRC变量所代表的源代码文件,生成main可执行文件
add_executable(main ${SRC})
9. add_compile_options
添加编译参数
add_compile_options(-Wall -std=c++11 -o2)
10. include_directories
向工程添加多个特定的头文件搜索路径
include_directories(./include)
11. link_directories
向工程添加多个特定的库文件搜索路径
link_directories(./lib)
尽量忘记下面这几个
所以这几个我放到了最后,功力不行的时候,他们容易制造混乱,大神说的,具体的大家也都再品品吧。
| add_compile_options |
|---|
| include_directories |
| link_directories |
| link_libraries |
三、CMake 常用变量
1. CMAKE_C_FLAGS
gcc编译选戏那个
2. CMAKE_CXX_FLAGS
g++编译选项
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O3")
3. CMAKE_BUILD_TYPE
编译类型Debug Release
# 发布时需要选择 Debug
set(CMAKE_BUILD_TYPE Debug)
# 发布时需要选择 Release
set(CMAKE_BUILD_TYPE Release)
4. CMAKE_BINARY_DIR
5. PROJECT_BINARY_DIR
6. PROJECTNAME_BINARY_DIR
构建路径
| 所在位置 | 4、5、6 这三个变量指代的内容是一致的 |
|---|---|
| 如果在源文件目录构建 | 指的就是工程顶级目录 |
| 如果是在源文件外构建,也就是我们通常构建的build目录(out-of-source编译) | 指的是工程编译发生的目录,这里也就是build目录 |
7. PROJECT_SOURCE_DIR
源码文件路径
8. EXECUTABLE_OUTPUT_PATH
可执行文件输出的存放路径
9. LBRARY_OUTPUT_PATH
库文件输出的存放路径
也可以自定义设置静态库文件的输出路径
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)