用 visual studio code 开发 C++ 程序

2019/7/22,由于下面地址指向的官网页面内容已经被重新排版和删减,因此中文翻译跟英文原文已经不太对得上。

翻译自:https://code.visualstudio.com/docs/languages/cpp
译者受水平所限,如有错漏,敬请包涵

2018/12

这个 Microsoft C/C++ extension 插件为 Visual Studio Code 提供了C/C++ 的支持,这个插件使 Visual Studio Code 可以在 Windows、Linux、和 macOS 上跨平台开发C和C++程序。这个插件目前尚在预览版阶段,开发这个插件的目标是让 VS Code 编辑、导航以及调试C和C++程序。
用 visual studio code 开发 C++ 程序_第1张图片
如果你只是想要一个轻量级的工具去编辑你的C++文件,Visual Studio Code 就是一个很好的选择。但如果你想在你的VC++项目上或者是在Windows上做调试时有尽可能好的体验,则建议您使用像 Visual Studio Community 这一类 Visual Studio IDE 级别的开发环境。

如果你对 Microsoft C/C++ 插件有问题或者有改进的意见,请到 issues and suggestions on GitHub 上进行提问或提交建议。如果想提供一些对于插件的反馈,请用这个 quick survey 提供反馈从而帮助我们使这个插件变得更好用。

开始使用插件

安装 Microsoft C/C++ 插件的步骤:

  • 打开 VS Code
  • 点击在侧边栏的插件浏览按钮(正方形那个)
  • 查询 C++
  • 点击 Install,然后点击 Reload

用 visual studio code 开发 C++ 程序_第2张图片
C/C++ 插件安装完成后,打开(通过 Open Folder)你的包含了C/C++源代码的文件夹, VS Code会把几个配置文件保存到一个名字叫 .vscode 的子文件夹(译者按:如果打开的是一个空的文件夹,.vscode 文件夹不会被自动创建。通过创建下文提及的 tasks.json 文件,.vscode 文件夹会自动先被创建的)。

注意:本 C/C++插件 不自带C++的编译器或者调试器。你需要自行安装这些工具,除非你的电脑已经安装了这些工具。比较出名的 C++编辑器有这些:Windows 的 mingw-w64,macOS 的 XCode 里自带的 Clang 编辑器,还有 Linux 的 GCC。请确保你的编译器记录在你的平台的环境变量里,这样本插件才能找到你的编译器。本 C/C++插件同时也支持 Windows Subsystem for Linux。

配置智能提示

本插件会尝试根据你的C++编译器来决定你的源码目录的基本配置信息。如果因为某些原因,那个配置信息没有完成,你可以自行初始化一个名为 c_cpp_properties.json 的文件,初始化该文件的方法是这样的:通过 Command Palette(Ctrl+Shift+P) 运行 C/Cpp: Edit configurations 命令,并添加之前缺失的信息。

如果一个需要 #include 的文件或者此文件的依赖文件找不到,你也可以通过点击位于 include声明 下方的红色波浪线来查看关于“如何升级你的配置”的建议。
用 visual studio code 开发 C++ 程序_第3张图片
此举会生成一个名为 c_cpp_properties.json 的文件,这个文件允许你添加额外的路径和定义,从而使代码的“导航”和“自动完成”功能生效。

在下面的配置中,你可以看到 MinGW C++编译器 已经被设置为 Windows 的默认编译器。本插件会利用这个配置的信息来决定系统的“包含路径和定义”(system include path and defines),因此这些“包含路径和定义”无需被添加到 c_cpp_properties.json。
(译者按:不同版本的C++插件,生成的c_cpp_properties.json可能有区别,不一定跟下面一模一样。但最关键的还是compilerPath这一项要根据自己电脑的实际安装位置设置好,一旦设置好,再敲代码,智能提示就能出现。)

{
    "name": "Win32",
    "includePath": [
        "${workspaceFolder}"
    ],
    "defines": [
        "_DEBUG",
        "UNICODE"
    ],
    "compilerPath": "C:\\mingw-w64\\bin\\gcc.exe",
    "intelliSenseMode": "clang-x64",
    "browse": {
        "path": [
            "${workspaceFolder}"
        ],
        "limitSymbolsToIncludedHeaders": true,
        "databaseFilename": ""
    }
}

编译代码

