From a66d3ab796c798acf012456cdf6daf4c5f358527 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 24 Aug 2026 19:03:46 +0800 Subject: [PATCH] fix: the import libraries are conditioned on the object ABI, not the C library MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -[target.'cfg(all(windows, env = "gnu"))'.build] +[target.'cfg(all(windows, not(env = "msvc")))'.build] ldflags = ["-lntdll", "-lsynchronization", "-lshell32", "-lkernel32"] 这四个是 Win32 导入库 —— 本包所实现的**平台接口**的性质,不是 C 库的性质。 `env = "gnu"` 一直在代表「GNU/PE 的 ABI 而不是 MSVC 的」,而在传统栈上两者重合。 它们在 C 库改由依赖图供给的那一刻不再重合:一次 `x86_64-windows-gnu` 的 openkal 构建解析出的 C 库是 musl —— mcpp 自己的报告就这么打印: kernel-abi openkal (openkal-windows@0.1.3, graph) c-abi musl (openkal-musl@0.3.3, graph) 而拼作 `x86_64-windows-musl` 的是同一次构建的诚实名字。旧谓词下第二个拼法 不带这四个库中的任何一个,实测: ld.lld: error: undefined symbol: __declspec(dllimport) GetStdHandle ld.lld: error: undefined symbol: __declspec(dllimport) WriteFile … 两份 build.ninja 的 ldflags 逐 token 对比,差别只有这四个 token; 连 `--target=x86_64-w64-windows-gnu` 都完全相同 —— 两个 mcpp 三元组翻译成 同一个 LLVM 三元组。 实测(改动后): Finished dev in 2.75s test3.exe: PE32+ executable (console) x86-64, 14 sections imports: ntdll.dll / api-ms-win-core-synch-l1-2-0.dll / SHELL32.dll / KERNEL32.dll wine test3.exe → Hello from test3! `cxxflags = ["-fno-exceptions", "-fno-rtti"]` 在同一张表里,因此一并生效于 两种拼法 —— 那也是对的:它们的理由同样是 ABI 而非 C 库。 ⚠️ 兼容性:`x86_64-windows-gnu` 的求值结果不变(`gnu != msvc`), 新增覆盖的是 `msvc` 之外的其它 env 拼法。 related: mcpp-community/mcpp#494 --- mcpp.toml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/mcpp.toml b/mcpp.toml index a5eaf34..d555db1 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -1,7 +1,7 @@ [package] namespace = "mcpplibs" name = "openkal-windows" -version = "0.1.3" +version = "0.1.4" description = "An implementation of openkal for Windows, written on the Win32 interfaces and the object manager beneath them, using no C runtime symbol." license = "Apache-2.0" @@ -38,7 +38,17 @@ openkal = "0.6.0" # the linker and the other as an input file. Naming them once in the spelling of # either would make this package build under two of the three toolchains it is # written for. -[target.'cfg(all(windows, env = "gnu"))'.build] +# ⚠️ THE PREDICATE IS THE OBJECT ABI, NOT THE C LIBRARY. +# +# These four are Win32 import libraries — a property of the platform interface +# this package implements. `env = "gnu"` was standing in for "the GNU/PE ABI +# rather than the MSVC one", and on a traditional stack the two coincide. They +# stop coinciding the moment the C library comes from the dependency graph: a +# build of `x86_64-windows-gnu` over openkal resolves musl, and one spelled +# `x86_64-windows-musl` is the same build under an honest name. Under the old +# predicate the second one linked with none of these libraries and failed on +# `GetStdHandle`. +[target.'cfg(all(windows, not(env = "msvc")))'.build] ldflags = ["-lntdll", "-lsynchronization", "-lshell32", "-lkernel32"] # Exceptions and run-time type information, on the one ABI where their absence