# let cmake use clang-cl when use ninja, not clang++ ,so people can migrate from visual studio nmake to ninja

**URL:** https://discourse.cmake.org/t/let-cmake-use-clang-cl-when-use-ninja-not-clang-so-people-can-migrate-from-visual-studio-nmake-to-ninja/15755
**Category:** Development
**Tags:** os:windows, gen:ninja
**Created:** [July 22, 2026, 2:28am UTC](https://discourse.cmake.org/t/let-cmake-use-clang-cl-when-use-ninja-not-clang-so-people-can-migrate-from-visual-studio-nmake-to-ninja/15755 "2026-07-22T02:28:21Z")
**Posts on this page:** 2
**Page:** 1

<div class="post-metadata">

### Author: ![photonest3](https://discourse.cmake.org/user_avatar/discourse.cmake.org/photonest3/32/6186_2.png) [@photonest3](https://discourse.cmake.org/u/photonest3)
#### Post date: [July 22, 2026, 2:28am UTC](https://discourse.cmake.org/t/let-cmake-use-clang-cl-when-use-ninja-not-clang-so-people-can-migrate-from-visual-studio-nmake-to-ninja/15755/1 "2026-07-22T02:28:21Z")

</div>

let cmake use clang-cl when use ninja, not clang++ ,so people can migrate from visual studio nmake to ninja.

OpenClaw (codebuddy.ai) output translate:

Here’s a natural, technically-accurate English translation (good for a Slack/PR comment or bug report):

* * *

Found the root cause — it’s a **CMake 4.4 misdetection bug for `clang-cl`** :

In `rules.ninja`, every C++ compile rule has its command hard-coded to `clang++` (the GCC driver):

```auto
command = ${LAUNCHER}${CODE_CHECK}clang++ /nologo -TP $DEFINES ...

```

But the flags are **MSVC-style `clang-cl` flags** ​ (`/nologo`, `/Fo`, `/EHsc`, `-target x86_64-pc-windows-msvc`, `-clang:-MD`…). CMake identified the compiler as **Clang with `FRONTEND_VARIANT=MSVC`** , yet still emitted the binary name as `clang++` following the plain-Clang convention — instead of `clang-cl`. It’s the **same binary** ​ (identical size, literally the same `clang`); launched as `clang++` it’s in GCC mode and rejects `/nologo`, while launched as `clang-cl` it’s in CL mode and accepts everything.

The link rule uses `lld-link.exe` (full path, fine), and the RC rule uses `rc` (needs to be on `PATH`). So as long as we swap `clang++` → `clang-cl` in the rules and add `LLVM/bin` + `SDK/bin` to `PATH`, it builds.

I’ll first replace all `clang++` with `clang-cl` in `rules.ninja` and verify:

chinese orijin output.

* * *

### A few wording notes

- **判定 bug** ​ → “misdetection bug” / “compiler-identification bug” (more natural than “judgment bug”)
- **写死** ​ → “hard-coded”
- **GCC 驱动 / CL 模式** ​ → “GCC driver” / “CL mode” (standard CMake/LLVM terminology)
- **不认 / 全部认** ​ → “rejects … / accepts everything”
- **编过** ​ → “it builds” / “the build goes through”

想要更偏 **upstream bug report** ​ 的正式语气，或者更短的 **IRC/Slack 口语版** 也可以告诉我～

找到根因了，是个 **CMake 4.4 对 clang-cl 的判定 bug** ：

`rules.ninja` 里所有 C++ 编译规则的命令被写死成了 **`clang++`** （GCC 驱动）：

```auto
command = ${LAUNCHER}${CODE_CHECK}clang++ /nologo -TP $DEFINES ...

```

但 flags 却是 clang-cl（MSVC）风格的（`/nologo`、`/Fo`、`/EHsc`、`-target x86_64-pc-windows-msvc`、`-clang:-MD`…）。CMake 把编译器识别成了 `Clang` + `FRONTEND_VARIANT=MSVC`，却按 `Clang` 的套路把二进制名写成了 `clang++`，而不是 `clang-cl`。同一个二进制（大小完全一致，是同一份 clang），用 `clang++` 起来是 GCC 模式，不认 `/nologo`；用 `clang-cl` 起来是 CL 模式，全部认。

链接规则用的是 `lld-link.exe`（完整路径，没问题），RC 规则用的是 `rc`（PATH 上要有）。所以 **只要把规则里的 `clang++` 改成 `clang-cl`，并把 LLVM/bin 和 SDK/bin 加进 PATH** ，就能编过。

我先把 `rules.ninja` 里的 `clang++` 全部替换成 `clang-cl` 并验证：

cmake output

[10/35] Building CXX object CMakeFiles\photol.dir\photol\photol\lang2.cpp.obj  
FAILED: [code=1] CMakeFiles/photol.dir/photol/photol/lang2.cpp.obj  
clang++ /nologo -TP -DNDEBUG -DNOMINMAX -DUNICODE -DWIN32\_LEAN\_AND\_MEAN -D\_UNICODE -D\_USRDLL -D\_WINDOWS -Dphotol\_EXPORTS -ID:\Community -ID:\Community\third\opencv\opencv-4.8.0\_build\_vs2019\_x64\install\include -ID:\Community\third\libmediainfo\_AllInclusive\MediaInfoLib\Source -ID:\Community\third\libmediainfo\_AllInclusive\ZenLib\Source -ID:\Community\third\osg-3rdparty-cmake-master\giflib\giflib-5.2.1 -ID:\Community\third\sqlite3mc-1.5.4\sqlite3mc-1.5.4 /DWIN32 /D\_WINDOWS /GR /EHsc -target x86\_64-pc-windows-msvc /Zi /Ob0 /Od /RTC1 -std:c++17 -MT -include photol/photol/stdafx.h -clang:-MD -clang:-MTCMakeFiles\photol.dir\photol\photol\lang2.cpp.obj -clang:-MFCMakeFiles\photol.dir\photol\photol\lang2.cpp.obj.d /FoCMakeFiles\photol.dir\photol\photol\lang2.cpp.obj /FdCMakeFiles\photol.dir\ -c – D:\Community\photol\photol\lang2.cpp  
clang++: error: unknown argument: ‘-std:c++17’  
clang++: error: unknown argument: ‘-clang:-MD’  
clang++: error: unknown argument: ‘-clang:-MTCMakeFiles\photol.dir\photol\photol\lang2.cpp.obj’  
clang++: error: unknown argument: ‘-clang:-MFCMakeFiles\photol.dir\photol\photol\lang2.cpp.obj.d’  
clang++: error: no such file or directory: ‘/nologo’  
clang++: error: no such file or directory: ‘/DWIN32’  
clang++: error: no such file or directory: ‘/D\_WINDOWS’  
clang++: error: no such file or directory: ‘/GR’  
clang++: error: no such file or directory: ‘/EHsc’  
clang++: error: no such file or directory: ‘/Zi’  
clang++: error: no such file or directory: ‘/Ob0’  
clang++: error: no such file or directory: ‘/Od’  
clang++: error: no such file or directory: ‘/RTC1’  
clang++: warning: treating ‘c-header’ input as ‘c+±header’ when in C++ mode, this behavior is deprecated [-Wdeprecated]  
clang++: error: no such file or directory: ‘photol/photol/stdafx.h’  
clang++: error: no such file or directory: ‘/FoCMakeFiles\photol.dir\photol\photol\lang2.cpp.obj’  
clang++: error: no such file or directory: ‘/FdCMakeFiles\photol.dir’  
ninja: build stopped: subcommand failed.

---

<div class="post-metadata">

### Author: ![photonest3](https://discourse.cmake.org/user_avatar/discourse.cmake.org/photonest3/32/6186_2.png) [@photonest3](https://discourse.cmake.org/u/photonest3)
#### Post date: [July 22, 2026, 2:35am UTC](https://discourse.cmake.org/t/let-cmake-use-clang-cl-when-use-ninja-not-clang-so-people-can-migrate-from-visual-studio-nmake-to-ninja/15755/2 "2026-07-22T02:35:47Z")

</div>

find solve plan:

quick in a sentence:

replace all rules.ninja in cmake build folder

the “clang++” to “clang-cl”.

> **[当 Clang-cl 遇见 MSVC：如何通过 CMAKE\_LANG\_SIMULATE\_ID 优雅地处理编译器兼容性](https://runebook.dev/zh/docs/cmake/variable/cmake_lang_simulate_id)**
>
> CMAKE\_\_SIMULATE\_ID 是一个 CMake 变量，用来指定“模拟”编译器的标识字符串。这里的 代表编程语言，比如 C、CXX（C++）、Fortran 等。所以完整的变量名可能是 CMAKE\_C\_SIMULATE\_ID 或 CMAKE\_CXX\_SIMULATE\_ID。

[https://wenku.csdn.net/column/1zh7u2zy91](https://wenku.csdn.net/column/1zh7u2zy91)

fix it upstream in cmake: CMAKE\_\_SIMULATE\_ID=MSVC or clang-cl

Here’s a clean, technically-precise English version — good for a Slack/Teams update or a bug-thread reply:

* * *

**The real reason for that string of errors**

It’s not a typo in your command — it’s a **CMake 4.4 misdetection bug for `clang-cl`** : CMake identifies the compiler as **Clang + MSVC frontend** , yet hard-codes the binary name as `clang++` (the GCC driver) in every C++ compile rule, while all the flags are **MSVC-style `clang-cl` flags** ​ — `/nologo`, `/Fo`, `/EHsc`, `-target x86_64-pc-windows-msvc`… Once `clang++` launches it’s in **GCC mode** , so naturally it doesn’t accept those `/`-prefixed args.

Linking uses `lld-link.exe` (full path, fine), and RC uses `rc` (needs the SDK `bin` on `PATH`).

**Fix I applied (already in effect)**

- Replaced all `clang++` → `clang-cl` in `build/CMakeFiles/rules.ninja` (10 compile rules), so the same `clang` runs in **CL mode** ​ and accepts all the flags.
- Added to the build env `PATH`: `C:\Program Files\LLVM\bin` + Windows SDK `bin\x64` (provides `clang-cl` and `rc`).
- Running `ninja -C build paint` now, in the background (task `hgsdqx`).

⚠ **One caveat** : if you ever re-run `cmake` to re-configure, it will regenerate `rules.ninja` and write `clang++` back — you’ll need to re-apply the swap. A normal **incremental `ninja` build won’t trigger this**.

Once it finishes (rebuilding `photol` + linking OpenCV takes a while), I’ll get auto-notified and report success/failure plus the `paint.exe` artifact path. You can also run the same steps on your local PowerShell — the core is that `rules.ninja` substitution.

* * *

### Slightly more concise / chat-friendly variant

> The errors aren’t from your command — it’s CMake 4.4 misdetecting `clang-cl`: it sees Clang+MSVC frontend but emits `clang++` (GCC driver) in all C++ rules while passing MSVC-style `/nologo /Fo /EHsc -target …`. `clang++` = GCC mode → rejects `/` flags. Link uses `lld-link.exe` (ok), RC needs `rc` on PATH.
> 
> Fix live: swapped `clang++`→`clang-cl` in `build/CMakeFiles/rules.ninja` (10 rules) + added LLVM/bin & SDK/bin/x64 to PATH. `ninja -C build paint` running in bg (task `hgsdqx`).
> 
> ⚠ Re-running `cmake` regenerates `rules.ninja` and reverts to `clang++` — incremental `ninja` is safe. Will ping you with result + `paint.exe` path once `photol`+OpenCV finish.

需要我顺手写成 **upstream CMake issue 的英文报告** （带最小复现步骤）也可以说～

# 1) 把 rc.exe 所在目录加入当前会话 PATH（改版本号以你实际 SDK 为准）  
$sdk = “C:\Program Files (x86)\Windows Kits\10”  
$ver = “10.0.28000.0”  
$env:PATH = $env:PATH + “;$sdk\bin\$ver\x64”

# 2) 配置（生成 Ninja 构建文件到 build/）

& “C:\Program Files\CMake\bin\cmake.exe” -B D:\Community\build -S D:\Community -G Ninja `  
“-DCMAKE\_MAKE\_PROGRAM=C:\ProgramData\chocolatey\bin\ninja.exe” `  
“-DCMAKE\_C\_COMPILER=C:\Program Files\LLVM\bin\clang-cl.exe” `  
“-DCMAKE\_CXX\_COMPILER=C:\Program Files\LLVM\bin\clang-cl.exe”

# 3) 编译 paint（及依赖的 photol 库 + OpenCV 静态链接）

& C:\ProgramData\chocolatey\bin\ninja.exe -C D:\Community\build paint

**刚才那串报错的真正原因**

- 不是你命令敲错，是 **CMake 4.4 对 clang-cl 的判定 bug** ：它把编译器认成 `Clang` + `MSVC 前端`，却在所有 C++ 编译规则里把二进制名写死成 `clang++`（GCC 驱动），而参数全是 clang-cl（MSVC）风格的 `/nologo`、`/Fo`、`/EHsc`、`-target x86_64-pc-windows-msvc`…。`clang++` 一跑起来是 GCC 模式，自然不认这些 `/` 开头的参数。
- 链接用的是 `lld-link.exe`（完整路径，OK），RC 用的是 `rc`（需要 SDK bin 在 PATH）。

**我做的修复（已生效）**

1. 把 `build/CMakeFiles/rules.ninja` 里的 `clang++` 全部改成 `clang-cl`（10 处编译规则），让同一份 clang 以 CL 模式运行，参数就全认了。
2. 给编译环境补上 PATH：`C:\Program Files\LLVM\bin` + Windows SDK 的 `bin\x64`（提供 `clang-cl` 和 `rc`）。
3. 重新 `ninja -C build paint`，后台运行中（task `hgsdqx`）。

⚠ 一个注意点： **以后如果你重跑 `cmake` 重新 configure，它会把 `rules.ninja` 重新生成、`clang++` 又写回来** ，需要再替换一次。正常的 `ninja` 增量构建不会触发这个。

编完（photol 库重编 + 链 OpenCV 比较耗时）会自动通知我，我再把成功/失败和 `paint.exe` 产物路径报给你。你也可以直接在你本机 PowerShell 用同样的方式跑——核心是那条 `rules.ninja` 的替换。
