Skip to content

Commit 6d13e08

Browse files
mcpplibs.mwrap: zlib 1.3.2, zstd 1.5.7, xz 5.8.3, xxhash 0.8.3, libarchive 3.8.7, libc 17.0.0; the llvm leg plants FFmpeg's headers (#721)
Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
1 parent e28ff04 commit 6d13e08

28 files changed

Lines changed: 780 additions & 26 deletions

File tree

‎.github/workflows/validate.yml‎

Lines changed: 76 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,40 +1421,60 @@ jobs:
14211421
# A bare GitHub runner has no libav* under /usr/include, so a
14221422
# descriptor that loses its vendored headers to the host's would still
14231423
# be green here. That is precisely how compat.ffmpeg's -idirafter hole
1424-
# survived: nothing in CI had a system ffmpeg to lose to. Installing
1425-
# the dev headers is what turns this leg into a real test of include
1426-
# ORDER rather than of include EXISTENCE.
1424+
# survived: nothing in CI had a system ffmpeg to lose to. Headers of
1425+
# FFmpeg's own names under /usr/include are what turn this leg into a
1426+
# test of include ORDER rather than of include EXISTENCE.
1427+
#
1428+
# They are planted, not installed: each public header of the release
1429+
# compat.ffmpeg names, as a file that stops the compile, naming itself.
1430+
# A reach of the host's header is then an error at the line that made
1431+
# it, where an installed header of another FFmpeg compiled silently or
1432+
# failed somewhere else. And nothing is downloaded from Ubuntu's mirror,
1433+
# whose ffmpeg closure (~100 MiB at the 2026-11-06 rates) outlasted
1434+
# every timeout on ubuntu-26.04 runners.
14271435
#
14281436
# Deliberately only on the llvm leg. The default leg reaches its
14291437
# compiler through --sysroot, so it is immune by construction and
1430-
# installing there would change an existing job's environment for no
1438+
# planting there would change an existing job's environment for no
14311439
# coverage. Keeping the blast radius to the new leg means a red here
14321440
# is always about the thing this leg was added to watch.
1433-
- name: Install host ffmpeg dev headers (llvm leg only)
1441+
- name: Plant host ffmpeg headers that stop the compile (llvm leg only)
14341442
if: matrix.platform == 'linux' && matrix.toolchain == 'llvm'
14351443
shell: bash
1436-
# Only Ubuntu's own archive is refreshed: a bare `apt-get update` also
1437-
# walks every third-party source the runner image carries (PPAs,
1438-
# vendor repos), and one slow mirror among them held this step for
1439-
# minutes. Bounded timeouts and retries, and no recommended packages.
14401444
run: |
1441-
apt_opts=(-o Acquire::Retries=3 -o Acquire::http::Timeout=20 -o Acquire::https::Timeout=20)
1442-
if [[ -f /etc/apt/sources.list.d/ubuntu.sources ]]; then
1443-
mkdir -p "$RUNNER_TEMP/apt-ubuntu"
1444-
cp /etc/apt/sources.list.d/ubuntu.sources "$RUNNER_TEMP/apt-ubuntu/"
1445-
apt_opts+=(-o Dir::Etc::SourceList=/dev/null -o "Dir::Etc::SourceParts=$RUNNER_TEMP/apt-ubuntu")
1446-
fi
1447-
time sudo timeout 180 apt-get update -qq "${apt_opts[@]}"
1448-
for attempt in 1 2; do
1449-
if time sudo timeout 300 apt-get install -y -qq --no-install-recommends "${apt_opts[@]}" \
1450-
libavutil-dev libavcodec-dev libavformat-dev \
1451-
libavfilter-dev libavdevice-dev libswscale-dev libswresample-dev; then
1452-
break
1453-
fi
1454-
[[ $attempt == 2 ]] && { echo "::error::the ffmpeg dev headers did not install"; exit 1; }
1455-
echo "::warning::apt-get install failed (attempt $attempt); retrying"
1456-
done
1457-
dpkg -l | grep -E 'libav(util|codec)-dev|libswscale-dev'
1445+
python3 - <<'PY'
1446+
import hashlib, io, re, subprocess, tarfile, urllib.request
1447+
from pathlib import Path
1448+
lua = Path("pkgs/c/compat.ffmpeg.lua").read_text()
1449+
entry = re.search(r'linux\s*=\s*\{\s*\["([^"]+)"\]\s*=\s*\{.*?GLOBAL\s*=\s*"([^"]+)".*?CN\s*=\s*"([^"]+)".*?sha256\s*=\s*"([0-9a-f]{64})"', lua, re.S)
1450+
version, urls, sha = entry.group(1), (entry.group(2), entry.group(3)), entry.group(4)
1451+
data = None
1452+
for url in urls:
1453+
try:
1454+
data = urllib.request.urlopen(url, timeout=120).read()
1455+
except OSError as e:
1456+
print(f"::warning::{url}: {e}")
1457+
continue
1458+
if hashlib.sha256(data).hexdigest() == sha:
1459+
break
1460+
data = None
1461+
if data is None:
1462+
raise SystemExit(f"::error::the FFmpeg {version} source matching the descriptor could not be read")
1463+
libs = ("libavutil", "libavcodec", "libavformat", "libavfilter", "libavdevice", "libswscale", "libswresample")
1464+
planted = 0
1465+
with tarfile.open(fileobj=io.BytesIO(data)) as tar:
1466+
for name in tar.getnames():
1467+
parts = name.split("/")
1468+
if len(parts) == 3 and parts[1] in libs and parts[2].endswith(".h"):
1469+
target = Path("/usr/include") / parts[1] / parts[2]
1470+
text = f'#error "host <{parts[1]}/{parts[2]}> reached: a vendored FFmpeg header was not found first"\n'
1471+
subprocess.run(["sudo", "mkdir", "-p", str(target.parent)], check=True)
1472+
subprocess.run(["sudo", "tee", str(target)], input=text.encode(), check=True, stdout=subprocess.DEVNULL)
1473+
planted += 1
1474+
if planted < 100:
1475+
raise SystemExit(f"::error::only {planted} FFmpeg headers were planted")
1476+
print(f"planted {planted} FFmpeg {version} headers under /usr/include")
1477+
PY
14581478
14591479
# ── Select the toolchain for this leg ─────────────────────────────
14601480
# No version pin: `llvm` resolves to whatever the toolchain family's
@@ -1675,6 +1695,36 @@ jobs:
16751695
shell: bash
16761696
run: python3 tests/mwrap/check_installed_template.py --mcpp "$MCPP" --package mcpplibs.mwrap.mimalloc@3.6.1 --deploy
16771697

