效率提升记录

  • bitcoin
  • 发布于 2025-06-21 18:48
  • 阅读 16

本文档提供了一些关于提高Bitcoin项目开发效率的技巧,包括使用ccache缓存编译、利用多线程编译、构建所需目标、使用git worktrees管理多个工作目录、以及使用git range-diff来比较不同提交范围的差异等。

生产力笔记

目录

通用

使用 ccache 缓存编译

加速编译时间最简单的方法是缓存编译。ccache 是一种实现方式,以下是编写时的描述:

ccache 是一个编译器缓存。它通过缓存先前编译的结果并检测何时再次执行相同的编译来加速重新编译。支持的语言包括 C、C++、Objective-C 和 Objective-C++。

通过你的发行版的包管理器安装 ccache,并使用你的常规配置选项运行 cmake -B build 以选择它。

要为所有 C/C++ 项目使用 ccache,请按照此处的符号链接方法进行设置。

为了充分利用 ccache,请将以下内容放入 ~/.ccache/ccache.conf 中:

max_size = 50.0G  # 或你喜欢的任何缓存大小;默认值为 5G;0 表示无限制
base_dir = /home/yourname  # 或你保存源文件的任何位置

注意:base_dir 是 ccache 跨不同存储库/路径共享同一文件的缓存编译所必需的;它仅对 base_dir 下的路径执行此操作。因此,此选项是配合 git worktrees(如下所述)有效使用 ccache 所必需的。

不得将 base_dir 设置为“/”或包含系统标头的任何位置(根据 ccache 文档)。

生成构建系统时禁用特性

在构建系统生成期间,默认情况下仅启用必要的构建选项,以节省编译时间。

运行 cmake -B build -LH 以查看可用选项的完整列表。GUI 工具(例如 ccmakecmake-gui)也可能会有所帮助。

使用 -j 来利用你的线程

如果你的机器上有多个线程,你可以使用以下命令利用所有线程:

cmake --build build -j "$(($(nproc)+1))"

只构建你需要的

在开发过程中重新构建时,请注意,在不指定目标的情况下运行 cmake --build build 将完成很多你可能不需要的工作。它将构建 GUI(如果你已启用它)和所有测试(这比构建应用程序花费的时间更长)。

显然,在适当的时候构建和运行测试非常重要——但是当你只想进行快速编译以检查你的工作时,请考虑选择与你正在处理的内容相关的一个或一组构建目标,例如:

cmake --build build --target bitcoind bitcoin-cli
cmake --build build --target bitcoin-qt
cmake --build build --target bench_bitcoin

(你可以并且应该将此与上面的 -j 结合使用,以进行并行构建。)

在多台机器上编译

如果你有多台计算机可供使用,则可以使用 distcc 来加快编译速度。当所有计算机运行相同的操作系统和编译器版本时,这最容易。

使用 git worktrees 管理多个工作目录

如果你使用多个分支或存储库的多个副本,则应尝试 git worktrees

要创建一个新分支,该分支位于新的工作目录下,而不会中断当前工作目录(对于创建拉取请求很有用):

git worktree add -b my-shiny-new-branch ../living-at-my-new-working-directory based-on-my-crufty-old-commit-ish

要简单地在新的工作目录下检出一个 commit-ish,而不会中断当前工作目录(对于查看拉取请求很有用):

git worktree add --checkout ../where-my-checkout-commit-ish-will-live my-checkout-commit-ish

使用 git merge-base 进行用于修复和执行的交互式“虚拟变基”

在进行变基时,我们经常想要进行“虚拟变基”,即我们不是在更新后的主分支上进行变基,而是在与主分支的最后一个共同提交上进行变基。这对于重新排列提交、rebase --autosquashrebase --exec 而不会引入由更新后的主分支引起的冲突可能很有用。在这些情况下,我们可以使用 git merge-base 来识别与主分支的最后一个共同提交,并以此为基础进行变基。

要在不更新主分支的情况下 squash 在 git commit --fixup 提交中,我们可以执行以下操作:

git rebase -i --autosquash "$(git merge-base master HEAD)"

要在自从上次与主分支分离以来,在每次提交上执行 cmake --build build && ctest --test-dir build,但不在更新的主分支上进行变基,我们可以执行以下操作:

git rebase -i --exec "cmake --build build && ctest --test-dir build" "$(git merge-base master HEAD)"

这与 ccache 协同工作得很好,因为未更改的代码生成的对象很可能会命中缓存,而无需重新编译。

你还可以设置上游 refspec,以便在上面的 git worktree 命令中更轻松地引用拉取请求。

编写代码

使用 clang-format-diff.py 格式化 C/C++ 的差异

请参阅 contrib/devtools/README.md

使用 yapf-diff.py 格式化 Python 的差异

用法与 clang-format-diff.py 完全相同。你可以在此处获取它。

变基/合并代码

使用 merge.conflictstyle diff3 提供更多冲突上下文

对于解决合并/变基冲突,使用 git config merge.conflictstyle diff3 启用 diff3 样式可能很有用。代替

