Skip to content

Latest commit

 

History

History
249 lines (171 loc) · 12.8 KB

File metadata and controls

249 lines (171 loc) · 12.8 KB

02 —— 场景

**读者:**正在判断 mcpp 适不适合手头这份工作、以及这份工作会用到它哪些功能的 开发者。

**本章回答的那一个问题:**mcpp 服务哪几类工程,而对其中一类,要用到哪些功能、 按什么顺序。

不在这里:字段参考,那是 04;示例目录,那是 03 —— 它按示例索引而不是按场景;以及命令查阅,那是 09。本章按工作本身索引。

每个场景陈述:处境、mcpp 对它贡献了什么、穿过章节的路径、可以跑的一个工程,以及 最常让人意外的那一件事。只读与手头工作相符的那个场景即可;它们之间不相互叠加。

场景一览

场景 运行
1 命令行工具或服务 examples/01-hello03-pack-static
2 供他人 import 的库 examples/11-features05-lib-distribution
3 一个仓库里的多个包 examples/04-workspace
4 图形应用 mcpp new … --template ocornut.imgui
5 为另一个操作系统构建 examples/06-openkal-cross
6 没有操作系统的目标 mcpp new … --template riscv-virt-rt
7 GPU 或加速器上的计算 examples/09-heterogeneous
8 图形渲染 examples/10-graphics/offscreen
9 工程需要的一步构建工作,以及把它共享出去 examples/08-build-rules12-a-new-device-language
10 为别人打包一个工具、一个驱动或一块板子 xim-pkgindexmcpp-index 里的描述符

1. 命令行工具或服务

处境。 一个由 C++23 模块构建的程序,带几个依赖,而且要跑在一台没有 mcpp 的 机器上。

mcpp 贡献了什么。 import std 零配置可用;编译器是被钉住的载荷,而不是机器 上恰好有的那个;并且一条命令产出一个自带所需之物的二进制。

路径。

  1. 00 —— mcpp 是什么 —— 五个名词。
  2. 01 —— 快速开始 —— 把程序跑起来。
  3. 05 —— 依赖与解析 —— [dependencies]、锁文件。
  4. 08 —— 测试 —— tests/**/*.cpp
  5. 20 —— 工具链管理 —— 当编译器版本要紧,或者工程必须钉住 一个的时候。
  6. 10 —— 发布打包 —— mcpp pack

跑。 examples/01-hello,然后 02-with-deps,再 03-pack-static

最让人意外的一件事。 debug 构建与 release 构建互不失效。每种配置在 target/ 下有自己的指纹目录,所以在两者之间来回切换不是一次重建。

2. 供他人 import 的库

处境。 别的包会把它写进 [dependencies] 的代码,其中可能有可选的部分。

mcpp 贡献了什么。 模块接口就是被发布的表面;feature 让其中一部分成为可选而 不必拆出第二个包;预建二进制可以声明它与哪些工具链兼容。

路径。

  1. 04 —— mcpp.toml 工程文件指南 —— [lib]、库根。
  2. 06 —— Feature 与能力 —— 可选部分,以及它们 拉取的依赖。
  3. 08 —— 测试 —— [dev-dependencies]
  4. 11 —— 发布一个库 —— 描述符。
  5. 12 —— 分发预编译库 —— 如果同时交付二进制。

跑。 examples/11-features 把三种 feature 形态 都声明了一遍;05-lib-distribution 是 生产方与消费方成对的那个。

最让人意外的一件事。 判断一个可选后端是否真的可选,判据不是「默认构建仍然 能过」,而是「默认构建的解析里不出现那个包」。一个被解析出来却没被用到的依赖, 仍然要付下载的代价。

3. 一个仓库里的多个包

处境。 多个包一起开发,彼此按路径依赖。

mcpp 贡献了什么。 一条命令构建或测试整组;成员之间不经注册表就能相互解析; 每个成员保留自己的 manifest 与身份。

路径。

  1. 07 —— 工作空间 —— [workspace]、path 依赖。
  2. 05 —— 依赖与解析 —— path 依赖做什么、不做什么。
  3. 08 —— 测试 —— 扇出。

跑。 examples/04-workspace

最让人意外的一件事。 工作空间的成员不是一个根。任何枚举「每一个包」的工具 都必须说清它指的是两者中的哪一个,而答案会改变构建什么。

4. 图形应用

处境。 一个带窗口、渲染器与字体的桌面程序。

mcpp 贡献了什么。 窗口与渲染栈就是普通依赖;模板脚手架出一个能跑的工程;产物 在运行期需要什么是被声明的,不是被发现的。

路径。

  1. 01 —— 快速开始 —— mcpp new --template
  2. 05 —— 依赖与解析 —— 那套栈。
  3. 10 —— 发布打包 —— 可执行文件旁边还要带什么。

跑。 mcpp new myapp --template ocornut.imgui

最让人意外的一件事。 在 Linux 上,mcpp 的产物跑在一个不查 /usr/lib 的 私有加载器后面。任何必须由宿主供给的东西 —— 图形驱动、Vulkan ICD —— 都经由工程 声明的适配包到达,而不是靠它装在机器上。

5. 为另一个操作系统构建

处境。 一份源码树要产出 Linux、Windows 与 macOS 的二进制。

mcpp 贡献了什么。 目标是一个参数,不是第二份检出;交叉工具链是载荷;而这台 宿主服务不了的目标会被拒绝,不会被悄悄按宿主构建。

路径。

  1. 21 —— 目标三元组 —— 目标怎么命名,哪台宿主服务哪个。
  2. 24 —— 基于 openkal 的交叉构建 —— 机制。
  3. 22 —— 目标侧 —— manifest 必须按目标不同时。

