Windows系统中vscode+MSVC的C++配置

Windows系统中vscode+MSVC的C++配置

在Windows上编译C++程序不能直接使用gcc和g++命令,一般来说如果非要使用的话可以用wsl或者MinGW。过去的很长一段时间我也确实是这么做的,但是最近在学习C++20,无奈MSVC是三大主流编译器里面相关特性支持最完善的,只能捣鼓一下怎么使用,特此记录。

安装Visual Studio

MSVC可以直接通过安装Visual Studio获取,在该页面选择合适的Visual Studio版本(一般来说是选社区版,因为是免费的)就可以下载安装。

其中MSVC工具链通过选择“使用C++的桌面开发”安装:

安装截图(来源:微软官网)
安装完之后,如果使用默认的安装位置,应该在C:\Program Files (x86)\Microsoft Visual Studio\20xx\Community\VC\Tools\MSVC\xx.xx.xx\bin\Hostx64\x64\这个路径下面有编译链包含的各个工具(比如cl.exe)。

配置环境变量

虽然说我们找到了编译链工具的所在位置,但是如果现在直接调用它们进行编译是无法正常运行的,这是因为MSVC工具链还有很多额外的环境变量配置。这些变量当然可以手动配置,但是Visual Studio本身提供了一个配置脚本:C:\Program Files (x86)\Microsoft Visual Studio\20xx\Community\VC\Auxiliary\Build\vcvars64.bat,这个bat脚本中干的事情就是把那些杂七杂八的环境变量给设置好。

因此我只把这个脚本所在的文件夹加入了Path环境变量,这样一来只需在cmd中先调用vcvars64,就可以正常使用cl.exe等编译工具了:

Path环境变量

C:\Users\xxx>where cl
INFO: Could not find files for the given pattern(s).

C:\Users\xxx>vcvars64
**********************************************************************
** Visual Studio 2019 Developer Command Prompt v16.11.22
** Copyright (c) 2021 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'

C:\Users\xxx>where cl
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\cl.exe

不过这个脚本比较坑,必须用cmd命令行才能运行,在powershell命令行中是无效的(而且依然会有配置成功的输出,真坑)。

其实这个时候就可以使用cl.exe直接进行C++源文件的编译了,比如现在有一份main.cpp

#include <iostream>

int main() {
    std::cout << "hello" << std::endl;
    return 0;
}

使用命令cl.exe /EHsc /std:c++20 main.cpp就可以编译得到文件main.exe,运行后输出hello

C:\Users\xxx>type main.cpp
#include <iostream>

int main() {
    std::cout << "hello" << std::endl;
    return 0;
}
C:\Users\xxx>cl /EHsc /std:c++20 main.cpp
用于 x64 的 Microsoft (R) C/C++ 优化编译器 19.29.30147 版
版权所有(C) Microsoft Corporation。保留所有权利。

main.cpp
Microsoft (R) Incremental Linker Version 14.29.30147.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:main.exe
main.obj

C:\Users\xxx>.\main.exe
hello

所以说使用MSVC也不难。既然搞清楚了原理,就可以去编写vscode的相关文件(launch.jsontasks.json),然后让vscode也能一键使用MSVC编译运行源代码。

配置launch.jsontasks.json

在安装了C++插件之后,使用vscode打开C++源文件会在右上角显示一个小三角形,按下它就会打开编译运行的选择列表:

小三角形

配置项列表

这个列表里面有的项是默认配置的(比如上图的后面四个)。一般来说这个时候是会显示像上图一样的那个使用cl.exe编译的默认配置项,但是其实这个是没法用的(需要在命令行中先调用vcvars64.bat,然后再调用code编辑代码,太麻烦)。

上图中我的vscode显示了一个我自定义的配置(也就是第一项),这个其实是在项目根目录的.vscode文件夹中的launch.jsontasks.json中定义的:

.vscode文件夹

launch.json中有一个configurations列表,其中的项就是用户自定义的那些调试启动项,先放出我最终的文件:

