From 9ee679adb31d4ee85ccb060aea2315ec05b5e5b8 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Fri, 11 Sep 2026 22:21:11 +0800 Subject: [PATCH 1/2] 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 --- pkgs/c/compat.vulkan.lua | 83 +++++++++++++++++++--- pkgs/e/compat.eui-neo.lua | 23 +++++- pkgs/k/khronos.vulkan-hpp.lua | 35 ++++++++- tests/examples/eui-neo-vulkan/mcpp.toml | 2 +- tests/examples/vulkan-hpp-module/mcpp.toml | 2 +- tests/examples/vulkan/mcpp.toml | 2 +- tests/examples/vulkan/tests/loader.cpp | 52 +++++++++++++- 7 files changed, 182 insertions(+), 17 deletions(-) diff --git a/pkgs/c/compat.vulkan.lua b/pkgs/c/compat.vulkan.lua index 5d16e344..d656a7da 100644 --- a/pkgs/c/compat.vulkan.lua +++ b/pkgs/c/compat.vulkan.lua @@ -33,12 +33,15 @@ -- this through `APPLE_STATIC_LOADER` + pthread_once; Linux through -- `__attribute__((constructor))`. Windows has neither. -- --- The supported Windows arrangement is the ordinary one every Vulkan --- application uses: link `vulkan-1.lib` and let the system `vulkan-1.dll`, --- installed by any GPU driver, do the ICD loading. The windows xpm entry is --- therefore a small artifact carrying that import library — symbol stubs, no --- code — generated from Khronos' own `loader/vulkan-1.def` (shipped in this --- very loader tarball) with a single reproducible command: +-- The supported Windows arrangement is the ordinary one: link `vulkan-1.lib` +-- and load `vulkan-1.dll` at process start. Through 1.4.357.2 that DLL was +-- assumed to come from the machine's GPU driver, which a driverless machine +-- does not have (0xC0000135 before `main`, measured on `windows-2022`). From +-- 1.4.357.3 the artifact also carries the DLL, built from the same tag, and +-- `runtime.library_dirs` has mcpp place it beside every consuming executable; +-- see the windows xpm entry. The import library in that artifact — symbol +-- stubs, no code — is generated from Khronos' own `loader/vulkan-1.def` +-- (shipped in this very loader tarball) with a single reproducible command: -- -- llvm-dlltool -d vulkan-1.def -l lib/vulkan-1.lib -m i386:x86-64 -- @@ -89,6 +92,16 @@ package = { -- version -- and where a consumer also names the farm directly, the -- two disagree and the build stops. Measured on a CI runner with a -- warm ~/.mcpp; see the note on compat.vulkan 1.4.357.1. + -- 1.4.357.3: the same loader source. A new version on every platform + -- because the WINDOWS artifact changed -- it now carries the loader DLL + -- (see the windows entry) -- and a version is one key across platforms. + ["1.4.357.3"] = { + url = { + GLOBAL = "https://github.com/KhronosGroup/Vulkan-Loader/archive/refs/tags/vulkan-sdk-1.4.357.0.tar.gz", + CN = "https://gitcode.com/mcpp-res/vulkan/releases/download/1.4.357.0/vulkan-1.4.357.0.tar.gz", + }, + sha256 = "54f2537df22313768da0317dda2abdaaab7711b4081c48c869a79db343d0ae70", + }, ["1.4.357.2"] = { url = { GLOBAL = "https://github.com/KhronosGroup/Vulkan-Loader/archive/refs/tags/vulkan-sdk-1.4.357.0.tar.gz", @@ -136,6 +149,16 @@ package = { -- version -- and where a consumer also names the farm directly, the -- two disagree and the build stops. Measured on a CI runner with a -- warm ~/.mcpp; see the note on compat.vulkan 1.4.357.1. + -- 1.4.357.3: the same loader source. A new version on every platform + -- because the WINDOWS artifact changed -- it now carries the loader DLL + -- (see the windows entry) -- and a version is one key across platforms. + ["1.4.357.3"] = { + url = { + GLOBAL = "https://github.com/KhronosGroup/Vulkan-Loader/archive/refs/tags/vulkan-sdk-1.4.357.0.tar.gz", + CN = "https://gitcode.com/mcpp-res/vulkan/releases/download/1.4.357.0/vulkan-1.4.357.0.tar.gz", + }, + sha256 = "54f2537df22313768da0317dda2abdaaab7711b4081c48c869a79db343d0ae70", + }, ["1.4.357.2"] = { url = { GLOBAL = "https://github.com/KhronosGroup/Vulkan-Loader/archive/refs/tags/vulkan-sdk-1.4.357.0.tar.gz", @@ -183,6 +206,37 @@ package = { -- version -- and where a consumer also names the farm directly, the -- two disagree and the build stops. Measured on a CI runner with a -- warm ~/.mcpp; see the note on compat.vulkan 1.4.357.1. + -- 1.4.357.3: THE LOADER DLL SHIPS WITH THE IMPORT LIBRARY. + -- + -- `vulkan-1.dll` is not a Windows component: it arrives with a GPU + -- driver, with LunarG's Vulkan Runtime redistributable, or beside an + -- application. So a machine without a driver has no loader, and a + -- program linking `vulkan-1.lib` dies before `main` with 0xC0000135 + -- (STATUS_DLL_NOT_FOUND). Measured on GitHub's `windows-2022` image + -- (mcpp-index #387 probe; `vulkan`, `eui-neo-vulkan` and + -- `vulkan-hpp-module` all failed that way). + -- + -- The artifact adds `bin/vulkan-1.dll`, built from + -- `vulkan-sdk-1.4.357.0` -- the same tag as the headers and the .def -- + -- by xlings-res/vulkan-loader's windows workflow, which loads the DLL + -- and resolves its entry points before publishing. `lib/vulkan-1.lib` + -- is byte-identical to 1.4.357.1's, and the DLL exports exactly the + -- 265 names in `vulkan-1.def`: every import that library can produce + -- resolves, so no consumer can hit "entry point not found". + -- + -- ON A MACHINE THAT ALREADY HAS A 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 GPU driver the + -- machine has is the ICD it uses. This is the ordinary arrangement for + -- an application that redistributes the loader. + ["1.4.357.3"] = { + url = { + GLOBAL = "https://github.com/xlings-res/vulkan-import/releases/download/1.4.357.3/vulkan-import-1.4.357.3.tar.gz", + CN = "https://gitcode.com/mcpp-res/vulkan-import/releases/download/1.4.357.3/vulkan-import-1.4.357.3.tar.gz", + }, + sha256 = "8118f1bd897e553baffabf484a14db980ce1f0a6cfdb5a6222c0a236ecdf12f5", + }, ["1.4.357.2"] = { url = { GLOBAL = "https://github.com/xlings-res/vulkan-import/releases/download/1.4.357.1/vulkan-import-1.4.357.1.tar.gz", @@ -359,15 +413,26 @@ package = { -- .def it came from. The anchor keeps a buildable target, the same -- shape `compat.opengl` uses for a headers-only package. -- - -- The artifact is packed FLAT — lib/ at the archive root, no wrap - -- directory — because `-L` is not glob-expanded the way + -- The artifact is packed FLAT — lib/ and bin/ at the archive root, no + -- wrap directory — because `-L` is not glob-expanded the way -- include_dirs and sources are. With a wrap layer the relative -- `-Llib` below misses and the link fails with -- "LNK1181: cannot open input file 'vulkan-1.lib'". sources = { "mcpp_generated/vulkan_import_anchor.c" }, ldflags = { "-Llib", "-lvulkan-1" }, runtime = { - -- vulkan-1.dll ships with the GPU driver, not with us. + -- THE LOADER TRAVELS WITH THE PROGRAM (1.4.357.3+). mcpp copies + -- every *.dll under a dependency's runtime library_dirs beside the + -- executable it builds -- for transitive dependencies too -- and + -- `mcpp pack` always searches the executable's own directory, so + -- the same file reaches a packed distribution. Versions before + -- 1.4.357.3 have no bin/ in their artifact; mcpp skips a declared + -- directory that does not exist, so for them this is inert. + -- + -- The ICD is deliberately NOT supplied: on a machine with a GPU + -- driver the driver's ICD is the right one, and a software + -- fallback would hide a missing driver behind a slow device. + library_dirs = { "bin" }, dlopen_libs = { "vulkan-1.dll" }, capabilities = { "vulkan.icd.driver" }, }, diff --git a/pkgs/e/compat.eui-neo.lua b/pkgs/e/compat.eui-neo.lua index 0fa4d0bb..abbd7829 100644 --- a/pkgs/e/compat.eui-neo.lua +++ b/pkgs/e/compat.eui-neo.lua @@ -148,6 +148,13 @@ package = { url = "https://github.com/sudoevolve/EUI-NEO/archive/refs/tags/v0.5.9.tar.gz", sha256 = "370d1da706d94bbbb144fa1634e1d9796a8a1ffd58b696fbb801296aef15703d", }, + -- 0.5.9.1: upstream 0.5.9 unchanged. Exists because the `vulkan` + -- feature now pins compat.vulkan 1.4.357.3, whose Windows artifact + -- carries the loader DLL; an installed 0.5.9 records the old pin. + ["0.5.9.1"] = { + url = "https://github.com/sudoevolve/EUI-NEO/archive/refs/tags/v0.5.9.tar.gz", + sha256 = "370d1da706d94bbbb144fa1634e1d9796a8a1ffd58b696fbb801296aef15703d", + }, }, macosx = { ["0.5.3"] = { @@ -183,6 +190,13 @@ package = { url = "https://github.com/sudoevolve/EUI-NEO/archive/refs/tags/v0.5.9.tar.gz", sha256 = "370d1da706d94bbbb144fa1634e1d9796a8a1ffd58b696fbb801296aef15703d", }, + -- 0.5.9.1: upstream 0.5.9 unchanged. Exists because the `vulkan` + -- feature now pins compat.vulkan 1.4.357.3, whose Windows artifact + -- carries the loader DLL; an installed 0.5.9 records the old pin. + ["0.5.9.1"] = { + url = "https://github.com/sudoevolve/EUI-NEO/archive/refs/tags/v0.5.9.tar.gz", + sha256 = "370d1da706d94bbbb144fa1634e1d9796a8a1ffd58b696fbb801296aef15703d", + }, }, windows = { ["0.5.3"] = { @@ -218,6 +232,13 @@ package = { url = "https://github.com/sudoevolve/EUI-NEO/archive/refs/tags/v0.5.9.tar.gz", sha256 = "370d1da706d94bbbb144fa1634e1d9796a8a1ffd58b696fbb801296aef15703d", }, + -- 0.5.9.1: upstream 0.5.9 unchanged. Exists because the `vulkan` + -- feature now pins compat.vulkan 1.4.357.3, whose Windows artifact + -- carries the loader DLL; an installed 0.5.9 records the old pin. + ["0.5.9.1"] = { + url = "https://github.com/sudoevolve/EUI-NEO/archive/refs/tags/v0.5.9.tar.gz", + sha256 = "370d1da706d94bbbb144fa1634e1d9796a8a1ffd58b696fbb801296aef15703d", + }, }, }, @@ -420,7 +441,7 @@ package = { "*/core/render/vulkan/vulkan_shadertoy.cpp", "*/core/render/vulkan/vulkan_text.cpp", }, - deps = { ["compat.vulkan"] = "1.4.357.0" }, + deps = { ["compat.vulkan"] = "1.4.357.3" }, }, -- ── Window backend ──────────────────────────────────────────── -- Exclusive in the same way and for the same reason as the render diff --git a/pkgs/k/khronos.vulkan-hpp.lua b/pkgs/k/khronos.vulkan-hpp.lua index f7dbf914..ff0e16da 100644 --- a/pkgs/k/khronos.vulkan-hpp.lua +++ b/pkgs/k/khronos.vulkan-hpp.lua @@ -159,6 +159,17 @@ package = { -- header, loader and bindings repositories together. xpm = { linux = { + -- 1.4.357.1: the same headers, pinned to compat.vulkan 1.4.357.3, whose + -- Windows artifact carries the loader DLL. A new version rather than a + -- moved pin, because an installed copy records the pin it resolved + -- with (see compat.vulkan 1.4.357.1). + ["1.4.357.1"] = { + url = { + GLOBAL = "https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/vulkan-sdk-1.4.357.0.tar.gz", + CN = "https://gitcode.com/mcpp-res/vulkan-headers/releases/download/1.4.357.0/vulkan-headers-1.4.357.0.tar.gz", + }, + sha256 = "e87dce08116151f6b6d7de6b6faf41498e87e6cf848ff16fa3bd5402190ad4a3", + }, ["1.4.357.0"] = { url = { GLOBAL = "https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/vulkan-sdk-1.4.357.0.tar.gz", @@ -168,6 +179,17 @@ package = { }, }, macosx = { + -- 1.4.357.1: the same headers, pinned to compat.vulkan 1.4.357.3, whose + -- Windows artifact carries the loader DLL. A new version rather than a + -- moved pin, because an installed copy records the pin it resolved + -- with (see compat.vulkan 1.4.357.1). + ["1.4.357.1"] = { + url = { + GLOBAL = "https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/vulkan-sdk-1.4.357.0.tar.gz", + CN = "https://gitcode.com/mcpp-res/vulkan-headers/releases/download/1.4.357.0/vulkan-headers-1.4.357.0.tar.gz", + }, + sha256 = "e87dce08116151f6b6d7de6b6faf41498e87e6cf848ff16fa3bd5402190ad4a3", + }, ["1.4.357.0"] = { url = { GLOBAL = "https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/vulkan-sdk-1.4.357.0.tar.gz", @@ -177,6 +199,17 @@ package = { }, }, windows = { + -- 1.4.357.1: the same headers, pinned to compat.vulkan 1.4.357.3, whose + -- Windows artifact carries the loader DLL. A new version rather than a + -- moved pin, because an installed copy records the pin it resolved + -- with (see compat.vulkan 1.4.357.1). + ["1.4.357.1"] = { + url = { + GLOBAL = "https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/vulkan-sdk-1.4.357.0.tar.gz", + CN = "https://gitcode.com/mcpp-res/vulkan-headers/releases/download/1.4.357.0/vulkan-headers-1.4.357.0.tar.gz", + }, + sha256 = "e87dce08116151f6b6d7de6b6faf41498e87e6cf848ff16fa3bd5402190ad4a3", + }, ["1.4.357.0"] = { url = { GLOBAL = "https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/vulkan-sdk-1.4.357.0.tar.gz", @@ -207,6 +240,6 @@ package = { targets = { ["vulkan_hpp"] = { kind = "lib" } }, -- The loader, for the static dispatcher's direct calls — and, through -- it, `compat.vulkan-headers` for the includes these units open. - deps = { ["compat.vulkan"] = "1.4.357.0" }, + deps = { ["compat.vulkan"] = "1.4.357.3" }, }, } diff --git a/tests/examples/eui-neo-vulkan/mcpp.toml b/tests/examples/eui-neo-vulkan/mcpp.toml index 69576464..8528f1a5 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.5.9", features = ["vulkan"] } +eui-neo = { version = "0.5.9.1", features = ["vulkan"] } [build] cxxflags = ["-DHAVE_EUI_VULKAN=1"] diff --git a/tests/examples/vulkan-hpp-module/mcpp.toml b/tests/examples/vulkan-hpp-module/mcpp.toml index 285f196c..5f849dc7 100644 --- a/tests/examples/vulkan-hpp-module/mcpp.toml +++ b/tests/examples/vulkan-hpp-module/mcpp.toml @@ -21,7 +21,7 @@ name = "vulkan-hpp-module-tests" version = "0.1.0" [dependencies.khronos] -vulkan-hpp = "1.4.357.0" +vulkan-hpp = "1.4.357.1" # No [build] section, and no per-platform gating: unlike tests/examples/vulkan, # which had to publish its own HAVE_VULKAN_LOADER switch, nothing here is diff --git a/tests/examples/vulkan/mcpp.toml b/tests/examples/vulkan/mcpp.toml index 40056d82..46d0c66d 100644 --- a/tests/examples/vulkan/mcpp.toml +++ b/tests/examples/vulkan/mcpp.toml @@ -3,7 +3,7 @@ name = "vulkan-tests" version = "0.1.0" [dependencies.compat] -vulkan = "1.4.357.0" +vulkan = "1.4.357.3" # All three platforms now carry compat.vulkan — linux/macOS build the loader # from source, windows links the import library. HAVE_VULKAN_LOADER stays as the diff --git a/tests/examples/vulkan/tests/loader.cpp b/tests/examples/vulkan/tests/loader.cpp index 88ab1936..d801a4e5 100644 --- a/tests/examples/vulkan/tests/loader.cpp +++ b/tests/examples/vulkan/tests/loader.cpp @@ -8,14 +8,22 @@ // legitimately ABSENT on a driverless machine and asserting on it would just be // testing the runner's hardware. // -// HAVE_VULKAN_LOADER is set by THIS project's own [target.'cfg(...)'.build] -// cxxflags, because compat.vulkan has no windows entry. A consumer that keys -// its source off a dependency's presence has to declare that itself. +// HAVE_VULKAN_LOADER is set by THIS project's own [build] cxxflags. A consumer +// that keys its source off a dependency's presence has to declare that itself. #if defined(HAVE_VULKAN_LOADER) #include #endif import std; +#if defined(HAVE_VULKAN_LOADER) && defined(_WIN32) +// Declared rather than taken from : two functions are needed, and +// the header's macros and min/max collide with `import std`. Both live in +// kernel32, which every Windows program already links. +extern "C" __declspec(dllimport) void* GetModuleHandleW(const wchar_t* name); +extern "C" __declspec(dllimport) unsigned long GetModuleFileNameW(void* module, wchar_t* path, + unsigned long size); +#endif + #if !defined(HAVE_VULKAN_LOADER) int main() { std::println("compat.vulkan: skipped (no windows build — static loader unsupported upstream)"); @@ -36,6 +44,44 @@ int main() { return 2; } +#if defined(_WIN32) + // WHERE THE LOADER CAME FROM is the point of compat.vulkan 1.4.357.3 on + // Windows: the package now ships vulkan-1.dll and mcpp places it beside the + // executable, so a machine with no GPU driver can still start this program. + // The loader has just answered, so the DLL is mapped; its directory must be + // this executable's. That holds on a machine WITH a driver too (the + // application directory precedes System32), which is what makes this a real + // check: with an older compat.vulkan the loader came from System32 there, + // and on a driverless machine the process never reached main. + { + std::vector dll(32768), exe(32768); + void* module = GetModuleHandleW(L"vulkan-1.dll"); + if (module == nullptr) { + std::println("vulkan-1.dll answered but is not mapped in this process"); + return 7; + } + const auto dllLen = GetModuleFileNameW(module, dll.data(), 32768); + const auto exeLen = GetModuleFileNameW(nullptr, exe.data(), 32768); + auto dirOf = [](std::wstring_view p) { + std::wstring d(p.substr(0, p.find_last_of(L"\\/"))); + for (auto& c : d) c = static_cast(std::towlower(c)); + return d; + }; + auto narrow = [](std::wstring_view p) { + std::string out; + for (wchar_t c : p) out.push_back(c < 128 ? static_cast(c) : '?'); + return out; + }; + const std::wstring_view dllPath(dll.data(), dllLen), exePath(exe.data(), exeLen); + if (dirOf(dllPath) != dirOf(exePath)) { + std::println("vulkan-1.dll was loaded from {}, not beside {}", + narrow(dllPath), narrow(exePath)); + return 8; + } + std::println("compat.vulkan: loader deployed beside the executable ({})", narrow(dllPath)); + } +#endif + std::uint32_t extensionCount = 0; if (vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr) != VK_SUCCESS) { std::println("vkEnumerateInstanceExtensionProperties failed"); From 5cf8f0d345520a4b4593f17acca0dc1d9e14f8ed Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Fri, 11 Sep 2026 22:28:07 +0800 Subject: [PATCH 2/2] fix(eui-neo): find upstream's directory under a re-released version; vulkan-hpp moves to a follow-up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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-`, 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 --- pkgs/e/compat.eui-neo.lua | 9 ++++++ pkgs/k/khronos.vulkan-hpp.lua | 35 +--------------------- tests/examples/vulkan-hpp-module/mcpp.toml | 2 +- 3 files changed, 11 insertions(+), 35 deletions(-) diff --git a/pkgs/e/compat.eui-neo.lua b/pkgs/e/compat.eui-neo.lua index abbd7829..25ffe7f5 100644 --- a/pkgs/e/compat.eui-neo.lua +++ b/pkgs/e/compat.eui-neo.lua @@ -697,7 +697,16 @@ local function normalise_layout(layer) -- hook runs on every platform; the host guard is further down and it only -- covers the glib staging. With no directory listing available, the -- archive's shape is ASKED ABOUT by name rather than discovered. + -- + -- The name carries UPSTREAM's version, which is not always this package's. + -- A fourth component is this index re-releasing the same tag -- 0.5.9.1 is + -- upstream 0.5.9 with one dependency re-pinned -- and the archive still + -- unpacks to `EUI-NEO-0.5.9/`. Taking the version verbatim looked for + -- `EUI-NEO-0.5.9.1/`, found nothing, and failed with the error below; + -- measured on the first 0.5.9.1 install. Three-component versions are + -- unchanged by this. local v = pkginfo.version() + v = v:match("^(%d+%.%d+%.%d+)%.%d+$") or v for _, name in ipairs({ "EUI-NEO-" .. v, "eui-neo-" .. v, "EUI-NEO-v" .. v, "eui-neo-v" .. v }) do if os.isfile(path.join(name, "CMakeLists.txt")) then diff --git a/pkgs/k/khronos.vulkan-hpp.lua b/pkgs/k/khronos.vulkan-hpp.lua index ff0e16da..f7dbf914 100644 --- a/pkgs/k/khronos.vulkan-hpp.lua +++ b/pkgs/k/khronos.vulkan-hpp.lua @@ -159,17 +159,6 @@ package = { -- header, loader and bindings repositories together. xpm = { linux = { - -- 1.4.357.1: the same headers, pinned to compat.vulkan 1.4.357.3, whose - -- Windows artifact carries the loader DLL. A new version rather than a - -- moved pin, because an installed copy records the pin it resolved - -- with (see compat.vulkan 1.4.357.1). - ["1.4.357.1"] = { - url = { - GLOBAL = "https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/vulkan-sdk-1.4.357.0.tar.gz", - CN = "https://gitcode.com/mcpp-res/vulkan-headers/releases/download/1.4.357.0/vulkan-headers-1.4.357.0.tar.gz", - }, - sha256 = "e87dce08116151f6b6d7de6b6faf41498e87e6cf848ff16fa3bd5402190ad4a3", - }, ["1.4.357.0"] = { url = { GLOBAL = "https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/vulkan-sdk-1.4.357.0.tar.gz", @@ -179,17 +168,6 @@ package = { }, }, macosx = { - -- 1.4.357.1: the same headers, pinned to compat.vulkan 1.4.357.3, whose - -- Windows artifact carries the loader DLL. A new version rather than a - -- moved pin, because an installed copy records the pin it resolved - -- with (see compat.vulkan 1.4.357.1). - ["1.4.357.1"] = { - url = { - GLOBAL = "https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/vulkan-sdk-1.4.357.0.tar.gz", - CN = "https://gitcode.com/mcpp-res/vulkan-headers/releases/download/1.4.357.0/vulkan-headers-1.4.357.0.tar.gz", - }, - sha256 = "e87dce08116151f6b6d7de6b6faf41498e87e6cf848ff16fa3bd5402190ad4a3", - }, ["1.4.357.0"] = { url = { GLOBAL = "https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/vulkan-sdk-1.4.357.0.tar.gz", @@ -199,17 +177,6 @@ package = { }, }, windows = { - -- 1.4.357.1: the same headers, pinned to compat.vulkan 1.4.357.3, whose - -- Windows artifact carries the loader DLL. A new version rather than a - -- moved pin, because an installed copy records the pin it resolved - -- with (see compat.vulkan 1.4.357.1). - ["1.4.357.1"] = { - url = { - GLOBAL = "https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/vulkan-sdk-1.4.357.0.tar.gz", - CN = "https://gitcode.com/mcpp-res/vulkan-headers/releases/download/1.4.357.0/vulkan-headers-1.4.357.0.tar.gz", - }, - sha256 = "e87dce08116151f6b6d7de6b6faf41498e87e6cf848ff16fa3bd5402190ad4a3", - }, ["1.4.357.0"] = { url = { GLOBAL = "https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/vulkan-sdk-1.4.357.0.tar.gz", @@ -240,6 +207,6 @@ package = { targets = { ["vulkan_hpp"] = { kind = "lib" } }, -- The loader, for the static dispatcher's direct calls — and, through -- it, `compat.vulkan-headers` for the includes these units open. - deps = { ["compat.vulkan"] = "1.4.357.3" }, + deps = { ["compat.vulkan"] = "1.4.357.0" }, }, } diff --git a/tests/examples/vulkan-hpp-module/mcpp.toml b/tests/examples/vulkan-hpp-module/mcpp.toml index 5f849dc7..285f196c 100644 --- a/tests/examples/vulkan-hpp-module/mcpp.toml +++ b/tests/examples/vulkan-hpp-module/mcpp.toml @@ -21,7 +21,7 @@ name = "vulkan-hpp-module-tests" version = "0.1.0" [dependencies.khronos] -vulkan-hpp = "1.4.357.1" +vulkan-hpp = "1.4.357.0" # No [build] section, and no per-platform gating: unlike tests/examples/vulkan, # which had to publish its own HAVE_VULKAN_LOADER switch, nothing here is