Skip to content

Commit a687b50

Browse files
authored
Add GLX runtime closure for GLFW (#29)
1 parent b697287 commit a687b50

17 files changed

Lines changed: 226 additions & 149 deletions

.github/workflows/validate.yml

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ jobs:
5353
uses: actions/cache@v4
5454
with:
5555
path: ~/.mcpp/registry
56-
key: mcpp-registry-${{ runner.os }}-0.0.45-${{ hashFiles('pkgs/**/*.lua', 'tests/*.sh', '.github/workflows/validate.yml') }}
56+
key: mcpp-registry-${{ runner.os }}-0.0.46-${{ hashFiles('pkgs/**/*.lua', 'tests/*.sh', '.github/workflows/validate.yml') }}
5757
restore-keys: |
58-
mcpp-registry-${{ runner.os }}-0.0.45-
58+
mcpp-registry-${{ runner.os }}-0.0.46-
5959
- name: Download mcpp
6060
env:
61-
MCPP_VERSION: "0.0.45"
61+
MCPP_VERSION: "0.0.46"
6262
run: |
6363
curl -L -fsS -o mcpp.tar.gz \
6464
"https://github.com/mcpp-community/mcpp/releases/download/v${MCPP_VERSION}/mcpp-${MCPP_VERSION}-linux-x86_64.tar.gz"
@@ -72,6 +72,7 @@ jobs:
7272
- name: Run compat smoke tests
7373
env:
7474
MCPP_INDEX_SMOKE_MCPP_HOME: ${{ runner.temp }}/mcpp-smoke-home
75+
MCPP_INDEX_SMOKE_CACHE_DIR: ${{ runner.temp }}/mcpp-smoke-cache
7576
run: |
7677
mkdir -p "$MCPP_INDEX_SMOKE_MCPP_HOME"
7778
"$MCPP" --version
@@ -91,14 +92,14 @@ jobs:
9192
include:
9293
- platform: macos
9394
os: macos-15
94-
archive: mcpp-0.0.45-macosx-arm64.tar.gz
95-
root: mcpp-0.0.45-macosx-arm64
95+
archive: mcpp-0.0.46-macosx-arm64.tar.gz
96+
root: mcpp-0.0.46-macosx-arm64
9697
mcpp: bin/mcpp
9798
xlings: registry/bin/xlings
9899
- platform: windows
99100
os: windows-latest
100-
archive: mcpp-0.0.45-windows-x86_64.zip
101-
root: mcpp-0.0.45-windows-x86_64
101+
archive: mcpp-0.0.46-windows-x86_64.zip
102+
root: mcpp-0.0.46-windows-x86_64
102103
mcpp: bin/mcpp.exe
103104
xlings: registry/bin/xlings.exe
104105
steps:
@@ -107,13 +108,13 @@ jobs:
107108
uses: actions/cache@v4
108109
with:
109110
path: ~/.mcpp/registry
110-
key: mcpp-registry-${{ runner.os }}-0.0.45-${{ hashFiles('pkgs/**/*.lua', 'tests/*.sh', '.github/workflows/validate.yml') }}
111+
key: mcpp-registry-${{ runner.os }}-0.0.46-${{ hashFiles('pkgs/**/*.lua', 'tests/*.sh', '.github/workflows/validate.yml') }}
111112
restore-keys: |
112-
mcpp-registry-${{ runner.os }}-0.0.45-
113+
mcpp-registry-${{ runner.os }}-0.0.46-
113114
- name: Download mcpp
114115
shell: bash
115116
env:
116-
MCPP_VERSION: "0.0.45"
117+
MCPP_VERSION: "0.0.46"
117118
MCPP_ARCHIVE: ${{ matrix.archive }}
118119
MCPP_ROOT: ${{ matrix.root }}
119120
run: |

README.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ mcpp build # 自动拉取源码 + 构建
3939
| `gtest` | 1.15.2 | Google Test 测试框架 |
4040
| `imgui` | 1.92.8 | Dear ImGui immediate-mode GUI 核心源码 |
4141
| `opengl` | 2026.05.31 | Khronos OpenGL API 头文件 |
42+
| `glx-runtime` | 2026.06.03 | Linux host GLVND/GLX/OpenGL runtime adapter |
4243
| `khrplatform` | 2026.05.31 | Khronos KHR platform 头文件 |
4344
| `xorgproto` | 2025.1 | X.Org protocol 头文件 |
4445
| `xtrans` | 1.6.0 | X.Org transport support headers/source snippets |
@@ -77,7 +78,10 @@ mcpplibs.xpkg
7778
imgui
7879
├── compat.imgui
7980
├── compat.glfw
80-
│ └── compat.opengl
81+
│ ├── compat.opengl
82+
│ └── compat.glx-runtime
83+
│ └── compat.xext → compat.x11
84+
│ ← Linux GLX/OpenGL driver runtime provider
8185
└── compat.opengl ← 消费者只需要 import imgui.* 模块
8286
8387
libarchive
@@ -90,6 +94,8 @@ libarchive
9094
glfw
9195
├── opengl
9296
│ └── khrplatform ← GLFW/glfw3.h 所需 OpenGL/KHR 头文件
97+
├── glx-runtime
98+
│ └── xext → x11 ← GLFW GLX dlopen 所需 host GLVND/driver runtime
9399
└── x11 / xcursor / xext / xfixes / xi
94100
/ xinerama / xorgproto / xrandr / xrender
95101
← GLFW Linux X11 后端所需 runtime/header 闭包
@@ -111,9 +117,11 @@ x11
111117
mcpp 0.0.3+ 的 transitive walker 自动沿链路传播头文件和依赖,消费者只需声明直接依赖。
112118

113119
> 当前 X11/XCB/Xau/Xdmcp 以及 GLFW 需要的 Xcursor/Xext/Xfixes/Xi/Xinerama/
114-
> Xrandr/Xrender 都已按上游源码提供 runtime `.so``compat.glfw` 仍沿用
115-
> GLFW 上游的 GLX/OpenGL 动态加载行为,包描述会声明需要 `dlopen`
116-
> `libGLX.so.0`/`libGL.so.1`/`libGL.so` 以及 `opengl.glx.driver` 能力。
120+
> Xrandr/Xrender 都已按上游源码提供 runtime `.so`,并声明标准 ELF SONAME
121+
> (如 `libX11.so.6``libxcb.so.1`)。`compat.glx-runtime` 是 Linux host
122+
> GLVND/GLX/OpenGL driver runtime adapter,提供 GLFW 上游 `dlopen` 需要的
123+
> `libGLX.so.0`/`libGL.so.1`/`libGL.so` runtime 目录,并通过 `compat.xext`
124+
> 带入 host GLX 库常见的 X11/Xext ABI 依赖闭包。
117125
> 窗口运行时仍需要宿主环境提供可用的 X server/GLX/OpenGL 驱动。
118126
119127
### 本地 smoke 验证

pkgs/c/compat.glfw.lua

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ package = {
7171
"src/posix_module.c",
7272
},
7373
deps = {
74+
["compat.glx-runtime"] = "2026.06.03",
7475
["compat.x11"] = "1.8.13",
7576
["compat.xcursor"] = "1.2.3",
7677
["compat.xext"] = "1.3.7",
@@ -119,25 +120,6 @@ package = {
119120

120121
import("xim.libxpkg.pkginfo")
121122

122-
local function patch_x11_loader_names(root)
123-
local file = path.join(root, "src", "x11_init.c")
124-
local data = io.readfile(file)
125-
local replacements = {
126-
['"libX11.so.6"'] = '"libX11.so"',
127-
['"libXi.so.6"'] = '"libXi.so"',
128-
['"libXrandr.so.2"'] = '"libXrandr.so"',
129-
['"libXcursor.so.1"'] = '"libXcursor.so"',
130-
['"libXinerama.so.1"'] = '"libXinerama.so"',
131-
['"libX11-xcb.so.1"'] = '"libX11-xcb.so"',
132-
['"libXrender.so.1"'] = '"libXrender.so"',
133-
['"libXext.so.6"'] = '"libXext.so"',
134-
}
135-
for from, to in pairs(replacements) do
136-
data = data:gsub(from, to)
137-
end
138-
io.writefile(file, data)
139-
end
140-
141123
function install()
142124
local srcdir = pkginfo.install_file():replace(".tar.gz", "")
143125
if not os.isdir(srcdir) then
@@ -146,6 +128,5 @@ function install()
146128

147129
os.tryrm(pkginfo.install_dir())
148130
os.mv(srcdir, pkginfo.install_dir())
149-
patch_x11_loader_names(pkginfo.install_dir())
150131
return true
151132
end

pkgs/c/compat.glx-runtime.lua

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package = {
2+
spec = "1",
3+
namespace = "compat",
4+
name = "compat.glx-runtime",
5+
description = "Host GLVND/GLX/OpenGL runtime adapter for mcpp Linux window applications",
6+
licenses = {"MIT"},
7+
repo = "https://github.com/KhronosGroup/OpenGL-Registry",
8+
type = "package",
9+
10+
xpm = {
11+
linux = {
12+
["2026.06.03"] = {
13+
url = "https://raw.githubusercontent.com/KhronosGroup/OpenGL-Registry/a30033d3e812c9bf10094f1010374a6b15e192eb/README.adoc",
14+
sha256 = "ea68efce197e68413ebb62c51ab4bccfb2309a2fca776d31b49d972f59f3640e",
15+
},
16+
},
17+
},
18+
19+
mcpp = {
20+
language = "c++23",
21+
import_std = false,
22+
c_standard = "c11",
23+
generated_files = {
24+
["mcpp_generated/glx_runtime_empty.c"] = "int mcpp_compat_glx_runtime_anchor(void) { return 0; }\n",
25+
},
26+
sources = {"mcpp_generated/glx_runtime_empty.c"},
27+
targets = { ["glx_runtime"] = { kind = "lib" } },
28+
runtime = {
29+
library_dirs = { "mcpp_generated/glx_runtime/lib" },
30+
dlopen_libs = { "libGLX.so.0", "libGL.so.1", "libGL.so" },
31+
capabilities = { "x11.display", "opengl.glx.driver" },
32+
},
33+
deps = {
34+
["compat.xext"] = "1.3.7",
35+
},
36+
},
37+
}
38+
39+
import("xim.libxpkg.pkginfo")
40+
import("xim.libxpkg.log")
41+
42+
local function sh_quote(value)
43+
return "'" .. tostring(value):gsub("'", "'\\''") .. "'"
44+
end
45+
46+
local function split_paths(value)
47+
local out = {}
48+
if not value or value == "" then
49+
return out
50+
end
51+
for item in tostring(value):gmatch("[^:]+") do
52+
if item ~= "" then
53+
table.insert(out, item)
54+
end
55+
end
56+
return out
57+
end
58+
59+
local function candidate_dirs()
60+
local out = {}
61+
local seen = {}
62+
local function add(dir)
63+
if dir and dir ~= "" and not seen[dir] and os.isdir(dir) then
64+
seen[dir] = true
65+
table.insert(out, dir)
66+
end
67+
end
68+
69+
for _, dir in ipairs(split_paths(os.getenv("MCPP_HOST_GL_LIBRARY_PATH"))) do
70+
add(dir)
71+
end
72+
add("/lib/x86_64-linux-gnu")
73+
add("/usr/lib/x86_64-linux-gnu")
74+
add("/lib64")
75+
add("/usr/lib64")
76+
add("/usr/lib")
77+
return out
78+
end
79+
80+
local host_gl_patterns = {
81+
"libGL.so*",
82+
"libGLX.so*",
83+
"libGLX_*.so*",
84+
"libGLdispatch.so*",
85+
"libOpenGL.so*",
86+
"libEGL.so*",
87+
"libEGL_*.so*",
88+
"libGLES*.so*",
89+
"libnvidia*.so*",
90+
"libglapi.so*",
91+
"libdrm*.so*",
92+
"libexpat.so*",
93+
"libxshmfence.so*",
94+
"libbsd.so*",
95+
"libmd.so*",
96+
}
97+
98+
local required = {
99+
["libGLX.so.0"] = false,
100+
["libGL.so.1"] = false,
101+
}
102+
103+
local function link_runtime_libs(outdir)
104+
os.mkdir(outdir)
105+
for _, dir in ipairs(candidate_dirs()) do
106+
for _, pattern in ipairs(host_gl_patterns) do
107+
os.exec(
108+
"for lib in " .. sh_quote(dir) .. "/" .. pattern ..
109+
"; do [ -e \"$lib\" ] || continue; " ..
110+
"ln -sf \"$lib\" " .. sh_quote(outdir) .. "/\"$(basename \"$lib\")\"; " ..
111+
"done"
112+
)
113+
end
114+
end
115+
116+
for name, _ in pairs(required) do
117+
if not os.isfile(path.join(outdir, name)) then
118+
log.error("required host GL runtime library not found: %s", name)
119+
return false
120+
end
121+
end
122+
return true
123+
end
124+
125+
function install()
126+
os.tryrm(pkginfo.install_dir())
127+
os.mkdir(pkginfo.install_dir())
128+
129+
local generated = path.join(pkginfo.install_dir(), "mcpp_generated")
130+
os.mkdir(generated)
131+
io.writefile(path.join(generated, "glx_runtime_empty.c"),
132+
"int mcpp_compat_glx_runtime_anchor(void) { return 0; }\n")
133+
134+
return link_runtime_libs(path.join(generated, "glx_runtime", "lib"))
135+
end

pkgs/c/compat.x11.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ package = {
5555
"modules/lc/Utf8/*.c",
5656
"modules/om/generic/*.c",
5757
},
58-
targets = { ["X11"] = { kind = "shared" } },
58+
targets = { ["X11"] = { kind = "shared", soname = "libX11.so.6" } },
5959
deps = {
6060
["compat.xcb"] = "1.17.0",
6161
["compat.xorgproto"] = "2025.1",

pkgs/c/compat.xau.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ package = {
3232
"*/AuUnlock.c",
3333
"*/AuWrite.c",
3434
},
35-
targets = { ["Xau"] = { kind = "shared" } },
35+
targets = { ["Xau"] = { kind = "shared", soname = "libXau.so.6" } },
3636
deps = {
3737
["compat.xorgproto"] = "2025.1",
3838
},

pkgs/c/compat.xcb.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ package = {
4242
"src/bigreq.c",
4343
"src/xc_misc.c",
4444
},
45-
targets = { ["xcb"] = { kind = "shared" } },
45+
targets = { ["xcb"] = { kind = "shared", soname = "libxcb.so.1" } },
4646
deps = {
4747
["compat.xau"] = "1.0.12",
4848
["compat.xcb-proto"] = "1.17.0",

pkgs/c/compat.xcursor.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ package = {
2323
cflags = {"-D_GNU_SOURCE", "-D_DEFAULT_SOURCE", "-DHAVE_XFIXES=1"},
2424
include_dirs = {"*/include", "*/include/X11/Xcursor", "*/include/X11/extensions", "*/src"},
2525
sources = {"*/src/*.c"},
26-
targets = { ["Xcursor"] = { kind = "shared" } },
26+
targets = { ["Xcursor"] = { kind = "shared", soname = "libXcursor.so.1" } },
2727
deps = {
2828
["compat.x11"] = "1.8.13",
2929
["compat.xfixes"] = "6.0.2",

pkgs/c/compat.xdmcp.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ package = {
3232
"*/Wrap.c",
3333
"*/Write.c",
3434
},
35-
targets = { ["Xdmcp"] = { kind = "shared" } },
35+
targets = { ["Xdmcp"] = { kind = "shared", soname = "libXdmcp.so.6" } },
3636
deps = {
3737
["compat.xorgproto"] = "2025.1",
3838
},

pkgs/c/compat.xext.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ package = {
2323
cflags = {"-D_GNU_SOURCE", "-D_DEFAULT_SOURCE"},
2424
include_dirs = {"*/include", "*/include/X11/extensions", "*/src"},
2525
sources = {"*/src/*.c"},
26-
targets = { ["Xext"] = { kind = "shared" } },
26+
targets = { ["Xext"] = { kind = "shared", soname = "libXext.so.6" } },
2727
deps = {
2828
["compat.x11"] = "1.8.13",
2929
["compat.xorgproto"] = "2025.1",

0 commit comments

Comments
 (0)