Skip to content

Commit c8abf43

Browse files
committed
fix(spirv): popen 是 POSIX 的,Windows 拼作 _popen
windows-2022 上 `mcpp.rules.spirv` 的宿主模块编译失败: rules/spirv.cppm:277:17: error: no member named 'popen' in the global namespace rules/spirv.cppm:282:7: error: no type named 'pclose' in the global namespace 同一形状此前在 sycl 里已经处理过。空设备也一样(`/dev/null` / `NUL`)。两者都命名 成常量,让调用点在每个宿主上读起来一样 —— 另一种写法是每个调用点套一个 `#if`,而 被忘掉的那一个恰好是没人编译的那一个。 hip 那条 lane 的 clang++ 也补上后缀:它今天只到得了 Linux(NVIDIA 平台的头文件包 只为它发布),所以这段 Windows 拼写没有任何东西在走。仍然写下来,因为错误的路径会 把自己报成「工具链缺 clang」。 CI:跨平台 job 里把「每条规则都为本宿主编译过」挪到端到端那一步之前。它更便宜、答案 更有信息量;放在后面时,它的失败以别人的构建错误形态到达 —— 一个与它无关的 consumer 报 `no member named 'popen'`。
1 parent b1d0ffc commit c8abf43

3 files changed

Lines changed: 55 additions & 17 deletions

File tree

.github/workflows/ci.yml

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,22 @@ jobs:
461461
echo "MCPP=$MCPP" >> "$GITHUB_ENV"
462462
echo "MCPP_VENDORED_XLINGS=$MCPP_VENDORED_XLINGS" >> "$GITHUB_ENV"
463463
464+
# FIRST, BECAUSE IT IS THE CHEAPER QUESTION AND THE MORE INFORMATIVE
465+
# ANSWER. Every other step here drives one rule end to end and needs
466+
# that rule's payload; this one names no accelerator, downloads nothing,
467+
# and asks only whether all six modules COMPILE for this host -- which
468+
# is the half of a rule that a Linux-only CI never sees. Run after the
469+
# end-to-end step, its failure arrived as somebody else's build error:
470+
# `no member named 'popen' in the global namespace`, reported against a
471+
# consumer that had nothing to do with it.
472+
- name: every rule module compiles for this host
473+
working-directory: tests/all-rules-compile
474+
run: |
475+
set -e
476+
"$MCPP" build
477+
"$MCPP" run | tee run.log
478+
grep -q '^all-rules-compile ok' run.log
479+
464480
- name: rules-spirv through a consumer
465481
working-directory: tests/spirv-consumer
466482
run: |
@@ -473,20 +489,6 @@ jobs:
473489
# come from the GRAPH, not from the fixture. Without it, a fixture that
474490
# quietly regained an `[xlings.workspace]` would keep this green while the
475491
# claim stopped being true.
476-
# THE STEP THAT MAKES THIS JOB WORTH ITS NAME. Above it, one rule is
477-
# exercised because one rule's compiler is published for these hosts.
478-
# Below it, EVERY rule is compiled for them -- including the ones whose
479-
# payload reaches a device that macOS and Windows do not both have, and
480-
# whose host-dependent code was therefore written without ever being
481-
# compiled on the host it was written for.
482-
- name: every rule module compiles for this host
483-
working-directory: tests/all-rules-compile
484-
run: |
485-
set -e
486-
"$MCPP" build
487-
"$MCPP" run | tee run.log
488-
grep -q '^all-rules-compile ok' run.log
489-
490492
- name: the rule declared its own compiler
491493
working-directory: tests/spirv-consumer
492494
run: |

rules/hip.cppm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,17 @@ inline std::vector<edge> plan(std::span<const std::string> sources, options opt
328328
// everywhere else. `mcpp.rules.cuda` takes the same path for the same
329329
// reason.
330330
const std::string tcdir = mcpp::toolchain_dir();
331+
// The suffix is the host's. This lane reaches only Linux today -- the
332+
// NVIDIA-platform header package is published for it alone -- so the
333+
// Windows spelling is not exercised by anything. It is written anyway,
334+
// because the alternative is a path that is wrong on a host this rule
335+
// will one day be asked about, and a wrong path reports itself as a
336+
// missing toolchain.
337+
#if defined(_WIN32)
338+
const std::string cc = tcdir + "/bin/clang++.exe";
339+
#else
331340
const std::string cc = tcdir + "/bin/clang++";
341+
#endif
332342
if (tcdir.empty() || !std::filesystem::exists(cc)) {
333343
std::cerr << std::format("mcpp.rules.hip: the NVIDIA platform compiles through clang, and this "
334344
"project's\n toolchain has no clang++ at {}.\n"

rules/spirv.cppm

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,13 +273,38 @@ inline compiler find_compiler(const options& opt) {
273273
// magic, the second is the release. The release is what a floor compares, and
274274
// stating it as a fact is what makes a build log answer "which compiler
275275
// produced this SPIR-V" without anyone having to reproduce the build.
276+
// `popen` is POSIX and Windows spells it `_popen`; the null device differs
277+
// too. Both are named here so the call sites below read the same on every
278+
// host -- the alternative is a `#if` around each one, and the one that gets
279+
// forgotten is the one nobody compiles.
280+
inline FILE* open_pipe(const std::string& cmd) {
281+
#if defined(_WIN32)
282+
return ::_popen(cmd.c_str(), "r");
283+
#else
284+
return ::popen(cmd.c_str(), "r");
285+
#endif
286+
}
287+
inline void close_pipe(FILE* p) {
288+
#if defined(_WIN32)
289+
::_pclose(p);
290+
#else
291+
::pclose(p);
292+
#endif
293+
}
294+
inline constexpr const char* kNullDevice =
295+
#if defined(_WIN32)
296+
"NUL";
297+
#else
298+
"/dev/null";
299+
#endif
300+
276301
inline std::string run_and_capture(const std::string& cmd) {
277-
FILE* p = ::popen(cmd.c_str(), "r");
302+
FILE* p = open_pipe(cmd);
278303
if (!p) return {};
279304
std::string text;
280305
char buf[512];
281306
while (std::fgets(buf, sizeof buf, p)) text += buf;
282-
::pclose(p);
307+
close_pipe(p);
283308
return text;
284309
}
285310

@@ -301,7 +326,8 @@ inline bool has_optimizer(const std::string& exe) {
301326
}
302327

303328
inline std::string compiler_version(const compiler& cc) {
304-
const std::string text = run_and_capture("\"" + cc.path + "\" --version 2>/dev/null");
329+
const std::string text = run_and_capture("\"" + cc.path + "\" --version 2>"
330+
+ std::string(kNullDevice));
305331
// glslc: `shaderc v2026.3 2fbab05...` on the first line. glslang:
306332
// `Glslang Version: 11:15.1.0`, whose first field is the SPIR-V generator
307333
// magic and whose second is the release.

0 commit comments

Comments
 (0)