Skip to content
Open
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
32 changes: 32 additions & 0 deletions .agents/docs/2026-10-03-add-libserial-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,35 @@ libstdc++ 仍保留(仅弃用告警),libc++ 在 C++20 及以上直接删掉,于

**另**:原分支合并 main 时把 CHANGELOG 中 `openkal-llvm-runtime 0.15.4` 与
`openkal-linux 0.16.1 / openkal-musl 0.20.1` 两条误删,已按 main 恢复。

## 11. 维护者追加(2026-10-20):aarch64 musl 的 `__MAX_BAUD`

**现象**:aarch64-linux-musl 配合严格 Clang 告警配置时,
`src/libserial/SerialPortConstants.h` 的 `#if __MAX_BAUD > B2000000` 报
`'__MAX_BAUD' is not defined, evaluates to 0 [-Werror,-Wundef]`。

**根因**:`__MAX_BAUD` 是 glibc `bits/termios.h` 的私有辅助宏。musl 1.2.5 定义了
`B2000000` 到 `B4000000`,但没有定义 `__MAX_BAUD`。上游把“该 libc 的最高波特率”
误写成所有 Linux libc 都保证的宏。

**补丁**:`pkgs/c/patches/libserial/0001-guard-musl-max-baud.patch` 由 git 生成,
把条件改为 `#if defined(__MAX_BAUD) && __MAX_BAUD > B2000000`。
`compat.libserial` 的 install hook 从描述符自身路径找到补丁,并以
`git apply` 打入解包树;应用后读取 `SerialPortConstants.h` 断言新文本确实存在,
避免 git 在仓库内发现父级 `.git` 后“Skipped patch”却仍返回成功。

版本资源提升为 `revision = 1`,让已经安装过 revision 0 的用户重新执行 install hook。
install hook 同时显式导入 `xim.libxpkg.log`。

**验证**:

- 纯 aarch64 musl 头 + Clang 22.1.8:
`-Wundef -Werror=undef` 对原式报上述错误,补丁式通过。
- 用打补丁后的实际 `SerialPortConstants.h` 配合 aarch64 musl 与 libc++ 头编译,
`-Wundef -Werror=undef` 通过。
- 清掉本包缓存后,mcpp `2026.10.1.2` 冷安装并通过
`mcpp test -p libserial --cache off`;安装目录中的头已包含守卫,安装标记为
`revision: 1`。
- OpenKal 的完整 aarch64-linux-musl 图在此之前还会先停在
`linux/serial.h: file not found`;这是 OpenKal C 环境没有提供 Linux UAPI 的另一问题,
不属于本补丁处理的 `__MAX_BAUD` 缺陷。
59 changes: 54 additions & 5 deletions pkgs/c/compat.libserial.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
-- compat.libaio. (Single-platform `xpm` is why platform-version-parity stays
-- quiet: it only compares platforms that both carry versions.)
--
-- TWO CONSUMER-VISIBLE DEFECTS ARE FIXED HERE. The first: src/libserial/SerialPortConstants.h
-- THREE CONSUMER-VISIBLE DEFECTS ARE FIXED HERE. The first: src/libserial/SerialPortConstants.h
-- declares `using DataBuffer = std::vector<uint8_t>;` but includes neither
-- <cstdint> nor <stdint.h>. On gcc 16.1.0 / libstdc++ this compiles only by
-- accident of transitive includes — a bare consumer that opens the header first
Expand All @@ -43,6 +43,15 @@
-- <type_traits> it needs, asserting each match count so an upstream change
-- fails the install instead of silently skipping the fix.
--
-- The third: SerialPortConstants.h guards the 2-4 Mbaud Linux enum values with
-- `#if __MAX_BAUD > B2000000`. __MAX_BAUD is a glibc bits/termios.h detail;
-- musl deliberately does not define it, so strict Clang configurations (for
-- example -Wundef -Werror) reject the public header on aarch64-linux-musl.
-- The checked-in patch pkgs/c/patches/libserial/0001-guard-musl-max-baud.patch
-- tests the macro before comparing it. install() applies it with `git apply`
-- before the result_of rewrite, and fails loudly when the upstream context no
-- longer matches instead of shipping an unpatched payload.
--
-- NO FEATURE. The three TUs are the whole library; upstream's optional parts
-- are the GoogleTest suite (test/, its own main()), the SIP Python bindings
-- (sip/) and the Doxygen docs (doxygen.conf.in) — none is an optional
Expand All @@ -69,6 +78,8 @@ package = {
CN = "https://gitcode.com/mcpp-res/libserial/releases/download/1.0.0/libserial-1.0.0.tar.gz",
},
sha256 = "063142d6bfe08898316e9a6055f2ddeedef56de06f7cfc8dcdfecc6efabf4bdd",
-- 1: apply the musl __MAX_BAUD patch in install().
revision = 1,
},
},
},
Expand Down Expand Up @@ -115,14 +126,52 @@ package = {
},
}

