From fc72517cded3e6773d8be80d574f4aae2c063ae7 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 1 Jun 2026 09:08:08 +0800 Subject: [PATCH 1/9] Add portable compat smoke coverage --- .github/workflows/validate.yml | 58 ++++++++ tests/smoke_compat_portable.sh | 265 +++++++++++++++++++++++++++++++++ 2 files changed, 323 insertions(+) create mode 100755 tests/smoke_compat_portable.sh diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 333d96b..16298a0 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -67,3 +67,61 @@ jobs: 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 + + smoke-portable: + name: smoke-${{ matrix.platform }} + runs-on: ${{ matrix.os }} + timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + include: + - platform: macos + os: macos-15 + archive: mcpp-0.0.40-macosx-arm64.tar.gz + root: mcpp-0.0.40-macosx-arm64 + mcpp: bin/mcpp + xlings: registry/bin/xlings + - platform: windows + os: windows-latest + archive: mcpp-0.0.40-windows-x86_64.zip + root: mcpp-0.0.40-windows-x86_64 + mcpp: bin/mcpp.exe + xlings: registry/bin/xlings.exe + steps: + - uses: actions/checkout@v4 + - name: Download mcpp + shell: bash + env: + MCPP_VERSION: "0.0.40" + MCPP_ARCHIVE: ${{ matrix.archive }} + MCPP_ROOT: ${{ matrix.root }} + run: | + curl -L -fsS -o "$MCPP_ARCHIVE" \ + "https://github.com/mcpp-community/mcpp/releases/download/v${MCPP_VERSION}/${MCPP_ARCHIVE}" + case "$MCPP_ARCHIVE" in + *.zip) + powershell -NoProfile -Command "Expand-Archive -Force -Path '${MCPP_ARCHIVE}' -DestinationPath '.'" + ;; + *) + tar -xzf "$MCPP_ARCHIVE" + ;; + esac + + root="$PWD/$MCPP_ROOT" + if [[ "$RUNNER_OS" == "Windows" ]]; then + echo "MCPP=$(cygpath -m "$root/${{ matrix.mcpp }}")" >> "$GITHUB_ENV" + echo "MCPP_VENDORED_XLINGS=$(cygpath -m "$root/${{ matrix.xlings }}")" >> "$GITHUB_ENV" + echo "$(cygpath -m "$root/bin")" >> "$GITHUB_PATH" + else + echo "MCPP=$root/${{ matrix.mcpp }}" >> "$GITHUB_ENV" + echo "MCPP_VENDORED_XLINGS=$root/${{ matrix.xlings }}" >> "$GITHUB_ENV" + echo "$root/bin" >> "$GITHUB_PATH" + fi + - name: Run portable compat smoke tests + shell: bash + env: + MCPP_INDEX_MIRROR: GLOBAL + run: | + "$MCPP" --version + bash tests/smoke_compat_portable.sh diff --git a/tests/smoke_compat_portable.sh b/tests/smoke_compat_portable.sh new file mode 100755 index 0000000..7dd8992 --- /dev/null +++ b/tests/smoke_compat_portable.sh @@ -0,0 +1,265 @@ +#!/usr/bin/env bash +# Cross-platform smoke tests for compat packages that should not depend on +# Linux/X11 runtime libraries. +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +MCPP_BIN="${MCPP:-}" +if [[ -z "$MCPP_BIN" ]]; then + MCPP_BIN="$(command -v mcpp || true)" +fi + +to_native_path() { + if [[ "${OS:-}" == "Windows_NT" ]] && command -v cygpath >/dev/null 2>&1; then + cygpath -m "$1" + else + printf '%s\n' "$1" + fi +} + +to_posix_path() { + if [[ "${OS:-}" == "Windows_NT" ]] && command -v cygpath >/dev/null 2>&1; then + cygpath -u "$1" + else + printf '%s\n' "$1" + fi +} + +MCPP_BIN_POSIX="" +if [[ -n "$MCPP_BIN" ]]; then + MCPP_BIN_POSIX="$(to_posix_path "$MCPP_BIN")" +fi +if [[ -z "$MCPP_BIN_POSIX" || ! -f "$MCPP_BIN_POSIX" ]]; then + echo "FATAL: set MCPP=/path/to/mcpp or put mcpp on PATH" >&2 + exit 1 +fi + +platform="$(uname -s)" +if [[ "${OS:-}" == "Windows_NT" ]]; then + platform="Windows_NT" +fi + +case "$platform" in + Windows_NT|Darwin) + TOOLCHAIN="${MCPP_INDEX_PORTABLE_TOOLCHAIN:-llvm@20.1.7}" + ;; + *) + TOOLCHAIN="${MCPP_INDEX_PORTABLE_TOOLCHAIN:-gcc@16.1.0}" + ;; +esac + +TMP="$(mktemp -d)" +if [[ "${MCPP_INDEX_KEEP_SMOKE_TMP:-0}" == "1" ]]; then + echo "KEEP: $TMP" +else + trap 'rm -rf "$TMP"' EXIT +fi + +MCPP_HOME_POSIX="$TMP/mcpp-home" +mkdir -p "$MCPP_HOME_POSIX" +export MCPP_HOME="$(to_native_path "$MCPP_HOME_POSIX")" + +INDEX_ROOT="$(to_native_path "$ROOT")" +SMOKE_CACHE_DIR="${MCPP_INDEX_SMOKE_CACHE_DIR:-}" + +USER_MCPP="${MCPP_INDEX_USER_MCPP_HOME:-${HOME}/.mcpp}" +mkdir -p "$MCPP_HOME_POSIX/registry/data/xpkgs" +link_xpkgs() { + local src="$1" + [[ -d "$src" ]] || return 0 + find "$src" -mindepth 1 -maxdepth 1 -type d | while read -r pkg; do + [[ "$(basename "$pkg")" == compat-x-* ]] && continue + ln -s "$pkg" "$MCPP_HOME_POSIX/registry/data/xpkgs/$(basename "$pkg")" 2>/dev/null || true + done +} +link_xpkgs "${MCPP_INDEX_SMOKE_XPKGS_DIR:-}" +link_xpkgs "$USER_MCPP/registry/data/xpkgs" +if [[ -d "$USER_MCPP/registry/data/xim-pkgindex" ]]; then + mkdir -p "$MCPP_HOME_POSIX/registry/data/xim-pkgindex" + cp -a "$USER_MCPP/registry/data/xim-pkgindex/." "$MCPP_HOME_POSIX/registry/data/xim-pkgindex/" 2>/dev/null || true + rm -f "$MCPP_HOME_POSIX/registry/data/xim-pkgindex/.xlings-index-cache.json" +fi +if [[ -d "$USER_MCPP/registry/bin" ]]; then + mkdir -p "$MCPP_HOME_POSIX/registry" + ln -s "$USER_MCPP/registry/bin" "$MCPP_HOME_POSIX/registry/bin" 2>/dev/null || true +fi +if [[ -f "$USER_MCPP/config.toml" ]]; then + cp -f "$USER_MCPP/config.toml" "$MCPP_HOME_POSIX/config.toml" 2>/dev/null || true +fi + +"$MCPP_BIN_POSIX" self config --mirror "${MCPP_INDEX_MIRROR:-GLOBAL}" + +copy_smoke_cache() { + [[ -n "$SMOKE_CACHE_DIR" && -d "$SMOKE_CACHE_DIR" ]] || return 0 + mkdir -p .mcpp/.xlings/data/runtimedir + find "$SMOKE_CACHE_DIR" -maxdepth 1 -type f \ + \( -name '*.tar.gz' -o -name '*.tar.xz' -o -name '*.zip' \) \ + -exec cp -f {} .mcpp/.xlings/data/runtimedir/ \; +} + +write_build_ldflags() { + case "$platform" in + Linux) + cat <<'EOF' + +[build] +ldflags = ["-ldl", "-lm"] +EOF + ;; + Darwin) + cat <<'EOF' + +[build] +ldflags = ["-lm"] +EOF + ;; + esac +} + +make_project() { + local name="$1" + mkdir -p "$TMP/$name/src" + cd "$TMP/$name" + cat > mcpp.toml <> mcpp.toml <<'EOF' + +[dependencies.compat] +gtest = "1.15.2" +ftxui = "6.1.9" +lua = "5.4.7" +mbedtls = "3.6.1" +opengl = "2026.05.31" +khrplatform = "2026.05.31" +EOF +write_build_ldflags >> mcpp.toml +cat > src/main.cpp <<'EOF' +#include +#include + +#include +#include +#include +#include +#include +#include + +extern "C" { +#include +#include +#include +} + +TEST(CompatPortableCore, UpstreamHeadersAndRuntime) { + using namespace ftxui; + Element document = hbox({text("compat"), separator(), text("ftxui")}); + Screen screen = Screen::Create(Dimension::Fit(document), Dimension::Fit(document)); + Render(screen, document); + const std::string rendered = screen.ToString(); + EXPECT_NE(rendered.find("compat"), std::string::npos); + EXPECT_NE(rendered.find("ftxui"), std::string::npos); + + lua_State* state = luaL_newstate(); + ASSERT_NE(state, nullptr); + luaL_openlibs(state); + ASSERT_EQ(luaL_dostring(state, "return 20 + 22"), LUA_OK); + EXPECT_TRUE(lua_isinteger(state, -1)); + EXPECT_EQ(lua_tointeger(state, -1), 42); + lua_close(state); + + const unsigned char input[] = "abc"; + std::array out{}; + mbedtls_sha256(input, 3, out.data(), 0); + EXPECT_EQ(out[0], 0xba); + EXPECT_EQ(out[1], 0x78); + EXPECT_EQ(out[30], 0x15); + EXPECT_EQ(out[31], 0xad); + + EXPECT_EQ(GL_TEXTURE_2D, 0x0DE1); + EXPECT_EQ(static_cast(1), 1u); +} +EOF +"$MCPP_BIN_POSIX" build +"$MCPP_BIN_POSIX" run + +make_project "compat-portable-archive-smoke" +cat >> mcpp.toml <<'EOF' + +[dependencies.compat] +libarchive = "3.8.7" +EOF +cat > src/main.cpp <<'EOF' +#include +#include +#include +#include +#include +#include +#include + +int main() { + archive* writer = archive_write_new(); + if (!writer) return 1; + archive_write_free(writer); + + archive_entry* entry = archive_entry_new(); + if (!entry) return 2; + archive_entry_free(entry); + + if (!archive_version_string()) return 3; + if (!zlibVersion()) return 4; + if (!BZ2_bzlibVersion()) return 5; + if (LZ4_versionNumber() <= 0) return 6; + if (ZSTD_versionNumber() == 0) return 7; + if (lzma_version_number() == 0) return 8; + return 0; +} +EOF +"$MCPP_BIN_POSIX" build +"$MCPP_BIN_POSIX" run + +make_project "compat-portable-imgui-glfw-smoke" +cat >> mcpp.toml <<'EOF' + +[dependencies.compat] +imgui = "1.92.8" +glfw = "3.4" +EOF +cat > src/main.cpp <<'EOF' +#include +#include +#include +#include + +#include "imgui_impl_glfw.cpp" +#include "imgui_impl_opengl3.cpp" + +int main() { + const char* glfw = glfwGetVersionString(); + const char* imgui = ImGui::GetVersion(); + return glfw && imgui && + GLFW_VERSION_MAJOR == 3 && + IMGUI_VERSION_NUM >= 19200 ? 0 : 1; +} +EOF +"$MCPP_BIN_POSIX" build +"$MCPP_BIN_POSIX" run + +echo "OK" From 7191da360da907ee36e99c13835ff0e8ee0bb733 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 1 Jun 2026 09:14:05 +0800 Subject: [PATCH 2/9] Define Unicode mode for FTXUI on Windows --- pkgs/c/compat.ftxui.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/c/compat.ftxui.lua b/pkgs/c/compat.ftxui.lua index c36e5c0..c4145b1 100644 --- a/pkgs/c/compat.ftxui.lua +++ b/pkgs/c/compat.ftxui.lua @@ -51,5 +51,8 @@ package = { }, targets = { ["ftxui"] = { kind = "lib" } }, deps = { }, + windows = { + cflags = { "-DUNICODE", "-D_UNICODE" }, + }, }, } From 8d48a4a75fbadc2c0f0f12284b410f80b4159e46 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 1 Jun 2026 09:20:23 +0800 Subject: [PATCH 3/9] Use CXX Unicode flags for FTXUI on Windows --- pkgs/c/compat.ftxui.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/c/compat.ftxui.lua b/pkgs/c/compat.ftxui.lua index c4145b1..9a816bf 100644 --- a/pkgs/c/compat.ftxui.lua +++ b/pkgs/c/compat.ftxui.lua @@ -52,7 +52,7 @@ package = { targets = { ["ftxui"] = { kind = "lib" } }, deps = { }, windows = { - cflags = { "-DUNICODE", "-D_UNICODE" }, + cxxflags = { "-DUNICODE", "-D_UNICODE" }, }, }, } From cd2755b2e5dcfd0b56472883979edc1c880d3f24 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 1 Jun 2026 09:25:33 +0800 Subject: [PATCH 4/9] Link mbedTLS bcrypt on Windows --- pkgs/c/compat.mbedtls.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/c/compat.mbedtls.lua b/pkgs/c/compat.mbedtls.lua index e02d929..2613d61 100644 --- a/pkgs/c/compat.mbedtls.lua +++ b/pkgs/c/compat.mbedtls.lua @@ -47,5 +47,8 @@ package = { c_standard = "c11", targets = { ["mbedtls"] = { kind = "lib" } }, deps = { }, + windows = { + ldflags = { "-lbcrypt" }, + }, }, } From d0a6c12fff43011112ba3d3a0036cb263c435eae Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 1 Jun 2026 09:33:24 +0800 Subject: [PATCH 5/9] Compile GLFW Cocoa sources as Objective-C++ --- pkgs/c/compat.glfw.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/c/compat.glfw.lua b/pkgs/c/compat.glfw.lua index df076d4..cf0f924 100644 --- a/pkgs/c/compat.glfw.lua +++ b/pkgs/c/compat.glfw.lua @@ -79,7 +79,8 @@ package = { }, }, macosx = { - cflags = { "-D_GLFW_COCOA" }, + cflags = { "-D_GLFW_COCOA" }, + cxxflags = { "-D_GLFW_COCOA", "-x", "objective-c++" }, sources = { "src/cocoa_time.c", "src/posix_thread.c", From e87dd69491c33c21dc2e60b3637f11b79f383901 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 1 Jun 2026 09:45:21 +0800 Subject: [PATCH 6/9] Use Objective-C++ copies for GLFW Cocoa sources --- pkgs/c/compat.glfw.lua | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/pkgs/c/compat.glfw.lua b/pkgs/c/compat.glfw.lua index cf0f924..c040623 100644 --- a/pkgs/c/compat.glfw.lua +++ b/pkgs/c/compat.glfw.lua @@ -85,11 +85,11 @@ package = { "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", + "src/cocoa_init_objc.cpp", + "src/cocoa_joystick_objc.cpp", + "src/cocoa_monitor_objc.cpp", + "src/cocoa_window_objc.cpp", + "src/nsgl_context_objc.cpp", }, ldflags = { "-framework", "Cocoa", @@ -116,6 +116,14 @@ package = { import("xim.libxpkg.pkginfo") +local objc_sources = { + "cocoa_init", + "cocoa_joystick", + "cocoa_monitor", + "cocoa_window", + "nsgl_context", +} + local function patch_x11_loader_names(root) local file = path.join(root, "src", "x11_init.c") local data = io.readfile(file) @@ -135,6 +143,17 @@ local function patch_x11_loader_names(root) io.writefile(file, data) end +local function copy_objc_sources_as_cpp(root) + local srcdir = path.join(root, "src") + for _, name in ipairs(objc_sources) do + local from = path.join(srcdir, name .. ".m") + local to = path.join(srcdir, name .. "_objc.cpp") + if os.isfile(from) then + os.cp(from, to) + end + end +end + function install() local srcdir = pkginfo.install_file():replace(".tar.gz", "") if not os.isdir(srcdir) then @@ -143,6 +162,7 @@ function install() os.tryrm(pkginfo.install_dir()) os.mv(srcdir, pkginfo.install_dir()) + copy_objc_sources_as_cpp(pkginfo.install_dir()) patch_x11_loader_names(pkginfo.install_dir()) return true end From 9ecd96f9fbace86866071d37cb933e14ee59cd65 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 1 Jun 2026 10:53:23 +0800 Subject: [PATCH 7/9] Use mcpp 0.0.41 for portable compat smoke --- .github/workflows/validate.yml | 12 ++++++------ pkgs/c/compat.glfw.lua | 33 ++++++--------------------------- 2 files changed, 12 insertions(+), 33 deletions(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 16298a0..5df9f2b 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -51,7 +51,7 @@ jobs: - uses: actions/checkout@v4 - name: Download mcpp env: - MCPP_VERSION: "0.0.40" + MCPP_VERSION: "0.0.41" 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" @@ -78,14 +78,14 @@ jobs: include: - platform: macos os: macos-15 - archive: mcpp-0.0.40-macosx-arm64.tar.gz - root: mcpp-0.0.40-macosx-arm64 + archive: mcpp-0.0.41-macosx-arm64.tar.gz + root: mcpp-0.0.41-macosx-arm64 mcpp: bin/mcpp xlings: registry/bin/xlings - platform: windows os: windows-latest - archive: mcpp-0.0.40-windows-x86_64.zip - root: mcpp-0.0.40-windows-x86_64 + archive: mcpp-0.0.41-windows-x86_64.zip + root: mcpp-0.0.41-windows-x86_64 mcpp: bin/mcpp.exe xlings: registry/bin/xlings.exe steps: @@ -93,7 +93,7 @@ jobs: - name: Download mcpp shell: bash env: - MCPP_VERSION: "0.0.40" + MCPP_VERSION: "0.0.41" MCPP_ARCHIVE: ${{ matrix.archive }} MCPP_ROOT: ${{ matrix.root }} run: | diff --git a/pkgs/c/compat.glfw.lua b/pkgs/c/compat.glfw.lua index c040623..df076d4 100644 --- a/pkgs/c/compat.glfw.lua +++ b/pkgs/c/compat.glfw.lua @@ -79,17 +79,16 @@ package = { }, }, macosx = { - cflags = { "-D_GLFW_COCOA" }, - cxxflags = { "-D_GLFW_COCOA", "-x", "objective-c++" }, + cflags = { "-D_GLFW_COCOA" }, sources = { "src/cocoa_time.c", "src/posix_thread.c", "src/posix_module.c", - "src/cocoa_init_objc.cpp", - "src/cocoa_joystick_objc.cpp", - "src/cocoa_monitor_objc.cpp", - "src/cocoa_window_objc.cpp", - "src/nsgl_context_objc.cpp", + "src/cocoa_init.m", + "src/cocoa_joystick.m", + "src/cocoa_monitor.m", + "src/cocoa_window.m", + "src/nsgl_context.m", }, ldflags = { "-framework", "Cocoa", @@ -116,14 +115,6 @@ package = { import("xim.libxpkg.pkginfo") -local objc_sources = { - "cocoa_init", - "cocoa_joystick", - "cocoa_monitor", - "cocoa_window", - "nsgl_context", -} - local function patch_x11_loader_names(root) local file = path.join(root, "src", "x11_init.c") local data = io.readfile(file) @@ -143,17 +134,6 @@ local function patch_x11_loader_names(root) io.writefile(file, data) end -local function copy_objc_sources_as_cpp(root) - local srcdir = path.join(root, "src") - for _, name in ipairs(objc_sources) do - local from = path.join(srcdir, name .. ".m") - local to = path.join(srcdir, name .. "_objc.cpp") - if os.isfile(from) then - os.cp(from, to) - end - end -end - function install() local srcdir = pkginfo.install_file():replace(".tar.gz", "") if not os.isdir(srcdir) then @@ -162,7 +142,6 @@ function install() os.tryrm(pkginfo.install_dir()) os.mv(srcdir, pkginfo.install_dir()) - copy_objc_sources_as_cpp(pkginfo.install_dir()) patch_x11_loader_names(pkginfo.install_dir()) return true end From ab3b617811f0dd5b209b8f31b55c3d4981d425e4 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 1 Jun 2026 11:04:45 +0800 Subject: [PATCH 8/9] Avoid GLFW GL headers in imgui smoke --- tests/smoke_compat_portable.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/smoke_compat_portable.sh b/tests/smoke_compat_portable.sh index 7dd8992..61f5288 100755 --- a/tests/smoke_compat_portable.sh +++ b/tests/smoke_compat_portable.sh @@ -243,6 +243,7 @@ imgui = "1.92.8" glfw = "3.4" EOF cat > src/main.cpp <<'EOF' +#define GLFW_INCLUDE_NONE #include #include #include From eb9c73916a511eeb1b556e2bc1331ce667b712ba Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 1 Jun 2026 11:12:11 +0800 Subject: [PATCH 9/9] Avoid GLFW GL headers in window smoke --- tests/smoke_compat_imgui_window.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/smoke_compat_imgui_window.sh b/tests/smoke_compat_imgui_window.sh index f0c7e5a..739d972 100755 --- a/tests/smoke_compat_imgui_window.sh +++ b/tests/smoke_compat_imgui_window.sh @@ -85,6 +85,7 @@ fi cat > src/main.cpp <<'EOF' #include +#define GLFW_INCLUDE_NONE #include #include #include