1698+
- name: Installed zlib wrapper archive, actual default compression template and its relocated notices
1699+
if: contains(format(' {0} ', env.MEMBERS), ' zlib-compress ') && matrix.toolchain == 'default'
1700+
shell: bash
1701+
run: python3 tests/mwrap/check_installed_template.py --mcpp "$MCPP" --package mcpplibs.mwrap.zlib@1.3.2 --deploy
1702+
1703+
- name: Installed zstd wrapper archive, actual default compression template and its relocated notices
1704+
if: contains(format(' {0} ', env.MEMBERS), ' zstd-squeeze ') && matrix.toolchain == 'default'
1705+
shell: bash
1706+
run: python3 tests/mwrap/check_installed_template.py --mcpp "$MCPP" --package mcpplibs.mwrap.zstd@1.5.7 --deploy
1707+
1708+
- name: Installed xz wrapper archive, actual default compression template and its relocated notices
1709+
if: contains(format(' {0} ', env.MEMBERS), ' xz-pack ') && matrix.toolchain == 'default'
1710+
shell: bash
1711+
run: python3 tests/mwrap/check_installed_template.py --mcpp "$MCPP" --package mcpplibs.mwrap.xz@5.8.3 --deploy
1712+
1713+
- name: Installed xxhash wrapper archive, actual default hashing template and its relocated notices
1714+
if: contains(format(' {0} ', env.MEMBERS), ' xxhash-digest ') && matrix.toolchain == 'default'
1715+
shell: bash
1716+
run: python3 tests/mwrap/check_installed_template.py --mcpp "$MCPP" --package mcpplibs.mwrap.xxhash@0.8.3 --deploy
1717+
1718+
- name: Installed libarchive wrapper archive, actual default archive template and its relocated notices
1719+
if: contains(format(' {0} ', env.MEMBERS), ' libarchive-bundle ') && matrix.toolchain == 'default'
1720+
shell: bash
1721+
run: python3 tests/mwrap/check_installed_template.py --mcpp "$MCPP" --package mcpplibs.mwrap.libarchive@3.8.7 --deploy
1722+
1723+
- name: Installed libc wrapper archive, actual default C stdio template and its relocated notices
1724+
if: contains(format(' {0} ', env.MEMBERS), ' libc-stdio ') && matrix.toolchain == 'default'
1725+
shell: bash
1726+
run: python3 tests/mwrap/check_installed_template.py --mcpp "$MCPP" --package mcpplibs.mwrap.libc@17.0.0 --deploy
1727+
16781728
- name: Installed libwebp wrapper archive, actual default image template and its relocated notices
16791729
if: contains(format(' {0} ', env.MEMBERS), ' libwebp-image ') && matrix.toolchain == 'default'
16801730
shell: bash

