Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
---

<!-- COVERAGE_START -->
![English Coverage](https://img.shields.io/badge/en_coverage-99%25-green.svg) 634/640 docs translated
![English Coverage](https://img.shields.io/badge/en_coverage-99%25-green.svg) 639/646 docs translated
<!-- COVERAGE_END -->

## 这是什么项目
Expand Down
7 changes: 7 additions & 0 deletions code/examples/getting-started/03-first-program/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 3.20)
project(hello LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(hello main.cpp)
6 changes: 6 additions & 0 deletions code/examples/getting-started/03-first-program/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include <iostream>

int main() {
std::cout << "Hello, C++!\n";
return 0;
}
7 changes: 7 additions & 0 deletions code/examples/getting-started/04-multi-file/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 3.20)
project(greeter LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(greeter main.cpp greet.cpp)
5 changes: 5 additions & 0 deletions code/examples/getting-started/04-multi-file/greet.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include "greet.h"

std::string greet(const std::string& name) {
return "Hello, " + name + "!";
}
4 changes: 4 additions & 0 deletions code/examples/getting-started/04-multi-file/greet.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#pragma once
#include <string>

std::string greet(const std::string& name);
7 changes: 7 additions & 0 deletions code/examples/getting-started/04-multi-file/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "greet.h"
#include <iostream>

int main() {
std::cout << greet("world") << "\n";
return 0;
}
10 changes: 10 additions & 0 deletions code/examples/getting-started/05-clangd/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 3.20)
project(greeter LANGUAGES CXX)

# 让 CMake 在 build 目录生成 compile_commands.json,clangd 靠它看懂工程
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(greeter main.cpp greet.cpp)
5 changes: 5 additions & 0 deletions code/examples/getting-started/05-clangd/greet.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include "greet.h"

std::string greet(const std::string& name) {
return "Hello, " + name + "!";
}
4 changes: 4 additions & 0 deletions code/examples/getting-started/05-clangd/greet.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#pragma once
#include <string>

std::string greet(const std::string& name);
7 changes: 7 additions & 0 deletions code/examples/getting-started/05-clangd/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "greet.h"
#include <iostream>

int main() {
std::cout << greet("world") << "\n";
return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 3.20)
project(hello_cmake LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(hello main.cpp)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include <iostream>

int main() {
std::cout << "Hello, CMake!\n";
return 0;
}
20 changes: 20 additions & 0 deletions code/examples/vol7/cmake-fundamentals/02-target/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.20)
project(target_demo LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# fmt:仅在本工程内部使用的极简"第三方库",真实工程会换成 find_package(fmt REQUIRED)
add_library(fmt STATIC fmt/fmt.cpp)
target_include_directories(fmt PUBLIC fmt)

# mylib:对外暴露的库,公开头文件 include/mylib/mylib.h 用了 std::string
add_library(mylib STATIC src/mylib.cpp)
target_include_directories(mylib PUBLIC include)
# fmt 在这里写成 PRIVATE —— mylib.cpp 内部要用,但 mylib.h 完全不暴露 fmt
target_link_libraries(mylib PRIVATE fmt)

# app:下游可执行,只链接 mylib,对 fmt 一无所知
add_executable(app main.cpp)
target_link_libraries(app PRIVATE mylib)
2 changes: 2 additions & 0 deletions code/examples/vol7/cmake-fundamentals/02-target/fmt/fmt.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#include "fmt.h"
// 真实 fmt 库这里有大量实现;演示用空翻译单元即可,只要能产生 fmt::format 的链接符号定义
12 changes: 12 additions & 0 deletions code/examples/vol7/cmake-fundamentals/02-target/fmt/fmt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once
#include <string>

namespace fmt {
// 仅供演示用的极简 fmt::format,真实工程用 find_package(fmt) 接入
inline std::string format(const std::string& tmpl, const std::string& value) {
auto pos = tmpl.find("{}");
if (pos == std::string::npos)
return tmpl;
return tmpl.substr(0, pos) + value + tmpl.substr(pos + 2);
}
} // namespace fmt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once
#include <string>

namespace mylib {

/// @brief 把问候语格式化成带前缀的字符串
/// @note 返回类型用 std::string —— 这是 mylib 公开 API 的一部分,
/// 下游 app 也必须看到完整的 std::string 定义,
/// 所以 <string> 对应的 include 路径属于 INTERFACE 需求
std::string make_greeting(const std::string& name);

} // namespace mylib
8 changes: 8 additions & 0 deletions code/examples/vol7/cmake-fundamentals/02-target/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include "mylib/mylib.h"

#include <iostream>

int main() {
std::cout << mylib::make_greeting("world") << '\n';
return 0;
}
13 changes: 13 additions & 0 deletions code/examples/vol7/cmake-fundamentals/02-target/src/mylib.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include "mylib/mylib.h"

#include "fmt.h"

namespace mylib {

std::string make_greeting(const std::string& name) {
// fmt 是 mylib 内部实现细节,公开头文件 mylib.h 里看不到 fmt 的痕迹
// 所以下游根本不需要知道 fmt 的存在 —— 这正是 fmt 应当为 PRIVATE 的理由
return fmt::format("hello, {}!", name);
}

} // namespace mylib
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# CMakeLists.txt —— find_package 与 cxx_std_NN 的现代写法
#
# 这份文件演示两件事:
# 1. 用 target_compile_features 给 target 单独设 C++ 标准(现代写法)
# 2. 用 find_package 接入第三方库,拿到导入 target(现代写法)
#
# 配套文章: documents/vol7-engineering/ch00-cmake-fundamentals/03-find-package-and-cxx-standard.md

cmake_minimum_required(VERSION 3.20)
project(find_package_demo LANGUAGES CXX)

# ------------------------------------------------------------------
# C++ 标准:绑在 target 上的现代写法
# ------------------------------------------------------------------
# target_compile_features(app PRIVATE cxx_std_20) 的含义是:
# "app 这个 target 要求至少 C++20"
# CMake 会根据编译器的默认标准决定是否要往编译命令里塞 -std 标志:
# - 编译器默认 < C++20: 自动加 -std=c++20(或 gnu++20)
# - 编译器默认 >= C++20: 不加标志(默认已经满足要求)
# 详见文章里 cxx_std_17/20/23 在 GCC 16 上的实测对比。
#
# 配套还可以关掉编译器扩展(CXX_EXTENSIONS OFF),强制走纯 -std=c++NN
# 而不是带 GNU 扩展的 -std=gnu++NN:

add_executable(app main.cpp)
target_compile_features(app PRIVATE cxx_std_20)
set_target_properties(app PROPERTIES CXX_EXTENSIONS OFF)

# ------------------------------------------------------------------
# 第三方库:find_package 的现代写法(可选,需要系统或 vcpkg/Conan 装好 fmt)
# ------------------------------------------------------------------
# 解开下面这段注释需要先有 fmt:
# - Linux: 系统包管理器装(如 apt install libfmt-dev)
# - 跨平台/可复现: 用 vcpkg 或 Conan,通过 toolchain 文件注入
#
# find_package(fmt REQUIRED) 会去 CMAKE_PREFIX_PATH 下的
# <prefix>/lib/cmake/fmt/ 找 fmt-config.cmake,
# 找到后给你一个 fmt::fmt 的"导入 target"。
# 这个 target 身上挂好了 INTERFACE_INCLUDE_DIRECTORIES / IMPORTED_LOCATION 等
# 使用需求,你只需 target_link_libraries,include 路径和编译选项自动传过来。
#
# find_package(fmt REQUIRED)
# add_executable(app_with_fmt main.cpp)
# target_link_libraries(app_with_fmt PRIVATE fmt::fmt)
#
# 反模式对照(别这么写):
# include_directories(${fmt_INCLUDE_DIRS}) # 目录级,污染所有 target
# target_link_libraries(app PRIVATE ${fmt_LIBRARIES}) # 变量风格,不传播使用需求
17 changes: 17 additions & 0 deletions code/examples/vol7/cmake-fundamentals/03-find-package/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// main.cpp —— 演示 target_compile_features(cxx_std_20) 设的最低标准
//
// 这里用了一个 C++20 才有的语法:模板 lambda([]<typename T>(...) ...)
// 如果编译器实际拿到的标准低于 C++20,这一行就编不过
// 用来证明 target_compile_features 真的把标准要求传到了编译命令里

#include <iostream>
#include <string>

int main() {
// C++20: 显式模板参数列表的 lambda
auto add = []<typename T>(T a, T b) { return a + b; };

std::cout << add(1, 2) << '\n';
std::cout << add(std::string("a"), std::string("b")) << '\n';
return 0;
}
11 changes: 11 additions & 0 deletions code/examples/vol7/cmake-fundamentals/04-presets/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.21)
project(presets_demo LANGUAGES CXX)

# 兜底:CMakePresets.json 已通过 cacheVariables 设了这几个值,
# 这里再 set 一遍是为了支持"不用 preset、直接 cmake -B build"的老式姿势
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# 用 NDEBUG 区分 Debug / Release,方便验证 CMAKE_BUILD_TYPE 真的流到了编译命令
add_executable(app main.cpp)
47 changes: 47 additions & 0 deletions code/examples/vol7/cmake-fundamentals/04-presets/CMakePresets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 21,
"patch": 0
},
"configurePresets": [
{
"name": "base",
"hidden": true,
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"CMAKE_CXX_STANDARD": "17",
"CMAKE_CXX_STANDARD_REQUIRED": "ON",
"CMAKE_CXX_EXTENSIONS": "OFF"
}
},
{
"name": "debug",
"displayName": "Debug (含 -g -O0)",
"inherits": "base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "release",
"displayName": "Release (含 -O3 -DNDEBUG)",
"inherits": "base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
}
],
"buildPresets": [
{
"name": "debug",
"configurePreset": "debug"
},
{
"name": "release",
"configurePreset": "release"
}
]
}
10 changes: 10 additions & 0 deletions code/examples/vol7/cmake-fundamentals/04-presets/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <cstdio>

