Clang on windows, debugging, compile times

I wanted to see if it was possible to debug clang compiled code in Visual Studio (clang MSVC compatibility page says it should be working). But the .pdb file generated by clang, while it loads in Visual Studio, doesn't allow to place breakpoints or watch values. After a bit of search I found that the -gcodeview flag is necessary to generate compatible debug information. To my understanding, codeview is the Microsoft format for debug information, and program database (PDB) is an "API" to access them and other information. If you don't pass -gcodeview I suppose the linker outputs DWARF symbols in the pdb (not sure).

After passing the flag to clang I can debug. But the display and stepping is weird and I don't know if it's intentional or not.

When stepping, part of the line is highlighted in yellow. At first I though it was showing what data was currently used by the current instruction but I'm not sure. Also you often need to step several time to just move one line. Displaying the disassembly on the side, it seems that stepping steps on each instruction.

Did anyone tried to debug clang compiled code in MSVC ? Is there a way to make it work better ? I tried the -Og flags but it didn't change anything and multiplied the compile time by at least 2.

Also I was surprised that clang was slower to compile. I compiled the same code (about 16k lines of C code, not counting system headers) with both compiler, as C and CPP, with and without linking. I tried to have similar flags on both but couldn't find some on clang. Using MSVC 2017 and clang 6. Here are the results.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
== C ==
cl, C, 1.028s
cl Y:\project\main.c -Feproject.exe -Od -MTd -Gm- -nologo -GR- -EHa- -Oi -fp:fast -WX -W4 -wd4201 -wd4505 -wd4996 -wd4100 -wd4189 -wd4204 -Zi -Fm -FC -DWINDOWS -DTARGET_x64 -DCOMPILER_CL -DDEBUG -DLOG -link -INCREMENTAL:NO -opt:ref -subsystem:windows -entry:mainCRTStartup wininet.lib shell32.lib user32.lib OpenGL32.lib GDI32.lib

clang, C, 1.841s
clang Y:\project\main.c -oproject.exe -O0 -g -gcodeview -fno-exceptions -fno-cxx-exceptions -ffast-math -fno-rtti -Werror -fdiagnostics-absolute-paths -DWINDOWS -DTARGET_x64 -DCOMPILER_CLANG -DDEBUG -DLOG --for-linker -INCREMENTAL:NO --for-linker -opt:ref --for-linker -subsystem:windows --for-linker -entry:mainCRTStartup -lwininet.lib -lshell32.lib -luser32.lib -lOpenGL32.lib -lGDI32.lib

== No linking ==
cl, C, no linker, 0.421s
cl Y:\project\main.c -Feproject.exe -Od -c -MTd -Gm- -nologo -GR- -EHa- -Oi -fp:fast -WX -W4 -wd4201 -wd4505 -wd4996 -wd4100 -wd4189 -wd4204 -Zi -Fm -FC -DWINDOWS -DTARGET_x64 -DCOMPILER_CL -DDEBUG -DLOG 

clang, C, no linker, 1.450s
clang Y:\project\main.c -oproject.exe -O0 -g -gcodeview -c -fno-exceptions -ffast-math -fno-rtti -Werror -fdiagnostics-absolute-paths -Wno-c++11-compat-deprecated-writable-strings -Wno-writable-strings -DWINDOWS -DTARGET_x64 -DCOMPILER_CLANG -DDEBUG -DLOG 

== CPP ==
cl, CPP, 1.373s
cl Y:\project\main.cpp -Feproject.exe -Od -MTd -Gm- -nologo -GR- -EHa- -Oi -fp:fast -WX -W4 -wd4201 -wd4505 -wd4996 -wd4100 -wd4189 -wd4204 -Zi -Fm -FC -DWINDOWS -DTARGET_x64 -DCOMPILER_CL -DDEBUG -DLOG -link -INCREMENTAL:NO -opt:ref -subsystem:windows -entry:mainCRTStartup wininet.lib shell32.lib user32.lib OpenGL32.lib GDI32.lib 

