VScode 使用初步

什么是 VScode Visual Studio Code(VScode) 是一个轻量级但功能强大的源代码编辑器,可在桌面上运行,并且可用于Windows,macOS和Linux。VS code 包括一整套系统:比如内部支持 JavaScript,TypeScript 和 Node.js,能够进行多种语言扩展(如 C++,C#,Java,Python,PHP,Go),也能够进行多种运行扩展(如.NET 和 Unity)。
简单的说就是 notepad+compiler+extensions。
VScode 特点 【VScode 使用初步】之前我也没有用过 VScode,一直用的都是 VS,Qt 这样的工具,但是真的用上 VScode 之后,就发现其实如果了解一下 VScode 的使用方式的话,这个工具使用起来还是比较简单的。主要的特点有:

  • 跨平台。VScode 能够运行在 macOS,Linux,Windows操作系统上
  • 轻便灵活。VScode 在最初安装只包含了开发流程共享的基本组件,只实现了包括编辑器,文件管理,窗口管理,首选项设置, JavaScript/TypeScript 语言服务和 Node.js 调试器等基本功能,此时的 VScode 就是一个代码编辑器
  • 可扩展。VS Code 扩展可以添加对以下内容的支持:
    • 语言:C++,C#,Go,Java,Python
    • 工具:ESLint,JSHint,PowerShell
    • 调试器:Chrome,PHP XDebug。
    • 键盘映射:Vim,Sublime Text,IntelliJ,Emacs,Atom,Visual Studio,Eclipse
hello world 这一部分以实际例子来说明 VScode 的使用方法,运行平台为 Linux,编程语言为 C/C++。
前提条件
  • GCC
  • GDB
  • VScode
建立工程
VScode 不同于 VS,Qt 可以直接新建工程,在 VScode 中需要自己手动建立工程目录。其实就是新建一个文件夹,也不需要在文件夹中包含类似 CMakeLists.txt 的文件,因为这样的文件会在之后自动生成。
然后打开 VScode,利用菜单栏中的 File 打开刚刚新建的新文件夹,该文件夹就是工程目录。
代码编辑
此时先写一个简单的 hello world 程序:
// main.cpp #include using namespace std; int main() { cout<<"Hello world!"<

.vscode
默认情况下,在工程目录中会自动生成隐藏目录 .vscode,该文件中主要包含三个文件:
  • task.json(编译器构建设置)
  • launch.json(调试器设置)
  • c_cpp_properties.json(编译器路径和IntelliSense设置)
如果如果你此时没有看到该隐藏文件夹也没有关系,之后你构建上述三个文件中的任何一个文件都会生成该隐藏文件夹。
从这里来看,该隐藏文件夹有点像是 Qt 中的 .pro 文件。
task.json
既然代码已经写完了,接下来就是 build task 了。
在主菜单中,选择 Terminal > Configure Default Build Task。出现一个下拉列表,显示用于C++编译器的各种预定义构建任务。选择C/C++: g++ build active file。
这将在 .vscode 文件夹中创建 tasks.json 文件,并在编辑器中将其打开。tasks.json 文件应类似于以下 JSON:
{ // See https://go.microsoft.com/fwlink/?LinkId=733558 // for the documentation about the tasks.json format "version": "2.0.0", "tasks": [ { "type": "shell", "label": "g++ build active file", "command": "/usr/bin/g++", "args": [ "-g", "${file}", "-o", "${fileDirname}/${fileBasenameNoExtension}" ], "options": { "cwd": "/usr/bin" }, "problemMatcher": [ "$gcc" ], "group": { "kind": "build", "isDefault": true } } ] }

此时可以看到隐藏文件目录 .vscode 自动被创建。上边的参数有:
  • Command: 指定要运行的程序,在这种情况下是 g++
  • Args: 指定将传递给 g++ 的命令行参数。参数必须按照编译器期望的顺序指定
  • Label: 就是在任务列表中看到的值,可以随意命名
  • Group: "isDefault": true指定当按Ctrl+Shift+B时将运行此任务。此属性仅仅是为了便利性,如果将其设置为false,仍然可以通过terminal菜单中的Tasks: Run Build Task运行
此任务告诉 g++ 获取活动文件(${file}),对其进行编译,然后在当前目录(${fileDirname})中创建一个与活动文件同名但没有扩展名(${fileBasenameNoExtension)})的可执行文件,示例为 main。
运行程序
  1. 返回 main.cpp,任务将构建活动文件。
  2. 要运行 tasks.json 中定义的构建任务,按 Ctrl+Shift+B 或从 terminal 菜单中选择 Run Build Task。
  3. 任务启动时,会看到集成终端面板出现在源代码编辑器下方。任务完成后,终端将显示编译器的输出,指示构建成功还是失败。
  4. 使用 + 按钮创建一个新终端,这将在 WSL 上下文中运行一个 bash 终端,并以当前文件夹作为工作目录。
  5. 此时可以在终端运行 main。
launch.json
此时只是构建了任务,生成了可执行程序,但是想要调试的话还需要用到 launch.json 来设置调试器的相关内容。
  • 在菜单栏中选择 Run > Add Configuration...,然后选择 C++ (GDB/LLDB)
  • 然后将出现各种预定义调试配置的下拉列表。选择 g++ build and debug active file
  • VS Code 创建 launch.json 文件,在编辑器中打开为:
{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "g++ - Build and debug active file", "type": "cppdbg", "request": "launch", "program": "${fileDirname}/${fileBasenameNoExtension}", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "MIMode": "gdb", "setupCommands": [ { "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true } ], "preLaunchTask": "g++ build active file", "miDebuggerPath": "/usr/bin/gdb" } ] }

上边的参数中:
  • Program: 指定要调试的程序。这里被设置为活动文件文件夹${fileDirname}和没有扩展名的活动文件名${fileBasenameNoExtension},如果helloworld.cpp是活动文件,则为helloworld
  • 默认情况下,C++扩展不会在源代码中添加任何断点,因此stopAtEntry值设置为false。stopAtEntry值为true时,调试器启动调试时遇到main方法停止
调试代码
  • 返回 main.cpp,使其成为活动文件
  • 按 F5 或从主菜单中选择 Run > Start Debugging。此时用户界面会发生一些更改:
    • 集成终端出现在源代码编辑器的底部。在 Debug Output 选项卡中,可以看到指示调试器已启动并正在运行
    • 编辑器突出显示main方法中的第一条语句。这是 C++ 扩展自动设置的断点
    • 左侧的 run 视图显示调试信息
    • 在代码编辑器的顶部,将显示一个调试控制面板
调试控制面板的使用方法与其它 IDE 基本相同。
WATCH
在调试的时候,左侧边栏会出现一个 WATCH 的栏目,利用 WATCH 可以实现对变量跟踪:
  • 在 WATCH 窗口中,单击加号,然后在文本框中键入 var(变量名),此时可以逐步调试程序,可以看出该变量一直显示在 WATCH
  • 在断点开启时,要快速查看任何变量的值,可以使用鼠标指针悬停在其上
c_cpp_properties.json
编程中通常会使用到一些第三方库,如果要用到第三方库的头文件的话,就需要在该文件中添加头文件目录,不过此时添加的头文件目录只是为了编程更加方法,实现智能感知,而并没有真正的链接。
真正的链接需要在 task.json 文件中设置参数,才能够正常编译。
可以通过从 Command Palette (Ctrl+Shift+P) 运行命令 C/C++: Edit Configurations (UI) 来查看 C/C++ 配置 UI。
  • 当在此处进行更改时,VS Code会将更改写入.vscode文件夹中的c_cpp_properties.json文件中。
  • 仅当程序包含不在工作空间或标准库路径中的头文件时,才需要修改includepath设置。
外部库链接的实例
当需要进行外部库链接时,至少需要在 tasks.json 中进行头文件包含和外部库链接,如果需要使用代码提示等智能感知功能的话,还需要修改 c_cpp_properties.json 文件。
以下用一个 C 语言的实例来简单说明需要进行外部库链接的情况(这里的静态库是利用这篇文章中的文件生成的):
// main.c #include #include int main() { printf("insert a node from tail\n"); ND *head = createListTail(); //printf("insert a node from head\n"); //ND *head = createListHead(); printf("traval all node using next\n"); travalListNext(head); printf("insert a node\n"); insertList(head,10); travalListNext(head); //printf("traval all node using pre\n"); //travalListPre(head); printf("calculate the length of list\n"); int length = lenList(head); printf("The length of list is %d\n",length); printf("search a node in list from single direction\n"); ND *pp = searchNodeSdir(head,10); printf("The search node is %d\n",pp->data); //printf("search a node in list from both direction\n"); //pp = searchNodeBdir(head,10); //printf("The search node is %d\n",pp->data); printf("delete a node\n"); deleteNode(pp); travalListNext(head); printf("sort list by swap data\n"); sortSwapData(head,9); travalListNext(head); //printf("sort list by swap pointer\n"); //sortSwapPointer(head,9); //travalListNext(head); printf("destroy list\n"); destroyList(head); }

// tasks.json { "version": "2.0.0", "tasks": [ { "type": "shell", "label": "gcc build active file", "command": "/usr/bin/gcc", "args": [ "-g", "${file}", "-I", "~/libr", "-L", "~/libr", "-l", "node", "-o", "${fileDirname}/${fileBasenameNoExtension}" ], "options": { "cwd": "/usr/bin" }, "problemMatcher": [ "$gcc" ], "group": { "kind": "build", "isDefault": true } } ] }

// launch.json { // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "gcc - Build and debug active file", "type": "cppdbg", "request": "launch", "program": "${fileDirname}/${fileBasenameNoExtension}", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "MIMode": "gdb", "setupCommands": [ { "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true } ], "preLaunchTask": "gcc build active file", "miDebuggerPath": "/usr/bin/gdb" } ] }

// c_cpp_properties.json { "configurations": [ { "name": "Linux", "includePath": [ "${workspaceFolder}/**", "~/libr/**" ], "defines": [], "compilerPath": "/usr/bin/gcc", "cStandard": "c11", "cppStandard": "c++17", "intelliSenseMode": "clang-x64" } ], "version": 4 }

  • 该工程需要的编译器是 gcc,而不是 g++
  • 如果在 c_cpp_properties.json 文件中没有为 includePath 参数添加头文件,则在 main.c 文件中的 #include 会出现下划线,也就是说编辑器找不到该函数,但是实际是能够编译的。
  • 在 tasks.json 文件中添加了一些参数,如 -I,-L,-l 等,这些参数包含了头文件和外部链接库。
  • 不需要调试的话,可以不用添加 launch.json 文件
一个常见错误 当开始构建或调试时,xxx.cpp 不是活动文件时,最常见的错误原因(如 undefined _main 或 attempting to link with file built for unknown-unsupported file format 等)。这是因为编译器正在尝试编译不是源代码的内容(如 launch.json,tasks.json 或 c_cpp_properties.json 文件)。
因此,运行任务时一定要保证当前活动文件为包含 main 函数的文件。

    推荐阅读