cmake 允许开发者通过编写 CMakeList.txt 文件来管理项目的编译流程,根据目标用户平台生成对应的 makefile 和工程文件,例如可以生成 unix 的 Makefile 文件或者 windows 的 visual studio 工程。从而达到 "Write once,run everywhere"。
另外,一般手写 makefile 是一件很痛苦的事,cmake 脚本语言是一种类似 C 的语言,所以更适合程序员理解记忆。避免在 makefile 的逻辑中迷失自我。
接下来先简单介绍一些 cmake 的一些概念。然后再通过实际例子,使用 cmake 编译程序运行。
cmake 的命令(command)类似与 C++ 中的函数方法,可以接受一些参数执行特定的任务。
cmake 的命令名称是不区分大小写的。
cmake commands: https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html
常用的命令:
cmake 还支持结构化语句:
cmake 不会关注缩进,但是为了阅读性最好添加缩进空格。每行语句结束也不用加上 ";"。
环境变量用于配置编译器标志、链接器标志、常规构建过程的测试配置。可以通过 set()
和 unset()
设置环境变量的值。
cmake 环境变量列表: https://cmake.org/cmake/help/latest/manual/cmake-env-variables.7.html
cmake 环境变量介绍:https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#cmake-language-environment-variables
CMAKE_<LANG>_FLAGS
用于配置指定语言编译器的标识。
上面的变量会被特定的环境变量初始化,例如 CMAKE_CXX_FLAGS 被 CXXFLAGS 初始化,CXXFLAGS 是一个环境变量,CXXFLAGS 的初始值来自调用环境,为 cxx(c++) 文件编译提供编译选项。cmake 将这个环境变量的值和 cmake 默认的编译选项合并后,存储到 CMAKE_CXX_FLAGS 变量中(即,CMAKE_CXX_FLAGS 初始化自 CXXFLAGS),然后提供给编译工具链。但是如果定义了 CMAKE_CXX_FLAGS 变量,那么 CXXFLAGS 的值就会被忽略。
例如 gcc
命令的 -Wall
用于打印所有的警告信息,我们可以使用 set 命令设置该编译选项。
# 不建议使用这种,它会覆盖原有的选项
set(CMAKE_CXX_FLAGS "-Wall")
# 使用这种,标识在原有的参数后面增加 -Wall,没有覆盖原有的命令 flag
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
可以使用 set 命令定义一个变量,cmake 中也包含一些预定义的变量,例如上面的 CMAKE_CXX_FLAGS
。
与命令不同,变量是区分大小写的。
cmake 变量:https://cmake.org/cmake/help/v3.0/manual/cmake-language.7.html#variables
一些常用的预定义变量(暂时不知道如何翻译比较好,先保留英文):
可以通过 ${variable_name}
获取变量值。
message("CXX Standard: ${CMAKE_CXX_STANDARD}")
set(CMAKE_CXX_STANDARD 14)
可以定义一个新变量。
set(TRIAL_VARIABLE "VALUE")
message("${TRIAL_VARIABLE}")
cmake 中所有的值都被存储为字符串形式,但是一个字符串在特定的上下文环境可以被当成list (列表) 使用。
设置 files 变量为一个列表,实际存储的是以分号隔开的字符串。
set(files a.txt b.txt c.txt)
# sets files to "a.txt;b.txt;c.txt"
遍历 files
列表:
foreach(file ${files})
message("Filename: ${file}")
endforeach()
生成器表达式:https://cmake.org/cmake/help/v3.3/manual/cmake-generator-expressions.7.html
创建一个 `main.cpp`` 文件,内容如下:
#include <iostream>
int main() {
std::cout<<"Hello CMake!"<<std::endl;
}
我们可以直接使用 g++ 编译该文件:
$ g++ main.cpp -o cmake_hello
但是我们的目的是使用 cmake 输出 makefile 文件,管理项目的构建过程,在 main.cpp 增加一个 CMakeLists.txt
文件,内容如下:
cmake_minimum_required(VERSION 3.9.1)
project(CMakeHello)
add_executable(cmake_hello main.cpp)
CMakeLists 的三行代码分别做了下面三件事:
接下来通过 cmake 生成 makefile:
$ cmake CMakeLists.txt
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
cmake 命令执行过程中,可以自动识别了 c(xx) 编译器的版本信息。通过这些信息生成一些默认的配置(CMakeCaceh.txt 等)和 makefile。
接下来可以执行 make 命令构建项目:
$ make all
# or
$ make cmake_hello
make 命令执行完毕后,当前目录会出现可执行文件 cmake_hello
,该文件名由 add_executable
命令指定。
有时候我们用到了一些 C++ 新语法,例如你用到了 C++14 中的语法,所以我们需要指定 C++ 的版本。
将 main.cpp
改为如下内容:
#include <iostream>
auto sum(int a, int b) {
return a + b;
}
int main() {
std::cout << "Hello CMake!" << std::endl;
std::cout << "Sum of 3 + 4: " << sum(3, 4) << std::endl;
}
auto 为 C++14 新增语法,所以编译时需要指定 C++14。
更新 CMakeLists.txt
:
cmake_minimum_required(VERSION 3.9.1)
project(CMakeHello)
set(CMAKE_CXX_STANDARD 14)
add_executable(cmake_hello main.cpp)
通过设置 CMAKE_CXX_STANDARD 变量值,设定 C++14。如果 C++ 版本不正确,构建会出错。
如果你的项目需要编译至多平台:
cmake 提供了一些变量可以用来检测系统相关信息:
CMAKE_SYSTEM
: 存储了完整的系统信息,例如 "Linux-2.4.22", "FreeBSD-5.4-RELEASE", "Windows 5.1"。CMAKE_SYSTEM_NAME
: 生成的可执行文件的平台名称,常用的有 Windows、Darwin、Linux、Android、FreeBSD 等,例如需要构建 windows 上的可执行程序,可以设置该变量值为 Windows,如果没有设置该值,该变量值默认为 CMAKE_HOST_SYSTEM_NAME。CMAKE_SYSTEM_VERSION
: 系统的内核版本CMAKE_SYSTEM_PROCESSOR
: 系统的处理器名称(e.g. "Intel(R) Pentium(R) M processor 2.00GHz")CMAKE_HOST_SYSTEM_NAME
: cmake 脚本运行的系统名称。我们可以使用下面的脚本,判断当前系统的信息:
cmake_minimum_required(VERSION 3.9.1)
project(CMakeHello)
# UNIX, WIN32, WINRT, CYGWIN, APPLE are environment variables as flags set by default system
if (UNIX)
message("This is a ${CMAKE_SYSTEM_NAME} system")
elseif (WIN32)
message("This is a Window System")
endif()
if (${CMAKE_SYSTEM_NAME} MATCHES Darwin)
message("This is a ${CMAKE_SYSTEM_NAME} system")
elseif(${CMAKE_SYSTEM_NAME} MATCHES Windows)
message("This is a Windows System")
endif()
add_executable(cmake_hello main.cpp)
可以使用 add_definitions
命令定义宏,在宏名称前需要加上 -D
标识,例如定义 CMAKEMACROSAMPLE
宏。
add_definitions(-DCMAKEMACROSAMPLE="Apple MacOS")
修改 CMakeLists.txt
文件:
cmake_minimum_required(VERSION 3.9.1)
project(CMakeHello)
set(CMAKE_CXX_STANDARD 14)
# or use MATCHES to see if actual system name
# Darwin is Apple's system name
if(${CMAKE_SYSTEM_NAME} MATCHES Darwin)
add_definitions(-DCMAKEMACROSAMPLE="Apple MacOS")
elseif(${CMAKE_SYSTEM_NAME} MATCHES Windows)
add_definitions(-DCMAKEMACROSAMPLE="Windows PC")
elseif(${CMAKE_SYSTEM_NAME} MATCHES Linux)
add_definitions(-DCMAKEMACROSAMPLE="Linux PC")
endif()
add_executable(cmake_hello main.cpp)
在 main.cpp 中打印宏:
#include <iostream>
#ifndef CMAKEMACROSAMPLE
#define CMAKEMACROSAMPLE "NO SYSTEM NAME"
#endif
int main() {
std::cout << "Hello CMake!" << std::endl;
std::cout << "CMAKEMACROSAMPLE: " << CMAKEMACROSAMPLE << std::endl;
return 0;
}
构建应用时,我们希望保持源文件树干净整洁,将自动生成的文件和源文件放在不同的位置。
很多开发者习惯在源文件的根目录下创建一个 build 文件夹,然后再 build 文件夹下执行 cmake 命令。
所以,首先创建一个 build 文件夹:
$ mkdir build
$ ls -al
total 32
drwxr-xr-x 4 fangyan fangyan 4096 Jan 16 23:10 .
drwxr-xr-x 16 fangyan fangyan 12288 Jan 16 22:06 ..
drwxr-xr-x 7 fangyan fangyan 4096 Jan 16 23:10 .git
-rw-r--r-- 1 fangyan fangyan 494 Jan 16 23:04 CMakeLists.txt
drwxr-xr-x 2 fangyan fangyan 4096 Jan 16 23:10 build
-rw-r--r-- 1 fangyan fangyan 246 Jan 16 23:05 main.cpp
在 build 文件夹执行 cmake 命令。
$ cd build
$ cmake ..
$ ls -al
total 40
drwxr-xr-x 3 fangyan fangyan 4096 Jan 16 23:12 .
drwxr-xr-x 4 fangyan fangyan 4096 Jan 16 23:10 ..
-rw-r--r-- 1 fangyan fangyan 13861 Jan 16 23:12 CMakeCache.txt
drwxr-xr-x 5 fangyan fangyan 4096 Jan 16 23:12 CMakeFiles
-rw-r--r-- 1 fangyan fangyan 5268 Jan 16 23:12 Makefile
-rw-r--r-- 1 fangyan fangyan 1660 Jan 16 23:12 cmake_install.cmake
上面的命令在 build 文件夹下生成了 build 文件。另外一般习惯将 build
文件夹添加到 .gitignore
文件夹中。
但是我们不希望每次都创建一个 build 文件夹,再进入(cd) build 文件夹,然后执行 cmake ..
命令。
我们可以使用 cmake 命令的 -H
和 -B
选项:
-H
: 指定源文件根目录-B
: 指定 build 文件夹路径所以我们可以直接再源文件根目录下执行下面的命令达到同样的效果:
$ cmake -H. -Bbuild
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/fangyan/projects/program/cmake-study/build
还可以再 CMakeLists.txt 文件中设置 CMAKE_RUNTIME_OUTPUT_DIRECTORY 或者 EXECUTABLE_OUTPUT_PATH 指定库文件和可执行文件生成的位置。
cmake_minimum_required(VERSION 3.9.1)
project(CMakeHello)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
add_executable(cmake_hello main.cpp)
执行 cmake -H. -Bbuild
后,然后进入 build 文件夹,执行 make 命令,生成的可执行文件在 build/bin/cmake_hello
。
还有一些变量可以设置动态库(.dll,.so)的路径:
或者设置静态库(.a 或者 .lib)的路径:
首先准备需要编译的代码文件,在当前目录增加两个文件:
// ============ lib/math/operations.hpp
#ifndef CMAKEHELLO_OPERATIONS_HPP
#define CMAKEHELLO_OPERATIONS_HPP
namespace math {
class operations {
public:
int sum(const int& a, const int& b);
int mult(const int& a, const int& b);
int div(const int& a, const int& b);
int sub(const int& a, const int& b);
};
}
#endif
// ============ lib/math/operations.cpp
#include "operations.hpp"
#include <exception>
#include <iostream>
#include <stdexcept>
int math::operations::sum(const int& a, const int& b) {
return a + b;
}
int math::operations::mult(const int& a, const int& b) {
return a * b;
}
int math::operations::div(const int& a, const int& b) {
if (b == 0) {
throw std::overflow_error("Divide by zero exception");
}
return a / b;
}
int math::operations::sub(const int& a, const int& b) {
return a - b;
}
然后更新 main.cpp 如下:
#include <iostream>
#include "lib/math/operations.hpp"
#ifndef CMAKEMACROSAMPLE
#define CMAKEMACROSAMPLE "NO SYSTEM NAME"
#endif
int main() {
std::cout << "Hello CMake!" << std::endl;
math::operations op;
int sum = op.sum(3, 4);
std::cout << "Sum of 3 + 4 :" << sum << std::endl;
return 0;
}
我们可以将库文件(lib/math)一起打包到最后生成的可执行文件中,只需要在 add_executable 中添加需要编译的文件即可。
cmake_minimum_required(VERSION 3.9.1)
project(CMakeHello)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
add_executable(cmake_hello main.cpp lib/math/operations.cpp lib/math/operations.hpp)
然后执行 cmake -H. -Bbuild
即生成 makefile,执行 make 命令可以生成最终可执行文件(cmake_hello)。
你可以创建一个 SOURCES
变量,将需要编译的文件路径放存储到 source list 中。
cmake_minimum_required(VERSION 3.9.1)
project(CMakeHello)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set (SOURCES main.cpp lib/math/operations.cpp lib/math/operations.hpp)
add_executable(cmake_hello ${SOURCES})
我们可以将库文件打包成分离的共享库(动态库)或者静态库。
将库文件打包成分离的库文件,在 build 时,还需要一个链接的过程。
需要做以下操作:
LIBRARY_OUT_PATH
target_link_libraries
下面是一个创建静态库的例子:
cmake_minimum_required(VERSION 3.9.1)
project(CMakeHello)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib)
message(${CMAKE_BINARY_DIR})
# add_library(math SHARED lib/math/operations.cpp)
add_library(math STATIC lib/math/operations.cpp)
add_executable(cmake_hello main.cpp)
target_link_libraries(cmake_hello math)
执行 cmake -H. -Bbuild
,然后再 build 目录下,执行 make
命令,在 build/lib
目录下会生成一个静态库。build/bin
目录下生成了最终可执行文件程序(cmake_hello),因为生成的是静态库,它已经被链接打包到了最终的可执行文件中,所以即使此时被删除,cmake_hello 也能正常执行。
创建动态库,只需要将 add_library(math STATIC lib/math/operations.cpp)
改为 add_library(math SHARED lib/math/operations.cpp)
即可。但是最终生成的可执行文件再运行过程中也需要库文件。
也可以在库文件目录 lib/math
中,创建一个新的 CMakeLists.txt
文件,在生成可执行文件前,单独构建库文件。
创建文件 lib/math/CMakeLists.txt
:
cmake_minimum_required(VERSION 3.9.1)
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib)
add_library(math SHARED operations.cpp)
然后将根目录下的 CMakeLists.txt
文件作出如下更改:
LIBRARY_OUTPUT_PATH
命令add_subdirectory
添加新的构件路径。这个命令可以使 cmake 命令查找指定目录下包含的 CMakeLists.txt
文件。cmake_minimum_required(VERSION 3.9.1)
project(CMakeHello)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
message(${CMAKE_BINARY_DIR})
add_subdirectory(lib/math)
add_executable(cmake_hello main.cpp)
target_link_libraries(cmake_hello math)
执行 cmake 和 make 后,你会发现结果与之前一致。
很多情况下,你找到一些开源库,你想使用这个库中的 API。例如你使用 apt-get 安装了 boost 库。
你可以使用 CMake 的条件语句判断库是否存在。然后决定是否继续构建程序。
cmake 能够在系统默认的库文件位置查找库文件,例如 /usr/lib;/usr/local/lib
。
可以使用包管理器(apt-get,brew)安装 Boost 库。在构建程序前,可以通过 cmake 的 find_package
命令检查 library 是否已经安装。
接下来,进行实操练习。
更新 main.cpp
文件,使用 boost 库 API:
#include <boost/random.hpp>
#include <iostream>
#include "lib/math/operations.hpp"
int main() {
std::cout << "Hello CMake!" << std::endl;
math::operations op;
int sum = op.sum(3, 4);
std::cout << "Sum of 3 + 4: " << sum << std::endl;
// Boost Random Sample
boost::mt19937 rng;
double mean = 2.3;
double std = 0.34;
auto normal_dist = boost::random::normal_distribution<double>(mean, std);
boost::variate_generator<boost::mt19937&,
boost::normal_distribution<> >
random_generator(rng, normal_dist);
for (int i = 0; i < 2; i++) {
auto rand_val = random_generator();
std::cout << "Random Val " << i + 1 << " :" << rand_val << std::endl;
}
return 0;
}
接下来更新 CMakeLists.txt
文件,我们需要检查 Boost 库是否存在,如果存在则使用 include_directories
将 Boost 头文件添加到编译器的头文件搜索路径之下,最后链接库。
cmake_minimum_required(VERSION 3.9.1)
project(CMakeHello)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
message(${CMAKE_BINARY_DIR})
add_subdirectory(lib/math)
add_executable(cmake_hello main.cpp)
find_package(Boost 1.66)
# check for library, if found print message, include dirs and link libraries
if (Boost_FOUND)
message("Boost Found")
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries(cmake_hello ${Boost_LIBRARIES})
elseif(NOT Boost_FOUND)
error("Boost Not Found")
endif()
target_link_libraries(cmake_hello math)
如果系统没有安装 Boost,执行 cmake 命令会报错。因为判断库文件不存在直接报错。可以执行 sudo apt-get install libboost-all-dev
安装 Boost,再执行 cmake 命令,将构建成功。
当使用 find_package 查找库文件时,下面的变量会自动创建:
<NAME>_FOUND
: 标识是否查找到库文件。<NAME>_INCLUDE_DIRS
或者 <NAME>_INCLUDES
: 库文件的头文件目录<NAME>_LIBRARIES
或者 <NAME>_LIBRARIES
或者<NAME>_LIBS
:库源文件<NAME>_DEFINITIONS
但是如果,想要链接的 lib 在一个自定义文件夹中,而不是在默认库文件目录,也不再 cmake 构建的 source tree 中呢?
使用 g++ 链接指定目录的库文件,命令是这样的:
$ g++ main.cpp -o cmake_hello -I/home/fangyan/libraries/boost/include -L/home/fangyan/libraries/boost -lBoost
上面的命令做了以下几件事:
-I<DIRECTORY>
: 指定库头文件的搜索路径-L<DIRECTORY>
: 指定库函数的搜索路径-l<LIBRARY_NAME>
: 指定连接的库文件名称在 CMakeLists.txt
需要完成同样的逻辑。
include_directories(/Users/User/Projects/libraries/include)
link_directories(/Users/User/Projects/libraries/libs)
# elseif case can be
elseif(NOT Boost_FOUND)
message("Boost Not Found")
include_directories(/Users/User/Projects/libraries/include)
link_directories(/Users/User/Projects/libraries/libs)
target_link_libraries(cmake_hello Boost)
endif()
还有很多其他的方式,例如你可以写自定义的 cmake 方法。这里最重要的是理解 C/C++ 的编译链接逻辑。
gcc 和 g++: https://pengfeixc.com/blogs/clang/gcc
你希望你开发的程序能够在不同平台运行。希望当程序运行在一个 intel 系统上时,能够包含 intel 相关的库文件。或者你希望能够交叉编译,在 windows 平台开发一个能够在其他系统或者嵌入式系统运行的程序。
所以你需要在 CMake 脚本中处理所有检查和宏(macros)。
现在你需要将你的程序进行交叉编译,能够在不同平台运行。所以当前 host 系统需要安装目标系统的编译器和链接器。
cmake 官方的交叉编译的例子:https://cmake.org/cmake/help/v3.6/manual/cmake-toolchains.7.html#cross-compiling-for-linux
下面是一个为树莓派系统构建应用程序的例子,使用树莓派上的 C/C++ 编译器和工具。
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_SYSROOT /home/devel/rasp-pi-rootfs)
set(CMAKE_STAGING_PREFIX /home/devel/stage)
set(tools /home/devel/gcc-4.7-linaro-rpi-gnueabihf)
set(CMAKE_C_COMPILER ${tools}/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER ${tools}/bin/arm-linux-gnueabihf-g++)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
上面的脚本最重要的地方是设置编译器和编译工具(linker)的路径。
这里就不详细说了,但是你得知道 cmake 可以实现交叉编译的配置。
设置编译器和链接器的命令项可以定义程序构建过程中的一些行为,例如打印警告信息,可以调试等等。
set(CMAKE_CXX_FLAGS "-std=c++0x -Wall")
# suggested way is to keep previous flags in mind and append new ones
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall")
# Alternatively, you can use generator expressions, which are conditional expressions. Below says that, if compiper is c++ then set it to c++11
add_compile_options("$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,CXX>:-std=c++11>")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl")
一般我们会用两种方式构建程序, Debug 和 Release,Debug 用于调试,Release 用于发布。用于发布的程序一般会去掉一些调试信息。
CMake 可以帮助你构建两种不同的版本。
使用下面两个命令可以创建不同的版本在不同的文件夹下:
$ cmake -H. -Bbuild/Debug
$ cmake -H. -Bbuild/Release
当然上面的两个命令最终生成的文件是一致的,我们需要设置 CMAKE_BUILD_TYPE
的值,来设置创建版本类型。
$ cmake -DCMAKE_BUILD_TYPE=Debug -H. -Bbuild/Debug
$ cmake -DCMAKE_BUILD_TYPE=Release -H. -Bbuild/Release
在 CMakeLists.txt 文件中也能使用 CMAKE_BUILD_TYPE
变量。
if(${CMAKE_BUILD_TYPE} MATCHES Debug)
message("Debug Build")
elseif(${CMAKE_BUILD_TYPE} MATCHES Release)
message("Release Build")
endif()
所以根据 build 类型可以单独设置编译器和链接器的选项。
CMake 还提供了很多命令帮助打包程序,这里有一篇很不错的文章介绍:https://cmake.org/cmake/help/v3.0/command/install.html
(完)