From 8cac742083eeb52682fad0d1d85567b904793cd5 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Wed, 5 Aug 2026 04:11:46 +0800 Subject: [PATCH] docs: record the compat.openssl windows gap as a TODO with its evidence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit windows support was attempted (#150, now a draft — it cannot be merged as it stands: it turns tests/examples/openssl on windows from a passing no-op main() into a failing build) and did not land. Rather than leave that as six rounds of CI archaeology, what was learned is written down. Settled, and not worth re-investigating: * OpenSSL 3.5.1 leaves exactly one x64 windows path — VC-WIN64A, whose build_scheme is an NMAKE makefile; the clang-cl configs are Windows-on-ARM. * That brings two HOST requirements the package cannot supply: perl (xim:perl ships no windows build — "The Windows answer is Strawberry Perl") and a VS C++ toolset for nmake. Declaring xim:perl in a windows xpm block would fail resolution BEFORE install() runs — the same trap compat.openssl already documents for xim:make on macosx. Where it stops: vswhere finds the toolset correctly, and then running vcvars in ANY form takes the whole process chain down — plain `call`, a child `cmd /c`, and the standard `cmd /c "vcvars & set"` environment dump all stop at that line with no RESULT and no error. That no longer looks like a mistake in the descriptor, so the doc recommends running `perl Configure VC-WIN64A && nmake` by hand on a windows machine inside the mcpp sandbox before writing more code. All six rounds so far were blind CI iterations at ~10 minutes each. The old "requires prebuilt MSVC libs uploaded to xlings-res" line in the descriptor is replaced: that is not the blocker, and leaving it would send the next person after the wrong thing. The doc also carries five findings that apply to ANY install() hook: log.error never reaches the job (only a self-made mcpp_*_build.log does), the xlings sandbox exposes a SUBSET of xmake's Lua API and calling outside it kills the hook silently (os.curdir, path.absolute), os.exec can report success for a script that did nothing, the log must exist before anything that can fail, and io.writefile does not translate line endings while cmd's batch parsing assumes CRLF. --- .../docs/2026-08-05-openssl-windows-todo.md | 92 +++++++++++++++++++ pkgs/c/compat.openssl.lua | 12 ++- 2 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 .agents/docs/2026-08-05-openssl-windows-todo.md diff --git a/.agents/docs/2026-08-05-openssl-windows-todo.md b/.agents/docs/2026-08-05-openssl-windows-todo.md new file mode 100644 index 00000000..57cdde5f --- /dev/null +++ b/.agents/docs/2026-08-05-openssl-windows-todo.md @@ -0,0 +1,92 @@ +# TODO:compat.openssl 的 Windows 支持(2026-08-05,未完成) + +**状态:未完成。** 尝试见 PR [#150](https://github.com/mcpplibs/mcpp-index/pull/150)(已转草稿,**不可按现状合并**)。 +本文记录已经查实的东西,让接手的人不必重走这六轮。 + +## 1. 为什么需要它 + +`compat.openssl` 是索引里唯一一个仍标着 "windows deferred" 的关键包,而它挡住的不止自己: + +- `mcpplibs.grpc`(#151)因此只能是 linux + macOS。gRPC 的 secure 构建去不掉 TLS, + 所以它的平台面**只能等于** `compat.openssl` 的平台面。Windows 上依赖解析在编译任何 TU 之前就失败: + ``` + error: xlings install_packages failed for 'compat.openssl@3.5.1' + E_NOT_FOUND: package 'compat:openssl@3.5.1' not found + ``` +- `compat.curl`、`tests/examples/asio-ssl` 等也都受同一约束。 + +`grpc-m` 已经把 Windows 所需的编译/链接选项(`_WIN32_WINNT`、`NOMINMAX`、`ws2_32`/`crypt32`/`iphlpapi`) +**预置好了**,本条一旦解决,只需把 `grpc-m` 的 Windows CI leg 与 `pkgs/g/grpc.lua` 的 windows xpm 块加回去。 + +## 2. 构建形态是确定的(已核实,不必再查) + +OpenSSL 3.5.1 在 x64 Windows 上**只有一条路**: + +| 事实 | 出处 | +|---|---| +| x64 目标只有 `VC-WIN64A` | `Configurations/10-main.conf` | +| clang-cl 配置只覆盖 **ARM**(`VC-WIN64-CLANGASM-ARM`) | `Configurations/50-win-clang-cl.conf` | +| `VC-WIN64A` 的 `build_scheme` 是 `VC-common` → **NMAKE** makefile,GNU make 驱动不了 | 同上 | + +由此带来两个**宿主要求**,包本身无法提供: + +- **perl** —— `xim:perl` 只有 linux/macosx 两个 xpm 块,其注释写着 + "windows — not shipped. The Windows answer is Strawberry Perl"。 + ⚠️ **不要**试图在 windows 块里写 `deps = { "xim:perl@latest" }`:声明一个在该平台没有块的依赖会 + `E_INVALID_INPUT: package ... not found`,**在 install() 运行之前**就失败(compat.openssl 自己的注释里 + 已记录过 macosx 上 `xim:make` 的同类教训)。 +- **Visual Studio C++ 工具集**(为了 nmake)。`xim:make` 是 GNU make 且只有 linux。 + 只有 `xim:nasm` 有 windows 构建。 + +## 3. 卡住的地方(这是接手的重点) + +CI 上 **vswhere 能正确找到工具集**: + +``` +[bat] vswhere=C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe +[bat] vspath=C:\Program Files\Microsoft Visual Studio\18\Enterprise +``` + +**但只要以任何形式运行 vcvars,整条进程链就消失**,后面一行都执行不到。三种写法都试过,行为一致: + +| 写法 | 结果 | +|---|---| +| 批处理里 `call "%VCVARS%"` | vcvars 打印 `Environment initialized for: 'x64'` 后脚本消失,无 RESULT | +| 把构建移进 `cmd /c ` 子进程 | 子进程与**外层脚本**一起消失,外层连 `RESULT=%errorlevel%` 都写不下 | +| `cmd /c ""%VCVARS%" & set" > env.txt`(标准的环境 dump 手法) | 同样停在这一行 | + +即:这已经**不像是描述符里的代码错误**,而是 xlings 执行子进程的方式与 VS 环境脚本之间的交互。 + +## 4. 下一步建议 + +**先做一次手工验证,再写代码。** 在一台 Windows 机器上,于 `mcpp` 的沙箱环境内手工跑一遍 +`perl Configure VC-WIN64A ... && nmake`,确认它在该环境下究竟能否完成。这一次手工验证能省掉十几轮 +CI 盲调(本次六轮全部是盲调,每轮约 10 分钟)。 + +若确认 vcvars 在该环境下不可用,剩下的路是**绕开所有 VS 脚本**:用 vswhere 拿到 `installationPath` 后 +自行推导并设置 `INCLUDE` / `LIB` / `PATH`(即 vcvars 内部所做的事)—— +`\VC\Tools\MSVC\\bin\Hostx64\x64` 等。可行但脆(Windows SDK 版本发现是主要麻烦), +所以更值得先确认 nmake 路线整体成立。 + +## 5. 顺带查实的通用结论(已写入 PR #150 的提交历史) + +这些不限于 openssl,任何 `install()` 钩子都适用,建议写新钩子时**先建可观测性再写逻辑**: + +1. **`log.error` 的内容到不了 CI 日志**,失败只表现为裸的 `E_INTERNAL: [openssl] failed:`。 + 唯一活得下来的通道是自建日志文件;`validate.yml` 的 "Dump install() build logs on failure" + 步骤 `find` 的是 `mcpp_*_build.log`,文件名要匹配这个模式。 +2. **xlings 沙箱只暴露 xmake Lua API 的子集,调用子集外的函数会让 hook 静默终止**——不报错、不回溯, + 日志停在上一行。实测不可用:`os.curdir()`、`path.absolute()`。 +3. **`os.exec` 的返回值不可信**:一个什么都没做、也无输出的批处理返回了 `ok=true`。 + 应让被调脚本自己往日志里写 `RESULT=`,由 Lua 读日志判定。 +4. **日志必须在最早时刻创建并逐步追加**。第一版把日志留给子进程写,而失败发生在那之前, + CI 只打出 `no install() build logs found` —— 零信息。 +5. `io.writefile` **按字节原样写**,不会替你转换换行;而 cmd 按**文件偏移**逐行读批处理、 + 其记账假定 CRLF。 + +## 6. 与之相关的既有约束 + +- 合并 PR #150 的现状会让 Windows **退化**:合入前 `tests/examples/openssl` 在 windows 上是 no-op + `main()`(绿),合入后会真去构建并失败。因此该 PR 已转草稿。 +- 本 TODO 完成后要一并恢复的:`grpc-m` 的 windows CI leg、`pkgs/g/grpc.lua` 的 windows xpm 块、 + `tests/examples/grpc-module` 的 windows 门控。 diff --git a/pkgs/c/compat.openssl.lua b/pkgs/c/compat.openssl.lua index 884fb47b..46a4fd3d 100644 --- a/pkgs/c/compat.openssl.lua +++ b/pkgs/c/compat.openssl.lua @@ -37,7 +37,17 @@ -- Platforms: -- * linux/macosx — build a fully static libcrypto.a + libssl.a from source -- via install() hook (anchor-triggered build, same pattern as compat.openblas). --- * windows — deferred (requires prebuilt MSVC libs uploaded to xlings-res). +-- * windows — still deferred, but NOT for the reason written here before: +-- a source build was attempted and the blocker is not a missing prebuilt +-- archive. vswhere finds the toolset fine, and then running vcvars in ANY +-- form takes the whole process chain down — plain `call`, a child +-- `cmd /c`, and the standard `cmd /c "vcvars & set"` environment dump all +-- stop dead at that line with no RESULT and no error. See +-- .agents/docs/2026-08-05-openssl-windows-todo.md for the evidence, the +-- two host requirements it brings (perl — xim:perl has no windows build; +-- a VS C++ toolset for nmake, since VC-WIN64A's build_scheme is an NMAKE +-- makefile), and why a manual run on a windows machine should come before +-- the next code attempt. package = { spec = "1", namespace = "compat",