clang, CPP, 2.136s
clang Y:\project\main.cpp -oproject.exe -O0 -g -gcodeview -fno-exceptions -fno-cxx-exceptions -ffast-math -fno-rtti -Werror -fdiagnostics-absolute-paths -Wno-c++11-compat-deprecated-writable-strings -Wno-writable-strings -DWINDOWS -DTARGET_x64 -DCOMPILER_CLANG -DDEBUG -DLOG --for-linker -INCREMENTAL:NO --for-linker -opt:ref --for-linker -subsystem:windows --for-linker -entry:mainCRTStartup -lwininet.lib -lshell32.lib -luser32.lib -lOpenGL32.lib -lGDI32.lib 

A few other questions:
- Is there an equivalent to -MT / -MTd flag for clang ?
- The -E flag makes clang print the pre-processor result to stdin. Is there a way to print it to a file directly without redirecting the console output ?
- Is there a way to limit the number of error that cl outputs (like clang's -ferror-limit= )?

Edited by Simon Anciaux on Reason: Initial post
If you want to use clang.exe with MSVC debugger I suggest using clang-cl.exe. It has cl.exe compatible options - including -MD/-MT and it produces codeview format debug info by default (when using -Zi).

Otherwise you'll need to use something like this to simulate -MD behavior: "clang main.c -D_DLL -Xlinker /NODEFAULTLIB -lmsvcrt -lucrt -lmsvcprt -lvcruntime -lkernel32"

To produce preprocessed output to file with clang.exe add "-o filename". clang.exe has compatible options with gcc.exe - so almost anything that works with gcc.exe will work with clang.exe

Afaik there is no way to change error limit to cl.exe.

Btw, great way do debug what clang/clang-cl.exe is doing is to use "-v" argument - it will show what options exactly driver (clang.exe, clang-cl.exe) is passing down to actualy compiler. You can even use this arguments yourself after "-cc1" switch.

As for slowness - what clang.exe are you using? It is possible to compile clang in release mode (with optimizations) but leave all asserts enabled (which helps debugging a lot). But leaving asserts makes it run much slower. It may be case that clang you are using is not fully optimized.

Edited by Mārtiņš Možeiko on
Thanks, I didn't found the time to go back to that this week, but I tried clang-cl and it seems that debugging works well with it. I still want to try to find what is necessary to make it work with "regular" clang. -v should help with that.

The version of clang I use is the one from clang.llvm.org download page.
I found the flag that makes the debug work correctly. It's -gno-column-info. The documentation doesn't give lots of information but if you don't specify it, the compiler will have the "-dwarf-column-info" flag which was one of the difference on using clang-cl ... Zi -v and clang-cl ... -v.

To summarize, to get debug symbols working in visual studio from clang:
1
clang main.c -O0 -g -gcodeview -gno-column-info

About clang-cl: it's showing lots of error that don't show with cl or clang. I believe it's caused by -WX -W4 where W4 would cause more error types to be reported in clang.

As for the speed, is there a download somewhere of an "optimized" version of clang ?
Yeah, +1 for the -v switch I used it extensively recently, great way to see to what the actual MSVC switches translate to on the clang-cl driver.
As for your third question, shouldn't it be possible to pass "-Xclang -ferror-limit=" to clang-cl? I might be wrong about that.

And if you took llvm+clang from the llvm releases download page I think the pre-built binaries are compiled in release mode (but the default when compiling from source is debug) so it should be fine. If you want to try rebuilding it I can give you some pointers since I've been doing it quite a few times recently, it's not too bad with the newer versions but it takes some time to hunt details down due to how LLVM documents their stuff.
I believe he is asking about increasing error limit for cl.exe, not clang-cl.exe.

Release build of clang can still be built with assertions. Just compiling LLVM in release mode does not mean that assertions will be disabled. Assertions is a separate argument than choosing Debug vs Release build. This helps debugging/troubleshooting release builds - which are way faster than debug builds, but still do some sanity checks on internal state with asserts.

You can check how they are build by running "llc.exe --verison". If it says "Optimized build" that means it is release build without assertions. If it says "Optimized build with assertions" that is release build with assertions. and "DEBUG build [with assertions]" is debug build with/without assertions. https://github.com/llvm-mirror/ll...lib/Support/CommandLine.cpp#L2126

Edited by Mārtiņš Možeiko on
Ah, but I was under the impression that assertions are off in Release builds as stated in the LLVM_ENABLE_ASSERTIONS argument in the docs (https://www.llvm.org/docs/CMake.html#llvm-specific-variables), but I might be misreading that?

Enables code assertions. Defaults to ON if and only if CMAKE_BUILD_TYPE is Debug.

Granted, this doesn't really mean that the pre-built binaries are built with the default settings even if they are in release.

EDIT: So I was interested to check this out as I didn't know llc outputs this information (thanks Martins!) and it seems (at least for the 6.0.0 version) the pre-built binaries for linux do indeed come with assertions off, "llc --version" (or --verison, as martins said :P) returns just "Optimized build", but curiously enough the "Clang for Windows" installer doesn't include llc.exe, as LLVM seems to be integrated into clang (?). So I'm not sure if there is a handy way to check this on Windows without rebuilding from source, but I haven't looked that hard into it.

Edited by Halarious on
mmozeiko
I believe he is asking about increasing error limit for cl.exe, not clang-cl.exe.

Yes, I was talking about cl.exe.

As Halarious said there is no llc.exe in the installer for windows. I'll try to compile it from source.

Edited by Simon Anciaux on Reason: typo
Oh, I did not realized that llvm tools are not in windows binary package.
There's another way - I did "strings clang.exe", output contained "Optimized build", but no " with assertions". That means assertions are not an issue.

Edited by Mārtiņš Možeiko on
So Clang is just slower ?

Halarious
If you want to try rebuilding it I can give you some pointers since I've been doing it quite a few times recently

Before mmozeiko's reply I tried to recompile it but ended up with a debug version (after 3 hours of compilation. I was happy). What do I need to do to build a release version ? I created the project with the following command
1
D:\temp\cmake\bin\cmake.exe -G "Visual Studio 15 2017 Win64" -Thost=x64 -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_ASSERTIONS=OFF -DLLVM_TARGETS_TO_BUILD=X86 ..\llvm

And I selected Release in Visual Studio.
Hmm, I fear I don't really see what could be wrong at first glance, the build type should give you the Release projects. Though I haven't built through Visual Studio, I have a setup with make files, so I am unsure if the projects have to be setup somehow individually in VS, but I doubt it.
Are you sure it output the debug version, you ran the llc command from martins? I vaguely remember Visual Studio putting the binaries in a 'Debug' folder, even though they were not way back when I first tried compiling some project.
Yeah it says debug in the output of llc --version.
1
2
3
4
5
6
7
8
9
LLVM (http://llvm.org/):
  LLVM version 6.0.0
  DEBUG build.
  Default target: x86_64-pc-windows-msvc
  Host CPU: nehalem

  Registered Targets:
    x86    - 32-bit X86: Pentium-Pro and above
    x86-64 - 64-bit X86: EM64T and AMD64
The binaries are in a Release folder.
I've been trying to do this recently as well.
Are you still using clang Simon? What does your setup look like after a few months?

Cheers,
Andrew
I use clang when msvc error messages aren't clear enough for me (it rarely the case but happens sometime). I tried to compile clang twice but always got a debug build and since the process takes 3 hours I don't want to try that again (my CPU is about 9 years old now, so it's probably faster for anyone else). I'm still on the same clang 6 build that was released on the clang web site.

Edited by Simon Anciaux on Reason: typo