Skip to content

fix(pkg): catch2 的 v2/v3 判别不能问系统目录 - #187

Merged
Sunrisepeak merged 1 commit into
mainfrom
fix/catch2-version-probe-ignores-system
Aug 8, 2026
Merged

fix(pkg): catch2 的 v2/v3 判别不能问系统目录#187
Sunrisepeak merged 1 commit into
mainfrom
fix/catch2-version-probe-ignores-system

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

catch2_main.cpp__has_include(<catch2/catch_all.hpp>) 区分两个大版本。这个探测同样会翻系统 include 目录,而 catch_all.hpp 正是每个发行版 catch2 包都会装的头。

于是在一台装了系统 Catch2 v3 的机器上,一个 v2 消费者被回答"你是 v3",编出 Catch::Session 那条入口,再死在链接:

ld.lld: error: undefined symbol: Catch::Session::Session()
>>> referenced by /usr/include/catch2/catch_session.hpp:39

#183 修的 compat.ffmpeg 是同一类问题:宿主机装了同名开发包,vendored 的东西就被挤掉。gcc 不中招是因为它通过 --sysroot 进 xlings subos,那里没有 /usr/include/catch2 —— 所以这条在 CI 和默认工具链下一直是绿的

修法

探测 catch2/catch_user_config.hpp.in —— 上游把它作为 CMake 模板放在 v3 的源码树里,安装的是生成后的 .hpp,模板本身从不安装。这就得到一个系统装不出来的标记。

情形 .in 探测 现行 catch_all.hpp
vendored v3 在 -I v3 v3
vendored v2 在 -I v2 v3 ← 本 bug
只有系统 v3 v2 v3

clang 22.1.8 与 gcc 16.1.0 上分别验过三种情形。

验证

四个 catch2 成员 × 两个工具链,在一台装了系统 Catch2 v3 的机器上:

              llvm    gcc
catch2         ok      ok
catch2-main    ok      ok
catch2-v2      ok      ok
catch2-v2-main ok      ok     ← 此前 llvm 下是 FAIL

80 个描述符 mcpp xpkg parse + lint 全过。

关于 mcpp#290

#183 的描述里我把这条列为"要等 per-version build blocks(mcpp#290)才能修" —— 那个判断下早了。要的不是"知道自己是哪个版本",只是一个系统装不出来的探针。

mcpp#290 仍然是更干净的答案:它让这个问题整个消失,而不是换一个探针。这里的探针有它的脆弱面,已写进描述符注释:如果上游哪天改成在树内直接生成而不再发 .in,或某个发行版开始安装模板,就得另找源码专属标记。

顺带一提

CI 抓不到这个:GitHub runner 不装 catch2,-idirafter / __has_include 都没有东西可输。#184 那条 llvm 腿即使装了 libav*-dev,也只覆盖 ffmpeg 这一族。这一类"宿主机装了同名包"的问题,目前只能靠开发机发现。

`catch2_main.cpp` 用 `__has_include(<catch2/catch_all.hpp>)` 区分两个大版本。
这个探测同样会翻系统 include 目录,而 catch_all.hpp 正是每个发行版的 catch2
包都会装的头。于是在一台装了系统 Catch2 v3 的机器上,一个 v2 消费者被回答
"你是 v3",编出 Catch::Session 那条入口,再死在链接:

    ld.lld: error: undefined symbol: Catch::Session::Session()
    >>> referenced by /usr/include/catch2/catch_session.hpp:39

和 #183 修的 compat.ffmpeg 是同一类问题:宿主机装了同名开发包,vendored 的
东西就被挤掉。gcc 不中招是因为它通过 --sysroot 进 xlings subos,那里没有
/usr/include/catch2 —— 所以这条在 CI 和默认工具链下一直是绿的。

改成探测 `catch2/catch_user_config.hpp.in`:上游把它作为 CMake 模板放在 v3
的源码树里,装的是生成后的 .hpp,模板本身从不安装。三种情形在 clang 22.1.8
和 gcc 16.1.0 上都验过:

    vendored v3 在 -I 上   -> v3     (两种探测一致)
    vendored v2 在 -I 上   -> v2     (catch_all.hpp 答 v3,即本 bug)
    只有系统 v3            -> v2     (catch_all.hpp 答 v3)

四个 catch2 成员 × 两个工具链,在一台装了系统 Catch2 v3 的机器上全过 ——
catch2-v2-main 此前在 llvm 下是 FAIL。

#183 的描述里把这条列为"要等 per-version build blocks(mcpp#290)才能修",
那个判断下早了:要的不是"知道自己是哪个版本",只是一个系统装不出来的探针。
mcpp#290 仍然是更干净的答案,它让这个问题整个消失,而不是换一个探针。
@Sunrisepeak
Sunrisepeak merged commit 6e452b9 into main Aug 8, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant