尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

SerenityOS 的 clangd 语言服务器配置指南:compile_commands 数据库、跨编译器路径与 Include Cleaner 实战

SerenityOS 的 clangd 语言服务器配置指南:compile_commands 数据库、跨编译器路径与 Include Cleaner 实战 SerenityOS 的 clangd 语言服务器配置指南compile_commands 数据库、跨编译器路径与 Include Cleaner 实战【免费下载链接】serenityThe Serenity Operating System 项目地址: https://gitcode.com/GitHub_Trending/se/serenityclangd 是 SerenityOS一个以 x86_64 / aarch64 / riscv64 为目标的类 Unix 操作系统官方推荐的 C 语言服务器它能基于 CMake 生成的compile_commands.json编译数据库理解整个仓库AK、Userland、Kernel、Ladybird 等数十万行 C 代码。本指南以仓库文档 Documentation/ClangdConfiguration.md 为骨架结合 Toolchain/BuildClang.sh 与 Toolchain/CMake/LLVMConfig.cmake 等源码完整讲解.clangd配置文件、编译数据库的生成时机、系统 clangd 与 Serenity 工具链 clangd 的取舍以及跨编译器头文件路径的排查方法。读完本文你将能在一小时内为任意编辑器配好可用的 SerenityOS C 开发环境并看懂 clangd 报错背后的原因。clangd 与 SerenityOS为什么它是首选clangd 是 LLVM 官方提供的 C 语言服务器language server通过 LSP 协议为编辑器提供补全、跳转、重命名、诊断等功能。官方建议在 SerenityOS 开发中优先选用 clangd理由是它在各平台上“最可能开箱即用”most likely to work on all platforms。如果你使用 CLionCLion 自带一个经过特殊构建的 clangd通常可以直接工作其他编辑器VS Code、Vim/Neovim、Emacs、Helix 等通过各自的 LSP 插件或专用扩展接入任意 clangd 二进制即可。需要注意的是SerenityOS 是一个交叉编译项目——它在宿主系统如 Linux上为 Serenity 目标x86_64、aarch64、riscv64构建内核与用户态程序。因此 clangd 需要两方面的信息才能正常工作编译数据库每个源码文件用什么命令行编译编译器路径、宏定义、头文件搜索路径交叉工具链的内建头文件Serenity 专用 libc/libm 等头文件位于工具链 sysroot 中系统 clangd 默认找不到。这两点正是下文.clangd文件与--query-driver参数要解决的问题。编译数据库compile_commands.jsonclangd 理解项目的根基clangd 依赖compile_commands.json文件来理解项目结构。该文件由 CMake 在配置阶段自动生成目录示例如下对应不同架构/工具链组合Build/x86_64—— 使用系统 GCC 工具链的构建目录Build/x86_64clang—— 使用 Serenity Clang 工具链的构建目录Build/lagom—— Lagom在宿主系统上构建并测试 Serenity 组件的子项目的构建目录。你日常使用哪种配置架构 工具链就把.clangd中的CompilationDatabase指向对应的构建目录。官方推荐优先使用Clang 工具链的构建目录如Build/x86_64clang因为 GCC 编译数据库与 clangd 存在已知兼容性问题见下文“GCC 编译数据库的已知问题”。生成与更新时机必须理解的关键约束文档特别强调了一个容易踩坑的点——编译数据库不是实时更新的首次配置至少运行一次./Meta/serenity.sh run该命令会触发配置与构建来生成compile_commands.json新增源文件或修改 CMake 编译选项后必须重新运行./Meta/serenity.sh build或任何构建命令CMake 才会重新生成编译数据库在你重跑构建之前clangd不会感知新源文件或者会报告错误的编译错误。也就是说编辑 CMakeLists 或新增.cpp/.h后如果发现 clangd 行为异常第一反应应该是重新构建而不是怀疑配置。这与Meta/serenity.sh的构建流程配置 → 编译 → 生成 compile commands是一一对应的。根目录.clangd文件官方推荐配置逐行解读在 Serenity 仓库根目录放置如下.clangd文件注意当前仓库不附带该文件需开发者自行创建官方称其“开箱即用”可按需调整CompileFlags: # Add compilation flags to remove errors, or to make clangd behave like you’re compiling a specific system configuration. Add: [] # You can remove unwanted flags such as those that arent supported by the current version of clang. Remove: [] # Build/x86_64 is also possible if you don’t have the Clang toolchain, but doesn’t work as well. CompilationDatabase: Build/x86_64clang Style: # clangd 20: Use correct include style. AngledHeaders: [AK/.*, Userland/.*, Kernel/.*, Applications/.*, Lib.*/.*] Diagnostics: UnusedIncludes: Strict MissingIncludes: LooseCompileFlags增删编译标志配置项含义与用法Add: []向每条编译命令追加标志用于修复报错或模拟特定系统配置的编译行为详见下节“实用技巧”Remove: []移除编译命令中不受当前 clang 版本支持的标志CompilationDatabase: Build/x86_64clang指定编译数据库所在目录换成Build/x86_64也可用未安装 Clang 工具链时但体验较差Style.AngledHeadersclangd 20 的包含风格控制自 clangd 20 起Style区块新增了AngledHeaders指令用于让 clangd 在“插入缺失 include”时使用正确的尖括号风格。上例给出的正则列表AK/.*—— AKAlgorithms data structures Kit头文件如AK/Vector.hUserland/.*—— 用户态库与程序如Userland/Libraries/LibCore/...Kernel/.*—— 内核头文件Applications/.*—— 应用程序目录Lib.*/.*—— 所有Lib*前缀库的头文件如LibGfx/...、LibWeb/...。这些目录下的头文件都应使用尖括号形式#include AK/Vector.h而非引号形式。该指令取代了 clangd 19 及以下版本中必须使用的--header-insertionnever命令行参数见下文使 include 自动插入能按 Serenity 的目录风格正确工作。DiagnosticsInclude Cleaner头文件清理器控制Diagnostics区块的两个标志用于禁用新版 clangd 自带的 Include Cleaner 特性UnusedIncludes: Strict—— 将“未使用的 include”提示级别设为严格启用MissingIncludes: Loose—— 将“缺失的 include”提示级别设为宽松减弱。官方注释指出这两个标志就是用来关闭 Include Cleaner 的如果你不介意其产生的噪音 inlay 提示inlay hints与 problem 面板噪音可以重新启用例如改为UnusedIncludes: None或直接删除相关行。“Strict”与“Loose”是对应诊断的严重度等级Strict会把所有相关 case 都当作问题报告Loose则只在比较确定时才报告。CompileFlags 实用技巧让 clangd 与真实编译行为对齐文档给出四组非常实用的“加标志”技巧用于修复 bug 与改善代码理解模拟 Serenity 目标而非宿主系统如果你使用的不是 Serenity 工具链 clangd请在Add中加入-D__serenity__。这样 clangd 会把所有代码当作“为 Serenity 编译”来解析而不是按你的宿主系统如 Linux来解析——否则大量#ifdef __serenity__分支会被错误裁剪产生海量假报错。模拟内核/预内核编译Add: [-DKERNEL]让 clangd 按内核编译配置解析Kernel/目录大量使用#ifdef KERNELAdd: [-DPREKERNEL]则对应预内核prekernel编译配置。屏蔽 GCC 特有参数当使用 GCC 编译数据库如Build/x86_64时clangd 常会在文件顶部抱怨 clang 不认识的命令行参数典型报错如clang: Unknown argument: -mpreferred-stack-boundary3。解决办法是给Add加上对应的否定形式-mno-preferred-stack-boundary即-mno-flag name规则。内核 GCC 数据库的额外已知项对于内核的 GCC 编译数据库-mno-sse与-mno-8087两个否定参数通常能消除一批报错。这些技巧的本质是clangd 默认会尝试“吃掉”它不认识的参数但对部分参数尤其-m系列与-f系列会直接报Unknown argument用-mno-*/ 对应的否定形式即可优雅地中和掉。clangd 命令行参数系统 clangd 必须配置 --query-driver--query-driver找到交叉编译器的内建头文件如果使用系统安装的 clangd而非 Serenity 工具链自带的必须让它能找到 Serenity 交叉编译器的内建 include 路径否则永远会报形如file new not found的错误。命令行为--query-driverSERENITY_PATH/Toolchain/Local/**/*其中SERENITY_PATH替换为 Serenity 源码目录的绝对路径。--query-driver的作用是clangd 在遇到编译命令中的 GCC 风格编译器路径时会按该 glob 匹配到的编译器实际执行一次查询query从而得知其内建头文件搜索路径与预定义宏。编辑器通常提供路径占位符例如 VS Code 的${workspaceFolder}可写成--query-driver${workspaceFolder}/Toolchain/Local/**/*--header-insertionclangd 19 及以下的必要开关对于 clangd 19 及以下版本强烈建议附加--header-insertionnever以阻止 clangd 插入风格错误的 include对应上游 clangd issue #1247。因为旧版 clangd 无法识别 Serenity 这种“目录即命名空间”的头文件组织方式#include AK/String.h自动插入常生成带错误相对路径或引号形式的 include。自 clangd 20 起这个参数不再需要取而代之的正是上文.clangd中的Style.AngledHeaders指令——它从配置层面告诉 clangd 哪些目录的头文件应使用尖括号风格属于更正确、更持久的解决方案。使用 Serenity 工具链自带 clangd推荐Serenity 的 LLVM/Clang 工具链能构建一个了解 Serenity 目标及其配置的 clangd官方总体上推荐使用它原因有二它天然知道 x86_64/aarch64/riscv64 的 Serenity 目标配置__serenity__等宏与内建头文件路径无需任何额外配置它“总是最新的”always be up-to-date——随仓库工具链版本同步演进。代价是必须先构建 Clang 工具链构建步骤详见 Documentation/AdvancedBuildInstructions.md。如何构建 Serenity-aware clangd构建入口是 Toolchain/BuildClang.sh按如下方式启用 clangd 组件cd Toolchain CLANG_ENABLE_CLANGDON ./BuildClang.shCLANG_ENABLE_CLANGDON环境变量是关键开关。仓库中的 Toolchain/CMake/LLVMConfig.cmake 明确实现了这一逻辑if(DEFINED ENV{CLANG_ENABLE_CLANGD} AND $ENV{CLANG_ENABLE_CLANGD} STREQUAL ON) message(STATUS Enabling clangd as a part of toolchain build) set(CLANG_ENABLE_CLANGD ON CACHE BOOL FORCE) else() message(STATUS Disabling clangd as a part of toolchain build) set(CLANG_ENABLE_CLANGD OFF CACHE BOOL FORCE) endif()即未设置该变量或值不是ON时工具链构建默认不编译 clangd与其他 libTooling 工具如 clang-format、clang-tidy 不同。构建完成后clangd 二进制位于Toolchain/Local/clang/bin/clangd把编辑器指向该可执行文件即可。构建注意事项来自 AdvancedBuildInstructions 的警告Clang 工具链构建期间机器可能严重变慢甚至短暂卡死尤其是 CPU 核数多于可用内存GB时。可通过设置MAKEJOBS环境变量为小于 CPU 核数的数值来限制并行编译任务数例如MAKEJOBS4 CLANG_ENABLE_CLANGDON ./BuildClang.sh同目录下 Toolchain/CMake/LLVMConfig.cmake 还显示工具链同时为x86_64-serenity、aarch64-serenity、riscv64-serenity三个目标构建 runtimeforeach(target x86_64-serenity;aarch64-serenity;riscv64-serenity)并为其设置 sysroot 与编译标志——这正是“Serenity-aware” clangd 能正确处理三个架构代码的原因。已知问题与排查清单文档列出两个官方确认的已知问题排查时可按顺序核对1. 发行版 clangd 找不到交叉编译器内建头文件部分发行版的 clangd 包在提供--query-driver后仍无法识别 Serenity 交叉编译器的内建 include 路径至少在 Debian 上观察到。当 inlay 提示显示new找不到时官方建议按以下顺序“三重检查 四重检查”三重检查.clangd配置是否与上文的推荐文件完全一致尤其CompilationDatabase与CompileFlags确认已通过./Meta/serenity.sh run运行过系统保证编译数据库与 sysroot 存在且最新四重检查clangd 的命令行参数--query-driver的路径 glob 是否匹配Toolchain/Local/**/*占位符是否被正确展开。若以上全部正确仍然失败那么从 Serenity clang 工具链构建 clangd 是已知可行的最终方案即上一节的CLANG_ENABLE_CLANGDON ./BuildClang.sh。2. clangd 在极端新特性下崩溃clangd 有在“压榨编译器的前沿特性”时崩溃的倾向官方举例有时光是打开AK/Variant.h就足以触发崩溃。应对方法通常只需重启 clangd若重启无效关闭当前打开的 C 文件再重启仍无效可尝试切换 git 分支后再重启有时有帮助。该问题与 Serenity 本身无关而是 clangd 对复杂模板元编程AK/Variant.h属于重度模板代码的已知弱点属于上游限制。快速上手最小可行配置清单综合全文一个全新的 SerenityOS 开发环境按以下顺序配置即可准备构建目录执行./Meta/serenity.sh run至少一次生成Build/x86_64clang/compile_commands.json若使用 GCC 工具链则为Build/x86_64/创建根目录.clangd文件采用上文官方推荐配置将CompilationDatabase指向你最常用的构建目录日常新增源码/改 CMake 后重跑./Meta/serenity.sh build刷新编译数据库选择 clangd 来源快速方案系统 clangd --query-driverSERENITY_PATH/Toolchain/Local/**/*clangd ≤ 19 追加--header-insertionnever推荐方案CLANG_ENABLE_CLANGDON ./Toolchain/BuildClang.sh构建 Serenity-aware clangd编辑器指向Toolchain/Local/clang/bin/clangd按需微调内核/预内核开发加-DKERNEL/-DPREKERNELGCC 编译数据库报Unknown argument时用-mno-flag中和非工具链 clangd 记得加-D__serenity__遇到new找不到等错误按上文“已知问题”的检查顺序逐一核对。按此流程你就能获得接近真实编译行为的补全、跳转与诊断体验——这也是 SerenityOS 官方在 Documentation/ClangdConfiguration.md 中沉淀下来的最佳实践。【免费下载链接】serenityThe Serenity Operating System 项目地址: https://gitcode.com/GitHub_Trending/se/serenity创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表