Skip to content

Commit af923e5

Browse files
feat(pkgs): add compat.spdlog 1.17.0 (header-only + declarative compi… (#72)
* feat(pkgs): add compat.spdlog 1.17.0 (header-only + declarative compiled feature) spdlog is dual-modal: default header-only (self-contained via bundled fmt in FMT_HEADER_ONLY mode, no external fmt dep) and a precompiled mode gated on SPDLOG_COMPILED_LIB. The `compiled` feature declares the correct intent (sources = src/*.cpp + the SPDLOG_COMPILED_LIB interface define), but mcpp 0.0.91 does not yet compile a dependency's feature-gated sources — verified three ways (this package, compat.cjson's utils, compat.eigen's eigen_blas all leave feature sources uncompiled → link-time undefined reference). The feature's `defines` DO propagate to the consumer. So CI asserts the fully-working header-only mode; the compiled feature works unchanged once the engine links feature sources (same follow-up as eigen_blas). No CN mirror (no mcpp-res write access): plain-string upstream url per the docs/cn-mirror.md fallback (tensorvia-cpu precedent). Verified on mcpp 0.0.91 (GLOBAL): xpkg parse OK, `mcpp test -p spdlog` passes. * fix(spdlog): 修正引擎限制误判 + compiled 模态进 CI(mcpp 0.0.94) 初版把「feature sources 不编译」判为引擎级限制,是**误判**:该 bug 只影响 `mcpp test` 路径,`mcpp build` 一直是好的(7 个 src TU 全进 build.ninja、 二进制真跑)。三重佐证(spdlog/cjson/eigen)现象属实,但三次都只走了 test 一条路径 —— 本仓 CI 是 workspace/test 模型。 真因(mcpp/src/build/prepare.cppm):feature 源集解析被整段门在 `!includeDevDeps`,test 模式跳过 → 激活 feature 的 sources 从不加回构建图; 叠加 xpkg 的 `features.X.sources` 只落进 featureSources、从不进 base sources。 已由 mcpp#218 修复并发布 0.0.94(drop 仍只在 build 模式,add 两模式都做+去重)。 - 描述符 Lua **一行未改** —— `compiled` feature 的建模本来就是对的; 只把注释从「引擎不支持、请用 header-only」改为如实的「test 下需 ≥0.0.94」。 - 新增 workspace 成员 `tests/examples/spdlog-compiled/`:**compiled 模态进 CI**。 静态断言 SPDLOG_COMPILED_LIB 已定义 + SPDLOG_HEADER_ONLY 未定义(退化回 inline 路径是编译错误而非静默通过),再跑行为断言 —— 调用解析到 default_logger_raw / log_msg ctor / logger::log_it_ / bundled fmt vformat 等非 inline 符号,正是 feature sources 没编译时链不上的那批。 - CI pin 0.0.91 → 0.0.94;index floor `min_mcpp` 不动(它追踪描述符**语法**, 本描述符在 0.0.87 上就能解析;header-only 模态任何版本都可用)。 - 修 `tests/examples/spdlog/mcpp.toml` 里 `pkgs/s/` 陈旧路径 → `pkgs/c/`。 --------- Co-authored-by: sunrisepeak <x.d2learn.org@gmail.com>
1 parent 1db4153 commit af923e5

8 files changed

Lines changed: 366 additions & 5 deletions

File tree

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# 收录 spdlog 1.17.0 —— 形态判定、双模态与验证结论
2+
3+
日期:2026-07-15。对应描述符 `pkgs/c/compat.spdlog.lua`、示例 `tests/examples/spdlog/`
4+
CI 版本 mcpp 0.0.91,index floor `min_mcpp = 0.0.87`
5+
6+
## 1. 来源与形态
7+
8+
- 来源:(a) 第三方上游库 —— spdlog(https://github.com/gabime/spdlog)上游不提供
9+
mcpp 支持,由本仓以 `compat` 形态适配。
10+
- 最新 tag:`v1.17.0`(`git ls-remote --tags` 排序确认)。裸版本 `1.17.0`,
11+
下载 URL 保留上游 `.../v1.17.0.tar.gz` 拼写。
12+
- License:MIT
13+
- sha256:`d8862955c6d74e5846b3f580b1605d2428b11d97a410d86e2fb13e857cd3a744`
14+
(下载后重复计算两次,稳定)。
15+
- 源码布局:`include/spdlog/**`(全部头文件,含 `-inl.h` 实现单元与
16+
`fmt/bundled/` 内联版 {fmt})、`src/*.cpp`(7 个预编译库 TU)。
17+
- 形态判定:**header-only + source-gated feature**,与 `compat.eigen` 同类。
18+
spdlog 是 DUAL-MODAL:
19+
- 默认(不定义宏)走 header-only:`common.h` 在未定义 `SPDLOG_COMPILED_LIB`
20+
时打开 `SPDLOG_HEADER_ONLY`,头文件末尾 `#include "*-inl.h"` 把实现内联。
21+
bundled fmt 以 `FMT_HEADER_ONLY` 使用,**整包自包含,无需外部 fmt 依赖**
22+
- 预编译模态(定义 `SPDLOG_COMPILED_LIB`)改为编译 `src/*.cpp`;每个 src TU
23+
在缺少该宏时 `#error`。该宏是 **interface define**:必须同时到达库源与
24+
消费者头(否则消费者头走 inline,与 .a 符号重复/冲突)。
25+
26+
## 2. 描述符设计
27+
28+
header-only 骨架(`include_dirs = {"*/include"}` + anchor TU 提供可构建 lib
29+
target),外加一个声明式 `compiled` feature:
30+
31+
```lua
32+
features = {
33+
["compiled"] = {
34+
sources = { "*/src/*.cpp" },
35+
defines = { "SPDLOG_COMPILED_LIB" },
36+
},
37+
}
38+
```
39+
40+
## 3. 关键实证:feature sources 在 `mcpp test` 下不编译(mcpp ≤0.0.93 的 bug,0.0.94 已修)
41+
42+
> **修订(2026-07-15)**:本节初版结论「mcpp 0.0.91 引擎不编译 feature 门控的
43+
> sources」**是误判**,已由 mcpp#218 查清并修复。误判的成因值得记下来。
44+
45+
初版三重佐证如下:
46+
47+
| 实验 | feature | 现象 |
48+
|---|---|---|
49+
| spdlog | `compiled` | `src/*.cpp` 未编译 → 大量 `undefined reference` |
50+
| compat.cjson | `utils` | `cJSON_Utils.c` 未编译 → `undefined reference to cJSONUtils_*` |
51+
| compat.eigen | `eigen_blas` | `blas/*.cpp` 未编译 → `undefined reference to dgemm_` |
52+
53+
三例现象属实,但**三次都只走了 `mcpp test` 这一条路径**(本仓 CI 是 workspace/test
54+
模型),于是把一个**只影响 test 模式**的 bug 误读成了「引擎不支持 feature sources」。
55+
56+
**真因**(`mcpp/src/build/prepare.cppm`):feature 源集解析(drop + add)**整段**被门在
57+
`!includeDevDeps`,而 `mcpp test``includeDevDeps = true` → 激活 feature 的 sources
58+
从不被加回构建图。叠加 xpkg 侧 `features.X.sources` 只落进 `featureSources`**从不进
59+
base `sources`** —— 于是「只在 features 下声明」的包:
60+
61+
| 路径 | 结果 |
62+
|---|---|
63+
| `mcpp build` |**一直是好的**,7 个 src TU 全进 build.ninja,二进制真跑 |
64+
| `mcpp test` |`undefined reference` |
65+
66+
那段门的注释假设「descriptor 会把 `gtest_main.cc` 同时留在 base sources 里,故 test
67+
模式不受影响」——**只对 gtest 成立**,是未被察觉的隐式耦合。`compat.eigen`
68+
"linking feature-built dependency objects into test binaries is a follow-up" 的定性
69+
同样是错的:**不是链接问题,是源集解析问题**
70+
71+
**修复**:mcpp 0.0.94(#218)—— drop 仍只在 build 模式做(test 模式需保留完整源面供
72+
dev-dep 轨 per-test main 检测剪枝),add 改为两模式都做 + 去重。
73+
74+
**采用方案**:描述符的 `compiled` feature 声明**本来就是对的,一行未改**;只把注释从
75+
「引擎不支持」改为如实的「`mcpp test` 下需 ≥0.0.94」。CI pin 提到 0.0.94 后,
76+
**两个模态都进 CI 断言**(`tests/examples/spdlog/` header-only +
77+
`tests/examples/spdlog-compiled/` compiled)。
78+
79+
**教训**:诊断 feature 相关问题**必须 `build` / `test` 两条路径对比**,只测一条会把
80+
路径 bug 误判成引擎能力缺失。
81+
82+
## 4. feature 评估:为何不为 tweakme 开关新增 feature
83+
84+
spdlog 的 `tweakme.h` 有大量编译期开关(`SPDLOG_USE_STD_FORMAT`
85+
`SPDLOG_NO_SOURCE_LOC``SPDLOG_CLOCK_COARSE``SPDLOG_ACTIVE_LEVEL=...` 等)。
86+
经确认(mcpp `05-mcpp-toml.md`),消费者可在**自己的** `mcpp.toml` 直接注入,
87+
无需包侧声明 feature:
88+
89+
```toml
90+
[targets.my-app]
91+
defines = ["SPDLOG_USE_STD_FORMAT"] # per-target,-D 随本 TU 编译
92+
# 或 [build] cxxflags = ["-DSPDLOG_NO_SOURCE_LOC"] # 整工程
93+
```
94+
95+
作用域陷阱(官方明示):`defines`/`cxxflags` **只作用于该 target 自己的 entry,
96+
不传播到共享/依赖代码**。对 spdlog:
97+
98+
- header-only 模态下 spdlog 全在头文件里,随消费者 TU 编译,消费者 `-D` 天然覆盖
99+
→ 所有 tweakme 开关消费者自助即可,做成 feature 是冗余(且不如消费侧灵活,
100+
消费侧还能带值,如 `SPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_INFO`)。
101+
- 唯一"消费者 `-D` 够不着、必须包侧统一注入"的是 `SPDLOG_COMPILED_LIB`
102+
(要同时影响库源与消费者)——已由 `compiled` feature 承载(受 §3 限制)。
103+
104+
因此**不新增 tweakme feature**,避免过度设计。
105+
106+
## 5. CN 镜像:纯字符串回退
107+
108+
本环境无 gitcode token(`~/.config/gitcode-tool/config.json` 不存在,
109+
`GITCODE_TOKEN` 未设),无法在 `mcpp-res` 上传资产。探查发现 `mcpp-res/spdlog`
110+
仓库页面已存在(200)但为空壳(release 资产 403)。
111+
112+
`docs/cn-mirror.md` 回退方案:三平台 `url` 采用**纯字符串**(仅上游 GitHub
113+
release),lint(`check_mirror_urls.lua`)对纯字符串 url 不施加镜像约束,
114+
`mirror-cn-reachable` 也不会抽取到需 curl 的 CN url。CN 用户回退至上游源。
115+
先例:`pkgs/t/tensorvia-cpu.lua`。后续获得权限或维护者补充镜像后,可将各
116+
`url` 改写为 `{ GLOBAL, CN }` 表(sha256 不变)。
117+
118+
lint 只允许 `gitcode.com/mcpp-res/` 下的 CN url(信任边界 + 字节一致),任何
119+
第三方域名在表形式下都过不了 lint,故无"其他可用 CN 镜像"。
120+
121+
## 6. 验证结论(mcpp 0.0.94,GLOBAL)
122+
123+
**两个模态都已 CI 断言**:
124+
125+
- `mcpp test -p spdlog` → header-only 默认模态,`test result ok. 1 passed`
126+
- `mcpp test -p spdlog-compiled` → compiled 模态,`test result ok. 1 passed`
127+
`tests/examples/spdlog-compiled/tests/compiled_test.cpp` 静态断言
128+
`SPDLOG_COMPILED_LIB` 已定义且 `SPDLOG_HEADER_ONLY` 未定义(退化回 inline 路径
129+
会是**编译错误**而非静默通过),再跑与 header-only 同款的行为断言 —— 这些调用
130+
解析到 `default_logger_raw` / `log_msg` ctor / `logger::log_it_` / bundled fmt
131+
`vformat`**非 inline 符号**,正是 feature sources 没编译时链不上的那批。
132+
133+
以下为初版(0.0.91)记录,保留作历史:
134+
135+
- `mcpp xpkg parse pkgs/c/compat.spdlog.lua``parse OK`(strict floor/grammar)。
136+
- workspace 成员 `mcpp test -p spdlog``test result ok. 1 passed`
137+
示例 `tests/examples/spdlog/tests/log_test.cpp` 用 ostream sink 捕获日志,
138+
断言 `logger.info("hello {}={}", "answer", 42)``{:#x}` 的格式化输出
139+
(走 bundled fmt 头内联),`return ok ? 0 : 1`
140+
- 负向语义:header-only 默认构建 `build.ninja``spdlog_anchor.o`
141+
(证明 src 未被默认编入);compiled 请求时消费者带 `-DSPDLOG_COMPILED_LIB`
142+
(证明 define 门控生效)。
143+
- 本地 lint(等价 CI lint job)全量 `ALL LINT PASS`;spdlog 镜像 lint 单独 OK。
144+
145+
## 7. 落点与注意事项
146+
147+
- 描述符落点 `pkgs/c/compat.spdlog.lua`——目录取**完整包名首字母**
148+
(`compat.spdlog``c`,非短名 `s`)。初次误置 `pkgs/s/` 导致
149+
`not found in local index`,移至 `pkgs/c/` 后解决。
150+
- 示例已登记进根 `mcpp.toml``[workspace].members`(否则
151+
`mcpp test --workspace` 不会跑到)。
152+
- CI 已由早期 `detect`+`run_example.sh` 重构为 workspace 模式
153+
(`mcpp test --workspace`),示例采用 `tests/*.cpp` + 断言布局,而非
154+
`src/main.cpp`

.github/workflows/validate.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ on:
1111
workflow_dispatch:
1212

1313
env:
14-
# Bumped to 0.0.91: carries standard = "c++fly" (experimental playground
15-
# mode) in the resolver grammar — required so descriptors declaring it get
16-
# the lint WARN below instead of a hard grammar-parse rejection from an
17-
# older pinned mcpp (admission policy: warn, don't reject).
18-
MCPP_VERSION: "0.0.91"
14+
# Bumped to 0.0.94: fixes feature-gated `sources` never being compiled under
15+
# `mcpp test` (mcpp#218) — required by the tests/examples/spdlog-compiled
16+
# member, which links against spdlog's feature-compiled src/*.cpp. Also
17+
# carries standard = "c++fly" in the resolver grammar (0.0.91), so c++fly
18+
# descriptors get the lint WARN below, not a hard grammar-parse rejection.
19+
MCPP_VERSION: "0.0.94"
1920

2021
jobs:
2122
lint:

mcpp.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ members = [
2020
"tests/examples/nlohmann.json",
2121
"tests/examples/openblas",
2222
"tests/examples/opencv",
23+
"tests/examples/spdlog",
24+
"tests/examples/spdlog-compiled",
2325
]

pkgs/c/compat.spdlog.lua

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
-- Form B inline descriptor for spdlog — a very fast, header-only / compiled C++
2+
-- logging library. spdlog is DUAL-MODAL and this recipe exposes both modes off
3+
-- one descriptor:
4+
--
5+
-- * DEFAULT (header-only). No feature requested. spdlog's headers are
6+
-- self-contained: including <spdlog/spdlog.h> pulls the -inl.h
7+
-- implementation inline (common.h flips on SPDLOG_HEADER_ONLY when
8+
-- SPDLOG_COMPILED_LIB is NOT defined). Nothing under src/ compiles; a tiny
9+
-- anchor TU gives mcpp a buildable `lib` target (same shape as
10+
-- compat.eigen / compat.opengl). The bundled {fmt} (include/spdlog/fmt/
11+
-- bundled/) is used in FMT_HEADER_ONLY mode, so this package is
12+
-- self-contained and needs NO external fmt dependency.
13+
--
14+
-- * COMPILED (`features = ["compiled"]`). Turns spdlog into a precompiled
15+
-- library: (1) compiles the seven src/*.cpp translation units into the lib,
16+
-- and (2) contributes the SPDLOG_COMPILED_LIB define. That define is an
17+
-- INTERFACE define — it must reach BOTH spdlog's own sources (each src/*.cpp
18+
-- #errors out without it) AND every consumer TU that includes a spdlog
19+
-- header (so the consumer's headers switch to the extern-template /
20+
-- non-inline path and link against the compiled objects instead of
21+
-- re-emitting the implementation inline). bundled_fmtlib_format.cpp compiles
22+
-- the bundled fmt implementation into the lib, so compiled mode is
23+
-- self-contained too — still NO external fmt dependency.
24+
--
25+
-- REQUIRES mcpp >= 0.0.94 under `mcpp test`. mcpp 0.0.93 and older gated the
26+
-- whole feature-source resolution on build mode, so an active feature's
27+
-- `sources` were never compiled under `mcpp test` → link-time `undefined
28+
-- reference` (`mcpp build` was always fine). Fixed in mcpp 0.0.94; the same
29+
-- bug is what compat.cjson's `utils` and compat.eigen's `eigen_blas`
30+
-- (`dgemm_`) hit. Header-only mode is unaffected and works on any version,
31+
-- which is why the index floor (`index.toml` min_mcpp) does not move: that
32+
-- floor tracks descriptor GRAMMAR, and this descriptor parses everywhere.
33+
--
34+
-- All `mcpp` paths are GLOBS relative to the verdir; the leading `*` absorbs the
35+
-- GitHub archive's `spdlog-<tag>/` wrap layer. include_dirs points at
36+
-- `*/include` so consumers write `#include <spdlog/spdlog.h>`.
37+
--
38+
-- No CN mirror yet: `url` is a plain string (upstream GitHub release only), the
39+
-- documented fallback when there is no mcpp-res write access (docs/cn-mirror.md;
40+
-- precedent: pkgs/t/tensorvia-cpu.lua). CN users fall back to the upstream
41+
-- source. A maintainer can later rewrite each `url` to a { GLOBAL, CN } table
42+
-- (sha256 unchanged) once the gitcode mcpp-res/spdlog mirror exists.
43+
package = {
44+
spec = "1",
45+
namespace = "compat",
46+
name = "compat.spdlog",
47+
description = "Fast C++ logging library (header-only by default, compiled via the `compiled` feature)",
48+
licenses = {"MIT"},
49+
repo = "https://github.com/gabime/spdlog",
50+
type = "package",
51+
52+
xpm = {
53+
linux = {
54+
["1.17.0"] = {
55+
url = "https://github.com/gabime/spdlog/archive/refs/tags/v1.17.0.tar.gz",
56+
sha256 = "d8862955c6d74e5846b3f580b1605d2428b11d97a410d86e2fb13e857cd3a744",
57+
},
58+
},
59+
macosx = {
60+
["1.17.0"] = {
61+
url = "https://github.com/gabime/spdlog/archive/refs/tags/v1.17.0.tar.gz",
62+
sha256 = "d8862955c6d74e5846b3f580b1605d2428b11d97a410d86e2fb13e857cd3a744",
63+
},
64+
},
65+
windows = {
66+
["1.17.0"] = {
67+
url = "https://github.com/gabime/spdlog/archive/refs/tags/v1.17.0.tar.gz",
68+
sha256 = "d8862955c6d74e5846b3f580b1605d2428b11d97a410d86e2fb13e857cd3a744",
69+
},
70+
},
71+
},
72+
73+
mcpp = {
74+
language = "c++23",
75+
import_std = false,
76+
c_standard = "c11",
77+
-- Exposes include/spdlog/** so consumers write `#include <spdlog/...>`.
78+
-- The bundled fmt under include/spdlog/fmt/bundled/ rides along, so no
79+
-- external fmt dependency is needed in either mode.
80+
include_dirs = { "*/include" },
81+
-- Header-only default: a trivial anchor TU gives mcpp a buildable lib
82+
-- target when no source is compiled.
83+
generated_files = {
84+
["mcpp_generated/spdlog_anchor.c"] = [==[
85+
int mcpp_compat_spdlog_headers_anchor(void) { return 0; }
86+
]==],
87+
},
88+
sources = { "mcpp_generated/spdlog_anchor.c" },
89+
targets = { ["spdlog"] = { kind = "lib" } },
90+
features = {
91+
-- Precompiled mode: compiles spdlog's src/*.cpp into the lib AND
92+
-- publishes SPDLOG_COMPILED_LIB as an interface define so consumer
93+
-- headers take the non-inline / extern-template path. src/spdlog.cpp
94+
-- (and the other six) #error without this define. Needs mcpp >=
95+
-- 0.0.94 under `mcpp test` — see the header note.
96+
["compiled"] = {
97+
sources = { "*/src/*.cpp" },
98+
defines = { "SPDLOG_COMPILED_LIB" },
99+
},
100+
},
101+
deps = { },
102+
},
103+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# spdlog test project: consumes compat.spdlog in its COMPILED mode
2+
# (`features = ["compiled"]`) — spdlog's src/*.cpp are compiled into the lib and
3+
# SPDLOG_COMPILED_LIB reaches this consumer's TUs as an interface define, so the
4+
# headers take the non-inline path and link against those objects.
5+
#
6+
# Sibling of tests/examples/spdlog/ (header-only default mode). Both modes ship
7+
# from one descriptor; this member is what keeps the compiled path honest.
8+
#
9+
# Needs mcpp >= 0.0.94: older versions never compiled a dependency's active
10+
# feature `sources` under `mcpp test`, so this member would fail to link.
11+
[package]
12+
name = "spdlog-compiled-tests"
13+
version = "0.1.0"
14+
15+
[indices]
16+
compat = { path = "../../.." }
17+
18+
[dependencies.compat]
19+
spdlog = { version = "1.17.0", features = ["compiled"] }
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Behavioral test: consume compat.spdlog in COMPILED mode. Asserts both halves
2+
// of what the `compiled` feature promises:
3+
//
4+
// 1. the interface define reached this TU (SPDLOG_COMPILED_LIB defined, and
5+
// spdlog's headers therefore did NOT flip on SPDLOG_HEADER_ONLY) — a
6+
// static check, so a regression is a compile error, not a silent fallback
7+
// to the header-only path that would still pass the runtime assertions;
8+
// 2. spdlog's src/*.cpp really were compiled and linked — the calls below
9+
// resolve to out-of-line symbols (default_logger_raw, log_msg's ctor,
10+
// logger::log_it_, and bundled fmt's vformat), which is exactly what fails
11+
// to link when the engine skips a feature's sources.
12+
#include <spdlog/spdlog.h>
13+
#include <spdlog/sinks/ostream_sink.h>
14+
#include <sstream>
15+
#include <string>
16+
17+
#ifndef SPDLOG_COMPILED_LIB
18+
#error "compiled feature did not propagate SPDLOG_COMPILED_LIB to the consumer"
19+
#endif
20+
#ifdef SPDLOG_HEADER_ONLY
21+
#error "SPDLOG_HEADER_ONLY is on in compiled mode — headers took the inline path"
22+
#endif
23+
24+
int main() {
25+
std::ostringstream captured;
26+
auto sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(captured);
27+
spdlog::logger logger("test", sink);
28+
logger.set_pattern("%v"); // message only, no timestamp/level decoration
29+
30+
logger.info("hello {}={}", "answer", 42);
31+
logger.warn("{:#x}", 255);
32+
logger.flush();
33+
34+
// Exercises the global registry too — default_logger_raw() is one of the
35+
// out-of-line symbols that only exists once src/spdlog.cpp is compiled.
36+
spdlog::set_level(spdlog::level::info);
37+
38+
const std::string out = captured.str();
39+
const bool ok = out.find("hello answer=42") != std::string::npos
40+
&& out.find("0xff") != std::string::npos;
41+
return ok ? 0 : 1;
42+
}

tests/examples/spdlog/mcpp.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# spdlog test project: consumes compat.spdlog in its DEFAULT header-only mode
2+
# (bundled fmt, no external dependency) and asserts behavior under `mcpp test`.
3+
# Part of the mcpp-index self-referential workspace: `[indices] compat` points
4+
# at this repo, so the dependency resolves to the checked-in recipe
5+
# (pkgs/c/compat.spdlog.lua). Compiled mode is covered by the sibling member
6+
# tests/examples/spdlog-compiled/.
7+
[package]
8+
name = "spdlog-tests"
9+
version = "0.1.0"
10+
11+
[indices]
12+
compat = { path = "../../.." }
13+
14+
[dependencies.compat]
15+
spdlog = "1.17.0"
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Behavioral test: consume compat.spdlog in its DEFAULT header-only mode. Logs
2+
// through a custom logger wired to an in-memory ostream sink, then asserts the
3+
// formatted output — this exercises the logger, the pattern formatter, and the
4+
// bundled {fmt} formatting all via the header inlines. Returns non-zero on any
5+
// mismatch.
6+
#include <spdlog/spdlog.h>
7+
#include <spdlog/sinks/ostream_sink.h>
8+
#include <sstream>
9+
#include <string>
10+
11+
int main() {
12+
std::ostringstream captured;
13+
auto sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(captured);
14+
spdlog::logger logger("test", sink);
15+
logger.set_pattern("%v"); // message only, no timestamp/level decoration
16+
17+
logger.info("hello {}={}", "answer", 42);
18+
logger.warn("{:#x}", 255);
19+
logger.flush();
20+
21+
const std::string out = captured.str();
22+
const bool ok = out.find("hello answer=42") != std::string::npos
23+
&& out.find("0xff") != std::string::npos;
24+
return ok ? 0 : 1;
25+
}

0 commit comments

Comments
 (0)