Skip to content
Closed
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
194 changes: 20 additions & 174 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ on:
workflow_dispatch:

env:
# 0.0.106: SPEC-001 package identity (mcpp#280). `package.name` is a SINGLE
# ATOMIC SEGMENT — all hierarchy lives in `package.namespace` — and mcpp
# addresses a package by the LITERAL name it read, so descriptors no longer
# repeat their namespace inside `name`. This index is migrated to the short
# form, which is why min_mcpp/latest_mcpp move in lock-step: an older client
# re-derives `<ns>.<short>`, misses, and reports a bare E_NOT_FOUND. Bundles
# xlings 0.4.69, which keys its index by (namespace, name) so two packages
# sharing a short name in one index are both addressable (xlings#381) — this
# index now has three such pairs (imgui / ffmpeg / lua under compat vs the
# default namespace).
# 0.0.102: windows command-line ceiling (mcpp#261 — the clang scan rule got
# its P1689 JSON through shell redirection, which forced a `cmd /c` wrapper
# and with it cmd.exe's 8191-char limit; clang-scan-deps -o removes both, and
Expand Down Expand Up @@ -47,149 +57,9 @@ env:
# 0.0.94 fixed feature-gated `sources` under `mcpp test` (mcpp#218); 0.0.91
# added standard = "c++fly" to the resolver grammar, so c++fly descriptors
# get the lint WARN below, not a hard grammar-parse rejection.
MCPP_VERSION: "0.0.102"
MCPP_VERSION: "0.0.107"

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install lua
run: sudo apt-get install -y --no-install-recommends lua5.4
- name: Lint package descriptors
run: |
fail=0
for f in pkgs/*/*.lua; do
# 1. Lua syntax check — load (= compile) without executing.
# `loadfile(name, 't')` rejects bytecode and parses text only.
if ! lua5.4 -e "assert(loadfile('$f', 't'))" >/dev/null 2>&1; then
echo "::error file=$f::lua syntax error"
fail=1
fi
# 2. xpkg V1 baseline: the file has to populate `package = { ... }`
# with at least `spec`, `name`, and an `xpm` table. Form A vs
# Form B (mcpp = "<path>" / mcpp = { ... }) is descriptor-author
# choice and not enforced here.
for needle in 'spec *=' 'name *=' 'xpm *='; do
if ! grep -q "$needle" "$f"; then
echo "::error file=$f::missing required field ($needle)"
fail=1
fi
done
# 3. Package version identifiers and dependency versions should be
# bare versions ("1.2.3"), not upstream tag names ("v1.2.3").
# Download URLs may still contain refs/tags/v* when upstream
# uses that tag spelling.
if grep -nE '\["v[0-9]+|\["[^"]+"\][[:space:]]*=[[:space:]]*"v[0-9]+' "$f"; then
echo "::error file=$f::version identifiers must not use a leading v"
fail=1
fi
# 4. Mirror table sanity: when a download `url` is written as a
# { GLOBAL=..., CN=... } table, both regions must be present and
# the CN entry must point at the gitcode mcpp-res mirror.
if ! lua5.4 tests/check_mirror_urls.lua "$f"; then
fail=1
fi
# 5. `name` must be the fully-qualified `<namespace>.<short>`.
# The split form (namespace = "chriskohlhoff", name = "asio")
# parses and passes `mcpp xpkg parse`, but xlings keys the index
# on the literal `name` while mcpp asks for the reconstructed
# FQN — they never meet, so the package is uninstallable on
# every platform (mcpp-community/mcpp#278). This check is cheap
# and catches in seconds what otherwise fails an hour into the
# workspace job.
if ! lua5.4 tests/check_package_name.lua "$f"; then
fail=1
fi
# 6. c++fly admission policy (mcpp design 2026-07-14 §11-Q2, v1):
# c++fly means "toolchain's latest level + every experimental
# gate" — deliberately toolchain-dependent, so a published
# package built with it is not reproducible for consumers.
# Policy: WARN (never fail) and observe ecosystem usage before
# deciding whether to tighten. Two spellings: `language = ` is
# the descriptor's inline mcpp-segment key; `standard = ` covers
# mcpp.toml content embedded in heredoc/generated_files blocks.
if grep -nE '\b(language|standard)[[:space:]]*=[[:space:]]*"c\+\+fly"' "$f" >/dev/null; then
echo "::warning file=$f::declares C++ standard \"c++fly\" (experimental playground mode) — toolchain-dependent and non-reproducible for consumers; published packages should pin a concrete standard (c++23/c++26)"
fi
done
[ $fail -eq 0 ] && echo "All package files valid."
exit $fail
# ── Single-source-of-truth grammar check ─────────────────────────
# `mcpp xpkg parse` uses EXACTLY the resolver's parser, so what
# passes here is what builds for users of the pinned MCPP_VERSION.
# Strict by default: unknown mcpp-segment keys fail (they would be
# silently ignored at build time). This also mechanically enforces
# the rollout rule "floor first, new grammar after": descriptors
# needing a newer grammar cannot pass a lint pinned to an older mcpp.
- name: Download pinned mcpp
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"
tar -xzf mcpp.tar.gz
echo "MCPP=$PWD/mcpp-${MCPP_VERSION}-linux-x86_64/bin/mcpp" >> "$GITHUB_ENV"
- name: Parse descriptors with the resolver grammar (mcpp xpkg parse)
run: |
fail=0
for f in pkgs/*/*.lua; do
if ! "$MCPP" xpkg parse "$f" > /dev/null; then
echo "::error file=$f::mcpp xpkg parse failed (resolver grammar)"
fail=1
fi
done
[ $fail -eq 0 ] && echo "All descriptors parse with mcpp ${MCPP_VERSION}."
exit $fail