<<<
yours
===
theirs
>>>

你将看到

<<<
yours
|||
original
===
theirs
>>>

这可以更清楚地了解导致冲突的原因。在这种样式中,你通常只需查看 originaltheirs 之间的变化,然后将该变化机械地应用于 yours(或反之亦然)。

审查代码

使用 git diff 选项减少精神负担

在审查更改 C++ 文件中缩进的补丁时,请使用 git diff -wgit show -w。这使 diff 算法忽略空白更改。此功能也可在 github.com 上使用,方法是在显示差异的任何 URL 的末尾添加 ?w=1

在审查在许多地方更改符号名称的补丁时,请使用 git diff --word-diff。这将显示已删除/添加的单词,而不是显示已删除/添加的

在审查移动代码的补丁时,请尝试使用 git diff --patience commit~:old/file.cpp commit:new/file/name.cpp,并忽略除移动的代码主体之外的所有内容,该代码主体不应显示为 +- 行。如果不是纯粹的移动,则即使与上面描述的 -w--word-diff 选项结合使用,这也可能有效。--color-moved=dimmed-zebra 还将使兼容终端上差异中移动的块的颜色变暗。

直接获取提交

在本地检查任何远程创建的提交之前,必须先获取它。这可以通过 git fetch origin <full_commit_hash> 实现。即使提交不属于任何分支或标签,只要远程服务器没有对其进行垃圾回收,也可以获取它们。

使用 refspec 轻松引用 PR

作为直接获取提交的替代方法,在查看其他人发出的拉取请求时,可以考虑将以下部分添加到你的 .git/config 文件中:

[remote "upstream-pull"]
        fetch = +refs/pull/*/head:refs/remotes/upstream-pull/*
        url = git@github.com:bitcoin/bitcoin.git

这会将 upstream-pull 远程添加到你的 git 存储库中,可以使用 git fetch --allgit fetch upstream-pull 获取它。它将下载并在磁盘上存储大量数据(所有 PR,包括已合并和已关闭的 PR)。之后,你可以在 git showgit checkout 和任何接受提交 ID 的参数中使用 upstream-pull/NUMBER/head,以查看来自拉取请求 NUMBER 的更改。

单独获取和更新 PR

refspec 远程非常占用资源,并且可以从远程单独获取 PR。为此,你可以运行:

## 单独获取
git fetch upstream pull/<number>/head

## 获取并自动创建和切换分支
git fetch upstream pull/<number>/head:pr-<number> && git switch pr-<number>

...从命令行中,将 <number> 替换为你想要获取/更新的 PR 编号。

[!NOTE] 此处名为“upstream”的远程必须是针对其打开拉取请求的远程。 例如 github.com/bitcoin/bitcoin.git 或对于 GUI github.com/bitcoin-core/gui

通过向你的 git 配置添加别名,使这些更易于使用:

[alias]
    # 获取单个拉取请求并在一个新分支中切换到它,使用 `git pr 12345`
    pr = "!f() { git fetch upstream pull/$1/head:pr-$1 && git switch pr-$1; }; f";

    # 更新拉取请求分支,即使在强制推送之后,甚至在签出时,使用 `git pru 12345`
    pru = "!f() { git fetch --update-head-ok -f upstream pull/$1/head:pr-$1; }; f";

然后,一个简单的 git pr 12345 将从上游获取并检出该 pr。

使用 git range-diff 比较差异的差异

贡献者通常会 rebase 他们的拉取请求,或者对不在他们分支顶端的提交进行更改(可能是为了响应审查)。 这给审查者带来了一个问题,因为当贡献者强制推送时,审查者不再确定他之前对提交的审查是否仍然有效(因为即使差异在语义上相同,提交哈希现在也可能不同)。 git range-diff (Git >= 2.19) 可以通过比较差异来帮助解决此问题。

例如,要识别你先前审查过的差异 P1-5 与新差异 P1-2,N3-4 之间的差异,如下图所示:

       P1--P2--P3--P4--P5   <-- previously-reviewed-head
      /
...--m   <-- master
      \
       P1--P2--N3--N4--N5   <-- new-head (with P3 slightly modified)

你可以这样做:

git range-diff master previously-reviewed-head new-head

请注意,git range-diff 也适用于 rebase:

       P1--P2--P3--P4--P5   <-- previously-reviewed-head
      /
...--m--m1--m2--m3   <-- master
                  \
                   P1--P2--N3--N4  <-- new-head (with P3 modified, P4 & P5 squashed)

PREV=P5 N=4 && git range-diff `git merge-base --all HEAD $PREV`...$PREV HEAD~$N...HEAD

其中 P5 是你上次审查的提交,4 是新版本中的提交数。


git range-diff 也接受普通的 git diff 选项,请参阅使用 git diff 选项减少精神负担以获取有用的 git diff 选项。

你还可以设置上游 refspec,以便在上面的 git range-diff 命令中更轻松地引用拉取请求。

  • 原文链接: github.com/bitcoin/bitco...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
bitcoin
bitcoin
江湖只有他的大名,没有他的介绍。