基础知识
CMake简介
CMake是一个开源的可扩展工具,用于独立于编译器的管理构建过程。CMake必须和本地构建系统联合使用,在每个源码目录中,需要编写CMakeLists.txt文件,以声明如何生成标准的构建文件(例如GNU Make的Makefiles,或者MSVS的解决方案)。
CMake支持所有平台的内部构建(in-source build)和外部构建(out-of-source build)。内部构建的源码目录和二进制目录为同一目录,即CMake会改变源码目录的内容。通过外部构建,可以针对单个源码树进行多重构建(Multiple builds )。
CMake会生成一个方便用户编辑的缓存文件,当其运行时,会定位头文件、库、可执行文件,这些信息被收集到缓存文件中。用户可以在生成本地构建文件之前编辑它。
CMake命令行支持自动或者交互式的运行。CMake还提供了一个基于QT的GUI,其名称为cmake-gui。注意此GUI同样依赖于环境变量的正确设置。
基本语法
CMakeLists.txt包含一系列的命令,每个命令都是 COMMAND (args…) 的形式,多个参数使用空白符分隔。CMake提供了很多预定义命令,你可以方便的扩展自己的命令。
CMake支持简单的变量,它们或者是字符串,或者是字符串的列表。引用一个变量的语法是 ${VAR_NAME} 。
如果向一个命令传递列表变量,效果等同于向它逐个传递列表成员:
1 2 | set(V 1 2 3) # V的值是1 2 3 command(${V}) # 等价于command(1 2 3) |
要把一个列表变量作为整体传递,只需要加上双引号即可:
1 | command("${V}") # 等价于command("1 2 3") |
CMake可以直接访问环境变量和Windows注册表,前者使用语法 $ENV{VAR} ,后者使用语法[HKEY_CURRENT_USER\\SOFTWARE\\path;key] 。示例:
1 2 3 4 | # 读取环境变量 message(STATUS "LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}" ) # 设置环境变量 set(ENV{PATH} "/home/alex/scripts") |
CMake的优势
- 支持多个底层构建工具,例如GNU Make、MSVC、XCode等等,可以生成这些构建工具需要的配置文件
- 通过分析环境变量、Windows注册表等,自动搜索构建所需的程序、库、头文件
- 支持创建复杂的命令
- 很方便的在共享库、静态库两种构建方式之间切换
- 自动生成、维护C/C++文件依赖关系,并且在大部分平台上支持并行构建
在开发跨平台软件时,CMake具有以下额外优势:
- 可以测试机器字节序和其它硬件特性
- 统一的构建配置文件
- 支持依赖于机器特定信息的配置,例如文件的位置
安装CMake
Shell
1 2 3 4 5 6 7 | # Ubuntu sudo apt-get install cmake # Redhat yum install cmake # Mac OS X with Macports sudo port install cmake # Window https://cmake.org/files/v3.5/cmake-3.5.2-win32-x86.zip |
HelloWorld
C++源码:
C++
1 2 3 4 5 6 7 | #include <iostream>
using namespace std;
int main() { return 0; } |
要通过CMake编译上述文件,需要在同一目录下放置CMakeLists.txt文件:
CMakeLists.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # 需要最小的CMake版本 cmake_minimum_required(VERSION 3.3) # 工程的名称,会作为MSVS的Workspace的名字 project(intellij_taste)
# 全局变量:CMAKE_SOURCE_DIR CMake的起始目录,即源码的根目录 # 全局变量:PROJECT_NAME 工程的名称 # 全局变量:PROJECT_SOURCE_DIR 工程的源码根目录的完整路径
# 全局变量:构建输出目录。默认的,对于内部构建,此变量的值等于CMAKE_SOURCE_DIR;否则等于构建树的根目录 set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/bin) # ${}语法用于引用变量 # 全局变量:可执行文件的输出路径 set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}) # 全局变量:库文件的输出路径 set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}) # 设置头文件位置 include_directories("${PROJECT_SOURCE_DIR}") # 设置C++标志位 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") # 设置源文件集合 set(SOURCE_FILES main.cpp) # 添加需要构建的可执行文件,第二个以及后续参数是用于构建此文件的源码文件 add_executable(intellij_taste ${SOURCE_FILES}) |
在上述目录中执行下面两条命令,即可执行构建:
Shell
1 2 3 4 5 6 7 8 9 10 | # 创建一个build子目录作为构建树 mkdir build && cd build && cmake .. && cd ..
# 在build/bin子目录中生成可执行文件: # cmake --build <dir> [options] [-- [native-options]] cmake --build build -- -j3 # --表示把其余选项传递给底层构建工具
# 注意,亦可使用底层构建系统,例如make命令或者MSVC的IDE cd build make -j3 |