Skip to content

Commit 6367a68

Browse files
0.1.0 —— C++ 运行时上到 openkal,连同编译器自己的运行时和裸机的展开约定 (#1)
* openkal-llvm-runtime 0.1.0:C++ 运行时在 openkal 之上 libc++、libc++abi、libunwind,为 openkal-musl 配置,而不是为某个宿主 C 库。 一份 C++ 标准库不像程序那样可移植:它是为某一个 C 库配置、并对着那个库的头 编译的,而「能找到头」和「为这个目标配置过」不是一回事。 vendored 的是四个 runtimes 子树,revision 与工具链自身构建所用的一致; 编译器和链接器不 vendored、不改 —— 它们按三元组生成代码,而 openkal 不改变 任何架构或目标格式。 配置只决定两位: _LIBCPP_HAS_MUSL_LIBC 1 底下的 C 库是 musl 的 _LIBCPP_HAS_RANDOM_DEVICE 0 openkal 没有熵源 第一位是实测出来的:置 0(工具链自带的值)时,一个 include <vector> 的翻译 单元报 20 个错,头一个点名原因「unknown rune table for this platform」;置 1 则一个不报。 判据:examples/cxx 五项断言,其中两项是这个包的全部理由 —— 异常跨三层栈帧 抛出并接住,以及栈展开时析构函数运行。其余的,一个链接进去但从没工作过的 运行时同样满足。examples/import-std 断言另一半:import std 本身。 ⚠️ 这不是预防性措辞。写这个包的过程中,示例打印完第一行就 libc++abi: terminating due to uncaught exception 而 _Unwind_Backtrace 走 0 帧,同时编译、链接、以及所有不抛的路径全绿。 真因在两层之下:openkal-musl 替换掉的 __libc_start_main 不读辅助向量,于是 dl_iterate_phdr 报了一个「没有程序头」的对象,unwinder 在那里找 PT_GNU_EH_FRAME,断定这个程序没有帧描述,而不是断定它没被告知。 一个只被构建过的包会把那个发出去。 * docs: README —— rebase 的冲突解决把它清空了 * feat: 为没有操作系统的机器构建 C++ 运行时 libc++ / libc++abi / libunwind 现在也为 riscv64-none-elf 建得出来。实测: 1431 个对象,ELF 64-bit LSB relocatable UCB RISC-V,__cxa_throw 与 __cxa_begin_catch 有定义。 llvm-generated/ 变成一个配置一个目录 —— 那正是 musl-generated/ 已有的形状, 理由相同:它们是 configure 产物,而一个没有 configure 步骤的包把它们提交进来。 freestanding 与 generic 的差别只有三位加两个开关: 线程 hosted 目标下 libc++ 自己认出系统并找到 pthread;不被认出的系统上 它停在 "No thread API" 而不是猜 —— 正确,因为不猜正是 configure 存在的理由。所以 freestanding 把它写出来。 文件系统 关掉,并且实现它的源文件随之不编 —— 与 random.cpp 同一条规则, 也是 libc++ 自己的构建用同一个开关做的事。 终端 关掉。 dladdr 关掉:没有动态加载器,它接口里那个类型不存在。 _GNU_SOURCE libc++abi 为线程标识去够 syscall,而 musl 只在这个宏下声明 那个名字。LLVM 自己的 runtimes 构建出于同样理由定义它 —— 而宿主构建从别处拿到了它,这个差别直到这个目标来问才可见。 ⚠️ 一并暴露的一处不完整:__assertion_handler 也是 configure 产物,而宿主那次 构建悄悄用了工具链载荷里的那份。现在它在 llvm-generated/ 里(与模板逐字相同, 所以是收进来而不是改写)。裸机这一试才让它现形 —— 宿主上它一直是绿的。 ⚠️ import std 在这种目标上仍被拒绝,而拒绝它的不是这个包: error: `import std;` is not available on 'riscv64-none-elf' --- a freestanding target has no hosted standard library. 那句话陈述的前提,这个包让它不成立了。解除它是构建工具的改动 —— 它问的是 「目标是不是 freestanding」,而该问的是「hosted 标准库在不在」。 * feat: 声明 hosted-standard-library 构建工具在 configure 期拒绝没有操作系统的目标上的 import std,理由是「那种目标 没有 hosted 标准库」—— 而这个包正是一份。这件事是依赖图的性质,不是三元组的 性质,所以在这里声明、在那里读。 配套改动:mcpp-community/mcpp#486。 * feat: 声明自己的 std 模块源 构建工具否则会向编译器问 std.cppm 在哪,而这一份是这个包为一个编译器毫不知情的 目标配置出来的:它的 __config_site 在 llvm-generated/,它的片段在 llvm/libcxx/modules/std/。 三个 flag 都是实测逼出来的,不是预防性的: --no-default-config 载荷的 clang++.cfg 无条件加一个宿主 C 库的头, 模块于是编那个库的 <wchar.h> 并停在它指望宿主编译器 提供的名字上 -nostdinc/-nostdinc++ 同上 -D_GNU_SOURCE libc++ 的 locale 层去够 musl 只在这个宏下声明的名字 (vasprintf、strtof_l 等),LLVM 自己的 runtimes 构建 出于同样理由定义它 -I llvm/libcxx/modules 模块源按相对名 include 九十来个片段,它们是上游的、 未改动,所以留在上游放的地方,由搜索路径点名那个目录 配套:mcpp-community/mcpp#486。 * feat: 编译器自己的运行时,裸机的展开约定,以及那个不会假绿的判据 ## compiler-rt 早就 vendored,只是没被构建 宿主目标链接工具链的 libclang_rt.builtins,没人注意到它存在。这个目标没有那份 归档可链,而它要的东西并不冷僻:这个架构上 long double 是 IEEE binary128 而且 没有硬件,于是 musl 的每一个 long double 函数都调用一个编译器发出调用、却不 定义的软浮点例程。 实测:C 库自己的链接错误清干净之后,二十个未定义名字,全是 __addtf3、__letf2、 __fixtfdi、__udivti3 这种形状。⚠️ 它们**一个都不出现在本仓库的任何源码里** —— 它们是编译器决定要调的,所以读源码永远找不到它们,而第一份证据是一次链接。 选择用的是 compiler-rt 自己的:它的 CMakeLists 为这个架构列出 GENERIC_SOURCES 与 GENERIC_TF_SOURCES 共 146 个文件,清单里排除的正好是目录里剩下的部分 —— 取自那份列表,而不是猜哪些能编过。 ## 裸机的展开约定走符号,不走程序头 _LIBUNWIND_IS_BAREMETAL:unwinder 通过链接脚本定义的符号找它的表,而不是通过 程序头。两条路上游都有,而这个目标必须走第二条 —— 走程序头要 __ehdr_start, 那要求 ELF 头落在已加载段里,那要求它在最低加载地址上,而固件跳的就是最低加载 地址。实测:镜像链接成功,入口移到 0x80200270,OpenSBI 仍然宣告 `Next Address 0x80200000`,机器停在把 \x7fELF 当指令执行上。 --eh-frame-hdr 也归这个包:选了裸机 unwinder 的包才知道那个节是被需要的。 没有它两个 _hdr_ 符号都是 0,libunwind 读成「没有索引」,于是每一帧都从头线性 扫 .eh_frame —— 一个保持正确性的减速,而**没有任何东西会报告它**。 ## examples/baremetal —— 判据本身 这上面每一步都跑在宿主上,而宿主本来就装着 C 库、C++ 运行时和 unwinder。 一个不小心够到了它们的程序照样能跑 —— 所以那些步骤可以在**根本没用到本包**的 情况下通过。 这里没有东西可以够到。C 库是 openkal-musl,标准库和 unwinder 是本包的,底下是 一个全部接口就是 ecall 的固件。三条断言各要一层:容器与算法要分配器,格式化与 输出要流,throw/catch **加上展开期跑掉的析构函数**要 unwinder 与 libc++abi —— 最后那个是「unwinder 能用」与「unwinder 只是链上了」的分界。 sorted: 2 4 7 caught: 42 unwound: true baremetal import std: ok * ci: 裸机那一步要的四个决定还没发布,所以从分支把工具建出来 这一步需要四个还没有任何已发布 mcpp 做出的决定,而它们都属于工具而不是本包: import std 的门问「有没有包为这个目标提供标准库」而不是「目标是不是 freestanding」;包可以带自己的 std 模块源;图里有为目标编译的 C++ 运行时时 -fno-exceptions/-fno-rtti/-ffreestanding 要摘掉;以及展开表要打开 —— 编译器为这类目标默认关掉它,而一套不完整的展开表不会降级,它会让走栈停住。 都在 mcpp-community/mcpp#486 上。在它发布之前,这个 job 用和这里每一个依赖 同样的方式把工具拿过来 —— 从分支 —— 这样下面那条判据是**真的在被执行**, 而不是一句「在某台笔记本上验过一次」的注释。 ⇒ #486 发布后,删掉这一步并抬高 MCPP_VERSION。 * ci: 克隆带过来的 workspace pin 指向索引里已经没有的版本 xlings: version '2026.8.17.1' not found for 'mcpp' available: 2026.8.19.4 仓库根的 .xlings.json 决定那棵树里的构建用哪个 mcpp,而 mcpp 自己的 bootstrap pin 不随发布移动 —— 它是上次动这个文件时的当前版本。把分支克隆过来,就把一个 只在那个仓库自己的 CI 里成立的 pin 一起带了过来。 改写成本 job 已经装好的那个版本,两边就一致了。它不改变被测的东西:pin 选的是 **构建 mcpp 的**工具,而被测的是构建出来的那个 mcpp。 * fix: 本机绝对路径又一次被提交进清单,而这次 CI 在「运行」那一步才说 程序建出来了(text 2494992,和本机一致),失败在运行:runner 指向 /home/speak/.mcpp/registry/... —— 一台机器上的绝对路径进了每台机器都读的文件。 ⚠️ 这是本生态里第二次,第一次在 conformance/mcpp.toml,两次的显形方式都一样: 别的仓库的 CI 挂在一条只存在于一台笔记本上的路径上。成因也一样:本机要跑就得 把名字换成装好的模拟器,而最顺手的做法就是改这一行。 清单改回裸名,并在旁边写下为什么它必须保持裸名。CI 那一步加了一条守卫:先断言 清单里还是裸名,再替换 —— 于是一个已经带着路径的 checkout 会**被告知**,而不是 得到一个路径套路径。 * examples: 一份源码,两台机器,中间什么都没改 原来这个目录叫 baremetal 并且 [build] target 钉死在 riscv64-none-elf —— 那让它 成了一个「裸机的例子」,而不是设计文档那条主张的**演示**。 主张是:openkal 之上的程序,构建时不关心底下是哪个实现。所以现在: mcpp run 这台机器,openkal-linux 之上 mcpp run --target riscv64-none-elf riscv64,OpenSBI 之上,没有操作系统 同一个 src/main.cpp,没有 #if,没有第二个目录,两边打印同样的四行。 唯一不同的是内存布局,而 build.mcpp 把它放在一个对 target_os 的条件后面 —— 因为那是一句关于**机器**的陈述,不是关于程序的。 CI 两步:第二步跑宿主那条,并且 两边的四行 —— 断言的是「输出相同」而不是 「两边都有输出」。 已验证两个方向都通过。目录改名为 same-source,因为它现在说的是这件事。 * ci: 自建工具那一步用 --dev,并把 job 上限抬到 90 分钟 被测的是工具对编译 flag 做出的一组决定,优化级别改变不了其中任何一条。实测: release 自建在双核 runner 上花掉了六十分钟里的半个多小时 —— 预算的大头花在了 测试观察不到的东西上。 ⚠️ 两处都是临时的:#486 发布后,那一步删掉,这里也跟着回去。 * feat(port): 差异放一个目录 —— libc++ 按 OS 宏选后端,而 openkal 按「配置的是哪个 C 库」 ⭐ 形态先说:`port/include` 是**覆盖目录**,不是对 vendored 树的修改。 openkal-musl 的 `port/` 把与上游 musl 的每一处差异收在一个目录里、靠 include 顺序遮蔽它;这里是 libc++ 的同一套安排 —— vendored 树与上游逐字节相同, `git diff` 对一份新 checkout 为空,而全部差异就是 port/include 下的这几个文件。 ## locale 后端 upstream 的选择链问的是「这是哪个操作系统」,并在每个答案上假定那个系统的 C 库: #if defined(__APPLE__) → support/apple.h #elif defined(__linux__) → support/linux.h 这在 libc++ 正常被构建的每个地方都成立,因为 OS 和它的 C 库是一起来的。 ⚠️ 在这里它们不是一起来的。openkal 的安排是 C 库是一个**包**,而下面的平台是一个 48 个函数的接口的实现。为 Apple 目标格式构建的程序定义了 `__APPLE__`,因为那是 关于**格式和 ABI** 的陈述 —— 而底下是 musl。upstream 的第一问于是对着错的问题 给出了正确答案: bsd_like.h:203: no member named 'asprintf_l' in the global namespace ⚠️ 这条**不能**用 `__config_site` 表达,而那是先试的:libc++ 那条链是写死的 `#if defined(__APPLE__)`,没有覆盖点;唯一相关的旋钮 `_LIBCPP_HAS_LOCALIZATION 0` 是**整个去掉 `<locale>`**,不是换后端。砍掉一个能用的设施去绕过一个口味问题, 比遮蔽一个头文件更差。 ## 三个 Apple SDK 桩 libunwind 与 libc++ 的源码在 `__APPLE__` 下 include Apple SDK 的头。整棵树里 一共 5 处、4 个头 —— 数出来的,不是估的。桩里只有**被读到**的那些名字,和 openkal-macos 那份只有两个名字的 `libSystem.tbd` 同一种做法。 ⚠️ `mach-o/dyld.h` 不是编译期的桩:refstring 与 UnwindCursor 在**运行期**调它。 openkal 没有动态加载器,一个这样构建的程序就是一个镜像,没有东西可枚举 —— 所以 诚实的答案是零个镜像,而两个调用者本来就处理这个情况。⚠️ 答零个和让符号未定义 不是一回事:后者是一个从没想要加载器的程序链接失败在 Apple 的加载器上。 ## std.compat `[package] std-compat-module`:提供一个模块的包提供两个。理由见 mcpp#486。 ⚠️ 未完成:libc++abi 的 guard 实现(`mach_port_t` / `syscall`)与 libc++ 的 locale 后端(`vasprintf` / `strtof_l`)各自按平台宏选实现,而「Mach-O 上的 musl」 两份都不是。CI 不跑这条,所以没有回归面。 * fix(port): 判据是「哪个 C 库」,不是「哪个 C 库,在 Apple 上」 覆盖里原来写的是 `_LIBCPP_HAS_MUSL_LIBC && defined(__APPLE__)`,因为 Apple 是 第一个暴露它的目标。实测 2026-08-23 的第二个:x86_64-windows-gnu 在 openkal 上走 _LIBCPP_MSVCRT_LIKE → support/windows.h,停在 `_locale_t` —— 那是微软的 C 运行时, 而这个程序的 C 库是 musl。同一个形状,第二种目标格式。 ⇒ 把规则收窄到一个平台,就意味着每个平台再写一遍。upstream 问的是「底下是哪个 C 库」;这里回答它,于是每一个答案是 musl 的目标都到达同一个后端 —— 而在 ELF 上 那本来就是它到达的那个。 * feat(port): C++ 运行时不再关心后端是谁 —— macOS 交叉构建打通 ⭐⭐ 在 Linux 上,`mcpp build --target aarch64-macos` 现在产出: Mach-O 64-bit arm64 executable /usr/lib/libSystem.B.dylib ← 唯一依赖 _clock_gettime_nsec_np ← 借的名字,仍然是那两个 _pthread_create_from_mach_thread dyld_stub_binder ← 第三个属于格式,不属于本包 带着 import std、容器、算法、异常与展开期析构 —— 全部来自 openkal 生态, 没有一个字节来自 Apple 的 SDK。 ## 一个谓词,而不是每个平台一遍 `_LIBCPP_HAS_MUSL_LIBC` 现在是 locale 后端的第一问。⚠️ 第一版写成 「musl **且在 Apple 上**」,第二个目标 Windows 立刻以同样形状失败(`_locale_t`) —— 收窄到一个平台就意味着每个平台再写一遍。 ## 三条搬出了「按目标」的块,因为它们是关于 openkal 的事实 - `_LIBUNWIND_USE_DLADDR=0` —— openkal 在**任何**目标上都没有动态加载器。 ⚠️ 它原来在 cfg(os="none") 里,macOS 目标于是以 `unknown type name 'Dl_info'` 重新发现了同一件事。 - `_GNU_SOURCE` —— musl 的非标准名字住在它后面(vasprintf/strtof_l/syscall)。 同样的搬迁,同样的理由。 - compiler-rt builtins —— ⚠️ 这条**不能**搬成包级:宿主链接里驱动仍然链载荷自己的 归档,实测重复定义 __muloti4。改为按目标格式各一份,并记下清单表达不了 「驱动的运行时选择被替换过」这件事。 ## 覆盖目录里的新增 `port/include/__thread/support.h` —— libc++abi 的 guard 问 `__APPLE__` 要 Mach 的 线程标识。⚠️ 三个分支里只有第一个不适合 openkal,而它正是命中的那个;第二个 (SYS_gettid)会经 musl 的系统调用垫片走到 kal_task_*,第三个是合法答案。 ⚠️ 而它关不掉:_LIBCPP_HAS_THREAD_API_PTHREAD 是我们的,清掉它是为了绕开一个 标识函数而拿掉整个线程层。 `mach-o/dyld.h` 加上卸载钩子 —— 这里没有东西会被卸载。 ## Mach-O 的 thread_local 走模拟 TLS ⚠️ `undefined symbol: _tlv_bootstrap`:这个格式经加载器 bootstrap 的描述符访问 thread_local,而这里没有加载器。`-femulated-tls` 让每次访问改走 `__emutls_get_address`。⭐ 机制不是新的 —— 生态设计的实验 A 验证过这条路 (32 项断言 0 failures),而那次也记下了这个 flag 是 LLVM 专有的, 这正是它能写在这里的原因:这个目标的编译器按构造就是 clang。 ⚠️ 而 `emutls.c` 要从排除表里拿掉,并且**顺序不决定这件事** —— 列表里任何位置的 排除都压过任何位置的包含。实测:加了包含而排除还在,产物没有那个对象。 * feat(port): 撤回 libc++ 从 _WIN32 draws 出来的那个结论 libc++ 的 __config 在 `#if defined(_WIN32)` 里写着: // Both MinGW and native MSVC provide a "MSVC"-like environment #define _LIBCPP_MSVCRT_LIKE 对它见过的两种 Windows 环境都成立。对这一种不成立:`_WIN32` 是关于**目标格式和 调用约定**的陈述,而底下的 C 库是 musl —— 和 ELF 上、Mach-O 上同一个 musl。 ⭐ 为什么在 __config 而不在 __config_site:__config_site 是构建陈述**答案**的 地方,这个包生成一份(_LIBCPP_HAS_MUSL_LIBC、线程 API、文件系统开关都在那里)。 而这条不是 libc++ 问的问题,是它自己**推**出来的结论 —— 在我们的答案被读到之前。 ⚠️ 实测 x86_64-windows-gnu 交叉: fstream:1004: use of undeclared identifier '_ftelli64' fstream:741: use of undeclared identifier '_wfopen' ⚠️ 三个名字要一起撤,不是一个:_LIBCPP_MSVCRT_LIKE 选 C 运行时, _LIBCPP_WIN32API 选操作系统 API,而这个目标下面两者都不是那个。只撤第一个会让 libc++ 一边调 fopen 一边去够 CreateFileW。 ⚠️ 而**从结论里再推出来的那个也要撤**:_LIBCPP_HAS_OPEN_WITH_WCHAR 在同一个 _WIN32 块里被 `#define` 成一个**值**,撤掉上面两个名字它仍然是 1,`<fstream>` 仍然去够 _wfopen。实测:撤前两个只消掉了 _ftelli64。 已验证无回归:same-source 宿主 ✅;macOS 交叉仍产出 Mach-O arm64 ✅。 * feat(port): PE 上的异常机制跟随我们带的 unwinder clang 面向这个三元组会定义 __SEH__,因为那是 mingw 在这个架构上用的东西 —— 而 libunwind 自己的公开头于是去够 <windows.h> 和 <ntverp.h>: unwind.h:22 → …/mingw32/include/windows.h → crtdefs.h → corecrt.h:98 typedef redefinition ⚠️ 和这个目标上其它每一条失败同一类:一个平台宏被读成了「底下是什么」的陈述。 这里答案是一个 flag 而不是一份覆盖,因为问题确实是一个构建决定:这个程序的 unwinder 就是本包里的这个,而它读 DWARF 表 —— 和它在 ELF 上、Mach-O 上读的 是同一批。 ⚠️ 它必须到达图里每一个翻译单元(docs/13 记着 -fno-exceptions 的同一条理由: 模型记在 BMI 里)。写在这里覆盖本包;消费者也要写一遍,而由 capability 决定 才是能消掉这份重复的形状。 ⚠️ 我第一次把它写在了 block header **之前**,于是它落进了上一个块 —— 实测 compile_commands 里根本没有这个 flag,而报错一字未变。 * feat(port): 平台相关的换成 openkal 接口 —— 立规矩,并做掉 std::atomic 的等待 ⭐ 规矩三条,写在 llvm/PATCHES.md 里,与 openkal-musl 的一致: 1. **可以动源码。** 移植就是动源码;假装不动只会把差异藏进别处。 2. **动过的地方要标注清楚。** 每一处夹在 `// ─── openkal ─── BEGIN/END` 之间, `grep -rn "openkal ─── BEGIN" llvm/` 一次数完。 3. **能不动的就不动。** 上游能自己走对的路,让它走。 判据:换的是「平台」不是「库」。每一处替换必须能填进这句话 ——「upstream 在这里 问『这是哪个 OS』,而这个问题真正的答案是 openkal 的 <接口>」。⚠️ 填不进去的不要 动:sizeof(long)、int64_t 的拼法、目标格式不是「下面是谁」,是目标自己的定义。 ## 已换:std::atomic 的等待与唤醒 上游一条链,五个分支,四个操作系统(SYS_futex / _umtx_op / futex / WaitOnAddress / 完全不等待)。openkal 的答案是 kal_task_wait / kal_task_wake —— 规范管它叫挂起 原语,而它在每一个目标上是同样的两个调用。 平台面**恰好两个函数**,其余 495 行全可移植 ⇒ 原地打标记的补丁,漂移面从 495 行 缩到约 50 行,而不是整文件拷贝。 ⚠️ 它本来就已经到 openkal 了,只是绕了一圈:Linux 上发 SYS_futex,musl 的 port 拦下来,__okm_futex 调 kal_task_wait。直接走去掉那一圈,并让另外两种目标格式也 能用 —— 在那里没有系统调用可拦。 ## 三处配套,而每一处都是「同一个事实的第二个说法」 - port/include/__atomic/contention_t.h —— 竞争计数器的宽度跟随挂起原语(4 字节) - port/include/__atomic/atomic_waitable_traits.h —— ⚠️ **只改前者不够**:开了 _LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE 之后实例化清单来自这个宏而不是 sizeof(__cxx_contention_t)。两个头陈述一个事实,改了读者先找到的那个,报错一字 不变。(这是本移植第二次遇到「一个事实走两条通道」,链接线是第一次。) - OPENKAL_HAS_TASK —— ⚠️ 只提供 core 的实现没有挂起原语,实测裸机链接停在 undefined symbol: kal_task_wait。那是 6.1 在工作,不是缺陷;答案是落回上游那条 本来就正确的分支(单执行上下文的机器上 atomic::wait 没有东西可等,轮询是准确的 实现而不是替代品)。⚠️ 这与 openkal-musl 的 OKM_HAS_TASK 是同一个事实,说了 第二遍 —— 因为现在有第二个消费者。 ## PATCHES.md 里比「已换」更重要的一节:不需要动的 整棵树 #include <windows.h> 共 19 处。12 处守在 _LIBCPP_WIN32API 上,已由 port/include/__config 撤回 ⇒ **自己落到 POSIX 分支,而那条本来就在 openkal 上** (它调 fopen/clock_gettime/pthread_*,那些是 musl)。2 处守在 __SEH__ 上,已由 -fdwarf-exceptions 绕开。 ⇒ 这就是为什么整份移植是几十行而不是把 libc++ 重做一遍。**先问「上游有没有一条 路已经通向 openkal」,再考虑换。** 已验证三个目标:宿主 ✅ / 裸机 riscv64 ✅ / macOS 交叉产出 Mach-O arm64 ✅ (外部符号仍是那三个)。 * feat(port): PE 目标打通 —— 展开表、锁、TLS 三处都问了「哪个 OS」 同一份 src/main.cpp 现在从一台 Linux 宿主构建出四个目标,并且两个能在本机跑的 输出逐字相同: x86_64-linux-gnu 静态 ELF ✅ 跑通 x86_64-windows-gnu PE32+ ✅ 跑通(wine 冒烟,⚠️ 不等于 Windows) aarch64-macos Mach-O arm64 ✅ 产出 riscv64-none-elf RISC-V ELF ✅ 产出 sorted: 2 4 7 / caught: 42 / unwound: true / import std over openkal: ok ⭐ unwound: true 是判据 —— 析构函数在展开中跑到了,说明 libunwind 靠自读镜像 找到了 .eh_frame,而不是靠 EnumProcessModules。 ── 三处 <windows.h>,一个形状 ────────────────────────────── ⭐⭐ AddressSpace.hpp 问「这个镜像的展开表在哪」,上游答「让操作系统枚举模块」。 而这份文件已经答过这个问题三遍,没有一遍问 OS:裸机读链接器符号,Darwin 读 _dyld_find_unwind_sections,ELF 读自己的 program headers。openkal 的答案和它们 同一句话 —— 镜像自己知道:__ImageBase 是链接器定义的符号(不是调用),段表在离 它固定的偏移上。 ⚠️ 而 PATCHES.md 原先写着这一支「已由 DWARF 路线绕开」—— 凭读守卫写的,实测 否掉了:_WIN32 && DWARF 正是它的守卫。修好它,同样的错误挪到 UnwindCursor.hpp (一处纯粹没被用到的 include),再挪到 RWMutex.hpp。 ⚠️ RWMutex 里同一个事实说了两遍(include 一处、class 一处),两处一起改。 ⚠️ 走过一条错路并记进台账:先试 COFF 分组段 .eh_frame$a/$z 夹住 .eh_frame, 实测链接器把不带 $ 的段排在最前 ⇒ start 落在数据之后,end-start=1 字节。那不是 链接失败,是静默的错答案。 ── emutls:第三种格式,同一堵墙 ──────────────────────────── PE 的 _tls_index 和 Mach-O 的 _tlv_bootstrap 都由动态加载器 bootstrap,而自包含 的 openkal 镜像没有加载器。macOS 上已经用 -femulated-tls + 编 emutls.c 解过一次; Windows 是它在第三种格式里的同一件事。 ⚠️ emutls.c 自己又问了一次「哪个 OS」,于是被编译到 PE 上的原因(平台的 TLS 用 不了)和它的行为(去要平台的 C 运行时)自相矛盾。走 POSIX 分支。 ── 一个名字,不是五个 ────────────────────────────────── 五处补丁统一守卫在 OPENKAL 上,cflags/cxxflags 各给一次(compiler-rt 是 C)。 ⚠️ 一度写成 _LIBUNWIND_OPENKAL,随后 emutls.c 需要同一个事实 —— 同一个事实两个 名字正是这套代码反复出问题的形状。 ── 另外三处不是「移植」而是「配置」 ──────────────────────── 1. __config_site 的线程 API:四个全写 0 不是「没有线程 API」,是「没人回答」, libc++ 于是按 OS 自选 —— ELF/Mach-O 上碰巧选对 pthread,PE 上选了 WIN32, 报 undefined symbol: std::__1::__libcpp_mutex_lock(void**)(void** 是 Win32 的形状)。⚠️ port/include/__config 撤回 _LIBCPP_WIN32API 修不了它,因为撤回 发生在 __config 已经据此下了结论之后 —— 该文件记录的「结论的结论」第三例。 2. operator new/delete 定义了两遍。libcxx/src/new.cpp 自己写着「以下代码原样 拷贝进 libcxxabi/src/stdlib_new_delete.cpp,本文件这份是权威的」。上游把两者 建成两个库,本包建成一个 ⇒ 同一条链接线上各来一份。 ⚠️ 三个目标看不见:两份都是弱符号,ELF/Mach-O 上重复的弱定义正是「弱」的 含义,链接器挑一个并且不说话。COFF 报了 30 条。⇒ 包级排除,不是 cfg(windows) 排除 —— 第三种格式没有制造这个重复,它只是报告了它。 3. -fdwarf-exceptions / -femulated-tls 从本包 [build] 里撤走,改由 mcpp 全图 推导 —— 见 mcpp 的 graph_runtime_compile_flags。它们决定 throw 和 thread_local 编译成什么,是整张图的性质。写在包里时只覆盖了本包的对象, ⚠️ 实测:全部编过之后链接报 undefined symbol: __gxx_personality_seh0, 引用它的是使用者的 main.o。 ── 例子清单 ─────────────────────────────────────────── examples/same-source 的 [toolchain] default 从 llvm@22.1.8 改成 openkal-llvm@22.1.8。⚠️ 同一个载荷、同一个 clang、同一个版本 —— 差别在 mcpp 据此相信目标侧从哪来。写成 llvm 时四个目标只成两个,而两条报错都没提到工具链族。 * ci: 在 Linux 上构建,在真机上跑 —— 而那两个 job 什么都不装 原先 CI 证明的是「同一份源码不知道自己在哪台机器上」(裸机 + 本机,四行输出 diff 相等)。现在加证「构建也不必在那台机器上」:一台 Linux 宿主产出 PE 和 Mach-O,两个 job 把它们下载下来在真的 Windows 和真的 macOS 上跑。 ⭐⭐ 那两个 job 故意没有任何工具链步骤 —— 不装 mcpp、不装编译器、不装 C 运行时。 程序自带 C 库、C++ 运行时和展开器,剩下的只有它被构建给的那个操作系统。如果哪 天有人因为「程序需要」而往里加一步安装,那一步就是发现,不是修复。 ⚠️ 交叉构建产出一个格式正确的文件,只证明编译器被告知了正确的目标。它不证明程 序能跑 —— 而这套生态在这两个平台上找到的每一处差异(加载器 bootstrap 的 thread-local、展开器找自己的表、人格例程)都是**链接成功、运行时失败**。 判据是 unwound: true —— 析构函数在展开中跑到了,链接骗不出这一行。 两处断言写在运行之前,因为它们的修法不同: · 格式(PE32+ / Mach-O arm64)在构建 job 里断言 —— 失败意味着目标选错了; · ad-hoc 签名在 macOS job 里断言 —— arm64 macOS 拒绝未签名镜像,失败意味着 链接器没签,而不是程序崩了。 ⚠️ 产物上传会丢执行位,所以 chmod 在前。 ── 本机已验(⚠️ wine 不等于 Windows,所以才要上面那个 job)────── x86_64-linux-gnu ELF 跑通 x86_64-windows-gnu PE 跑通(wine) riscv64-none-elf ELF 跑通(qemu + OpenSBI) aarch64-macos Mach-O 产出,LC_CODE_SIGNATURE 在 * ci: 宿主维度 —— 两台不是 Linux 的机器,各自到达全部四个目标 上面所有 job 都在 Linux 上构建。那证明的是「一台宿主能到达每个目标」,而 N×N 矩阵真正要问的另一半没被碰:**宿主重不重要**。方案的答案是不重要 —— 目标侧是 一组包、编译器是可重定向的 clang,所以 N 宿主 × N 目标塌缩成 N 个实现加一个工具。 ⚠️ 那是一个断言,而这个形状的断言在这里错过:Linux 宿主到达 PE 之前需要四处 分别的修复,每一处在真正跑一次构建之前都看不见。两台宿主的代价是两个 job;不跑 就断言塌缩成立的代价是一段话,而它什么都不证明。 每台宿主构建全部四个目标,并**运行它自己是的那一个** —— 与 Linux job 对自己用的 是同一条判据。 ⚠️ 写这个 job 时预测到并已在 mcpp 侧修掉一处真缺陷:链接行的三支是按宿主分的, 而只有 Linux 那一支消费 --target=。见 mcpp#486 的对应提交。 * fix(windows): 栈探针从 compiler-rt 取,它是 .S 所以被 *.c 的 glob 漏掉了 编译器在足够大的帧之前发 ___chkstk_ms 的调用,而在这个格式上那是**编译器运行时** 的例程,不是 C 库的。compiler-rt 有它,在架构自己的目录里:x86_64/chkstk.S。 ⚠️ 实测 2026-08-22,openkal-musl 那侧把 -lgcc 从这个格式的链接线上拿掉之后 —— 那个归档是 GCC 的,它一直在悄悄供给这个符号给一条编译器是 clang 的链接: ld.lld: error: undefined symbol: ___chkstk_ms ⚠️ 只取这一个文件而不是整个目录:x86_64/ 里还有 floatdidf.c 等,上面的通用列表 已经供给了它们,整目录会让每个都定义两遍。 * fix(windows): x87 的 long double 例程被一条从 macOS 抄来的排除挡掉了 ld.lld: error: undefined symbol: __mulxc3 *xf*.c 和 *xc3.c 是 x87 80 位 long double 的例程。在 Apple 的 arm64 上 long double 就是 double,没有东西能调用它们,编了是死重量 —— 那个块排除它们是对的。 而在 x86_64-w64-windows-gnu 上 long double **就是** x87 80 位,调用是真的 (libc++ 的 <complex> 发出来的)。两行是从 macOS 块整份抄过来的。 GCC 的归档一直在供给它,而排除项让 compiler-rt 供给不了。-lgcc 拿掉之后现形。 ⚠️ 一处方法教训:第一次改的时候我按行号定位,而断言通过了 —— 因为 cfg(os = "none") 块里碰巧有一模一样的两行。**按位置的断言匹配到了错误的那一份**, 于是我从裸机块里删掉了正确的排除,同时把 Windows 那两条留在原处。改成按块定位。 ── 从全清缓存复验(rm -rf ~/.mcpp/git/*)──────────────── x86_64-linux-gnu ELF 跑通 x86_64-windows-gnu PE32+ 跑通(wine),unwound: true aarch64-macos Mach-O 产出 riscv64-none-elf ELF 跑通(qemu + OpenSBI) ⭐ 而这一轮的意义不只是绿:Windows 那条链接线现在**不引用宿主的 mingw 任何东西** —— 导入库由 openkal-windows 从自己的 .def 生成,builtins / emutls / 栈探针由 compiler-rt 供给,__main 由 openkal-musl 的 port 供给。 * ci: 宿主维度少了 toolchain install;以及让 macOS 上的崩溃当场给出回溯 ⭐⭐ 而这一轮 CI 已经证明了它存在的理由: the artefact built on Linux runs on Windows ✅ pass the artefact built on Linux runs on macOS ✗ Segmentation fault: 11 在 Linux 上构建的 Mach-O 链接成功、ad-hoc 签名合法、在**真机**上崩。这是这套栈 第一次在这个系统上真的跑 —— 而 R6 写的就是「平台实现的 stub 与真实系统不一致, 只有真机能验」。 ⚠️ 有意思的失败在外面看起来都一样(入口对内核交给它什么的假设、线程指针、借来的 两个名字),所以崩溃时当场跑一次 lldb 打回溯、otool -L 打依赖、LC_MAIN 打入口 —— 一个能打出回溯的 CI 轮次抵得上好几个打不出的。 ── 另一条 ───────────────────────────────────────── 两个 host-dimension job 报 `llvm@22.1.8 is not installed`:toolchain default 只是 点名,不会去取。补 install。 * ci: 跳到 0 的时候要问的是 lr,不是 bt stop reason = EXC_BAD_ACCESS (code=1, address=0x0) frame #0: 0x0000000000000000 ⚠️ bt 只能说出「PC 是 0」,那是把症状重述一遍 —— 跳到地址 0 没有留下可展开的帧。 而链接寄存器里还是发出那次调用的人的返回地址,image lookup 能把它变成名字。 本机已排除的: · LC_MAIN entryoff 124032 = 0x1e480,正是 _okm_start(不是入口错); · __init_offsets 的十七项里前十个是 openkal 的模块初始化器,各一条 ret(合法); · __init_array_start == __init_array_end,__libc_start_init 的循环不跑; · _init / _fini 各一条 ret; · 未定义符号只有三个,没有弱未定义。 ⇒ 剩下的是「谁调用了 0」,那要 lr。顺带跑一次 DYLD_PRINT_INITIALIZERS 看加载器 走到哪一步。 * ci: lldb 的 -o 在第一个错误后就不往下走了 —— 崩溃诊断要用 -k 上一轮加的三条命令(register read / image lookup $lr / bt all)一条都没执行: --batch 模式下 lldb 在第一个报错的 -o 之后放弃余下的,而在 PC=0 处读寄存器就是 报错。-k 是「进程崩溃时执行」的那一组,正对这个场景。 ⚠️ 同时把 DYLD_PRINT_INITIALIZERS 的输出写进文件再读:管进 tail 会和 shell 自己 对信号的报告交错,而最后几行 —— 说明当时在跑哪个初始化器的那几行 —— 正是被冲掉 的那些。 * fix: -nostdinc —— 这个包不该从构建它的那台机器上拿到任何头文件 libcxx/src/chrono.cpp:59 → …/MacOSX.sdk/usr/include/mach/mach_time.h:55: error: unknown type name '__MAC_10_10' (× 19) ⚠️ 这个 flag 一直只在 std-module-flags 上,包自己的源码编译没有它。在 Linux 上无害 (宿主没有 mach/ 头,C 库的头从 -I 来);在 macOS 上 SDK 就在手边。 chrono.cpp 用 __has_include 守卫那个 include —— 而那是**一个关于机器的问题**。 Linux 上答案是否,文件编过;macOS 上 SDK 在那里,答案是是,而头文件到来时它自己的 SDK 本该提供的前提没有到位。⇒ 那个 include 对 libc++ 是可选的、这次构建走的路径也 不用它;缺陷在于这个问题**能被问出来**。 本包在 include_dirs 里陈述了它需要的每一个头;编译器自己找到的任何东西都是「正在 构建它的那个系统」的头。 从全清缓存复验四个目标:linux / windows(wine)/ riscv64(qemu)三个跑通并输出 逐字相同,aarch64-macos 产出 Mach-O。 * feat(linux): compiler-rt 的 builtins 也为这个目标编 —— 它是最后一个还在借的 macOS / Windows / 裸机都从本包的 compiler-rt 取「编译器发出调用而 C 库不定义」的 那些例程。Linux 不:openkal-musl 点名 -lgcc,而在 Linux 宿主上那会解析到一个碰巧 装着的载荷。 ⚠️ macOS 宿主交叉到 x86_64-linux-gnu 时:ld.lld: error: unable to find library -lgcc ⚠️ 与 -lgcc 并存不是重复定义的危险:归档只贡献仍未定义的东西,我们的先链上去, 归档就不会为它们被查询。 * chore: 删掉误提交的 .mcpp/,并补上这个仓唯一缺的那条 .gitignore .mcpp/.xlings.json 是裸机那次工作里的实验残留 —— 它声明 xim:picolibc-riscv,而本包 没有任何地方用它。 ⚠️ 而它能进来的原因是可查的:这套生态里七个仓,**只有这一个**的 .gitignore 没有 .mcpp。补上。 ⭐ 顺手把七个 PR 的改动文件全扫了一遍(对象/归档/日志/构建目录/临时文件),其余六个 干净。 * chore: 第二个误提交的 .mcpp/,以及上一次扫描为什么没看见它 examples/import-std/.mcpp/.xlings.json —— 与根下那个同源的实验残留(同样声明 xim:picolibc-riscv,本包同样没有任何地方用它)。 ⚠️ 上一轮已经做过一次这个检查并报告「六个仓干净」。它漏掉这一个的原因是判据写成了 ^(\.mcpp|target/…) —— **锚定在路径开头**,所以只看得见仓库根下的那一个。 ⇒ 一个检查报告「干净」的时候,要先问它看得见多少。 * refactor(example): 板子的内存布局不再由这个例子陈述 它此前带着一份链接脚本 —— OpenSBI 把控制权交到哪里、多少栈、堆在哪 —— 挂在一个 关于目标的条件后面。那个条件是诚实的部分:它们是关于**一台机器**的陈述,不是关于 这个程序的。 ⭐ 而这恰恰说明它们也不属于这里。openkal-opensbi 是知道那台机器的包,它现在用自己的 构建程序供给这份地图,到达每个使用者的链接线 —— 与它供给 kal_* 定义的方式相同。 于是这个目录所主张的「同一份源码、不同的机器、什么都不用改」对构建文件也成立。 ⚠️ 两份并存时实测(板级事实**可传递**地到达使用者,而这个例子是使用者): ld.lld: error: section .eh_frame file range overlaps with .debug_str_offsets ld.lld: error: section .debug_str file range overlaps with .eh_frame_hdr 两份脚本都被应用了,而诊断一个字都没提「有两份」。 复验四个目标全部产出;裸机(qemu+OpenSBI)、Linux、Windows(wine)三个跑通, 输出逐字相同。 * docs: README 的授权段说 vendored 源码「unchanged」,而那句话现在是假的 ⚠️ llvm/PATCHES.md 记录着五处原地标记补丁,而 README 的授权段写着 vendored 源码 「are unchanged」。一句与授权相邻的陈述不该与台账矛盾。 改为「几乎未改动」,并把例外**枚举**出来而不是描述:四个文件五处区域,各自夹在 BEGIN/END 之间,一条 grep 数得完。同时写明判据(upstream 在这里问哪个 OS,而真正 的答案是 openkal 的某个接口)以及那份文档更重要的另一半 —— 十九处 <windows.h> 里 有十二处**不需要动**,谓词答对之后 libc++ 的 POSIX 分支本来就已经经 musl 到达 openkal。 并补一节「四个目标,一份源码」:四种目标格式、各自怎么被运行,以及为什么裸机那个 不会侥幸通过;⚠️ 并写明产物是在**真机上被运行**而不是被检查 —— 这个包在 Mach-O 和 PE 上要找的每一处差异都是链接成功、运行时失败。 * feat: name the c++-abi layer in the current vocabulary `hosted-standard-library` is kept beside `mcpp:c++-abi=libc++` so that an engine predating the layer vocabulary still recognises this package. Both name the same layer; a newer engine reads the second, which additionally carries the interface name, and ignores the first. Claude-Session: https://claude.ai/code/session_01Q4ucduLuSsETHYJ1RkGVVD * refactor(example): name an ordinary toolchain The target side no longer follows from the toolchain family name. It follows from the one dependency this example declares, and mcpp resolves it after the dependency graph exists. `llvm@22.1.8` therefore says all this example needs to say about a compiler. Claude-Session: https://claude.ai/code/session_01Q4ucduLuSsETHYJ1RkGVVD --------- Co-authored-by: speak-agent <x.d2learn.org@gmail.com>
1 parent d83ef94 commit 6367a68

13,979 files changed

Lines changed: 1889766 additions & 1 deletion

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 443 additions & 0 deletions
Large diffs are not rendered by default.

.gitignore

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
target/
2+
compile_commands.json
3+
mcpp.lock
4+
.cache/
5+
# ⚠️ THE ONE THIS REPOSITORY DID NOT HAVE, AND THE ONE THAT SLIPPED IN.
6+
# `.mcpp/` is where the build tool keeps a workspace's own state; every other
7+
# repository in this ecosystem ignores it and this one did not, so a
8+
# `.mcpp/.xlings.json` from an experiment was committed with the bare-metal
9+
# work and then travelled in the pull request.
10+
.mcpp/
11+
# ⚠️ One `.mcpp/` rule matches the directory at any depth, and it does not
12+
# remove a file that is ALREADY TRACKED. This repository had two: one at the
13+
# root and one under `examples/import-std/`. The first cleanup found only the
14+
# root one, because the scan it used anchored the path at the beginning.

.mailmap

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# This file allows mapping several author and committer email addresses and
2+
# names to a single canonical one for `git shortlog`, `git log --author`,
3+
# or `git check-mailmap`.
4+
#
5+
# For example, if you commit as `random.person@example.com` but sometimes use
6+
# "Rañdom Person" and sometimes "Random Person" as name and you want the former
7+
# to be your canonical name, add
8+
#
9+
# Rañdom Person <random.person@example.com>
10+
#
11+
# If you commit as both `random.person@example.com` and `ranp@example.com` and
12+
# you want the former to be your canonical email address, add
13+
#
14+
# <random.person@example.com> <ranp@example.com>
15+
#
16+
# Combinations of both are possible too, see
17+
# https://git-scm.com/docs/gitmailmap for format details.
18+
#
19+
# You can commit changes for your own names and email addresses without review.
20+
# If you want to add entries for other people, please have them review the
21+
# addition.
22+
#
23+
# Please keep this file sorted.
24+
25+
<compnerd@compnerd.org> <abdulras@fb.com>
26+
<compnerd@compnerd.org> <abdulras@google.com>
27+
<compnerd@compnerd.org> <abdulras@thebrowser.company>
28+
<git@xen0n.name> <xen0n@gentoo.org>
29+
<hans@hanshq.net> <hans@chromium.org>
30+
<i@maskray.me> <maskray@google.com>
31+
<JCTremoulet@gmail.com> <jotrem@microsoft.com>
32+
Min Hsu <min.hsu@sifive.com> <min@myhsu.dev>
33+
Min Hsu <min.hsu@sifive.com> <minyihh@uci.edu>
34+
<qcf@ecnelises.com> <qiucofan@cn.ibm.com> <qiucf@cn.ibm.com>
35+
<rnk@google.com> <reid@kleckner.net>
36+
<thakis@chromium.org> <nicolasweber@gmx.de>
37+
Jianjian GUAN <jacquesguan@me.com>
38+
Jianjian GUAN <jacquesguan@me.com> <Jianjian.Guan@streamcomputing.com>
39+
Jon Roelofs <jonathan_roelofs@apple.com> <jonathan@codesourcery.com>
40+
Jon Roelofs <jonathan_roelofs@apple.com> <jroelofs@jroelofs.com>
41+
Jonathan Thackray <jonathan.thackray@arm.com> <jthackray@users.noreply.github.com>
42+
klensy <nightouser@gmail.com>
43+
klensy <nightouser@gmail.com> <klensy@users.noreply.github.com>
44+
LLVM GN Syncbot <llvmgnsyncbot@gmail.com>
45+
Martin Storsjö <martin@martin.st>
46+
Med Ismail Bennani <ismail@bennani.ma> <m.i.b@apple.com>
47+
Med Ismail Bennani <ismail@bennani.ma> <medismail.bennani@gmail.com>
48+
Ramkumar Ramachandra <r@artagnon.com> <artagnon@gmail.com>
49+
Ramkumar Ramachandra <r@artagnon.com> <Ramkumar.Ramachandra@imgtec.com>
50+
Saleem Abdulrasool <compnerd@compnerd.org>
51+
Tommy Chiang <ty1208chiang@gmail.com> <oToToT@users.noreply.github.com>
52+
Pengcheng Wang <wangpengcheng.pp@bytedance.com>
53+
Pengcheng Wang <wangpengcheng.pp@bytedance.com> <137158460+wangpc-pp@users.noreply.github.com>
54+
Pengcheng Wang <wangpengcheng.pp@bytedance.com> <pc.wang@linux.alibaba.com>

LICENSE

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
Copyright (c) 2026-present mcpp community, speakshen@163.com
2+
3+
---
4+
5+
Apache License
6+
Version 2.0, January 2004
7+
http://www.apache.org/licenses/
8+
9+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
10+
11+
1. Definitions.
12+
13+
"License" shall mean the terms and conditions for use, reproduction,
14+
and distribution as defined by Sections 1 through 9 of this document.
15+
16+
"Licensor" shall mean the copyright owner or entity authorized by
17+
the copyright owner that is granting the License.
18+
19+
"Legal Entity" shall mean the union of the acting entity and all
20+
other entities that control, are controlled by, or are under common
21+
control with that entity. For the purposes of this definition,
22+
"control" means (i) the power, direct or indirect, to cause the
23+
direction or management of such entity, whether by contract or
24+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
25+
outstanding shares, or (iii) beneficial ownership of such entity.
26+
27+
"You" (or "Your") shall mean an individual or Legal Entity
28+
exercising permissions granted by this License.
29+
30+
"Source" form shall mean the preferred form for making modifications,
31+
including but not limited to software source code, documentation
32+
source, and configuration files.
33+
34+
"Object" form shall mean any form resulting from mechanical
35+
transformation or translation of a Source form, including but
36+
not limited to compiled object code, generated documentation,
37+
and conversions to other media types.
38+
39+
"Work" shall mean the work of authorship, whether in Source or
40+
Object form, made available under the License, as indicated by a
41+
copyright notice that is included in or attached to the work
42+
(an example is provided in the Appendix below).
43+
44+
"Derivative Works" shall mean any work, whether in Source or Object
45+
form, that is based on (or derived from) the Work and for which the
46+
editorial revisions, annotations, elaborations, or other modifications
47+
represent, as a whole, an original work of authorship. For the purposes
48+
of this License, Derivative Works shall not include works that remain
49+
separable from, or merely link (or bind by name) to the interfaces of,
50+
the Work and Derivative Works thereof.
51+
52+
"Contribution" shall mean any work of authorship, including
53+
the original version of the Work and any modifications or additions
54+
to that Work or Derivative Works thereof, that is intentionally
55+
submitted to Licensor for inclusion in the Work by the copyright owner
56+
or by an individual or Legal Entity authorized to submit on behalf of
57+
the copyright owner. For the purposes of this definition, "submitted"
58+
means any form of electronic, verbal, or written communication sent
59+
to the Licensor or its representatives, including but not limited to
60+
communication on electronic mailing lists, source code control systems,
61+
and issue tracking systems that are managed by, or on behalf of, the
62+
Licensor for the purpose of discussing and improving the Work, but
63+
excluding communication that is conspicuously marked or otherwise
64+
designated in writing by the copyright owner as "Not a Contribution."
65+
66+
"Contributor" shall mean Licensor and any individual or Legal Entity
67+
on behalf of whom a Contribution has been received by Licensor and
68+
subsequently incorporated within the Work.
69+
70+
2. Grant of Copyright License. Subject to the terms and conditions of
71+
this License, each Contributor hereby grants to You a perpetual,
72+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
73+
copyright license to reproduce, prepare Derivative Works of,
74+
publicly display, publicly perform, sublicense, and distribute the
75+
Work and such Derivative Works in Source or Object form.
76+
77+
3. Grant of Patent License. Subject to the terms and conditions of
78+
this License, each Contributor hereby grants to You a perpetual,
79+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
80+
(except as stated in this section) patent license to make, have made,
81+
use, offer to sell, sell, import, and otherwise transfer the Work,
82+
where such license applies only to those patent claims licensable
83+
by such Contributor that are necessarily infringed by their
84+
Contribution(s) alone or by combination of their Contribution(s)
85+
with the Work to which such Contribution(s) was submitted. If You
86+
institute patent litigation against any entity (including a
87+
cross-claim or counterclaim in a lawsuit) alleging that the Work
88+
or a Contribution incorporated within the Work constitutes direct
89+
or contributory patent infringement, then any patent licenses
90+
granted to You under this License for that Work shall terminate
91+
as of the date such litigation is filed.
92+
93+
4. Redistribution. You may reproduce and distribute copies of the
94+
Work or Derivative Works thereof in any medium, with or without
95+
modifications, and in Source or Object form, provided that You
96+
meet the following conditions:
97+
98+
(a) You must give any other recipients of the Work or
99+
Derivative Works a copy of this License; and
100+
101+
(b) You must cause any modified files to carry prominent notices
102+
stating that You changed the files; and
103+
104+
(c) You must retain, in the Source form of any Derivative Works
105+
that You distribute, all copyright, patent, trademark, and
106+
attribution notices from the Source form of the Work,
107+
excluding those notices that do not pertain to any part of
108+
the Derivative Works; and
109+
110+
(d) If the Work includes a "NOTICE" text file as part of its
111+
distribution, then any Derivative Works that You distribute must
112+
include a readable copy of the attribution notices contained
113+
within such NOTICE file, excluding those notices that do not
114+
pertain to any part of the Derivative Works, in at least one
115+
of the following places: within a NOTICE text file distributed
116+
as part of the Derivative Works; within the Source form or
117+
documentation, if provided along with the Derivative Works; or,
118+
within a display generated by the Derivative Works, if and
119+
wherever such third-party notices normally appear. The contents
120+
of the NOTICE file are for informational purposes only and
121+
do not modify the License. You may add Your own attribution
122+
notices within Derivative Works that You distribute, alongside
123+
or as an addendum to the NOTICE text from the Work, provided
124+
that such additional attribution notices cannot be construed
125+
as modifying the License.
126+
127+
You may add Your own copyright statement to Your modifications and
128+
may provide additional or different license terms and conditions
129+
for use, reproduction, or distribution of Your modifications, or
130+
for any such Derivative Works as a whole, provided Your use,
131+
reproduction, and distribution of the Work otherwise complies with
132+
the conditions stated in this License.
133+
134+
5. Submission of Contributions. Unless You explicitly state otherwise,
135+
any Contribution intentionally submitted for inclusion in the Work
136+
by You to the Licensor shall be under the terms and conditions of
137+
this License, without any additional terms or conditions.
138+
Notwithstanding the above, nothing herein shall supersede or modify
139+
the terms of any separate license agreement you may have executed
140+
with Licensor regarding such Contributions.
141+
142+
6. Trademarks. This License does not grant permission to use the trade
143+
names, trademarks, service marks, or product names of the Licensor,
144+
except as required for reasonable and customary use in describing the
145+
origin of the Work and reproducing the content of the NOTICE file.
146+
147+
7. Disclaimer of Warranty. Unless required by applicable law or
148+
agreed to in writing, Licensor provides the Work (and each
149+
Contributor provides its Contributions) on an "AS IS" BASIS,
150+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
151+
implied, including, without limitation, any warranties or conditions
152+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
153+
PARTICULAR PURPOSE. You are solely responsible for determining the
154+
appropriateness of using or redistributing the Work and assume any
155+
risks associated with Your exercise of permissions under this License.
156+
157+
8. Limitation of Liability. In no event and under no legal theory,
158+
whether in tort (including negligence), contract, or otherwise,
159+
unless required by applicable law (such as deliberate and grossly
160+
negligent acts) or agreed to in writing, shall any Contributor be
161+
liable to You for damages, including any direct, indirect, special,
162+
incidental, or consequential damages of any character arising as a
163+
result of this License or out of the use or inability to use the
164+
Work (including but not limited to damages for loss of goodwill,
165+
work stoppage, computer failure or malfunction, or any and all
166+
other commercial damages or losses), even if such Contributor
167+
has been advised of the possibility of such damages.
168+
169+
9. Accepting Warranty or Additional Liability. While redistributing
170+
the Work or Derivative Works thereof, You may choose to offer,
171+
and charge a fee for, acceptance of support, warranty, indemnity,
172+
or other liability obligations and/or rights consistent with this
173+
License. However, in accepting such obligations, You may act only
174+
on Your own behalf and on Your sole responsibility, not on behalf
175+
of any other Contributor, and only if You agree to indemnify,
176+
defend, and hold each Contributor harmless for any liability
177+
incurred by, or claims asserted against, such Contributor by reason
178+
of your accepting any such warranty or additional liability.
179+
180+
END OF TERMS AND CONDITIONS
181+
182+
APPENDIX: How to apply the Apache License to your work.
183+
184+
To apply the Apache License to your work, attach the following
185+
boilerplate notice, with the fields enclosed by brackets "[]"
186+
replaced with your own identifying information. (Don't include
187+
the brackets!) The text should be enclosed in the appropriate
188+
comment syntax for the file format. We also recommend that a
189+
file or class name and description of purpose be included on the
190+
same "printed page" as the copyright notice for easier
191+
identification within third-party archives.
192+
193+
Copyright [yyyy] [name of copyright owner]
194+
195+
Licensed under the Apache License, Version 2.0 (the "License");
196+
you may not use this file except in compliance with the License.
197+
You may obtain a copy of the License at
198+
199+
http://www.apache.org/licenses/LICENSE-2.0
200+
201+
Unless required by applicable law or agreed to in writing, software
202+
distributed under the License is distributed on an "AS IS" BASIS,
203+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
204+
See the License for the specific language governing permissions and
205+
limitations under the License.

0 commit comments

Comments
 (0)