1 背景介绍 clangd
是一个基于 LLVM 的 Clang 编译器前端提供的代码补全服务工具,主要用于 C 和 C++ 的代码补全、诊断、重构等功能。它支持多种编辑器和 IDE,并且通过 Language Server Protocol (LSP) 提供服务,使得它可以很容易地集成到不同的开发环境中。
个实际开发过程中不需要了解 clangd
的细节, 只需要通过 .clangd
配置文件指导 clangd
行为。
2 配置规则介绍 .clangd
是 Clangd 的配置文件,用于在项目中自定义 Clangd 的行为。这个文件通常位于项目的根目录下,Clangd 会在当前文件所在的所有父目录中搜索 .clangd
文件。
2.1 配置文件层次结构 .clangd
文件使用 YAML 格式,可以包含以下几个主要部分:
CompileFlags
: 编译标志部分
Diagnostics
: 诊断设置部分
InlayHints
: 代码提示设置部分
Completion
: 代码补全设置部分
SemanticTokens
: 语义标记设置部分
2.2 案例配置文件说明 更详细的配置工作参考 https://clangd.llvm.org/config
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 If: PathMatch: .*\.h PathExclude: include/llvm-c/.* CompileFlags: Add: - "-Wall" - "-Wextra" - "-std=c++20" - "-Iinclude" - "-isystemF:/include" Remove: ["-Werror" ] Compiler: clang++ Index: Background: true BuildSystem: "CMake" IndexFile: ".clangd-index" ImplicitDynamic: true ResourceDir: "/path/to/resource" Diagnostics: ClangTidy: Add: ["cppcoreguidelines-*" , "modernize-*" , "performance-*" ] Remove: ["clang-analyzer-*" ] ClangTidyChecks: true Options: UseChecks: ["*" ] HeaderFilterRegex: ".*" WarningsAsErrors: "cppcoreguidelines-*" InlayHints: Enabled: true ParameterNames: true DeducedTypes: true Designators: true Completion: AllScopes: true Brackets: "[]" SemanticTokens: Enabled: true DisabledKinds: ["Macro" ] DisabledModifiers: ["Static" ]
3 生成 compile_commands.json
文件 compile_commands.json
是一个包含编译命令的 JSON 文件,用于描述项目中每个源文件的编译方式。它的主要作用是帮助 Clangd
和其他工具了解项目的编译设置,从而提供更准确的代码补全、跳转和诊断功能。具体作用如下:
3.1 Cmake生成 compile_commands.json
3.1.1 方案一: CMakeLists.txt
设置 1 set (CMAKE_EXPORT_COMPILE_COMMANDS ON )
3.1.2 方案二: 命令行参数设置 1 2 3 mkdir buildcd buildcmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
3.2 Makefile生成 compile_commands.json
Makefile本身不能直接生成 compile_commands.json
文件1。不过,可以使用一些工具来生成这个文件,例如Bear 和CompileDB 。
3.2.1 Bear Bear是一个生成JSON编译数据库的工具,非常适合用于Makefile项目3。使用方法如下:
安装Bear:bash Copy
运行Makefile并生成 compile_commands.json
:bash Copy
3.2.2 CompileDB CompileDB是另一个生成 compile_commands.json
的工具,适用于GNU Make项目5。使用方法如下:
安装CompileDB:bash Copy
运行Makefile并生成 compile_commands.json
:bash Copy
4 实际案例 以一个使用 C++20
+ vcpkg
包管理的 CMake
项目为例,详细代码参考: https://github.com/ToniXWD/ClangdLearn
关于vcpkg的使用可以参考我上一篇文章: vcpkg包管理工具介绍
配置 CMakeLixts.txt
1 2 3 4 5 6 7 8 9 10 11 cmake_minimum_required (VERSION 3.10 )project (ClangdLearn)find_package (fmt CONFIG REQUIRED)set (CMAKE_CXX_STANDARD 20 )set (CMAKE_EXPORT_COMPILE_COMMANDS ON )add_executable (ClangdLearn main.cpp)target_link_libraries (ClangdLearn PRIVATE fmt::fmt)
main.cpp
, 使用C++20的协程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 #include "fmt/core.h" #include <algorithm> #include <coroutine> #include <iostream> #include <optional> #include <ranges> #include <vector> void print_even_numbers (const std::vector<int > &numbers) { auto even_numbers = numbers | std::views::filter ([](int n) { return n % 2 == 0 ; }); for (const auto &num : even_numbers) { fmt::print ("{} " , num); } fmt::print ("\n" ); } struct Generator { struct promise_type { int current_value; auto yield_value (int value) -> std::suspend_always { current_value = value; return {}; } auto initial_suspend () -> std::suspend_always { return {}; } auto final_suspend () noexcept -> std::suspend_always { return {}; } auto get_return_object () -> Generator { return Generator{this }; } void return_void () {} void unhandled_exception () { std::terminate (); } }; using handle_type = std::coroutine_handle<promise_type>; handle_type coro; Generator (promise_type *p) : coro (handle_type::from_promise (*p)) {} ~Generator () { if (coro) coro.destroy (); } auto move_next () -> bool { coro.resume (); return !coro.done (); } [[nodiscard]] auto current_value () const -> int { return coro.promise ().current_value; } }; auto generate_numbers (int max) -> Generator { for (int i = 1 ; i <= max; ++i) { co_yield i; } } auto main () -> int { std::vector<int > numbers = {1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }; fmt::print ("Even numbers: " ); print_even_numbers (numbers); fmt::print ("Generated numbers: " ); auto gen = generate_numbers (10 ); while (gen.move_next ()) { fmt::print ("{} " , gen.current_value ()); } fmt::print ("\n" ); return 0 ; }
配置 .clangd
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 CompileFlags: Add: - "-Wall" - "-Wextra" - "-std=c++20" - "-Iinclude" - "-isystemF:/software/vcpkg/installed/x64-windows/include" Diagnostics: ClangTidy: Add: ["cppcoreguidelines-*" , "modernize-*" , "performance-*" ] Remove: ["clang-analyzer-*" ] InlayHints: Enabled: true ParameterNames: true DeducedTypes: true Designators: true Completion: AllScopes: true
编译运行
1 2 cmake --preset vcpkg cmake --build build