Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 34 additions & 8 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: validate

on:
pull_request:
paths: ["pkgs/**/*.lua", ".github/workflows/validate.yml"]
paths: ["pkgs/**/*.lua", "tests/**", "README.md", ".github/workflows/validate.yml"]
push:
branches: [main]

Expand All @@ -17,18 +17,13 @@ jobs:
run: |
fail=0
for f in pkgs/*/*.lua; do
# 1. Forbidden install hook (security: descriptors must not run code)
if grep -q "^function install" "$f"; then
echo "::error file=$f::install hook is forbidden"
fail=1
fi
# 2. Lua syntax check — load (= compile) without executing.
# 1. Lua syntax check — load (= compile) without executing.
# `loadfile(name, 't')` rejects bytecode and parses text only.
if ! lua5.4 -e "assert(loadfile('$f', 't'))" >/dev/null 2>&1; then
echo "::error file=$f::lua syntax error"
fail=1
fi
# 3. xpkg V1 baseline: the file has to populate `package = { ... }`
# 2. xpkg V1 baseline: the file has to populate `package = { ... }`
# with at least `spec`, `name`, and an `xpm` table. Form A vs
# Form B (mcpp = "<path>" / mcpp = { ... }) is descriptor-author
# choice and not enforced here.
Expand All @@ -38,6 +33,37 @@ jobs:
fail=1
fi
done
# 3. Package version identifiers and dependency versions should be
# bare versions ("1.2.3"), not upstream tag names ("v1.2.3").
# Download URLs may still contain refs/tags/v* when upstream
# uses that tag spelling.
if grep -nE '\["v[0-9]+|\["[^"]+"\][[:space:]]*=[[:space:]]*"v[0-9]+' "$f"; then
echo "::error file=$f::version identifiers must not use a leading v"
fail=1
fi
done
[ $fail -eq 0 ] && echo "All package files valid."
exit $fail

smoke-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Download mcpp
env:
MCPP_VERSION: "0.0.40"
run: |
curl -L -fsS -o mcpp.tar.gz \
"https://github.com/mcpp-community/mcpp/releases/download/v${MCPP_VERSION}/mcpp-${MCPP_VERSION}-linux-x86_64.tar.gz"
tar -xzf mcpp.tar.gz
root="$PWD/mcpp-${MCPP_VERSION}-linux-x86_64"
echo "MCPP=$root/bin/mcpp" >> "$GITHUB_ENV"
echo "MCPP_VENDORED_XLINGS=$root/registry/bin/xlings" >> "$GITHUB_ENV"
echo "$root/bin" >> "$GITHUB_PATH"
- name: Run compat smoke tests
run: |
"$MCPP" --version
timeout 1800 bash tests/smoke_compat_core.sh
timeout 1800 bash tests/smoke_compat_imgui.sh
timeout 1800 bash tests/smoke_compat_archive.sh
timeout 1800 bash tests/smoke_compat_imgui_window.sh
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.xlings-index-cache.json
84 changes: 78 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,31 @@ mcpp build # 自动拉取源码 + 构建
| 包名 | 版本 | 简介 |
|------|------|------|
| `ftxui` | 6.1.9 | C++ 函数式终端 UI 库(screen + dom + component) |
| `glfw` | 3.4 | GLFW 窗口与输入库(null platform 后端源码构建) |
| `glfw` | 3.4 | GLFW 窗口与输入库(X11/null 后端源码构建) |
| `gtest` | 1.15.2 | Google Test 测试框架 |
| `imgui` | v1.92.8 | Dear ImGui immediate-mode GUI 核心源码 |
| `imgui` | 1.92.8 | Dear ImGui immediate-mode GUI 核心源码 |
| `opengl` | 2026.05.31 | Khronos OpenGL API 头文件 |
| `khrplatform` | 2026.05.31 | Khronos KHR platform 头文件 |
| `xorgproto` | 2025.1 | X.Org protocol 头文件 |
| `xtrans` | 1.6.0 | X.Org transport support headers/source snippets |
| `xau` | 1.0.12 | X authorization runtime library(`libXau.so`) |
| `xdmcp` | 1.1.5 | X Display Manager Control Protocol runtime library(`libXdmcp.so`) |
| `xcb-proto` | 1.17.0 | XCB protocol XML definitions and generator metadata |
| `xcb` | 1.17.0 | X C Binding runtime library(`libxcb.so`) |
| `x11` | 1.8.13 | Xlib runtime library(`libX11.so`) and public headers |
| `xcursor` | 1.2.3 | Xcursor runtime library(`libXcursor.so`) and public headers |
| `xext` | 1.3.7 | Xext runtime library(`libXext.so`) and public headers |
| `xfixes` | 6.0.2 | Xfixes runtime library(`libXfixes.so`) and public headers |
| `xi` | 1.8.3 | XInput runtime library(`libXi.so`) and public headers |
| `xinerama` | 1.1.6 | Xinerama runtime library(`libXinerama.so`) and public headers |
| `xrandr` | 1.5.5 | Xrandr runtime library(`libXrandr.so`) and public headers |
| `xrender` | 0.9.12 | Xrender runtime library(`libXrender.so`) and public headers |
| `mbedtls` | 3.6.1 | TLS/加密库(纯 C) |
| `lua` | 5.4.7 | Lua 脚本语言(纯 C 嵌入式库) |
| `zlib` | v1.3.2 | DEFLATE 压缩库 |
| `zlib` | 1.3.2 | DEFLATE 压缩库 |
| `bzip2` | 1.0.8 | bzip2 压缩库 |
| `lz4` | v1.10.0 | LZ4 压缩库 |
| `zstd` | v1.5.7 | Zstandard 压缩库 |
| `lz4` | 1.10.0 | LZ4 压缩库 |
| `zstd` | 1.5.7 | Zstandard 压缩库 |
| `xz` | 5.8.3 | XZ Utils liblzma 压缩库 |
| `libarchive` | 3.8.7 | 多格式归档与压缩库 |

Expand All @@ -61,11 +76,68 @@ libarchive
└── xz ← 压缩后端自动传递

glfw
└── opengl ← GLFW/glfw3.h 所需 OpenGL 头文件
├── opengl
│ └── khrplatform ← GLFW/glfw3.h 所需 OpenGL/KHR 头文件
└── x11 / xcursor / xext / xfixes / xi
/ xinerama / xorgproto / xrandr / xrender
← GLFW Linux X11 后端所需 runtime/header 闭包

xau / xdmcp
└── xorgproto ← X11 底层 runtime 库的协议头文件

xcb
├── xcb-proto ← hook 内生成 xcb 协议源文件
├── xau
└── xdmcp

x11
├── xcb
├── xorgproto
└── xtrans ← Xlib/XIM transport 源码片段
```

mcpp 0.0.3+ 的 transitive walker 自动沿链路传播头文件和依赖,消费者只需声明直接依赖。

> 当前 X11/XCB/Xau/Xdmcp 以及 GLFW 需要的 Xcursor/Xext/Xfixes/Xi/Xinerama/
> Xrandr/Xrender 都已按上游源码提供 runtime `.so`。`compat.glfw` 仍沿用
> GLFW 上游的 GLX/OpenGL 动态加载行为,窗口运行时需要宿主环境提供可用的
> X server/GLX/OpenGL 驱动。

### 本地 smoke 验证

```bash
MCPP=/path/to/mcpp tests/smoke_compat_core.sh
MCPP=/path/to/mcpp tests/smoke_compat_imgui.sh
MCPP=/path/to/mcpp tests/smoke_compat_archive.sh
```

该脚本会通过当前 checkout 作为本地 path index 创建临时 mcpp 项目,验证:

- `compat.gtest`/`compat.ftxui`/`compat.lua`/`compat.mbedtls` 能用上游
`#include <...>` API 构建并运行最小用例
- `compat.opengl`/`compat.khrplatform` 能提供 GLFW/OpenGL 常见头文件闭包
- `compat.imgui@1.92.8` core 能构建并运行一个 headless ImGui frame
- `compat.glfw@3.4` 能构建、运行 `glfwInit()` smoke,并链接 X11 扩展 runtime `.so`
- `compat.xau@1.0.12`/`compat.xdmcp@1.1.5` 能构建、运行并链接 runtime `.so`
- `compat.xcb@1.17.0` 能构建、运行并链接 `libxcb.so`
- `compat.x11@1.8.13` 能构建、运行并链接 `libX11.so` → `libxcb.so`
- `compat.xcursor`/`compat.xext`/`compat.xfixes`/`compat.xi`/`compat.xinerama`/
`compat.xrandr`/`compat.xrender` 能构建、运行并链接对应 `libX*.so`
- `compat.libarchive` 能连同 `zlib`/`bzip2`/`lz4`/`zstd`/`xz` 压缩后端构建并运行

有窗口的 ImGui + GLFW + OpenGL demo 单独放在可选 smoke 中:

```bash
MCPP=/path/to/mcpp tests/smoke_compat_imgui_window.sh
MCPP=/path/to/mcpp MCPP_INDEX_RUN_WINDOW_SMOKE=1 tests/smoke_compat_imgui_window.sh
```

默认只验证 demo 构建和 X11 runtime 链接闭包。显式设置
`MCPP_INDEX_RUN_WINDOW_SMOKE=1` 后才会运行隐藏窗口帧渲染,此时需要当前
`DISPLAY` 可用,并且宿主机提供 GLVND/GLX/OpenGL 驱动 runtime。脚本会把
宿主 GL runtime 和 compat X11 runtime 组装到临时 `LD_LIBRARY_PATH` 中,
避免系统 X11 库覆盖 mcpp 构建出的 `libX11.so`/`libxcb.so`。

## 包描述文件

每个包对应一个 `pkgs/<首字母>/<包名>.lua` 文件,遵循 [xpkg V1 规范](https://github.com/d2learn/xim-pkgindex/blob/main/docs/V1/xpackage-spec.md)。
Expand Down
137 changes: 118 additions & 19 deletions pkgs/c/compat.glfw.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package = {
spec = "1",
namespace = "compat",
name = "compat.glfw",
description = "GLFW windowing and input library built from source with the null platform backend",
description = "GLFW windowing and input library built from upstream sources",
licenses = {"Zlib"},
repo = "https://github.com/glfw/glfw",
type = "package",
Expand All @@ -14,35 +14,134 @@ package = {
sha256 = "c038d34200234d071fae9345bc455e4a8f2f544ab60150765d7704e08f3dac01",
},
},
macosx = {
["3.4"] = {
url = "https://github.com/glfw/glfw/archive/refs/tags/3.4.tar.gz",
sha256 = "c038d34200234d071fae9345bc455e4a8f2f544ab60150765d7704e08f3dac01",
},
},
windows = {
["3.4"] = {
url = "https://github.com/glfw/glfw/archive/refs/tags/3.4.tar.gz",
sha256 = "c038d34200234d071fae9345bc455e4a8f2f544ab60150765d7704e08f3dac01",
},
},
},

mcpp = {
language = "c++23",
import_std = false,
c_standard = "c11",
cflags = { "-D_DEFAULT_SOURCE" },
include_dirs = {"*/include", "*/src"},
include_dirs = {"include", "src"},
sources = {
"*/src/context.c",
"*/src/init.c",
"*/src/input.c",
"*/src/monitor.c",
"*/src/platform.c",
"*/src/vulkan.c",
"*/src/window.c",
"*/src/egl_context.c",
"*/src/osmesa_context.c",
"*/src/null_init.c",
"*/src/null_monitor.c",
"*/src/null_window.c",
"*/src/null_joystick.c",
"*/src/posix_time.c",
"*/src/posix_thread.c",
"*/src/posix_module.c",
"src/context.c",
"src/init.c",
"src/input.c",
"src/monitor.c",
"src/platform.c",
"src/vulkan.c",
"src/window.c",
"src/egl_context.c",
"src/osmesa_context.c",
"src/null_init.c",
"src/null_monitor.c",
"src/null_window.c",
"src/null_joystick.c",
},
targets = { ["glfw"] = { kind = "lib" } },
deps = {
["compat.opengl"] = "2026.05.31",
},
linux = {
cflags = { "-D_DEFAULT_SOURCE", "-D_GLFW_X11" },
sources = {
"src/x11_init.c",
"src/x11_monitor.c",
"src/x11_window.c",
"src/xkb_unicode.c",
"src/glx_context.c",
"src/linux_joystick.c",
"src/posix_poll.c",
"src/posix_time.c",
"src/posix_thread.c",
"src/posix_module.c",
},
deps = {
["compat.x11"] = "1.8.13",
["compat.xcursor"] = "1.2.3",
["compat.xext"] = "1.3.7",
["compat.xfixes"] = "6.0.2",
["compat.xi"] = "1.8.3",
["compat.xinerama"] = "1.1.6",
["compat.xorgproto"] = "2025.1",
["compat.xrandr"] = "1.5.5",
["compat.xrender"] = "0.9.12",
},
},
macosx = {
cflags = { "-D_GLFW_COCOA" },
sources = {
"src/cocoa_time.c",
"src/posix_thread.c",
"src/posix_module.c",
"src/cocoa_init.m",
"src/cocoa_joystick.m",
"src/cocoa_monitor.m",
"src/cocoa_window.m",
"src/nsgl_context.m",
},
ldflags = {
"-framework", "Cocoa",
"-framework", "IOKit",
"-framework", "CoreFoundation",
},
},
windows = {
cflags = { "-D_GLFW_WIN32", "-DUNICODE", "-D_UNICODE" },
sources = {
"src/win32_time.c",
"src/win32_thread.c",
"src/win32_module.c",
"src/win32_init.c",
"src/win32_joystick.c",
"src/win32_monitor.c",
"src/win32_window.c",
"src/wgl_context.c",
},
ldflags = { "-lgdi32" },
},
},
}

