diff --git a/.agents/docs/2026-11-13-add-tensorvia-plan.md b/.agents/docs/2026-11-13-add-tensorvia-plan.md new file mode 100644 index 00000000..9a28c571 --- /dev/null +++ b/.agents/docs/2026-11-13-add-tensorvia-plan.md @@ -0,0 +1,60 @@ +# Register aimol.tensorvia 0.3.0 + +Date: 2026-11-13. + +Register the multi-backend Tensorvia library (`aimol.tensorvia`, Form A: the +release tarball carries its own `mcpp.toml`, emitted by `mcpp emit xpkg` from +that manifest) and retire the CPU-only split `aimol.tensorvia-cpu`: the +upstream maintainer confirms it is unused, so its descriptor is removed in the +same change and the live documents that cited it as the plain-string-url +precedent (docs/zh/cn-mirror.md, both descriptor-examples pages, the spdlog +descriptor's comment, the add-mcpp-index-package skill, the site plugin's two +comments, and the now-unreachable Tensorvia-cpu cache entries) now cite +`pkgs/t/tensorvia.lua` — the English cn-mirror page and the plugin/cache edits +were found by a final sweep after the descriptor was removed. Historical plan +documents keep their point-in-time mentions. + +Form and source: C++23 module library (`import tensorvia;`), CPU backend on by +default; vulkan/cuda/sycl are features gated on the accelerator axis, so this +index entry serves the CPU artifact a consumer gets without `--accel`. The +vulkan lane's `xim:shaderc` sits on the package's own target axis and is +deliberately NOT promoted to the descriptor: a CPU consumer must not download a +shader compiler, and the package's own build program already warns and names +the payload when a vulkan accelerator is selected. + +The `mcpp` pointer is the literal `mcpp.toml`: the release asset is built by +`git archive`, so there is no `-/` wrap layer for a `*/` glob to +absorb (precedent: `pkgs/g/gcc.libstdcxx.lua`). The test member declares its +own `[indices] aimol = { path = "../../.." }`; a member-level table replaces +the root's `compat` alias, which cannot resolve `aimol.*` (same shape as +`tests/examples/taskflow-module`). + +The descriptor carries no "AUTO-GENERATED / do not edit by hand" banner: `name`, +`maintainers` and the `mcpp` pointer are hand edits, so the file presents itself +as hand-maintained, the same treatment `pkgs/h/huxerui.huxerui.lua` documents. + +Version 0.3.0 is the `v0.3.0` tag of Aimol-l/Tensorvia, archived with +`git archive` (`.vscode/` excluded via `.gitattributes` export-ignore). All +three platform blocks name the same tarball, SHA256 +d01e36f09db56cea1470425dbb0e0bbeb9d9bb9cee184b1c6d3d51760518fb1f, computed +twice and stable. The CPU lane is portable C++23 + OpenMP; the device lanes +are Linux-only and feature-gated, so no per-platform split is needed. CN +mirror: plain upstream release URL, the simplified path +`pkgs/c/compat.spdlog.lua` documents; this descriptor is itself the +mcpp-native precedent now. + +Feature evaluation: the three device features exist in the shipped manifest +and select themselves via the consumer's `--accel`; nothing here registers +feature-deps, because a CPU consumer installs none of the device payloads and +the negative path is the default. The test member asserts that default: it +depends on `aimol.tensorvia` with no features, imports the module, runs CPU +ops and reads back scalars, and exits non-zero on any mismatch. + +Autoupdate: registered as `tag = "v${version}"` with the tarball URL pattern +above, matching the upstream's actual tagging. + +Validation: `lua5.4` syntax, `check_mirror_urls`, `check_package_name`, +`check_reserved_namespace` and strict `mcpp xpkg parse` pass locally on +mcpp 2026.11.7.2; `bash tests/run_members.sh tensorvia` downloads the published +release, builds the module and passes the smoke assertions: `test result ok. +1 passed; 0 failed` in 20.32s (build 13.36s + run 0.01s). diff --git a/.agents/skills/add-mcpp-index-package/SKILL.md b/.agents/skills/add-mcpp-index-package/SKILL.md index fc9da695..672458fd 100644 --- a/.agents/skills/add-mcpp-index-package/SKILL.md +++ b/.agents/skills/add-mcpp-index-package/SKILL.md @@ -31,7 +31,7 @@ description: Use when adding a new third-party library/package to the mcpp-index - **(a) 第三方上游库**:其上游自身不提供 mcpp 支持(如 cJSON、Eigen、nlohmann),由本仓以 `compat` 形态适配。 - **(b) 基于 mcpp 开发的库**:其上游已是 mcpp 工程(自带 `mcpp.toml`,可由 `mcpp emit xpkg` 产出描述符,且具备自有 - release),仅需登记进索引(如 `mcpplibs.*`、`tensorvia-cpu`)。此类库通常采用 **Form A**,描述符只声明元数据与 + release),仅需登记进索引(如 `mcpplibs.*`、`aimol.tensorvia`)。此类库通常采用 **Form A**,描述符只声明元数据与 下载地址,无需内联构建信息。 本流程不适用于修改 mcpp 本体、修改 xlings 引擎或纯文档变更,上述内容不在本仓范围内。 @@ -43,7 +43,7 @@ description: Use when adding a new third-party library/package to the mcpp-index 1. **调研来源与形态**(决定模板,为最关键步骤)。 - 首先判定来源:属于 (a) 第三方上游库,还是 (b) 基于 mcpp 开发的库。 - 对 (b),形态已确定(Form A 模块库),版本与 release 由上游提供,因此本步骤较为简单:可直接采用上游 - `mcpp emit xpkg` 的描述符,或参照 `pkgs/t/tensorvia-cpu.lua` 编写;工作重心在镜像、登记与验证。 + `mcpp emit xpkg` 的描述符,或参照 `pkgs/t/tensorvia.lua` 编写;工作重心在镜像、登记与验证。 - 对 (a),需按下文判定形态。 - 确定上游仓库与**最新 tag/版本**(`git ls-remote --tags ` 配合 `sort -V | tail`;须注意大版本跳跃, 如 Eigen 由 3.4 跃迁至 5.x)。 diff --git a/.xpkgindex/cache/github.json b/.xpkgindex/cache/github.json index c7cdc1f3..a22961ee 100644 --- a/.xpkgindex/cache/github.json +++ b/.xpkgindex/cache/github.json @@ -1,20 +1,5 @@ { "entries": { - "https://api.github.com/repos/Aimol-l/Tensorvia-cpu": { - "at": 1786040367, - "body": { - "description": "多后端张量库Tensorvia的CPU 后端,移植到纯 C++23 模块化设计,使用mcpp构建。", - "homepage": "", - "language": "C++", - "license": "MIT", - "owner": "Aimol-l", - "owner_avatar": "https://avatars.githubusercontent.com/u/56304358?v=4", - "owner_url": "https://github.com/Aimol-l", - "slug": "Aimol-l/Tensorvia-cpu", - "stars": 3, - "topics": [] - } - }, "https://api.github.com/repos/ArthurSonzogni/FTXUI": { "at": 1786040374, "body": { @@ -1082,40 +1067,6 @@ ] } }, - "https://raw.githubusercontent.com/Aimol-l/Tensorvia-cpu/v0.1.1/mcpp.toml": { - "at": 1786040356, - "body": { - "deps": [], - "description": "CPU backend of Tensorvia, ported to C++23 modules", - "language": "c++23", - "license": "MIT", - "modules": [ - "tensorvia" - ], - "modules_path": "src/tensorvia.cppm", - "modules_source": "export", - "name": "tensorvia-cpu", - "namespace": "", - "platforms": [ - "linux", - "macos", - "windows" - ], - "sources": [ - "src/tensorvia.cppm" - ], - "targets": { - "tensorvia-cpu": { - "kind": "lib" - } - }, - "version": "0.1.1" - } - }, - "https://raw.githubusercontent.com/Aimol-l/Tensorvia-cpu/v0.1.1/src/tensorvia.cppm": { - "at": 1786040356, - "body": "tensorvia" - }, "https://raw.githubusercontent.com/Sunrisepeak/opencv-m/v0.0.10/mcpp.toml": { "at": 1786040363, "body": { diff --git a/.xpkgindex/plugins/mcpp.py b/.xpkgindex/plugins/mcpp.py index 5f6a9769..68263b98 100644 --- a/.xpkgindex/plugins/mcpp.py +++ b/.xpkgindex/plugins/mcpp.py @@ -110,7 +110,7 @@ def _t(en: str, zh: str, hant: str) -> Dict[str, str]: _IMPORT_RE = re.compile(r"^\s*import\s+([A-Za-z_][\w.]*)\s*;", re.M) _INCLUDE_RE = re.compile(r"^\s*#include\s+([<\"][^>\"]+[>\"])", re.M) _TAG_RE = re.compile(r"/archive/refs/tags/(.+?)\.(?:tar\.gz|zip|tgz)$") -# Release assets carry the tag in the path instead — `tensorvia-cpu` publishes +# Release assets carry the tag in the path instead — `aimol.tensorvia` publishes # that way, and matching only archive URLs left it with no upstream data. _RELEASE_TAG_RE = re.compile(r"/releases/download/([^/]+)/") _IMPORT_IN_TEXT = re.compile(r"\bimport\s+([A-Za-z_][\w.]*)\s*;") @@ -176,7 +176,7 @@ def _project_manifest(text: str) -> Dict[str, Any]: sources = [str(s) for s in sources] if isinstance(sources, list) else [] # `[lib] path = "src/x.cppm"` is the other way a manifest names its - # library — tensorvia-cpu uses it instead of `[targets.x]`, and reading + # library — aimol.tensorvia uses it instead of `[targets.x]`, and reading # only one shape left that package with no upstream data at all. lib = data.get("lib") or {} lib_path = str(lib.get("path") or "") diff --git a/docs/cn-mirror.md b/docs/cn-mirror.md index 13c28d9c..32fb14b7 100644 --- a/docs/cn-mirror.md +++ b/docs/cn-mirror.md @@ -33,7 +33,7 @@ fallback is a plain-string url (upstream release only) — lint imposes no mirro ``` - CN users fall back to the upstream source: slower to reach, but functionally unaffected. -- Existing precedent: `pkgs/t/tensorvia-cpu.lua` (a user's own mcpp library, no CN mirror, a single upstream string +- Existing precedent: `pkgs/t/tensorvia.lua` (a user's own mcpp library, no CN mirror, a single upstream string url on all three platforms). - Later, once access is granted or a maintainer supplies the mirror, that version's `url` can be rewritten into a `{ GLOBAL=…, CN=… }` table (the sha256 stays the same). diff --git a/docs/descriptor-examples.md b/docs/descriptor-examples.md index 4370905b..e00b21f6 100644 --- a/docs/descriptor-examples.md +++ b/docs/descriptor-examples.md @@ -11,7 +11,7 @@ For descriptor templates see [package-types.md](package-types.md). | Shape | Examples | |------|------| -| Native module library (Form A) | [`mcpplibs.xpkg`](../pkgs/x/xpkg.lua) · [`mcpplibs.tinyhttps`](../pkgs/t/tinyhttps.lua) · [`tensorvia-cpu`](../pkgs/t/tensorvia-cpu.lua) · [`ffmpeg`](../pkgs/f/ffmpeg.lua) (module layer; sources compiled directly through `compat.ffmpeg`) · [`opencv`](../pkgs/o/opencv.opencv.lua) (single repository: the module layer and the full OpenCV 5 source build both live in the package, and only this descriptor stays on the index side) · [`mcpplibs.grpc`](../pkgs/g/grpc.lua) (gRPC 1.83.0 — the one library here that CANNOT be a compat descriptor: upstream publishes no self-contained source artifact, its tag archive carrying abseil/protobuf/re2/boringssl/zlib as empty submodule placeholders, so [grpc-m](https://github.com/mcpplibs/grpc-m)'s release tarball IS that artifact. It vendors only gRPC's own source and takes the five dependencies from this index, so a consumer that also uses protobuf links one copy rather than two) | +| Native module library (Form A) | [`mcpplibs.xpkg`](../pkgs/x/xpkg.lua) · [`mcpplibs.tinyhttps`](../pkgs/t/tinyhttps.lua) · [`aimol.tensorvia`](../pkgs/t/tensorvia.lua) · [`ffmpeg`](../pkgs/f/ffmpeg.lua) (module layer; sources compiled directly through `compat.ffmpeg`) · [`opencv`](../pkgs/o/opencv.opencv.lua) (single repository: the module layer and the full OpenCV 5 source build both live in the package, and only this descriptor stays on the index side) · [`mcpplibs.grpc`](../pkgs/g/grpc.lua) (gRPC 1.83.0 — the one library here that CANNOT be a compat descriptor: upstream publishes no self-contained source artifact, its tag archive carrying abseil/protobuf/re2/boringssl/zlib as empty submodule placeholders, so [grpc-m](https://github.com/mcpplibs/grpc-m)'s release tarball IS that artifact. It vendors only gRPC's own source and takes the five dependencies from this index, so a consumer that also uses protobuf links one copy rather than two) | | Form A whose consumer deps must be written by hand | [`huxerui.huxerui`](../pkgs/h/huxerui.huxerui.lua) (HuxerUI declares its GTK4 stack on the TARGET axis, which is the form mcpp recommends and which a descriptor structurally cannot carry — three platform blocks, and a cfg selector is not a platform. `mcpp emit xpkg` says so and emits empty `deps`, so the 36-entry closure is transcribed into `xpm.linux.deps` at PLATFORM level (a per-version `deps` is inert). Its `licenses`/`repo` also deliberately disagree with what emit produces) | | Native multi-module library with feature-scoped sources | [`gzj-creator.galay`](../pkgs/g/gzj-creator.galay.lua) (Galay 5.0.2 — the upstream Form-A manifest exposes `galay.utils` and `galay.kernel` by default, while SSL, HTTP, database, RPC, MCP, and tracing modules stay behind named features and their corresponding dependencies. The index keeps the upstream manifest intact and tests the default module surface on Unix.) | | C-source compat (with `features`) | [`compat.cjson`](../pkgs/c/compat.cjson.lua) · [`compat.zlib`](../pkgs/c/compat.zlib.lua) · [`compat.zlib-ng`](../pkgs/c/compat.zlib-ng.lua) (zlib-ng 2.3.3 in its zlib-compatible form — CMake's `WITH_RUNTIME_CPU_DETECTION=OFF` build, so each function binds at compile time to the best path the architecture's baseline guarantees: NEON on aarch64, SSE2 on x86_64, which an ok image needs because openkal names no processor feature. The architecture sources gate themselves and a generated header sets the gate from the compiler's own macro; the one source without a gate is compiled through a generated forwarder. install() derives `zlib.h`, `zconf.h`, `zlib_name_mangling.h` and `gzread_mangle.h` from the tarball's templates, writing zconf.h's `HAVE_UNISTD_H` line as `#if !defined(_WIN32)` so the library and every consumer read one text. The test reads a stream madler's zlib wrote) · [`compat.hiredis`](../pkgs/c/compat.hiredis.lua) (the classic 1.2.0 — a 7-TU C build whose flat tarball headers get `hiredis/`-prefixed wrapper headers via `generated_files`, so consumers write `#include ` exactly like upstream's install layout) · [`compat.sqlite3`](../pkgs/c/compat.sqlite3.lua) (plain C-source, no features: the single `sqlite3.c` amalgamation; 3.45.3, the final maintenance release of the most widely deployed 3.45.x line) · [`compat.libuv`](../pkgs/c/compat.libuv.lua) (libuv 1.48.0 — the per-OS source sets transcribed from upstream's CMakeLists, because a `src/unix/*.c` glob would compile every OS's backend at once; linux/macos get explicit unix subsets, windows globs `src/win/*.c`) · [`compat.xxhash`](../pkgs/c/compat.xxhash.lua) (one TU, one header, no features at all — the interesting decision is what is NOT compiled: `xxh_x86dispatch.c` selects an AVX2/AVX512 path at RUNTIME and needs per-file `-mavx2` plus `XXH_X86DISPATCH` at every call site, so the package ships the flagless SSE2 baseline instead. Nor is the header-only `XXH_INLINE_ALL` mode chosen: it re-emits the implementation in every TU that hashes anything, which is the right trade only when there is exactly one such TU — something a package cannot know) · [`compat.quickjs-ng`](../pkgs/c/compat.quickjs-ng.lua) (QuickJS-ng 0.17.0 — upstream's four engine TUs and nothing else. `quickjs-libc.c`, the optional standard library that gives scripts files, the environment, timers and child processes, is NOT compiled, so an embedder gets an engine with no host access unless it adds its own. The tarball keeps `quickjs.h` beside private headers with generic names (`list.h`, `cutils.h`), so a `generated_files` forwarder is the only include directory, as in compat.libaio) | diff --git a/docs/zh/cn-mirror.md b/docs/zh/cn-mirror.md index 3758826b..4f0a8380 100644 --- a/docs/zh/cn-mirror.md +++ b/docs/zh/cn-mirror.md @@ -31,7 +31,7 @@ lint 对纯字符串 url 不施加镜像约束: ``` - CN 用户将回退至上游源,访问较慢但功能不受影响。 -- 既有先例:`pkgs/t/tensorvia-cpu.lua`(用户自有 mcpp 库,无 CN 镜像,三平台均使用上游单一字符串 url)。 +- 既有先例:`pkgs/t/tensorvia.lua`(用户自有 mcpp 库,无 CN 镜像,三平台均使用上游单一字符串 url)。 - 后续在获得权限、或由维护者补充镜像后,可将该版本的 `url` 改写为 `{ GLOBAL=…, CN=… }` 表(sha256 保持不变)。 如需表达“GLOBAL 与 CN 均指向上游”,应采用上述单一字符串写法,而不应写成 `{ GLOBAL=x, CN=x }` 表(其无法通过 diff --git a/docs/zh/descriptor-examples.md b/docs/zh/descriptor-examples.md index 35aabd75..a52e70fd 100644 --- a/docs/zh/descriptor-examples.md +++ b/docs/zh/descriptor-examples.md @@ -10,7 +10,7 @@ | 形态 | 示例 | |------|------| -| 原生模块库(Form A) | [`mcpplibs.xpkg`](../../pkgs/x/xpkg.lua) · [`mcpplibs.tinyhttps`](../../pkgs/t/tinyhttps.lua) · [`tensorvia-cpu`](../../pkgs/t/tensorvia-cpu.lua) · [`ffmpeg`](../../pkgs/f/ffmpeg.lua)(模块层,源码经 `compat.ffmpeg` 直编) · [`opencv`](../../pkgs/o/opencv.opencv.lua)(单仓库:模块层与 OpenCV 5 全源码构建同在包内,索引侧只留本描述符) · [`mcpplibs.grpc`](../../pkgs/g/grpc.lua)(gRPC 1.83.0 —— 本索引里唯一**无法**做成 compat 描述符的库:上游不发布任何自包含源码产物,其 tag 归档里 abseil/protobuf/re2/boringssl/zlib 全是空 submodule 占位,因此 [grpc-m](https://github.com/mcpplibs/grpc-m) 的 release tarball 才是那个产物。它只 vendor gRPC 自己的源码,五个依赖全取自本索引,故同时直接使用 protobuf 的消费者链进去的是同一份而非两份)| +| 原生模块库(Form A) | [`mcpplibs.xpkg`](../../pkgs/x/xpkg.lua) · [`mcpplibs.tinyhttps`](../../pkgs/t/tinyhttps.lua) · [`aimol.tensorvia`](../../pkgs/t/tensorvia.lua) · [`ffmpeg`](../../pkgs/f/ffmpeg.lua)(模块层,源码经 `compat.ffmpeg` 直编) · [`opencv`](../../pkgs/o/opencv.opencv.lua)(单仓库:模块层与 OpenCV 5 全源码构建同在包内,索引侧只留本描述符) · [`mcpplibs.grpc`](../../pkgs/g/grpc.lua)(gRPC 1.83.0 —— 本索引里唯一**无法**做成 compat 描述符的库:上游不发布任何自包含源码产物,其 tag 归档里 abseil/protobuf/re2/boringssl/zlib 全是空 submodule 占位,因此 [grpc-m](https://github.com/mcpplibs/grpc-m) 的 release tarball 才是那个产物。它只 vendor gRPC 自己的源码,五个依赖全取自本索引,故同时直接使用 protobuf 的消费者链进去的是同一份而非两份)| | 消费者依赖须手写的 Form A | [`huxerui.huxerui`](../../pkgs/h/huxerui.huxerui.lua)(HuxerUI 把 GTK4 栈声明在 TARGET 轴上 —— 这是 mcpp 推荐的写法,而描述符在结构上承载不了:只有三个平台块,cfg 选择器不是平台。`mcpp emit xpkg` 会如实说明并输出空 `deps`,因此 36 项闭包被手工抄进 PLATFORM 级的 `xpm.linux.deps`(按版本写的 `deps` 不生效)。它的 `licenses`/`repo` 也刻意与 emit 的产出不同) | | 原生多模块库(按 feature 管理源码) | [`gzj-creator.galay`](../../pkgs/g/gzj-creator.galay.lua)(Galay 5.0.2 —— 上游 Form-A manifest 默认提供 `galay.utils` 与 `galay.kernel`,SSL、HTTP、数据库、RPC、MCP、tracing 等模块及其依赖按具名 feature 开启。索引保持上游 manifest 原样,Unix 成员测试默认模块表面)| | C 源码 compat(含 `features`) | [`compat.cjson`](../../pkgs/c/compat.cjson.lua) · [`compat.zlib`](../../pkgs/c/compat.zlib.lua) · [`compat.zlib-ng`](../../pkgs/c/compat.zlib-ng.lua)(zlib-ng 2.3.3 的 zlib 兼容形态 —— 即 CMake 的 `WITH_RUNTIME_CPU_DETECTION=OFF` 构建:每个函数在编译期绑定到该架构基线保证的最优实现,aarch64 为 NEON,x86_64 为 SSE2;ok 映像需要这种形态,因为 openkal 不提供处理器特性。架构源文件自带门控,由生成的配置头按编译器自身的宏设置;唯一没有门控的源文件经生成的转发文件编译。install() 由发布包中的模板生成 `zlib.h`、`zconf.h`、`zlib_name_mangling.h` 与 `gzread_mangle.h`,并把 zconf.h 的 `HAVE_UNISTD_H` 一行写为 `#if !defined(_WIN32)`,使库与每个使用者读同一份文本。测试读取 madler zlib 写出的流)· [`compat.hiredis`](../../pkgs/c/compat.hiredis.lua)(经典 1.2.0 —— 7 个 C TU;tarball 平铺头经 `generated_files` 补 `hiredis/` 前缀薄包装头,消费者可写 `#include `,与上游安装布局一致) · [`compat.sqlite3`](../../pkgs/c/compat.sqlite3.lua)(纯 C 源码、无 feature:单一 `sqlite3.c` amalgamation;3.45.3,部署最广的 3.45.x 线) · [`compat.libuv`](../../pkgs/c/compat.libuv.lua)(libuv 1.48.0 —— 逐 OS 源清单转录自上游 CMakeLists,因为 `src/unix/*.c` 通配会一次编进所有 OS 的后端;linux/macos 显式列 unix 子集,windows 用 `src/win/*.c` glob) · [`compat.xxhash`](../../pkgs/c/compat.xxhash.lua)(单 TU、单头、无 feature —— 值得说的是**没有**编译什么:`xxh_x86dispatch.c` 在运行期选择 AVX2/AVX512 路径,需要 per-file `-mavx2` 并要求每个调用点定义 `XXH_X86DISPATCH`,故本包只出无需任何 flag 的 SSE2 基线。也没有选 header-only 的 `XXH_INLINE_ALL` 模式:它会在每个做哈希的 TU 里重新展开整份实现,那只有在「恰好只有一个这样的 TU」时才划算 —— 而这件事包本身无从知道) · [`compat.quickjs-ng`](../../pkgs/c/compat.quickjs-ng.lua)(QuickJS-ng 0.17.0 —— 只编上游的四个引擎 TU。可选标准库 `quickjs-libc.c`(给脚本文件、环境变量、定时器与子进程能力)不编,嵌入方拿到的引擎碰不到宿主,除非自己提供。tarball 把 `quickjs.h` 和 `list.h`、`cutils.h` 这类名字很通用的私有头放在一起,所以 include 路径上只放一个 `generated_files` 转发头,与 compat.libaio 同法) | diff --git a/mcpp.toml b/mcpp.toml index 84489f03..c41e6266 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -270,6 +270,7 @@ members = [ "tests/examples/openlifa.openas", "tests/examples/openlifa.openmui", "tests/examples/os", + "tests/examples/tensorvia", ] # ── The index redirect, hoisted to the workspace root ─────────────────── diff --git a/pkgs/c/compat.spdlog.lua b/pkgs/c/compat.spdlog.lua index 7a504370..00109972 100644 --- a/pkgs/c/compat.spdlog.lua +++ b/pkgs/c/compat.spdlog.lua @@ -37,7 +37,7 @@ -- -- No CN mirror yet: `url` is a plain string (upstream GitHub release only), the -- documented fallback when there is no mcpp-res write access (docs/cn-mirror.md; --- precedent: pkgs/t/tensorvia-cpu.lua). CN users fall back to the upstream +-- precedent: pkgs/t/tensorvia.lua). CN users fall back to the upstream -- source. A maintainer can later rewrite each `url` to a { GLOBAL, CN } table -- (sha256 unchanged) once the gitcode mcpp-res/spdlog mirror exists. package = { diff --git a/pkgs/t/tensorvia-cpu.lua b/pkgs/t/tensorvia-cpu.lua deleted file mode 100644 index 22f580a5..00000000 --- a/pkgs/t/tensorvia-cpu.lua +++ /dev/null @@ -1,31 +0,0 @@ --- AUTO-GENERATED by `mcpp emit xpkg`. Do not edit by hand. --- Source: mcpp.toml @ v0.2.3 -package = { - spec = "1", - name = "tensorvia-cpu", - description = "CPU backend of Tensorvia, ported to C++23 modules", - licenses = {"MIT"}, - repo = "https://github.com/Aimol-l/Tensorvia-cpu", - type = "package", - namespace = "aimol", - maintainers = {"Aimol-l"}, - - extensions = { - autoupdate = { - tag = "v${version}", - url = "https://github.com/Aimol-l/Tensorvia-cpu/releases/download/${tag}/tensorvia-cpu-${version}.tar.gz", - }, - }, - - xpm = { - linux = { - ['0.2.3'] = { url = "https://github.com/Aimol-l/Tensorvia-cpu/releases/download/v0.2.3/tensorvia-cpu-0.2.3.tar.gz", sha256 = "8476d2fa27eb47a8e9d50b3ef3b974cad8923f4fdebd4d3f6d45355cc6a534f7" }, - }, - macosx = { - ['0.2.3'] = { url = "https://github.com/Aimol-l/Tensorvia-cpu/releases/download/v0.2.3/tensorvia-cpu-0.2.3.tar.gz", sha256 = "8476d2fa27eb47a8e9d50b3ef3b974cad8923f4fdebd4d3f6d45355cc6a534f7" }, - }, - windows = { - ['0.2.3'] = { url = "https://github.com/Aimol-l/Tensorvia-cpu/releases/download/v0.2.3/tensorvia-cpu-0.2.3.tar.gz", sha256 = "8476d2fa27eb47a8e9d50b3ef3b974cad8923f4fdebd4d3f6d45355cc6a534f7" }, - }, - }, -} diff --git a/pkgs/t/tensorvia.lua b/pkgs/t/tensorvia.lua new file mode 100644 index 00000000..b7b6cd0e --- /dev/null +++ b/pkgs/t/tensorvia.lua @@ -0,0 +1,44 @@ +-- aimol.tensorvia — C++23 module tensor library with CPU, Vulkan, CUDA and SYCL +-- backends (`import tensorvia;`). +-- +-- Emitted by `mcpp emit xpkg` from the package's own manifest @ v0.3.0, then +-- hand-maintained: `name` is the single atomic segment with the namespace +-- beside it, `maintainers` stays here (mcpp.toml has no such key), and the +-- `mcpp` pointer is the literal path rather than a `*/` glob. Those edits are +-- deliberate, so the "AUTO-GENERATED / do not edit by hand" banner is not +-- carried on this file. +package = { + spec = "1", + namespace = "aimol", + name = "tensorvia", + description = "Tensorvia: C++23 module tensor library with CPU, Vulkan, CUDA and SYCL backends", + licenses = {"MIT"}, + repo = "https://github.com/Aimol-l/Tensorvia", + type = "package", + maintainers = {"Aimol-l"}, + + extensions = { + autoupdate = { + tag = "v${version}", + url = "https://github.com/Aimol-l/Tensorvia/releases/download/${tag}/tensorvia-${version}.tar.gz", + }, + }, + + xpm = { + linux = { + ['0.3.0'] = { url = "https://github.com/Aimol-l/Tensorvia/releases/download/v0.3.0/tensorvia-0.3.0.tar.gz", sha256 = "d01e36f09db56cea1470425dbb0e0bbeb9d9bb9cee184b1c6d3d51760518fb1f" }, + }, + macosx = { + ['0.3.0'] = { url = "https://github.com/Aimol-l/Tensorvia/releases/download/v0.3.0/tensorvia-0.3.0.tar.gz", sha256 = "d01e36f09db56cea1470425dbb0e0bbeb9d9bb9cee184b1c6d3d51760518fb1f" }, + }, + windows = { + ['0.3.0'] = { url = "https://github.com/Aimol-l/Tensorvia/releases/download/v0.3.0/tensorvia-0.3.0.tar.gz", sha256 = "d01e36f09db56cea1470425dbb0e0bbeb9d9bb9cee184b1c6d3d51760518fb1f" }, + }, + }, + + -- Form A: the tarball carries the library's own manifest at its root; + -- modules, features and the build program are declared there. The release + -- asset is `git archive v0.3.0` with no `-/` wrap layer, so the + -- pointer is the literal path (same as gcc.libstdcxx). + mcpp = "mcpp.toml", +} diff --git a/tests/examples/tensorvia/mcpp.toml b/tests/examples/tensorvia/mcpp.toml new file mode 100644 index 00000000..b1efb7c7 --- /dev/null +++ b/tests/examples/tensorvia/mcpp.toml @@ -0,0 +1,17 @@ +# aimol.tensorvia test project: the module imports, CPU tensors round-trip +# through ops, and reductions read back the scalar the API contract promises. +# No accelerator is selected here, so this member exercises exactly the CPU +# artifact an unqualified consumer gets; the device lanes need a GPU and their +# payloads stay unpulled in CI. +[package] +name = "tensorvia-tests" +version = "0.1.0" + +[indices] +# A member-level [indices] REPLACES the inherited table: the root's `compat` +# alias cannot resolve `aimol.*`. Point the `aimol` alias at this repo instead +# (the same shape taskflow-module uses for `taskflow`). +aimol = { path = "../../.." } + +[dev-dependencies] +aimol.tensorvia = "0.3.0" diff --git a/tests/examples/tensorvia/tests/smoke.cpp b/tests/examples/tensorvia/tests/smoke.cpp new file mode 100644 index 00000000..b1b5004f --- /dev/null +++ b/tests/examples/tensorvia/tests/smoke.cpp @@ -0,0 +1,35 @@ +// aimol.tensorvia smoke: import the module, run CPU ops, and read back +// scalars. Every check can fail; a non-zero exit is the signal. +import std; +import tensorvia; + +namespace { + +int failures = 0; + +void check(bool ok, std::string_view what) { + if (!ok) { + std::println("FAIL: {}", what); + ++failures; + } +} + +} // namespace + +int main() { + const Tensor ones = ops::Ones({4, 4}, DataType::FLOAT32); + check(ops::Sum(ones).item() == 16.0f, "Sum(Ones(4x4)) == 16"); + + const Tensor twos = ops::Add(ones, ones); + check(ops::Sum(twos).item() == 32.0f, "Sum(Ones+Ones) == 32"); + + // Add(tensor, scalar) then Relu: the negative half clamps to zero. + const Tensor clamped = ops::Relu(ops::Add(ones, -3.0f)); + check(ops::Sum(clamped).item() == 0.0f, "Relu(1-3) == 0"); + + // The library's version constant reaches a string_view consumer. + check(!tensorvia::version.empty(), "version is non-empty"); + + std::println("tensorvia smoke: {} failures", failures); + return failures == 0 ? 0 : 1; +}