Skip to content
Merged
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
16 changes: 16 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1456,6 +1456,22 @@ jobs:
mine="${kept# }"
fi

# `mp-units-module`: the reverse case. `mpusz.mp-units` requires
# libc++ on linux because GCC 16.1 cannot import its modules
# (`recursive lazy load`, mpusz/mp-units#717), so the gcc leg would
# only reach that refusal. Lift once xim ships a GCC that works.
if [ "${{ matrix.platform }}" = "linux" ] && [ "${{ matrix.toolchain }}" = "default" ]; then
kept=""
for m in $mine; do
case "$m" in
mp-units-module)
echo "skipping '$m' on the gcc leg: the package requires libc++" ;;
*) kept="$kept $m" ;;
esac
done
mine="${kept# }"
fi

echo "MEMBERS=$mine" >> "$GITHUB_ENV"
echo "shard ${{ matrix.shard }}/${{ matrix.shards }}: ${mine:-<none>}"

Expand Down
1 change: 1 addition & 0 deletions docs/descriptor-examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,4 @@ in the [root README](../README.md#reference-examples).
| C++23 module, upstream's own unit | [`khronos.vulkan-hpp`](../pkgs/k/khronos.vulkan-hpp.lua) (Vulkan-Hpp 1.4.357.0 — Khronos generates `vulkan.cppm` / `vulkan_video.cppm` into every Vulkan-Headers release, so `sources` names the two units and NOTHING is authored here; the payload is the same tarball, URL and sha256 as `compat.vulkan-headers`, which is what makes the module and the headers it includes impossible to skew. `import_std = true` is forced by the unit's own unconditional `export import std;`. No `include_dirs`: the headers arrive with the `compat.vulkan` dependency, which is also what satisfies the STATIC dispatcher's direct calls at link — depending on headers alone gives a package that compiles and then fails at every consumer's link. Module names stay upstream's `vulkan` / `vulkan_video`, never `khronos.vulkan`. The second unit `import`s the first and mcpp orders the pair from the scan, which `tests/examples/vulkan-hpp-module/tests/video.cpp` is the regression for) |
| C++23 module, upstream's CPU partitions | [`taskflow.taskflow`](../pkgs/t/taskflow.taskflow.lua) (Taskflow 4.1.0, `import tf;`; reuses the four upstream CPU module units and omits the competing CUDA entry point. The checked install hook removes two nonexistent exports, moves the umbrella include/version export into core and imports core first for GCC, and supplies `<algorithm>` to utility for libc++. Only three module files are patched; headers and scheduler implementation stay upstream. No fork; consumers use `tf::version()` because macros are not exported) |
| C++23 module, upstream asynchronous logging | [`odygrd.quill`](../pkgs/o/odygrd.quill.lua) (Quill 13.0.0, upstream experimental `quill` module; the checked install hook generates `.cppm` from `src/quill.cc`, guards x86 intrinsics by target architecture and includes Apple Mach headers in the global module fragment. Consumers use `import std; import quill;` and the macro-free API, or define `QUILL_USE_MODULE` and include `quill/LogMacros.h` for logging macros. Bundled fmt needs no separate dependency; Linux links with `-pthread`. Multi-TU logger identity, worker-thread output, formatting and filtering are tested) |
| C++23 modules, upstream units | [`mpusz.mp-units`](../pkgs/m/mpusz.mp-units.lua) (2.5.0; upstream `mp_units.core`, `mp_units.systems` and `mp_units`, copied verbatim to `.cppm` by the install hook so Clang treats them as interfaces. `import std`, `std::format`, runtime contracts off, experimental natural units off. Linux requires libc++ (LLVM): GCC 16.1 fails to import the module with `recursive lazy load`, mpusz/mp-units#717) |
1 change: 1 addition & 0 deletions docs/zh/descriptor-examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,4 @@
| C++23 module,上游自带单元 | [`khronos.vulkan-hpp`](../../pkgs/k/khronos.vulkan-hpp.lua)(Vulkan-Hpp 1.4.357.0 —— Khronos 把 `vulkan.cppm` / `vulkan_video.cppm` 生成进每个 Vulkan-Headers release,所以 `sources` 点名这两个单元即可,本仓**不写一行**包装体;载荷与 `compat.vulkan-headers` 是同一份 tarball、同一个 URL 与 sha256,这让模块与它 include 的头不可能错配。`import_std = true` 由单元自身无条件的 `export import std;` 决定。不声明 `include_dirs`:头随 `compat.vulkan` 依赖到达,而该依赖同时满足静态 dispatcher 在链接期的直接调用 —— 只依赖头会得到一个「能编译、每个消费者都链接失败」的包。模块名保持上游的 `vulkan` / `vulkan_video`,绝不写成 `khronos.vulkan`。第二个单元 `import` 第一个,顺序由 mcpp 扫描决定,`tests/examples/vulkan-hpp-module/tests/video.cpp` 就是这条的回归)|
| C++23 module,上游 CPU 分区 | [`taskflow.taskflow`](../../pkgs/t/taskflow.taskflow.lua)(Taskflow 4.1.0,`import tf;`;复用上游四个 CPU 模块单元,排除提供同名主模块的 CUDA 入口。安装钩子逐项校验匹配次数:移除两个不存在的导出,将总头文件及版本导出移至 core 并优先导入 core 以兼容 GCC,为 utility 补 `<algorithm>` 以兼容 libc++。仅适配三个模块文件,头文件和调度实现保持上游原样,无独立 fork;宏不随模块导出,版本查询使用 `tf::version()`) |
| C++23 module,上游异步日志 | [`odygrd.quill`](../../pkgs/o/odygrd.quill.lua)(Quill 13.0.0,上游实验性 `quill` 模块;安装钩子以 `src/quill.cc` 生成 `.cppm`,精确适配 x86 intrinsic 的架构条件与 Apple Mach 头的全局模块归属。消费者使用 `import std; import quill;` 和无宏 API,或定义 `QUILL_USE_MODULE` 并包含 `quill/LogMacros.h` 使用日志宏。自带 fmt,无需额外依赖;Linux 链接使用 `-pthread`。测试覆盖多 TU logger 身份、工作线程输出、格式化和过滤) |
| C++23 模块,上游自带单元 | [`mpusz.mp-units`](../../pkgs/m/mpusz.mp-units.lua)(2.5.0;复用 `mp_units.core`、`mp_units.systems`、`mp_units`,安装钩子将接口原样复制为 `.cppm` 供 Clang 识别。使用 `import std` 与 `std::format`,关闭运行时契约和实验性自然单位。Linux 要求 libc++(LLVM):GCC 16.1 导入模块时报 `recursive lazy load`,见 mpusz/mp-units#717) |
1 change: 1 addition & 0 deletions mcpp.toml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ members = [
"tests/examples/sqlitecpp",
"tests/examples/taskflow-module",
"tests/examples/quill-module",
"tests/examples/mp-units-module",
"tests/examples/tinyhttps",
"tests/examples/usockets",
"tests/examples/opencl",
Expand Down
77 changes: 77 additions & 0 deletions pkgs/m/mpusz.mp-units.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package = {
spec = "1",
namespace = "mpusz",
name = "mp-units",
description = "Physical quantities and units through the upstream mp_units C++ modules",
licenses = { "MIT" },
repo = "https://github.com/mpusz/mp-units",
type = "package",
xpm = {
linux = {
["2.5.0"] = {
url = "https://github.com/mpusz/mp-units/archive/refs/tags/v2.5.0.tar.gz",
sha256 = "a6bd48bee699f11f0ed5b04b8c5006d15f76e6d898e058db3880554d2e47a400",
},
},
macosx = {
["2.5.0"] = {
url = "https://github.com/mpusz/mp-units/archive/refs/tags/v2.5.0.tar.gz",
sha256 = "a6bd48bee699f11f0ed5b04b8c5006d15f76e6d898e058db3880554d2e47a400",
},
},
windows = {
["2.5.0"] = {
url = "https://github.com/mpusz/mp-units/archive/refs/tags/v2.5.0.tar.gz",
sha256 = "a6bd48bee699f11f0ed5b04b8c5006d15f76e6d898e058db3880554d2e47a400",
},
},
},
mcpp = {
language = "c++23",
import_std = true,
modules = { "mp_units.core", "mp_units.systems", "mp_units" },
include_dirs = { "*/src/core/include", "*/src/systems/include" },
-- 上游 import std 配置:标准格式化、关闭运行时契约;自然单位为实验特性,LLVM 22 下约束失败
defines = {
"MP_UNITS_IMPORT_STD",
"MP_UNITS_API_STD_FORMAT=1",
"MP_UNITS_API_CONTRACTS=0",
"MP_UNITS_API_NATURAL_UNITS=0",
},
sources = {
"*/src/core/mp-units-core.cppm",
"*/src/systems/mp-units-systems.cppm",
"*/src/mp-units.cppm",
},
-- 两个上游接口的 std 导入受 MP_UNITS_IMPORT_STD 守卫
scan_overrides = {
["*/src/core/mp-units-core.cppm"] = {
provides = { "mp_units.core" }, imports = { "std" },
},
["*/src/systems/mp-units-systems.cppm"] = {
provides = { "mp_units.systems" }, imports = { "mp_units.core", "std" },
},
},
targets = { ["mp-units"] = { kind = "lib" } },
deps = {},
linux = {
-- 暂不支持 GCC:GCC 16.1 导入该模块时报 recursive lazy load(mpusz/mp-units#717)
requires = { "mcpp:c++-abi=libc++" },
},
},
}

import("xim.libxpkg.pkginfo")

function install()
local wrap = "mp-units-" .. pkginfo.version()
-- 上游接口以 .cpp 命名,复制为 .cppm 供 Clang 识别为模块接口
for _, relative in ipairs({ "src/core/mp-units-core", "src/systems/mp-units-systems", "src/mp-units" }) do
os.cp(path.join(wrap, relative .. ".cpp"), path.join(wrap, relative .. ".cppm"))
end
local prefix = pkginfo.install_dir()
os.tryrm(prefix)
os.mkdir(prefix)
os.mv(wrap, path.join(prefix, wrap))
return true
end
9 changes: 9 additions & 0 deletions tests/examples/mp-units-module/mcpp.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "mp-units-module-tests"
version = "0.1.0"

[indices]
mpusz = { path = "../../.." }

[dependencies.mpusz]
mp-units = "2.5.0"
9 changes: 9 additions & 0 deletions tests/examples/mp-units-module/src/quantity_bridge.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import std;
import mp_units.core;
import mp_units.systems;

#include "quantity_bridge.h"

distance add_distance(distance left, distance right) {
return left + right;
}
5 changes: 5 additions & 0 deletions tests/examples/mp-units-module/src/quantity_bridge.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

using distance = mp_units::quantity<mp_units::si::metre, int>;

distance add_distance(distance left, distance right);
22 changes: 22 additions & 0 deletions tests/examples/mp-units-module/tests/units.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import std;
import mp_units;

#include "../src/quantity_bridge.h"

using namespace mp_units;
using namespace mp_units::si::unit_symbols;

template<class Left, class Right>
concept Addable = requires(Left left, Right right) { left + right; };

static_assert(1 * km == 1000 * m);
static_assert(!Addable<decltype(1 * m), decltype(1 * s)>);
static_assert((120 * km / (2 * h)).numerical_value_in(km / h) == 60);
static_assert(quantity{std::chrono::minutes{2}} == 120 * s);

int main() {
if (add_distance(20 * m, 22 * m) != 42 * m) return 1;
if (std::format("{}", 42 * m) != "42 m") return 2;
if (std::format("{}", 2 * ohm) != "2 \xce\xa9") return 3;
return 0;
}
Loading