From 13a848da52b55fd060b20e7d31eb21f97ba07cc4 Mon Sep 17 00:00:00 2001 From: wellwei Date: Thu, 6 Aug 2026 21:55:37 +0800 Subject: [PATCH 1/3] fix(asio): keep std::println usable with import asio --- pkgs/c/chriskohlhoff.asio.lua | 8 ++++++-- tests/examples/asio-module/mcpp.toml | 3 +++ tests/examples/asio-module/tests/surface.cpp | 5 +++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/pkgs/c/chriskohlhoff.asio.lua b/pkgs/c/chriskohlhoff.asio.lua index ebbf47a1..da8d0e29 100644 --- a/pkgs/c/chriskohlhoff.asio.lua +++ b/pkgs/c/chriskohlhoff.asio.lua @@ -8,8 +8,8 @@ -- `#include ` 和 `import asio;`,避免 inline 定义与模块 BMI -- 的 separate-compilation 定义产生 ODR 差异。 -- * 默认 feature 显式传播 ASIO_STANDALONE、ASIO_SEPARATE_COMPILATION、 --- ASIO_DISABLE_BOOST_CONTEXT_FIBER 和 ASIO_HAS_THREADS。Asio 头文件内部 --- 自动检测的其他 ASIO_HAS_* 宏不会由 `import asio;` 导出。 +-- ASIO_DISABLE_BOOST_CONTEXT_FIBER、ASIO_HAS_THREADS 和 ASIO_NO_IOSTREAM。 +-- Asio 头文件内部自动检测的其他 ASIO_HAS_* 宏不会由 `import asio;` 导出。 -- -- 与 header-only Asio 的区别/限制 -- * 上游 1.38.x 没有模块接口单元。本描述生成 `asio.cppm`,并只编译一次 @@ -35,6 +35,9 @@ -- streambuf:对应 `asio/deadline_timer.hpp`、`asio/generic/*.hpp`、 -- `asio/execution/*.hpp`、`asio/traits/*.hpp`、`asio/yield.hpp`、 -- `asio/coroutine.hpp`、`asio/streambuf.hpp`。 +-- * iostream/streambuf 适配:模块禁用 ASIO 的 iostream 表面,避免 libc++ +-- `` 同时进入 `std` 与 `asio` 两个 BMI 后破坏 `std::println`; +-- 因此基于 streambuf 的 read_at/write_at 重载也不可用。 package = { spec = "1", namespace = "chriskohlhoff", @@ -289,6 +292,7 @@ using ::asio::ssl::error::make_error_code; "ASIO_SEPARATE_COMPILATION", "ASIO_DISABLE_BOOST_CONTEXT_FIBER", "ASIO_HAS_THREADS", + "ASIO_NO_IOSTREAM", }, }, ["ssl"] = { diff --git a/tests/examples/asio-module/mcpp.toml b/tests/examples/asio-module/mcpp.toml index d1b20abf..2ce29ce5 100644 --- a/tests/examples/asio-module/mcpp.toml +++ b/tests/examples/asio-module/mcpp.toml @@ -13,3 +13,6 @@ version = "0.1.0" [dependencies.chriskohlhoff] asio = "1.38.1" + +[dependencies.fmtlib] +fmt = "12.2.0" diff --git a/tests/examples/asio-module/tests/surface.cpp b/tests/examples/asio-module/tests/surface.cpp index da5ae643..029d8dc4 100644 --- a/tests/examples/asio-module/tests/surface.cpp +++ b/tests/examples/asio-module/tests/surface.cpp @@ -1,9 +1,14 @@ // Surface/smoke coverage: exported types, completion tokens, and vocabulary // types are usable across the module boundary. import std; +import fmt; import asio; int main() { + // 回归:导入 Asio 后,libc++ 的 println 仍应保持可用。 + std::println("asio module println"); + std::println("asio module println {}", 42); + // --- buffer / address (existing) --- std::array src{'m', 'c', 'p', 'p'}; asio::const_buffer cb = asio::buffer(src); From 9f4c664c2f37938e982595fa938e99c101e39f9a Mon Sep 17 00:00:00 2001 From: wellwei Date: Fri, 7 Aug 2026 20:36:13 +0800 Subject: [PATCH 2/3] fix(openssl): pass Linux payload headers to external build --- pkgs/c/compat.openssl.lua | 45 +++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/pkgs/c/compat.openssl.lua b/pkgs/c/compat.openssl.lua index 46a4fd3d..eba05f59 100644 --- a/pkgs/c/compat.openssl.lua +++ b/pkgs/c/compat.openssl.lua @@ -9,9 +9,9 @@ -- so there resolve_make() falls back to PATH. -- -- Because that build runs OUTSIDE mcpp's compile rules, it inherits none of --- the resolved toolchain's flags — it just calls `cc`. Anything the host --- toolchain needs spelled out (macOS SDK, ranlib) has to be handed to it --- explicitly; see cc_override() and the install_sw step. +-- the resolved toolchain's flags — it just calls `cc`. Anything the toolchain +-- needs spelled out (Linux payload headers, macOS SDK, ranlib) has to be +-- handed to it explicitly; see cc_override() and the install_sw step. -- -- PERL. `./config` execs `Configure`, which is `#!/usr/bin/env perl` and opens -- with `use Config; use FindBin;`. So what this build needs is not "a perl @@ -59,7 +59,12 @@ package = { xpm = { linux = { - deps = { "xim:make@latest", "xim:perl@latest" }, + deps = { + "xim:make@latest", + "xim:perl@latest", + "xim:glibc@2.39", + "xim:linux-headers@5.11.1", + }, ["3.5.1"] = { url = { GLOBAL = "https://github.com/openssl/openssl/releases/download/openssl-3.5.1/openssl-3.5.1.tar.gz", @@ -161,12 +166,39 @@ end -- inherit the resolved toolchain's sysroot flags — it just runs `cc`. On macOS -- the toolchain in PATH is xim's llvm, which has no macOS SDK wired up, so -- every compile would fail on . Pin Apple's own driver, which finds --- the SDK by itself. Left alone elsewhere: on linux the xim gcc carries its --- own payload and is the right compiler to use. +-- the SDK by itself. On Linux, use the same payload-first header order as +-- mcpp's GCC link model instead of relying on the active subos sysroot. local function cc_override() if os.host() == "macosx" and os.isfile("/usr/bin/cc") then return "CC=/usr/bin/cc " end + if os.host() == "linux" then + local glibc_dir = pkginfo.dep_install_dir("glibc") + local linux_headers_dir = pkginfo.dep_install_dir("linux-headers") + local glibc_include = glibc_dir and path.join(glibc_dir, "include") + local linux_include = linux_headers_dir + and path.join(linux_headers_dir, "include") + + -- install() 不继承 mcpp 的工具链参数,必须把两个 payload 的系统头 + -- 文件目录显式传给 OpenSSL 的 Configure/Make。GCC 使用 -idirafter, + -- 以保留其 include_next 对内置包装头的语义。 + if not glibc_include or not os.isdir(glibc_include) then + log.error("compat.openssl: glibc headers are unavailable at %s", + tostring(glibc_include)) + return nil + end + if not linux_include or not os.isdir(linux_include) then + log.error("compat.openssl: Linux headers are unavailable at %s", + tostring(linux_include)) + return nil + end + + local header_flags = "-idirafter " .. sh_quote(glibc_include) + .. " -idirafter " .. sh_quote(linux_include) + return "CC=" .. sh_quote("gcc") + .. " CPPFLAGS=" .. sh_quote(header_flags) + .. " CFLAGS=" .. sh_quote(header_flags) .. " " + end return "" end @@ -312,6 +344,7 @@ local function _install_impl() perl_path, make, sh_quote(logf))) local cc = cc_override() + if not cc then return false end if not run("./config", logf, string.format( "%scd %s && %s./config --prefix=%s --libdir=lib %s >> %s 2>&1", perl_path, sh_quote(srcroot), cc, sh_quote(prefix), flags, From 0df371f6e9c372f703bdfc1fa566f3ae14f57b67 Mon Sep 17 00:00:00 2001 From: wellwei Date: Fri, 7 Aug 2026 21:23:13 +0800 Subject: [PATCH 3/3] chore: use upstream OpenSSL toolchain repair --- pkgs/c/compat.openssl.lua | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pkgs/c/compat.openssl.lua b/pkgs/c/compat.openssl.lua index 5a12285c..52a7a3de 100644 --- a/pkgs/c/compat.openssl.lua +++ b/pkgs/c/compat.openssl.lua @@ -9,9 +9,9 @@ -- so there resolve_make() falls back to PATH. -- -- Because that build runs OUTSIDE mcpp's compile rules, it inherits none of --- the resolved toolchain's flags — it just calls `cc`. Anything the toolchain --- needs spelled out (Linux payload headers, macOS SDK, ranlib) has to be --- handed to it explicitly; see cc_override() and the install_sw step. +-- the resolved toolchain's flags — it just calls `cc`. Anything the host +-- toolchain needs spelled out (macOS SDK, ranlib) has to be handed to it +-- explicitly; see cc_override() and the install_sw step. -- -- PERL. `./config` execs `Configure`, which is `#!/usr/bin/env perl` and opens -- with `use Config; use FindBin;`. So what this build needs is not "a perl @@ -395,7 +395,6 @@ local function _install_impl() perl_path, make, sh_quote(logf))) local cc = cc_override() - if not cc then return false end if not run("./config", logf, string.format( "%scd %s && %s./config --prefix=%s --libdir=lib %s >> %s 2>&1", perl_path, sh_quote(srcroot), cc, sh_quote(prefix), flags,