Skip to content

Commit 577bbcf

Browse files
committed
fix: Windows ninja rules — remove $toolenv prefix, fix cp_bmi
$toolenv is empty on Windows but leaves a leading space that breaks CreateProcess. Remove $toolenv from all ninja rule commands on Windows. Also replace POSIX cp_bmi rule with cmd /c copy on Windows.
1 parent af1229c commit 577bbcf

2 files changed

Lines changed: 38 additions & 7 deletions

File tree

.github/workflows/ci-windows.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -274,11 +274,7 @@ jobs:
274274
ls "$MCPP_XPKGS/xim-x-llvm/20.1.7/bin/" | head -5
275275
fi
276276
277-
"$MCPP_EXE" build || {
278-
echo "=== build.ninja (first 50 lines) ==="
279-
find target -name "build.ninja" -exec head -50 {} \; 2>/dev/null
280-
exit 1
281-
}
277+
"$MCPP_EXE" build
282278
283279
# Find the self-hosted binary
284280
SELF_MCPP=$(find target -name "mcpp.exe" -path "*/bin/*" | head -1)

src/build/ninja_backend.cppm

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,11 @@ std::string emit_ninja_string(const BuildPlan& plan) {
197197
append("\n");
198198

199199
append("rule cp_bmi\n");
200+
#if defined(_WIN32)
201+
append(" command = cmd /c copy /y $in $out >nul\n");
202+
#else
200203
append(" command = mkdir -p $$(dirname $out) && cp -f $in $out\n");
204+
#endif
201205
append(" description = STAGE $out\n\n");
202206

203207
// P1: per-file dyndep rule. Converts one .ddi → .dd independently.
@@ -222,9 +226,9 @@ std::string emit_ninja_string(const BuildPlan& plan) {
222226
append("rule cxx_module\n");
223227
#if defined(_WIN32)
224228
// Windows: skip BMI restat optimization (requires POSIX shell).
225-
// Just compile directly — incremental rebuild still works via dyndep.
229+
// No $toolenv (empty on Windows; its leading space breaks CreateProcess).
226230
append(std::format(" command = "
227-
"$toolenv $cxx $cxxflags{} -c $in -o $out\n", module_output_flag));
231+
"$cxx $cxxflags{} -c $in -o $out\n", module_output_flag));
228232
#else
229233
append(std::format(" command = "
230234
"if [ -n \"$bmi_out\" ] && [ -f \"$bmi_out\" ]; then "
@@ -244,21 +248,42 @@ std::string emit_ninja_string(const BuildPlan& plan) {
244248
append("\n");
245249

246250
append("rule cxx_object\n");
251+
#if defined(_WIN32)
252+
append(" command = $cxx $cxxflags -c $in -o $out\n");
253+
#else
247254
append(" command = $toolenv $cxx $cxxflags -c $in -o $out\n");
255+
#endif
248256
append(" description = OBJ $out\n");
249257
if (dyndep)
250258
append(" restat = 1\n");
251259
append("\n");
252260

253261
if (need_c_rule) {
254262
append("rule c_object\n");
263+
#if defined(_WIN32)
264+
append(" command = $cc $cflags -c $in -o $out\n");
265+
#else
255266
append(" command = $toolenv $cc $cflags -c $in -o $out\n");
267+
#endif
256268
append(" description = CC $out\n");
257269
if (dyndep)
258270
append(" restat = 1\n");
259271
append("\n");
260272
}
261273

274+
#if defined(_WIN32)
275+
append("rule cxx_link\n");
276+
append(" command = $cxx $in -o $out $ldflags\n");
277+
append(" description = LINK $out\n\n");
278+
279+
append("rule cxx_archive\n");
280+
append(" command = $ar rcs $out $in\n");
281+
append(" description = AR $out\n\n");
282+
283+
append("rule cxx_shared\n");
284+
append(" command = $cxx -shared $in -o $out $ldflags\n");
285+
append(" description = SHARED $out\n\n");
286+
#else
262287
append("rule cxx_link\n");
263288
append(" command = $toolenv $cxx $in -o $out $ldflags\n");
264289
append(" description = LINK $out\n\n");
@@ -270,6 +295,7 @@ std::string emit_ninja_string(const BuildPlan& plan) {
270295
append("rule cxx_shared\n");
271296
append(" command = $toolenv $cxx -shared $in -o $out $ldflags\n");
272297
append(" description = SHARED $out\n\n");
298+
#endif
273299

274300
if (dyndep) {
275301
// Scan rule: produce P1689 .ddi for one TU.
@@ -278,14 +304,23 @@ std::string emit_ninja_string(const BuildPlan& plan) {
278304
append("rule cxx_scan\n");
279305
if (plan.scanDepsPath.empty()) {
280306
// GCC path: compiler-integrated P1689 scanning.
307+
#if defined(_WIN32)
308+
append(" command = $cxx $cxxflags -fmodules "
309+
#else
281310
append(" command = $toolenv $cxx $cxxflags -fmodules "
311+
#endif
282312
"-fdeps-format=p1689r5 "
283313
"-fdeps-file=$out -fdeps-target=$compile_target "
284314
"-M -MM -MF $out.dep -E $in -o $compile_target\n");
285315
} else {
286316
// Clang path: clang-scan-deps produces P1689 JSON to stdout.
317+
#if defined(_WIN32)
318+
append(" command = $scan_deps -format=p1689 -- "
319+
"$cxx $cxxflags -c $in -o $compile_target > $out\n");
320+
#else
287321
append(" command = $toolenv $scan_deps -format=p1689 -- "
288322
"$cxx $cxxflags -c $in -o $compile_target > $out\n");
323+
#endif
289324
}
290325
append(" description = SCAN $out\n\n");
291326

0 commit comments

Comments
 (0)