$npx -y skills add mohitmishra786/low-level-dev-skills --skill msvc-clMSVC cl.exe and clang-cl skill for Windows C/C++ projects. Use when configuring Visual Studio builds, MSBuild, or clang-cl as a drop-in MSVC replacement. Covers translating GCC/Clang flags to MSVC equivalents, runtime library selection, Windows SDK setup, and diagnosing MSVC-spec
| 1 | # MSVC cl.exe and clang-cl |
| 2 | |
| 3 | ## Purpose |
| 4 | |
| 5 | Guide agents through Windows C/C++ compilation: MSVC `cl.exe`, `clang-cl` as MSVC-compatible driver, MSBuild project settings, and runtime library choices. |
| 6 | |
| 7 | ## Triggers |
| 8 | |
| 9 | - "How do I compile with MSVC from the command line?" |
| 10 | - "What is the MSVC equivalent of `-O2`?" |
| 11 | - "/MT vs /MD — which do I use?" |
| 12 | - "How do I use clang-cl instead of cl.exe?" |
| 13 | - "I'm getting LNK errors on Windows" |
| 14 | - "How do I generate PDB files?" |
| 15 | |
| 16 | ## Workflow |
| 17 | |
| 18 | ### 1. Set up the environment |
| 19 | |
| 20 | MSVC requires the Visual Studio environment variables. Use the Developer Command Prompt or set up manually: |
| 21 | |
| 22 | ```cmd |
| 23 | REM x64 native |
| 24 | "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" |
| 25 | |
| 26 | REM x86 cross (host x64, target x86) |
| 27 | "...\vcvarsamd64_x86.bat" |
| 28 | |
| 29 | REM Check compiler version |
| 30 | cl /? |
| 31 | ``` |
| 32 | |
| 33 | In CMake, use the "Visual Studio 17 2022" generator or pass `-DCMAKE_GENERATOR="Visual Studio 17 2022"`. |
| 34 | |
| 35 | ### 2. Flag translation: GCC → MSVC |
| 36 | |
| 37 | | GCC/Clang | MSVC cl.exe | Notes | |
| 38 | |-----------|-------------|-------| |
| 39 | | `-O0` | `/Od` | Debug, no optimisation | |
| 40 | | `-O1` | `/O1` | Minimise size | |
| 41 | | `-O2` | `/O2` | Maximise speed | |
| 42 | | `-O3` | `/Ox` | Full optimisation | |
| 43 | | `-Os` | `/Os` | Favour size | |
| 44 | | `-g` | `/Zi` | PDB debug info | |
| 45 | | `-g` (embedded) | `/Z7` | Debug info in object file | |
| 46 | | `-Wall` | `/W3` or `/W4` | Warning level | |
| 47 | | `-Werror` | `/WX` | Warnings as errors | |
| 48 | | `-std=c++17` | `/std:c++17` | Standard selection | |
| 49 | | `-DFOO=1` | `/DFOO=1` | Preprocessor define | |
| 50 | | `-I path` | `/I path` | Include path | |
| 51 | | `-c` | `/c` | Compile only (no link) | |
| 52 | | `-o out` | `/Fe:out.exe` or `/Fo:out.obj` | Output file | |
| 53 | | `-shared` | `/LD` | Build DLL | |
| 54 | | `-fPIC` | (implicit on Windows) | Not needed on Windows | |
| 55 | | `-flto` | `/GL` (compile) + `/LTCG` (link) | Whole program optimisation | |
| 56 | |
| 57 | ### 3. Runtime library selection |
| 58 | |
| 59 | This is the most common source of LNK errors on Windows. |
| 60 | |
| 61 | | Flag | Runtime | Use case | |
| 62 | |------|---------|---------| |
| 63 | | `/MD` | `MSVCRT.dll` (dynamic) | Release, DLL linkage (recommended default) | |
| 64 | | `/MDd` | `MSVCRTd.dll` (debug dynamic) | Debug builds | |
| 65 | | `/MT` | Static CRT | Standalone exe; avoid mixing with DLLs | |
| 66 | | `/MTd` | Static CRT debug | Debug + static | |
| 67 | |
| 68 | **Rule:** All objects and libraries in a link must use the same runtime. Mixing `/MT` and `/MD` causes `LNK2038: mismatch detected`. |
| 69 | |
| 70 | ### 4. clang-cl |
| 71 | |
| 72 | `clang-cl` is Clang's MSVC-compatible driver. It accepts `cl.exe`-style flags and can replace `cl.exe` in most MSBuild/CMake projects. |
| 73 | |
| 74 | ```cmd |
| 75 | REM Install: part of LLVM Windows release or VS "LLVM" component |
| 76 | |
| 77 | REM Basic usage (MSVC-style flags) |
| 78 | clang-cl /O2 /std:c++17 /MD src.cpp /Fe:prog.exe |
| 79 | |
| 80 | REM Pass Clang-native flags with /clang: |
| 81 | clang-cl /O2 /clang:-Rpass=inline src.cpp /Fe:prog.exe |
| 82 | |
| 83 | REM Use in CMake |
| 84 | cmake -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl .. |
| 85 | ``` |
| 86 | |
| 87 | Minimum Clang version for MSVC STL compatibility: Clang 8+. For C++20 features with MSVC STL: Clang 14+. |
| 88 | |
| 89 | Source: <https://learn.microsoft.com/en-us/cpp/build/clang-support-msbuild> |
| 90 | |
| 91 | ### 5. PDB files and debugging |
| 92 | |
| 93 | ```cmd |
| 94 | REM Compile with /Zi (external PDB) and /Fd (PDB name) |
| 95 | cl /Zi /Fd:prog.pdb /O2 src.cpp /link /DEBUG |
| 96 | |
| 97 | REM /Z7: debug info embedded in .obj (no separate PDB for objects) |
| 98 | cl /Z7 /O2 src.cpp /link /DEBUG /PDB:prog.pdb |
| 99 | ``` |
| 100 | |
| 101 | For WinDbg or VS debugger, ensure the PDB is alongside the executable or set the symbol path. |
| 102 | |
| 103 | ### 6. Common LNK errors |
| 104 | |
| 105 | | Error | Cause | Fix | |
| 106 | |-------|-------|-----| |
| 107 | | `LNK2019: unresolved external` | Missing `.lib` | Add library in project settings or `/link foo.lib` | |
| 108 | | `LNK2038: mismatch detected for 'RuntimeLibrary'` | Mixed `/MT` and `/MD` | Unify all to `/MD` or `/MT` | |
| 109 | | `LNK1104: cannot open file 'foo.lib'` | Library not in search path | Add path via `/LIBPATH:` or `LIB` env var | |
| 110 | | `LNK2005: already defined` | Multiple definitions | Use `__declspec(selectany)` or check for duplicate definitions | |
| 111 | | `LNK4098: defaultlib 'LIBCMT' conflicts` | Runtime mismatch | Explicitly pass `/NODEFAULTLIB:LIBCMT` or unify runtimes | |
| 112 | |
| 113 | ### 7. Useful cl.exe flags |
| 114 | |
| 115 | ```cmd |
| 116 | REM Preprocessed output |
| 117 | cl /P src.cpp # produces src.i |
| 118 | |
| 119 | REM Assembly output |
| 120 | cl /FA /O2 src.cpp # produces src.asm (MASM syntax) |
| 121 | cl /FAs # interleave source + asm |
| 122 | |
| 123 | REM Show include files |
| 124 | cl /showIncludes src.cpp |
| 125 | |
| 126 | REM Compiler version |
| 127 | cl /? 2>&1 | findstr /i "version" |
| 128 | ``` |
| 129 | |
| 130 | For flag details, see [references/flags.md](references/flags.md). |
| 131 | |
| 132 | ## Related skills |
| 133 | |
| 134 | - Use `skills/compilers/clang` for clang-cl's Clang-native diagnostics |
| 135 | - Use `skills/build-systems/cmake` for CMake |