diff --git a/.agents/docs/2026-08-02-add-boost-ext-ut-plan.md b/.agents/docs/2026-08-02-add-boost-ext-ut-plan.md new file mode 100644 index 0000000..59199b8 --- /dev/null +++ b/.agents/docs/2026-08-02-add-boost-ext-ut-plan.md @@ -0,0 +1,144 @@ +# 收录 [Boost::ext].UT(boost-ext.ut)2.3.1 + +> 日期:2026-08-02(2026-08-03 依 CI 与本地实测结论重写) +> 分支:`add-boost-ext-ut` / PR #142 +> 仓库:[boost-ext/ut](https://github.com/boost-ext/ut) +> 背景:把 boost-ext 组织(**不是** boost 官方)的 UT 单头测试框架收录进 mcpp-index。 +> 上游自带模块单元 `include/boost/ut.cppm`,宣告 `export module boost.ut;`。 + +## 1. 来源与形态判定 + +- 来源:**(a) 第三方上游库**。上游不提供 mcpp 支持,但 release tarball **自带**官方模块单元。 +- 版本:`v2.3.1`(截至 2026-08-02 的最新 release tag)。 +- License:Boost Software License 1.0,SPDX `BSL-1.0`。 +- 布局:tarball 顶层 wrap 目录 `ut-2.3.1/`,模块单元 `include/boost/ut.cppm`, + 头文件 `include/boost/ut.hpp`(3378 行,`namespace boost::inline ext::ut::inline v2_3_1`)。 +- 形态:**C++23 module(generated wrapper)**,与 `nlohmann.json` / `marzer.tomlplusplus` 同类。 + 但与它们不同的是,本包的 wrapper 是上游 cppm 的**逐字复制**,只加一处 shim(见 §2)。 + +身份:`namespace = "boost-ext"`、`name = "ut"`。**不是** `boost`、**不是** `compat` —— +该项目并非 boost 官方库,不应占用 `compat` 习惯位置,也不应进 boost 命名空间。 +mcpp 命名空间用 `-` 分层,避免与 `.` 点号寻址约定碰撞。 + +## 2. 唯一的偏离:Clang-on-MSVC 的 `__argc` / `__argv` + +`generated_files` 内嵌的 cppm 在上游 v2.3.1 `ut.cppm` 之上**只加一处**,不删任何一行, +连 `export import std;` 都原样保留: + +``` +ut.hpp:688:29: error: use of undeclared identifier '__argc'; did you mean 'largc'? +ut.hpp:689:63: error: use of undeclared identifier '__argv'; did you mean 'largv'? +``` + +`ut.hpp:687` 是 `#if defined(_MSC_VER)`,引用 MSVC 内建 `__argc` / `__argv`。 +Clang 在 MSVC ABI 上设了 `_MSC_VER` 但不提供这两个内建 —— 上游相邻分支(行 291 / 311 / 1147) +已用 `&& !defined(__clang__)` 排除 clang,行 687 漏了同一守卫。属上游的 clang-on-windows 适配缺口。 + +这一条对本仓是必需的,因为本索引的 **Windows 默认工具链就是 LLVM/Clang + MSVC ABI** +(`.agents/docs/2026-07-19-full-platform-support-plan.md`:`llvm@20.1.7`,NOT mingw,NOT cl.exe), +CI 日志里也是 `Resolved llvm@20.1.7 → …/clang++.exe`。shim 用 `_MSC_VER && __clang__` 双重门控, +真 MSVC 永远不进入;`cfg::largc` / `cfg::largv` 在运行期由 `main()` 的 argv 重新赋值,替身值不会被读。 + +## 3. 曾经走过的弯路(留档,避免重走) + +PR #142 的前 22 个 commit 里做过三处后来被**证伪并回退**的改动。记在这里,是因为它们的 +"理由"看上去都很有说服力: + +### 3.1 删 `export import std;` + 手写 24 个 GMF `#include` + +**动机**:macOS 上 verbatim 模块在静态初始化期 SIGSEGV,lldb 停在 `ut.hpp:1620` 的 +`std::cout.rdbuf()`,address `-0x18` 说明 `std::cout` 的 vptr 为零。当时判断是 +`export import std;` 让模块持有自己那份 std 流实体,与 libc++ 库里的那份 ODR 分裂。 + +**证伪**:commit `3eff289`(已删 `export import std;`)在 mcpp 0.0.109 上,macOS 仍然 +`ut ... FAIL (exit 139)`。后续的 `ios_base::Init` 强制构造(`fbf1ad0`)同样失败。 +macOS 唯一转绿的变更是把 mcpp pin 提到 2026.8.3.1。 + +**真因**:mcpp-community/mcpp#336 —— Mach-O 没有按优先级排序的初始化段,libc++ 的 +`` 也不像 libstdc++ / MSVC STL 那样自带 `ios_base::Init` 守卫,于是归档成员的 +初始化器跑到时流还是全零。**包侧无法修复**:`std::ios_base::Init` 在 libc++ 的 `` 里 +只有前向声明。mcpp 2026.8.3.1 起生成一个极小 C 翻译单元排在链接行最前,由它先把流顶起来。 + +**副作用**:删掉 `export import std;` 之后,GCC 会爆出一连串 `-Wtemplate-body` 错误 +(无修饰 `size_t`、`std::empty`、literal using 块),于是又被迫补 `using std::size_t;` +和 `cxxflags = { "-Wno-template-body" }`。**这些全部是自造的问题** —— 保留上游原样就没有。 +本地实测(mcpp 2026.8.3.3 **与** 0.0.109,linux / gcc 16.1.0,冷跑):上游 cppm 逐字、 +不加任何 `cxxflags`,`mcpp test -p boost-ext.ut` 通过,编译行里确认没有 `-Wno-template-body`。 + +### 3.2 追加上游 `master` 的显式模板实例化块 + +**动机**:当作 macOS SIGSEGV 的修复引进。 + +**证伪**:它在 `61b9441` 就已就位,macOS 仍 exit 139。它是上游为某个 Clang module linkage +gap 加的,且**不在任何 release tag 里**。既然不解决本仓遇到的问题,就不进信任路径。 + +### 3.3 `.github/workflows/diag-ut-macos.yml` + +排 macOS 崩溃时的一次性诊断 workflow(lldb 反汇编 / `__init_offsets` 符号化 / relink 矩阵), +`on: push: branches: [add-boost-ext-ut]`。问题定位后已删除。 + +## 4. mcpp pin 与 index.toml floor + +`MCPP_VERSION` 从 `0.0.109` 提到 `2026.8.3.3`,`index.toml` 的 `min_mcpp` / `latest_mcpp` 同步。 + +- 提 pin 是**必需**的:macOS 的崩溃修在 mcpp 侧(§3.1),包侧无解。 +- floor 同步跟随 pin 是本仓一贯做法(见 #125 把 0.0.108 → 0.0.109)。这里尤其应该同步: + 低于 floor 的 macOS 消费者装上本包会**直接段错误且无任何诊断**,比 E0006 更糟。 +- 取 `.3.3` 而非 `.3.1`:`.3.2` / `.3.3` 只有交叉编译相关修复(PE 产物命名、`-static` + 按主机而非目标判定),本 CI 矩阵不走那些路径,取最新一档零成本。 + +## 5. CI:`MCPP_BUILD_CACHE: local` + +mcpp >= 2026.7.30.2 引入了全局包构建缓存。它在本仓的全量 workspace 下有 bug, +必须先绕开(已上报 **mcpp-community/mcpp#344**): + +- mcpp#233 的 obj 路径消歧按**整个 build dir 内的 basename 冲突**触发,也就是按 + **消费方拉了哪些包**触发;而 cache key 只覆盖依赖包自身(v2026.7.30.2 的设计明确 + "不含 root 的身份与 flags")。 +- `tests/examples/archive` 同时拉 zlib 与 bzip2(两者都有 `compress.c`)→ 触发消歧, + 写进缓存的是 `obj/compat_zlib/zlib-1.3.2/compress.o`;而只拉 zlib 的消费者 + (`libpng` / `freetype` / `eui-neo*` / `sdl2` / `vulkan`)按同一个 key 去要平的 + `obj/compress.o` → `ninja: error: … missing and no known rule to make it`。 +- 本地在 2026.8.3.3 上**双向对称复现**(谁第二个跑谁挂),`--cache local` / + `MCPP_BUILD_CACHE=local` 可绕过,且 `local` 仍然缓存 std BMI(贵的那份),只跳过包条目。 + +mcpp#344 修好后删掉这个 env 即可。 + +## 6. feature 评估 + +**不实现 feature**。ut 为纯头文件 + 单个模块单元,无"额外的可编译源码"可门控。 +其可选行为(`BOOST_UT_CONFIG_*`)均为编译期 **define**,而 `features` 表当前仅能门控 `sources`。 +与 Eigen 的 `EIGEN_MPL2_ONLY`、toml++ 的 `TOML_EXCEPTIONS` 属同类限制。 + +## 7. CN 镜像 + +未配置。无 `mcpp-res` 写权限,lint 允许 plain-string `url`(`tests/check_mirror_urls.lua` +对字符串形式直接放行),CN 用户回退至上游源,镜像由维护者后续补充。 + +## 8. 测试工程与验证 + +`tests/examples/boost-ext.ut/`,已登记进根 `mcpp.toml` 的 `[workspace].members`(按字母序)。 +成员级 `[indices] boost-ext = { path = "../../.." }` 恰好一条 —— 它**替换**而非合并根级继承的 +`compat` 表,把项目级 index repo 保持在一个。 + +断言覆盖 UDL 语法(`"..."_test = []{}`)与函数语法(`test("...") = []{}`)两路,通过 +`expect()` 判定。测试 `main()` 返回 0 是安全的:ut 的 `~runner()`(ut.hpp:2032)在 +`fails_` 非零时 `std::exit(-1)`,静态析构期生效,所以断言失败会让 `mcpp test` 非零退出。 + +| 检查 | 结果 | +|---|---| +| tarball sha256 二次核对 | ✅ `e51bf187…ea9b1` | +| `tests/check_package_name.lua` | ✅ pass | +| `tests/check_mirror_urls.lua` | ✅ pass | +| `tests/check_cross_package_refs.lua` | ✅ pass | +| 前导 v 版本号 lint | ✅ `"2.3.1"` 裸版本 | +| `mcpp test -p boost-ext.ut`(linux / gcc 16.1.0 / mcpp 2026.8.3.3,冷跑) | ✅ `all tests passed (3 asserts in 2 tests)` | +| macOS / Windows | 由 PR #142 的 CI 判定 | + +冷验证前均已 `rm -rf tests/examples/boost-ext.ut/{target,.mcpp,mcpp.lock,compile_commands.json}`, +自干净状态走完「拉 tarball → 编译 wrapper → 编译/链接测试 → 运行」完整管线。 + +## 9. 演进条件 + +一旦 ut 发出 >2.3.1 的 release,且其 ut.hpp 在 687 行补上 `&& !defined(__clang__)` 守卫, +`generated_files` 整块即可删除,`sources` 切回 `*/include/boost/ut.cppm` 直接用上游文件。 diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index b937a58..79ac841 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -14,6 +14,19 @@ on: workflow_dispatch: env: + # 2026.8.3.1: on macOS, a global object that touches std::cout during static + # init crashes on sight (mcpp#336). Mach-O has no priority-ordered init + # section and libc++'s carries no ios_base::Init guard of its own, + # so the streams are still all-zero when an archive member's initializer + # runs. mcpp now links a generated object FIRST whose constructor brings them + # up. It is not fixable package-side — std::ios_base::Init is only + # forward-declared in libc++'s — so boost-ext.ut genuinely requires + # this floor on macOS, and min_mcpp/latest_mcpp move with the pin as they + # always have (a consumer below the floor would get a segfault with no + # diagnostic, which is worse than E0006). + # 2026.8.3.3 is the pin rather than .3.1: .3.2/.3.3 are cross-compilation + # fixes (PE artifact naming, -static host-vs-target) that no leg of this + # matrix exercises, so taking the newest of the train costs nothing. # 0.0.109: a bare dependency's wire address takes BOTH halves from the # descriptor the identity gate accepted (mcpp#286). This is the client-side # other half of the SPEC-001 migration below: mcpp used to take the NAME from @@ -75,7 +88,7 @@ env: # 0.0.94 fixed feature-gated `sources` under `mcpp test` (mcpp#218); 0.0.91 # added standard = "c++fly" to the resolver grammar, so c++fly descriptors # get the lint WARN below, not a hard grammar-parse rejection. - MCPP_VERSION: "0.0.109" + MCPP_VERSION: "2026.8.3.3" jobs: lint: @@ -240,21 +253,21 @@ jobs: ext: tar.gz mcpp: bin/mcpp xlings: registry/bin/xlings - mcpp_version: "0.0.109" # keep in sync with env.MCPP_VERSION + mcpp_version: "2026.8.3.3" # keep in sync with env.MCPP_VERSION - platform: macos os: macos-15 suffix: macosx-arm64 ext: tar.gz mcpp: bin/mcpp xlings: registry/bin/xlings - mcpp_version: "0.0.109" # keep in sync with env.MCPP_VERSION + mcpp_version: "2026.8.3.3" # keep in sync with env.MCPP_VERSION - platform: windows os: windows-latest suffix: windows-x86_64 ext: zip mcpp: bin/mcpp.exe xlings: registry/bin/xlings.exe - mcpp_version: "0.0.109" # keep in sync with env.MCPP_VERSION + mcpp_version: "2026.8.3.3" # keep in sync with env.MCPP_VERSION env: MCPP_EFFECTIVE: ${{ matrix.mcpp_version }} steps: @@ -400,6 +413,21 @@ jobs: shell: bash env: MCPP_INDEX_MIRROR: GLOBAL + # Dependencies build inside each member's own target/ instead of + # through the global package build cache (mcpp >= 2026.7.30.2). + # That cache is unusable here: mcpp#233's object-path disambiguation + # fires on basename collisions across the WHOLE build dir — i.e. on + # which packages the CONSUMER pulls in — while the cache key covers + # only the dependency itself, so one entry can hold two different + # layouts. `tests/examples/archive` pulls zlib AND bzip2 (both ship + # compress.c) and stores obj/compat_zlib/zlib-1.3.2/compress.o; + # every zlib consumer without bzip2 then asks the same key for a + # flat obj/compress.o and ninja dies at graph time with + # "missing and no known rule to make it". Reproduced both ways round + # on 2026.8.3.3 and filed as mcpp-community/mcpp#344; drop this once + # it lands. `local` still caches the std BMI, which is the expensive + # one — only package entries are bypassed. + MCPP_BUILD_CACHE: local run: | "$MCPP" --version # No `timeout` wrapper: absent on macOS runners; job-level timeout-minutes bounds it. diff --git a/README.md b/README.md index ee8e588..1f9f605 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ Two kinds of packages live here: | Multiple majors in one package (shape switches with the version) | [`compat.catch2`](pkgs/c/compat.catch2.lua) (3.x compiles `src/catch2/` into a static library; 2.x goes header-only through `single_include/`) | | External build system (`install()` builds from source) | [`compat.openblas`](pkgs/c/compat.openblas.lua) (Make) · [`compat.openssl`](pkgs/c/compat.openssl.lua) (Perl Configure + Make, static libssl/libcrypto) | | Whole-source direct build (config snapshot + source list, no external build system) | [`compat.ffmpeg`](pkgs/c/compat.ffmpeg.lua) (2281 TUs including NASM assembly, declared through 28 directory globs) | -| C++23 module wrapper | [`nlohmann.json`](pkgs/n/nlohmann.json.lua) · [`marzer.tomlplusplus`](pkgs/m/marzer.tomlplusplus.lua) · [`neargye.magic_enum`](pkgs/n/neargye.magic_enum.lua) | +| C++23 module wrapper | [`nlohmann.json`](pkgs/n/nlohmann.json.lua) · [`marzer.tomlplusplus`](pkgs/m/marzer.tomlplusplus.lua) · [`neargye.magic_enum`](pkgs/n/neargye.magic_enum.lua) · [`boost-ext.ut`](pkgs/b/boost-ext.ut.lua) (upstream's own `include/boost/ut.cppm` reproduced verbatim but for one `__argc`/`__argv` shim that Clang-on-MSVC needs; namespace `boost-ext` since it is NOT an official Boost library) | ### Adding a package diff --git a/README.zh-CN.md b/README.zh-CN.md index cb3b366..daba711 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -47,7 +47,7 @@ mcpp self config --mirror CN # 切换至国内镜像,默认使用 GLOBAL 上 | 单包多 major(形态随版本切换) | [`compat.catch2`](pkgs/c/compat.catch2.lua)(3.x 编 `src/catch2/` 出静态库;2.x 走 `single_include/` header-only) | | 外部构建系统(`install()` 从源码构建) | [`compat.openblas`](pkgs/c/compat.openblas.lua)(Make) · [`compat.openssl`](pkgs/c/compat.openssl.lua)(Perl Configure + Make,静态 libssl/libcrypto) | | 全源码直编(config 快照 + 源列表,零外部构建系统) | [`compat.ffmpeg`](pkgs/c/compat.ffmpeg.lua)(2281 TU 含 NASM 汇编,28 个目录 glob 声明) | -| C++23 module wrapper | [`nlohmann.json`](pkgs/n/nlohmann.json.lua) · [`marzer.tomlplusplus`](pkgs/m/marzer.tomlplusplus.lua) · [`neargye.magic_enum`](pkgs/n/neargye.magic_enum.lua) | +| C++23 module wrapper | [`nlohmann.json`](pkgs/n/nlohmann.json.lua) · [`marzer.tomlplusplus`](pkgs/m/marzer.tomlplusplus.lua) · [`neargye.magic_enum`](pkgs/n/neargye.magic_enum.lua) · [`boost-ext.ut`](pkgs/b/boost-ext.ut.lua)(逐字复用上游自带的 `include/boost/ut.cppm`,仅加一处 Clang-on-MSVC 需要的 `__argc`/`__argv` shim;命名空间取 `boost-ext`,因其并非 boost 官方库) | ### 新增一个包 diff --git a/index.toml b/index.toml index 2915961..2793f7f 100644 --- a/index.toml +++ b/index.toml @@ -7,5 +7,5 @@ # "floor first, new grammar after" rollout rule mechanically. [index] spec = "1" -min_mcpp = "0.0.109" -latest_mcpp = "0.0.109" +min_mcpp = "2026.8.3.3" +latest_mcpp = "2026.8.3.3" diff --git a/mcpp.toml b/mcpp.toml index 7f57b6d..47323c5 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -10,6 +10,7 @@ members = [ "tests/examples/archive", "tests/examples/asio-module", "tests/examples/asio-ssl", + "tests/examples/boost-ext.ut", "tests/examples/build-mcpp", "tests/examples/catch2", "tests/examples/catch2-main", diff --git a/pkgs/b/boost-ext.ut.lua b/pkgs/b/boost-ext.ut.lua new file mode 100644 index 0000000..bf3e57b --- /dev/null +++ b/pkgs/b/boost-ext.ut.lua @@ -0,0 +1,151 @@ +-- Form B inline descriptor for [Boost::ext].UT — the C++20 single-header +-- unit-testing framework shipped by the boost-ext org (NOT an official Boost +-- library; hence the `boost-ext` package namespace, NOT `compat` and NOT +-- `boost`). Exposed as the C++23 module `boost.ut` so users can write +-- `import boost.ut;` out of the box. +-- +-- The upstream release tarball ships an official module interface unit at +-- `include/boost/ut.cppm` (`export module boost.ut;`). This descriptor +-- reproduces that file through `generated_files` with EXACTLY ONE deviation — +-- everything else, including `export import std;`, is upstream's own bytes in +-- upstream's own order. +-- +-- The one deviation: Clang on the MSVC ABI (`*-pc-windows-msvc`, this index's +-- Windows default toolchain — llvm@20.1.7, NOT mingw, NOT cl.exe) rejects +-- upstream's file with +-- ut.hpp:688:29: error: use of undeclared identifier '__argc' +-- ut.hpp:689:63: error: use of undeclared identifier '__argv' +-- ut.hpp line 687 is `#if defined(_MSC_VER)` and reaches for the MSVC builtins +-- `__argc` / `__argv`. Clang DOES set `_MSC_VER` on that ABI but does NOT +-- provide those builtins — the neighbouring upstream guards at lines 291 / 311 +-- / 1147 already gate clang out, line 687 missed it. So the wrapper defines the +-- two names as macros around the `#include`, under `_MSC_VER && __clang__` +-- only: real MSVC never enters the guard and keeps its builtins, and no +-- non-Windows target ever sees the macros. `cfg::largc` / `cfg::largv` are +-- reassigned from `main()`'s argv at runtime, so the stand-in values are never +-- read. +-- +-- That is the whole delta. In particular this descriptor does NOT: +-- * drop `export import std;` — keeping upstream's spelling is what makes +-- GCC 16.1 accept ut.hpp's unqualified `size_t` (ut.hpp:1916 et al) and +-- the `literals` using-block with no `-Wno-template-body` and no +-- hand-written global-module-fragment include list; +-- * carry the post-v2.3.1 explicit-template-instantiation block from +-- upstream `master` — it is in no release tag, and the macOS crash it was +-- tried against turned out to be a toolchain-side problem (below). +-- +-- macOS: the verbatim module used to SIGSEGV (exit 139) during static init of +-- `cfg::runner>`, at ut.hpp:1620's member-init +-- `std::streambuf* cout_save = std::cout.rdbuf();` — libc++'s `std::cout` had +-- not been constructed yet. That is mcpp-community/mcpp#336, fixed in mcpp +-- 2026.8.3.1: Mach-O has no priority-ordered init section and libc++'s +-- `` carries no `ios_base::Init` guard of its own, so mcpp now links +-- a generated object first whose constructor brings the streams up. It is not +-- fixable package-side (`std::ios_base::Init` is only forward-declared in +-- libc++'s ``), which is why this package needs mcpp >= 2026.8.3.1 on +-- macOS — covered by the floor this index declares in index.toml. +-- +-- `include_dirs` exposes `*/include/boost` so the wrapper's `#include +-- "ut.hpp"` resolves (and `#include ` stays available to +-- consumers who want the header form). That path is a GLOB — the leading `*` +-- absorbs the archive's `ut-2.3.1/` wrap layer — while the generated cppm path +-- is verdir-relative (no glob), like nlohmann.json / marzer.tomlplusplus. +-- +-- `import_std` stays false: the module TU must not get an injected `import +-- std;` (upstream's file does its own `export import std;`), and consumers +-- `import std;` themselves exactly like the other module packages. +-- +-- No features. ut is header-only plus a single module unit, with no extra +-- compilable sources to gate; its optional `BOOST_UT_CONFIG_*` toggles are +-- compile-time defines, which the `features` table cannot carry today (the +-- same limitation as compat.eigen's `EIGEN_MPL2_ONLY` and toml++'s +-- `TOML_EXCEPTIONS`). +-- +-- No CN mirror: plain-string upstream URLs, which tests/check_mirror_urls.lua +-- accepts as-is. CN users fall back to the GLOBAL source until a maintainer +-- backfills the gitcode release. +-- +-- License: Boost Software License 1.0. The SPDX identifier is BSL-1.0. +-- +-- Package identity: `namespace = "boost-ext"`, `name = "ut"`. The C++ +-- namespace the library declares is `boost::ext::ut::v2_3_1` — unrelated to +-- the mcpp namespace, which uses `-` precisely because `.` would collide with +-- mcpp's own `.` addressing convention. +package = { + spec = "1", + namespace = "boost-ext", + name = "ut", + description = "[Boost::ext].UT — C++20 single-header unit testing framework, exposed as the C++23 module boost.ut", + licenses = {"BSL-1.0"}, + repo = "https://github.com/boost-ext/ut", + type = "package", + + xpm = { + linux = { + ["2.3.1"] = { + url = "https://github.com/boost-ext/ut/archive/refs/tags/v2.3.1.tar.gz", + sha256 = "e51bf1873705819730c3f9d2d397268d1c26128565478e2e65b7d0abb45ea9b1", + }, + }, + macosx = { + ["2.3.1"] = { + url = "https://github.com/boost-ext/ut/archive/refs/tags/v2.3.1.tar.gz", + sha256 = "e51bf1873705819730c3f9d2d397268d1c26128565478e2e65b7d0abb45ea9b1", + }, + }, + windows = { + ["2.3.1"] = { + url = "https://github.com/boost-ext/ut/archive/refs/tags/v2.3.1.tar.gz", + sha256 = "e51bf1873705819730c3f9d2d397268d1c26128565478e2e65b7d0abb45ea9b1", + }, + }, + }, + + mcpp = { + schema = "0.1", + language = "c++23", + import_std = false, + modules = { "boost.ut" }, + include_dirs = { "*/include/boost" }, + -- Upstream's v2.3.1 include/boost/ut.cppm, reproduced verbatim apart + -- from the __argc / __argv shim documented at the top of this file. + -- Verdir-relative path, no glob. + generated_files = { + ["mcpp_generated/boost.ut.cppm"] = [==[ +module; + +#if __has_include() and __has_include() +#include +#include +#endif + +export module boost.ut; +export import std; + +// ---- the only mcpp-index deviation from upstream v2.3.1's ut.cppm --------- +// ut.hpp:687 is `#if defined(_MSC_VER)` and references the MSVC builtins +// __argc / __argv. Clang on the MSVC ABI (this index's Windows default, +// *-pc-windows-msvc) sets _MSC_VER but does not provide them; the adjacent +// upstream guards at lines 291 / 311 / 1147 already gate clang out, 687 +// missed it. cfg::largc / cfg::largv are reassigned from main()'s argv at +// runtime, so these stand-in values are never read. MSVC itself never enters +// the guard and keeps its own builtins. +#if defined(_MSC_VER) and defined(__clang__) + #define __argc 0 + #define __argv ((const char**)nullptr) +#endif + +#define BOOST_UT_CXX_MODULES 1 +#include "ut.hpp" + +#if defined(_MSC_VER) and defined(__clang__) + #undef __argc + #undef __argv +#endif +]==], + }, + sources = { "mcpp_generated/boost.ut.cppm" }, + targets = { ["boost_ut"] = { kind = "lib" } }, + deps = { }, + }, +} diff --git a/tests/examples/boost-ext.ut/mcpp.toml b/tests/examples/boost-ext.ut/mcpp.toml new file mode 100644 index 0000000..6521207 --- /dev/null +++ b/tests/examples/boost-ext.ut/mcpp.toml @@ -0,0 +1,15 @@ +# boost-ext.ut test project: consumes the C++23 module `boost.ut` and +# asserts two test styles (UDL + function syntax) plus an expect failure +# under `mcpp test`. +# Overrides the workspace-root redirect (`compat`): this member needs the +# `boost-ext` namespace. A member-level [indices] REPLACES the inherited +# table rather than merging with it — keeps the project index repo to ONE. +[indices] +boost-ext = { path = "../../.." } + +[package] +name = "boost-ext-ut-tests" +version = "0.1.0" + +[dependencies.boost-ext] +ut = "2.3.1" diff --git a/tests/examples/boost-ext.ut/tests/ut.cpp b/tests/examples/boost-ext.ut/tests/ut.cpp new file mode 100644 index 0000000..b139c13 --- /dev/null +++ b/tests/examples/boost-ext.ut/tests/ut.cpp @@ -0,0 +1,23 @@ +// Behavioral test: build two tests under [Boost::ext].UT via `import boost.ut;`, +// then exercise the UDL ("..."_test) and function-call (test("...")) syntaxes. +// Counts test registration by reading ut's `tests_runner` directly is awkward, +// so the test instead just RUNS a passing assertion in each style; if the +// module fails to import or any expect() fails, [Boost::ext].UT reports the +// failure through its test runner and `mcpp test` returns non-zero. +import std; +import boost.ut; + +using namespace boost::ut; + +int main() { + "UDL syntax"_test = [] { + expect(42_i == 42); + }; + + test("function syntax") = [] { + expect(0_i == 0); + expect(1u == 1_u); + }; + + return 0; +}