基本写法示例
环境准备
编译在centos7下,需要先安装相关软件:
yum -y install gcc gcc-c++ automake autoconf libtool make
编写文件
/demo/CMakeLists.txt
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo1)
# 指定生成目标
add_executable(Demo main.cc)
/demo/main.cc
#include <stdio.h>
#include <stdlib.h>
double multiplication(double one, double two)
{
return one*two;
}
int main(int argc, char *argv[])
{
double one = atof(argv[1]);
double two = atof(argv[2]);
double result = multiplication(one, two);
printf("%g * %g is %g\n", one, two, result);
return 0;
}
生成
/demo目录下执行:
cmake .
会生成Makefile,CMakeCache.txt,cmake_install.cmake,CMakeFiles,其中Makefile就可以用来构建可执行文件。
由于cmake并没有clean类似的操作,为了避免临时文件和代码混在一起,我们可以在当前目录创建build目录,然后/demo/build执行:
cmake ..
cmake . 命令的详细作用:
扫描源代码:CMake 会扫描当前目录下的源代码文件、目录结构和包含的库依赖关系。
生成配置:CMake 根据扫描结果生成一个名为 CMakeCache.txt(或 CMakeCache.cmake)的缓存文件。这个文件包含了所有检测到的配置信息,如编译器路径、库依赖、生成器类型等。
生成构建系统:CMake 会根据 CMakeLists.txt 文件中的指令和缓存文件中的配置信息,生成适用于当前系统的构建系统。这可能包括 Makefile、Visual Studio 解决方案、Xcode 项目文件等。
确定依赖关系:CMake 会检测项目依赖的库,并尝试找到可用的版本。如果依赖的库不在系统中,CMake 会报错,并要求用户指定库的路径。
设置构建目录:CMake 默认会在当前目录下创建一个名为 build 的子目录,用于存放构建过程中的文件和生成的目标文件。用户也可以通过 -B 选项指定一个不同的构建目录。
启动构建:配置完成后,CMake 通常会提示用户运行构建工具(如 make)来编译和链接项目。如果没有指定生成器,CMake 通常会使用默认的生成器,如 Unix Makefiles。
/demo目录在执行:
make
就可以生成可执行文件Demo,我们可以测试,会输出对应结果:
./Demo 2 2
CMake语法
说明
- 编写 CMakeLists.txt 文件时使用的语法称为CMake 语法(CMake syntax)或CMake 脚本语言(CMake scripting language)。
- CMake 语法用于编写 CMakeLists.txt 文件,指导 CMake 如何为项目生成构建系统。
- CMake 脚本语言包括指令、变量、函数、宏、控制结构等,用于组织和控制项目的构建过程。
基本语法
注释
# 这是一个注释
打印
message("hello world!")
变量
# 设置
set(VARIABLE_NAME hello)
message("使用: ${VARIABLE_NAME}")
# 清空
set(VARIABLE_NAME)
或
unset(VARIABLE_NAME)
上面的称为一般变量,此外还有缓存变量,环境变量,对应的设置和清空方式也不大一样。
清空后的如果再使用(比如message),将整行不会打印。
include_directories
include_directories ("${PROJECT_SOURCE_DIR}/math")
- 可以将对应的路径应用到当前环境下,c文件在调用时,就可以不指明具体路径。
- 比如a.c文件同级别有目录math/MathFunctions.h,a.c正常引用头文件需要#include "math/MathFunctions.h",而写了include_directories ("${PROJECT_SOURCE_DIR}/math")则只需要#include "MathFunctions.h"。
- 可参考:https://blog.csdn.net/sinat_31608641/article/details/121666564
configure_file
configure_file (
"${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_BINARY_DIR}/config.h"
)
- cmake 中的 configure_file 指令通过读取输入文件中的内容,将 CMakeLists.txt 文件中的变量转变为 C/C++ 中可识别的宏定义,然后存入另一个文件中。
- 让普通文件,也能使用CMake中的变量,比如CMakeLists.txt中定义set(BUILD_Version 1)
输入文件中内容为:#define BUILD_Version @BUILD_Version@
输出文件中就会被转化为:#define BUILD_Version 1
然后c文件可以使用此h文件进行判断。
通常情况下,输入文件以.h.in为后缀,输出文件以.h为后缀。 - 参考:
https://blog.csdn.net/qq_38410730/article/details/103741579
https://zhuanlan.zhihu.com/p/436923370
option
option (USE_MYMATH "Use provided math implementation" ON)
- 定义选项USE_MYMATH,只有ON/OFF,然后在CMakeFiles可以进行条件判断:
if (USE_MYMATH)
...
endif (USE_MYMATH)
- 该定义的值并不能在c代码中读取,为了实现该功能,我们可以配合configure_file,生成一个头文件:
configure_file (
"${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_BINARY_DIR}/config.h"
)
config.h.in内容为:#cmakedefine USE_MYMATH,即如果CMakeFiles没有定义USE_MYMATH(option设置,on代表定义,off代表没定义),则生成的config.h则没有#define USE_MYMATH,我们的c文件就可以进行#ifdef USE_MYMATH进行存在/不存在的判断了。
奇怪的是第一次cmake肯定为config.h没有#define USE_MYMATH,第二次才有,即使option的时候为ON;
使用set(BUILD_Version 1)的方式则正常。
在cmake时,我可以改用ccmake .来运行交互式的界面进行配置的设置,ccmake主要帮助用户设置和调整 CMake 构建系统的参数。
第一次ccmake显示EMPTY CACHE,得执行过cmake命令后,才显示出配置选项,原因是:这通常意味着 CMake 缓存(.cmake 文件)尚未被创建或初始化。缓存文件用于存储 CMake 运行时的配置信息,如编译器路径、生成器类型、依赖项等。在第一次运行 ccmake 之前,如果没有通过 cmake 命令扫描源代码目录并生成缓存,那么 ccmake 就不会显示任何配置选项,因为它们还没有被定义。这就是为什么你需要在运行 ccmake 之前先运行 cmake 命令的原因。