import("xim.libxpkg.pkginfo")

local function patch_x11_loader_names(root)
local file = path.join(root, "src", "x11_init.c")
local data = io.readfile(file)
local replacements = {
['"libX11.so.6"'] = '"libX11.so"',
['"libXi.so.6"'] = '"libXi.so"',
['"libXrandr.so.2"'] = '"libXrandr.so"',
['"libXcursor.so.1"'] = '"libXcursor.so"',
['"libXinerama.so.1"'] = '"libXinerama.so"',
['"libX11-xcb.so.1"'] = '"libX11-xcb.so"',
['"libXrender.so.1"'] = '"libXrender.so"',
['"libXext.so.6"'] = '"libXext.so"',
}
for from, to in pairs(replacements) do
data = data:gsub(from, to)
end
io.writefile(file, data)
end

function install()
local srcdir = pkginfo.install_file():replace(".tar.gz", "")
if not os.isdir(srcdir) then
srcdir = "glfw-" .. pkginfo.version()
end

os.tryrm(pkginfo.install_dir())
os.mv(srcdir, pkginfo.install_dir())
patch_x11_loader_names(pkginfo.install_dir())
return true
end
6 changes: 3 additions & 3 deletions pkgs/c/compat.imgui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ package = {

xpm = {
linux = {
["v1.92.8"] = {
["1.92.8"] = {
url = "https://github.com/ocornut/imgui/archive/refs/tags/v1.92.8.tar.gz",
sha256 = "fecb33d33930e12ff53a34064e9d3a06c8f7c3e04408f14cd36c80e3faac863b",
},
},
macosx = {
["v1.92.8"] = {
["1.92.8"] = {
url = "https://github.com/ocornut/imgui/archive/refs/tags/v1.92.8.tar.gz",
sha256 = "fecb33d33930e12ff53a34064e9d3a06c8f7c3e04408f14cd36c80e3faac863b",
},
},
windows = {
["v1.92.8"] = {
["1.92.8"] = {
url = "https://github.com/ocornut/imgui/archive/refs/tags/v1.92.8.tar.gz",
sha256 = "fecb33d33930e12ff53a34064e9d3a06c8f7c3e04408f14cd36c80e3faac863b",
},
Expand Down
Loading
Loading