[万字长文]Visual Studio Code 配置 C/C++ 开发环境的最佳实践(VSCode + Clangd + XMake)
本文持续更新,建议收藏
0 前言
听说 C++ 23 中 std::printf 又要王者归来,如果不想学 C艹,那试试 Rust 也不错:
为什么要写这篇文章?
自从微软推出了 LSP 语言服务协议(Language Server Protocol) 后,每种编程语言只需实现一个强大的 Language Server 后端,就可以为任何支持 LSP 协议的 IDE/Editor 前端提供代码高亮、自动补全、导航重构等功能,而不必为每一个开发工具单独开发插件。实际上,正是 LSP 和 DAP 的出现让 IDE 和编辑器的界限越来越模糊。
截止到 2022 年,开源社区已经涌现出一大批优秀的 Language Server 实现,它们在各自领域已经拥有了接近甚至超越商业化 IDE 的功能:
- Rust-Analyzer(Rust)
- Clangd(C/C++)
- Haskell-Language-Server(Haskell)
- Gopls(Go)
- Pylance(Python)
- TexLab(LaTeX)
- ...
关于更多 Language Server 实现:
目前支持 LSP 协议的 IDE/Editor:
- Visual Studio Code
- Neovim
- Sublime Text
- Emacs
- Fleet
- Eclipse
- ...
其中 VS Code 是当下最流行的代码编辑器,拥有现代化的外观和丰富的插件生态,配合 LSP 就是一个轻量级的 IDE。但笔者在配置开发环境时发现,互联网上大量教程要么已经过时、要么使用的插件和工具链并不理想,给人一种 VSC 仍不堪大用的感觉。实际上,对于 Rust、Haskell 等编程语言,VS Code 未必比 Jetbrains 全家桶逊色。
C/C++ 因其复杂的语法、沉重的历史包袱、多样的平台和工具链,导致 IDE/Editor 对工程项目的支持往往不甚理想。本文将初步介绍如何利用 XMake 在 Windows、Macos、Linux 平台配置 VSCode C/C++ 开发环境。
与 VSCode 官方文档配置 相比拥有的优势
- Clangd 具有更优秀的性能,微软官方 Cpptools 的代码提示功能有明显延迟
- Clangd 提供更精准的「功能」、「转到定义」、「重命名符号」、「自动添加头文件」等功能(大名鼎鼎的 CLion 就是基于 Clangd)
- Clang-Tidy 提供了强大的「静态检查」支持,并对于部分代码提供「快速修复」功能。详情请见 Clang-Tidy Checks。本文主要添加了对于「Google 开源项目风格指南」「Cpp Core Guidelines」和性能、潜在的 bug、移植性、现代 C++ 的检查
- 微软官方 Cpptools 仅提供 Debug 功能(也支持使用 CodeLLDB 插件进行调试)
-
使用
XMake
而非 CMake 作为项目构建工具
。XMake 是一个基于 Lua 的轻量级跨平台自动构建工具,适用于多种编程语言,关于 XMake 相对 CMake 的优势,知乎上有大把的文章。XMake 插件可以轻松一键编译、运行和调试,
无需配置
tasks.json
和launch.json
,会给你一种在 C++ 中用 Cargo 的错觉(ㄟ( ▔, ▔ )ㄏ
笔者手头没有 Mac,新电脑又装不了黑苹果,所以配置过程中如果遇到问题,请善用互联网:
- 项目官网
- GitHub issue
- 知乎
- CSDN
- Stack Overflow
- 搜索引擎
- ...
还是无法解决的话,欢迎在评论区提出,大家一起讨论。
1 安装开发工具
首先在操作系统上安装 C/C++ 工具链(编译器和构建工具)
Windows
Windows 平台最常用的 C/C++ 编译器是微软的 MSVC,这也是目前对 C++20 标准支持最好的编译器。最简单的安装方法就是装一个 Community Visual Studio 2022 ,然后在如下对话框中选择“使用 C++ 的桌面开发”(其它工具如 git 也可以在这里安装)
你也可以安装 C + + 桌面开发工具包,而无需安装完整的 Visual Studio。从 Visual Studio 下载页 向下滚动,直到在“所有下载”部分中看到“ 适用于 Visual Studio 2022 的工具”,然后点击“为 Visual Studio 2022 生成工具”的下载按钮。这将启动 Visual Studio Installer,它将打开一个对话框,显示可用的 Visual Studio Build Tools,后安装即可:
为 MSVC 编译器配置环境变量( 这一步应该是可选的,配置的时候不妨先跳过去,遇到问题再回来 ):
首先打开 设置-系统-关于界面,点击 Advanced system settings,在弹出窗口中点击 Environment Variables(如下图所示):
然后在弹出的窗口中,在 User variables for XXX 一栏中,配置用户变量(如下图所示):
接下来 要配置的路径会因你的系统环境而有所不同!请在你的文件管理器地址栏中复制对应的路径 :
点击 New 按钮,新建几个用户变量,变量名和变量值如下表:
Variable | Value |
---|---|
MSVC | C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.33.31629 |
WK10_BIN | C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0 |
WK10_INCLUDE | C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0 |
WK10_LIB | C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0 |
INCLUDE | %WK10_INCLUDE%\ucrt;%WK10_INCLUDE%\um;%WK10_INCLUDE%\shared;%MSVC%\include; |
LIB | %WK10_LIB%\um\x64;%WK10_LIB%\ucrt\x64;%MSVC%\lib\x64; |
然后在选则名为 Path 的用户变量,点击 Edit,点击 New 新增如下三行内容:
%MSVC%\bin\HostX64\x64
%WK10_BIN%\x64
C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin
最后在 WIndows 终端中输入
cl
命令和
cmake
命令进行验证(如下图所示):
然后安装 XMake:
可以在 Github Release 下载并安装最新版的 XMake:
也可以通过 Powershell 脚本安装 XMake:
$ Invoke-Expression (Invoke-Webrequest 'https://xmake.io/psget.text' -UseBasicParsing).Content
MacOS X
OS X 平台使用 Clang-LLVM 工具链进行 C/C++ 开发,之前提到的 Clangd 就是 LLVM 工具链的一个子项目。如果你安装过 XCode ,应该会附带 Apple Clang 编译器。通过以下命令检验 Clang 是否安装:
$ clang --version
如果无法输出版本信息,通过以下命令安装 Apple Calng:
$ xcode-select --install
然后通过 MacOS 上著名的包管理工具 Homebrew 安装 XMake:
$ brew install xmake
如果你的 Mac 上没有安装 Homebrew,因为 homebrew官网 给出的安装脚本需要科学上网,笔者建议用国内 某大神写的安装脚本 ,不仅免去科学上网的繁琐,安装完成后还会自动转换为国内镜像源,在系统终端内输入如下命令以安装 Homebrew:
$ /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"
按照说明进行操作:
安装过程出现错误请查询:
相比 XCode 自带的 Apple Calng,通过 Homebrew 安装的 Clang 对 C++20 标准支持更好,各大编译器对 C++ 版本(语言特性和标准库)的支持见:
所以你也可以用 Homebrew 安装 Clang-LLVM:
$ brew install llvm
输入以下命令添加环境变量:
$ echo 'export PATH="/usr/local/opt/llvm/bin:$PATH"' >> ~/.zshrc
$ echo 'export LDFLAGS="-L/usr/local/opt/llvm/lib"' >> ~/.zshrc
$ echo 'export CPPFLAGS="-I/usr/local/opt/llvm/include"' >> ~/.zshrc
可能需要输入 Password,注意输入密码时终端不会显示已输入的字符(你的键盘没有坏~)
在终端内键入命令,以验证是否安装成功:
$ which clang
$ which clangd
$ which lldb
会输出对应的安装路径。
GNU/Linux
可以使用 GCC 编译器,也可以通过系统的包管理器安装 Clang-LLVM 工具链,用 GNU/Linux 工作的大佬应该懂得取舍。
推荐使用 shell 脚本安装 XMake:
$ bash <(wget https://xmake.io/shget.text -O -)
2 配置 VSCode 及其拓展
VSC 快捷键
-
Ctrl+鼠标左键
是文件、函数等跳转。 -
Alt + ←
跳转后返回原处 -
Ctrl + Shift + O
列出函数名 -
Ctrl + P
列出近期打开的文件名 -
Ctrl + Tab
列出最近打开的文件,在开发时,两个文件间切换时效率很高。
插件推荐
在 官网 安装 Visual Studio Code 后,安装如下拓展:
- clangd (安装后建议通过它下载 clangd 二进制包)
- C/C++ (又名 cpptools,用来 debug 程序)
- XMake (XMake 插件)
- C++ Class Creator (快速创建 C++ Class)
- One Dark Pro
- Gruvbox Material Icon Theme (图标主题)
- Project Manager(收藏、识别和管理你的工作空间和项目文件夹)
- Error Lens(更直观的错误提示,可选)
- Vim(Vim 模拟器,不了解 Vim 的不要安装)
- GitLens(Git插件,可选)
- Git Graph(Git插件,可选)
- GitHub Copilot(Github 开发的代码智能提示插件,不建议初学者使用)
注意: 「C/C++」插件和「clangd」插件共存,VSC 会提示发生冲突,请选择「Disable IntelliSense」
Vim 插件的使用:
settings.json 配置 ⚠
通过
F1
或
ctrl/command+shift+p
快捷键打开 VSC 的命令面板(Command Palette),然后输入并执行
Preferences: Open User Settings (JSON)
即可打开名为
setting.json
的设置文件。笔者倾向于将尽可能多的设置放在
settings.json
中,以便于用账号进行同步。下面贴出笔者的个人配置及说明,你可以
有选择地粘贴
到自己的
settings.json
中。
- 请认真读一遍注释!
-
除全局
settings.json
外,这些配置也可以粘贴到项目文件夹中的.vscode/settings.json
中,这样只对该项目生效,且优先级高于全局设置 - 如果你认为 Clangd 插件对 C++20 语法的支持还不够好,也可以使用 cpptools
{
// [[Terminal]]
"terminal.integrated.defaultProfile.osx": "zsh", // MacOS: 集成终端默认为 zsh
"terminal.integrated.macOptionIsMeta": true, // MacOS: 将 Option 键视为终端上的元键
"terminal.integrated.tabs.showActions": "always", // 始终显示“新建终端”按钮旁的“终端拆分”和“终止”按钮
"terminal.integrated.tabs.showActiveTerminal": "always", // 始终显示活动终端
"terminal.integrated.enableBell": true, // 集成终端启用视觉化铃声
"terminal.integrated.gpuAcceleration": "on", // 集成终端使用GPU加速
"terminal.integrated.rightClickBehavior": "selectWord", // 集成终端右击时选择光标下方的字词,并打开上下文菜单
"terminal.integrated.defaultProfile.windows": "PowerShell",
"terminal.integrated.env.windows": {
"LC_ALL": "zh_CN.UTF-8" // 集成终端编码: zh_CN.UTF-8
"terminal.integrated.profiles.windows": {
"PowerShell": {
"source": "PowerShell",
"icon": "terminal-powershell"
"Command Prompt": {
"path": [
"${env:windir}\\Sysnative\\cmd.exe",
"${env:windir}\\System32\\cmd.exe"
"args": [],
"icon": "terminal-cmd"
"Git Bash": {
"source": "Git Bash"
"Windows PowerShell": {
"path": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
// [[Git]]
"git.autofetch": true, // 自动从当前 Git 存储库的默认远程库提取提交
"git.confirmSync": false, // 同步 Git 存储库前确认
"git.enableSmartCommit": true, // 没有暂存的更改时,直接提交全部更改
"git.mergeEditor": true, // 启用三向合并编辑器
"gitlens.defaultDateLocale": null,
"gitlens.defaultDateFormat": null,
"gitlens.defaultDateShortFormat": null,
// [[Vim]]
"vim.easymotion": true,
"vim.incsearch": true,
"vim.useSystemClipboard": true,
"vim.useCtrlKeys": true,
"vim.hlsearch": true,
"vim.insertModeKeyBindings": [
"before": [
"j",
"after": [
"<Esc>"
"vim.normalModeKeyBindingsNonRecursive": [
"before": [
"<leader>",
"after": [
"d",
"before": [
"<C-n>"
"commands": [
":nohl"
"before": [
"commands": [
"lineBreakInsert"
"silent": true
"vim.leader": "<space>",
"vim.handleKeys": {
"<C-a>": false,
"<C-f>": false
// [[Appearance]]
"terminal.integrated.fontSize": 14, // 集成终端字号
"explorer.compactFolders": false, // 资源管理器不采用紧凑模式
"editor.fontFamily": "JetBrains Mono Medium, LXGW Bright Medium", // 编辑器全局字体
"editor.fontLigatures": true, // 启用连字体
"editor.fontSize": 14, // 字号
// "editor.fontWeight": "450", // 字体粗细
"editor.lineHeight": 0, // 行高:使用 0 根据字号自动计算行高
"editor.bracketPairColorization.enabled": true, // 控制是否对括号着色
"editor.bracketPairColorization.independentColorPoolPerBracketType": false, // 各类括号着色等级不独立
"editor.guides.bracketPairs": true, // 启用括号指导线
"editor.guides.bracketPairsHorizontal": "active", // 启用水平括号指导线
"editor.guides.highlightActiveIndentation": false, // 禁用高亮选中的缩进指导线
"editor.guides.indentation": false, // 禁用缩进指导线
"editor.semanticHighlighting.enabled": true, // 启用语义高亮
// 自定义语法高亮示例
"editor.semanticTokenColorCustomizations": {
"[One Dark Pro]": {
"rules": {
// "selfKeyword": {
// "foreground": "#DD94E5",
// "fontStyle": "italic"
// }
"workbench.colorTheme": "One Dark Pro", // 颜色主题
"workbench.iconTheme": "gruvbox-material-icon-theme", // 图标主题
"workbench.startupEditor": "none", // 在没有从上一个会话恢复出信息的情况下,在启动时不打开编辑器
"workbench.view.alwaysShowHeaderActions": true, // 显示视图头部的操作项
// 括号颜色
"workbench.colorCustomizations": {
"[One Dark Pro]": {
"editorBracketHighlight.foreground3": "#9CDCFE",
"editorBracketHighlight.foreground4": "#F3FD00",
"editorBracketHighlight.foreground5": "#F47D9F",
"editorBracketHighlight.foreground6": "#A5ADFE"
// 针对输出窗口的部分设置
"[plaintext]": {
"editor.fontLigatures": false, // 不使用连字体
"editor.formatOnSave": false, // 不在保存时自动格式化
"editor.wordWrap": "on" // 启用自动换行
// [[Copilot]]
"github.copilot.enable": {
"*": true,
"yaml": false,
"plaintext": true,
"markdown": false,
"jsonc": false,
"cpp": false
// [[XMake]]
"xmake.runMode": "buildRun", // 运行前自动 build
//
"xmake.additionalConfigArguments": "--cc=clang-cl --cxx=clang-cl", // windows 可以指定 clang-cl 作为编译器
// "xmake.debugConfigType": "codelldb", // 使用 codelldb 插件而非 cpptools 进行调试
"xmake.buildLevel": "verbose", // 设置编译时输出信息级别,默认是warnings级别,仅输出编译警告信息以及正常信息,verbose级别输出完整的编译命令行参数,debug级别对应 xmake -vD 的诊断信息,会打印出错的栈信息
"xmake.customDebugConfig": {
"console": "integratedTerminal" // XMake调试时使用集成终端而非 debug console,也可以使用 externalTerminal
"xmake.debuggingTargetsArguments": {
"default": [
// 啥也没有
// [[C/C++]]
// cpptools
"C_Cpp.intelliSenseEngine": "Disabled", // 禁用微软 Cpptools 插件的提示功能
"C_Cpp.codeAnalysis.runAutomatically": false,
"C_Cpp.formatting": "Disabled",
// clangd
"clangd.path": "c:\\Users\\Sirius\\AppData\\Roaming\\Code\\User\\globalStorage\\llvm-vs-code-extensions.vscode-clangd\\install\\15.0.3\\clangd_15.0.3\\bin\\clangd.exe", // clangd 安装路径
// Clangd 运行参数(在终端/命令行输入 clangd --help-list-hidden 可查看更多)
"clangd.arguments": [
"--all-scopes-completion", // 全局补全(补全建议会给出在当前作用域不可见的索引,插入后自动补充作用域标识符),例如在main()中直接写cout,即使没有`#include <iostream>`,也会给出`std::cout`的建议,配合"--header-insertion=iwyu",还可自动插入缺失的头文件
"--background-index", // 后台分析并保存索引文件
"--clang-tidy", // 启用 Clang-Tidy 以提供「静态检查」,下面设置 clang tidy 规则
"--clang-tidy-checks=performance-*, bugprone-*, misc-*, google-*, modernize-*, readability-*, portability-*",
"--compile-commands-dir=${workspaceFolder}/.vscode", // 编译数据库(例如 compile_commands.json 文件)的目录位置
"--completion-parse=auto", // 当 clangd 准备就绪时,用它来分析建议
"--completion-style=detailed", // 建议风格:打包(重载函数只会给出一个建议);还可以设置为 detailed
// "--query-driver=/usr/bin/clang++", // MacOS 上需要设定 clang 编译器的路径,homebrew 安装的clang 是 /usr/local/opt/llvm/bin/clang++
// 启用配置文件(YAML格式)项目配置文件是在项目文件夹里的“.clangd”,用户配置文件是“clangd/config.yaml”,该文件来自:Windows: %USERPROFILE%\AppData\Local || MacOS: ~/Library/Preferences/ || Others: $XDG_CONFIG_HOME, usually ~/.config
"--enable-config",
"--fallback-style=Webkit", // 默认格式化风格: 在没找到 .clang-format 文件时采用,可用的有 LLVM, Google, Chromium, Mozilla, Webkit, Microsoft, GNU
"--function-arg-placeholders=true", // 补全函数时,将会给参数提供占位符,键入后按 Tab 可以切换到下一占位符,乃至函数末
"--header-insertion-decorators", // 输入建议中,已包含头文件的项与还未包含头文件的项会以圆点加以区分
"--header-insertion=iwyu", // 插入建议时自动引入头文件 iwyu
"--include-cleaner-stdlib", // 为标准库头文件启用清理功能(不成熟!!!)
"--log=verbose", // 让 Clangd 生成更详细的日志
"--pch-storage=memory", // pch 优化的位置(Memory 或 Disk,前者会增加内存开销,但会提升性能)
"--pretty", // 输出的 JSON 文件更美观
"--ranking-model=decision_forest", // 建议的排序方案:hueristics (启发式), decision_forest (决策树)
"-j=12" // 同时开启的任务数量
// Clangd 找不到编译数据库(例如 compile_flags.json 文件)时采用的设置,缺陷是不能直接索引同一项目的不同文件,只能分析系统头文件、当前文件和include的文件
"clangd.fallbackFlags": [
"-pedantic",
"-Wall",
"-Wextra",
"-Wcast-align",
"-Wdouble-promotion",
"-Wformat=2",
"-Wimplicit-fallthrough",
"-Wmisleading-indentation",
"-Wnon-virtual-dtor",
"-Wnull-dereference",
"-Wold-style-cast",
"-Woverloaded-virtual",
"-Wpedantic",
"-Wshadow",
"-Wunused",
"-pthread",
"-fuse-ld=lld",
"-fsanitize=address",
"-fsanitize=undefined",
"-stdlib=libc++",
"-std=c++20"
"clangd.checkUpdates": true, // 自动检测 clangd 更新
"clangd.onConfigChanged": "restart", // 重启 clangd 时重载配置,具体方法: F1 + Fn 打开命令面板,然后搜索“clangd: restart"
"clangd.serverCompletionRanking": true, // 借助网上的信息排序建议
"clangd.detectExtensionConflicts": true, // 当其它拓展与 clangd 冲突时警告并建议禁用
"editor.suggest.snippetsPreventQuickSuggestions": false, // clangd的snippets有很多的跳转点,不用这个就必须手动触发Intellisense了
// [[LLDB]]
"lldb.commandCompletions": true, // LLDB 指令自动补全
"lldb.dereferencePointers": true, // LLDB 指针显示解引用内容
"lldb.evaluateForHovers": true, // LLDB 鼠标悬停在变量上时预览变量值
"lldb.launch.expressions": "native", // LLDB 监视表达式的默认类型
"lldb.showDisassembly": "never", // LLDB 不显示汇编代码
"lldb.verboseLogging": true, // LLDB 生成更详细的日志
// [[General Settings]]
"breadcrumbs.filePath": "on", // 控制是否及如何在“导航路径”视图中显示文件路径
// debug
"debug.console.acceptSuggestionOnEnter": "on", // 调试控制台中可以用 enter 接受建议
"debug.internalConsoleOptions": "neverOpen", // 从不自动打开内部调试控制台
// editor
"editor.acceptSuggestionOnEnter": "on", // 编辑器中可以用 enter 接受建议
"editor.stickyScroll.enabled": true, // 启用粘滞滚动,即显示上一级对应的代码
"editor.wordBasedSuggestionsMode": "allDocuments", // 建议所有打开文档中的字词
"editor.unicodeHighlight.ambiguousCharacters": false, // 不突出显示可能与基本 ASCII 字符混淆的字符
"editor.inlayHints.enabled": "on", // 在编辑器中显示内联提示
"editor.minimap.enabled": true, // 控制是否显示缩略图cod
"editor.formatOnType": true, // 自动格式化
"editor.renderWhitespace": "none", // 控制编辑器在空白字符上显示符号的方式
"editor.snippetSuggestions": "top", // 代码片段建议置于其他建议之上
"editor.stickyTabStops": true, // 使用空格缩进时模拟制表符的行为,可以方便对齐
"editor.tabSize": 4, // 一个制表符 = 4个空格
"editor.suggest.insertMode": "replace", // 建议的接受方式
"editor.suggest.localityBonus": true, // 控制排序时是否提高靠近光标的词语的优先级
"editor.suggest.matchOnWordStartOnly": false, // 禁用建议必须匹配开头
"editor.suggest.shareSuggestSelections": true,
"editor.suggest.showStatusBar": true, // 控制建议小部件底部的状态栏可见
"editor.suggestOnTriggerCharacters": true, // 控制在键入触发字符后是否自动显示建议
"editor.suggestSelection": "first", // 始终预先选择第一个建议
"editor.wordBasedSuggestions": true, // 控制是否根据文档中的文字提供建议列表
"editor.autoClosingOvertype": "always", // 控制编辑器应当自动改写左引号或右引号
"editor.detectIndentation": false, // 禁用自动检测文件缩进模式和缩进大小,即打开文件后自动将文件更改为 VSCode 配置的缩进格式
"editor.formatOnSave": true, // 保存自动格式化代码
"editor.formatOnPaste": true, // 粘贴自动格式化
"editor.quickSuggestionsDelay": 0, // 控制显示快速建议前的等待时间(毫秒)
"editor.inlineSuggest.enabled": true, // 在编辑器中自动显示内联建议
"editor.parameterHints.enabled": true, // 是否在输入时显示含有参数文档和类型信息的小面板
// 控制是否在键入代码时自动显示建议
"editor.quickSuggestions": {
"comments": false, // 键入注释时不允许
"other": true, // 键入其他时允许
"strings": false // 键入字符串时不允许
// explorer
"explorer.confirmDragAndDrop": false, // 移动文件时无需确认
"explorer.confirmDelete": true, // 删除文件确认
"explorer.incrementalNaming": "smart", // 粘贴同名文件时的重命名方式;smart: 在重复名称末尾智能地添加/递增数字
// files
"files.autoSave": "afterDelay", // 自动保存
"files.hotExit": "onExitAndWindowClose", // 在会话间记住未保存的文件,允许在退出编辑器时跳过保存提示 onExitAndWindowClose: 退出或窗口关闭时
// 配置排除的文件和文件夹的glob模式,文件资源管理器将根据此设置决定要显示或隐藏的文件和文件夹
"files.exclude": {
"**/.classpath": true,
"**/.factorypath": true,
"**/.project
": true,
"**/.settings": true
"files.associations": {
"*.pl": "prolog"
// notebook
"notebook.lineNumbers": "on", // 控制单元格编辑器中行号的显示
// 应该在何处显示单元格工具栏,或是否隐藏它
"notebook.cellToolbarLocation": {
"default": "right", // 默认: 右边
"jupyter-notebook": "left" // jupyter-notebook: 左边
// search
"search.showLineNumbers": true, // 显示搜索结果所在行号
"search.smartCase": true, // 当搜索词为小写时,则不区分大小写进行搜索,否则区分大小写
// 配置在搜索中排除的文件和文件夹的glob模式
"search.exclude": {
// "someFolder/": true,
// "somefile": true
// workbench
"workbench.settings.editor": "json", // 默认打开 settings.json 进行设置
"workbench.editor.historyBasedLanguageDetection": true, // 允许语言检测使用编辑器历史记录
// window
"window.restoreWindows": "all",
"window.titleBarStyle": "native",
"window.menuBarVisibility": "hidden",
// output
"output.smartScroll.enabled": true, // 输出窗口智能滚动:点击时锁定,点击最后一行时解锁
// problems
"problems.showCurrentInStatus": true, // 在状态栏显示当前问题
"problems.sortOrder": "position", // 控制问题导航的显示顺序
// other
"security.workspace.trust.untrustedFiles": "open",
"extensions.ignoreRecommendations": true,
"http.proxySupport": "on",
"[log]": {
"editor.fontSize": 16
"grunt.autoDetect": "on", // Grunt 任务自动检测
"gulp.autoDetect": "on" // Gulp 任务自动检测
}
根据
Clangd 官方文档
,Clangd 配置文件采用 YAML 格式,包括用户配置(全局配置)和项目配置。项目配置在位于该项目文件夹根目录的
.clangd
文件中,用户配置在如下路径的
clangd/config.yaml
文件中。
-
Windows:
%USERPROFILE%\AppData\Local
-
MacOS X:
~/Library/Preferences/
-
Others:
$XDG_CONFIG_HOME,通常是 ~/.config
通常情况下系统中并无此文件,可以按 F1 打开 VSCode 命令面板,输入
clangd: Open user configuration file
,即可创建并打开
config.yaml
文件,然后编辑文件内容如下以发挥 Clangd 的全部特性(项目配置同理):
Diagnostics:
ClangTidy:
Add: ["*"]
Remove:
abseil*,
fuchsia*,
llvmlib*,
zircon*,
altera*,
google-readability-todo,
readability-braces-around-statements,
hicpp-braces-around-statements,
modernize-use-trailing-return-type,
Index:
Background: Build
除了
settings.json
设置外,还可为每个项目设置 clangd tidy 规则,用于静态分析提示。只需在项目文件夹下建立
.clang-tidy
文件,文件具体内容请参考 clangd 官方文档。
3 VSCode 使用 XMake 构建系统管理 C/C++ 项目
本文旨在简单介绍 VSCode 和 XMake 的配合使用,因此不会深入讲解 XMake。关于 XMake 的使用,请参考教程和官网:
首先检查 XMake 是否安装,运行
$ xmake --help
能正常输出则说明安装成功。
使用 shell 脚本安装的 XMake 已经带有自动补全和虚拟环境功能。对于其他方式安装的 XMake,如果想要启用自动补全和虚拟环境功能,需要在安装完毕后运行
$ xmake update --integrate
安装之后,若要将xmake更新至最新版,只需使用
$ xmake update
命令行中的 XMake
使用 shell 切换至一个有足够权限的文件目录,创建 helloworld 项目:
$ xmake create helloworld
$ cd helloworld
如果已经安装了 C/C++ 的编译器(GCC/XCode/Visual Studio 等),那么可以直接在 Shell 中编译并运行该项目:
$ xmake # 编译
$ xmake run helloworld # 运行
Hello World!
VSCode 中的 XMake
除了通过命令行新建 XMake 项目,也可以用 xmake-vscode 插件提供的工程创建功能来完成 C/C++ 工程的创建:首先新建一个空工程目录,用 VSC 打开它,然后打开命令面板,输入
xmake: CreateProject
命令,会提示找不到 xmake.lua 配置文件的错误,如图:
点击
Create a new xmake project
按钮,选择项目语言(这里选择 C++)
选择 console 类型的工程
完成后,项目就创建好了,工程根目录下有
xmake.lua
配置文件。Clangd 需要读取 C/C++ 项目的编译数据库(通常是
compile_commands.json
文件)才能发挥全部功能,这里 VSC 插件自动地在
.vscode
文件夹中帮你生成该文件。
我们也可以先在终端运行
xmake config
完成 configure 过程,然后在控制面板中输入
XMake: UpdateIntellsense
,就可以在
.vscode
文件夹中找到自动生成的
compile_commands.json
。此后,如果你的项目构建过程发生变化,重复上述步骤:运行
xmake config
命令后打开控制面板输入
XMake: UpdateIntellisense
即可。
在 VSCode 下方的 Status Bar 中,有一排与 XMake 有关的操作按钮:
- 项目根目录
- 项目构建平台
- 项目构建架构
- 构建模式(debug or release)
- 构建工具链(例如在 Windows 上选择 MSVC)
- 一键构建项目
- 目标程序
- 一键运行项目 (笔者设置了运行前自动构建)
- 一键调试项目 (调试前用 debug 模式构建)
- 宏记录
- 宏回放
- ...
注意:release 模式构建的目标程序,不附带调试符号信息。因此必须用 debug 模式构建 ,使其带上调试符号信息后,才能进行调试。
不仅仅是创建工程,在安装 xmake-vscode 插件后,使用 vscode 打开一个根目录带有 xmake.lua 的工程,那 vscode 底部的 xmake 工具栏面板也会自动激活。除命令行和 VSC 底部的 XMake 工具栏按钮外,
更多功能可以在命令面板(Command Palette)中输入 xmake 使用
,例如底部工具链只有
Build
按钮而没有
rebuild
,但你可以在命令面板找到该功能。
编译完成后,如果想要清理生成的文件,可以运行
xmake clean
来清理中间文件与目标文件。
xmake clean -a
可以连同 XMake 缓存一同清除。
xmake config -c
命令仅仅清除 XMake 缓存并重新生成,不清理中间文件和目标文件。
Tips: XMake 文件发生更改后,为提升效率默认原来的缓存继续生效,可能会影响构建过程。建议在项目文件发生较大更改后,或者遇到问题的时候手动运行
xmake f -c
来清理缓存。
xmake.lua 配置文件
XMake 工程的配置文件是根目录里的 xmake.lua,在文件中添加
set_languages
语句设置语言版本,这一条语句通常放在所有 target 声明之前,全局生效,否则容易导致标准库冲突。举个栗子,你希望 Clangd 和编译器使用 C99 和 C++20 标准,只需在 xmake.lua 中增加
set_languages("c99", "c++20")
这样一行配置即可(如下图所示,你可以在一个项目里同时设置 C 和 C++ 的标准),xmake 会自动根据你对 xmake.lua 的更改生成新的 compile_commands.json 文件,Clangd 进行自动补全、静态检查依据的标准也会随之改变。
编辑 xmake.lua 文件时 xmake-vscode 插件具备自动提示和补全支持,只需要输入
add_
、
set_
等字样的文本,就会自动列举出与其相关的所有 API 供我们使用,来方便快速配置 xmake.lua。
代码格式化
VScode 快捷键
Alt + Shift + F
格式化代码,如果你对之前设置中几种代码格式化样式都不满意,在 VSCode 打开的项目根目录中添加
.clang-format
文件,编辑该文件内容即可自定义 Format 样式,该文件模板如下:
# 语言: None, Cpp, Java, JavaScript, ObjC, Proto, TableGen, TextProto
Language: Cpp
# BasedOnStyle: LLVM
# 访问说明符(public、private等)的偏移
AccessModifierOffset: -4
# 开括号(开圆括号、开尖括号、开方括号)后的对齐: Align, DontAlign, AlwaysBreak(总是在开括号后换行)
AlignAfterOpenBracket: Align
# 连续赋值时,对齐所有等号
AlignConsecutiveAssignments: false
# 连续声明时,对齐所有声明的变量名
AlignConsecutiveDeclarations: false
# 右对齐逃脱换行(使用反斜杠换行)的反斜杠
AlignEscapedNewlines: Right
# 水平对齐二元和三元表达式的操作数
AlignOperands: true
# 对齐连续的尾随的注释
AlignTrailingComments: true
# 不允许函数声明的所有参数在放在下一行
AllowAllParametersOfDeclarationOnNextLine: false
# 不允许短的块放在同一行
AllowShortBlocksOnASingleLine: true
# 允许短的case标签放在同一行
AllowShortCaseLabelsOnASingleLine: true
# 允许短的函数放在同一行: None, InlineOnly(定义在类中), Empty(空函数), Inline(定义在类中,空函数), All
AllowShortFunctionsOnASingleLine: None
# 允许短的if语句保持在同一行
AllowShortIfStatementsOnASingleLine: true
# 允许短的循环保持在同一行
AllowShortLoopsOnASingleLine: true
# 总是在返回类型后换行: None, All, TopLevel(顶级函数,不包括在类中的函数),
# AllDefinitions(所有的定义,不包括声明), TopLevelDefinitions(所有的顶级函数的定义)
AlwaysBreakAfterReturnType: None
# 总是在多行string字面量前换行
AlwaysBreakBeforeMultilineStrings: false
# 总是在template声明后换行
AlwaysBreakTemplateDeclarations: true
# false表示函数实参要么都在同一行,要么都各自一行
BinPackArguments: true
# false表示所有形参要么都在同一行,要么都各自一行
BinPackParameters: true
# 大括号换行,只有当BreakBeforeBraces设置为Custom时才有效
BraceWrapping:
# class定义后面
AfterClass: false
# 控制语句后面
AfterControlStatement: false
# enum定义后面
AfterEnum: false
# 函数定义后面
AfterFunction: false
# 命名空间定义后面
AfterNamespace: false
# struct定义后面
AfterStruct: false
# union定义后面
AfterUnion: false
# extern之后
AfterExternBlock: false
# catch之前
BeforeCatch: false
# else之前
BeforeElse: false
# 缩进大括号
IndentBraces: false
# 分离空函数
SplitEmptyFunction: false
# 分离空语句
SplitEmptyRecord: false
# 分离空命名空间
SplitEmptyNamespace: false
# 在二元运算符前换行: None(在操作符后换行), NonAssignment(在非赋值的操作符前换行), All(在操作符前换行)
BreakBeforeBinaryOperators: NonAssignment
# 在大括号前换行: Attach(始终将大括号附加到周围的上下文), Linux(除函数、命名空间和类定义,与Attach类似),
# Mozilla(除枚举、函数、记录定义,与Attach类似), Stroustrup(除函数定义、catch、else,与Attach类似),
# Allman(总是在大括号前换行), GNU(总是在大括号前换行,并对于控制语句的大括号增加额外的缩进), WebKit(在函数前换行), Custom
# 注:这里认为语句块也属于函数
BreakBeforeBraces: Custom
# 在三元运算符前换行
BreakBeforeTernaryOperators: false
# 在构造函数的初始化列表的冒号后换行
BreakConstructorInitializers: AfterColon
#BreakInheritanceList: AfterColon
BreakStringLiterals: false
# 每行字符的限制,0表示没有限制
ColumnLimit: 0
CompactNamespaces: true
# 构造函数的初始化列表要么都在同一行,要么都各自一行
ConstructorInitializerAllOnOneLineOrOnePerLine: false
# 构造函数的初始化列表的缩进宽度
ConstructorInitializerIndentWidth: 4
# 延续的行的缩进宽度
ContinuationIndentWidth: 4
# 去除C++11的列表初始化的大括号{后和}前的空格
Cpp11BracedListStyle: true
# 继承最常用的指针和引用的对齐方式
DerivePointerAlignment: false
# 固定命名空间注释
FixNamespaceComments: true
# 缩进case标签
IndentCaseLabels: false
IndentPPDirectives: None
# 缩进宽度
IndentWidth: 4
# 函数返回类型换行时,缩进函数声明或函数定义的函数名
IndentWrappedFunctionNames: false
# 保留在块开始处的空行
KeepEmptyLinesAtTheStartOfBlocks: false
# 连续空行的最大数量
MaxEmptyLinesToKeep: 1
# 命名空间的缩进: None, Inner(缩进嵌套的命名空间中的内容), All
NamespaceIndentation: None
# 指针和引用的对齐: Left, Right, Middle
PointerAlignment: Right
# 允许重新排版注释
ReflowComments: true
# 允许排序#include
SortIncludes: false
# 允许排序 using 声明
SortUsingDeclarations: false
# 在C风格类型转换后添加空格
SpaceAfterCStyleCast: false
# 在Template 关键字后面添加空格
SpaceAfterTemplateKeyword: true
# 在赋值运算符之前添加空格
SpaceBeforeAssignmentOperators: true
# SpaceBeforeCpp11BracedList: true
# SpaceBeforeCtorInitializerColon: true
# SpaceBeforeInheritanceColon: true
# 开圆括号之前添加一个空格: Never, ControlStatements, Always
SpaceBeforeParens: ControlStatements
# SpaceBeforeRangeBasedForLoopColon: true
# 在空的圆括号中添加空格
SpaceInEmptyParentheses: false
# 在尾随的评论前添加的空格数(只适用于//)
SpacesBeforeTrailingComments: 1
# 在尖括号的<后和>前添加空格
SpacesInAngles: false
# 在C风格类型转换的括号中添加空格
SpacesInCStyleCastParentheses: false
# 在容器(ObjC和JavaScript的数组和字典等)字面量中添加空格
SpacesInContainerLiterals: true
# 在圆括号的(后和)前添加空格
SpacesInParentheses: false
# 在方括号的[后和]前添加空格,lamda表达式和未指明大小的数组的声明不受影响
SpacesInSquareBrackets: false
# 标准: Cpp03, Cpp11, Auto
Standard: Cpp11