{
    "configurations": [
        {
            "name": "C/C++: 运行活动文件(自定义)",
            "type": "cppdbg",
            "request": "launch",
            "program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${fileDirname}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "C:\\Program Files\\mingw64\\bin\\gdb.exe",
            "setupCommands": [
                {
                    "description": "为 gdb 启用整齐打印",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                },
                {
                    "description": "将反汇编风格设置为 Intel",
                    "text": "-gdb-set disassembly-flavor intel",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "C/C++: 生成活动文件(自定义)"
        }
    ],
    "version": "2.0.0"
}

其中name就是会在表项中显示的名字,注意不要含有cl.exe字样,因为当前版本的vscode似乎是直接通过命名进行检测的,如果发现名字里面有cl.exe,而你又不是先调用vcvars.bat再调用code的,vscode就直接不让你运行这个任务(我真是呃呃)。

type值为cppdbg,就表示这个配置项适用于C++源文件。后面的MIModemiDebuggerPath等都是对gdb的配置,这里我就继续沿用了MinGW的gdb

program就是要运行的编译后的文件名。那么要得到这个exe文件,就要先进行编译。编译的步骤定义在tasks.json中,上面的preLaunchTask就是在指定先运行tasks.json中定义的nameC/C++: 生成活动文件(自定义)的预编译任务,该任务完成后再执行launch.json中指定的指令。

tasks.jsonlaunch.json的结构大差不差,有个tasks列表列出各个预编译任务:

{
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: 生成活动文件(自定义)",
            "command": "cmd",
            "args": [
                "/c",
                "vcvars64 && cl /EHsc /std:c++20 ${file}"
            ],
            "options": {
                "cwd": "${fileDirname}"
            },
            "problemMatcher": [ ],
            "group": "build",
            "detail": "编译器生成的任务。"
        }
    ],
    "version": "2.0.0"
}

因为我的vscode默认终端是powershell,不能直接调用vcvars64.bat,所以只能通过cmd /c的方式开一个cmd子进程运行,/c就是表示cmd直接运行后面接的指令。而后面接的具体指令是vcvars64 && cl /EHsc /std:c++20 ${file}&&是连接符,表示左边的命令正常完成之后执行右边的命令,所以其实它干的事情就是先调用vcvars64设置好各个环境变量,然后再调用cl编译vscode当前打开的C++源文件。

测试

完成上述操作之后,就可以直接点vscode右上角的三角形按钮一键使用MSVC编译运行C++程序了(另:也可以使用快捷键F5)。

另外,当前vscode的官方C++插件是默认不开启C++20相关特性的支持的,虽然说不影响编译和运行,但是写代码的时候一堆波浪线和智能提示还是让人很不爽。其实只需在settings.json中加入一项:"C_Cpp.default.cppStandard": "c++23"就可以开启C++20特性的支持了。

本人编写了一个简单的用到concept特性的代码,模拟实现了python中的enumerate函数,都是可以正常编译运行的:

#include <iostream>
#include <vector>

template <typename T> 
concept Iterable = requires(T x) { x.begin(); x.end(); };

template <Iterable T>
class enumerate {
    int start;
    T obj;
    using _T_Iter = decltype(obj.begin());
    class _Iter {
        int index;
        _T_Iter iter;
    public:
        _Iter(int index, _T_Iter iter): index(index), iter(iter) {}
        void operator ++ () { ++iter, ++index; }
        void operator ++ (int) { ++iter, ++index; }
        auto operator * () { return std::pair(index, *iter); }
        bool operator == (const _Iter& i) const { return iter == i.iter; }
        bool operator != (const _Iter& i) const { return iter != i.iter; }
    };
public:
    enumerate(T obj, int start = 0): obj(std::move(obj)), start(start) {}
    auto begin() { return _Iter(start, obj.begin()); }
    auto end() { return _Iter(start, obj.end()); }
};

int main() {
    std::vector vec = {1, 4, 8, 9};
    for (auto [index, item]: enumerate(vec)) {
        std::cout << "[" << index << "] " << item << std::endl;
    }
    return 0;
}

成功运行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值