clang on Windows detected with MSVC interface

Hello,
i try to compile a program on windows with ninja using clang++ (not clang-cl), in order to be able to use the same flags as on macOS and simplify the cmake scripts.
However i encountered some strange behaviour, it seems like clang++ is detected having a MSVC-compatible interface. I ran some tests to understand the information better:

cmake .. -G "Visual Studio 16 2019"
CMAKE_CXX_COMPILER_ID: MSVC
CMAKE_CXX_SIMULATE_ID:
CMAKE_CXX_COMPILER_FRONTEND_VARIANT:

cmake .. -G "Visual Studio 16 2019" -T ClangCL
CMAKE_CXX_COMPILER_ID: Clang
CMAKE_CXX_SIMULATE_ID: MSVC
CMAKE_CXX_COMPILER_FRONTEND_VARIANT: MSVC

cmake .. -G Ninja -DCC="C:\Program Files\LLVM\bin\clang.exe" -DCXX="C:\Program Files\LLVM\bin\clang++.exe"
CMAKE_CXX_COMPILER_ID: Clang
CMAKE_CXX_SIMULATE_ID: MSVC
CMAKE_CXX_COMPILER_FRONTEND_VARIANT: GNU

cmake .. -G Ninja -DCC="C:\Program Files\LLVM\bin\clang-cl.exe" -DCXX="C:\Program Files\LLVM\bin\clang-cl.exe"
CMAKE_CXX_COMPILER_ID: Clang
CMAKE_CXX_SIMULATE_ID: MSVC
CMAKE_CXX_COMPILER_FRONTEND_VARIANT: GNU

Clang-cl that is shipped alongside VS2019 is reported, as expected, to be clang simulating MSVC with a MSVC frontent.
However both clang and clang-cl shipped via the official LLVM reports to be Clang simulating MSVC (which clang actually isn’t), having a GNU interface (which clang-cl actually hasn’t).
How does one distinguish between clang-cl and clang given this situation?
Thank you, Stephan

-DCC="..." -DCXX="..."

Those options will not set the compiler. CC and CXX are supported only as environment variables to initialize the CMAKE_C_COMPILER and CMAKE_CXX_COMPILER CMake variables. What is the rest of the CMake output in each case? In particular, what are the lines

-- The C compiler identification is ...
...
-- Check for working C compiler: ...
...
-- The CXX compiler identification is ...
...
-- Check for working CXX compiler: ...

?

Thanks for your reply, i re-run the commands using -DCMAKE_C_COMPILER instead of -DCC, these are the relevant output lines.
It now indeed seems to distinguish between CMAKE_CXX_COMPILER_FRONTEND_VARIANT: GNU for
clang and CMAKE_CXX_COMPILER_FRONTEND_VARIANT: MSVC for clang-cl.
So I guess this is the variable that i should be looking at, right?

cmake .. -G "Visual Studio 16 2019"
-- Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.19042.
-- The C compiler identification is MSVC 19.28.29914.0
-- The CXX compiler identification is MSVC 19.28.29914.0
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.28.29910/bin/Hostx64/x64/cl.exe - skipped
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.28.29910/bin/Hostx64/x64/cl.exe - skipped
CMAKE_CXX_COMPILER_ID: MSVC
CMAKE_CXX_SIMULATE_ID:
CMAKE_CXX_COMPILER_FRONTEND_VARIANT:

cmake .. -G "Visual Studio 16 2019" -T ClangCL
-- Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.19042.
-- The C compiler identification is Clang 11.0.0 with MSVC-like command-line
-- The CXX compiler identification is Clang 11.0.0 with MSVC-like command-line
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/Llvm/x64/bin/clang-cl.exe - skipped
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/Llvm/x64/bin/clang-cl.exe - skipped
CMAKE_CXX_COMPILER_ID: Clang
CMAKE_CXX_SIMULATE_ID: MSVC
CMAKE_CXX_COMPILER_FRONTEND_VARIANT: MSVC

cmake .. -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang
-- The C compiler identification is Clang 12.0.0 with GNU-like command-line
-- The CXX compiler identification is Clang 12.0.0 with GNU-like command-line
-- Check for working C compiler: C:/Program Files/LLVM/bin/clang.exe - skipped
-- Check for working CXX compiler: C:/Program Files/LLVM/bin/clang.exe - skipped
CMAKE_CXX_COMPILER_ID: Clang
CMAKE_CXX_SIMULATE_ID: MSVC
CMAKE_CXX_COMPILER_FRONTEND_VARIANT: GNU

