VSCode开发C、C++
环境准备
GCC、MinGW、Cygwin中的开发工具都可以。
如果是使用cygwin中的gcc,那么对应的包有:
安装好以下工具并且确保它们都在环境变量PATH
中:
- gcc-core
- gcc-g++
- make
- gdb
- binutils 包含 readelf nm 等 工具(注意:只选择devel版本即可,正常情况下,我们一般需要携带调试信息的版本)
安装完成后可以测试一下如何查看so文件,查看一个完整的so文件的Section命令:
readelf -S libshella-2.8.so
VSCode插件安装
参考官方文档安装C/C++插件:
- https://code.visualstudio.com/docs/editor/variables-reference
- https://code.visualstudio.com/docs/cpp/config-mingw
例子
简单例子
简单地处理两种情况:
- 编译并调试单个文件
- 多个文件编译链接并调试
编译并运行单个文件
配置文件.vscode/tasks.json
中可以定义多个任务。
可以在里面定义一个任务,直接调用gcc编译我们正在编辑的文件:
{ "label": "build: sample-1", "command": "gcc", //c++为g++, c为gcc "args": [ "-g", "${file}", "-o", "${file}.exe" ], // 命令参数 "options": { "cwd": "${workspaceFolder}" }, "problemMatcher": { "owner": "cpp", "fileLocation": [ "relative", "${workspaceRoot}" ], "pattern": { "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$", "file": 1, "line": 2, "column": 3, "severity": 4, "message": 5 } } }
注意这里编译参数中:
-
-g
表示带调度标记 -
${file}
表示当前正在编辑的那个源代码文件。
配置文件.vscode/launch.json
中可以定义多个运行程序的启动配置。
可以在里面定义一个调用gdb的启动配置:
{ "name": "debug: sample-1", // 配置名称,将会在启动配置的下拉菜单中显示 "type": "cppdbg", // 配置类型,这里只能为cppdbg "request": "launch", // 请求配置类型,可以为launch(启动)或attach(附加) //"launchOptionType": "Local", // 调试器启动类型,这里只能为Local "targetArchitecture": "x64", // 生成目标架构,一般为x86或x64,可以为x86, arm, arm64, mips, x64, amd64, x86_64 "program": "${file}.exe", // 将要进行调试的程序的路径 "miDebuggerPath":"c:/cygwin64/bin/gdb.exe", // miDebugger的路径,注意这里要与cygwin/MinGw的路径对应 "args": ["blackkitty", "1221", "# #"], // 程序调试时传递给程序的命令行参数,一般设为空即可 "stopAtEntry": true, // 设为true时程序将暂停在程序入口处,一般设置为false "cwd": "${workspaceRoot}", // 调试程序时的工作目录,一般为${workspaceRoot}即代码所在目录 "externalConsole": true, // 调试时是否显示控制台窗口,一般设置为true显示控制台 "preLaunchTask": "build: sample-1" // 调试会话开始前执行的任务,编译 }
-
program
指定为${file}.exe
,正好是当前编辑的文件名加上后缀。 -
prelaunchTask
关联到了之前定义的编译任务。这样在VSCode的「运行视图」 中就可以编译并调试当前程序了。
如果源代码是C++代码,只要在编译任务中把编译命令替换成g++
就可以了。
一般C和C++代码都可以用g++命令编译,而gcc命令一般只用来编译c代码。
编译连接并调试
配置文件.vscode/tasks.json
中的任务要调用make
命令:
{ "label": "build: sample-3", "command": "make", "args": [ "all" ], // 编译命令参数 "options": { "cwd": "${workspaceFolder}" }, "problemMatcher": ["$gcc", { "owner": "cpp", "fileLocation": [ "relative", "${workspaceRoot}" ], "pattern": { "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$", "file": 1, "line": 2, "column": 3, "severity": 4, "message": 5 } }] }
配置文件.vscode/launch.json
中要指定最终生成的可执行文件,
而不是当前编辑文件的文件名加上后缀:
{ "name": "debug: sample-3", // 配置名称,将会在启动配置的下拉菜单中显示 "type": "cppdbg", // 配置类型,这里只能为cppdbg "request": "launch", // 请求配置类型,可以为launch(启动)或attach(附加) //"launchOptionType": "Local", // 调试器启动类型,这里只能为Local "targetArchitecture": "x64", // 生成目标架构,一般为x86或x64,可以为x86, arm, arm64, mips, x64, amd64, x86_64 "program": "${workspaceRoot}/out/hello.exe",// 将要进行调试的程序的路径 "miDebuggerPath":"c:/cygwin64/bin/gdb.exe", // miDebugger的路径,注意这里要与cygwin/MinGw的路径对应 "args": ["blackkitty", "1221", "# #"], // 程序调试时传递给程序的命令行参数,一般设为空即可 "stopAtEntry": true, // 设为true时程序将暂停在程序入口处,一般设置为false "cwd": "${workspaceRoot}", // 调试程序时的工作目录,一般为${workspaceRoot}即代码所在目录 "externalConsole": true, // 调试时是否显示控制台窗口,一般设置为true显示控制台 "preLaunchTask": "build: sample-3" // 调试会话开始前执行的任务,一般为编译程序,c++为g++, c为gcc }
全部代码
#include <stdio.h> int main() { for (int i = 0; i < 10; i++) { printf("%d\n", i); } return 0; }
#include <iostream> #include <vector> #include <string> using namespace std; int main() { vector<string> msg {"Hello", "C++", "World", "from", "VS Code", "and the C++ extension!"}; for (const string& word : msg) { cout << word << " "; } cout << endl; return 0; }
void print_hello(); int factorial(int n);
#include "../functions.h" int factorial(int n){ if (n!=1) return n * factorial(n-1); else return 1; }
#include <iostream> void print_hello() { std::cout << "hello world" << std::endl; }
# include <iostream> # include "functions.h" int main() { print_hello(); std::cout << "this is main" << std::endl; std::cout << "The factorial of 5 is " << factorial(5) << std::endl; return 0; }
CC = g++ SRC_DIR = src OUT_DIR = out rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)) OBJS = $(patsubst $(SRC_DIR)/%.cpp, $(OUT_DIR)/%.o, $(call rwildcard,src/,*.cpp)) CFLAGS = -c -Wall -g LFLAGS = -Wall CYGLIB = -static-libgcc -static-libstdc++ all: $(OUT_DIR)/hello $(OUT_DIR)/hello: $(OBJS) $(CC) $(LFLAGS) $(CYGLIB) $^ -o $@ $(OBJS): $(OUT_DIR)/%.o : $(SRC_DIR)/%.cpp @mkdir -p $(@D) $(CC) $(CFLAGS) $(CYGLIB) $< -o $@ clean: rm -rf $(OUT_DIR)/* $(OUT_DIR)/hello
{ "version": "2.0.0", "tasks": [ { "label": "build: sample-1", "command": "gcc", //c++为g++, c为gcc "args": [ "-g", "${file}", "-o", "${file}.exe" ], // 编译命令参数 "options": { "cwd": "${workspaceFolder}" }, "problemMatcher": { "owner": "cpp", "fileLocation": [ "relative", "${workspaceRoot}" ], "pattern": { "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$", "file": 1, "line": 2, "column": 3, "severity": 4, "message": 5 } } }, { "label": "build: sample-2", "command": "g++", //c++为g++, c为gcc "args": [ "-g", "${file}", "-o", "${file}.exe" ], // 编译命令参数 "options": { "cwd": "${workspaceFolder}" }, "problemMatcher": ["$gcc", { "owner": "cpp", "fileLocation": [ "relative", "${workspaceRoot}" ], "pattern": { "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$", "file": 1, "line": 2, "column": 3, "severity": 4, "message": 5 } }] }, { "label": "build: sample-3", "command": "make", "args": [ "all" ], // 编译命令参数 "options": { "cwd": "${workspaceFolder}" }, "problemMatcher": ["$gcc", { "owner": "cpp", "fileLocation": [ "relative", "${workspaceRoot}" ], "pattern": { "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$", "file": 1, "line": 2, "column": 3, "severity": 4, "message": 5 } }] } ] }
{ "version": "0.2.0", "configurations": [ { "name": "debug: sample-1", // 配置名称,将会在启动配置的下拉菜单中显示 "type": "cppdbg", // 配置类型,这里只能为cppdbg "request": "launch", // 请求配置类型,可以为launch(启动)或attach(附加) //"launchOptionType": "Local", // 调试器启动类型,这里只能为Local "targetArchitecture": "x64", // 生成目标架构,一般为x86或x64,可以为x86, arm, arm64, mips, x64, amd64, x86_64 "program": "${file}.exe", // 将要进行调试的程序的路径 "miDebuggerPath":"c:/cygwin64/bin/gdb.exe", // miDebugger的路径,注意这里要与cygwin/MinGw的路径对应 "args": ["blackkitty", "1221", "# #"], // 程序调试时传递给程序的命令行参数,一般设为空即可 "stopAtEntry": true, // 设为true时程序将暂停在程序入口处,一般设置为false "cwd": "${workspaceRoot}", // 调试程序时的工作目录,一般为${workspaceRoot}即代码所在目录 "externalConsole": true, // 调试时是否显示控制台窗口,一般设置为true显示控制台 "preLaunchTask": "build: sample-1" // 调试会话开始前执行的任务,一般为编译程序,c++为g++, c为gcc }, { "name": "debug: sample-2", // 配置名称,将会在启动配置的下拉菜单中显示 "type": "cppdbg", // 配置类型,这里只能为cppdbg "request": "launch", // 请求配置类型,可以为launch(启动)或attach(附加) //"launchOptionType": "Local", // 调试器启动类型,这里只能为Local "targetArchitecture": "x64", // 生成目标架构,一般为x86或x64,可以为x86, arm, arm64, mips, x64, amd64, x86_64 "program": "${file}.exe",// 将要进行调试的程序的路径 "miDebuggerPath":"c:/cygwin64/bin/gdb.exe", // miDebugger的路径,注意这里要与cygwin/MinGw的路径对应 "args": ["blackkitty", "1221", "# #"], // 程序调试时传递给程序的命令行参数,一般设为空即可 "stopAtEntry": true, // 设为true时程序将暂停在程序入口处,一般设置为false "cwd": "${workspaceRoot}", // 调试程序时的工作目录,一般为${workspaceRoot}即代码所在目录 "externalConsole": true, // 调试时是否显示控制台窗口,一般设置为true显示控制台 "preLaunchTask": "build: sample-2" // 调试会话开始前执行的任务,一般为编译程序,c++为g++, c为gcc }, { "name": "debug: sample-3", // 配置名称,将会在启动配置的下拉菜单中显示 "type": "cppdbg", // 配置类型,这里只能为cppdbg "request": "launch", // 请求配置类型,可以为launch(启动)或attach(附加) //"launchOptionType": "Local", // 调试器启动类型,这里只能为Local "targetArchitecture": "x64", // 生成目标架构,一般为x86或x64,可以为x86, arm, arm64, mips, x64, amd64, x86_64 "program": "${workspaceRoot}/out/hello.exe",// 将要进行调试的程序的路径 "miDebuggerPath":"c:/cygwin64/bin/gdb.exe", // miDebugger的路径,注意这里要与cygwin/MinGw的路径对应 "args": ["blackkitty", "1221", "# #"], // 程序调试时传递给程序的命令行参数,一般设为空即可 "stopAtEntry": true, // 设为true时程序将暂停在程序入口处,一般设置为false "cwd": "${workspaceRoot}", // 调试程序时的工作目录,一般为${workspaceRoot}即代码所在目录 "externalConsole": true, // 调试时是否显示控制台窗口,一般设置为true显示控制台 "preLaunchTask": "build: sample-3" // 调试会话开始前执行的任务,一般为编译程序,c++为g++, c为gcc } ] }