tmp(ci): probe the three windows images — do NOT merge - #387
Closed
Sunrisepeak wants to merge 2 commits into
Closed
Conversation
…ogether TEMPORARY — delete once the windows image question is settled. #385 pinned the windows leg to `windows-2022` because `windows-latest` (= windows-2025-vs2026, MSVC STL 14.51) cannot compile `huxerui.huxerui`: clang instantiates MSVC STL's vectorized `std::find` for a 24-byte type and hits `static_assert(false, "unexpected size")` (mcpp-community/mcpp#609). The pin worked and cost three members. `vulkan`, `eui-neo-vulkan` and `vulkan-hpp-module` now fail at RUN time with 0xC0000135 (STATUS_DLL_NOT_FOUND) — they compile fine. The Vulkan loader is not a Windows component; it arrives with a GPU driver or the SDK, so whether an image carries `vulkan-1.dll` is a property of the image. So the pin is a TRADE: one compile failure removed, three load failures created. `windows-2025` was never tried, and it is the obvious candidate — old enough to miss 14.51's vectorized find, new enough to plausibly carry the loader. This asks all three images both questions at once: * does `vulkan-1.dll` exist (the vulkan members' failure), and * does `huxerui-module` compile (huxerui's failure) `continue-on-error` on both so every image reports a full row instead of stopping at its first red, and the image inventory is printed BEFORE any build so the answer is visible even if the builds behave unexpectedly. A separate FILE, not a change to validate.yml, and that is the point: validate.yml's `paths:` names only itself, so adding this selects no members and the run is two members on three images instead of the full matrix. Nothing here is meant to merge.
…C 14.44
The inventory step already paid for itself. `windows-2025` carries THREE
toolsets:
MSVC\14.29.30133
MSVC\14.44.35207
MSVC\14.51.36231 <- clang picks this one, and dies in it
So the trade this branch exists to resolve may not be a trade at all. The
loader question and the STL question were assumed to move together because
both were read off the image label; they do not. A new image carries the
Vulkan loader AND an older STL — the only thing choosing 14.51 is clang's
default of newest-wins.
Two ways to ask it otherwise, probed separately because they fail in
different places: `VCToolsInstallDir`, which is what a developer prompt
exports and what clang's MSVC detection reads, and clang's own
`/vctoolsdir`. If neither reaches the compile, toolset selection belongs to
mcpp and CI cannot fix it — which is itself the answer, just a different
one.
The last step prints which MSVC path the build actually touched, pass or
fail. Without it a pass proves nothing: "compiled against 14.44" and
"compiled against 14.51 and got lucky" look the same from the outcome.
This was referenced Sep 11, 2026
Member
Author
|
Closing with #388. The probe did its job — the table it produced is what settled the question, including the part that sank #388:
And the inventory step, which is the part worth remembering: Deleting the branch: a scheduled-off, dispatch-only workflow left in the tree is a loaded gun with no owner. |
Sunrisepeak
added a commit
that referenced
this pull request
Sep 11, 2026
…ne else does `vulkan-1.dll` is not part of Windows. It arrives with a GPU driver, with LunarG's Vulkan Runtime redistributable, or bundled beside an application, so a runner with no driver has no loader and anything linking `vulkan-1.lib` dies at process start with 0xC0000135, before main. MEASURED across the three images (#387 probe, run 34569282837): windows-2022 vulkan-1.dll absent MSVC 14.29/14.44 huxerui PASS vulkan FAIL 0xC0000135 windows-2025 vulkan-1.dll PRESENT MSVC +14.51 huxerui FAIL (STL) vulkan PASS windows-latest same as windows-2025 Neither image satisfies both. This leg is pinned to `windows-2022` to dodge the MSVC STL 14.51 bug (mcpp-community/mcpp#609, microsoft/STL#6294), and windows-2022 is the image without the loader. THIS REPLACES THE PACKAGE-DEPENDENCY APPROACH, which did not work. The first version of this PR had `compat.vulkan`'s windows branch declare `xim:vulkan-loader@>=1.4.313`. Three runs: 1. cold store -- loader installed, its config() hook failed (`subos.env` PATH declaration; fixed by openxlings/xim-pkgindex#819, asymmetry filed as mcpp-community/mcpp#614) 2. warm store -- `compat.vulkan@1.4.357.0` already installed, so its dependency closure was never re-evaluated and the loader was not installed at all 3. cold store again, after deleting the three registry caches -- still no loader, and no error saying why The declaration sits in `xpm.windows` beside working precedents (`compat.cuda-runtime`, `compat.cudart`), and range versions have precedent too (`compat.openssl`, `compat.vulkan-runtime`), so the shape is not obviously wrong -- but three runs produced no loader and no diagnostic, and chasing it further is not worth it for a problem whose actual shape is "the runner is missing a redistributable". WHAT EVERYONE ELSE DOES, since this is a common Windows problem: * dynamic loading in the consumer -- volk, Vulkan-Hpp's VULKAN_HPP_DISPATCH_LOADER_DYNAMIC, glfwVulkanSupported(), SDL_Vulkan_LoadLibrary. The process starts and degrades gracefully instead of dying before main. This is the robust answer for applications. * rely on the GPU driver -- what most games do, and sound: a machine that can run Vulkan has a driver, and the driver brought the loader. * ship the loader -- Apache-2.0, which is what the LunarG Runtime redistributable is for. * on CI specifically -- install the Runtime/SDK, or register a software ICD (SwiftShader, lavapipe) when device-level coverage is wanted. These members assert loader-level calls only (`vkEnumerateInstanceVersion`, instance extension enumeration), deliberately: the loader advertises WSI extensions only when an ICD supports them, so asserting on those would be testing the runner's hardware. A loader with no ICD is exactly the right amount here. The payload is the one built for openxlings/xim-pkgindex#818 -- built on a runner from Khronos' source, and the build loads the DLL and resolves vkEnumerateInstanceVersion, vkCreateInstance and vkGetInstanceProcAddr before publishing. Hash-pinned here, and the step is idempotent: if the image ever grows the DLL, it leaves it alone. The xim-pkgindex loader package stays. It is a real ecosystem capability for a driverless Windows machine; it is simply not the layer that fixes a missing redistributable on a CI runner. Co-authored-by: sunrisepeak <x.d2learn.org@gmail.com>
Sunrisepeak
added a commit
that referenced
this pull request
Sep 11, 2026
* feat(compat.vulkan): 1.4.357.3 ships the Vulkan loader on Windows A Windows program that links `vulkan-1.lib` needs `vulkan-1.dll` at process start, and that DLL is not part of Windows. It arrives with a GPU driver, with LunarG's Vulkan Runtime redistributable, or beside an application. A machine without a driver has none, and the program dies before `main` with 0xC0000135 (STATUS_DLL_NOT_FOUND). Measured on GitHub's `windows-2022` image (#387 probe, run 34569282837): `vulkan`, `eui-neo-vulkan` and `vulkan-hpp-module` all fail that way, while images that happen to carry a driver pass. WHAT CHANGES compat.vulkan 1.4.357.3 windows artifact adds bin/vulkan-1.dll and LICENSE.txt; mcpp.windows.runtime gains library_dirs = { "bin" } khronos.vulkan-hpp 1.4.357.1 same headers, pin -> compat.vulkan 1.4.357.3 compat.eui-neo 0.5.9.1 upstream 0.5.9 unchanged, `vulkan` feature pin -> compat.vulkan 1.4.357.3 members vulkan 1.4.357.3, vulkan-hpp-module 1.4.357.1, eui-neo-vulkan 0.5.9.1 tests/examples/vulkan on Windows, asserts the mapped vulkan-1.dll lives in the executable's own directory THE MECHANISM ALREADY EXISTS AND IS NOT NEW HERE. mcpp copies every *.dll under a dependency's `runtime.library_dirs` beside the executable it builds (mcpp #185, v0.0.73); `compat.openblas` has shipped `bin/libopenblas.dll` this way on Windows CI since mcpp-index #55. Two properties this change leans on were measured locally with mcpp 2026.9.11.2 rather than assumed: * transitive -- app -> mid -> dep(bin/vulkan-1.dll): the DLL lands beside `app`. `vulkan-hpp-module` and `eui-neo-vulkan` reach compat.vulkan only transitively. * test binaries -- `mcpp test` places it beside the test executable too. `mcpp pack` needs nothing further: its PE closure always searches the executable's own directory ("whatever the build staged beside it ... is by definition part of what it runs with"), and `vulkan-1.dll` is not in its system-DLL allow-list, so the deployed copy is what a packed program carries. THE ARTIFACT (xlings-res/vulkan-import 1.4.357.3, sha256 8118f1bd...12f5) lib/vulkan-1.lib byte-identical to 1.4.357.1's vulkan-1.def upstream `loader/vulkan-1.def`, tag vulkan-sdk-1.4.357.0 bin/vulkan-1.dll built from vulkan-sdk-1.4.357.0 by xlings-res/vulkan-loader's windows workflow, which loads the DLL and resolves vkEnumerateInstanceVersion, vkCreateInstance and vkGetInstanceProcAddr before publishing (run 34608619850) LICENSE.txt Vulkan-Loader's Apache-2.0 -- a redistributed binary carries its license README.md how each file was produced Packed deterministically (sorted, fixed mtime, numeric owner, gzip -n); the sha was computed twice, read back from GitHub, and the gitcode mirror (mcpp-res/vulkan-import 1.4.357.3) is byte-identical. COMPATIBILITY, MEASURED. The DLL exports exactly the 265 names in the .def -- no additions, no omissions -- so every import `vulkan-1.lib` can produce resolves, and no consumer can hit "entry point not found". The loader version the earlier xim payload carried (1.4.313) exports the same 265; the build is at 1.4.357 anyway so the loader matches the headers it is consumed with. On a machine that ALREADY has a GPU driver nothing is lost: the copy beside the executable is found first (the application directory precedes System32), and the loader still reads HKLM\SOFTWARE\Khronos\Vulkan\Drivers, so the driver the machine has is the ICD it uses. The ICD is deliberately not supplied -- a software fallback would hide a missing driver behind a slow device. WHY NEW VERSIONS INSTEAD OF MOVING PINS. An installed copy records the pins it resolved with. Moving a pin inside a published version does not reach a warm store, which is not hypothetical here: with #391's first approach, a warm CI store kept `compat.vulkan@1.4.357.0`, never re-evaluated its closure, and the loader never arrived. That is the same rule as compat.vulkan 1.4.357.1. Versions before 1.4.357.3 have no bin/; mcpp skips a declared runtime directory that does not exist, so `library_dirs` is inert for them. WHY THE TEST ASSERTION IS A REAL CHECK. On Windows the test now requires the mapped vulkan-1.dll to sit in the executable's directory. With an older compat.vulkan that fails on a machine with a driver (the loader comes from System32) and never runs on one without (the process dies first). The `windows-2022` leg of this PR has no system loader at all, so it can only pass if the deployment works. This is also why #391 -- which put the DLL in System32 on the runner -- is superseded rather than merged: it would make that leg pass whether or not the package works. Co-authored-by: sunrisepeak <x.d2learn.org@gmail.com> * fix(eui-neo): find upstream's directory under a re-released version; vulkan-hpp moves to a follow-up TWO THINGS LOCAL VERIFICATION FOUND in the first push of this branch. 1. compat.eui-neo 0.5.9.1 could not install. The install hook looks for the unpacked archive by name, `EUI-NEO-<version>`, and took the version verbatim -- so it looked for `EUI-NEO-0.5.9.1/` in an archive that unpacks to `EUI-NEO-0.5.9/`: eui-neo: no CMakeLists.txt under .../compat-x-eui-neo/0.5.9.1/eui-neo-0.5.9.1 after unpacking; the archive layout is neither wrapped nor flat A fourth version component is this index re-releasing the same upstream tag, so the lookup now drops it. Three-component versions are unchanged; checked directly: 0.5.9 -> 0.5.9, 0.5.9.1 -> 0.5.9, 0.5.10 -> 0.5.10, 1.2.3.45 -> 1.2.3, 0.5.9-rc1 -> 0.5.9-rc1. The `layer` directory keeps the package's own version; the sources are `*/` globs, so its name never mattered. After the fix, locally with mcpp 2026.9.11.2: compat.eui-neo[vulkan]: ok (backend=vulkan, loader api 1.4.357) i.e. eui-neo 0.5.9.1 resolved compat.vulkan 1.4.357.3 through the feature. This is the same class of bug as openxlings/xim-pkgindex#821 fixed in vulkan-loader: a hook deriving a path from the version works exactly until a second version shares an archive. 2. khronos.vulkan-hpp 1.4.357.1 cannot be verified in the same change that introduces compat.vulkan 1.4.357.3. `vulkan-hpp-module` redirects only the `khronos` namespace to this checkout, so `compat` comes from the PUBLISHED index, which does not have 1.4.357.3 until this merges: xlings install_packages failed (exit 1) for 'compat.vulkan@1.4.357.3' with 1 index repo configured [mcpplibs -> https://github.com/mcpplibs/mcpp-index.git] Redirecting `compat` as well was tried and is still refused -- mcpp reports "≥2 project-level index repos is a known xlings resolution gap (mcpp #238; root cause openxlings/xlings#374)" even though #238 is closed. So the khronos.vulkan-hpp bump and its member pin are reverted here and follow once this is merged and the index republished -- the same order openxlings/xim-pkgindex#818 and mcpp-index#391 needed. Consequence for this PR's CI, stated in advance: `vulkan-hpp-module` is still selected (its manifest names vulkan) and still resolves compat.vulkan 1.4.357.0, so on the windows leg it fails exactly as it does on main today. `vulkan` and `eui-neo-vulkan` are the members this change is judged by. Co-authored-by: sunrisepeak <x.d2learn.org@gmail.com> --------- Co-authored-by: sunrisepeak <x.d2learn.org@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Temporary. Not for merge. Delete the branch once the question below is answered.
The question
#385 pinned the windows leg to
windows-2022becausewindows-latest(=windows-2025-vs2026, MSVC STL 14.51) cannot compilehuxerui.huxerui— clang instantiates MSVC STL's vectorizedstd::findfor a 24-byte trivially-comparable type and hitsstatic_assert(false, "unexpected size"). Filed as mcpp-community/mcpp#609.The pin worked, and it cost three members.
vulkan,eui-neo-vulkanandvulkan-hpp-modulenow fail at run time with0xC0000135(STATUS_DLL_NOT_FOUND); they compile fine. The Vulkan loader is not a Windows component — it ships with a GPU driver or the SDK — so whether an image carriesvulkan-1.dllis a property of the image, andwindows-2022does not have it.So the pin is a trade, not a win:
windows-latest(VS2026 / STL 14.51)windows-2022(VS2022 / STL 14.3x)windows-2025windows-2025is the obvious candidate: old enough to miss 14.51's vectorized find, new enough to plausibly carry the loader.What this runs
Both questions, on all three images, in one run:
vulkan-1.dllpresent or absent (both System32 and SysWOW64, with file version), and every MSVC toolset directory on the box. Printed before any build, so the answer survives a build behaving unexpectedly.mcpp test -p huxerui-module— the compile questionmcpp test -p vulkan— the loader questionBoth are
continue-on-error, so every image reports a complete row rather than stopping at its first red, and aRowstep prints the pair.Why a separate file
validate.yml'spaths:names only itself, so adding a new workflow file selects no members. This run is two members on three images — minutes, not the ~50 the full matrix costs. Changingvalidate.ymlto ask the same question would have selected everything.After
Whatever it says, the follow-up is a one-line change to
validate.yml'semit windows …and deleting this file. Ifwindows-2025clears both, that is the pin. If it clears neither, the trade is real and the choice has to be argued rather than discovered.