Skip to content

feat: add compat.vulkan, sdl2, curl, glx-headers and vulkan-headers - #134

Merged
Sunrisepeak merged 1 commit into
mainfrom
feat/eui-neo-backends
Jul 28, 2026
Merged

feat: add compat.vulkan, sdl2, curl, glx-headers and vulkan-headers#134
Sunrisepeak merged 1 commit into
mainfrom
feat/eui-neo-backends

Conversation

@Sunrisepeak

@Sunrisepeak Sunrisepeak commented Jul 28, 2026

Copy link
Copy Markdown
Member

Merge this first — #133 depends on it.

Five packages behind the alternate GUI and network backends. They land together because
each exercised the same class of problem — an upstream that generates its build
configuration where this index wants a plain source list — and they are independently
useful: nothing here depends on any consumer.

package version what it is
compat.vulkan-headers 1.4.357.0 Khronos Vulkan headers
compat.vulkan 1.4.357.0 Khronos Vulkan loader, built from source
compat.curl 8.21.0 libcurl, OpenSSL on unix / Schannel on Windows
compat.sdl2 2.32.10 SDL2
compat.glx-headers 1.7.0 libglvnd's GL/glx.h

All five build from plain source lists — no CMake, no autotools, no install() hook.

Notes per package

compat.vulkan — buildable as a source list because loader/generated/ is checked in
upstream and the assembly path is optional: upstream gates dev_ext_trampoline.c /
phys_dev_ext.c on UNKNOWN_FUNCTIONS_SUPPORTED and falls back to
unknown_function_handling.c's pure-C implementation when no assembler is found. Two
things only a real build surfaces: VK_ENABLE_BETA_EXTENSIONS is mandatory despite the
name (the checked-in vk_object_types.h names VK_OBJECT_TYPE_CUDA_MODULE_NV), and
SYSCONFDIR/FALLBACK_*_DIRS must come through a force-included header because
-DSYSCONFDIR="/etc" does not survive mcpp's flag splitting (mcpp#234).

Windows is deferred for compat.vulkan. Upstream's only static-loader option is
APPLE_STATIC_LOADER, gated to macOS with the warning that it "will only work on MacOS and
is not supported" elsewhere; built anyway, the Windows loader links and then faults at the
first entry point (0xC0000005 out of vkEnumerateInstanceVersion). Linux is not covered by
that option either, but a static loader is the ordinary case there and works. Follows
compat.openssl; consumers gate with [target.'cfg(...)'].

compat.curl — every unselected protocol and TLS backend compiles to an empty TU, so
the source list is globs. Windows needs no generated config (lib/config-win32.h is
checked in and curl_setup.h selects it); unix gets one branching on __linux__ /
__APPLE__. Generating it against the right compiler mattered — a first pass with the
host cc claimed ssize_t did not exist and curl then failed against its own config.

compat.sdl2 — the mirror image: upstream checks in SDL_config_windows.h and
SDL_config_macosx.h, and only Linux falls through to SDL_config_minimal.h. Three things
the Linux config needed by hand, each found by building: X11 switched on (the CMake probe
ran without system X11 headers), libudev off, and src/core/linux listed file by file —
the one directory where a glob over-reaches, since SDL_dbus.c / SDL_ibus.c /
SDL_fcitx.c / SDL_ime.c are not internally guarded.

compat.glx-headers — SDL's X11 driver includes <GL/glx.h>, and no package in this
index had it: GL/glx.h is not part of the Khronos OpenGL-Registry, so compat.opengl
cannot supply it. libglvnd is the canonical provider and is already named as a wanted
package in 2026-06-03-gl-runtime-packages-plan.md. Headers only — compat.glx-runtime
still owns the runtime side. It overlaps compat.opengl on GL/gl.h, so depend on one or
the other, never both.

CURL_STATICLIB, and a deliberate use of an mcpp quirk