跑。 examples/06-openkal-cross —— 一个 程序在任意宿主上为四个目标构建。

最让人意外的一件事。 --target 不要求机器上已经有那条工具链。它要求的是 这个目标能被这台宿主服务;21 里的支持矩阵说明哪些 可以。

6. 没有操作系统的目标

处境。 板子或单片机上的固件:没有 OS、默认没有 libc、有链接脚本与向量表。

mcpp 贡献了什么。 板级支持包供给整个目标世界 —— 链接脚本、启动代码,以及 runner —— 于是 mcpp run 在模拟器上与在真实硬件上是同一条命令。

路径。

  1. 40 —— 裸机与 freestanding 目标 —— 目标、档位、std 还剩什么。
  2. 41 —— 抵达一台设备 —— runner、具名 runner。
  3. 08 —— 测试 —— 跑在板子上的测试。

跑。 mcpp new blinky --template riscv-virt-rt

最让人意外的一件事。 模拟器与真实板子相差的是一个 feature,不是两个包。 mcpp run --features hardware 移动的是默认 runner;开发者敲的那条命令不变。

7. GPU 或加速器上的计算

处境。 程序的一部分是由厂商编译器编译、再链接进普通二进制的 kernel。

mcpp 贡献了什么。 设备工具包由规则包声明、由构建安装;加速器是一条只写一次 的轴;产物记录下它携带了哪些设备的代码。

路径。

  1. 42 —— 异构硬件构建 —— accel、岛、接缝。
  2. 30 —— 构建程序 —— 规则怎样到达图。
  3. 06 —— Feature 与能力 —— 选中一条 lane 的 那个 feature。

跑。examples/09-heterogeneous/boundary —— 它不需要设备 —— 再 …/cuda

最让人意外的一件事。 不点名加速器的构建一个字节都不下载。多 GB 的工具包 被取之前要开两道闸:选中规则的那个 feature,以及说明「这次构建确实为设备编译」的 cfg(accelerator = …) 选择器。

8. 图形渲染

处境。 编译到 SPIR-V 的着色器、一条管线,以及必须正确的像素。

mcpp 贡献了什么。 着色器编译器是被声明的载荷;编译好的着色器以模块到达, 而不是一个没人写过其名字的生成头;并且渲染结果可以在没有 GPU 的情况下被断言。

路径。

  1. 42 —— 异构硬件构建 —— 着色器那条 lane。
  2. 30 —— 构建程序 —— 要模块表面的那一行。
  3. 10 —— 发布打包 —— 交付它。

跑。 examples/10-graphics/offscreen —— 离屏渲染一个三角形,并与软件光栅器逐像素比对。

最让人意外的一件事。 软件设备不自动等价于硬件的替身。框架可能因为设备的类型 就拒绝它,哪怕它满足框架要求的每一项;那是框架自己的策略,不是打包缺陷。

9. 工程需要的一步构建工作

处境。 代码生成、嵌入资源、一项检查,或者第二个编译器 —— 引擎没有规则的东西。

mcpp 贡献了什么。 这一步变成与其余一切同一张图上的边:被定序、进指纹、可增量, 失败时按自己的名字被报出。它不是一个构建前脚本。

路径。

  1. 30 —— 构建程序 —— mcpp::action、四种 role。
  2. 31 —— 编写规则包 —— 如果别的工程也该用上它。
  3. 23 —— 项目环境 —— 声明这一步要跑的工具。

跑。 examples/08-build-rules 是做检查与 嵌入的规则;12-a-new-device-language 教会 mcpp 一门引擎从未听说过的语言。

最让人意外的一件事。 这一步调用的那个工具本身是它的输入。少了这一条,改动 生成器会让每条边都是干净的,产物保留上一个生成器产生的字节 —— 一次覆盖在陈旧结果 之上的绿色构建。

10. 为别人打包一个工具、一个驱动或一块板子

处境。 别的工程应当能够声明并得到的东西:一个编译器、一个着色器编译器、一个 模拟器、一个宿主图形驱动、一块板子。

mcpp 贡献了什么。 消费者按名字声明它就能得到一个能用的程序 —— 载荷被安装、它的 库进了产物的搜索路径,而档位决定「一次从不运行的构建要不要为它付代价」。

路径。

  1. 32 —— 编写一个载荷 —— 由 mcpp 安装的工具或预编译库。
  2. 33 —— 编写运行时适配包 —— 当那个库属于宿主、 不可再分发时。
  3. 34 —— 编写板级支持包 —— 一块板子、它的内存布局,以及 抵达它的方式。
  4. 31 —— 编写规则包 —— 如果有一步构建工作要驱动 这个工具。

跑。 描述符本身:载荷看 xim-pkgindex/pkgs/g/glslang.lua,适配包看 mcpp-index/pkgs/c/compat.vulkan-runtime.lua,板子看 mcpplibs/cortex-m-rt

最让人意外的一件事。 该用哪个答案,由许可证与 ABI 决定,不由偏好决定。 用户态与内核模块处于锁步、且许可证禁止再分发的驱动不能是载荷;它是宿主能力, 而适配包是产物够到它的方式。开源驱动就是载荷,用着它的机器完全不需要适配包。

当前边界

  • 这里列出的场景,都是背后有可运行的工程或已发布模板的那些。mcpp 服务得了、 但本仓库没有任何东西演示的场景不在此列 —— 一条没有工程可跑的路径是一个主张, 不是一个场景。
  • 在既有构建系统内部采用 mcpp 不是这里的场景。mcpp 构建它自己拥有的工程;与另一个 构建系统的产物互操作既无文档也无示例覆盖。