hello CMake
Hello, CMake
CMake是一个用于构建C++项目的编译链工具。通过编写CMakeLists.txt文件,完成项目的构建。
一个基本的CMakeLists.txt需要有版本要求,项目名称,和项目目标(可执行文件或库文件)组成。
1 | cmake_minimum_required(VERSION 3.20) |
CMake语言不区分大小写,但是参数区分大小写。
CMake基本构建命令
在源文件的根目录下,执行cmake -S. -Bbuild
,会生成一个和源文件根目录同级的build目录,并在其中生成项目所需的CMake配置文件,这一步等于先mkdir -p build
,然后进入build目录下执行cmake ..
。-B
可以指定build目录的路径。
在构建好了项目树后,进入build目录下,执行cmake --build .
生成项目的可执行文件或者生成库,这个.
表示了当前的build目录,当然也可以不进入build目录,在外面用相对路径或绝对路径代替这个.
。
另外,在生成过程中可以使用cmake -D CMAKE_CXX_COMPILER=clang++ ..
指定编译器。
使用-D CMAKE_BUILD_TYPE=Debug
来切换构建类型,其中类型有Debug,Release,RelWithDebInfo,MinSizeRel四种。
生成库
CMake生成库的命令是add_library
,将项目中生成的库链接到目标上的命令是target_link_libraries
。
1 | cmake_minimum_required(VERSION 3.20) |
在执行完add_library
后,会在linux平台生成一个.a文件或者在windows平台生成一个.lib文件,这就是静态库文件。第二个参数可以是STATIC,SHARED,OBJECT,MODULE的其中一个,分别代表着静态库、动态库、对象库和模组。动态库和静态库很好理解,对象库会使要编译的文件先存起来,既不生成静态库,也不允许链接,然后在需要的时候一次性创建成静态库和动态库。MODULE生成的目标对象是动态库类型,不会被链接到项目中的目标,但又可以进行动态加载,一般用于构建运行时插件。
1 | add_library(objs OBJECT some.hpp some.cpp) |
CMake文件中的目标名是不可以重复的,但可以指定目标的属性,来修改其最后输出的名称。
变量和条件控制
CMake中使用set(name value)
来定义一个全局变量name,其实际内容是value。
通过list(APPEND file.cpp)
可以向变量中追加内容
CMake中使用if() ... else() ... endif()
的方式书写条件控制语句,其中if()
的括号中可以指定变量。
option
命令可以指定一个开关,并且允许在构建的时候由外部来修改。
变量通过${}
来读取内容。
1 | set(use_lib OFF) |
编译器选项
使用target_compile_options()
设置目标的编译选项,或者在命令行中使用-D CMAKE_CXX_FLAGS="..."
手动指定。
控制流
使用foreach(val lists)
的形式来执行循环控制。
1 | target_compile_options(geometry PRIVATE -O3) |
foreach()有四种使用方式:
- foreach(loop_var arg1 arg2 …) : 其中提供循环变量和显式项列表。当为sources_with_lower_optimization 中的项打印编译器标志集时,使用此表单。注意,如果项目列表位于变量中,则必须显式展开它;也就是说, ${sources_with_lower_optimization} 必须作为参数传递。
- 通过指定一个范围,可以对整数进行循环,例如: foreach(loop_var rangetotal) 或 foreach(loop_var range start stop [step]) 。
- 对列表值变量的循环,例如: foreach(loop_var IN LISTS [list1[…]]) 。参数解释为列表,其内容就会自动展开。
- 对变量的循环,例如: foreach(loop_var IN ITEMS [item1 […]]) 。参数的内容没有展开。