From 71d17aced99320c68e8b69c26c45d08936e819ae Mon Sep 17 00:00:00 2001 From: XxingGoD <3223114647@qq.com> Date: Fri, 2 Oct 2026 03:37:17 +0800 Subject: [PATCH 1/9] feat(pkg): add libevent 2.1.13 compat package --- .agents/docs/2026-10-02-add-libevent-plan.md | 8 ++ .github/workflows/libevent-matrix-review.yml | 55 +++++++++ CHANGELOG.md | 4 + README.md | 1 + README.zh-CN.md | 1 + mcpp.toml | 1 + pkgs/c/compat.libevent.lua | 120 +++++++++++++++++++ tests/examples/libevent/mcpp.toml | 6 + tests/examples/libevent/tests/event.cpp | 38 ++++++ 9 files changed, 234 insertions(+) create mode 100644 .agents/docs/2026-10-02-add-libevent-plan.md create mode 100644 .github/workflows/libevent-matrix-review.yml create mode 100644 pkgs/c/compat.libevent.lua create mode 100644 tests/examples/libevent/mcpp.toml create mode 100644 tests/examples/libevent/tests/event.cpp diff --git a/.agents/docs/2026-10-02-add-libevent-plan.md b/.agents/docs/2026-10-02-add-libevent-plan.md new file mode 100644 index 00000000..ee546a0e --- /dev/null +++ b/.agents/docs/2026-10-02-add-libevent-plan.md @@ -0,0 +1,8 @@ +# Libevent 2.1.13 compat package + +- Source: `libevent/libevent`, latest stable tag observed `release-2.1.13-stable` (2.2 tags were alpha prereleases); GitHub tag archive SHA-256 `1a0885e17dc78afbaeddf13cf849f9238bbc24acdc178464a0d1934d7c5ffbd5`, calculated twice. +- Shape: Form B, C source package. The release needs `event2/event-config.h` and `evconfig-private.h` generated by CMake feature probes. `install()` invokes declared `xim:cmake` only to produce those platform headers; mcpp compiles the upstream C translation units so the library follows the consumer's toolchain. Its source list mirrors CMake's `SRC_CORE` and `SRC_EXTRA`, plus the per-platform backends (Linux epoll, macOS kqueue, Windows IOCP/select), and POSIX/Win32 threading. TLS integrations are not part of the default library and are deliberately excluded, not exposed as unverified features. +- Platforms: linux, macosx, windows all declared against the same archive and sha256. The test member executes the same event timer, evbuffer round trip, and HTTP object construction on each. Windows system libraries are explicitly linked. +- License: BSD-3-Clause for the main sources, ISC for arc4random included by `evutil_rand.c`, and MIT for the Windows timer code derived from libutp (`evutil_time.c`; see upstream LICENSE). The separate wepoll and TLS integrations are not compiled. +- Mirror: no GitCode credentials/assets available; use a plain upstream URL (not a fictional CN URL). +- Verification: pending matrix on macOS/Windows. On local Linux GCC 16.1.0 using mcpp 2026.10.1.2, `mcpp xpkg parse --all-os pkgs/c/compat.libevent.lua` reports 24/24/25 sources; cold `mcpp test -p libevent --cache off` passed after switching the test to a single-event loop (`EVLOOP_ONCE`); the first test incorrectly assumed `event_base_dispatch()` returns zero after a one-shot timer (it returns one when the queue empties, even though the callback fired). diff --git a/.github/workflows/libevent-matrix-review.yml b/.github/workflows/libevent-matrix-review.yml new file mode 100644 index 00000000..831232e4 --- /dev/null +++ b/.github/workflows/libevent-matrix-review.yml @@ -0,0 +1,55 @@ +name: libevent pre-PR matrix + +on: + push: + branches: [feat/add-libevent] + +jobs: + smoke: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + suffix: linux-x86_64 + ext: tar.gz + - os: macos-15 + suffix: macosx-arm64 + ext: tar.gz + - os: windows-2022 + suffix: windows-x86_64 + ext: zip + runs-on: ${{ matrix.os }} + timeout-minutes: 30 + steps: + - uses: actions/checkout@v4 + - name: Install mcpp 2026.10.1.2 + shell: bash + run: | + version=2026.10.1.2 + archive="mcpp-${version}-${{ matrix.suffix }}.${{ matrix.ext }}" + curl -L -fsS -o "$archive" "https://github.com/mcpp-community/mcpp/releases/download/v${version}/${archive}" + case "$archive" in + *.zip) powershell -NoProfile -Command "Expand-Archive -Force -Path '${archive}' -DestinationPath '.'" ;; + *) tar -xzf "$archive" ;; + esac + root="$PWD/mcpp-${version}-${{ matrix.suffix }}" + mkdir -p "$HOME/.mcpp/registry" + cp -a "$root/registry/." "$HOME/.mcpp/registry/" + echo "MCPP_HOME=$HOME/.mcpp" >> "$GITHUB_ENV" + if [[ "$RUNNER_OS" == "Windows" ]]; then + echo "MCPP=$(cygpath -m "$root/bin/mcpp.exe")" >> "$GITHUB_ENV" + echo "MCPP_VENDORED_XLINGS=$(cygpath -m "$root/registry/bin/xlings.exe")" >> "$GITHUB_ENV" + else + echo "MCPP=$root/bin/mcpp" >> "$GITHUB_ENV" + echo "MCPP_VENDORED_XLINGS=$root/registry/bin/xlings" >> "$GITHUB_ENV" + fi + - name: Exercise libevent + shell: bash + env: + MCPP_INDEX_MIRROR: GLOBAL + run: | + "$MCPP" --version + "$MCPP" xpkg parse --all-os pkgs/c/compat.libevent.lua + "$MCPP" index update + "$MCPP" test -p libevent --cache off diff --git a/CHANGELOG.md b/CHANGELOG.md index e3120416..0c11e4c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ ### Added +- **`compat.libevent` 2.1.13。** Linux、macOS、Windows 分别通过上游 CMake 生成 + 平台配置头,再由 mcpp 编译 libevent 核心、HTTP/DNS 扩展和对应系统后端; + TLS 可选组件未收录。workspace 成员测试事件分派、缓冲区和 HTTP 对象。 + - **`compat.muduo` 2.0.3 与 Boost 头组件。** muduo 仅支持 Linux;内联构建 `muduo_base`/`muduo_net` 源码,按上游 2.0.3 的依赖补充 `compat.boost-any`、 `compat.boost-circular-buffer`、`compat.boost-concept-check` 并复用既有 `compat.boost-utility`。 diff --git a/README.md b/README.md index 13053cc8..88a69f11 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ One descriptor per common shape: | Header-only | [`compat.gtl`](pkgs/c/compat.gtl.lua) | | Linux-only C++ network library | [`compat.muduo`](pkgs/c/compat.muduo.lua) | | Generated config header | [`compat.c-ares`](pkgs/c/compat.c-ares.lua) | +| Cross-platform C event-loop library | [`compat.libevent`](pkgs/c/compat.libevent.lua) | | C++23 module wrapper | [`nlohmann.json`](pkgs/n/nlohmann.json.lua) | | C++23 module shipped by upstream | [`khronos.vulkan-hpp`](pkgs/k/khronos.vulkan-hpp.lua) | | External build system (`install()`) | [`compat.openssl`](pkgs/c/compat.openssl.lua) | diff --git a/README.zh-CN.md b/README.zh-CN.md index 3ac1bbb9..e49023e5 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -41,6 +41,7 @@ mcpp self config --mirror CN # 切换至国内镜像,默认使用 GLOBAL 上 | 仅 Linux 的 C++ 网络库 | [`compat.muduo`](pkgs/c/compat.muduo.lua) | | header-only | [`compat.gtl`](pkgs/c/compat.gtl.lua) | | 生成 config 头 | [`compat.c-ares`](pkgs/c/compat.c-ares.lua) | +| 跨平台 C 事件循环库 | [`compat.libevent`](pkgs/c/compat.libevent.lua) | | C++23 module wrapper | [`nlohmann.json`](pkgs/n/nlohmann.json.lua) | | 上游自带 C++23 module | [`khronos.vulkan-hpp`](pkgs/k/khronos.vulkan-hpp.lua) | | 外部构建系统(`install()`) | [`compat.openssl`](pkgs/c/compat.openssl.lua) | diff --git a/mcpp.toml b/mcpp.toml index 8046edb1..ad27a9d9 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -107,6 +107,7 @@ members = [ "tests/examples/libassert", "tests/examples/libcoro", "tests/examples/libdrm", + "tests/examples/libevent", "tests/examples/libffi", "tests/examples/expat", "tests/examples/spirv-headers", diff --git a/pkgs/c/compat.libevent.lua b/pkgs/c/compat.libevent.lua new file mode 100644 index 00000000..83200900 --- /dev/null +++ b/pkgs/c/compat.libevent.lua @@ -0,0 +1,120 @@ +-- libevent 2.1.13-stable: configure headers with upstream CMake, then compile +-- core and extra sources with mcpp's C toolchain on Linux, macOS and Windows. +package = { + spec = "1", + namespace = "compat", + name = "libevent", + description = "Libevent asynchronous event notification and networking library", + licenses = {"BSD-3-Clause", "ISC", "MIT"}, + repo = "https://github.com/libevent/libevent", + type = "package", + + xpm = { + linux = { + deps = { "xim:cmake@latest" }, + ["2.1.13"] = { + url = "https://github.com/libevent/libevent/archive/refs/tags/release-2.1.13-stable.tar.gz", + sha256 = "1a0885e17dc78afbaeddf13cf849f9238bbc24acdc178464a0d1934d7c5ffbd5", + }, + }, + macosx = { + deps = { "xim:cmake@latest" }, + ["2.1.13"] = { + url = "https://github.com/libevent/libevent/archive/refs/tags/release-2.1.13-stable.tar.gz", + sha256 = "1a0885e17dc78afbaeddf13cf849f9238bbc24acdc178464a0d1934d7c5ffbd5", + }, + }, + windows = { + deps = { "xim:cmake@latest" }, + ["2.1.13"] = { + url = "https://github.com/libevent/libevent/archive/refs/tags/release-2.1.13-stable.tar.gz", + sha256 = "1a0885e17dc78afbaeddf13cf849f9238bbc24acdc178464a0d1934d7c5ffbd5", + }, + }, + }, + + mcpp = { + language = "c++23", + import_std = false, + c_standard = "c11", + include_dirs = { "*/include", "config/include", "*/compat", "*/WIN32-Code" }, + cflags = { "-DHAVE_CONFIG_H" }, + sources = { + "*/buffer.c", "*/bufferevent.c", "*/bufferevent_filter.c", + "*/bufferevent_pair.c", "*/bufferevent_ratelim.c", + "*/bufferevent_sock.c", "*/event.c", "*/evmap.c", + "*/evthread.c", "*/evutil.c", "*/evutil_rand.c", + "*/evutil_time.c", "*/listener.c", "*/log.c", + "*/signal.c", "*/strlcpy.c", "*/event_tagging.c", + "*/http.c", "*/evdns.c", "*/evrpc.c", + }, + targets = { ["event"] = { kind = "lib" } }, + deps = {}, + linux = { + sources = { "*/select.c", "*/poll.c", "*/epoll.c", "*/evthread_pthread.c" }, + }, + macosx = { + sources = { "*/select.c", "*/poll.c", "*/kqueue.c", "*/evthread_pthread.c" }, + }, + windows = { + sources = { "*/buffer_iocp.c", "*/bufferevent_async.c", "*/event_iocp.c", + "*/win32select.c", "*/evthread_win32.c" }, + cflags = { "-D_CRT_SECURE_NO_WARNINGS", "-D_CRT_NONSTDC_NO_DEPRECATE" }, + ldflags = { "-lws2_32", "-lshell32", "-ladvapi32", "-liphlpapi" }, + }, + }, +} + +import("xim.libxpkg.pkginfo") +import("xim.libxpkg.log") + +local function quote(s) + return '"' .. tostring(s):gsub('"', '\\"') .. '"' +end + +function install() + local wrap = "libevent-release-" .. pkginfo.version() .. "-stable" + if not os.isfile(path.join(wrap, "CMakeLists.txt")) then + log.error("compat.libevent: expected %s/CMakeLists.txt", wrap) + return false + end + local prefix = pkginfo.install_dir() + os.tryrm(prefix) + os.mkdir(prefix) + local srcroot = path.join(prefix, wrap) + os.mv(wrap, srcroot) + + local pkg = pkginfo.build_dep("xim:cmake") + local cmake + if pkg then + for _, candidate in ipairs({ + pkg.bin and path.join(pkg.bin, "cmake") or "", + pkg.bin and path.join(pkg.bin, "cmake.exe") or "", + pkg.path and path.join(pkg.path, "cmake.app/Contents/bin/cmake") or "", + pkg.path and path.join(pkg.path, "CMake.app/Contents/bin/cmake") or "", + }) do + if os.isfile(candidate) then cmake = candidate; break end + end + end + if not cmake then + log.error("compat.libevent: xim:cmake executable not found") + return false + end + local command = quote(cmake) .. " -S " .. quote(srcroot) + .. " -B " .. quote(path.join(prefix, "config")) + .. " -DCMAKE_POLICY_VERSION_MINIMUM=3.5" + .. " -DEVENT__DISABLE_OPENSSL=ON -DEVENT__DISABLE_MBEDTLS=ON" + .. " -DEVENT__DISABLE_TESTS=ON -DEVENT__DISABLE_SAMPLES=ON" + .. " -DEVENT__DISABLE_BENCHMARK=ON -DEVENT__LIBRARY_TYPE=STATIC" + local ok, result = pcall(os.exec, command) + if not ok or not result then + log.error("compat.libevent: upstream CMake configuration failed: %s", tostring(result)) + return false + end + local generated = path.join(prefix, "config/include/event2/event-config.h") + if not os.isfile(generated) then + log.error("compat.libevent: CMake did not generate %s", generated) + return false + end + return true +end diff --git a/tests/examples/libevent/mcpp.toml b/tests/examples/libevent/mcpp.toml new file mode 100644 index 00000000..a5ef217e --- /dev/null +++ b/tests/examples/libevent/mcpp.toml @@ -0,0 +1,6 @@ +[package] +name = "libevent-tests" +version = "0.1.0" + +[dependencies.compat] +libevent = "2.1.13" diff --git a/tests/examples/libevent/tests/event.cpp b/tests/examples/libevent/tests/event.cpp new file mode 100644 index 00000000..0809dc07 --- /dev/null +++ b/tests/examples/libevent/tests/event.cpp @@ -0,0 +1,38 @@ +#include +#include +#include + +#include +#include + +static void fired(evutil_socket_t, short, void* arg) { + ++*static_cast(arg); +} + +int main() { + event_base* base = event_base_new(); + if (!base) return 1; + int count = 0; + timeval delay = {0, 0}; + const int scheduled = event_base_once(base, -1, EV_TIMEOUT, fired, &count, &delay); + const int dispatched = scheduled == 0 ? event_base_loop(base, EVLOOP_ONCE) : -1; + bool ok = scheduled == 0 && dispatched == 0 && count == 1; + if (!ok) std::fprintf(stderr, "event loop: schedule=%d dispatch=%d count=%d\n", scheduled, dispatched, count); + + evbuffer* buffer = evbuffer_new(); + if (!buffer) { event_base_free(base); return 1; } + const char text[] = "libevent"; + char out[sizeof(text)] = {}; + ok = ok && evbuffer_add(buffer, text, sizeof(text) - 1) == 0 + && evbuffer_remove(buffer, out, sizeof(text) - 1) == sizeof(text) - 1 + && std::strcmp(out, text) == 0 && evbuffer_get_length(buffer) == 0; + if (!ok) std::fprintf(stderr, "buffer round trip failed\n"); + + evhttp* http = evhttp_new(base); + ok = ok && http != nullptr; + if (!http) std::fprintf(stderr, "evhttp_new failed\n"); + if (http) evhttp_free(http); + evbuffer_free(buffer); + event_base_free(base); + return ok ? 0 : 1; +} From 5425b94bfaa9f9cc0fb816f906446986e3df6af8 Mon Sep 17 00:00:00 2001 From: XxingGoD <3223114647@qq.com> Date: Fri, 2 Oct 2026 03:39:45 +0800 Subject: [PATCH 2/9] docs(pkg): record libevent LLVM verification --- .agents/docs/2026-10-02-add-libevent-plan.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.agents/docs/2026-10-02-add-libevent-plan.md b/.agents/docs/2026-10-02-add-libevent-plan.md index ee546a0e..e7e108d0 100644 --- a/.agents/docs/2026-10-02-add-libevent-plan.md +++ b/.agents/docs/2026-10-02-add-libevent-plan.md @@ -6,3 +6,4 @@ - License: BSD-3-Clause for the main sources, ISC for arc4random included by `evutil_rand.c`, and MIT for the Windows timer code derived from libutp (`evutil_time.c`; see upstream LICENSE). The separate wepoll and TLS integrations are not compiled. - Mirror: no GitCode credentials/assets available; use a plain upstream URL (not a fictional CN URL). - Verification: pending matrix on macOS/Windows. On local Linux GCC 16.1.0 using mcpp 2026.10.1.2, `mcpp xpkg parse --all-os pkgs/c/compat.libevent.lua` reports 24/24/25 sources; cold `mcpp test -p libevent --cache off` passed after switching the test to a single-event loop (`EVLOOP_ONCE`); the first test incorrectly assumed `event_base_dispatch()` returns zero after a one-shot timer (it returns one when the queue empties, even though the callback fired). +- The same member also passed with mcpp 2026.10.1.2 and `--toolchain llvm@22.1.8 --cache off` on Linux (`event ... ok`, one test passed). The macOS and Windows matrices are still unverified; no PR has been opened. From 52fb4a23125b1c42bf0139da34430663dab86dcf Mon Sep 17 00:00:00 2001 From: XxingGoD <3223114647@qq.com> Date: Fri, 2 Oct 2026 03:43:19 +0800 Subject: [PATCH 3/9] fix(pkg): run libevent configure through cmd on Windows --- pkgs/c/compat.libevent.lua | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pkgs/c/compat.libevent.lua b/pkgs/c/compat.libevent.lua index 83200900..877f5755 100644 --- a/pkgs/c/compat.libevent.lua +++ b/pkgs/c/compat.libevent.lua @@ -106,9 +106,19 @@ function install() .. " -DEVENT__DISABLE_OPENSSL=ON -DEVENT__DISABLE_MBEDTLS=ON" .. " -DEVENT__DISABLE_TESTS=ON -DEVENT__DISABLE_SAMPLES=ON" .. " -DEVENT__DISABLE_BENCHMARK=ON -DEVENT__LIBRARY_TYPE=STATIC" + local logfile = path.join(prefix, "mcpp_cmake_configure.log") + if os.host() == "windows" then + -- Windows xlings does not reliably execute a quoted .exe directly. + -- Drive it through cmd as compat.openssl does, and inspect its output. + local bat = path.join(prefix, "mcpp_configure.bat") + io.writefile(bat, "@echo off\r\n" .. command .. " > " .. quote(logfile) + .. " 2>&1\r\nif errorlevel 1 exit /b 1\r\n") + command = "cmd /c " .. quote(bat) + end local ok, result = pcall(os.exec, command) if not ok or not result then - log.error("compat.libevent: upstream CMake configuration failed: %s", tostring(result)) + log.error("compat.libevent: CMake configuration failed: %s; log: %s", + tostring(result), os.isfile(logfile) and io.readfile(logfile) or "") return false end local generated = path.join(prefix, "config/include/event2/event-config.h") From d7d6bd8c0abd44716cef0efd7a685e7c78c2028c Mon Sep 17 00:00:00 2001 From: XxingGoD <3223114647@qq.com> Date: Fri, 2 Oct 2026 03:47:35 +0800 Subject: [PATCH 4/9] test(pkg): initialize Winsock in libevent matrix smoke --- .agents/docs/2026-10-02-add-libevent-plan.md | 4 +-- tests/examples/libevent/tests/event.cpp | 35 ++++++++++++++++---- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/.agents/docs/2026-10-02-add-libevent-plan.md b/.agents/docs/2026-10-02-add-libevent-plan.md index e7e108d0..47b23ec3 100644 --- a/.agents/docs/2026-10-02-add-libevent-plan.md +++ b/.agents/docs/2026-10-02-add-libevent-plan.md @@ -5,5 +5,5 @@ - Platforms: linux, macosx, windows all declared against the same archive and sha256. The test member executes the same event timer, evbuffer round trip, and HTTP object construction on each. Windows system libraries are explicitly linked. - License: BSD-3-Clause for the main sources, ISC for arc4random included by `evutil_rand.c`, and MIT for the Windows timer code derived from libutp (`evutil_time.c`; see upstream LICENSE). The separate wepoll and TLS integrations are not compiled. - Mirror: no GitCode credentials/assets available; use a plain upstream URL (not a fictional CN URL). -- Verification: pending matrix on macOS/Windows. On local Linux GCC 16.1.0 using mcpp 2026.10.1.2, `mcpp xpkg parse --all-os pkgs/c/compat.libevent.lua` reports 24/24/25 sources; cold `mcpp test -p libevent --cache off` passed after switching the test to a single-event loop (`EVLOOP_ONCE`); the first test incorrectly assumed `event_base_dispatch()` returns zero after a one-shot timer (it returns one when the queue empties, even though the callback fired). -- The same member also passed with mcpp 2026.10.1.2 and `--toolchain llvm@22.1.8 --cache off` on Linux (`event ... ok`, one test passed). The macOS and Windows matrices are still unverified; no PR has been opened. +- Local Linux verification: mcpp 2026.10.1.2 `mcpp xpkg parse --all-os pkgs/c/compat.libevent.lua` reports 24/24/25 sources; cold `mcpp test -p libevent --cache off` passed under GCC 16.1.0. The test deliberately uses `EVLOOP_ONCE` because `event_base_dispatch()` returns one after a one-shot timer drains the queue even when its callback ran. +- With mcpp 2026.10.1.2 and `--toolchain llvm@22.1.8 --cache off`, the Linux LLVM member passed (`event ... ok`, one test passed). The fork-only [first matrix run](https://github.com/XxingGoD/mcpp-index/actions/runs/36915945625) passed on Linux and macOS but Windows failed before compilation because xlings could not execute the quoted CMake command directly. The hook now runs CMake through `cmd /c` on Windows. The [second matrix run](https://github.com/XxingGoD/mcpp-index/actions/runs/36916373090) passed on Linux, macOS and Windows, including `event ... ok` on Windows. Its log emitted an `evsig_init_ socketpair` warning because the test had not initialized Winsock; the test now calls `WSAStartup`/`WSACleanup` explicitly and needs a final CI run. No PR has been opened. diff --git a/tests/examples/libevent/tests/event.cpp b/tests/examples/libevent/tests/event.cpp index 0809dc07..aa399a4e 100644 --- a/tests/examples/libevent/tests/event.cpp +++ b/tests/examples/libevent/tests/event.cpp @@ -1,3 +1,7 @@ +#ifdef _WIN32 +#include +#endif + #include #include #include @@ -10,8 +14,17 @@ static void fired(evutil_socket_t, short, void* arg) { } int main() { +#ifdef _WIN32 + WSADATA winsock; + if (WSAStartup(MAKEWORD(2, 2), &winsock) != 0) return 1; +#endif event_base* base = event_base_new(); - if (!base) return 1; + if (!base) { +#ifdef _WIN32 + WSACleanup(); +#endif + return 1; + } int count = 0; timeval delay = {0, 0}; const int scheduled = event_base_once(base, -1, EV_TIMEOUT, fired, &count, &delay); @@ -20,13 +33,20 @@ int main() { if (!ok) std::fprintf(stderr, "event loop: schedule=%d dispatch=%d count=%d\n", scheduled, dispatched, count); evbuffer* buffer = evbuffer_new(); - if (!buffer) { event_base_free(base); return 1; } + if (!buffer) { + event_base_free(base); +#ifdef _WIN32 + WSACleanup(); +#endif + return 1; + } const char text[] = "libevent"; char out[sizeof(text)] = {}; - ok = ok && evbuffer_add(buffer, text, sizeof(text) - 1) == 0 - && evbuffer_remove(buffer, out, sizeof(text) - 1) == sizeof(text) - 1 - && std::strcmp(out, text) == 0 && evbuffer_get_length(buffer) == 0; - if (!ok) std::fprintf(stderr, "buffer round trip failed\n"); + const bool buffer_ok = evbuffer_add(buffer, text, sizeof(text) - 1) == 0 + && evbuffer_remove(buffer, out, sizeof(text) - 1) == sizeof(text) - 1 + && std::strcmp(out, text) == 0 && evbuffer_get_length(buffer) == 0; + if (!buffer_ok) std::fprintf(stderr, "buffer round trip failed\n"); + ok = ok && buffer_ok; evhttp* http = evhttp_new(base); ok = ok && http != nullptr; @@ -34,5 +54,8 @@ int main() { if (http) evhttp_free(http); evbuffer_free(buffer); event_base_free(base); +#ifdef _WIN32 + WSACleanup(); +#endif return ok ? 0 : 1; } From 419b88c029b8ca3a50ad0d7a87fc5430fec5687b Mon Sep 17 00:00:00 2001 From: XxingGoD <3223114647@qq.com> Date: Fri, 2 Oct 2026 03:51:44 +0800 Subject: [PATCH 5/9] docs(pkg): record libevent platform matrix results --- .agents/docs/2026-10-02-add-libevent-plan.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.agents/docs/2026-10-02-add-libevent-plan.md b/.agents/docs/2026-10-02-add-libevent-plan.md index 47b23ec3..7009612b 100644 --- a/.agents/docs/2026-10-02-add-libevent-plan.md +++ b/.agents/docs/2026-10-02-add-libevent-plan.md @@ -6,4 +6,4 @@ - License: BSD-3-Clause for the main sources, ISC for arc4random included by `evutil_rand.c`, and MIT for the Windows timer code derived from libutp (`evutil_time.c`; see upstream LICENSE). The separate wepoll and TLS integrations are not compiled. - Mirror: no GitCode credentials/assets available; use a plain upstream URL (not a fictional CN URL). - Local Linux verification: mcpp 2026.10.1.2 `mcpp xpkg parse --all-os pkgs/c/compat.libevent.lua` reports 24/24/25 sources; cold `mcpp test -p libevent --cache off` passed under GCC 16.1.0. The test deliberately uses `EVLOOP_ONCE` because `event_base_dispatch()` returns one after a one-shot timer drains the queue even when its callback ran. -- With mcpp 2026.10.1.2 and `--toolchain llvm@22.1.8 --cache off`, the Linux LLVM member passed (`event ... ok`, one test passed). The fork-only [first matrix run](https://github.com/XxingGoD/mcpp-index/actions/runs/36915945625) passed on Linux and macOS but Windows failed before compilation because xlings could not execute the quoted CMake command directly. The hook now runs CMake through `cmd /c` on Windows. The [second matrix run](https://github.com/XxingGoD/mcpp-index/actions/runs/36916373090) passed on Linux, macOS and Windows, including `event ... ok` on Windows. Its log emitted an `evsig_init_ socketpair` warning because the test had not initialized Winsock; the test now calls `WSAStartup`/`WSACleanup` explicitly and needs a final CI run. No PR has been opened. +- Linux, macOS and Windows passed the fork-only [final mcpp 2026.10.1.2 matrix](https://github.com/XxingGoD/mcpp-index/actions/runs/36916893185); each ran `mcpp xpkg parse --all-os` and `mcpp test -p libevent --cache off`. The Windows source hook uses `cmd /c` for CMake; the behavior test initializes and cleans up Winsock, avoiding libevent's uninitialized-Winsock warning. A local Linux LLVM 22.1.8 test also passed. The temporary workflow used to obtain the matrix has been removed; its logs remain available from the linked fork run. No PR has been opened. From 63e31e68d7dc96c026b010eb50cd9eda758b22e3 Mon Sep 17 00:00:00 2001 From: XxingGoD <3223114647@qq.com> Date: Fri, 2 Oct 2026 03:57:04 +0800 Subject: [PATCH 6/9] docs(pkg): keep package examples out of README --- README.md | 3 --- README.zh-CN.md | 3 --- 2 files changed, 6 deletions(-) diff --git a/README.md b/README.md index 88a69f11..0459ca25 100644 --- a/README.md +++ b/README.md @@ -38,11 +38,8 @@ One descriptor per common shape: | Native module library (Form A) | [`mcpplibs.tinyhttps`](pkgs/t/tinyhttps.lua) · [`gzj-creator.galay`](pkgs/g/gzj-creator.galay.lua) | | C sources + `features` | [`compat.cjson`](pkgs/c/compat.cjson.lua) | | C++ sources, several versions | [`compat.yaml-cpp`](pkgs/c/compat.yaml-cpp.lua) | -| Boost header-only components | [`compat.boost-any`](pkgs/c/compat.boost-any.lua) · [`compat.boost-circular-buffer`](pkgs/c/compat.boost-circular-buffer.lua) · [`compat.boost-concept-check`](pkgs/c/compat.boost-concept-check.lua) · [`compat.boost-utility`](pkgs/c/compat.boost-utility.lua) | | Header-only | [`compat.gtl`](pkgs/c/compat.gtl.lua) | -| Linux-only C++ network library | [`compat.muduo`](pkgs/c/compat.muduo.lua) | | Generated config header | [`compat.c-ares`](pkgs/c/compat.c-ares.lua) | -| Cross-platform C event-loop library | [`compat.libevent`](pkgs/c/compat.libevent.lua) | | C++23 module wrapper | [`nlohmann.json`](pkgs/n/nlohmann.json.lua) | | C++23 module shipped by upstream | [`khronos.vulkan-hpp`](pkgs/k/khronos.vulkan-hpp.lua) | | External build system (`install()`) | [`compat.openssl`](pkgs/c/compat.openssl.lua) | diff --git a/README.zh-CN.md b/README.zh-CN.md index e49023e5..a996bda4 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -37,11 +37,8 @@ mcpp self config --mirror CN # 切换至国内镜像,默认使用 GLOBAL 上 | 原生模块库(Form A) | [`mcpplibs.tinyhttps`](pkgs/t/tinyhttps.lua) · [`gzj-creator.galay`](pkgs/g/gzj-creator.galay.lua) | | C 源码 + `features` | [`compat.cjson`](pkgs/c/compat.cjson.lua) | | C++ 源码,多版本 | [`compat.yaml-cpp`](pkgs/c/compat.yaml-cpp.lua) | -| Boost 头文件组件 | [`compat.boost-any`](pkgs/c/compat.boost-any.lua) · [`compat.boost-circular-buffer`](pkgs/c/compat.boost-circular-buffer.lua) · [`compat.boost-concept-check`](pkgs/c/compat.boost-concept-check.lua) · [`compat.boost-utility`](pkgs/c/compat.boost-utility.lua) | -| 仅 Linux 的 C++ 网络库 | [`compat.muduo`](pkgs/c/compat.muduo.lua) | | header-only | [`compat.gtl`](pkgs/c/compat.gtl.lua) | | 生成 config 头 | [`compat.c-ares`](pkgs/c/compat.c-ares.lua) | -| 跨平台 C 事件循环库 | [`compat.libevent`](pkgs/c/compat.libevent.lua) | | C++23 module wrapper | [`nlohmann.json`](pkgs/n/nlohmann.json.lua) | | 上游自带 C++23 module | [`khronos.vulkan-hpp`](pkgs/k/khronos.vulkan-hpp.lua) | | 外部构建系统(`install()`) | [`compat.openssl`](pkgs/c/compat.openssl.lua) | From b6b75d017353a251dc1783b162e48d3e4edb65c3 Mon Sep 17 00:00:00 2001 From: XxingGoD <3223114647@qq.com> Date: Fri, 2 Oct 2026 03:59:09 +0800 Subject: [PATCH 7/9] chore(ci): remove temporary libevent matrix workflow --- .github/workflows/libevent-matrix-review.yml | 55 -------------------- 1 file changed, 55 deletions(-) delete mode 100644 .github/workflows/libevent-matrix-review.yml diff --git a/.github/workflows/libevent-matrix-review.yml b/.github/workflows/libevent-matrix-review.yml deleted file mode 100644 index 831232e4..00000000 --- a/.github/workflows/libevent-matrix-review.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: libevent pre-PR matrix - -on: - push: - branches: [feat/add-libevent] - -jobs: - smoke: - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu-latest - suffix: linux-x86_64 - ext: tar.gz - - os: macos-15 - suffix: macosx-arm64 - ext: tar.gz - - os: windows-2022 - suffix: windows-x86_64 - ext: zip - runs-on: ${{ matrix.os }} - timeout-minutes: 30 - steps: - - uses: actions/checkout@v4 - - name: Install mcpp 2026.10.1.2 - shell: bash - run: | - version=2026.10.1.2 - archive="mcpp-${version}-${{ matrix.suffix }}.${{ matrix.ext }}" - curl -L -fsS -o "$archive" "https://github.com/mcpp-community/mcpp/releases/download/v${version}/${archive}" - case "$archive" in - *.zip) powershell -NoProfile -Command "Expand-Archive -Force -Path '${archive}' -DestinationPath '.'" ;; - *) tar -xzf "$archive" ;; - esac - root="$PWD/mcpp-${version}-${{ matrix.suffix }}" - mkdir -p "$HOME/.mcpp/registry" - cp -a "$root/registry/." "$HOME/.mcpp/registry/" - echo "MCPP_HOME=$HOME/.mcpp" >> "$GITHUB_ENV" - if [[ "$RUNNER_OS" == "Windows" ]]; then - echo "MCPP=$(cygpath -m "$root/bin/mcpp.exe")" >> "$GITHUB_ENV" - echo "MCPP_VENDORED_XLINGS=$(cygpath -m "$root/registry/bin/xlings.exe")" >> "$GITHUB_ENV" - else - echo "MCPP=$root/bin/mcpp" >> "$GITHUB_ENV" - echo "MCPP_VENDORED_XLINGS=$root/registry/bin/xlings" >> "$GITHUB_ENV" - fi - - name: Exercise libevent - shell: bash - env: - MCPP_INDEX_MIRROR: GLOBAL - run: | - "$MCPP" --version - "$MCPP" xpkg parse --all-os pkgs/c/compat.libevent.lua - "$MCPP" index update - "$MCPP" test -p libevent --cache off From 4dabc284289ce15958d8d1f8684cf6159c5a527f Mon Sep 17 00:00:00 2001 From: XxingGoD <3223114647@qq.com> Date: Fri, 2 Oct 2026 04:09:39 +0800 Subject: [PATCH 8/9] fix(pkg): use host compiler for libevent probes --- .agents/docs/2026-10-02-add-libevent-plan.md | 2 +- pkgs/c/compat.libevent.lua | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.agents/docs/2026-10-02-add-libevent-plan.md b/.agents/docs/2026-10-02-add-libevent-plan.md index 7009612b..2f0f66c0 100644 --- a/.agents/docs/2026-10-02-add-libevent-plan.md +++ b/.agents/docs/2026-10-02-add-libevent-plan.md @@ -6,4 +6,4 @@ - License: BSD-3-Clause for the main sources, ISC for arc4random included by `evutil_rand.c`, and MIT for the Windows timer code derived from libutp (`evutil_time.c`; see upstream LICENSE). The separate wepoll and TLS integrations are not compiled. - Mirror: no GitCode credentials/assets available; use a plain upstream URL (not a fictional CN URL). - Local Linux verification: mcpp 2026.10.1.2 `mcpp xpkg parse --all-os pkgs/c/compat.libevent.lua` reports 24/24/25 sources; cold `mcpp test -p libevent --cache off` passed under GCC 16.1.0. The test deliberately uses `EVLOOP_ONCE` because `event_base_dispatch()` returns one after a one-shot timer drains the queue even when its callback ran. -- Linux, macOS and Windows passed the fork-only [final mcpp 2026.10.1.2 matrix](https://github.com/XxingGoD/mcpp-index/actions/runs/36916893185); each ran `mcpp xpkg parse --all-os` and `mcpp test -p libevent --cache off`. The Windows source hook uses `cmd /c` for CMake; the behavior test initializes and cleans up Winsock, avoiding libevent's uninitialized-Winsock warning. A local Linux LLVM 22.1.8 test also passed. The temporary workflow used to obtain the matrix has been removed; its logs remain available from the linked fork run. No PR has been opened. +- The first PR #503 Linux-GCC CI run found CMake's platform probes produced an incomplete `event-config.h` (missing pointer-size and socket/address-family macros) when run through the ambient toolchain wrapper. The install hook now selects native `/usr/bin/cc` for CMake's Linux/macOS host probes; mcpp still compiles the package sources with the selected consumer compiler. A cold Linux GCC build passes with this fix; the PR's next matrix must reconfirm Linux, macOS and Windows. diff --git a/pkgs/c/compat.libevent.lua b/pkgs/c/compat.libevent.lua index 877f5755..5a48ccf3 100644 --- a/pkgs/c/compat.libevent.lua +++ b/pkgs/c/compat.libevent.lua @@ -103,6 +103,9 @@ function install() local command = quote(cmake) .. " -S " .. quote(srcroot) .. " -B " .. quote(path.join(prefix, "config")) .. " -DCMAKE_POLICY_VERSION_MINIMUM=3.5" + -- Probe the native platform with its system compiler, not a toolchain + -- wrapper whose sysroot may differ from the generated headers' ABI. + .. (os.host() == "windows" and "" or " -DCMAKE_C_COMPILER=/usr/bin/cc") .. " -DEVENT__DISABLE_OPENSSL=ON -DEVENT__DISABLE_MBEDTLS=ON" .. " -DEVENT__DISABLE_TESTS=ON -DEVENT__DISABLE_SAMPLES=ON" .. " -DEVENT__DISABLE_BENCHMARK=ON -DEVENT__LIBRARY_TYPE=STATIC" From 9e95dd6ee9202db536db5f6a1f863e8d1cba60d4 Mon Sep 17 00:00:00 2001 From: XxingGoD <3223114647@qq.com> Date: Fri, 2 Oct 2026 04:25:18 +0800 Subject: [PATCH 9/9] docs(pkg): record libevent GCC probe fix --- .agents/docs/2026-10-02-add-libevent-plan.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.agents/docs/2026-10-02-add-libevent-plan.md b/.agents/docs/2026-10-02-add-libevent-plan.md index 2f0f66c0..b6ba6eec 100644 --- a/.agents/docs/2026-10-02-add-libevent-plan.md +++ b/.agents/docs/2026-10-02-add-libevent-plan.md @@ -6,4 +6,5 @@ - License: BSD-3-Clause for the main sources, ISC for arc4random included by `evutil_rand.c`, and MIT for the Windows timer code derived from libutp (`evutil_time.c`; see upstream LICENSE). The separate wepoll and TLS integrations are not compiled. - Mirror: no GitCode credentials/assets available; use a plain upstream URL (not a fictional CN URL). - Local Linux verification: mcpp 2026.10.1.2 `mcpp xpkg parse --all-os pkgs/c/compat.libevent.lua` reports 24/24/25 sources; cold `mcpp test -p libevent --cache off` passed under GCC 16.1.0. The test deliberately uses `EVLOOP_ONCE` because `event_base_dispatch()` returns one after a one-shot timer drains the queue even when its callback ran. -- The first PR #503 Linux-GCC CI run found CMake's platform probes produced an incomplete `event-config.h` (missing pointer-size and socket/address-family macros) when run through the ambient toolchain wrapper. The install hook now selects native `/usr/bin/cc` for CMake's Linux/macOS host probes; mcpp still compiles the package sources with the selected consumer compiler. A cold Linux GCC build passes with this fix; the PR's next matrix must reconfirm Linux, macOS and Windows. +- PR #503 initially failed only on Linux default GCC: CMake's host probes produced an incomplete `event-config.h` (missing pointer-size and socket/address-family macros) when using the ambient toolchain wrapper. The hook now selects native `/usr/bin/cc` for CMake's Linux/macOS host probes; mcpp still compiles the sources with the selected consumer compiler. The fix passed a cold local Linux GCC build and the full PR matrix on Linux GCC/LLVM, macOS and Windows. +- The final PR validation run passed lint, mirror checks, build, Linux default, all Linux LLVM shards, macOS, and Windows. Results: [PR #503 checks](https://github.com/mcpplibs/mcpp-index/pull/503/checks).