‎CHANGELOG.md‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,24 @@
1313
块,链接时找不到这两个归档;新增 `openkal` 块,不列链接参数。`-latomic` 上游只在找到时才链接,mimalloc 的原子操作在本索引
1414
构建的各架构上都是无锁的,LLVM 工具链在图中 C 库之上没有这个归档。
1515

16+
### Chore
17+
18+
- **validate:llvm 腿不再从 Ubuntu 镜像安装 ffmpeg 开发包,改为在 `/usr/include` 下放置 FFmpeg 公开头文件同名、内容为
19+
`#error` 的文件。** 文件名取自 compat.ffmpeg 描述符所指发布(按描述符的 sha256 校验)。宿主头文件一旦被包含即在包含处报错,
20+
比安装另一版本的头文件更直接地检验包含顺序;2026-11-06 起 ubuntu-26.04 运行器上 ffmpeg 依赖闭包(约 100 MiB)的下载在每个
21+
超时内都完成不了。
22+
1623
### Added
1724

25+
- **mcpplibs.mwrap.zlib 1.3.2、.zstd 1.5.7、.xz 5.8.3、.xxhash 0.8.3、.libarchive 3.8.7、.libc 17.0.0(新包)。** 六个 mwrap
26+
包装把头文件收敛到各自的包中(mcpp 设计记录 2026-11-07 D10)。前五个以 C++23 模块使用同版本的 compat 实现:函数、类型、
27+
枚举值以上游的全局名导出,常量宏与类型宏在 `.macros` 中为同名常量与别名,带参数的宏在 `<mwrap/<lib>/macros.hpp>`;
28+
导出清单由各仓库的 `tools/generate.py` 按 clang 读到的头文件生成并在 CI 中审计。`mcpplibs.mwrap.libc` 映射 ISO C17
29+
附录 B 的对象宏(`stdout()`、`errno()`、`EOF`、`INT_MAX` 等),实现为目标的 C 库。消费者测试 `tests/mwrap/zlib-compress`、
30+
`zstd-squeeze`、`xz-pack`、`xxhash-digest`、`libarchive-bundle`、`libc-stdio`,以及已安装模板与重定位许可检查(检查脚本以
31+
`STATIC_NOTICES` 表统一六个包的约定)。GLOBAL 为 GitHub 发布资产,CN 为 GitCode `mcpp-res/mwrap-<lib>` 镜像,sha256
32+
两处一致。`docs/mwrap.md` 补充 C 标准库这一实现来源。
33+
1834
- **openkal-macos 0.22.1.** The confinement rules are sized to the grants of each start; sixteen grants named near
1935
`MAXPATHLEN` no longer refuse a well-formed start with `kal_err_invalid`. OpenKal is the compatible range `^0.24.0`.
2036
First member of the openkal 0.24.1 correction group (mcpp design record 2026-11-07 §4.2.3).