如果你想通过 VS Code 来编译你的 app,你需要建立一个叫 tasks.json 的文件:

  • 打开命令行(Ctrl+Shift+P)
  • 选择 Tasks: Configure Task 命令,点击 Create tasks.json file from templates,然后你会看到一个“任务运行器模版”(task runner templates)列表。
  • 选择 Others 从而创建一个运行外部命令的任务
  • 如下,修改 command 的内容,改为你用来编译你的应用程序的命令行表达式(例如 g++)
  • 添加任意需要的 args (例如 -g 用以创建以调试为目的的程序
  • 你可以修改 label 的内容,使之更具语义化

你现在应该可以在你的“工作空间”里的名叫 .vscode 的文件夹里,看到一个名叫 tasks.json 的文件,内容大致如下:

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build hello world",
            "type": "shell",
            "command": "g++",
            "args": [
                "-g", "helloworld.cpp"
            ]
        }
    ]
}

如果你希望能够使用 Tasks: Run Build Task (Ctrl+Shift+B) 指令来编译你的应用程序,你可以如下一样,添加一个叫 “group” 的组(译者按:如果使用了 Tasks: Run Build Task (Ctrl+Shift+B),但 tasks.json 里没有如下添加 “group” 组,工具也会提示是否需要自动为我们在 tasks.json 添加 “group” 组)。

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build hello world",
            "type": "shell",
            "command": "g++",
            "args": [
                "-g", "helloworld.cpp"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
}

(译者按:如果如上设置的话,但 g++ 不存在,在使用 Tasks: Run Build Task (Ctrl+Shift+B) 指令进行编译时,当然也会报错的)

想要更多的关于“任务”的信息,请见 Integrate with External Tools via Tasks。

调试代码

要能够调试代码,你需要生成一个名叫 launch.json 的文件

  • 通过点击在侧边栏的调试(Debug)按钮,导航到调试界面
  • 在调试界面,点击配置(Configure )按钮
  • 从弹出来的 环境选择(Select Environment) 下拉列表中,选择 C++ (GDB/LLDB) (使用 GDB 或者 LLDB)或者 C++ (Windows) (使用 Visual Studio Windows 调试器) 。这个操作会生成一个名叫 launch.json 的文件,用来编辑以下两个配置:
    • C++ Launch 在你开始调试时,用于定义你的应用程序的属性
    • C++ Attach 在附加到一个已经运行的程序时,定义属性
  • 根据你正在调试的程序的路径,修改 program 属性值
  • 如果你希望你的应用程序在你开始调试时先编译,加一个 preLaunchTask 属性,该属性的值是你写在 tasks.json 文件里的“编译任务”(build task)的名字(在上面出现过的名为"build hello world"的例子)。

下面是一个用了 MinGW GDB 的例子:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/a.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": true,
            "MIMode": "gdb",
            "miDebuggerPath": "C:\\mingw\\bin\\gdb.exe",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "build hello world"
        }
    ]
}

详见 Configuring launch.json for C/C++ debugging
如果你想要用 Windows 上的 GDB 进行调试,详见 Windows Debugging with GDB

