CMake入门
CMake
简介
CMake
是一个跨平台的构建系统生成工具,用于管理编译过程,其主要功能如下:
- 通过读取配置文件(
CMakeLists.txt
)
- 生成特定于平台的构建文件(如
Makefile
或 Visual Studio 工程文件);
- 帮助用户管理项目的依赖关系、编译流程等;
也就是说CMake
是一套交叉编译的工具链,通过CMake
我们可以更好地管理项目结构;
CMake
相比于传统的构建工具(如直接编写 Makefile
),具有以下几个核心特性:
跨平台:CMake 支持多个平台(如 Windows
、Linux
、macOS
)和编译器(GCC
、Clang
、MSVC
等),通过生成平台特定的构建系统文件,能够帮助开发者更轻松地在不同平台上编译项目。
依赖管理:CMake
能够自动检测并配置项目的依赖库,确保在编译过程中正确地链接外部库。例如,它可以通过 find_package
指令查找和配置第三方库。
增量编译:CMake
支持增量编译机制。当源代码部分更新时,它只会重新编译受影响的部分,减少不必要的编译时间。
模块化与可扩展性:CMake
允许用户编写模块和脚本,用于管理更复杂的项目结构。它提供了丰富的指令集来配置编译流程,并且可以通过编写自定义的模块扩展其功能。
可集成性:CMake
可以生成多种构建工具的配置文件,支持不同的 IDE 和构建系统;
C++工程目录设计最佳实践
一个典型的 C++ 项目目录结构应该具有清晰的分层,常见的目录和文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| /project-root ├── CMakeLists.txt # 项目的主 CMake 配置文件 ├── src/ # 源文件目录 │ ├── main.cpp # 主程序入口 │ ├── module1.cpp # 模块1的源文件 │ ├── module2.cpp # 模块2的源文件 ├── include/ # 公共头文件目录 │ ├── module1.h # 模块1的头文件 │ ├── module2.h # 模块2的头文件 ├── lib/ # 外部库(静态或动态库)存放目录 ├── bin/ # 存放二进制文件 ├── tests/ # 测试代码 │ ├── CMakeLists.txt # 测试目录的 CMake 文件 │ ├── test_module1.cpp # 测试模块1的单元测试 ├── examples/ # 示例代码 ├── docs/ # 文档(用户指南、API 文档等) ├── build/ # 构建生成目录(通常不放入源码控制系统中) ├── scripts/ # 构建、部署、运行等自动化脚本 ├── README.md # 项目说明文件 └── LICENSE # 项目许可证
|
除此之外,仍有一些细节需要注意:
src/
和 include/
目录分离
src/
中应该存放项目的 .cpp
、.c
文件,即项目的具体实现代码。
include/
则存放公共的 .h
、.hpp
文件,这些头文件定义了接口,并且其他项目或模块可以包含这些头文件。
使用这种分离策略有助于清晰地定义哪些文件是实现细节,哪些文件是对外暴露的接口;
注意在头文件中不要using namespace std;
;
模块化管理
依赖管理
lib/
目录:推荐通过自动化脚本或包管理工具自动下载和构建依赖,而非手动放入外部库的二进制文件;
third_party/
目录:将外部依赖源代码放在 third_party/
目录中,并使用 CMake
或其他工具集成;
测试目录结构
tests/
目录应该用于存放所有的测试代码;
- 推荐使用与项目主目录相同的模块化结构,保证测试代码清晰、独立,方便集成到 CI/CD 流程中
文档目录
docs/
目录用于存放项目的文档资料,文档可以包含项目概述、API 文档、使用指南、开发者指南等。
- 推荐使用
Doxygen
并将其保存在此目录中;
构建输出目录
build/
** 目录用于存放项目的构建输出文件(如中间文件、可执行文件等)。
- 为了避免污染源码目录,建议将构建生成的文件放入单独的
build/
目录中,并将此目录加入 .gitignore
中,防止其被加入版本控制;
使用脚本自动化流程
scripts/
目录可以用于存放一些常用的自动化脚本,如构建、清理、测试、打包、发布等脚本。
- 通常包括
build.sh, test.sh, deploy.sh
CMake
基本编译原理
CMake
的编译过程可以分为几个主要步骤:
配置阶段:
- 读取
CMakeLists.txt
文件:
CMake
通过解析项目中的 CMakeLists.txt
文件来获取项目信息(源文件、依赖库、编译选项等);
- 生成构建系统:
- ``CMake
解析
CMakeLists.txt` 后,基于当前平台和用户指定的生成器生成特定的构建系统文件这些生成的文件控制项目的编译流程;
生成阶段:
CMake
根据配置阶段的结果,生成构建文件(如IDE
工程文件),详细描述了如何从源代码生成目标文件;
CMake
不直接编译代码,而是通过生成的构建系统文件调用具体的编译工具链来进行编译。
编译阶段:
- 用户运行生成的构建系统(例如执行
make
命令),调用编译器编译源代码,生成目标文件(如 .o
文件)。
- 链接目标文件,生成最终的可执行文件或库文件(如
.exe
或 .so/.dll
文件)。
简要来说,如果我的项目遵循上述的最佳实践的话,可以通过一个文件编写两条命令实现:
- 编写
CMakeLists.txt
;
cmake .
cmake --build .
CMakeLists.txt
编写原则
模块化:
- 将项目配置划分为多个
CMake
文件;
- 使用变量来避免重复代码,并通过函数/宏封装复杂的操作。
指定最低版本要求
- 每个项目的
CMakeLists.txt
中明确指定所需的最低 CMake 版本;
项目声明
管理编译选项:
- 设置编译器选项:通过
target_compile_options()
为目标指定编译器选项,而不是使用全局变量 CMAKE_CXX_FLAGS
,这样可以避免全局配置导致的不必要副作用。
- 使用
CMAKE_BUILD_TYPE
:通过 CMAKE_BUILD_TYPE
设置构建模式(如 Debug
或 Release
)。在实际项目中,建议允许用户在命令行中指定,而非硬编码在 CMakeLists.txt
中;
处理依赖项:
- 如果项目依赖于外部库,使用
find_package()
查找库,并根据需要设置是否强制要求该库;
- 对于一些外部库,可以使用
FetchContent
下载和构建它们,避免手动配置;
管理源文件
- 将源文件列表集中管理,并根据项目结构清晰划分。例如,可以将源文件分组,并使用
file()
或变量存储文件路径;
启用自动化测试:
- 建议为项目配置测试框架,并使用 CMake 的
enable_testing()
和 add_test()
来集成测试
多平台支持:
支持安装和打包:
- 为了方便部署项目,可以在
CMakeLists.txt
中配置安装和打包规则。使用 install()
命令设置如何将生成的可执行文件、库和其他资源安装到系统路径;
CMakeLists.txt
配置具体含义
指定CMake
的最低版本
1
| cmake_minimum_required(VERSION 3.15)
|
项目命名
指定C++标准
1
| set(CMAKE_CXX_STANDARD 20)
|
设置编译器路径
1 2
| set(CMAKE_C_COMPILER "/usr/bin/gcc") set(CMAKE_CXX_COMPILER "/usr/bin/g++")
|
确保它们只在项目第一次运行时配置, 避免重复配置,或者即使清除CMake
缓存;
设置源文件目录
1
| file(GLOB SRC_LIST "${PROJECT_SOURCE_DIR}/src/tb/*.cpp")
|
添加头文件路径
1
| include_directories(include)
|
生成目标可执行文件
1
| add_executable(tb ${SRC_LIST})
|
外部库的引用
fmt库
从 CMake 3.11 开始,可以使用 FetchContent 自动 在 configure 时下载 {fmt} 作为依赖项:
1 2 3 4 5 6 7 8 9
| include(FetchContent)
FetchContent_Declare( fmt GIT_REPOSITORY https://github.com/fmtlib/fmt GIT_TAG e69e5f977d458f2650bb346dadf2ad30c5320281) FetchContent_MakeAvailable(fmt)
target_link_libraries(<your-target> fmt::fmt)
|
注意<your-target>
应填写可执行文件的名称
- 在编译的最后一步,链接器会把编译后的目标文件(即
.o
文件或 .obj
文件)与所依赖的外部库(如静态库 .a
文件或动态库 .so
/.dll
文件)链接在一起,生成最终的可执行文件。因此,target
通常是这个最终生成的可执行文件的名称;
- 如果项目中包含多个不同的可执行文件,每个可执行文件可能会依赖不同的库。在这种情况下,你可以为每个目标定义一个不同的
target
,以便生成多个不同的可执行文件;
在头文件内加入
1 2 3 4 5 6 7 8 9 10 11 12
| # define FMT_HEADER_ONLY # include "fmt/core.h" # include "fmt/format.h" # include "fmt/ranges.h" # include "fmt/chrono.h" # include "fmt/std.h" # include "fmt/compile." # include "fmt/color.h" # include "fmt/os.h" # include "fmt/ostream." # include "fmt/printf.h" # include "fmt/xchar.h"
|
注意
相对路径问题
通常,工作目录是在命令行中运行可执行文件的地方;
如果设置bin/
为输出目录,那么需要一个上级目录..
才能回到项目根目录;
对于头文件的相对路径,通常会设置include_directories(include)
,直接引用对应模块即可;
示例
以下是一个CMakeLists.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| cmake_minimum_required(VERSION 3.15)
project(MyDraft)
set(CMAKE_CXX_STANDARD 20)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/bin")
include_directories(include)
file(GLOB SRC_LIST "${PROJECT_SOURCE_DIR}/src/hello/*.cpp")
add_executable(hello ${SRC_LIST})
include(FetchContent)
FetchContent_Declare( fmt GIT_REPOSITORY https://github.com/fmtlib/fmt GIT_TAG e69e5f977d458f2650bb346dadf2ad30c5320281) FetchContent_MakeAvailable(fmt)
target_link_libraries(hello fmt::fmt)
|
我的目录树如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
| .MyCMake ├── bin │ └── hello ├── build │ ├── CMakeCache.txt │ ├── CMakeFiles │ │ ├── 3.30.3 │ │ │ ├── CMakeCCompiler.cmake │ │ │ ├── CMakeCXXCompiler.cmake │ │ │ ├── CMakeDetermineCompilerABI_C.bin │ │ │ ├── CMakeDetermineCompilerABI_CXX.bin │ │ │ ├── CMakeSystem.cmake │ │ │ ├── CompilerIdC │ │ │ │ ├── a.out │ │ │ │ ├── CMakeCCompilerId.c │ │ │ │ └── tmp │ │ │ └── CompilerIdCXX │ │ │ ├── a.out │ │ │ ├── CMakeCXXCompilerId.cpp │ │ │ └── tmp │ │ ├── cmake.check_cache │ │ ├── CMakeConfigureLog.yaml │ │ ├── CMakeDirectoryInformation.cmake │ │ ├── CMakeScratch │ │ ├── hello.dir │ │ │ ├── build.make │ │ │ ├── cmake_clean.cmake │ │ │ ├── compiler_depend.make │ │ │ ├── compiler_depend.ts │ │ │ ├── DependInfo.cmake │ │ │ ├── depend.make │ │ │ ├── flags.make │ │ │ ├── link.txt │ │ │ ├── progress.make │ │ │ └── src │ │ │ └── hello │ │ │ ├── hello.cpp.o │ │ │ └── hello.cpp.o.d │ │ ├── Makefile2 │ │ ├── Makefile.cmake │ │ ├── pkgRedirects │ │ ├── progress.marks │ │ └── TargetDirectories.txt │ ├── cmake_install.cmake │ ├── _deps │ │ ├── fmt-build │ │ │ ├── CMakeFiles │ │ │ │ ├── CMakeDirectoryInformation.cmake │ │ │ │ ├── Export │ │ │ │ │ └── b834597d9b1628ff12ae4314c3a2e4b8 │ │ │ │ │ ├── fmt-targets.cmake │ │ │ │ │ └── fmt-targets-noconfig.cmake │ │ │ │ ├── fmt.dir │ │ │ │ │ ├── build.make │ │ │ │ │ ├── cmake_clean.cmake │ │ │ │ │ ├── cmake_clean_target.cmake │ │ │ │ │ ├── compiler_depend.make │ │ │ │ │ ├── compiler_depend.ts │ │ │ │ │ ├── DependInfo.cmake │ │ │ │ │ ├── depend.make │ │ │ │ │ ├── flags.make │ │ │ │ │ ├── link.txt │ │ │ │ │ ├── progress.make │ │ │ │ │ └── src │ │ │ │ │ ├── format.cc.o │ │ │ │ │ ├── format.cc.o.d │ │ │ │ │ ├── os.cc.o │ │ │ │ │ └── os.cc.o.d │ │ │ │ └── progress.marks │ │ │ ├── cmake_install.cmake │ │ │ ├── fmt-config.cmake │ │ │ ├── fmt-config-version.cmake │ │ │ ├── fmt.pc │ │ │ ├── fmt-targets.cmake │ │ │ ├── libfmt.a │ │ │ └── Makefile │ │ ├── fmt-src │ │ │ ├── ChangeLog.md │ │ │ ├── CMakeLists.txt │ │ │ ├── CONTRIBUTING.md │ │ │ ├── doc │ │ │ │ ├── api.rst │ │ │ │ ├── basic-bootstrap │ │ │ │ │ ├── layout.html │ │ │ │ │ ├── README │ │ │ │ │ └── theme.conf │ │ │ │ ├── bootstrap │ │ │ │ │ ├── alerts.less │ │ │ │ │ ├── badges.less │ │ │ │ │ ├── bootstrap.less │ │ │ │ │ ├── breadcrumbs.less │ │ │ │ │ ├── button-groups.less │ │ │ │ │ ├── buttons.less │ │ │ │ │ ├── carousel.less │ │ │ │ │ ├── close.less │ │ │ │ │ ├── code.less │ │ │ │ │ ├── component-animations.less │ │ │ │ │ ├── dropdowns.less │ │ │ │ │ ├── forms.less │ │ │ │ │ ├── glyphicons.less │ │ │ │ │ ├── grid.less │ │ │ │ │ ├── input-groups.less │ │ │ │ │ ├── jumbotron.less │ │ │ │ │ ├── labels.less │ │ │ │ │ ├── list-group.less │ │ │ │ │ ├── media.less │ │ │ │ │ ├── mixins │ │ │ │ │ │ ├── alerts.less │ │ │ │ │ │ ├── background-variant.less │ │ │ │ │ │ ├── border-radius.less │ │ │ │ │ │ ├── buttons.less │ │ │ │ │ │ ├── center-block.less │ │ │ │ │ │ ├── clearfix.less │ │ │ │ │ │ ├── forms.less │ │ │ │ │ │ ├── gradients.less │ │ │ │ │ │ ├── grid-framework.less │ │ │ │ │ │ ├── grid.less │ │ │ │ │ │ ├── hide-text.less │ │ │ │ │ │ ├── image.less │ │ │ │ │ │ ├── labels.less │ │ │ │ │ │ ├── list-group.less │ │ │ │ │ │ ├── nav-divider.less │ │ │ │ │ │ ├── nav-vertical-align.less │ │ │ │ │ │ ├── opacity.less │ │ │ │ │ │ ├── pagination.less │ │ │ │ │ │ ├── panels.less │ │ │ │ │ │ ├── progress-bar.less │ │ │ │ │ │ ├── reset-filter.less │ │ │ │ │ │ ├── resize.less │ │ │ │ │ │ ├── responsive-visibility.less │ │ │ │ │ │ ├── size.less │ │ │ │ │ │ ├── tab-focus.less │ │ │ │ │ │ ├── table-row.less │ │ │ │ │ │ ├── text-emphasis.less │ │ │ │ │ │ ├── text-overflow.less │ │ │ │ │ │ └── vendor-prefixes.less │ │ │ │ │ ├── mixins.less │ │ │ │ │ ├── modals.less │ │ │ │ │ ├── navbar.less │ │ │ │ │ ├── navs.less │ │ │ │ │ ├── normalize.less │ │ │ │ │ ├── pager.less │ │ │ │ │ ├── pagination.less │ │ │ │ │ ├── panels.less │ │ │ │ │ ├── popovers.less │ │ │ │ │ ├── print.less │ │ │ │ │ ├── progress-bars.less │ │ │ │ │ ├── responsive-embed.less │ │ │ │ │ ├── responsive-utilities.less │ │ │ │ │ ├── scaffolding.less │ │ │ │ │ ├── tables.less │ │ │ │ │ ├── theme.less │ │ │ │ │ ├── thumbnails.less │ │ │ │ │ ├── tooltip.less │ │ │ │ │ ├── type.less │ │ │ │ │ ├── utilities.less │ │ │ │ │ ├── variables.less │ │ │ │ │ └── wells.less │ │ │ │ ├── build.py │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── conf.py │ │ │ │ ├── contents.rst │ │ │ │ ├── fmt.less │ │ │ │ ├── index.rst │ │ │ │ ├── python-license.txt │ │ │ │ ├── _static │ │ │ │ │ ├── bootstrap.min.js │ │ │ │ │ ├── breathe.css │ │ │ │ │ └── fonts │ │ │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ │ │ └── glyphicons-halflings-regular.woff │ │ │ │ ├── syntax.rst │ │ │ │ ├── _templates │ │ │ │ │ ├── layout.html │ │ │ │ │ └── search.html │ │ │ │ └── usage.rst │ │ │ ├── include │ │ │ │ └── fmt │ │ │ │ ├── args.h │ │ │ │ ├── chrono.h │ │ │ │ ├── color.h │ │ │ │ ├── compile.h │ │ │ │ ├── core.h │ │ │ │ ├── format.h │ │ │ │ ├── format-inl.h │ │ │ │ ├── os.h │ │ │ │ ├── ostream.h │ │ │ │ ├── printf.h │ │ │ │ ├── ranges.h │ │ │ │ ├── std.h │ │ │ │ └── xchar.h │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── src │ │ │ │ ├── fmt.cc │ │ │ │ ├── format.cc │ │ │ │ └── os.cc │ │ │ ├── support │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── Android.mk │ │ │ │ ├── bazel │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── README.md │ │ │ │ │ └── WORKSPACE.bazel │ │ │ │ ├── build-docs.py │ │ │ │ ├── build.gradle │ │ │ │ ├── cmake │ │ │ │ │ ├── FindSetEnv.cmake │ │ │ │ │ ├── fmt-config.cmake.in │ │ │ │ │ ├── fmt.pc.in │ │ │ │ │ └── JoinPaths.cmake │ │ │ │ ├── compute-powers.py │ │ │ │ ├── C++.sublime-syntax │ │ │ │ ├── docopt.py │ │ │ │ ├── manage.py │ │ │ │ ├── printable.py │ │ │ │ ├── README │ │ │ │ ├── rtd │ │ │ │ │ ├── conf.py │ │ │ │ │ ├── index.rst │ │ │ │ │ └── theme │ │ │ │ │ ├── layout.html │ │ │ │ │ └── theme.conf │ │ │ │ └── Vagrantfile │ │ │ └── test │ │ │ ├── add-subdirectory-test │ │ │ │ ├── CMakeLists.txt │ │ │ │ └── main.cc │ │ │ ├── args-test.cc │ │ │ ├── assert-test.cc │ │ │ ├── chrono-test.cc │ │ │ ├── CMakeLists.txt │ │ │ ├── color-test.cc │ │ │ ├── compile-error-test │ │ │ │ └── CMakeLists.txt │ │ │ ├── compile-fp-test.cc │ │ │ ├── compile-test.cc │ │ │ ├── core-test.cc │ │ │ ├── cuda-test │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── cpp14.cc │ │ │ │ └── cuda-cpp14.cu │ │ │ ├── detect-stdfs.cc │ │ │ ├── enforce-checks-test.cc │ │ │ ├── find-package-test │ │ │ │ ├── CMakeLists.txt │ │ │ │ └── main.cc │ │ │ ├── format-impl-test.cc │ │ │ ├── format-test.cc │ │ │ ├── fuzzing │ │ │ │ ├── build.sh │ │ │ │ ├── chrono-duration.cc │ │ │ │ ├── chrono-timepoint.cc │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── float.cc │ │ │ │ ├── fuzzer-common.h │ │ │ │ ├── main.cc │ │ │ │ ├── named-arg.cc │ │ │ │ ├── one-arg.cc │ │ │ │ ├── README.md │ │ │ │ └── two-args.cc │ │ │ ├── gtest │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── gmock │ │ │ │ │ └── gmock.h │ │ │ │ ├── gmock-gtest-all.cc │ │ │ │ └── gtest │ │ │ │ ├── gtest.h │ │ │ │ └── gtest-spi.h │ │ │ ├── gtest-extra.cc │ │ │ ├── gtest-extra.h │ │ │ ├── gtest-extra-test.cc │ │ │ ├── header-only-test.cc │ │ │ ├── mock-allocator.h │ │ │ ├── module-test.cc │ │ │ ├── noexception-test.cc │ │ │ ├── os-test.cc │ │ │ ├── ostream-test.cc │ │ │ ├── posix-mock.h │ │ │ ├── posix-mock-test.cc │ │ │ ├── printf-test.cc │ │ │ ├── ranges-odr-test.cc │ │ │ ├── ranges-test.cc │ │ │ ├── scan.h │ │ │ ├── scan-test.cc │ │ │ ├── static-export-test │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── library.cc │ │ │ │ └── main.cc │ │ │ ├── std-test.cc │ │ │ ├── test-assert.h │ │ │ ├── test-main.cc │ │ │ ├── unicode-test.cc │ │ │ ├── util.cc │ │ │ ├── util.h │ │ │ └── xchar-test.cc │ │ └── fmt-subbuild │ │ ├── CMakeCache.txt │ │ ├── CMakeFiles │ │ │ ├── 3.30.3 │ │ │ │ └── CMakeSystem.cmake │ │ │ ├── cmake.check_cache │ │ │ ├── CMakeConfigureLog.yaml │ │ │ ├── CMakeDirectoryInformation.cmake │ │ │ ├── CMakeRuleHashes.txt │ │ │ ├── fmt-populate-complete │ │ │ ├── fmt-populate.dir │ │ │ │ ├── build.make │ │ │ │ ├── cmake_clean.cmake │ │ │ │ ├── compiler_depend.make │ │ │ │ ├── compiler_depend.ts │ │ │ │ ├── DependInfo.cmake │ │ │ │ ├── Labels.json │ │ │ │ ├── Labels.txt │ │ │ │ └── progress.make │ │ │ ├── Makefile2 │ │ │ ├── Makefile.cmake │ │ │ ├── pkgRedirects │ │ │ ├── progress.marks │ │ │ └── TargetDirectories.txt │ │ ├── cmake_install.cmake │ │ ├── CMakeLists.txt │ │ ├── fmt-populate-prefix │ │ │ ├── src │ │ │ │ └── fmt-populate-stamp │ │ │ │ ├── fmt-populate-build │ │ │ │ ├── fmt-populate-configure │ │ │ │ ├── fmt-populate-done │ │ │ │ ├── fmt-populate-download │ │ │ │ ├── fmt-populate-gitclone-lastrun.txt │ │ │ │ ├── fmt-populate-gitinfo.txt │ │ │ │ ├── fmt-populate-install │ │ │ │ ├── fmt-populate-mkdir │ │ │ │ ├── fmt-populate-patch │ │ │ │ ├── fmt-populate-patch-info.txt │ │ │ │ ├── fmt-populate-test │ │ │ │ └── fmt-populate-update-info.txt │ │ │ └── tmp │ │ │ ├── fmt-populate-cfgcmd.txt │ │ │ ├── fmt-populate-gitclone.cmake │ │ │ ├── fmt-populate-gitupdate.cmake │ │ │ └── fmt-populate-mkdirs.cmake │ │ └── Makefile │ └── Makefile ├── CMakeLists.txt ├── doc │ └── CMake入门.md ├── include │ └── hello │ └── hello.hpp ├── lib └── src └── hello └── hello.cpp 61 directories, 294 files
|
我编写了一个引用外部库fmt
输出hello,world
的程序src/hello/hello.cpp
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| # include "hello/hello.hpp"
void stdSayHello(int i){ while(i--) fmt::print("hello world_{}\n", i); }
void fmtSayHello(int i){ while(i--) std::cout<< "hello world_"<<i<<std::endl; }
int main(){ stdSayHello(3); fmtSayHello(3); }
|
在include/
中,头文件include/hello/hello.hpp
也很简单:
1 2 3 4
| # include <iostream>
# define FMT_HEADER_ONLY // 推荐 # include "fmt/core.h"
|
cd build & cmake .. & cmake --build .
执行便在bin/
生成了可执行文件,这表明我们编译成功了!