十兽鉴的博客

我的 CMAKE 入门

尝试 CMake 入门。之前跟着 TheCherno 大佬的游戏引擎视频教程 最好的游戏引擎开发教学没意见吧!repo)尝试使用 premake 构建工程,但是考虑到大多数的开源项目都是用 CMake 进行管理的,还是决定要学习一下 CMake。在这里会记录一下常用的 CMake,同时也作为我的第一篇正式博客贴出。

说明

学习内容参考(这一段内容作废,万物靠百度,万事靠自学)cmake-examples-Chinese,对应的代码 cmake-examples

  • 除非特殊说明,所有的 CMake 项目构建过程按如下方式进行:
1
2
3
mkdir build
cd build
cmake ..

Windows 下(如果安装了VS)默认生成 VS 的 .sln 工程项目,Linux 下可以直接在 build 文件夹中执行

1
make

编译代码生成可执行文件。

2021.5.27

基本信息

对于只包含一个源文件 main.cpp 的简单项目,只需要在项目文件夹下创建 CMakeLists.txt 并写入基本信息:

1
2
3
cmake_minimum_required(VERSION 3.5)     #设置CMake最小版本
project (hello_cmake) #设置工程名
add_executable(hello_cmake main.cpp) #生成可执行文件

cmake_minimum_required 版本要求需要查看 API 文档,像添加预编译头文件(pch.h)的功能 target_precompile_headers 的功能在版本 3.16 之后添加。

project 同时定义了以下的常量:

1
${PROJECT_NAME}     # 就是 hello_cmake

add_executable 中第一个参数就是解决方案中唯一一个(暂时)项目的名字。

项目设置

  • project 项目名后可以添加性质(trait)
    • 版本就是 VERSION X.X.X
    • 描述就是 DESCRIPTION "XXX"
    • 语言就是 LANGUAGES CXX
  • 使用 set 可以设置常量和修改预置量,如
    • 设置常量
      • set(INCLUDE_DIR "include/") => ${INCLUDE_DIR} 等价 "include"
    • 修改预置量
      • set(CMAKE_CXX_STANDARD 17) 指定 C++ 语言版本为 C++17
      • set(CMAKE_CXX_STANDARD_REQUIRED ON/OFF) 是否允许低版本语言编译
      • set(CMAKE_CXX_EXTENSIONS ON/OFF) 不懂干嘛的,之后懂了可能会补上
  • 使用 target_include_directories(name <PUBLIC|PRIVATE|INTERFACE> dir) 向项目 name 添加位于 dir 下的头文件,有三种访问方式:
    • PUBLIC: name 中的头文件和源文件都包含了 dir 的头文件,main.cpp 也需要包含 dir 下的头文件
    • PRIVATE: name 中只有源文件包含了 dir 的头文件,main.cpp 对 dir 的头文件未知(无法 include)
    • INTERFACE: name 中只有头文件包含了 dir 的头文件,main.cpp 需要包含 dir 下的头文件

2021.8.18

久违的更新

文件包含

添加辅助源文件目录

1
aux_source_directory(path target)

得到的 target 用于命令 add_executableadd_library 中,最终会把 path 下的所有源文件添加到项目的源文件管理器中。

同名文件搜索

如果要添加目录 path 下所有某后缀 *.xx 的文件,则可以

1
2
file(GLOB_RECURSE target *.xx)
source_group("name" FILES path)

这样 path 下所有的 *.xx 文件路径都被添加到了 target 中,在 add_executableadd_library 中添加对应条目即可在最终生成的项目中看到同名文件夹和对应的文件。

子目录、子工程

add_subdirectory(path) 是将 path 下的子项目包含进编译工程中,但是要求 path 下必须有描述子项目的 CMAKE 文件 CMakeLists.txt

多个子项目之间的连接依赖关系可以通过命令

1
2
3
target_link_libraries(target
[PUBLIC|PRIVATE|INTERFACE] dependency1
[PUBLIC|PRIVATE|INTERFACE] dependency2 ...)

完成,且不要求子目录 CMakeLists.txt 令添加依赖子项目目录,只需要在根目录的 CMakeLists.txt 中添加了所有子项目目录即可。该命令的依赖关系指标参数[PUBLIC|PRIVATE|INTERFACE]target_include_directories 相同。

1
2
3
target_include_directories(target
[PUBLIC|PRIVATE|INTERFACE] path1
[PUBLIC|PRIVATE|INTERFACE] path2 ...)

target 添加包含头文件,参数与 target_include_directories 相同。

目标文件目录

对于目标为可执行文件的目标,可以指定可执行文件生成目录为

1
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY path)

对于目标为静态库的目标,可以指定静态库生成目录为

1
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY path)

对于目标为动态库的目标,可以指定动态库生成目录为

1
set(CMAKE_BINARY_OUTPUT_DIRECTORY path)

  • 注意,修改目标文件目录的操作必须在 add_executableadd_library 之前!

今天就这些了。

十兽鉴(hands133)

一个(伪)图形程序员,专业方向为模型压缩和科学计算可视化,喜欢开发点小工具。最近在看游戏引擎开发,学习框架。

Comments