‎docs/mwrap.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ A wrapper should depend on it when its configuration and ABI are sufficient.
2828
Complex implementations may instead vendor pinned sources under `upstream/`.
2929
Each implementation has one owner in a program: do not link both a vendored copy
3030
and a compat copy of the same library.
31+
The C standard library is the third source: its implementation is the target's
32+
C library, which mcpp selects with the target (glibc, musl, the Windows CRT,
33+
macOS libSystem, openkal-musl, mingw-w64). `mcpplibs.mwrap.libc` links nothing;
34+
its version names the standard (17.0.0 for ISO/IEC 9899:2018), recorded with
35+
`standard` in `[package.metadata.mwrap]`.
3136

3237
## Repository layout
3338

‎docs/zh/mwrap.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
包和模块名不带 -m,不创建另一套普通 API namespace。已发布旧身份、版本和内容保持不可变,
2121
通过新 mwrap 身份迁移。简单实现优先依赖 compat.xxx;复杂库可以 vendor 到 upstream/。
2222
同一程序的同一实现只能有一个所有者,不能把 compat 与 vendored 实现重复链接。
23+
C 标准库是第三种实现来源:实现由目标的 C 库提供,由 mcpp 随目标选定(glibc、musl、Windows CRT、macOS libSystem、
24+
openkal-musl、mingw-w64)。`mcpplibs.mwrap.libc` 不链接任何实现;版本号表示所依据的标准(ISO/IEC 9899:2018 为 17.0.0),
25+
记录在 `[package.metadata.mwrap]` 的 `standard` 中。
2326

2427
## 仓库分层
2528