<curl/curl.h> declares everything __declspec(dllimport) unless CURL_STATICLIB is set,
so every Windows consumer of a static libcurl needs it — and no consumer should have to
know that. The define has to be always on AND consumer-visible, and mcpp has no single
key for that: cflags is always on but package-private, a feature's defines reach the
consumer but need naming.

default = { implies = … } gives both. A default feature's own defines are inert on
mcpp, but what it implies is applied unconditionally — verified on 0.0.109 (the CI pin)
and on 2026.7.29.1 (latest), so this is not version-specific. tests/examples/curl
deliberately does not define it and static_asserts that it arrived from the package;
deleting the default line makes that assertion fire.

Cross-platform results

All five checks green. Every member built and run on all three platforms:

linux macos windows
compat.vulkan loader api 1.4.357, WSI trampolines linked same skipped (deferred)
compat.curl ssl=OpenSSL/3.5.1 ssl=OpenSSL/3.5.1 ssl=Schannel
compat.sdl2 driver=dummy, 320x240 window, events round-tripped same same

Things only CI could find

Linux passed on the first try; each of these was silent or misleading locally.

  • SDL2's tag archive cannot be extracted on Windows — two POSIX symlinks under
    android-project-ant/. The package then "installs" empty: reports success, compiles
    nothing, exports no include dirs, and every consumer fails with 'SDL.h' file not found
    while the package itself never errors. chriskohlhoff.asio set the precedent, so GLOBAL
    points at a symlink-free repack on xlings-res/sdl2 with identical bytes mirrored to
    mcpp-res.
  • SDL on Apple requires ARC — its cocoa classes declare __weak SDL_WindowData *_data,
    and a __weak ivar without -fobjc-arc is rejected ('_data' is unavailable).
  • SDL on Windows needs HAVE_LIBC — upstream's config only sets it for _MSC_VER, and
    this index builds with clang++, so SDL compiled its own memcpy and collided with
    libvcruntime.
  • SDL's Windows condvar falls back to thread/generic/SDL_syscond.c — but the rest of
    thread/generic shares basenames with thread/windows, so only that one file can be
    added (mcpp#233: objects are keyed by basename in one flat per-link directory).
  • SDL's macOS config also enables the X11 driver, loaded from /opt/X11; #undef'd,
    since it would make src/video/x11 a compile dependency on Apple for a driver nobody
    reaches with Cocoa present.
  • src/joystick/iphoneos serves macOS tooSDL_JOYSTICK_MFI is on there.
  • curl must be told which strerror_r it has and refuses to build otherwise; Apple's
    is POSIX, glibc's returns char*.
  • curl needs secur32 on Windows and CoreFoundation + SystemConfiguration on
    macOS.

What the tests can and cannot assert

  • SDL2 genuinely runs. Its dummy video driver is a real driver, so the test executes
    SDL_Init, SDL_CreateWindow, SDL_GetWindowSize and a full event round-trip. It is
    the only one here that can be exercised rather than merely linked.
  • Vulkan is driverless by construction. The loader advertises WSI surface extensions
    only when an ICD supports them, so VK_KHR_surface is legitimately absent without a GPU
    — an early draft asserted on it and failed, which is exactly the "testing the runner's
    hardware" trap. Asserted instead: vkEnumerateInstanceVersion (answerable only by the
    loader), VK_EXT_debug_utils (loader-implemented, driver-independent), and a reference
    to vkDestroySurfaceKHR as link-time proof that wsi.c is in the library.
  • curl never opens a connection. Asserted: init succeeds, CURL_VERSION_SSL with a
    non-null ssl_version (a curl built without TLS still links and runs — it just cannot do
    https), http+https in the protocol list, and that a handle accepts a real option set.
  • No frame is drawn anywhere, on any platform.

CN mirrors published to gitcode mcpp-res for all five, byte-identical to GLOBAL, 200 on
curl. Full validate.yml lint reproduced locally over the whole repo.

Design: .agents/docs/2026-07-29-add-gui-backend-packages-plan.md

