Clang Is Now Used to Build Chrome for Windows
blog.llvm.org
blog.llvm.org
[0] https://randomascii.wordpress.com/2018/02/25/compiler-bug-li...
[1] https://randomascii.wordpress.com/2017/07/09/24-core-cpu-and...
Luckily they are all mitigated, fixed, or being fixed, so my Chrome builds run much more smoothly now.
The original work was just finding bugs in the codebase and compiler. It's gone so far!
GCC (mingw.org and mingw-w64 triples) has existed and been able to do this, including and especially cross-compiling, for a long time. No need to manually download a Windows SDK either.
edited to add: to be fair, it's not ABI compatible with MSVC. But it deserves a mention and it's an easier option than MSVC-style build systems for many open source projects.
other than technical merits, permissible license of Clang is attractive for some developers/businesses
Pretty sure this is significant in Chrome's case.
A lot of the windows API can (ab)use this so it’s best to follow it, despite it being C (ish).
A lot of newer Win32 APIs are IUnknown-based COM interfaces. APIs that are probably relevant for Chrome are shell interop, drag & drop, Direct2D, Direct Write, Media Foundation.
Still, this is very different from the first-class support for compatible debug info that Clang provides.
These work great most of the time, but if you start hooking deeply into windows, you realise they are a little bit outdated or incompatible. e.g. I get a lot of errors like
#warning COM interfaces layout in this header has not been verified.
#warning COM interfaces with incorrect layout may not work at all.
#pragma message: Interface Ifoo has unverified layout.
in COM code, and some ATL things it is unable to build at all.Over the past 2-3 years, with great help from a few other LLVM devs I have slowly pushed for native clang support for mingw-w64. With the current in tree HEAD you can now build and bootstrap mingw-w64 with a llvm-only toolchain (no binutils or gcc, thus no disregard of the PECOFF SPEC)
The stack is as follows. LLVM+CLANG+LLD+COMPILER-RT+LIBCXX+LIBCXXABI+LIBUNWIND+MINGW-W64.
The libraries and executables built this way can be dropped into visual studio quite easily, the two environments are now basically interchangeable. This also means we can borrow the PDB debugging work by Zachary Turner and/or any msvc features added to llvm for free that was done by the various googlers working on chrome. See a talk from Reid on the most recent LLVM developer meetup for more info on PDB and how it works. There has been no formal release of this environment yet but you should see something in the coming weeks/months. I keep build scripts here for those interested.
https://github.com/martell/mingw-w64-clang
I'm due another cleanup of the repo now that wine 3.0 is out so I can actually run x64 tests within a linux docker container. I'm going to be doing some blogging to make this more visible with various partners that want to support this.
The most interesting part of this for me was implementing a llvm-dlltool alternative to binutils dlltool that actually works within the PECOFF spec so msvc lib.exe and link.exe likes what it produces.
I did all of the PDB stuff in LLVM, happy to help if you need it (ping me on the mailing list or IRC)
This also works the other way: buggy code that "works" in Clang may now go unnoticed.
This means it will be harder to build Chromium using GCC or MSVC. I see that Arch Linux already has to depend on Clang to build Chromium [1], which isn't very reassuring.
[1] https://www.archlinux.org/packages/extra/x86_64/chromium/
I'm a bit surprised to see that build times in Clang are worse, and that resulting binary performance is comparable.
Maybe that will change when the Clang build starts to use LTCG, as the article mentions.
For reference, in distributed builds, the build times are ridiculously faster using clang. (it shaves many hours off the time).
What does clang offer in this regard? Is incremental build sufficient?
It's literally things like "parsing large numbers of pragmas is slower in clang because nobody has bothered to optimize it".
This is not uncommon for very different codebases.
Clang was, for a long time, many times slower at compiling the linux kernel, for example, because the linux kernel headers have a huge amount of inline assembly and nobody ever bothered to optimize the parsing paths for inline assembly. (now somewhat fixed).
This is just the very typical "hey, when you change the use cases dramatically, you may need to retune/rethink how certain things are done"
I think people just may not realize how wildly different these types of codebases are in what types of statements/things occur.
clang-cl is a drop-in replacement for cl (even the command lines are the same).
But clang-cl is just a driver for clang, and it's still possible to get the ABI compatibility without clang-cl, but you have to know what you're doing and get the flags right.
https://www.youtube.com/watch?v=029YXzHtRy0
The Clang discussion begins at 18:53
First: We were already publishing all our GCC changes, as we did all our work upstream (we worked on a staging branch in the gcc repo, and changes were moved to trunk as fast as possible) Plenty of other companies used our branch and we were happy with it.
We do all our work upstream for clang/llvm as well, and pull compiler releases when upstream is green according to our internal testing. (Pretty much the only cherry picks are a small number of reverts sometimes)
Second, literally nobody has ever come and expressed a concern about using GCC to me.
I've had to explain the runtime and libstdc++ exceptions to people, but that was the other way around -- They weren't worrying, and I needed to make sure they worried and shipped source when they ship it as a .so.
It's just the better platform for writing these things. Heck, this is what is was built for in the first place. GCC is a solid, but also a very traditional compiler.
LLVM was supposed to be a virtual machine environment (hence the name); I remember when it came out and I was in college doing program language research. It entirely dropped that history and got twisted into a compiler platform much later. And clang only came into existence because the developers of g c (in particular, Richard Stallman) did not want to work with Apple on maintaining LLVM as a gdc backend (which was a stupid stupid decision: Apple said they would be willing to give the copyright of LLVM to the FSF, which would have kept all compiler tech under GPL), which was all well after Apple had been switching to LLVM for their compiler stack (in order to obtain weird optimizations).
Of all the reasons, I doubt they're working on fuchsia as a GPL license workaround.
In this case, we just felt clang/llvm was a better architecture to build on at this point. These are also many-year projects.
I was a GCC/gdb/etc maintainer for many years, so i've got nothing against GPL software.
[1] Well, part of it is that by numbers, most newer open source projects are not GPL. The percent of GPL'd new projects before, say, 2010 and after 2010 is very different. I haven't gone far back to see when that starts, but the percentages are quite significant. It used to be 40-50% of new projects, and now it's like 10-20, maybe.
As a note for myself, I should check out llvm in greater detail.
https://blogs.msdn.microsoft.com/vcblog/2017/05/10/c17-featu...
It is as official as Google and Apple devs doing blog posts on Medium.
> We do not plan to support ISO C features that are not part of either C90 or ISO C++.
https://herbsutter.com/2012/05/03/reader-qa-what-about-vc-an...
All the updates regarding C99 and C11 in Visual C++ are related to ANSI/ISO C++ requirements regarding C compatibility, as Herb states.
Regarding legacy, Visual C++ is one of the top C++ compilers doing incremental compilation and linking, which still beats Rust compilation times on Windows.
https://blogs.msdn.microsoft.com/vcblog/2013/06/28/c1114-stl...
and
https://blogs.msdn.microsoft.com/vcblog/2013/07/19/c99-libra...
They even added C99 compound literals and designated initializers:
https://msdn.microsoft.com/en-us/library/hh409293(v=vs.120)....
Compound literals could never be added to C++ because the syntax and semantics conflict with existing C++ constructs.
As for the minor language changes, there was a blog post that I cannot locate now, stating it was to the extent required for porting well known projects to Windows, the remaining features would depend on key customers feedback.
If that's the case then Microsoft should get its corporate ass out of C's standardization committee. It makes no sense to waste their time forcing requirements onto a standard that they refuse to comply with.
Edit Mingw-w64 its quite nice and includes gcc without all stuff cgwin does.
In fact, there are way too many c++ compilers if you ask me. I would gladly accept a world where clang is the one and only.
Not me, IMO clang is where it is due to competition.
And luckily you don’t have any saying in such matters.
https://stackoverflow.com/questions/19269350/how-to-generate...
Lack of VC++ ABI support would be another reason.
2) Debug Information. GCC does not emit PDBs, it emits DWARF. This means you cannot use Visual Studio to debug, you cannot use vTune or WPA to profile, you cannot use symbol / source servers.
3) There are licensing implications, GPL != BSD and it's easier to use BSD.
These are the main reasons. There are other reasons though, such as if the entire goal is to get down to 1 toolchain and that toolchain is X, then why would you waste your time converting Y to Z?
You can on 64 bit.
At one point, after updating the toolchain from gcc 4.x to 7.x and from mingw32 to mingw-w64, it started to produce broken binaries.
The manifestation of that brokenness was that binaries refused to start properly on systems where the toolchain was not installed. It just silently exited during startup - no crash, or error message, or anything.
This applied both to binaries that were cross-built on linux, and binaries built using MSYS2 on Windows.
I decided to just switch to clang-cl + MSVC headers instead, which worked properly. The only gotcha there was the need to store the headers on a case insensitive file system (I chose vfat) when compiling on linux, because the case of the includes aren't consistent (e.g. Windows.h vs. windows.h), even in the MSVC headers themselves.
As far as I could tell, the only DLLs the binaries referenced were msvcrt.dll and standard windows DLLs (KERNEL32, USER32, etc).
The application was also plain C.
Even if missing compiler runtime libraries were the issue, I would have expected the program crash or fail with an error message.
2. Not performant (Relative to other solutions)
3. Would be the odd man out. Literally all other development was on clang/llvm at this point.
Supporting mingw would have meant duplicating all performance/etc work for GCC.
4. Chrome also wanted other benefits that clang/LLVM would bring them (easy ability to build various forms of refactoring and analysis tooling, etc)
My point was that, in the context of Chrome using ninja, the claim that "Ninja is used because it's simple, multiplatform and very fast. The mainstream alternatives offer at most 2 out of 3." is a bit odd considering that the decision doesn't seem to be ninja vs mainstream alternatives but rather ninja+gn(or gyp or whatever else) vs alternatives.
From that document:
Asynchronous Exceptions (SEH): Partial. Structured exceptions (__try / __except / __finally) mostly work on x86 and x64. LLVM does not model asynchronous exceptions, so it is currently impossible to catch an asynchronous exception generated in the same frame as the catching __try.
(To the extent possible. There are some edge cases left, but they're very rare. Essentially all the real-world code we've seen works now.)
Chrome is currently built using VS 2017 15.3 (that's update 3). Eventually we will probably upgrade to VS 2017 15.7 in order to get more STL conformance, linker improvements, etc.