Skip to content

Commit 5f10035

Browse files
FarnaHerryspeak-agent
authored andcommitted
feat: add compat.eui-neo 0.5.3 with selectable render and window backends
EUI-NEO as a Form B compat package: the core TUs compiled into one lib, public headers exposed via include_dirs, so consumers write `#include <eui_neo.h>`. The C++23 module surface is out of scope — upstream ships no module interface units. Depends on #134 for compat.vulkan, compat.sdl2 and compat.curl; the `vulkan`, `sdl2` and `network` features resolve against them. Sourced from upstream's v0.5.3 release tag with a real sha256, mirrored to gitcode mcpp-res. Upstream vendors freetype/glfw/libpng/zlib/glad/tray/yyjson/ md4c under 3rd/; none are built here — each is already in this index at the same version, which is what the six packages from #131 were for. Backend selection is the interesting part. Upstream compiles exactly one render backend and one window backend, dispatching on `#if OPENGL ... #elif VULKAN` and `#if SDL2` / else-GLFW, so defining both halves of either pair silently picks the first and ignores the caller — invisible in CI, since neither backend runs headless. mcpp features are additive with no `default-features = false` (mcpp#242), and all three obvious encodings fail silently: a `default` feature carrying defines/sources/deps is inert, `default = { implies = ... }` is the opposite and always applies, and a package-level define cannot be unset by a feature. Verified with probes on both 0.0.109 and 2026.7.29.1 — a version bump does not change it. What works is resolving the choice in the preprocessor from the -DMCPP_FEATURE_<NAME> flags mcpp already passes, via a force-included header; that also means naming an unrelated feature no longer drops the backends. Doing so exposed a second problem: mcpp routes `cflags` to C translation units and `cxxflags` to C++ ones. The first revision of this descriptor carried `cflags = { "-DEUI_RENDER_BACKEND_OPENGL=1" }` and nothing else, so render_backend.cpp never saw it — the package built, linked, passed its tests, and had no render backend at all. Four members cover the matrix: default (opengl+glfw), markdown, vulkan, and sdl2+network. Backend selection is verified structurally rather than by trusting a green test — render_backend.o and window_backend.o are checked for which backend they actually reference, including for the member that names only an unrelated feature. Verified cold on all three platforms with mcpp 0.0.109. compat.vulkan has no windows build, so the vulkan member gates with [target.'cfg(...)'] and asserts the default OpenGL configuration there instead. Design: .agents/docs/2026-07-29-add-eui-neo-plan.md Co-authored-by: SPeak Agent <248744407+speak-agent@users.noreply.github.com>
1 parent 6da8452 commit 5f10035

14 files changed

Lines changed: 1235 additions & 23 deletions

File tree

.agents/docs/2026-07-29-add-eui-neo-plan.md

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

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ mcpp self config --mirror CN # 切换至国内镜像,默认使用 GLOBAL 上
3838
| 运行时 loader compat(纯源码,绕开上游 codegen/asm) | [`compat.vulkan`](pkgs/c/compat.vulkan.lua)(Khronos loader:`loader/generated/` 已签入,汇编路径经 `UNKNOWN_FUNCTIONS_SUPPORTED` 降级为纯 C,故无需 CMake/Python/汇编器;windows 延后)· [`compat.vulkan-headers`](pkgs/c/compat.vulkan-headers.lua) |
3939
| 全源码直编 + 生成 config(仅缺口平台) | [`compat.curl`](pkgs/c/compat.curl.lua)(win32 用上游签入 config,unix 生成) · [`compat.sdl2`](pkgs/c/compat.sdl2.lua)(win/mac 用上游签入 config,linux 生成 + 手工开 X11) |
4040
| 补索引空缺的头文件包 | [`compat.glx-headers`](pkgs/c/compat.glx-headers.lua)(libglvnd 的 `GL/glx.h`,Khronos registry 不含,SDL 的 X11 后端必需) |
41+
| C++ 应用框架 compat(依赖复用索引内既有包) | [`compat.eui-neo`](pkgs/e/compat.eui-neo.lua)(上游 `3rd/` 自带 8 个 vendored 依赖,此处一个不编,全部改指索引内同版本 `compat.*`) |
42+
| 互斥后端(同包多后端二选一) | [`compat.eui-neo`](pkgs/e/compat.eui-neo.lua)`opengl`/`vulkan``glfw`/`sdl2`**`default` feature 在 mcpp 上不可用**(带 `defines/sources/deps` 完全不生效;带 `implies` 反而恒生效),可行解是用 `-DMCPP_FEATURE_<NAME>` 在强制包含头里做前置判定。另注意 `cflags` 只作用于 C TU,C++ 需 `cxxflags` |
4143
| 恒开的 interface define | [`compat.curl`](pkgs/c/compat.curl.lua)`CURL_STATICLIB`:`cflags` 恒开但包私有,feature `defines` 可达消费端但需点名 —— `default = { implies = … }` 无条件生效,恰好两者兼得 |
4244
| 单包多 major(形态随版本切换) | [`compat.catch2`](pkgs/c/compat.catch2.lua)(3.x 编 `src/catch2/` 出静态库;2.x 走 `single_include/` header-only) |
4345
| 外部构建系统(`install()` 从源码构建) | [`compat.openblas`](pkgs/c/compat.openblas.lua)(Make) · [`compat.openssl`](pkgs/c/compat.openssl.lua)(Perl Configure + Make,静态 libssl/libcrypto) |