mirror-cn-reachable:
# Closed-loop guard for the CN mirror: every CN url referenced by a
# descriptor must be a live, downloadable gitcode release asset.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install lua
run: sudo apt-get install -y --no-install-recommends lua5.4
- name: Check CN mirror assets are reachable
run: |
fail=0
# collect unique CN urls across all descriptors
: > /tmp/cn.tsv
for f in pkgs/*/*.lua; do
lua5.4 tests/list_cn_urls.lua "$f" >> /tmp/cn.tsv || true
done
sort -u /tmp/cn.tsv -o /tmp/cn.tsv
total=$(grep -c . /tmp/cn.tsv || true)
echo "checking $total CN mirror url(s)"
while IFS=$'\t' read -r url sha; do
[ -z "$url" ] && continue
# follow redirects; gitcode release assets resolve to object storage
code=$(curl -fsSL -o /dev/null -w '%{http_code}' --retry 2 --max-time 60 "$url" || echo "000")
if [ "$code" != "200" ]; then
echo "::error::CN mirror unreachable ($code): $url"
fail=1
else
echo "ok: $url"
fi
done < /tmp/cn.tsv
[ $fail -eq 0 ] && echo "All CN mirror urls reachable."
exit $fail

# ── The whole test surface, as a mcpp workspace ───────────────────────
# mcpp-index is a mcpp [workspace]; every per-library test project under
# tests/examples/ is a member. `mcpp test --workspace` builds + runs each
# member's tests/ (behavioral assertions) on each OS — members self-gate by
# `[target.'cfg(...)']` (e.g. the X11/glfw stack is linux-only, openblas is
# windows-only), so one command covers the matrix with no shell driver.
# The ~/.mcpp/registry cache carries the built compat packages (xpkgs) across
# runs, so repeat builds are fast.
#
# timeout-minutes is sized for the COLD build, not the cached path. The opencv
# module package carries a from-source OpenCV 5 build, and each feature variant
# re-keys the store into a full recompile, so a full run (forced whenever this
# workflow file changes — e.g. a version bump) serially builds three OpenCV
# variants on one runner: the opencv-module base member plus the `unifont` and
# `dnn` feature members. The registry cache (restore-keys prefix below)
# amortizes those across subsequent runs. 150 covers the one-time cold full
# build with headroom; it is a ceiling, not a target.
workspace:
name: workspace (${{ matrix.platform }})
runs-on: ${{ matrix.os }}
Expand All @@ -198,30 +68,16 @@ jobs:
fail-fast: false
matrix:
include:
# Archive names are derived from env.MCPP_VERSION in the Download
# step — bumping the pin is a ONE-line change (hardcoded versions
# here once 404'd a pin bump).
- platform: linux
os: ubuntu-latest
suffix: linux-x86_64
ext: tar.gz
mcpp: bin/mcpp
xlings: registry/bin/xlings
mcpp_version: "0.0.102" # keep in sync with env.MCPP_VERSION
- platform: macos
os: macos-15
suffix: macosx-arm64
ext: tar.gz
mcpp: bin/mcpp
xlings: registry/bin/xlings
mcpp_version: "0.0.102" # keep in sync with env.MCPP_VERSION
# PROBE: only Windows, and pinned to the instrumented debug build
# published by mcpp's debug-win workflow (branch
# debug/win127-instrumentation, prerelease tag v0.0.107-dbg).
- platform: windows
os: windows-latest
suffix: windows-x86_64
ext: zip
mcpp: bin/mcpp.exe
xlings: registry/bin/xlings.exe
mcpp_version: "0.0.102" # keep in sync with env.MCPP_VERSION
mcpp_version: "0.0.107-dbg"
env:
MCPP_EFFECTIVE: ${{ matrix.mcpp_version }}
steps:
Expand Down Expand Up @@ -345,18 +201,8 @@ jobs:
MCPP_INDEX_MIRROR: GLOBAL
run: |
"$MCPP" --version
# No `timeout` wrapper: absent on macOS runners; job-level timeout-minutes bounds it.
if [ "$MEMBERS" = "__ALL__" ]; then
"$MCPP" test --workspace
elif [ -z "$MEMBERS" ]; then
echo "No workspace member affected by this change — nothing to test."
else
rc=0
for m in $MEMBERS; do
echo "::group::mcpp test -p $m"
"$MCPP" test -p "$m" || rc=1
echo "::endgroup::"
done
exit $rc
fi

echo "=== ffmpeg member, instrumented ==="
rc=0
"$MCPP" test -p tests/examples/ffmpeg 2>&1 | tail -120 || rc=$?
echo "=== ffmpeg member exit status: $rc ==="
exit $rc
24 changes: 23 additions & 1 deletion docs/repository-and-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ tests/examples/<member>/ 每库测试工程(workspace 成员;<member> 为包
([target.'cfg(...)'])
tests/*.cpp 行为断言(独立 main,退出码非 0 即失败)
tests/check_mirror_urls.lua lint:GLOBAL+CN 表完整性,以及 CN 指向 mcpp-res
tests/check_package_name.lua lint:身份形态(name 为单一原子段,层级归 namespace)
tests/list_cn_urls.lua 抽取 CN url,供 mirror-cn-reachable 使用
README.md 索引说明与贡献入口
.github/workflows/validate.yml CI:lint / mirror-cn-reachable / workspace(3 平台矩阵)
Expand All @@ -37,6 +38,24 @@ tools/compat-ffmpeg/ 等 compat 大包的描述符再生成流水线

`package` 必填字段:`spec`、`namespace`、`name`、`description`、`licenses`、`repo`、`type="package"`、`xpm`、`mcpp`。

### 包身份:`(namespace, name)`

身份是二元组 —— **`namespace` 是点分层级路径,`name` 是单一原子段**。层级一律放 `namespace`(mcpp SPEC-001 §3.2,`docs/spec/package-identity.md`):

```lua
namespace = "compat", name = "zlib" -- ✅
namespace = "mcpplibs.capi", name = "lua" -- ✅ 多级命名空间
namespace = "mcpplibs", name = "capi.lua" -- ❌ 短名仍带点
```

最后一种被拒绝而非重新解读:`name` 里多出的点描述的是一个**没人声明过的命名空间**。mcpp 曾按最后一个点切分、静默造出 `(mcpplibs.capi, lua)`,0.0.106 起改为拒绝。

**兼容形态**:SPEC-001 之前发布的描述符把命名空间重复写在 `name` 里(`namespace="compat", name="compat.zlib"`),仍被接受 —— 前缀会先剥离再判定,wire key 是字面 `name`,两种写法都可安装。本仓已统一迁到短名形态。

**同短名不同命名空间可共存**:本仓现有三对 —— `compat:imgui` 与默认命名空间的 `imgui`、`compat:ffmpeg` 与 `ffmpeg`、`compat:lua` 与 `mcpplibs.capi:lua`。需要 xlings ≥ 0.4.69([xlings#381](https://github.com/openxlings/xlings/issues/381));`(namespace, name)` 唯一即可,`name` 本身不必唯一。

**文件名不参与解析**,可以任意。推荐 `<name>.lua` 或 `<namespace>.<name>.lua`(命中 mcpp 的快路径),但描述符按**声明的身份**被发现,叫别的名字也能解析。

`xpm.<linux|macosx|windows>.<裸版本>`:

- `url`:字符串,或 `{ GLOBAL=…, CN=… }` 表(本仓统一使用表形式)。
Expand Down Expand Up @@ -76,7 +95,9 @@ mcpp 跑 `xpkg parse`(strict:未知键即失败),所以需要更新文法/键的
- 触发条件:PR(改动 `pkgs/**/*.lua`、`tests/**`、`README.md` 或本 workflow)、push 至 main、nightly cron、手动触发。
- `env.MCPP_VERSION` 为全部 job 使用的 mcpp 版本,本地验证应与之对齐。
- `lint`(始终运行):lua 语法 `loadfile(f,'t')`;须含 `spec=`/`name=`/`xpm=`;禁止前导 v 版本;执行
`check_mirror_urls.lua`;再用 CI pin 的 mcpp 对每个描述符跑 `mcpp xpkg parse`(strict,未知键即失败)。
`check_mirror_urls.lua`;执行 `check_package_name.lua`(身份形态,见上文「包身份」);再用 CI pin 的
mcpp 对每个描述符跑 `mcpp xpkg parse`(strict,未知键即失败)。mcpp ≥ 0.0.106 的 `xpkg parse` 自身
也强制身份形态,lua lint 因此是更早、更便宜的冗余闸门。
- `mirror-cn-reachable`(始终运行):逐个 `curl` CN url,均须返回 200。
- `workspace (linux|macos|windows)`:整个测试面就是一个 mcpp workspace,**唯一的构建/运行通道**——
没有任何 shell 驱动的例外(公开模块包 imgui/ffmpeg/opencv/tinyhttps 也是普通成员,经成员级
Expand All @@ -96,6 +117,7 @@ for f in pkgs/*/*.lua; do
for n in 'spec *=' 'name *=' 'xpm *='; do grep -q "$n" "$f" || { echo "MISS $n $f"; fail=1; }; done
grep -nqE '\["v[0-9]+|\["[^"]+"\][[:space:]]*=[[:space:]]*"v[0-9]+' "$f" && { echo "LEADING-V $f"; fail=1; }
lua5.4 tests/check_mirror_urls.lua "$f" >/dev/null 2>&1 || { echo "MIRROR $f"; fail=1; }
lua5.4 tests/check_package_name.lua "$f" || fail=1
done
[ $fail -eq 0 ] && echo "ALL LINT PASS"
```
Expand Down
4 changes: 2 additions & 2 deletions index.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
# "floor first, new grammar after" rollout rule mechanically.
[index]
spec = "1"
min_mcpp = "0.0.102"
latest_mcpp = "0.0.102"
min_mcpp = "0.0.107"
latest_mcpp = "0.0.107"
2 changes: 1 addition & 1 deletion pkgs/c/chriskohlhoff.asio.lua
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ package = {
-- identity normalizes both spellings) but registers the index entry under
-- `asio`, which no consumer request can ever hit → E_NOT_FOUND at install.
-- See mcpp-community/mcpp#278; the lint in validate.yml enforces this.
name = "chriskohlhoff.asio",
name = "asio",
description = "Standalone asio exposed as the C++23 module `asio` (separate compilation)",
licenses = {"BSL-1.0"},
repo = "https://github.com/chriskohlhoff/asio",
Expand Down
2 changes: 1 addition & 1 deletion pkgs/c/cmdline.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
package = {
spec = "1",
namespace = "mcpplibs",
name = "mcpplibs.cmdline",
name = "cmdline",
description = "A simple command-line parsing library/framework for modern C++",
licenses = {"Apache-2.0"},
repo = "https://github.com/mcpplibs/cmdline",
Expand Down
2 changes: 1 addition & 1 deletion pkgs/c/compat.bzip2.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package = {
spec = "1",
namespace = "compat",
name = "compat.bzip2",
name = "bzip2",
description = "A freely available high-quality data compressor",
licenses = {"bzip2-1.0.6"},
repo = "https://sourceware.org/bzip2/",
Expand Down
2 changes: 1 addition & 1 deletion pkgs/c/compat.cjson.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
package = {
spec = "1",
namespace = "compat",
name = "compat.cjson",
name = "cjson",
description = "Ultralightweight JSON parser in ANSI C",
licenses = {"MIT"},
repo = "https://github.com/DaveGamble/cJSON",
Expand Down
2 changes: 1 addition & 1 deletion pkgs/c/compat.eigen.lua
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
package = {
spec = "1",
namespace = "compat",
name = "compat.eigen",
name = "eigen",
description = "C++ template library for linear algebra (header-only)",
licenses = {"MPL-2.0"},
repo = "https://gitlab.com/libeigen/eigen",
Expand Down
2 changes: 1 addition & 1 deletion pkgs/c/compat.ffmpeg.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
-- include_dirs_after (-idirafter, mcpp#249) so libc++ <version> is not shadowed
-- by ffmpeg's VERSION file on case-insensitive macOS.
package = {
spec = "1", namespace = "compat", name = "compat.ffmpeg",
spec = "1", namespace = "compat", name = "ffmpeg",
description = "FFmpeg 8.1.2 multimedia libraries, full source build (LGPL profile, multi-platform)",
licenses = {"LGPL-2.1-or-later"}, repo = "https://ffmpeg.org", type = "package",
xpm = {
Expand Down
2 changes: 1 addition & 1 deletion pkgs/c/compat.ftxui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
package = {
spec = "1",
namespace = "compat",
name = "compat.ftxui",
name = "ftxui",
description = "C++ Functional Terminal User Interface (screen + dom + component)",
licenses = {"MIT"},
repo = "https://github.com/ArthurSonzogni/FTXUI",
Expand Down
2 changes: 1 addition & 1 deletion pkgs/c/compat.glfw.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package = {
spec = "1",
namespace = "compat",
name = "compat.glfw",
name = "glfw",
description = "GLFW windowing and input library built from upstream sources",
licenses = {"Zlib"},
repo = "https://github.com/glfw/glfw",
Expand Down
2 changes: 1 addition & 1 deletion pkgs/c/compat.glx-runtime.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package = {
spec = "1",
namespace = "compat",
name = "compat.glx-runtime",
name = "glx-runtime",
description = "Host GLVND/GLX/OpenGL runtime adapter for mcpp Linux window applications",
licenses = {"MIT"},
repo = "https://github.com/KhronosGroup/OpenGL-Registry",
Expand Down
2 changes: 1 addition & 1 deletion pkgs/c/compat.gtest.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
package = {
spec = "1",
namespace = "compat",
name = "compat.gtest",
name = "gtest",
description = "Google's C++ test framework",
licenses = {"BSD-3-Clause"},
repo = "https://github.com/google/googletest",
Expand Down
2 changes: 1 addition & 1 deletion pkgs/c/compat.imgui.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package = {
spec = "1",
namespace = "compat",
name = "compat.imgui",
name = "imgui",
description = "Dear ImGui immediate-mode GUI library core sources",
licenses = {"MIT"},
repo = "https://github.com/ocornut/imgui",
Expand Down
2 changes: 1 addition & 1 deletion pkgs/c/compat.khrplatform.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package = {
spec = "1",
namespace = "compat",
name = "compat.khrplatform",
name = "khrplatform",
description = "Khronos KHR platform header for OpenGL/EGL compat packages",
licenses = {"Khronos"},
repo = "https://github.com/KhronosGroup/EGL-Registry",
Expand Down
Loading
Loading