【C++】LLVM-mingw + VSCode:Windows 开发攻略

LLVM-mingw 是一个基于 LLVM 项目的开源工具链,用于在类 Unix 系统(如 Linux 或 macOS)上为 Windows 平台交叉编译应用程序,它结合了 LLVM 编译器基础设施(包括 Clang C/C++/Objective-C 编译器和 LLD 链接器,用以替代传统的 GNU 编译器 GCC)以及 MinGW-w64 运行时库(提供 Windows 平台的 API 头文件和导入库,支持 32 位和 64 位 Windows 应用程序开发)。


安装与配置 LLVM-mingw

1. 下载 LLVM-mingw

LLVM-mingw 提供了预编译工具链,可在以下地址获取:

推荐下载文件 llvm-mingw-20250826-ucrt-x86_64.zip,并将其解压至:

C:\Development\llvm-mingw 
20250826:发布日期,格式为 YYYYMMDD,表示版本时间(可选最新)ucrt:使用 Windows Universal C Runtime(UCRT)作为 C 运行时x86_64:架构类型,表示 64 位目标平台

解压后的文件夹结构应类似如下:

LICENSE.TXT arm64ec-w64-mingw32 bin include python x86_64-w64-mingw32 aarch64-w64-mingw32 armv7-w64-mingw32 i686-w64-mingw32 lib share 

2. 配置环境变量

检查现有工具

确保系统中未添加旧版 MinGW 或其他 GCC 工具链路径。

在 PowerShell 中执行以下命令,查看是否已安装:

gcc --version clang++--version 

如果命令未找到,说明未配置环境变量或尚未安装。


添加到 PATH

C:\Development\llvm-mingw\bin 添加到 系统级环境变量 PATH

setx PATH "$($env:Path);C:\Development\llvm-mingw\bin"/M 
setx PATH:修改系统 PATH。"$($env:Path);...":保留原有 PATH 内容并追加新路径。/M:设置为系统变量,对所有用户生效。

配置完成后,需重新打开 PowerShell 或 VSCode 终端使其生效。


临时生效(当前会话)

如果仅希望当前 PowerShell 会话立即可用,可以使用:

$env:Path +=";C:\Development\llvm-mingw\bin"
这种方式不会永久保存,窗口关闭后失效。

3. 测试编译和运行

创建测试文件

使用 PowerShell 一行命令创建 main.cpp

echo'#include <iostream>' > main.cpp;echo'int main() { std::cout << "Hello, World!" << std::endl; return 0; }' >> main.cpp

编译 C++ 程序

使用 clang++ 编译生成 main.exe

clang++ main.cpp-o main.exe 

运行测试程序

执行生成的程序:

./main.exe 

输出结果应为:

Hello, World! 

清理测试文件

如果不再需要测试文件,可以删除:

Remove-Item main.cpp, main.exe 

可以按照之前的文风,将内容润色、分段和强化说明如下:


安装 VSCode 与插件

1. 下载与安装 VSCode

访问 Visual Studio Code 官网,下载安装最新版本的 VSCode。
安装过程中可保持默认设置即可,安装完成后即可打开编辑器。


2. 安装必要插件

在 VSCode 中按下 Ctrl + Shift + X 打开插件市场,然后搜索并安装以下插件:

  • Chinese (Simplified):提供 VSCode 界面汉化,使编辑器更易上手
  • CodeLLDB:利用 LLVM 工具链中的 lldb 对 C++ 程序进行调试,包括断点、变量查看和堆栈分析
  • Clangd:基于 LLVM 工具链中的 clangd 提供 C++ 代码智能提示、格式化、高亮、跳转等功能

运行与调试单文件

1. 创建项目文件夹

  1. 新建一个代码文件夹,例如 demo
  2. 使用 VSCode 打开该文件夹,作为工作区。

2. 配置编译任务(tasks.json)

在项目根目录下创建 .vscode\tasks.json 文件,用于定义 Clang++ 编译任务

