Skip to content

Commit b863082

Browse files
authored
fix(glfw): complete Windows link dependencies and add native smoke test (#538)
* test(glfw): exercise standalone package and native Windows backend * docs(glfw): explain Windows smoke coverage and link dependency ownership * fix(glfw): declare native User32 and Shell32 link dependencies * test(glfw): use window size above native Windows minimum * fix(glfw): retain upstream version for descriptor-only changes
1 parent 725ca5d commit b863082

6 files changed

Lines changed: 112 additions & 1 deletion

File tree

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# GLFW Windows package closure
2+
3+
The existing gui-stack and imgui-window members gate GLFW behind Linux, leaving
4+
Windows package compilation/linkage untested. Add a standalone glfw workspace
5+
member with a local compat index and no other direct dependencies. Test Null
6+
windows everywhere and require native Win32 initialization and hidden window
7+
behavior on Windows; use GLFW_NO_API and GLFW_INCLUDE_NONE.
8+
9+
PR #538's initial Windows run (39048720103, job 117442681476) reproduced
10+
undefined LoadCursorW, CreateWindowExW, RegisterClassExW and DragAcceptFiles.
11+
All references originate in GLFW's own win32 sources, not the consumer.
12+
13+
Declare user32 (window/input), gdi32 (pixel formats), and shell32 (drag/drop) in
14+
windows.runtime.libraries. Upstream CMake gets user32/shell32 from CMake's default
15+
Windows standard libraries; the direct clang driver does not. Retain the existing
16+
dialect-neutral form rather than raw linker flags. GLFW dynamically loads its
17+
OpenGL, XInput, DirectInput and DWM functions; no new import libraries are needed
18+
for those. Application calls to OpenGL/Vulkan remain the consumer's responsibility.
19+
20+
Keep the existing package versions and upstream 3.4 archive, URLs, SHA and
21+
install hook. This is a descriptor-only fix: xpkg refreshes the descriptor, so
22+
no new package version is needed when the source is unchanged. The new test
23+
consumes upstream version 3.4.
24+
25+
Validation: CI uses mcpp 2026.10.1.2. Initial Windows failure is the regression
26+
proof; final PR checks must cover the fix, including execution of the Win32 test.

‎mcpp.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ members = [
7171
"tests/examples/godot-cpp-v10",
7272
"tests/examples/grpc-codegen",
7373
"tests/examples/grpc-module",
74+
"tests/examples/glfw",
7475
"tests/examples/gui-stack",
7576
"tests/examples/imgui",
7677
"tests/examples/imgui-module",

‎pkgs/c/compat.glfw.lua‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,12 @@ package = {
168168
-- consumer's build. `runtime.libraries` renders as gdi32.lib for
169169
-- MSVC and -lgdi32 for GNU.
170170
runtime = {
171-
libraries = { "gdi32" },
171+
-- GLFW calls User32 window/input APIs, GDI pixel-format APIs,
172+
-- and Shell32 drag/drop APIs itself. CMake's Windows defaults
173+
-- hide user32/shell32; a direct clang consumer needs them here.
174+
-- OpenGL, XInput, DirectInput and DWM are dynamically loaded by
175+
-- GLFW, so they do not require additional import libraries.
176+
libraries = { "user32", "gdi32", "shell32" },
172177
},
173178
},
174179
},

‎tests/examples/glfw/README.md‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Standalone GLFW smoke test
2+
3+
From the repository root, run `mcpp test -p glfw` (including on Windows).
4+
The manifest redirects `compat` to this checkout so the test checks the PR's
5+
package descriptor rather than the published index.
6+
7+
The test checks the upstream version and creates a Null-platform window on every
8+
platform. On Windows it also requires the Win32 backend, creates a hidden native
9+
window, checks its size and user pointer, polls events, and closes it. A failed
10+
initialization or window creation fails the test. No visible window or graphics
11+
context is required.
12+
13+
The only direct dependency is `compat.glfw`. `GLFW_INCLUDE_NONE` and
14+
`GLFW_NO_API` keep graphics API headers and context creation out of this test.
15+
GLFW's own native system-library references belong in the package descriptor;
16+
libraries used directly by an application (for example OpenGL entry points or a
17+
Vulkan loader) belong to that application. GLFW dynamically loads several
18+
optional Windows APIs, so their DLL names alone are not a reason to add import
19+
libraries. Keep dialect-neutral native link requirements in `runtime.libraries`.

‎tests/examples/glfw/mcpp.toml‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "glfw-tests"
3+
version = "0.1.0"
4+
5+
[dependencies.compat]
6+
glfw = "3.4"
7+
8+
[indices]
9+
compat = { path = "../../.." }
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#define GLFW_INCLUDE_NONE
2+
#include <GLFW/glfw3.h>
3+
#include <cstdio>
4+
#include <cstring>
5+
6+
static void error(int code, const char* description) {
7+
std::fprintf(stderr, "GLFW error %d: %s\n", code, description);
8+
}
9+
10+
static bool window_test(int platform) {
11+
glfwInitHint(GLFW_PLATFORM, platform);
12+
if (!glfwInit()) return false;
13+
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
14+
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
15+
GLFWwindow* window = glfwCreateWindow(640, 480, "compat.glfw smoke", nullptr, nullptr);
16+
bool ok = window && glfwGetPlatform() == platform;
17+
if (window) {
18+
int width = 0, height = 0;
19+
glfwGetWindowSize(window, &width, &height);
20+
int marker = 42;
21+
glfwSetWindowUserPointer(window, &marker);
22+
ok = ok && width == 640 && height == 480 &&
23+
glfwGetWindowUserPointer(window) == &marker &&
24+
!glfwWindowShouldClose(window);
25+
if (!ok) std::fprintf(stderr, "platform %x: size=%dx%d, expected=640x480, user_pointer=%d, should_close=%d\n",
26+
platform, width, height,
27+
glfwGetWindowUserPointer(window) == &marker,
28+
glfwWindowShouldClose(window));
29+
glfwSetWindowShouldClose(window, GLFW_TRUE);
30+
ok = ok && glfwWindowShouldClose(window);
31+
glfwPollEvents();
32+
glfwDestroyWindow(window);
33+
}
34+
glfwTerminate();
35+
return ok;
36+
}
37+
38+
int main() {
39+
glfwSetErrorCallback(error);
40+
int major = 0, minor = 0, revision = 0;
41+
glfwGetVersion(&major, &minor, &revision);
42+
if (major != 3 || minor != 4 || revision != 0) return 1;
43+
if (!window_test(GLFW_PLATFORM_NULL)) return 2;
44+
#ifdef _WIN32
45+
// Require the real Win32 backend too: a null-only test misses native links.
46+
if (!glfwPlatformSupported(GLFW_PLATFORM_WIN32)) return 3;
47+
if (!std::strstr(glfwGetVersionString(), "Win32")) return 4;
48+
if (!window_test(GLFW_PLATFORM_WIN32)) return 5;
49+
#endif
50+
return 0;
51+
}

0 commit comments

Comments
 (0)