int main() {
#ifdef NDEBUG
std::puts("release build (NDEBUG defined)");
#else
std::puts("debug build (NDEBUG NOT defined)");
#endif
return 0;
}
21 changes: 21 additions & 0 deletions code/examples/vol7/wsl-clangd/.clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# .clang-tidy —— clang-tidy 配置(YAML)
# clangd 启动时会自动找工程根目录的 .clang-tidy 读进来,
# 配合 .clangd 里的 Diagnostics.ClangTidy 一起决定跑哪些 check。
# 顺序:.clangd 的 Add/Remove 在 .clang-tidy 的 Checks 之后再叠加。

Checks: >
-*,
modernize-*,
bugprone-*,
performance-*,
readability-*,
-modernize-use-trailing-return-type,
-readability-magic-numbers,
-readability-identifier-length

WarningsAsErrors: ''
HeaderFilterRegex: '.*'
CheckOptions:
- key: readability-function-cognitive-complexity.Threshold
value: '25'
FormatStyle: file
53 changes: 53 additions & 0 deletions code/examples/vol7/wsl-clangd/.clangd
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# .clangd —— clangd 项目级配置(YAML)
# clangd 会沿源文件所在目录一路向上搜 .clangd,所有命中的片段按顺序合并,
# 越靠近源文件的片段优先级越高(可覆盖父目录的同名 key)。
# 字段权威来源:https://clangd.llvm.org/config.html