local descriptor_dir = debug.getinfo(1, "S").source:match("^@(.*)/[^/]+$")

import("xim.libxpkg.pkginfo")
import("xim.libxpkg.log")

-- See the header note: the C++20-removed std::result_of in SerialPort.h.
-- Patched in the unpacked tree, which is then moved into the install dir as
-- its single wrap level so the `*/src` globs keep matching (compat.ftxui /
-- taskflow.taskflow do the same).
-- See the header notes: apply the tracked musl __MAX_BAUD patch, fix the
-- C++20-removed std::result_of in SerialPort.h, then move the unpacked tree
-- into the install dir as its single wrap level so the `*/src` globs keep
-- matching (compat.ftxui / taskflow.taskflow do the same).
function install()
local wrap = "libserial-" .. pkginfo.version()

local function quote(value)
return "'" .. tostring(value):gsub("'", "'\\''") .. "'"
end

if not descriptor_dir then
log.error("compat.libserial: cannot locate the descriptor directory")
return false
end
local musl_patch = path.join(descriptor_dir,
"patches/libserial/0001-guard-musl-max-baud.patch")
if not os.isfile(musl_patch) then
log.error("compat.libserial: patch file not found: %s", musl_patch)
return false
end
-- The unpacked payload lives under this checkout's ignored .mcpp/ tree in
-- local tests. Without an explicit non-repository git-dir, git discovers
-- mcpp-index's .git and silently skips the ignored target ("Skipped
-- patch"). A nonexistent git-dir keeps `git apply` in plain-file mode.
local apply_command = "git -C " .. quote(wrap)
.. " --git-dir=/__mcpp_no_git_dir__ apply --whitespace=nowarn "
.. quote(musl_patch)
local applied, apply_result = pcall(os.exec, apply_command)
if not applied or not apply_result then
log.error("compat.libserial: failed to apply %s", musl_patch)
return false
end
local constants = path.join(wrap, "src/libserial/SerialPortConstants.h")
local constants_text = io.readfile(constants)
local patched_marker = "#if defined(__MAX_BAUD) && __MAX_BAUD > B2000000"
if not constants_text or not constants_text:find(patched_marker, 1, true) then
log.error("compat.libserial: patch did not reach %s", constants)
return false
end

local function patch(relative, before, after, expected)
local source = path.join(wrap, relative)
local content = io.readfile(source)
Expand Down
13 changes: 13 additions & 0 deletions pkgs/c/patches/libserial/0001-guard-musl-max-baud.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
diff --git a/src/libserial/SerialPortConstants.h b/src/libserial/SerialPortConstants.h
index 4f05bd5..c75ee67 100644
--- a/src/libserial/SerialPortConstants.h
+++ b/src/libserial/SerialPortConstants.h
@@ -216,7 +216,7 @@ namespace LibSerial
BAUD_1000000 = B1000000,
BAUD_1152000 = B1152000,
BAUD_1500000 = B1500000,
-#if __MAX_BAUD > B2000000
+#if defined(__MAX_BAUD) && __MAX_BAUD > B2000000
BAUD_2000000 = B2000000,
BAUD_2500000 = B2500000,
BAUD_3000000 = B3000000,
Loading