Five packages behind the alternate GUI and network backends. They land
together because each exercised the same class of problem — an upstream that
generates its build configuration where this index wants a plain source list —
and they are independently useful; nothing here depends on any consumer.

  compat.vulkan-headers  1.4.357.0   Khronos headers
  compat.vulkan          1.4.357.0   Khronos loader, from source (windows deferred)
  compat.curl            8.21.0      libcurl, OpenSSL / Schannel TLS
  compat.sdl2            2.32.10     SDL2
  compat.glx-headers     1.7.0       libglvnd's GL/glx.h

All five build from plain source lists: no CMake, no autotools, no install().
The Vulkan loader manages it because loader/generated/ is checked in and the
GAS/MASM path is optional (UNKNOWN_FUNCTIONS_SUPPORTED gates it; upstream
itself falls back to a pure-C implementation). curl and SDL manage it because
both compile every unselected backend to an empty TU, so configuration lives
entirely in a generated config header — needed only where upstream has a gap:
unix for curl, linux for SDL, since both check in configs for the rest.

compat.glx-headers fills a real hole: GL/glx.h is not in the Khronos
OpenGL-Registry, so compat.opengl cannot supply it, and SDL's X11 driver does
not build without it.

compat.vulkan declares no windows entry. Upstream's only static-loader option
is APPLE_STATIC_LOADER, gated to macOS with the warning that it "will only work
on MacOS and is not supported" elsewhere; built anyway, the Windows loader
links and then faults at the first entry point. This follows compat.openssl.

CURL_STATICLIB needs to be always-on AND consumer-visible, and mcpp has no
single key for that — cflags is always on but package-private, a feature's
defines reach the consumer but need naming. `default = { implies = ... }` gives
both: a default feature's own defines are inert, but what it implies is applied
unconditionally (verified on 0.0.109 and 2026.7.29.1). tests/examples/curl does
not define it and static_asserts that it arrived from the package; removing the
default line makes that assertion fire.

Verified cold on all three platforms. SDL2 is the one backend that genuinely
runs headless — its dummy video driver executes SDL_Init, SDL_CreateWindow and
a full event round-trip. Vulkan and curl are asserted on what is answerable
without a GPU or a network; several near-misses there are recorded in the
design doc, including a first draft that asserted on VK_KHR_surface and was
really testing the runner's hardware.

Windows and macOS each surfaced problems invisible on Linux, most notably that
SDL2's tag archive carries POSIX symlinks and cannot be extracted on Windows —
the package then installs empty, reports success, and every consumer fails with
'SDL.h' file not found. GLOBAL now points at a symlink-free repack on
xlings-res/sdl2, following chriskohlhoff.asio.

CN mirrors published to gitcode mcpp-res for all five, byte-identical.

Design: .agents/docs/2026-07-29-add-gui-backend-packages-plan.md

Co-authored-by: SPeak Agent <248744407+speak-agent@users.noreply.github.com>
@Sunrisepeak
Sunrisepeak force-pushed the feat/eui-neo-backends branch from b522531 to 366beb3 Compare July 28, 2026 22:28
Sunrisepeak pushed a commit to FarnaHerry/mcpp-index that referenced this pull request Jul 28, 2026
…ends

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 mcpplibs#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 mcpplibs#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>
@Sunrisepeak Sunrisepeak changed the title feat: add compat.vulkan/sdl2/curl + glx-headers, wire eui-neo's alternate backends feat: add compat.vulkan, sdl2, curl, glx-headers and vulkan-headers Jul 28, 2026
@Sunrisepeak
Sunrisepeak merged commit 6da8452 into main Jul 28, 2026
5 checks passed
Sunrisepeak pushed a commit to FarnaHerry/mcpp-index that referenced this pull request Jul 28, 2026
…ends

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 mcpplibs#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 mcpplibs#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>
Sunrisepeak pushed a commit to FarnaHerry/mcpp-index that referenced this pull request Jul 28, 2026
…ends

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 mcpplibs#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 mcpplibs#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>
Sunrisepeak pushed a commit to FarnaHerry/mcpp-index that referenced this pull request Jul 28, 2026
…ends

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.