CompileFlags:
# Add:在 compile_commands.json 里每条命令后面追加这些 flag
# 想让 clangd 的报错和真编译一样严,就把它加上
Add: [-Wall, -Wextra, -Wno-unused-parameter]
# Remove:干掉编译命令里某些 clangd 不该再跑一遍的 flag
# 典型场景:compile_commands 里有 -fsanitize=thread,clangd 不需要也不该重跑它
Remove: [-Wno-unused-parameter, -fsanitize=thread]
# Compiler:把编译器可执行名替换成指定值
# 不写就用 compile_commands.json 里原始的;写 clang++ 是让 clangd 用 Clang 自家
# 驱动去 query 系统头/ABI,常见于交叉编译场景(原始编译器是 arm-none-eabi-g++)
Compiler: clang++

Index:
# Background: Build = 后台索引项目并落盘到 ~/.cache/clangd/index/
# Skip = 不做后台索引(超大项目想省内存时关掉)
Background: Build
# StandardLibrary: Yes = 把标准库符号纳入索引,补全 std::xxx 才有结果
StandardLibrary: Yes
# External:指向一个外部预构建好的索引文件,大项目用得上
# External:
# File: /path/to/project-idx.riff
# MountPoint: /path/to/dep-source-tree

InlayHints:
# 行内提示(灰色虚文字)。clangd 18+ 支持,18 之前这些 key 被忽略
Enabled: Yes
ParameterNames: Yes # 函数调用处显示参数名 foo(/*name=*/"x")
DeducedTypes: Yes # 显示 auto 推导出的类型 auto /*= int*/
Designators: Yes # 结构体初始化显示字段名 {.x=1, .y=2}
BlockEnd: Yes # 大块 } 后显示它属于哪个函数/命名空间

Diagnostics:
# ClangTidy:clangd 直接读 .clang-tidy 文件就能跑,这里再加一份项目级开关
# 用于覆盖 .clang-tidy,或者按目录差异化(比如 tests/ 目录关掉某些 check)
ClangTidy:
Add: [modernize-*, bugprone-*, performance-*, readability-*]
Remove: [modernize-use-trailing-return-type, readability-magic-numbers]
# UnusedIncludes / MissingIncludes:clangd 自带的 include-cleaner
# Strict = 标记"include 了但没用上"和"用上了但没 include"两种问题
# 想 IWYU 严格化再开;刚上手建议先 None,免得满屏是黄波浪线
UnusedIncludes: Strict
MissingIncludes: Strict
# Suppress:屏蔽某些 clangd 内建诊断。常见值 '*'(全屏,慎用)或具体 code
Suppress: [unused-includes]

Hover:
# ShowAKA:鼠标悬停在宏/typedef 展开后的"别名"上时,同时显示原始名
ShowAKA: Yes
13 changes: 13 additions & 0 deletions code/examples/vol7/wsl-clangd/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.20)
project(greeter LANGUAGES CXX)

# 把每个 .cpp 的完整编译命令导出到 build/compile_commands.json,
# clangd 拿到这份"翻译说明书"才能精确还原每个文件的编译视角
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_executable(greeter main.cpp greet.cpp)
target_include_directories(greeter PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
Loading
Loading