mcpp.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ members = [
1919
"tests/examples/core",
2020
"tests/examples/curl",
2121
"tests/examples/eigen",
22+
"tests/examples/eui-neo",
23+
"tests/examples/eui-neo-markdown",
24+
"tests/examples/eui-neo-sdl2",
25+
"tests/examples/eui-neo-vulkan",
2226
"tests/examples/ffmpeg",
2327
"tests/examples/ffmpeg-module",
2428
"tests/examples/fmtlib.fmt",

pkgs/c/compat.vulkan.lua

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,32 @@
2020
-- entry points (ones this loader version has never heard of) get no
2121
-- trampoline, which no consumer in this index uses.
2222
--
23-
-- WINDOWS IS DEFERRED. A statically linked loader is not something upstream
24-
-- supports there: the only static option in its CMake is `APPLE_STATIC_LOADER`,
25-
-- gated to macOS and carrying the warning that it "will only work on MacOS and
26-
-- is not supported" elsewhere. Built anyway, the Windows loader links but faults
27-
-- at the first entry point (0xC0000005 out of vkEnumerateInstanceVersion). Linux
28-
-- is not covered by that option either, but a static loader is the ordinary
29-
-- case there and works — Chromium ships one. Rather than carry a package that
30-
-- crashes, this follows `compat.openssl` and declares no windows xpm entry;
31-
-- consumers gate with `[target.'cfg(...)']`.
23+
-- WINDOWS TAKES A DIFFERENT SHAPE: an import library, not a built loader.
24+
--
25+
-- A statically linked loader cannot work there, and the reason is in upstream's
26+
-- own source rather than just its docs. `vk_loader_platform.h` says the Windows
27+
-- build "does initialization in the first API call made, using
28+
-- InitOnceExecuteOnce, EXCEPT for initialization primitives which must be done
29+
-- in DllMain" — and `loader_windows.c`'s DllMain is what creates `loader_lock`
30+
-- and `loader_preload_icd_lock`. A static library never gets a DllMain, so the
31+
-- first API call takes an uninitialized CRITICAL_SECTION and faults
32+
-- (0xC0000005 out of vkEnumerateInstanceVersion, observed in CI). macOS escapes
33+
-- this through `APPLE_STATIC_LOADER` + pthread_once; Linux through
34+
-- `__attribute__((constructor))`. Windows has neither.
35+
--
36+
-- The supported Windows arrangement is the ordinary one every Vulkan
37+
-- application uses: link `vulkan-1.lib` and let the system `vulkan-1.dll`,
38+
-- installed by any GPU driver, do the ICD loading. The windows xpm entry is
39+
-- therefore a small artifact carrying that import library — symbol stubs, no
40+
-- code — generated from Khronos' own `loader/vulkan-1.def` (shipped in this
41+
-- very loader tarball) with a single reproducible command:
42+
--
43+
-- llvm-dlltool -d vulkan-1.def -l lib/vulkan-1.lib -m i386:x86-64
44+
--
45+
-- Deliberately NOT an install() hook running that command at build time: the
46+
-- hook would have to locate llvm-dlltool inside the resolved toolchain, and the
47+
-- output is a fixed function of an upstream text file. Prebuilt Windows
48+
-- artifacts on xlings-res are the pattern `compat.openssl` already anticipates.
3249
--
3350
-- SYSCONFDIR / FALLBACK_*_DIRS are the ICD and layer manifest search paths.
3451
-- Upstream's CMake derives them from the install prefix; the values below are
@@ -65,14 +82,24 @@ package = {
6582
sha256 = "54f2537df22313768da0317dda2abdaaab7711b4081c48c869a79db343d0ae70",
6683
},
6784
},
68-
-- windows deferred, see the note at the top of this file.
85+
windows = {
86+
["1.4.357.0"] = {
87+
url = {
88+
GLOBAL = "https://github.com/xlings-res/vulkan-import/releases/download/1.4.357.0/vulkan-import-1.4.357.0.tar.gz",
89+
CN = "https://gitcode.com/mcpp-res/vulkan-import/releases/download/1.4.357.0/vulkan-import-1.4.357.0.tar.gz",
90+
},
91+
sha256 = "a45bf6d71a6977ee1d3e134218f5506e3ff2f73df7731dba107329411c7e1c7d",
92+
},
93+
},
6994
},
7095

7196
mcpp = {
7297
language = "c++23",
7398
import_std = false,
7499
c_standard = "c11",
75100

101+
-- `*/loader*` simply match nothing in the windows artifact, which
102+
-- carries only lib/ and the .def.
76103
include_dirs = { "*/loader", "*/loader/generated", "mcpp_generated" },
77104

78105
-- SYSCONFDIR / FALLBACK_*_DIRS have to reach the compiler as STRING
@@ -83,6 +110,8 @@ package = {
83110
-- the command line entirely — the same move `compat.opencv5` made for
84111
-- its space-bearing defines.
85112
generated_files = {
113+
["mcpp_generated/vulkan_import_anchor.c"] =
114+
"int mcpp_compat_vulkan_import_anchor(void) { return 0; }\n",
86115
["mcpp_generated/mcpp_vulkan_paths.h"] = [==[
87116
/* Manifest search paths for the Vulkan loader — see the descriptor note. */
88117
#pragma once
@@ -184,6 +213,17 @@ package = {
184213
},
185214
},
186215

187-
-- No `windows` block: see the deferral note at the top.
216+
windows = {
217+
-- Nothing to compile: the artifact is the import library plus the
218+
-- .def it came from. The anchor keeps a buildable lib target, the
219+
-- same shape `compat.opengl` uses for a headers-only package.
220+
sources = { "mcpp_generated/vulkan_import_anchor.c" },
221+
ldflags = { "-Llib", "-lvulkan-1" },
222+
runtime = {
223+
-- vulkan-1.dll ships with the GPU driver, not with us.
224+
dlopen_libs = { "vulkan-1.dll" },
225+
capabilities = { "vulkan.icd.driver" },
226+
},
227+
},
188228
},
189229
}

0 commit comments

Comments
 (0)