cmake .. -G Ninja -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl
-- The C compiler identification is Clang 12.0.0 with MSVC-like command-line
-- The CXX compiler identification is Clang 12.0.0 with MSVC-like command-line
-- Check for working C compiler: C:/Program Files/LLVM/bin/clang-cl.exe - skipped
-- Check for working CXX compiler: C:/Program Files/LLVM/bin/clang-cl.exe - skipped
CMAKE_CXX_COMPILER_ID: Clang
CMAKE_CXX_SIMULATE_ID: MSVC
CMAKE_CXX_COMPILER_FRONTEND_VARIANT: MSVC

Yes.

Thanks for your help, the compiler is now identified correctly, but i’m struggeling with the linker now.
It fails because of missing symbols:
lld-link: error: <root>: undefined symbol: mainCRTStartup
From what i understand this means that the windows runtime isn’t linked correctly.
I would assume that CMAKE_MSVC_RUNTIME_LIBRARY is the variable i want to look at, but none of the possible values led to correct linking. Changing the CMAKE_BUILD_TYPE didn’t help either.
Is there another option that is needed for this setup?

cmake .. -G Ninja -D CMAKE_C_COMPILER=clang -D CMAKE_CXX_COMPILER=clang++
-- The C compiler identification is Clang 12.0.0 with GNU-like command-line
-- The CXX compiler identification is Clang 12.0.0 with GNU-like command-line
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - failed
-- Check for working C compiler: C:/Program Files/LLVM/bin/clang.exe
-- Check for working C compiler: C:/Program Files/LLVM/bin/clang.exe - broken
...

    Run Build Command(s):C:/ProgramData/chocolatey/bin/ninja.exe cmTC_3fdcc && [1/2] Building C object CMakeFiles/cmTC_3fdcc.dir/testCCompiler.c.obj
    [2/2] Linking C executable cmTC_3fdcc.exe
    FAILED: cmTC_3fdcc.exe
    cmd.exe /C "cd . && C:\PROGRA~1\LLVM\bin\clang.exe -fuse-ld=lld-link -nostartfiles -nostdlib -g -Xclang -gcodeview -O0 -D_DEBUG -D_DLL -D_MT -XAlso clang --dependent-lib=msvcrtd -fuse-ld=lld-link   -Xlinker /subsystem:console CMakeFiles/cmTC_3fdcc.dir/testCCompiler.c.obj -o cmTC_3fdcc.exe -Xlinker /implib:cmTC_3fdcc.lib -Xlinker /pdb:cmTC_3fdcc.pdb -Xlinker /version:0.0   -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -loldnames && cd ."
    lld-link: error: <root>: undefined symbol: mainCRTStartup
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    ninja: build stopped: subcommand failed.

The default CMAKE_MSVC_RUNTIME_LIBRARY should work fine. We do have nightly testing for the GNU-like Clang compiler with the MSVC ABI. Please be sure you are using a fresh/empty build directory and not trying to change the compiler in an existing directory.

I’ll try to reproduce this situation on a windows machine. As Brad mentioned, some test run checks for this case and they seem to work…

Of course I’ve run the commands with a clean directory, i’ve even just re-installed visual studio with no success.
For the reference: I’m using CMake 3.20.3, LLVM 12.0 (both installed via chocolatey), and Visual Studio Community 2019 Version 16.10.0 on Windows 10 Pro 21H1 (build 19043.985).
Thanks for checking this out!

I used the windows development evaluation vm and once the tools setup, I ran inside a vs native development console the following:

C:\Users\User\Documents\Test\build>cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ .. -- The C compiler identification is Clang 12.0.0 with GNU-like command-line -- The CXX compiler identification is Clang 12.0.0 with GNU-like command-line -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: c:/Program Files/LLVM/bin/clang.exe - skipped -- Detecting C compile features -- Detecting C compile features - done -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: c:/Program Files/LLVM/bin/clang++.exe - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done -- Build files have been written to: C:/Users/User/Documents/Test/build

There must be something causing the failure on your setup.
Are you sure, you used the development environment command prompt ?
If it still fails, could you send the output of the command:
cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ --trace ..

fwiw I use -Xclang when setting my options on clang through cmake, that works on both clang-cl and clang++, and will be a clang option on both. This doesn’t work with some options, for some reason.

In particular you must do this when setting -Wall -Wextra ... with clang, since if you don’t then on windows clang-cl will translate -Wall to /Wall which it implements as -Weverything, probably not what you had in mind.

Ah, now i noticed something.
I’ve been using the developer powershell. It seems like this was configured for x86, and failed to invoke the compiler with the error that i’ve posted before.
I get the same behaviour using the x86 Native Tools Command Prompt for VS 2019.
If i use the x64 Native Tools Command Prompt for VS 2019, the compiler check indeed passes!
Thank you for your help!