diff --git a/.agents/docs/2026-11-15-bump-eui-neo-0.6.3-plan.md b/.agents/docs/2026-11-15-bump-eui-neo-0.6.3-plan.md new file mode 100644 index 00000000..5a93a8b5 --- /dev/null +++ b/.agents/docs/2026-11-15-bump-eui-neo-0.6.3-plan.md @@ -0,0 +1,129 @@ +# Design doc: bump `compat.eui-neo` to 0.6.3 + +Date: 2026-11-15 + +Follow-up to `.agents/docs/2026-10-30-bump-eui-neo-0.6.2-plan.md` and commit `1809c8b` (0.6.2). +Upstream released 0.6.3; this bumps the index from 0.6.2 to 0.6.3. + +## Source and version + +| | | +|---|---| +| Upstream | `https://github.com/sudoevolve/EUI-NEO` | +| Version | `0.6.3` (latest release, 2026-11-12) | +| Tarball | `archive/refs/tags/v0.6.3.tar.gz` | +| sha256 | `08074e2fb72662c8a4c2f7d75dec558aed2c751545797e0ccccbdbe8f439b669` (computed twice from two fresh downloads, stable) | +| Wrap dir | `EUI-NEO-0.6.3/` — absorbed by the existing `install()` hook (`normalise_layout`) | +| CN mirror | **pending** — no `mcpp-res` write access on this machine; plain-string url fallback per SOP | +| License | Apache-2.0 (unchanged) | +| Auto-update | not covered by `.github/xpkgindex-update.yml` (the descriptor has `generated_files` + an `install()` hook); bumped manually | + +## What changed upstream (0.6.2 → 0.6.3) + +Release notes: `docs/releases/v0.6.3.md` (keyboard navigation + focus, a +backend-agnostic widget semantics snapshot, virtualized `dataTable`, system +save/directory dialogs, input undo byte budgets, line-chart sampling, +async/serial lifecycle fixes, docs reorganisation). + +- **`CORE_SOURCES` and `VULKAN_SOURCES` are byte-identical to 0.6.2** + (extracted and diffed from both `CMakeLists.txt`). Every changed core file + is already in the source list (`async.cpp`, `platform.cpp`, `primitive.cpp`, + runtime headers, `window_backend.cpp`); the only new headers are + `core/accessibility.h` and `include/eui/accessibility.h`, both header-only + and re-exported by `include/eui_neo.h`. +- **The one link-line change**: upstream's Windows block grew + `ole32 comdlg32 uuid` (`target_link_libraries(eui_neo PUBLIC …)`), for + `platform.cpp`'s new directory picker (`CoCreateInstance(CLSID_FileOpenDialog, + … IID_PPV_ARGS)`, `SHCreateItemFromParsingName`). This descriptor already + named ole32/comdlg32 from the 0.6.1 CI work; `-luuid` is the new name (the + `IID_*`/`CLSID_*` GUID symbols). The linux implementation shells out to + zenity/kdialog and the macOS one to osascript, so neither leg gains a + link-time dependency. +- **New optional module with a TU**: `modules/serial/` ships + `serial.cpp`/`serial.h` and CMake builds it as `eui::module_serial`, a + separate target linking `eui::neo` — it is NOT part of `CORE_SOURCES`, and + the only in-tree consumer is the `serial_tool` example and the `serial_port` + unit test (which compiles the TU per-test). Exposed here as the `serial` + feature (see below). `modules/keyboard/` is a single header with no TU, so + it needs no feature entry — the `*` include root already serves it. +- The SDL2 branch of `window_backend.cpp` keeps 0.6.2's hoisted + `sendX11MoveResizeForWindow` definition (`#endif` position unchanged across + 0.6.2 → 0.6.3, diffed), so the 0.6.1-era package-private template stub in + `mcpp_eui_backends.h` stays inert on non-linux and the linux + `SDL_VIDEO_DRIVER_X11` define stays a practical no-op. **No shim change.** +- No build-config macro changed: the `EUI_*` macro set extracted from + `core/`, `include/` and `components/` is identical between 0.6.1 and 0.6.3. + +## Descriptor changes (`pkgs/e/compat.eui-neo.lua`) + +- `xpm.["0.6.3"]`: plain-string GLOBAL url (no CN + mirror yet), sha256 above. +- Windows `ldflags`: `-luuid` added, with the rationale next to it. +- New `serial` feature: `sources = { "*/modules/serial/serial.cpp" }` — + source-gated exactly like `app-main`; a consumer that names it includes + `` through the existing `*` include root. +- File-top version note for 0.6.3; the `CORE_SOURCES` recipe reference moved + to `v0.6.3`. + +## Test members + +- All seven `tests/examples/eui-neo*` members: pin `0.6.2` → `0.6.3`. +- **New member `tests/examples/eui-neo-serial`** (registered in the root + `mcpp.toml` workspace): asserts the feature at link time (SerialPort ctor/ + dtor/open/isOpen come from `serial.cpp`) and at runtime opens a device path + that cannot exist, so `!open().ok`, `!isOpen()`, and move-ownership leaving + the moved-from object closed — no hardware, no privileges. + +## Verification + +Local Linux x86_64, mcpp **2026.11.15.1** (the CI `MCPP_VERSION`, downloaded +as the release tarball), `MCPP_INDEX_MIRROR=GLOBAL`, every member cold +(`target/` and `.mcpp/` removed) before its run: + +| Member | Result | +|---|---| +| `eui-neo` | `test result ok` — `compat.eui-neo smoke test: ok (parsed eui-neo v3, markdown gated off)` | +| `eui-neo-window` | `test result ok` — own-main loop linked, window run opt-in | +| `eui-neo-app-main` | `test result ok` — package-supplied `main()` linked | +| `eui-neo-markdown` | `test result ok` — `markdown: ok (2 blocks, h1 = 'Heading')` | +| `eui-neo-tray` | `test result ok` — `linux tray backend verified over a private session bus` | +| `eui-neo-vulkan` | `test result ok` — `backend=vulkan, loader api 1.4.357` | +| `eui-neo-sdl2` | `test result ok` — `SDL driver=dummy, curl 8.21.0-DEV ssl=OpenSSL/3.5.1` | +| `eui-neo-serial` | `test result ok` — feature on: link + runtime assertions pass | + +Negative verification for `serial`: with the feature removed from the +member's dependency declaration, the cold build fails at link with +`undefined reference to 'core::serial::SerialPort::SerialPort()'` (and +`isOpen`, `open`, the move ctor, `close`, the dtor) — the gating is real, not +a default. Restoring the feature returns the member to `test result ok`. + +Index lint: `check_mirror_urls`, `check_package_name`, +`check_reserved_namespace`, `check_cross_package_refs`, +`check_platform_version_parity`, `check_duplicate_versions` — all clean; +`mcpp xpkg parse` reports `features 7`, `parse OK`. + +Known local noise (pre-existing, not caused by this bump): the sdl2 member's +link prints mcpp's "one library, two providers" note for zlib +(`compat.zlib` vs glib's runtime `libz.so.1`, mcpp#519). The descriptor +already documents why libz is not staged. + +## CI status + +PR #804 (run `43730038159`), all legs green: `lint`, `select`, `build`, `scan`, +`mirror-cn-reachable`, `graphics install: no side effects on unrelated +members`, workspace linux default + llvm 0–3/4, macOS, Windows, and the +`candidate (compat:eui-neo 0.6.3)` install/build legs on linux +default/llvm, macosx and windows. The Windows candidate + workspace legs are +what validate `-luuid` and `serial.cpp`'s `windows.h` branch; the macOS leg +validates the termios branch and the framework links. + +## Notes + +- macOS and Windows legs are unverified locally; the CI `workspace` legs are + authoritative for `-luuid` and for `serial.cpp`'s `windows.h`/termios + branches. +- The `serial` feature is new surface, so the 0.6.3 bump is two things at + once: three version entries and the first descriptor-level exposure of + upstream's module system. If CI finds a platform-specific break in + `serial.cpp`, the version entries stand on their own and the feature can be + reverted without touching them. diff --git a/mcpp.toml b/mcpp.toml index 6a523cc7..8afec9a6 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -100,6 +100,7 @@ members = [ "tests/examples/eui-neo-app-main", "tests/examples/eui-neo-markdown", "tests/examples/eui-neo-sdl2", + "tests/examples/eui-neo-serial", "tests/examples/eui-neo-tray", "tests/examples/eui-neo-vulkan", "tests/examples/eui-neo-window", diff --git a/pkgs/e/compat.eui-neo.lua b/pkgs/e/compat.eui-neo.lua index 1b2be93a..e62ec5e1 100644 --- a/pkgs/e/compat.eui-neo.lua +++ b/pkgs/e/compat.eui-neo.lua @@ -40,7 +40,30 @@ -- fails with "malformed mcpp segment", measured), so one header must serve -- every published version, and the template is what makes that possible. -- --- The build recipe below tracks upstream `CMakeLists.txt` (v0.6.2): CORE_SOURCES +-- 0.6.3: CORE_SOURCES and VULKAN_SOURCES are byte-identical to 0.6.2, so the +-- lib's source list, deps, features and flags carry over unchanged. The +-- release is keyboard navigation + accessibility semantics snapshots, data- +-- table virtualization, the system save/directory dialogs, input undo budgets +-- and the line-chart sampling path. What it DOES move, and what a bump has to +-- follow: +-- * `platform.cpp` grows the Windows directory picker (IFileOpenDialog, +-- SHCreateItemFromParsingName, CLSID_FileOpenDialog), so upstream's link +-- line now names ole32/comdlg32/uuid. This descriptor already carried +-- ole32 + comdlg32 from the 0.6.1 CI work; `-luuid` is the new one (the +-- IID_/CLSID_ symbols). The linux/macOS implementations shell out to +-- zenity/kdialog/osascript, so they add no link-time dependency. +-- * `modules/serial/` is upstream's first optional module with a TU of its +-- own (`serial.cpp`, built as `eui::module_serial` in CMake, NOT part of +-- CORE_SOURCES). It is exposed as the `serial` feature; `modules/keyboard` +-- is header-only and already reachable through the `*` include root. +-- * `core/accessibility.h` + `include/eui/accessibility.h` are header-only: +-- `include/eui_neo.h` re-exports the snapshot types, nothing gains a TU. +-- * the SDL2 branch of `window_backend.cpp` keeps 0.6.2's hoisted +-- sendX11MoveResizeForWindow definition (diffed, `#endif` position +-- unchanged), so the template stub below stays inert on non-linux and the +-- linux `SDL_VIDEO_DRIVER_X11` define stays a no-op in practice. +-- +-- The build recipe below tracks upstream `CMakeLists.txt` (v0.6.3): CORE_SOURCES -- plus the OpenGL backend and, for the glfw window backend, `ime_bridge.c`. -- 0.5.5 grew a Shadertoy subsystem: render_backend.h and include/eui/types.h now -- include core/render/shadertoy.h unconditionally, and opengl_backend.cpp calls @@ -281,6 +304,14 @@ package = { url = "https://github.com/sudoevolve/EUI-NEO/archive/refs/tags/v0.6.2.tar.gz", sha256 = "189d97aadb044de653237e12ac97d6fa92f1a65952854e3db6211d360f4d4124", }, + -- 0.6.3: CORE_SOURCES/VULKAN_SOURCES byte-identical to 0.6.2; the + -- windows leg gains -luuid and the descriptor gains the `serial` + -- feature (see the file-top note). No CN mirror yet — plain-string + -- GLOBAL url, same as 0.6.2. + ["0.6.3"] = { + url = "https://github.com/sudoevolve/EUI-NEO/archive/refs/tags/v0.6.3.tar.gz", + sha256 = "08074e2fb72662c8a4c2f7d75dec558aed2c751545797e0ccccbdbe8f439b669", + }, }, macosx = { ["0.5.3"] = { @@ -338,6 +369,11 @@ package = { url = "https://github.com/sudoevolve/EUI-NEO/archive/refs/tags/v0.6.2.tar.gz", sha256 = "189d97aadb044de653237e12ac97d6fa92f1a65952854e3db6211d360f4d4124", }, + -- 0.6.3: see the linux block — plain-string GLOBAL, no CN mirror. + ["0.6.3"] = { + url = "https://github.com/sudoevolve/EUI-NEO/archive/refs/tags/v0.6.3.tar.gz", + sha256 = "08074e2fb72662c8a4c2f7d75dec558aed2c751545797e0ccccbdbe8f439b669", + }, }, windows = { ["0.5.3"] = { @@ -395,6 +431,11 @@ package = { url = "https://github.com/sudoevolve/EUI-NEO/archive/refs/tags/v0.6.2.tar.gz", sha256 = "189d97aadb044de653237e12ac97d6fa92f1a65952854e3db6211d360f4d4124", }, + -- 0.6.3: see the linux block — plain-string GLOBAL, no CN mirror. + ["0.6.3"] = { + url = "https://github.com/sudoevolve/EUI-NEO/archive/refs/tags/v0.6.3.tar.gz", + sha256 = "08074e2fb72662c8a4c2f7d75dec558aed2c751545797e0ccccbdbe8f439b669", + }, }, }, @@ -727,6 +768,18 @@ inline bool sendX11MoveResizeForWindow(W* window, int direction) { defines = { "EUI_HAS_MD4C=1" }, deps = { ["compat.md4c"] = "0.5.3" }, }, + -- 0.6.3: `modules/serial/` is upstream's first optional module that + -- is NOT header-only — CMake builds `serial.cpp` into a separate + -- `eui::module_serial` target that links `eui::neo`. An xpkg + -- descriptor models one lib target, so the module's TU rides here + -- as an extra `sources` entry: a consumer that names `serial` gets + -- core::serial::SerialPort in the same archive and includes it as + -- `` (the `*` include root already + -- exposes the whole tree). Off by default, like every other + -- feature: a consumer that does not open a port does not pay for + -- the termios/Win32 code. `modules/keyboard` needs no entry — it + -- is a single header with no TU behind it. + ["serial"] = { sources = { "*/modules/serial/serial.cpp" } }, }, -- ── Platform-specific ────────────────────────────────────────────── @@ -787,10 +840,16 @@ inline bool sendX11MoveResizeForWindow(W* window, int direction) { -- the one TU in this package that had never been compiled — naming -- it costs nothing and the comment above is precisely about mcpp not -- inheriting CMake's defaults. + -- + -- uuid is 0.6.3's addition: platform.cpp's directory picker uses + -- CoCreateInstance(CLSID_FileOpenDialog, … IID_PPV_ARGS) and + -- SHCreateItemFromParsingName, whose IID_/CLSID_ GUIDs live in + -- uuid.lib (upstream's own 0.6.3 link line grew ole32 comdlg32 + -- uuid for the same TU). ole32/comdlg32 were already here. ldflags = { "-lwinmm", "-lurlmon", "-lshell32", "-luser32", "-limm32", "-lpdh", "-lole32", - "-lcomdlg32", "-lkernel32", + "-lcomdlg32", "-luuid", "-lkernel32", }, }, diff --git a/tests/examples/eui-neo-app-main/mcpp.toml b/tests/examples/eui-neo-app-main/mcpp.toml index 30f1fc56..48825807 100644 --- a/tests/examples/eui-neo-app-main/mcpp.toml +++ b/tests/examples/eui-neo-app-main/mcpp.toml @@ -30,4 +30,4 @@ name = "eui-neo-app-main-tests" version = "0.1.0" [dependencies.compat] -eui-neo = { version = "0.6.2", features = ["app-main"] } +eui-neo = { version = "0.6.3", features = ["app-main"] } diff --git a/tests/examples/eui-neo-markdown/mcpp.toml b/tests/examples/eui-neo-markdown/mcpp.toml index bd0535e1..5d99f3d5 100644 --- a/tests/examples/eui-neo-markdown/mcpp.toml +++ b/tests/examples/eui-neo-markdown/mcpp.toml @@ -7,4 +7,4 @@ version = "0.1.0" # what switches components/markdown.h from its fallback to the real parser. [dependencies.compat] -eui-neo = { version = "0.6.2", features = ["markdown"] } +eui-neo = { version = "0.6.3", features = ["markdown"] } diff --git a/tests/examples/eui-neo-sdl2/mcpp.toml b/tests/examples/eui-neo-sdl2/mcpp.toml index 784a2d96..1fe5bcf8 100644 --- a/tests/examples/eui-neo-sdl2/mcpp.toml +++ b/tests/examples/eui-neo-sdl2/mcpp.toml @@ -7,4 +7,4 @@ version = "0.1.0" # into a real libcurl-backed implementation. The render backend stays OpenGL, # unnamed — naming a feature no longer costs you the defaults. [dependencies.compat] -eui-neo = { version = "0.6.2", features = ["sdl2", "network"] } +eui-neo = { version = "0.6.3", features = ["sdl2", "network"] } diff --git a/tests/examples/eui-neo-serial/mcpp.toml b/tests/examples/eui-neo-serial/mcpp.toml new file mode 100644 index 00000000..8189a759 --- /dev/null +++ b/tests/examples/eui-neo-serial/mcpp.toml @@ -0,0 +1,18 @@ +[package] +name = "eui-neo-serial-tests" +version = "0.1.0" + +# compat.eui-neo's `serial` feature: modules/serial/serial.cpp is upstream's +# first optional module with a TU of its own (CMake builds it as +# eui::module_serial, outside CORE_SOURCES), so the descriptor exposes it as a +# source-gated feature rather than compiling termios/Win32 code into every +# consumer. +# +# The assertion is link-time first: without the feature, SerialPort's +# constructor/destructor/open() are undefined symbols. The runtime half opens a +# device path that cannot exist on any platform, so it needs no hardware and is +# deterministic — open() must report !ok and leave the port closed. +# +# The `compat` index redirect is inherited from the workspace root. +[dependencies.compat] +eui-neo = { version = "0.6.3", features = ["serial"] } diff --git a/tests/examples/eui-neo-serial/tests/serial.cpp b/tests/examples/eui-neo-serial/tests/serial.cpp new file mode 100644 index 00000000..2c08127e --- /dev/null +++ b/tests/examples/eui-neo-serial/tests/serial.cpp @@ -0,0 +1,50 @@ +// Verify compat.eui-neo's `serial` feature — upstream's first optional MODULE +// with a translation unit of its own (modules/serial/serial.cpp, built as +// eui::module_serial in CMake and absent from CORE_SOURCES). +// +// The primary assertion is LINK-time: SerialPort's ctor/dtor/open()/isOpen() +// only exist when the feature's `sources` entry compiled that TU into the +// package lib. Without it the program fails with undefined references, which +// is the negative result this member is here to make visible. +// +// The runtime half stays hardware-free on purpose: the device path cannot +// exist on any platform, so open() must fail and leave the port closed. 0.6.3 +// is the release that made a failed open release its handle and keep the +// previous connection; there is no previous connection here, so the observable +// contract is simply "still closed". No serial hardware, no privileges. +// +// Windows macros first: modules/serial/serial.h includes for the +// consumer, and this TU is compiled by the CONSUMER, which does not inherit the +// package-private NOMINMAX / WIN32_LEAN_AND_MEAN flags. +#if defined(_WIN32) +#ifndef NOMINMAX +#define NOMINMAX +#endif +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#endif + +#include + +#include + +int main() { + bool ok = true; + + core::serial::SerialPort port; + ok = ok && !port.isOpen(); + + const core::serial::OpenResult missing = + port.open("__mcpp_no_such_serial_device__", 115200); + ok = ok && !missing.ok; + ok = ok && missing.error != core::serial::OpenError::None; + ok = ok && !port.isOpen(); + + // 0.6.3: ownership is movable and the moved-from object ends up closed. + core::serial::SerialPort moved(std::move(port)); + ok = ok && !moved.isOpen(); + moved.close(); + + return ok ? 0 : 1; +} diff --git a/tests/examples/eui-neo-tray/mcpp.toml b/tests/examples/eui-neo-tray/mcpp.toml index 0d5f1696..f1cc4fdc 100644 --- a/tests/examples/eui-neo-tray/mcpp.toml +++ b/tests/examples/eui-neo-tray/mcpp.toml @@ -25,4 +25,4 @@ name = "eui-neo-tray-tests" version = "0.1.0" [dependencies.compat] -eui-neo = "0.6.2" +eui-neo = "0.6.3" diff --git a/tests/examples/eui-neo-vulkan/mcpp.toml b/tests/examples/eui-neo-vulkan/mcpp.toml index d82f5f24..45161f0b 100644 --- a/tests/examples/eui-neo-vulkan/mcpp.toml +++ b/tests/examples/eui-neo-vulkan/mcpp.toml @@ -6,7 +6,7 @@ version = "0.1.0" # package resolves the exclusive choice in its own preprocessor from the # MCPP_FEATURE_* flags. The window backend stays GLFW, unnamed. [dependencies.compat] -eui-neo = { version = "0.6.2", features = ["vulkan"] } +eui-neo = { version = "0.6.3", features = ["vulkan"] } [build] cxxflags = ["-DHAVE_EUI_VULKAN=1"] diff --git a/tests/examples/eui-neo-window/mcpp.toml b/tests/examples/eui-neo-window/mcpp.toml index bdb8f75f..a44a0dfa 100644 --- a/tests/examples/eui-neo-window/mcpp.toml +++ b/tests/examples/eui-neo-window/mcpp.toml @@ -34,4 +34,4 @@ name = "eui-neo-window-tests" version = "0.1.0" [dependencies.compat] -eui-neo = "0.6.2" +eui-neo = "0.6.3" diff --git a/tests/examples/eui-neo/mcpp.toml b/tests/examples/eui-neo/mcpp.toml index cdbfd1de..f040f91c 100644 --- a/tests/examples/eui-neo/mcpp.toml +++ b/tests/examples/eui-neo/mcpp.toml @@ -3,4 +3,4 @@ name = "eui-neo-tests" version = "0.1.0" [dependencies.compat] -eui-neo = "0.6.2" +eui-neo = "0.6.3"