|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +作者:yahah |
| 6 | +链接:https://www.zhihu.com/question/1979609139266213083/answer/2009429788666909340 |
| 7 | +来源:知乎 |
| 8 | +著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 |
| 9 | + |
| 10 | +## 使用方式 |
| 11 | + |
| 12 | +- 本文件分为默认规则与按需模式两层。 |
| 13 | +- 默认规则始终生效。 |
| 14 | +- 按需模式仅在用户明确要求,或任务明显需要且已获用户确认时启用;未启用前,不默认进入重流程。 |
| 15 | +- 涉及项目/系统设计、文档体系设计或高风险改动时,应在开始时让用户选择是否启用相关按需模式。 |
| 16 | + |
| 17 | +## 默认规则 |
| 18 | + |
| 19 | +### 工作原则 |
| 20 | + |
| 21 | +- 非微小改动先说明方法。 |
| 22 | +- 需求有歧义、风险高或影响大时,先澄清并获批,再开始写代码。 |
| 23 | +- 坚持 Spec Coding,避免 Vibe Coding;Plan 只写方案、范围、风险和验收标准,不写实现代码。 |
| 24 | +- 优先小步迭代;实现与审查分离。 |
| 25 | +- 完成后可执行 /simplify;必要时使用 /loop。 |
| 26 | + |
| 27 | +### 编码约束 |
| 28 | + |
| 29 | +- 代码中只使用英文。 |
| 30 | +- 注释说明意图、约束和边界,不记录开发过程式说明。 |
| 31 | +- 优先用概念、模块、职责和符号名定位代码;不要只依赖易漂移的行号,必要时可补充文件路径。 |
| 32 | +- Spec 不依赖行号定位代码。 |
| 33 | +- 不为未被请求的未来需求提前抽象、泛化或暴露配置。 |
| 34 | + |
| 35 | +### 质量与验证 |
| 36 | + |
| 37 | +- 项目早期只保留最小必要质量标准:可运行、可验证、可回滚。 |
| 38 | +- 关键路径、高风险改动和外部接口必须可验证。 |
| 39 | +- 修复 bug 时,先复现,再修复,再验证。 |
| 40 | +- 任何"已完成""已修复""已通过"的结论,都必须附验证方式、命令或结果摘要。 |
| 41 | +- 若当前无法验证,必须明确说明原因、风险和未覆盖范围。 |
| 42 | + |
| 43 | +### 拆分与沉淀 |
| 44 | + |
| 45 | +- 将任务拆成低耦合、可独立验证的子任务;必要时使用 /batch。 |
| 46 | +- 重复出现且边界稳定的流程,应沉淀为 Skill、脚本或检查清单。 |
| 47 | +- 公共规则优先沉淀为文档、测试或自动化,而不是只停留在对话里。 |
| 48 | + |
| 49 | +### 协作与纠错 |
| 50 | + |
| 51 | +- 被纠正时,先验证问题是否适用于当前代码库,再调整做法。 |
| 52 | +- 外部建议先核对是否适用,再决定是否采纳。 |
| 53 | +- 对重复性问题,沉淀为明确规则、测试或自动检查。 |
| 54 | + |
| 55 | +### Codex 协作 |
| 56 | + |
| 57 | +- Codex 是补充能力,不是默认执行者;当前 Agent 负责主线推进、需求澄清、关键决策、首轮实现和最终验收。 |
| 58 | +- 仅在以下场景使用 Codex:独立只读代码评审、adversarial review、边界清晰且可并行的子任务、或长耗时调查与后台续跑;委派前必须先定义目标、约束、验收标准和边界。 |
| 59 | +- 不要把需求澄清、方案收敛、架构取舍、小而集中的直接实现或需要持续用户交互的主线任务交给 Codex;Codex 的结果必须由当前 Agent 整合并复核。 |
| 60 | +- 可用命令:`/codex:review`、`/codex:adversarial-review`、`/codex:rescue`、`/codex:status`、`/codex:result`、`/codex:cancel`(需安装 [codex-plugin-cc](https://github.com/openai/codex-plugin-cc)) |
| 61 | + |
| 62 | +### 禁止事项 |
| 63 | + |
| 64 | +- 永远不要使用 /init,除非项目明确要求。 |
| 65 | +- CLAUDE.md 必须按项目实际需求编写,不套用空泛模板。 |
| 66 | +- 不要在代码注释、commit message 或 PR body 中使用描述开发进度的词,如 FIXED、Step、Week、Section、Phase、AC-x。 |
| 67 | +- 不要在代码注释、commit message 或 PR body 中出现 AI 工具名称,如 Codex、Claude、Grok、Gemini 等。 |
| 68 | +- 不要把外部实现细节、外部文档或外部技能树直接提升为当前项目的硬约束。 |
| 69 | + |
| 70 | +## 按需模式 |
| 71 | + |
| 72 | +### 架构与演进模式 |
| 73 | + |
| 74 | +- 适用:用户要求项目或系统设计满足分层、稳定接口、可演进,或明确要求按架构流程推进。 |
| 75 | +- 优先做分层设计;不同层次保持职责分离,只通过明确、稳定的接口交互。 |
| 76 | +- 不要让上层依赖下层实现细节,也不要建立非必要的跨层耦合;若必须依赖,应收敛为单向、最小依赖。 |
| 77 | +- 每个层次内优先做 primitive 设计;primitive 应是独立、可替换、可组合、可验证的最小功能单元。 |
| 78 | +- 若项目采用多 Agent 协作,应按层次设计专用 agent 与 skill,使其职责、输入、输出和边界清晰。 |
| 79 | +- 架构演进必须逐步验证;每一步新增特性或重构,都要确认不破坏已有接口、行为和关键路径。 |
| 80 | + |
| 81 | +### Agent-Native 文档模式 |
| 82 | + |
| 83 | +- 适用:用户要求文档同时服务人类和 Agent,或明确要求 Agent-Native 文档体系。 |
| 84 | +- 使用两层结构,避免重复: |
| 85 | + - canonical skill docs (.claude/docs/):保存详细、长期维护的正式正文,供人类和 Agent 共读。 |
| 86 | + - agent-facing index(.claude/skills/):只负责把 Agent 路由到正确正文,不复述内容,也不要求与每份正文一一对应。 |
| 87 | +- 文档应同时对人类和 Agent 可读:写清能力、前提、边界、依赖、接口和典型用法,避免只对单一读者成立的隐式上下文。 |
| 88 | +- 仅 skill 文档必须包含 frontmatter:type、tags、requires(仅写硬依赖)。 |
| 89 | +- Agent 读取文档时,先通过索引定位主题,再进入正文;仅递归读取 requires 指向的硬依赖文档,其他相邻或参考文档按需读取。 |
| 90 | +- 本地文档是当前仓库契约;外部资料、外部 skills 或示例实现只作参考,不覆盖本地约定。 |
| 91 | +- 量化结论必须带测试条件和适用范围。 |
| 92 | + |
| 93 | +### 严格验证模式 |
| 94 | + |
| 95 | +- 适用:改动高风险、回归代价高,或用户要求每一步都经过验证。 |
| 96 | +- 将工作拆成可独立验证的小步;每一步完成后先验证,再继续下一步。 |
| 97 | +- 新增特性、重构或修复都要确认不破坏已有功能、接口和关键路径。 |
| 98 | +- 若当前无法完成必要验证,应暂停继续扩展,并明确说明阻塞、风险和未覆盖范围。 |
| 99 | + |
| 100 | +## 项目简介 |
| 101 | + |
| 102 | +Apache bRPC —— 工业级 C++ RPC 框架。仓库同时包含若干可独立复用的基础库(`butil`、`bthread`、`bvar`、`json2pb`、`mcpack2pb`),RPC 层构建于其之上。权威架构文档位于 `docs/en/` 与 `docs/cn/`,重点参考 `io.md`、`threading_overview.md`、`memory_management.md`、`bthread.md`、`iobuf.md`、`load_balancing.md`、`new_protocol.md`。 |
| 103 | + |
| 104 | +## 构建 |
| 105 | + |
| 106 | +仓库同时支持三套构建系统,日常开发以 CMake 为主。 |
| 107 | + |
| 108 | +```sh |
| 109 | +# CMake(推荐,外部构建目录 + 并行编译) |
| 110 | +cmake -B build && cmake --build build -j6 |
| 111 | + |
| 112 | +# 启用单元测试需显式开启(详见下文 "测试" 章节) |
| 113 | +cmake -B build -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DBUILD_UNIT_TESTS=ON && cmake --build build -j6 |
| 114 | + |
| 115 | +# 常用 CMake 选项 |
| 116 | +-DCMAKE_EXPORT_COMPILE_COMMANDS=ON # 生成 compile_commands.json,供 clangd/LSP 使用 |
| 117 | +-DWITH_DEBUG_SYMBOLS=OFF # 不带调试符号,二进制更小 |
| 118 | +-DWITH_GLOG=ON # 用 glog 替换 butil/logging |
| 119 | +-DWITH_THRIFT=ON # 启用 thrift 协议 |
| 120 | +-DWITH_RDMA=ON # 启用 RDMA 传输 |
| 121 | +-DWITH_BTHREAD_TRACER=ON # 链接 libunwind,启用 bthread tracer |
| 122 | +-DLINK_SO=ON # example 链接共享库版本 |
| 123 | +``` |
| 124 | + |
| 125 | +替代方案:`sh config_brpc.sh --headers=<inc> --libs=<lib> [--with-glog --with-thrift --cxx=clang++ --cc=clang]` 后执行 `make`。也支持 Bazel(`bazel build //...`),细节见 `docs/en/bazel_support.md`。 |
| 126 | + |
| 127 | +如果需要快速查看最新编译产物,可优先复用仓库里已存在的 `cmake-build-debug/` 与 `cmake-build-debug-gdr/` 构建目录(确认未过期即可)。 |
| 128 | + |
| 129 | +## 测试 |
| 130 | + |
| 131 | +启用 `-DBUILD_UNIT_TESTS=ON` 后,测试二进制会生成在 `build/test/` 下。命名遵循以下模式:`test_butil`、`test_bvar`、`bthread_*_unittest`、`brpc_*_unittest`。 |
| 132 | + |
| 133 | +```sh |
| 134 | +# 通过 CTest 跑全部测试 |
| 135 | +cmake --build build -j6 && (cd build && ctest --output-on-failure) |
| 136 | + |
| 137 | +# 或使用旧版驱动脚本(要求二进制在当前目录,需 cd 到 build/test 下) |
| 138 | +cd build/test && bash ../../test/run_tests.sh |
| 139 | + |
| 140 | +# 只跑单个测试二进制(支持 gtest filter) |
| 141 | +./build/test/brpc_channel_unittest --gtest_filter=ChannelTest.connection_failed |
| 142 | +``` |
| 143 | + |
| 144 | +测试编译时带有 `-Dprivate=public -Dprotected=public -DUNIT_TEST -DBVAR_NOT_LINK_DEFAULT_VARIABLES`,并强制 include `test/sstream_workaround.h` —— 单测会主动访问类的内部状态,这是有意为之。仓库已接入 ASan,`run_tests.sh` 默认设置 `ASAN_OPTIONS="detect_leaks=0:detect_stack_use_after_return=1"`。 |
| 145 | + |
| 146 | +## 架构总览(big picture) |
| 147 | + |
| 148 | +代码呈清晰的分层结构。改动时请把新增逻辑放在已经持有相关概念的最低层: |
| 149 | + |
| 150 | +- **`src/butil/`** —— Chromium 衍生的基础库(日志、字符串、文件、时间、原子、容器、`IOBuf`、FlatMap、ResourcePool/ObjectPool、Arena)。不依赖 bthread 与 RPC。RPC 层最常用的部件是 `IOBuf`(贯穿全链路的零拷贝缓冲区)、`ResourcePool`/`ObjectPool`(无锁的强类型对象池,支撑大量内部对象)、以及 `endpoint`/`fd_utility`。 |
| 151 | +- **`src/bthread/`** —— M:N 用户态线程库。一个 bthread 是带栈协程,被一组 pthread worker 调度执行;`butex.{h,cpp}` 是类似 futex 的同步原语,所有阻塞机制(mutex、条件变量、`bthread_id`、ExecutionQueue)都构建于其上。`task_group.cpp` 是每个 worker 的调度器(含 work-stealing),`task_control.cpp` 管理 worker 池。在改调度相关代码前,请先阅读 `docs/en/bthread.md` 与 `docs/en/threading_overview.md`。 |
| 152 | +- **`src/bvar/`** —— 无锁计数器/Gauge/Recorder + 采样。框架内部统计与 `/vars` builtin 服务都依赖它。 |
| 153 | +- **`src/json2pb/`、`src/mcpack2pb/`** —— protobuf 与 JSON / mcpack 之间的编解码。HTTP/JSON 与 Baidu 历史协议会用到。 |
| 154 | +- **`src/brpc/`** —— RPC 框架本体,关键模块: |
| 155 | + - `Server` / `Acceptor` / `InputMessenger` —— 接受连接、切分输入、分派处理。`EventDispatcher`(epoll/kqueue)只负责"通知可读",真正的读取动作发生在新启动的 bthread 中,且 EDISP 会主动让出当前 worker 给该 bthread,以获得更好的 cache locality。详见 `docs/en/io.md`。 |
| 156 | + - `Socket` —— 通用连接抽象(覆盖 TCP、UDS、RDMA、流式)。发送侧使用 wait-free 的 MPSC 单链表;当一次 syscall 写不完时,会 fork 出 `KeepWrite` bthread 接管剩余数据。Socket 通过 `SocketId` 引用计数,由 `ResourcePool` 回收复用。 |
| 157 | + - `Channel` / `Controller` —— 客户端入口。`Controller` 是贯穿每次调用的状态对象,超时、重试、attachment、请求/响应编解码、鉴权等几乎所有客户端特性都从它穿过。 |
| 158 | + - **协议是可插拔的**。每个协议位于 `src/brpc/policy/*_protocol.{h,cpp}`,通过向 `InputMessenger` 注册 `Parse` + `Process` 回调接入。新增协议请按 `docs/en/new_protocol.md` 操作;**不要**把协议特有的逻辑塞进 `server.cpp` / `channel.cpp` / `controller.cpp`(这一点在 `CONTRIBUTING.md` 中已明确指出)。 |
| 159 | + - **命名服务与负载均衡同样可插拔**,位于 `src/brpc/policy/`(`*_naming_service.cpp`、`*_load_balancer.cpp`)。`LocalityAwareLoadBalancer` 是其中最微妙的一类 —— 近期 commit 表明它对所使用的时间源很敏感。 |
| 160 | + - `src/brpc/builtin/` —— HTTP 调试页(`/status`、`/vars`、`/flags`、`/rpcz`、`/connections`、各类 profiler)。新增 server 端调试接口请放在这里。 |
| 161 | + |
| 162 | +横切关注点:gflags 在全仓库被广泛用于运行时调参,`grep` `DEFINE_int32` / `DEFINE_bool` 即可定位。许多看似隐晦的行为其实是某个 flag 控制的(例如 `event_dispatcher_edisp_unsched`)。 |
| 163 | + |
| 164 | +## Examples |
| 165 | + |
| 166 | +`example/<name>_c++/` 下每个目录都是独立可构建的 demo,自带 `Makefile` 与 `CMakeLists.txt` 链接 bRPC。它们是几乎所有特性的标准用法示范 —— 在回答"X 怎么用?"之前,先在 example 里找一找,不要自行臆造用法。构建示例: |
| 167 | + |
| 168 | +```sh |
| 169 | +cd example/echo_c++ && cmake -B build && cmake --build build -j4 |
| 170 | +./build/echo_server & ./build/echo_client |
| 171 | +``` |
| 172 | + |
| 173 | +## 代码规范 |
| 174 | + |
| 175 | +- 遵循 Google C++ 风格,**缩进 4 空格**(见 `CONTRIBUTING.md`)。新增功能必须配单测。 |
| 176 | +- 头文件统一用 `.h`;实现文件 `.cpp` 与 `.cc` 混用(Chromium 来源代码保留 `.cc`,bRPC 自身代码使用 `.cpp`)。 |
| 177 | +- 仓库部分代码早于 C++17,整体最低标准是 C++11。引入更新标准的特性前,先检查 `CMakeLists.txt` 与 `Makefile` 的编译选项。 |
| 178 | +- 编译没有开启 `-Werror`(`Makefile` 中有显式注释说明),不要用"修复警告以通过 -Werror"为由做掩盖问题的改动。 |
| 179 | + |
| 180 | +# PR |
| 181 | + |
| 182 | +按照 .github/pull_request_template.md 模板,提供英文 PR 描述。 |
0 commit comments