Builds on mcpplibs#134 (compat.vulkan / sdl2 / curl), and carries two fixes to that
half that only a machine with a GPU could have found — see below.

Backend selection. 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.
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 = ... }` always applies,
and a package-level define cannot be unset. Verified with probes on 0.0.109 and
2026.7.29.1. What works is resolving the choice in the preprocessor from the
-DMCPP_FEATURE_<NAME> flags mcpp already passes, via a force-included header.

That exposed a second problem: mcpp routes `cflags` to C translation units and
`cxxflags` to C++ ones. The first revision carried only
`cflags = { "-DEUI_RENDER_BACKEND_OPENGL=1" }`, so render_backend.cpp never saw
it — the package built, linked, passed its tests, and had no render backend.

REAL GUI VERIFICATION, on a workstation with an X display and an RTX 4080: all
four backend combinations open a window, create the backend and present three
frames, with no environment variables set. Getting the Vulkan half there needed
two changes, both invisible to a headless test:

  * compat.vulkan-runtime (new) — the loader found every host ICD manifest and
    then failed to dlopen any driver, because an mcpp binary runs under mcpp's
    own glibc and a bare-soname dlopen never searches the host path. This is
    the counterpart of compat.glx-runtime, which is why OpenGL already worked:
    a symlink farm plus runtime.library_dirs, no vendored driver. Instance
    extensions 4 -> 22. Versioned sonames only — library_dirs lands on the link
    line too, so a bare libxcb.so there shadows compat.xcb.

  * compat.vulkan is now kind="shared" with soname libvulkan.so.1. SDL2's
    SDL_CreateWindow(SDL_WINDOW_VULKAN) dlopens libvulkan.so.1 and resolves
    surface creation through whatever it finds; against a static loader the
    application ends up with two, and createSurface gets an instance the second
    one never saw. Shared, the application, GLFW (via glfwInitVulkanLoader) and
    SDL all converge on one object — which is what the loader is designed to be.

Also: glfwInitVulkanLoader must be called before glfwInit. Upstream's
glfw_app_main.cpp gets this right; a consumer writing its own entry point must
too.

Verified cold on all three platforms with mcpp 0.0.109, plus the local GUI
harness on Linux.

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

Co-authored-by: SPeak Agent <248744407+speak-agent@users.noreply.github.com>
Sunrisepeak pushed a commit to FarnaHerry/mcpp-index that referenced this pull request Jul 29, 2026
…ends

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.

Builds on mcpplibs#134 (compat.vulkan / sdl2 / curl), and carries two fixes to that
half that only a machine with a GPU could have found — see below.

Backend selection. 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.
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 = ... }` always applies,
and a package-level define cannot be unset. Verified with probes on 0.0.109 and
2026.7.29.1. What works is resolving the choice in the preprocessor from the
-DMCPP_FEATURE_<NAME> flags mcpp already passes, via a force-included header.

That exposed a second problem: mcpp routes `cflags` to C translation units and
`cxxflags` to C++ ones. The first revision carried only
`cflags = { "-DEUI_RENDER_BACKEND_OPENGL=1" }`, so render_backend.cpp never saw
it — the package built, linked, passed its tests, and had no render backend.

REAL GUI VERIFICATION, on a workstation with an X display and an RTX 4080: all
four backend combinations open a window, create the backend and present three
frames, with no environment variables set. Getting the Vulkan half there needed
two changes, both invisible to a headless test:

  * compat.vulkan-runtime (new) — the loader found every host ICD manifest and
    then failed to dlopen any driver, because an mcpp binary runs under mcpp's
    own glibc and a bare-soname dlopen never searches the host path. This is
    the counterpart of compat.glx-runtime, which is why OpenGL already worked:
    a symlink farm plus runtime.library_dirs, no vendored driver. Instance
    extensions 4 -> 22. Versioned sonames only — library_dirs lands on the link
    line too, so a bare libxcb.so there shadows compat.xcb.

  * compat.vulkan is now kind="shared" with soname libvulkan.so.1. SDL2's
    SDL_CreateWindow(SDL_WINDOW_VULKAN) dlopens libvulkan.so.1 and resolves
    surface creation through whatever it finds; against a static loader the
    application ends up with two, and createSurface gets an instance the second
    one never saw. Shared, the application, GLFW (via glfwInitVulkanLoader) and
    SDL all converge on one object — which is what the loader is designed to be.

