使用临时 Shell 的项目特定 clangd 配置
摘要
一位开发者分享了一个脚本,该脚本创建一个临时 Shell,其中包含一个指向项目特定编译数据库的 clangd 包装器,从而允许一个仓库中的多个固件项目同时使用各自的 clangd 配置。
<p><a href="https://lobste.rs/s/j04gsk/project_specific_clangd_configuration">评论</a></p>
查看缓存全文
缓存时间: 2026/07/31 14:48
Felix 的博客 - 使用临时 Shell 实现项目特定的 clangd 配置
来源:https://felix-knorr.net/posts/2026-07-31-lsp-config.html
过去五年里,我一直在基于终端的编辑器中编写 C 语言和部分 C++ 代码。默认情况下,clangd 会在当前文件的父目录中查找 `compile_commands.json`。当仓库中包含多个独立构建、共享代码且具有共同仓库根的固件项目时,这就变得很烦人。每个项目都需要自己的编译数据库。每次切换项目时都要替换仓库级别的单个 `compile_commands.json` 已经很糟糕,而为不同项目运行独立的编辑器实例则让事情更糟,因为两个 clangd 实例都需要同一个文件包含不同的数据。最近我想出了一个足够喜欢(也足够不显而易见)的解决方案,值得写一篇短文。
下面的脚本以构建目标(build target)为参数,创建一个临时的、针对特定目标的开发环境。它会:
1. 在临时目录中生成该目标的 `compile_commands.json`。
2. 在同一目录中创建一个 `clangd` 包装脚本。
3. 配置该包装脚本使用生成的编译数据库,并应用我们需要的其他设置。
4. 启动一个交互式 Bash 会话,并将临时目录前置到 `PATH`。
5. 将所选目标添加到 shell 提示符中作为提醒。
由于包装脚本名为 `clangd` 且位于 `PATH` 最前面,从该 shell 启动的编辑器会启动配置正确的 clangd,无需任何项目特定的编辑器配置。`bashrc` 在加载我正常的 `~/.bashrc` 之后才将该目录前置到 PATH,这也防止了 direnv 等工具在 shell 初始化期间意外地将另一个 clangd 放在它前面。
```bash
#!/usr/bin/env bash
# Start a shell whose clangd uses the compilation database for one Bob target.
set -euo pipefail
if (($# != 1)); then
echo "usage: $(basename "$0") <target>" >&2
exit 2
fi
target=$1
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)
repo_root=$(cd "$script_dir/.." && pwd -P)
firmware_dir=$repo_root/firmware
clangd=$repo_root/dev-tools/clangd
if [[ ! -d $firmware_dir || ! -x $clangd ]]; then
echo "device-env must be located in the repository's dev-tools directory" >&2
exit 1
fi
if ! command -v uv >/dev/null; then
echo "uv is not on PATH; install it before running device-env" >&2
exit 1
fi
tmpdir=$(mktemp -d "${TMPDIR:-/tmp}/device-env.XXXXXX")
trap 'rm -rf "$tmpdir"' EXIT
(
cd "$firmware_dir"
uv run bob ninja-tool -f compdb "$target"
) >"$tmpdir/compile_commands.json"
cat >"$tmpdir/clangd" <<'EOF'
#!/usr/bin/env bash
exec /path/to/real/clangd --compile-commands-dir="$(dirname "$0")" "$@"
EOF
chmod +x "$tmpdir/clangd"
cat >"$tmpdir/bashrc" <<'EOF'
if [[ -f ~/.bashrc ]]; then
source ~/.bashrc
fi
export PATH="$DEVICE_ENV_TMPDIR:$PATH"
PS1="[denv:${DEVICE_ENV_TARGET}] ${PS1}"
EOF
export DEVICE_ENV_TARGET=$target
export DEVICE_ENV_TMPDIR=$tmpdir
bash --noprofile --rcfile "$tmpdir/bashrc" -i
```
我现在可以这样启动一个项目特定的 shell:然后从那里启动 Helix,或任何其他通过 `PATH` 调用 `clangd` 的编辑器。每个 shell 都有自己的编译数据库和 clangd 进程,因此可以同时打开多个项目而不会相互干扰。
顺便说一句,这种机制并非 clangd 专属。包含包装可执行文件的临时目录可以成为一种有用的方式,为那些通常由全局或启动它们的编辑器配置的工具提供项目特定的行为。
相似文章
Show HN: Clawk – 为编程代理提供一次性Linux虚拟机,而非你的笔记本电脑
Clawk是一个开源工具,为Claude Code等编程代理提供一次性Linux虚拟机,使其能自由运行而不危及宿主机。它通过网络白名单和文件隔离来保护密钥和系统文件安全。
使用并行Claude团队构建C编译器
Anthropic研究员展示了如何使用16个并行Claude实例自主构建一个基于Rust的C编译器,该编译器能够编译Linux内核。文章详细介绍了这一多智能体自主编码实验的架构、成本和经验教训。
使用Nix的开发环境:四个快速示例
本教程演示了使用Nix设置开发环境的四种方法,包括交互式一次性使用、配置文件以及密封的Nix Flakes,并以GoCV和OpenCV为例。
一篇详细描述Anthropic自身工程师使用Claude Code时的确切配置和工作流程的文章,包括并行实例、CLAUDE.md模式、写作者/审阅者分离、技能文件夹、插件、钩子和批量操作。
一篇详细介绍Anthropic工程师在使用Claude Code时的具体配置和工作流程的文章,涵盖并行实例、CLAUDE.md模式、写作者/审阅者分离、技能文件夹、插件、钩子和批量操作。
一份让Claude Code遵循项目规范的配置文件——「上帝模式CLAUDE.md」
一份精简的CLAUDE.md配置文件,用于强制Claude Code遵循项目规范,包含经过实战检验的规则,提升输出质量且不超过200行。