(译者按:如果运行调试时,出现类似这样的报错:“Unable to start debugging. Launch options string provided by the project system is invalid. “”(十六进制值 0x08)是无效的字符。 第 6 行,位置 95。”,请检查你的 gdb.exe 的路径的反斜杠是否都加好了,参考:https://github.com/Microsoft/vscode-cpptools/issues/2405)

编辑代码

代码的格式化
本插件支持源码的格式化,这是因为插件内置了 clang-format

你可以通过右键菜单里的 Format Document (Shift+Alt+F) 命令格式化整个文件,或者通过 Format Selection (Ctrl+K Ctrl+F) 命令只格式化当前选中的段落。你也可以通过下面的设置来配置自动格式化功能:

  • editor.formatOnSave - 在你保存文件的时候格式化。
  • editor.formatOnType - 在你打字的时候格式化(通过 “;” 来触发)。

clang-format 的风格默认地设置为"file",这意味着它会在你的工作空间(workspace)找寻一个名为.clang-format的文件。如果 .clang-format 文件被找到了,则将会根据文件里的设定进行格式化。如果 .clang-format 文件没有被找到,则会根据默认的风格(由 C_Cpp.clang_format_fallbackStyle 来定义) 来格式化。目前,默认的格式化风格是 “Visual Studio”,此风格与 Visual Studio 的代码格式化风格近似。

这个 “Visual Studio” 的 c语言格式风格还不是一个官方的 OOTB c语言格式风格,但其隐含了下面的c语言格式设定:

UseTab: (VS Code current setting)
IndentWidth: (VS Code current setting)
BreakBeforeBraces: AllMan
AllowShortIfStatementsOnASingleLine: false
IndentCaseLabels: false
ColumnLimit: 0

如果你希望使用与本插件自带的c语言格式化风格不同版本的风格设置,你可以修改 C_Cpp.clang_format_path 设置的值,使其指向“c语言格式器”的路径。
例如,下面是在 Windows 平台的某种设置:

"C_Cpp.clang_format_path": "C:\\Program Files (x86)\\LLVM\\bin\\clang-format.exe"

自动完成功能
自动完成功能是由跟 Visual Studio 相同的引擎提供的。你可以得到相关性最高的代码自动完成的提示,前提是你的工作空间(workspace)已经设置了所有必需的路径和定义(参见上面提及的“配置智能提示”小节)

代码导航

本 C/C++ 插件提供的“源代码导航特性”(code navigation features),是帮助你阅读和检索你的源码的有效工具。专门保存“关键字信息”(symbol information)的离线数据库里,保存着跟你的源码有关的“关键字”(tags),这些“关键字”提供了上述的“源代码导航特性”。只要本 C/C++ 插件已被安装,那么当一个包含有 C++ 源码的文件夹被加载到 VS Code, 这个离线数据库就会被初始化。当“关键字解释器”(tag-parser)工作的时候,这个离线数据库的图标就会出现在“处于活动状态的的配置的名字”(active configuration name)旁边(在下图是"Win32"的旁边)。
在这里插入图片描述
当这个图标出现,意味着跟源码有关的“关键字信息”已经记录在离线数据库中。

指定额外的目录以求更好的关键字支持
为了提供更好的体验,本 C/C++ 插件需要知道哪里可以找到你的代码所引用的头文件。默认地,本插件会查找当前源码文件夹,以及它的子文件夹,还有一些平台指定的路径。如果一个被引用的头文件没有找到,VS Code 会在每一个引用到这个头文件的#include指示符的下方显示一个绿色的波浪线。为了使一些其它的“包含目录”(include directories)能被查找到,把你的鼠标指向任意的下方有绿色波浪线的#include指示符,然后等出现“电灯泡”图标的时候点击它。这个操作会打开 c_cpp_properties.json 文件用于编辑;在这时候你可以通过为 ‘browse.path’ 属性添加更多的文件夹路径,从而为各个平台指定额外的“包含目录”。

查找标记
你可以通过在当前文件或者工作空间中搜索“关键字”(symbols ),从而更快地浏览你的代码。

如果想要在当前文件中搜索一个“关键字”,按快捷键 Ctrl+Shift+O,然后输入你希望查找的“关键字”。在你输入的过程中,一个下拉的提示列表会显示出来,列表里包含了符合你的输入的“联想词”。从列表中选择符合你需求的关键字,从而导航到它所在的位置。
用 visual studio code 开发 C++ 程序_第4张图片
如果需要在当前工作目录查找一个关键字,按 Ctrl+T,然后输入关键字。一个下拉列表会显示出来,里面有与你输入有关的“联想词”。如果你选择了一个“联想词”,而改词所在的文档并没有打开,那么该文档会先被打开,然后再定位到改词所在的位置。
用 visual studio code 开发 C++ 程序_第5张图片
你还可以通过“命令行”(Command Palette)来搜索关键字。使用“快速打开”(Ctrl+P),然后输入“@”开头的指令来搜索当前文件,输入“#”开头的指令来搜索当前工作空间。Ctrl+Shift+O 和 Ctrl+T其实就是 ‘@’ 和 ‘#’ 指令的快捷方式。效果是一样的。

快速查看定义
你可以通过“快速查看定义”特性,方便地查看一个关键字的定义。这个特性,会在一个提示框内显示与当前关键字的定义有关的几行代码,这样你就可以不用跳转到定义处,即可了解到关键字的一些定义信息。

为了快速查看一个关键字的定义,方法是把你的鼠标放到关键字上面,然后按 Alt+F12。另外,你也可以通过右键菜单使用“快速查看定义”。
用 visual studio code 开发 C++ 程序_第6张图片
目前来说,本 C/C++插件 不会在关键字的定义出现冲突时,自动帮忙转化代码用于区分。这些冲突的定义指关键字在不同的环境重复定义,这些所谓不同的环境包括重载的方法,不同的类以及这些类的构造方法,等等。当这些冲突的定义发生了以后,所有冲突会在提示窗的右边列举出来,同时左边是当前所选中的源代码。

通过打开的提示窗口,你可以浏览所列举出来的冲突,找到你感兴趣的。如果你想要定位到某一项的定义,那你只需要双击你感兴趣的那一项,或者也可以双击提示框左边的源码。

到定义处
你也可以通过“到定义处”的特性,快速地查找并定位到某个关键字。
如果想要去到一个关键字的定义处,把你的鼠标放到关键字上,然后按 F12。另外,你也可以在右键菜单选择 Go to Definition 达到同样的效果。如果这个关键字只有一处定义,你会直接被定位到它所在的定义处,否则冲突的定义会如上文所说一样,显示在一个提示框内,然后你可以选中你希望的定义,跳去查看。

调试

在你已经按上文提及,设置好你的调试环境的基本设置后,你可以知道更多的关于调试方面的细节。

VS Code 支持下列的 C/C++调试器,当然这取决于你正在试用的系统:

  • Linux: GDB
  • macOS: LLDB 或者 GDB
  • Windows: Visual Studio Windows 自带的调试器 或者 GDB (使用 Cygwin 或者 MinGW 的情况下)

使用 GDB 的 Windows 调试器
你可以用 VS Code 来调试 Cygwin 或者 MinGW 创建的 Windows 应用程序。为了使用 Cygwin 或者 MinGW 的调试特性,调试器的所在路径,必须手动地在“启动设置”( launch.json )里设置好。为了调试 Cygwin 或者 MinGW 的应用程序,在“启动设置”添加 miDebuggerPath 属性,并且把值设置成相关的 Cygwin 或者 MinGW 环境的 gdb.exe 路径。
例如:
“miDebuggerPath”: “c:\mingw\bin\gdb.exe”
Cygwin 或者 MinGW 既支持“附加”的调试操作也支持“直接启动”的调试操作。

条件性断点
条件性断点使你可以让代码的运行,仅在某条件成立时,中断在特定的某行代码。为了设置一个条件性断点,在某个已有的断点上右键,并选择 Edit Breakpoin。上述操作会打开一个小提示框,用于输入在调试中允许断点被命中的条件。
用 visual studio code 开发 C++ 程序_第7张图片
在编辑器中,条件性断点的符号是一个里面有一个黑色等号的断点符号。把鼠标移到条件性断点符号上面,会显示断点命中的条件。

函数断点
函数断点使你可以在一个函数开始执行之前中断代码的运行,而不是在特定的一行代码上中断。为了设置一个函数断点,在“调试”(Debug )窗格的“断点”(Breakpoints )区域右键,然后选择“添加函数断点”(Add Function Breakpoint),然后输入你想要中断运行的函数的名字。

表达式计算
VS Code 支持表达式计算

  • 你可以在“调试”(Debug )窗格的“查看”(Watch)区域输入一个表达式,这样,这个表达式在每逢断点命中时,都会被计算。
  • 你可以在“调试命令行”(Debug Console)输入一个表达式,那么这样这个表达式只会被计算一次
  • 你可以在某断点命中时,计算你的代码里原有的任意表达式

注意的是,写在“查看”(Watch)区域的表达式作用于正在被调试的应用程序;一个表达式一但修改了一个变量的值,那么这个修改是对于整个程序的运行过程而言的。

多线程调试
本 C/C++插件 具备多线程程序的调试能力。所有的线程以及他们的调用堆栈都会显示在 Call Stack 区域。
用 visual studio code 开发 C++ 程序_第8张图片

Memory Dump 调试
本 C/C++插件 也有调试 Memory Dump 的能力。为了调试 memory dump,打开你的 launch.json 文件,在 C++ Launch 的设置上添加属性 coreDumpPath(对于 GDB 或者 LLDB 而言) 或者 dumpPath(对于 Visual Studio 自带的调试器而言 ) ,把属性的值设置为包含 memory dump 的路径的字符串。这样的做法,即使在64位机器上调试32位的程序也能起作用。

附加的信息
如果有调试器可以查找的关键字文档的附加目录(例如,对于 Visual Studio 而言的 .pdb 文档),这些目录可以通过添加属性 additionalSOLibSearchPath(对于 GDB 或者 LLDB 而言) 或者 symbolSearchPath(对于 Visual Studio 自带的调试器而言 )。
例如:

"additionalSOLibSearchPath":"/path/to/symbols;/another/path/to/symbols"

或者

"symbolSearchPath":"C:\\path\\to\\symbols;C:\\another\\path\\to\\symbols"

定位源代码
如果希望源代码跟编译路径不在同一个地方,那么源码的位置可以另外指定。只要在 sourceFileMap 区域添加几个键值对就可以实现了。在这个列表中,第一个吻合的键值对会被使用。
例如:

"sourceFileMap": {
    "/build/gcc-4.8-fNUjSI/gcc-4.8-4.8.4/build/i686-linux-gnu/libstdc++-v3/include/i686-linux-gnu": "/usr/include/i686-linux-gnu/c++/4.8",
    "/build/gcc-4.8-fNUjSI/gcc-4.8-4.8.4/build/i686-linux-gnu/libstdc++-v3/include": "/usr/include/c++/4.8"
}

GDB, LLDB 和 MI 命令 (GDB/LLDB)
对于 C++ (GDB/LLDB) 的调试环境来说,你可以通过调试控制台并附加 -exec命令 来运行 GDB, LLDB 和 MI 命令,但需要注意的是,在调试控制台直接运行命令,这是没有测试过的并且有可能在某些情况下导致 VS Code 崩溃。

其它的一些调试特性

  • 无条件断点
  • “观看”(Watch)窗口
  • 调用堆栈
  • 逐步调试
    关于使用 VS Code 调试的更多信息,请见这篇介绍 debugging in VS Code 。

已知的限制

关键字和代码导航
对于所有平台而言:

  • 因为本插件不会分析函数内部,“快速查看定义”以及“跳转到定义处”这两个功能,对于定义在函数内部的关键字而言,是不起作用的。

调试
Windows:

  • Cygwin 上的 GDB 和 MinGW 不能够中断一个正在运行的进程。如果想在一个程序正在运行的时候设置一个断点,或者想要暂停一个正在被调试的程序,在程序的终端按 Ctrl-C。
  • Cygwin 上的 GDB 不能打开 core dumps。

Linux:

  • GDB 需要更高权限才能附加到一个进程。当使用“附加到进程”(attach to process)功能时,你需要先输入你的用户密码,然后调试功能才能顺利开始。

macOS:

  • LLDB:
    • 当使用 LLDB 进行调试时,当处于“中断模式”(break mode)的时候,如果终端窗口关闭了,调试不会自动结束的。调试只有在按了“停止”(Stop)按钮的时候,才会被终止。
    • 当调试结束的时候,终端窗口也不会自动关闭。
  • GDB:
    • 附加的手动安装步骤必需完成后,才能在 macOS 上使用 GDB。详情请见 README 里的 Manual Installation of GDB for OS X 小节。
    • 当利用 GDB 附加到进程时,正在被调试的程序是不能被中止的。GDB 只会绑定那些在程序还没有运行就已经加上的断点(要么在附加到程序之前,或者当程序处于一个停止的状态)。这是由于 GDB 的一个漏洞导致的(a bug in GDB)。
    • 当用 GDB 进行调试的时候 Core dumps 无法被加载,因为 GDB 不支持 macOS 所使用的 Core dumps 格式(does not support the core dump format used in macOS)。
    • 当使用 GDB 附加到进程的时候,break-all 将会结束进程。

后续步骤

更多的内容请见:

  • Basic Editing - 了解 VS Code 编辑器的厉害之处
  • Code Navigation - 如何更快地浏览你的源代码
  • Tasks - 如何使用“任务”(tasks)去构建你的项目
  • Debugging - 学习如何使用“调试器”(debugger)来调试你的项目

常见问题

我的项目无法加载
VS Code 当前不支持 C++ 的项目文件,但会把你选择的一个目录作为你的项目的“工作空间”(workspace)。在目录里的源代码文件和它的子目录,都是工作空间的一部分。

我该如何构建以及运行我的项目?
你可以通过 VS Code 配置一些“任务”(tasks)来构建你的应用程序。VS Code 也原生地支持 MSBuild、CSC 以及 XBuild 的输出。更多的信息请见 Tasks。
如果你有任何疑问,或者对某个主题感兴趣,请在 GitHub 上起草一个问题。

你可能感兴趣的:(Visual,Studio,Code)