@小明 后面有计划支持 msvc
mcpp-team
mcpp社区团队
帖子
-
想请教一下大家构建C++模块架构是这样的吗? -
想请教一下大家构建C++模块架构是这样的吗?而且 mcpp 项目 完全使用 C++23 + 模块化工程结构, 本身可以作为 真实的 模块化项目示例 进行参考
-
想请教一下大家构建C++模块架构是这样的吗?@小明 模块文件布局没有什么问题
module; // 全局传统头文件 export module xxx; // 模块申明 import xxx; 导入 // 具体实现但是 cmake_minimum_required(VERSION 3.28) 这个版本好像太低了 而且cmake目前还是实验性支持module需要设置一个值, 我之之前有做一个视频有详细细节 可以参考
另外, 如果想要体验模块化建议使用 mcpp 专门为模块化工程打造的构建工具 支持非常好
我也简单做过功能介绍视频, 可以了解
-
[mcpp]: 用 C++23 模块 + import std 开发了个构建工具,并实现自己构建自己(自举)从去年 gcc 15.1 初步支持 import std 开始, 我就在 C++的模块化上做了很多实践
前段时间, 突然产生了以 C++23 模块化为基础, 实现一个现代 C++模块化项目的构建工具。并以其能用自己从源码构建出自己也就是所谓的自举来做为初步目标, 目前这个目标已经实现
欢迎对现代 C++和模块化感兴趣的朋友来用, mcpp 构建工具使用模块化特性 玩一玩或开发开发小项目 也欢迎大家来反馈和交流
开源仓库: https://github.com/mcpp-community/mcpp
mcpp
一个 现代 C++ 模块化构建工具 — 纯 C++23 模块编写,已实现自举
核心特性
- C++23 模块原生支持 —
import std自动处理,文件级增量构建,模块依赖自动分析,零手动配置 - 纯模块化自举 — mcpp 自身由 43+ 个 C++23 模块组成,用自己构建自己,模块系统经实战验证
- 开箱即用 — 一条命令安装,内置 GCC 16 / LLVM 20 工具链,自动下载到隔离沙盒,不污染系统
- 集成依赖管理 — SemVer 约束解析、锁文件、跨项目 BMI 缓存、自定义包索引
- 多包工作空间 — Workspace 统一锁文件与版本管理,适合大型项目
为什么选择 mcpp ?
mcpp 专门为 C++23 模块化开发 打造。如果你想在项目中使用
import std、模块接口单元(.cppm)、模块分区等现代 C++ 特性,mcpp 在 Linux 上能为你提供便捷且友好的开发体验:- 默认模块化 —
mcpp new创建的项目模板直接使用 C++23 模块,import std开箱即用 - 文件级增量构建 — 基于 P1689 dyndep 的三层优化(前端脏检查 + 逐文件扫描 + BMI restat ),只重编真正变化的模块
- 一键创建 & 构建 —
mcpp new hello && cd hello && mcpp build,工具链自动安装,无需手动配置编译器和构建系统 - 模块化生态 — mcpplibs 提供一系列可直接
import的 C++ 模块化库,支持自定义包索引
注: 早期版本 — mcpp 仍在积极开发中,接口和行为可能在后续版本调整。
欢迎对现代 C++ 模块化构建工具感兴趣的开发者参与贡献。
问题 / 反馈 / 想法欢迎在 issues 留言。快速开始
安装
方式一:使用 xlings 安装(推荐)
xlings install mcpp -y方式二:一键安装脚本
curl -fsSL https://github.com/mcpp-community/mcpp/releases/latest/download/install.sh | bash安装到
~/.mcpp/,自动加进 shell PATH 。删除~/.mcpp即可干净卸载。方式三:让 AI 助手帮你安装
将以下提示词复制给你的 AI 编码助手( Claude Code / Cursor / Copilot 等):
阅读 https://github.com/mcpp-community/mcpp 的 README , 帮我安装 mcpp 并创建一个 C++23 模块项目,构建并运行。 项目的 .agents/skills/mcpp-usage/SKILL.md 有详细的使用指南。创建项目 & 构建运行
mcpp new hello cd hello mcpp build mcpp run注:首次构建会初始化环境并获取工具链,可能需要一些时间。
项目结构
hello/ ├── mcpp.toml ← 工程描述 └── src/ └── main.cpp ← import std; 直接可用# mcpp.toml [package] name = "hello" [targets.hello] kind = "bin" main = "src/main.cpp"使用模块化库
在
mcpp.toml中添加两行依赖,即可引用 mcpplibs 社区模块化库:[dependencies] cmdline = "0.0.2"然后在代码中直接
import:import mcpplibs.cmdline;更多依赖配置方式(版本约束、命名空间、Git 引用、本地路径等)参见 mcpp.toml 指南 — 依赖管理。
平台支持
OS / arch GCC (glibc) GCC (musl) Clang / LLVM MSVC Linux x86_64 
默认
— Linux aarch64 


