PGStudy-CMake简单了解以及模块化编程
CMake
概念
Cmake是一个跨平台的编译工具,用简单的命令取代繁琐的Makefile文件编写
Grammar Feature
- 基本语法格式为:指令(参数1, 参数2…)
- 指令是大小写无关的,参数,变量是大小写相关的
- 变量使用
${}
方式取值,但在IF控制语句中直接使用变量名
Cmake中重要指令与常用变量
重要指令
==cmake_minimum_required== - 指定Cmake最小版本要求
1
2# Cmake最小版本要求为3.22.0
cmake_minimum_required(VERSION 3.22.0)==project== - 定义工程名
1
2# 指定工程名为Project_Name
project(Project_Name)==set== - 显示定义的变量
1
2# 定义SRC变量,其值为sayhello.cpp hello.cpp
set(SRC sayhello.cpp hello.cpp)==include_directories== - 向工程添加多个特定的头文件搜索路径,相当于g++的-l参数
1
2# 将/myinclude /include添加到头文件搜索路径
include_directories(./myinclude ./include)==link_directories== - 项工程添加多个特定的库文件搜索路径,相当于g++编译时的-L参数
1
2# 将/mylib /lib 添加到库文件搜索路径
link_directories(./mylib ./lib)==add_library== - 生成库文件
1
2# 通过SRC生成libhello.so共享库
add_library(hello SHARED ${SRC})==add_compaile_option== - 添加编译参数
1
2#添加编译参数 -Wall -std=c++11 -O2
add_compile_options(-Wall -std=c++11 -O2)==add_executable== - 生成可执行文件
1
2# 编译main.cpp 生成执行文件main
add_executable(main main.cpp)==target_link_libraries== - 为target添加所需要链接的共享库 –> 相当于g++编译时的-I参数
1
2# 将hello动态库文件链接到可执行文件main
target_link_libraries(main hello)==add_subdirectory== - 向当前工程田间存放源文件的子目录,并可以指定中间二进制和目标二进制的存放位置
1
2# 添加src子目录,src中需要有一个CMakeLists.txt
add_subdirectory(src)==aux_source_directory== - 发现一个目录下所有的源代码文件并将列表存储在一个变量中,这个指令临时被用来自动构建源文件列表
1
2
3
4# 定义SRC变量,其值为当前目录下所有的源代码文件
aux_source_directory(. SRC)
# 编译SRC变量所代表的源代码文件,生成main可执行文件
add_executable(main ${SRC})
常用参数
==CMAKE_C_FLAGS== gcc编译选项
==CMAKE_CXX_FLAGS== g++编译选项
1
2# 在CMAKE_CXX_FLAG变量后追加std=c++11
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")==CMAKE_BUILD_TYPE== 编译类型(DEBUG, RELEASE)
==CMAKE_BINARY_DIR== 指Cmake的build的生成二进制文件夹
==CMAKE_C_STANDARD== 指编译过程中C的标准
==CMAKE_CXX_STANDARD== 指编译过程过程中的CPP标准
Cmake参数选项
添加编译参数与预处理指令
在makefile中,通过shell形式的configure与makefile的配合可以实现对可选模块与编译可选指令的支持,在Cmake中,通过option与一些其他命令同样可以做到对可选模块与编译指令的支持。
- 添加编译参数:
- 使用
add_compile_options
命令。这个命令将添加到所有的目标上。例如:cmake add_compile_options(-Wall)
- 使用
target_compile_options
命令。这个命令只会添加到指定的目标上。例如:cmake target_compile_options(target PRIVATE -Wall)
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ...")
是另一种常见的添加编译参数的方法。这种方法直接修改了CMake的全局变量,所以它会影响到所有的目标。 例如,如果你想添加-Wall
编译选项,你可以这样写:cmake set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
这行代码的意思是,将-Wall
添加到CMAKE_CXX_FLAGS
变量中。CMAKE_CXX_FLAGS
变量包含了C++编译器的编译选项。 同样的,对于C编译器,你可以使用CMAKE_C_FLAGS
:cmake set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
这种方法的一个缺点是,它会影响到所有的目标,而不仅仅是一个特定的目标。如果你只想为一个特定的目标添加编译选项,你应该使用target_compile_options
命令。 - 添加预处理指令:
- 使用
add_definitions
命令。这个命令将添加到所有的目标上。例如:cmake add_definitions(-DDEBUG)
- 使用
target_compile_definitions
命令。这个命令只会添加到指定的目标上。例如:cmake target_compile_definitions(target PRIVATE DEBUG)
在上述两个例子中,DEBUG
是一个预处理指令,它会在编译时被定义。
注意,PRIVATE
、PUBLIC
、INTERFACE
这些关键字的含义:
PRIVATE
:只有目标自己会使用这些编译参数。PUBLIC
:目标自己和其他依赖这个目标的目标都会使用这些编译参数。INTERFACE
:只有其他依赖这个目标的目标会使用这些编译参数。
下面将给出一个示例
1 | # CMakeList.txt |
1 | /*test.c*/ |
这段代码解耦了对内存映射的赋值与文件的赋值,甚至解耦了对不同模块的编译,对小型项目具有一定的参考意义,在CMake中仍存在很多特性这里并未提及,并且这里的代码也并不规范(这可能导致预处理的作用范围扩展)。但对初学者很好理解cmake如何使项目模块化。下面是一些命令行代码。
1 | 处在项目文件CMakeLists.txt同级目录下 |
如果希望用脚本进一步封装,一个我目前学习到的写法如下
1 | # start.sh |
这里的代码为某个项目代码,并不能提供完整代码,请注意辨别,仅作示意。
以上
参考文献
- 基于vscode与cmake实现c/c++开发 哔哩哔哩_bilibili
- 【Cmake 增加编译参数 】cmake增加编译参数和预处理指令的几种方法 - 知乎 (zhihu.com)
- chatgpt kimi ai (由作者prompt并审查正确性)