{"version":"2.0.0","tasks":[{"type":"shell","label":"Build with Clang++","command":"clang++.exe","args":[// === 调试与优化 ==="-g3",// 最高级调试信息,方便GDB/LLDB"-O0",// 关闭优化,便于调试// === 各类运行时检测 ==="-fsanitize=address",// ASan "-fsanitize=undefined",// UBSan"-fno-omit-frame-pointer",// 保留帧指针,ASan 需要"-fno-optimize-sibling-calls",// 调用栈更清晰// === 启用所有常见警告 ==="-Wall",// 基础警告"-Wextra",// 额外警告"-Wpedantic",// 严格遵循C++标准// === C++ 标准 (可改成 c++17 / c++23) ==="-std=c++17",// === 输出文件 ==="${file}","-o","${fileDirname}\\${fileBasenameNoExtension}.exe"],"group":{"kind":"build","isDefault":true}}]}
-g3:生成调试信息-O0:关闭优化,便于调试${file} / ${fileDirname} / ${fileBasenameNoExtension}:VSCode 内置变量,可支持任意源文件名配置完成后,按 Ctrl + Shift + B 可以快速编译当前文件

3. 配置调试任务(launch.json)

.vscode\launch.json 中配置 CodeLLDB 调试器

{"version":"0.2.0","configurations":[{"name":"Debug with CodeLLDB","type":"lldb","request":"launch","program":"${workspaceFolder}/${fileBasenameNoExtension}.exe","args":[],"cwd":"${workspaceFolder}","stopOnEntry":false,"preLaunchTask":"Build with Clang++","sourceLanguages":["cpp"],"terminal":"integrated"}]}
preLaunchTask:在启动调试前自动执行编译任务${fileBasenameNoExtension}.exe:与源文件同名的可执行文件调试时可直接按 F5 启动

4. 创建测试源文件

在项目根目录下创建 main.cpp(支持任意文件名):

#include<iostream>intmain(){ std::cout <<"Hello, World!"<< std::endl;return0;}

5. 编译与调试

  1. 在 VSCode 中打开 main.cpp
  2. F5 启动调试。
  3. 如果配置正确,调试器会编译源文件并运行程序,输出:
Hello, World! 
至此,你已经完成了单文件的编译与调试环境配置。
可在此基础上,逐步扩展为多文件或 CMake 项目。

可以将你的章节内容润色、补充说明,并给出一个推荐的 .clang-format 配置示例:


代码格式化

1. 快捷格式化

安装 Clangd 后,你可以:

  • Ctrl + Alt + F 或右键选择 “Format Document” 进行手动格式化
  • 打开 设置Ctrl + ,),搜索 Format On Save 并勾选
    • 这样每次保存文件时,VSCode 会自动格式化代码
使用 Format On Save 可以保证代码风格统一,减少格式相关的提交差异。

2. 配置 .clang-format

Clangd 的格式化规则可通过项目根目录下的 .clang-format 文件进行定制。
下面给出一个适用于现代 C++ 项目的推荐配置:

# 语言: None, Cpp, Java, JavaScript, ObjC, Proto, TableGen, TextProtoLanguage: 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(定义在类中,空函数), AllAllowShortFunctionsOnASingleLine: 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: AfterColonBreakStringLiterals:false# 每行字符的限制,0表示没有限制ColumnLimit:0CompactNamespaces:true# 构造函数的初始化列表要么都在同一行,要么都各自一行ConstructorInitializerAllOnOneLineOrOnePerLine:false# 构造函数的初始化列表的缩进宽度ConstructorInitializerIndentWidth:4# 延续的行的缩进宽度ContinuationIndentWidth:4# 去除C++11的列表初始化的大括号{后和}前的空格Cpp11BracedListStyle:true# 继承最常用的指针和引用的对齐方式DerivePointerAlignment:false# 固定命名空间注释FixNamespaceComments:true# 缩进case标签IndentCaseLabels:falseIndentPPDirectives: None # 缩进宽度IndentWidth:4# 函数返回类型换行时,缩进函数声明或函数定义的函数名IndentWrappedFunctionNames:false# 保留在块开始处的空行KeepEmptyLinesAtTheStartOfBlocks:false# 连续空行的最大数量MaxEmptyLinesToKeep:1# 命名空间的缩进: None, Inner(缩进嵌套的命名空间中的内容), AllNamespaceIndentation: None # 指针和引用的对齐: Left, Right, MiddlePointerAlignment: Right # 允许重新排版注释ReflowComments:true# 允许排序#includeSortIncludes:false# 允许排序 using 声明SortUsingDeclarations:false# 在C风格类型转换后添加空格SpaceAfterCStyleCast:false# 在Template 关键字后面添加空格SpaceAfterTemplateKeyword:true# 在赋值运算符之前添加空格SpaceBeforeAssignmentOperators:true# SpaceBeforeCpp11BracedList: true# SpaceBeforeCtorInitializerColon: true# SpaceBeforeInheritanceColon: true# 开圆括号之前添加一个空格: Never, ControlStatements, AlwaysSpaceBeforeParens: ControlStatements # SpaceBeforeRangeBasedForLoopColon: true# 在空的圆括号中添加空格SpaceInEmptyParentheses:false# 在尾随的评论前添加的空格数(只适用于//)SpacesBeforeTrailingComments:1# 在尖括号的<后和>前添加空格SpacesInAngles:false# 在C风格类型转换的括号中添加空格SpacesInCStyleCastParentheses:false# 在容器(ObjC和JavaScript的数组和字典等)字面量中添加空格SpacesInContainerLiterals:true# 在圆括号的(后和)前添加空格SpacesInParentheses:false# 在方括号的[后和]前添加空格,lamda表达式和未指明大小的数组的声明不受影响SpacesInSquareBrackets:false# 标准: Cpp03, Cpp11, AutoStandard: Auto # tab宽度TabWidth:4# 使用tab字符: Never, ForIndentation, ForContinuationAndIndentation, AlwaysUseTab: Never 

新建万能头文件(可选)

虽然 LLVM-mingw 基于 MinGW,但它只包含标准 C++ 内容,而不包括 GCC 的扩展特性。bits/stdc++.h 是 GCC 中的一个特有头文件,它并不是 C++ 标准库的一部分,因此在 LLVM-mingw 中默认并不可用。如果你希望在 LLVM-mingw 中使用该头文件,可以手动创建一个 bits/stdc++.h 并将其放置到工具链的 include 目录中。以下是详细的操作方法:


1. 创建 stdc++.h

在任意临时目录下新建文件 stdc++.h,内容可以如下(覆盖常用 C++ 标准库):

#ifndef_GLIBCXX_NO_ASSERT#include<cassert>#endif#include<cctype>#include<cfloat>#include<climits>#include<csetjmp>#include<cstdarg>#include<cstddef>#include<cstdlib>#if__cplusplus >=201103L#include<cstdint>#if__cplusplus <201703L#include<ciso646>#endif#endif// C++// #include <bitset>// #include <complex>#include<algorithm>#include<bitset>#include<functional>#include<iterator>#include<limits>#include<memory>#include<new>#include<numeric>#include<typeinfo>#include<utility>#if__cplusplus >=201103L#include<array>#include<atomic>#include<initializer_list>#include<ratio>#include<scoped_allocator>#include<tuple>#include<typeindex>#include<type_traits>#endif#if__cplusplus >=201402L#endif#if__cplusplus >=201703L#include<any>// #include <execution>#include<optional>#include<variant>#include<string_view>#endif#if__cplusplus >=202002L#include<bit>#include<compare>#include<concepts>#include<numbers>#include<ranges>#include<span>#include<source_location>#include<version>#if__cpp_impl_coroutine#include<coroutine>#endif#endif#if__cplusplus >202002L#include<expected>#include<stdatomic.h>#endif#if_GLIBCXX_HOSTED// C#ifndef_GLIBCXX_NO_ASSERT#include<cassert>#endif#include<cctype>#include<cerrno>#include<cfloat>#include<climits>#include<clocale>#include<cmath>#include<csetjmp>#include<csignal>#include<cstdarg>#include<cstddef>#include<cstdio>#include<cstdlib>#include<cstring>#include<ctime>#include<cwchar>#include<cwctype>#if__cplusplus >=201103L#include<cfenv>#include<cinttypes>#include<cstdint>#include<cuchar>#if__cplusplus <201703L#include<ccomplex>#include<cstdalign>#include<cstdbool>#include<ctgmath>#endif#endif// C++#include<complex>#include<deque>#include<exception>#include<fstream>#include<functional>#include<iomanip>#include<ios>#include<iosfwd>#include<iostream>#include<istream>#include<iterator>#include<limits>#include<list>#include<locale>#include<map>#include<memory>#include<new>#include<numeric>#include<ostream>#include<queue>#include<set>#include<sstream>#include<stack>#include<stdexcept>#include<streambuf>#include<string>#include<typeinfo>#include<utility>#include<valarray>#include<vector>#if__cplusplus >=201103L#include<array>#include<atomic>#include<chrono>#include<codecvt>#include<condition_variable>#include<forward_list>#include<future>#include<initializer_list>#include<mutex>#include<random>#include<ratio>#include<regex>#include<scoped_allocator>#include<system_error>#include<thread>#include<tuple>#include<typeindex>#include<type_traits>#include<unordered_map>#include<unordered_set>#endif#if__cplusplus >=201402L#include<shared_mutex>#endif#if__cplusplus >=201703L#include<any>#include<charconv>// #include <execution>#include<filesystem>#include<optional>#include<memory_resource>#include<variant>#endif#if__cplusplus >=202002L#include<barrier>#include<bit>#include<compare>#include<concepts>#include<format>#include<latch>#include<numbers>#include<ranges>#include<span>#include<stop_token>#include<semaphore>#include<source_location>#include<syncstream>#include<version>#endif#if__cplusplus >202002L#include<expected>#include<flat_map>#include<flat_set>#include<generator>#include<print>#include<spanstream>#include<stacktrace>#include<stdatomic.h>#include<stdfloat>#endif#if__cplusplus >202302L#include<text_encoding>#include<stdbit.h>#include<stdckdint.h>#endif#endif// HOSTED
注:可以根据需要裁剪头文件,只包含项目会用到的内容。

2. 放置到系统 include 路径

LLVM-mingw 的 include 路径通常在:

C:\Development\llvm-mingw\include\c++\v1\ 

你可以创建 bits 文件夹:

C:\Development\llvm-mingw\include\c++\v1\bits\ 

然后将 stdc++.h 放入该目录:

C:\Development\llvm-mingw\include\c++\v1\bits\stdc++.h 

这样在你的代码中就可以:

#include<bits/stdc++.h>

总结

通过本教程,我们成功搭建了一个基于 LLVM-mingw 和 VSCode 的 Windows C++ 开发环境。使用 LLVM-mingw 工具链,不仅能享受 LLVM 编译器提供的高效优化和现代 C++ 支持,还能通过 MinGW-w64 提供的 Windows API 和运行时库实现无缝的 Windows 平台开发。

与传统的 Windows 开发工具链相比,LLVM-mingw 在跨平台开发、性能和编译速度上具有优势,同时结合 VSCode 的智能编辑功能和强大的插件支持,开发者可以在 Windows 平台上以更简洁、便捷的方式进行 C++ 开发。

整个开发流程涵盖了从环境配置、编译、调试到代码格式化等各个方面,确保了高效的开发和调试体验。通过配置 tasks.jsonlaunch.json,VSCode 能够自动化编译、调试任务,使得开发流程更加顺畅。此外,借助 Clangd 插件的代码智能提示、格式化功能,能够提高代码的可维护性和团队协作的效率。

总体来说,使用 LLVM-mingw 和 VSCode 可以帮助开发者在 Windows 平台上获得更加现代化、高效的 C++ 开发体验,尤其适合那些希望避免 Visual Studio 或 Cygwin 等重量级工具的开发者。

Read more

C++起始之路——模板进阶

C++起始之路——模板进阶

💁‍♂️个人主页:进击的荆棘 👇作者其它专栏: 《数据结构与算法》《算法》《C++起始之路》 目录 1.非类型模板参数 2.模板的特化 3.模板分离编译 4.模板总结 1.非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参即:出现在模板参数列表中,跟在class或typename之类的后面的参数类型名称。 非类型形参,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。 namespace Achieve{ //定义一个模板类型的静态数组 tempalte<class T,size_t N=10> class array{ public: T& operator[](size_t index)

【免费下载】 Microsoft Visual C++ Runtime 下载指南

Microsoft Visual C++ Runtime 下载指南 【下载地址】MicrosoftVisualCRuntime下载指南Microsoft Visual C++ Runtime 是微软发布的一个重要组件,它允许运行由Visual C++编写的程序。许多应用程序依赖这些运行时库才能正确运行。如果你遇到因为缺失VC++运行库导致的应用启动失败问题,本指南将帮助你顺利下载并安装所需的Visual C++ Runtime 项目地址: https://gitcode.com/Resource-Bundle-Collection/20369 简介 Microsoft Visual C++ Runtime 是微软发布的一个重要组件,它允许运行由Visual C++编写的程序。许多应用程序依赖这些运行时库才能正确运行。如果你遇到因为缺失VC++运行库导致的应用启动失败问题,本指南将帮助你顺利下载并安装所需的Visual C++ Runtime。 下载步骤 1. 访问官方资源:首先,推荐直接从微软官网或信誉高的平台下载Visual C++ Runtime。为了避免链接失效或

C++之动态数组vector

C++之动态数组vector

Vector * 一、什么是 `std::vector`? * 二、`std::vector` 的基本特性 * (一)动态扩展 * (二)随机访问 * (三)内存管理 * 三、`std::vector` 的基本操作 * (一)定义和初始化 * (二)添加和删除元素 * (三)访问元素 * (四)遍历 * (五)大小和容量 * 四、`std::vector` 的应用场景 * (一)动态数组 * (二)随机访问 * (三)内存管理 * 五、注意事项 * (一)性能优化 * (二)内存释放 * (三)异常安全 * 六、总结 在

【Java Web学习 | 第八篇】JavaScript(2) 基础知识2

【Java Web学习 | 第八篇】JavaScript(2) 基础知识2

🌈个人主页: Hygge_Code🔥热门专栏:从0开始学习Java | Linux学习| 计算机网络💫个人格言: “既然选择了远方,便不顾风雨兼程” 文章目录 * JavaScript 运算符与流程控制全解析 * 一、运算符:自增、比较与逻辑🥝 * 1. 自增运算符(++) * 2. 比较运算符 * 3. 逻辑运算符 * 二、条件判断语句🥝 * 1. if 语句 * 2. 三目运算符 * 3. switch 语句 * 三、循环语句🥝 * 1. while 循环 * 2. for 循环 * 总结🍂 JavaScript 运算符与流程控制全解析 在 JavaScript 中,运算符和流程控制是实现逻辑处理的基础。本文在前文基础上补充for循环内容,全面讲解比较运算符、