本章目标:学会组织真实项目——CMake 构建系统、 单元测试框架、代码组织、CI 思维。写完代码只是开始, 能"持续地、可验证地"维护才是工程师。
myapp/
├── CMakeLists.txt # 构建脚本
├── include/myapp/ # 头文件(公共接口)
│ └── math.hpp
├── src/ # 源文件
│ ├── main.cpp
│ └── math.cpp
├── tests/ # 测试
│ ├── CMakeLists.txt
│ └── test_math.cpp
└── CMakePresets.json # 可选的构建预设
规则:
# CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(myapp CXX) # 项目名 + 语言
set(CMAKE_CXX_STANDARD 26) # C++26
set(CMAKE_CXX_STANDARD_REQUIRED ON) # 强制
set(CMAKE_CXX_EXTENSIONS OFF) # 不要 GNU 扩展
# 库 + 可执行文件
add_library(mymath src/math.cpp) # 库
target_include_directories(mymath PUBLIC include)
add_executable(app src/main.cpp)
target_link_libraries(app PRIVATE mymath)
# 测试
enable_testing()
add_subdirectory(tests)
# tests/CMakeLists.txt
add_executable(test_math test_math.cpp)
target_link_libraries(test_math PRIVATE mymath)
add_test(NAME math COMMAND test_math)
构建命令(两种方式二选一):
# 方式1:Makefile
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
ctest --test-dir build # 跑测试
# 方式2:Ninja(更快,Termux 推荐)
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build
ctest --test-dir build
常用变量:
-DCMAKE_BUILD_TYPE=Debug/Release # 调试/发布
-DCMAKE_CXX_FLAGS="-O2 -Wall" # 附加编译参数
-DCMAKE_PREFIX_PATH=... # 依赖查找路径
不用框架也能测(本书测试就是这么写的), 但工程上推荐框架。最流行两个:
Catch2 极简用法(v3):
#include <catch2/catch_test_macros.hpp>
#include "math.hpp"
TEST_CASE("加法", "[math]") {
REQUIRE(add(2, 3) == 5); // 断言:失败即中止本用例
CHECK(mul(2, 3) == 6); // 断言:失败继续跑
}
// 需要提供 main:
#define CATCH_CONFIG_MAIN // 放在某个 cpp 顶部
#include <catch2/catch_all.hpp>
GoogleTest 极简用法:
#include <gtest/gtest.h>
TEST(MathTest, Add) {
EXPECT_EQ(add(2, 3), 5);
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
测试三原则:
[手工/UI 测试] ← 少
[集成测试] ← 中
[单元测试] ← 多(最重要、最快)
TDD(测试驱动开发):先写失败测试 → 写代码让它过 → 重构。不是所有人都用,但"写完立刻测"是底线。
覆盖率工具:llvm-cov(clang 自带):
clang++ -std=c++26 -fprofile-instr-generate -fcoverage-mapping ...
llvm-profdata merge ...
llvm-cov report ...
第28章测试目录里会生成一个完整 mini 项目:
mini_project/
├── CMakeLists.txt
├── include/mymath/math.hpp
├── src/math.cpp
└── tests/test_math.cpp
构建并测试:
cd mini_project
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build
ctest --test-dir build --output-on-failure
亲手跑通它,你就掌握了现代 C++ 工程化的基本闭环。
AddressSanitizer(内存错误检测):
clang++ -std=c++26 -fsanitize=address,undefined -g app.cpp -o app
./app # 越界/悬空/泄漏/UB 立刻报告并定位
日常开发建议:Debug 构建永远开 ASan。 它找不到真凶时的退路是 gdb(见附录 A)。
git init
git add . && git commit -m "初始版本"
git log --oneline
git branch feature-x && git checkout feature-x
git merge feature-x
规范:
clang-tidy src/math.cpp -- -std=c++26
clang-format -i src/*.cpp
配合 CMake:
add_compile_options(-Wall -Wextra -Werror) # 警告当错误
vcpkg(微软):C++ 的 npm
git clone https://github.com/microsoft/vcpkg
./vcpkg install fmt boost
# CMake 里自动 find_package
Conan(更灵活):配置复杂,团队/公司用得多。 知道"有这回事"即可,需要时再学。
练习题(配套测试:测试_第28章_工程化.sh)