Also: glfwInitVulkanLoader must be called before glfwInit. Upstream's
glfw_app_main.cpp gets this right; a consumer writing its own entry point must
too.

Verified cold on all three platforms with mcpp 0.0.109, plus the local GUI
harness on Linux.

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

Co-authored-by: SPeak Agent <248744407+speak-agent@users.noreply.github.com>
Sunrisepeak pushed a commit to FarnaHerry/mcpp-index that referenced this pull request Jul 29, 2026
…ends

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.

Builds on mcpplibs#134 (compat.vulkan / sdl2 / curl), and carries two fixes to that
half that only a machine with a GPU could have found — see below.

Backend selection. 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.
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 = ... }` always applies,
and a package-level define cannot be unset. Verified with probes on 0.0.109 and
2026.7.29.1. What works is resolving the choice in the preprocessor from the
-DMCPP_FEATURE_<NAME> flags mcpp already passes, via a force-included header.

That exposed a second problem: mcpp routes `cflags` to C translation units and
`cxxflags` to C++ ones. The first revision carried only
`cflags = { "-DEUI_RENDER_BACKEND_OPENGL=1" }`, so render_backend.cpp never saw
it — the package built, linked, passed its tests, and had no render backend.

REAL GUI VERIFICATION, on a workstation with an X display and an RTX 4080: all
four backend combinations open a window, create the backend and present three
frames, with no environment variables set. Getting the Vulkan half there needed
two changes, both invisible to a headless test:

  * compat.vulkan-runtime (new) — the loader found every host ICD manifest and
    then failed to dlopen any driver, because an mcpp binary runs under mcpp's
    own glibc and a bare-soname dlopen never searches the host path. This is
    the counterpart of compat.glx-runtime, which is why OpenGL already worked:
    a symlink farm plus runtime.library_dirs, no vendored driver. Instance
    extensions 4 -> 22. Versioned sonames only — library_dirs lands on the link
    line too, so a bare libxcb.so there shadows compat.xcb.

  * compat.vulkan is now kind="shared" with soname libvulkan.so.1. SDL2's
    SDL_CreateWindow(SDL_WINDOW_VULKAN) dlopens libvulkan.so.1 and resolves
    surface creation through whatever it finds; against a static loader the
    application ends up with two, and createSurface gets an instance the second
    one never saw. Shared, the application, GLFW (via glfwInitVulkanLoader) and
    SDL all converge on one object — which is what the loader is designed to be.

Also: glfwInitVulkanLoader must be called before glfwInit. Upstream's
glfw_app_main.cpp gets this right; a consumer writing its own entry point must
too.

Verified cold on all three platforms with mcpp 0.0.109, plus the local GUI
harness on Linux.

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

Co-authored-by: SPeak Agent <248744407+speak-agent@users.noreply.github.com>
Sunrisepeak pushed a commit to FarnaHerry/mcpp-index that referenced this pull request Jul 29, 2026
…ends

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.

Builds on mcpplibs#134 (compat.vulkan / sdl2 / curl), and carries two fixes to that
half that only a machine with a GPU could have found — see below.

Backend selection. 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.
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 = ... }` always applies,
and a package-level define cannot be unset. Verified with probes on 0.0.109 and
2026.7.29.1. What works is resolving the choice in the preprocessor from the
-DMCPP_FEATURE_<NAME> flags mcpp already passes, via a force-included header.

That exposed a second problem: mcpp routes `cflags` to C translation units and
`cxxflags` to C++ ones. The first revision carried only
`cflags = { "-DEUI_RENDER_BACKEND_OPENGL=1" }`, so render_backend.cpp never saw
it — the package built, linked, passed its tests, and had no render backend.