‎mcpp.toml‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ members = [
3131
"tests/mwrap/libvpx-webm",
3232
"tests/mwrap/box2d-physics",
3333
"tests/mwrap/mimalloc-heap",
34+
"tests/mwrap/zlib-compress",
35+
"tests/mwrap/zstd-squeeze",
36+
"tests/mwrap/xz-pack",
37+
"tests/mwrap/xxhash-digest",
38+
"tests/mwrap/libarchive-bundle",
39+
"tests/mwrap/libc-stdio",
3440
"tests/mwrap/miniaudio-engine",
3541
"tests/mwrap/freetype-render",
3642
"tests/mwrap/harfbuzz-shape",

‎pkgs/mwrap/libarchive.lua‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
-- Immutable upstream-aligned mwrap source release (libarchive-m mwrap-3.8.7);
2+
-- GLOBAL and CN bytes are identical.
3+
--
4+
-- The wrapper is Apache-2.0; the library it links, compat.libarchive
5+
-- (libarchive 3.8.7), is BSD-2-Clause with the exceptions its COPYING lists,
6+
-- linked statically: the package deploys its README and COPYING beside
7+
-- programs (runtime.deploy).
8+
package = {
9+
spec = "1",
10+
namespace = "mcpplibs.mwrap",
11+
name = "libarchive",
12+
description = "libarchive-m: libarchive 3.8.7 (tar, cpio, zip, 7-Zip, ISO 9660 … with their compression filters, entries, disk access) as C++23 modules, with the constants of archive.h as C++ constants",
13+
licenses = { "Apache-2.0" },
14+
repo = "https://github.com/mcpplibs/libarchive-m",
15+
type = "package",
16+
extensions = {
17+
autoupdate = {
18+
tag = "mwrap-${version}",
19+
url = "https://github.com/mcpplibs/libarchive-m/releases/download/${tag}/libarchive-m-${version}.tar.gz",
20+
},
21+
},
22+
xpm = {
23+
linux = {
24+
["3.8.7"] = {
25+
url = {
26+
GLOBAL = "https://github.com/mcpplibs/libarchive-m/releases/download/mwrap-3.8.7/libarchive-m-3.8.7.tar.gz",
27+
CN = "https://gitcode.com/mcpp-res/mwrap-libarchive/releases/download/3.8.7/libarchive-m-3.8.7.tar.gz",
28+
},
29+
sha256 = "b55c102f8743112d94bd57ab8e79b31cdfe49935c1bebaed846b1a4508e9c8f8",
30+
},
31+
},
32+
macosx = {
33+
["3.8.7"] = {
34+
url = {
35+
GLOBAL = "https://github.com/mcpplibs/libarchive-m/releases/download/mwrap-3.8.7/libarchive-m-3.8.7.tar.gz",
36+
CN = "https://gitcode.com/mcpp-res/mwrap-libarchive/releases/download/3.8.7/libarchive-m-3.8.7.tar.gz",
37+
},
38+
sha256 = "b55c102f8743112d94bd57ab8e79b31cdfe49935c1bebaed846b1a4508e9c8f8",
39+
},
40+
},
41+
windows = {
42+
["3.8.7"] = {
43+
url = {
44+
GLOBAL = "https://github.com/mcpplibs/libarchive-m/releases/download/mwrap-3.8.7/libarchive-m-3.8.7.tar.gz",
45+
CN = "https://gitcode.com/mcpp-res/mwrap-libarchive/releases/download/3.8.7/libarchive-m-3.8.7.tar.gz",
46+
},
47+
sha256 = "b55c102f8743112d94bd57ab8e79b31cdfe49935c1bebaed846b1a4508e9c8f8",
48+
},
49+
},
50+
},
51+
}

‎pkgs/mwrap/libc.lua‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
-- Immutable upstream-aligned mwrap source release (libc-m mwrap-17.0.0);
2+
-- GLOBAL and CN bytes are identical.
3+
--
4+
-- The wrapper is Apache-2.0 and links nothing: the implementation is the
5+
-- target's C library. The version names the standard, ISO/IEC 9899:2018 (C17).
6+
package = {
7+
spec = "1",
8+
namespace = "mcpplibs.mwrap",
9+
name = "libc",
10+
description = "libc-m: the C standard library (ISO C17) for C++ modules: std.compat with the object-like macros of ISO C (stdout, errno, EOF, INT_MAX …) as C++ constants and functions",
11+
licenses = { "Apache-2.0" },
12+
repo = "https://github.com/mcpplibs/libc-m",
13+
type = "package",
14+
extensions = {
15+
autoupdate = {
16+
tag = "mwrap-${version}",
17+
url = "https://github.com/mcpplibs/libc-m/releases/download/${tag}/libc-m-${version}.tar.gz",
18+
},
19+
},
20+
xpm = {
21+
linux = {
22+
["17.0.0"] = {
23+
url = {
24+
GLOBAL = "https://github.com/mcpplibs/libc-m/releases/download/mwrap-17.0.0/libc-m-17.0.0.tar.gz",
25+
CN = "https://gitcode.com/mcpp-res/mwrap-libc/releases/download/17.0.0/libc-m-17.0.0.tar.gz",
26+
},
27+
sha256 = "e601179504f0fc94bb4d2f002982b2f5b9cc4b95a50a13822bd9b272519a3a9c",
28+
},
29+
},
30+
macosx = {
31+
["17.0.0"] = {
32+
url = {
33+
GLOBAL = "https://github.com/mcpplibs/libc-m/releases/download/mwrap-17.0.0/libc-m-17.0.0.tar.gz",
34+
CN = "https://gitcode.com/mcpp-res/mwrap-libc/releases/download/17.0.0/libc-m-17.0.0.tar.gz",
35+
},
36+
sha256 = "e601179504f0fc94bb4d2f002982b2f5b9cc4b95a50a13822bd9b272519a3a9c",
37+
},
38+
},
39+
windows = {
40+
["17.0.0"] = {
41+
url = {
42+
GLOBAL = "https://github.com/mcpplibs/libc-m/releases/download/mwrap-17.0.0/libc-m-17.0.0.tar.gz",
43+
CN = "https://gitcode.com/mcpp-res/mwrap-libc/releases/download/17.0.0/libc-m-17.0.0.tar.gz",
44+
},
45+
sha256 = "e601179504f0fc94bb4d2f002982b2f5b9cc4b95a50a13822bd9b272519a3a9c",
46+
},
47+
},
48+
},
49+
}

‎pkgs/mwrap/xxhash.lua‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
-- Immutable upstream-aligned mwrap source release (xxhash-m mwrap-0.8.3);
2+
-- GLOBAL and CN bytes are identical.
3+
--
4+
-- The wrapper is Apache-2.0; the library it links, compat.xxhash (xxHash
5+
-- 0.8.3), is BSD-2-Clause, linked statically: the package deploys its README
6+
-- and LICENSE beside programs (runtime.deploy).
7+
package = {
8+
spec = "1",
9+
namespace = "mcpplibs.mwrap",
10+
name = "xxhash",
11+
description = "xxhash-m: xxHash 0.8.3 (XXH32, XXH64, XXH3 64 and 128 bits, one-shot and streaming) as C++23 modules",
12+
licenses = { "Apache-2.0" },
13+
repo = "https://github.com/mcpplibs/xxhash-m",
14+
type = "package",
15+
extensions = {
16+
autoupdate = {
17+
tag = "mwrap-${version}",
18+
url = "https://github.com/mcpplibs/xxhash-m/releases/download/${tag}/xxhash-m-${version}.tar.gz",
19+
},
20+
},
21+
xpm = {
22+
linux = {
23+
["0.8.3"] = {
24+
url = {
25+
GLOBAL = "https://github.com/mcpplibs/xxhash-m/releases/download/mwrap-0.8.3/xxhash-m-0.8.3.tar.gz",
26+
CN = "https://gitcode.com/mcpp-res/mwrap-xxhash/releases/download/0.8.3/xxhash-m-0.8.3.tar.gz",
27+
},
28+
sha256 = "4e389afbece2290b44c24c12b4ad1086c28f146e78de8cebf5c701f676dc36cc",
29+
},
30+
},
31+
macosx = {
32+
["0.8.3"] = {
33+
url = {
34+
GLOBAL = "https://github.com/mcpplibs/xxhash-m/releases/download/mwrap-0.8.3/xxhash-m-0.8.3.tar.gz",
35+
CN = "https://gitcode.com/mcpp-res/mwrap-xxhash/releases/download/0.8.3/xxhash-m-0.8.3.tar.gz",
36+
},
37+
sha256 = "4e389afbece2290b44c24c12b4ad1086c28f146e78de8cebf5c701f676dc36cc",
38+
},
39+
},
40+
windows = {
41+
["0.8.3"] = {
42+
url = {
43+
GLOBAL = "https://github.com/mcpplibs/xxhash-m/releases/download/mwrap-0.8.3/xxhash-m-0.8.3.tar.gz",
44+
CN = "https://gitcode.com/mcpp-res/mwrap-xxhash/releases/download/0.8.3/xxhash-m-0.8.3.tar.gz",
45+
},
46+
sha256 = "4e389afbece2290b44c24c12b4ad1086c28f146e78de8cebf5c701f676dc36cc",
47+
},
48+
},
49+
},
50+
}

0 commit comments

Comments
 (0)