— macOS — — 
— Windows — — 

已支持 |
计划中默认:release 二进制走 musl 全静态,Linux x86_64 可直接运行,无 glibc 依赖。
文档
任意命令的完整选项可通过
mcpp <cmd> --help查阅。AI 辅助学习:你可以将以下提示词发给 AI 编码助手,让它帮你快速了解 mcpp:
阅读 https://github.com/mcpp-community/mcpp 仓库的 .agents/skills/mcpp-usage/SKILL.md 和 docs/ 目录下的文档, 告诉我如何用 mcpp 创建一个带依赖的 C++23 模块项目。参与贡献
欢迎通过 Issue 和 PR 参与项目开发。项目接受开发者使用 AI Agent 参与开发与贡献。
基本流程
- 创建 Issue — Bug 修复、新功能、优化等,先在 issues 创建讨论
- 实现改动 — Fork 仓库,创建分支,实现并验证(
mcpp build+ E2E 测试) - 提交 PR — 使用
gh pr create,确保 CI 通过 - CI 必须通过 — CI 不通过的 PR 不会被合入
提交信息规范:
feat:/fix:/test:/docs:/refactor:前缀AI Agent 贡献:项目的
.agents/skills/mcpp-contributing/SKILL.md提供了完整的 Agent 贡献流程和项目结构说明。将以下提示词发给 AI 助手即可:阅读 https://github.com/mcpp-community/mcpp 仓库的 .agents/skills/mcpp-contributing/SKILL.md , 按照指南帮我给 mcpp 项目提交一个贡献。社区 & 生态
- 社区论坛 — 交流群 (Q: 1067245099)
- mcpp-index — 默认包索引
- mcpplibs — 模块化 C++ 库集合
致谢
项目依赖和灵感来源:
- xlings — 工具链 / 包管理底座
- mcpplibs.cmdline — CLI 框架
- ninja — 底层构建引擎
- xmake — 跨平台构建工具
- cargo — Rust 包管理器
- C++23 模块原生支持 —
-
GCC 16 上手初体验:环境配置、默认 C++20、模块化、诊断增强和 C++26 反射GCC 16 上手初体验:环境配置、默认 C++20、模块化、诊断增强和 C++26 反射
从去年发布GCC 15.1 并支持
import std开始, 我的新项目也全面转向C++23 + 模块化(踩了不少坑 [逃]). 而最近几天 GCC 16.1 也正式发布了, 这篇文章就来初步的上手体验一下.主要内容包括:
- 0.GCC 16 环境配置
- 1.默认标准: 从C++17升级到C++20, 正式进入C++2x时代
- 2.模块化: 有一定优化, 但任处于实验性支持阶段 (悲)
- 3.代码诊断和静态分析增强
- 4.C++ 26 反射实验性支持
- 5.总结及相关链接
0. 环境配置 (Linux)
安装GCC 16可以选择按官方文档从源码进行构建 GCC WIKI 或 直接使用xlings工具安装预构建版本(注: 该方式有个好处不污染系统环境)
安装xlings包管理工具curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/refs/heads/main/tools/other/quick_install.sh | bash source ~/.bashrc # 或重新打开一次控制台 xlings -hxlings工具安装后, 创建隔离环境并安装gcc 16xlings subos new gcc-test xlings subos use gcc-test xlings install gcc@16.1.0 -y gcc --version
1.默认标准: 从 C++17 升级到 C++20, 正式进入 C++2x 时代
GCC 16 的一个关键变化是: C++ 编译默认标准从 GNU++17 变成 GNU++20。不用额外再写
-std=c++20也能编译下面的程序了:#include <iostream> consteval int answer() { return 16; } int main() { std::cout << "__cplusplus=" << __cplusplus << ", consteval=" << answer() << '\n'; }编译运行:
g++ cpp20-default.cpp -o cpp20-default ./cpp20-default输出:
__cplusplus=202002, consteval=16如果显式退回 C++17:
g++ -std=c++17 cpp20-default.cpp -o cpp17-check会报错:
t.cpp:3:1: error: 'consteval' does not name a type; did you mean 'constexpr'? 3 | consteval int answer() { | ^~~~~~~~~ | constexpr默认标准的改变, 不仅仅只是帮我们省了
-std=c++20,而是默认构建行为的改变 会加速C++ 2x时代生态的发展2.模块化: 有一定优化, 但任处于实验性支持阶段
模块化早在C++20就发布, 他的目标是想解决 C++ 头文件模型长期存在的问题: 重复解析、宏污染、包含顺序敏感、接口和实现边界不够清晰。在工程方面他对C++的影响是颠覆性的, 但是由于历史/兼容性/复杂度等多方面原因导致, GCC 16 的默认标准虽然是 GNU++20,但 modules 支持仍然是实验性的,所以GCC 16对模块化爱好者来说只能算波澜不惊
只不过, GCC16 还是有在模块化做了一些工作的
- 修复了一些模块化的bug
- 新增
--compile-std-module,用于更方便地构建标准库相关模块和 header unit
其中
--compile-std-module的增加 更方便大家体验模块化和import std, 避免了之前连一个hello world级别的main.cpp编译都要分几步的情况(有时候还有问题), 所以这也算是一大进步 - 现在可以像下面一样一键编译import std的程序了// main.cpp import std; int main() { std::println("{}", 42); }编译:
g++ -std=c++23 -fmodules --compile-std-module main.cpp -o app ./app3. 诊断增强: 错误信息结构化 + 编译期静态代码分析
C++ 报错经常被吐槽,不是因为编译器不知道哪里错了,而是因为错误链太长,人很难从一堆候选函数、模板实例化和类型展开里看出主线。
GCC 16 的一个明显变化是,部分 C++ 错误信息开始用层级结构展示。例如这个声明和定义不一致的例子:
class Foo { public: void test(int i, int j, void *ptr, int k); }; void Foo::test(int i, int j, const void *ptr, int k) { } int main() { return 0; }编译:
g++ diagnostics-mismatch.cppGCC 16 会把候选函数和参数差异分层展示,核心信息大致是:
error: no declaration matches 'void Foo::test(int, int, const void*, int)' - there is 1 candidate - candidate is: 'void Foo::test(int, int, void*, int)' - parameter 3 of candidate has type 'void*' - which does not match type 'const void*'这比以前只告诉你 找不到匹配声明 更有用,它一定程度指出了候选是谁、哪里不一致、哪一个参数出了问题。
甚至还能生成更适合浏览器查看的诊断html页面:
g++ diagnostics-mismatch.cpp \ -fdiagnostics-add-output=experimental-html
如果想给 CI、IDE 或代码扫描平台使用,可以生成 SARIF:
g++ diagnostics-mismatch.cpp \ -fdiagnostics-format=sarif这个的优化, 不仅 报错更容易看了,而且后面可能会影响工具链体验。编译器不再只是把错误打印到终端,而是可以把结构化诊断交给网页、编辑器、代码审查和静态分析系统。
配合上
-fanalyzer的能力。它是 GCC 自带的静态分析能力。如果加上-Werror体验就有点类似Rust的严格编译期检查功能看一个 use-after-delete:
#include <iostream> int main() { int *p = new int(42); delete p; std::cout << *p << "\n"; }编译:
g++ -std=c++20 -fanalyzer analyzer-uaf.cppGCC 16 会给出类似警告:
warning: use after 'delete' of 'p' [CWE-416] [-Wanalyzer-use-after-free]
4. C++26 特性: Reflection / 反射
GCC 16 实现了若干 C++26 特性,这里简单试一试
-std=c++26 -freflection以一个简单的结构体为例, 看看 C++26反射 的功能:
#include <iostream> #include <meta> #include <string_view> struct User { int id; double score; }; consteval std::size_t field_count() { auto fields = std::meta::nonstatic_data_members_of( ^^User, std::meta::access_context::unchecked() ); return fields.size(); } consteval std::string_view field_name(std::size_t index) { auto fields = std::meta::nonstatic_data_members_of( ^^User, std::meta::access_context::unchecked() ); return std::meta::identifier_of(fields[index]); } consteval std::string_view field_type(std::size_t index) { auto fields = std::meta::nonstatic_data_members_of( ^^User, std::meta::access_context::unchecked() ); return std::meta::display_string_of(std::meta::type_of(fields[index])); } int main() { constexpr auto type_name = std::meta::display_string_of(^^User); std::cout << type_name << " has " << field_count() << " fields\n"; std::cout << field_name(0) << ": " << field_type(0) << '\n'; std::cout << field_name(1) << ": " << field_type(1) << '\n'; }编译运行:
g++ -std=c++26 -freflection reflection-user.cpp -o reflection-user ./reflection-user输出:
User has 2 fields id: int score: double这里的
^^User是对User这个结构体类型做静态反射,std::meta::display_string_of可以拿到类型的显示名。std::meta::nonstatic_data_members_of则能拿到结构体的非静态数据成员列表,再通过identifier_of和type_of分别取得成员名和成员类型。C++ 代码可以在编译期拿到结构体自身的字段信息。这个功能对 序列化、ORM、RPC、命令行参数解析、UI 绑定、测试生成等大量现在依赖宏、模板技巧或外部代码生成的场景 有重要影响
5. 总结
GCC 16.1.0 感觉最核心的就是默认标准从C++17变成了C++20, 某种意义上也算正式迈入C++2x时代了, 下面是一些个人感觉
- 1.默认 C++ 标准从 GNU++17 变成 GNU++20。能进一步加速C++生态进入C++2x的时代
- 2.C++20 modules特性 在 GCC 16 里只是做了部分优化, 相比GCC 15.1.0引入import std来说, 没有特别惊喜
- 3.诊断输出更结构化了。嵌套错误、HTML、SARIF 会让编译器错误更适合教学、CI 和 IDE 集成。
- 4.C++26 Reflection 已经可以初步尝试。对于个人项目可以上手用一用 (但可能存在很多潜在的坑)
我个人是比较关注模块化的进展, 总体来说GCC16虽然模块化特性上没有过多惊喜, 但在
import std之后, 模块化算是已经初步可以在项目里尝试的水平了, 并且我们 mcpp-community 现代C++爱好者社区 已经在 模块化的 项目/库的 工程化、包管理、工具链 等方面有一定的探索, 欢迎感兴趣的朋友加入讨论- 社区Github主页: https://github.com/mcpp-community
- C++23模块化项目: https://github.com/openxlings/xlings
- C++23模块化库: https://github.com/mcpplibs
相关链接
- xlings: https://github.com/openxlings/xlings
- mcpp-community: https://github.com/mcpp-community
- GCC 16.1 Released: https://gcc.gnu.org/pipermail/gcc-announce/2026/000190.html
- GCC 16 Release Series: Changes, New Features, and Fixes: https://gcc.gnu.org/gcc-16/changes.html
- GCC 16.1.0: https://sourceware.org/pub/gcc/releases/gcc-16.1.0/
-
请教如何自定义异常class myException : public std::exception { private: std::string _msg; public: myException(const char* message) noexcept : _msg(message) {} const char* what() const noexcept override { return _msg.c_str(); } }; -
请教如何自定义异常就你上面写的就可以啊
-
请教如何自定义异常const char * msg; 指针可能会关联到外部对象(不可预期的生命周期), 可以使用 std::string 自己持有对象, 确保生命周期安全. 对关于 __cow_string 这个是 内部实现的 字符串的写时复制 机制, 可以不用管
可能的风险点
{ std::string localVar = "Hi, I'm local var"; throw myException(localVar.c_str()); // localVar 出作用域 会析构, 可能会导致msg指向无效内存 } -
[windows系统][环境配置] d2x命令好像无法使用? -
xlings安装完成,但是项目安装提示失败@sleepyiang 找到原因, 这个时项目里d2x buildtools的bug
现在已经修复了可以使用 d2x install d2mcpp 获取最新的项目 再尝试尝试
注: 应该不是上面说的版本原因