REAL GUI VERIFICATION, on a workstation with an X display and an RTX 4080: all
four backend combinations open a window, create the backend and present three
frames, with no environment variables set. Getting the Vulkan half there needed
two changes, both invisible to a headless test:

  * compat.vulkan-runtime (new) — the loader found every host ICD manifest and
    then failed to dlopen any driver, because an mcpp binary runs under mcpp's
    own glibc and a bare-soname dlopen never searches the host path. This is
    the counterpart of compat.glx-runtime, which is why OpenGL already worked:
    a symlink farm plus runtime.library_dirs, no vendored driver. Instance
    extensions 4 -> 22. Versioned sonames only — library_dirs lands on the link
    line too, so a bare libxcb.so there shadows compat.xcb.

  * compat.vulkan is now kind="shared" with soname libvulkan.so.1. SDL2's
    SDL_CreateWindow(SDL_WINDOW_VULKAN) dlopens libvulkan.so.1 and resolves
    surface creation through whatever it finds; against a static loader the
    application ends up with two, and createSurface gets an instance the second
    one never saw. Shared, the application, GLFW (via glfwInitVulkanLoader) and
    SDL all converge on one object — which is what the loader is designed to be.

Also: glfwInitVulkanLoader must be called before glfwInit. Upstream's
glfw_app_main.cpp gets this right; a consumer writing its own entry point must
too.

Verified cold on all three platforms with mcpp 0.0.109, plus the local GUI
harness on Linux.

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

Co-authored-by: SPeak Agent <248744407+speak-agent@users.noreply.github.com>
Sunrisepeak pushed a commit that referenced this pull request Jul 29, 2026
…ends (#133)

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.

Builds on #134 (compat.vulkan / sdl2 / curl), and carries two fixes to that
half that only a machine with a GPU could have found — see below.

Backend selection. 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.
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 = ... }` always applies,
and a package-level define cannot be unset. Verified with probes on 0.0.109 and
2026.7.29.1. What works is resolving the choice in the preprocessor from the
-DMCPP_FEATURE_<NAME> flags mcpp already passes, via a force-included header.

That exposed a second problem: mcpp routes `cflags` to C translation units and
`cxxflags` to C++ ones. The first revision carried only
`cflags = { "-DEUI_RENDER_BACKEND_OPENGL=1" }`, so render_backend.cpp never saw
it — the package built, linked, passed its tests, and had no render backend.

REAL GUI VERIFICATION, on a workstation with an X display and an RTX 4080: all
four backend combinations open a window, create the backend and present three
frames, with no environment variables set. Getting the Vulkan half there needed
two changes, both invisible to a headless test:

  * compat.vulkan-runtime (new) — the loader found every host ICD manifest and
    then failed to dlopen any driver, because an mcpp binary runs under mcpp's
    own glibc and a bare-soname dlopen never searches the host path. This is
    the counterpart of compat.glx-runtime, which is why OpenGL already worked:
    a symlink farm plus runtime.library_dirs, no vendored driver. Instance
    extensions 4 -> 22. Versioned sonames only — library_dirs lands on the link
    line too, so a bare libxcb.so there shadows compat.xcb.

  * compat.vulkan is now kind="shared" with soname libvulkan.so.1. SDL2's
    SDL_CreateWindow(SDL_WINDOW_VULKAN) dlopens libvulkan.so.1 and resolves
    surface creation through whatever it finds; against a static loader the
    application ends up with two, and createSurface gets an instance the second
    one never saw. Shared, the application, GLFW (via glfwInitVulkanLoader) and
    SDL all converge on one object — which is what the loader is designed to be.

Also: glfwInitVulkanLoader must be called before glfwInit. Upstream's
glfw_app_main.cpp gets this right; a consumer writing its own entry point must
too.

Verified cold on all three platforms with mcpp 0.0.109, plus the local GUI
harness on Linux.

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

Co-authored-by: SPeak Agent <248744407+speak-agent@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant