While building WebKit using the latest incarnation of Visual Studio, VS2012, I’ve hit compiler errors in gtest that seemed overwhelming. Since the errors were clearly coming from a testing framework, I thought it was reasonable to wait until it was fixed. After all, WebKit did build, sans tests of course, and VS2012 is new.
I thought it interesting to find the root cause. It turned out to be a rather simple fix. And I learned a thing or two along the way. First, this is a known issue and a bug was reported to gtest back in early June. But I discovered the solution from StackOverflow first.
The Visual Studio 2012 C++ compiler adds a number of new C++11 features and improvements. Historically, when there was no variable template argument support in the language, implementations had to support many versions of the template class or function in question each with an increasing number of arguments. This resulted in a lot of tedious work, which was sometimes auto-generated by scripts macros, but also caused bloat in both source code and compiler time and resources. Worst of all is that it always limited the maximum number of arguments to the template in question. One had to manually create versions with more and more arguments to satisfy their needs. With Variadic templates all of that will be history. All except for compile time, perhaps. There is a certain overhead to adding language features after all.
A decision was made within the VS2012 C++ standard library team, a.k.a. Stephan T. Lavavej or STL as he’s also known, to change the implementation of variadic template headers as explained on the features page of the new compiler (scroll to “Faux variadics”). Astute developers will have figured out that this means that the compiler doesn’t support variadic templates yet. Otherwise, they’d need to reimplement the templates in question using the new and shiny variadic template feature and, well, we wouldn’t be having this discussion.
Unfortunately for us, the new compiler, while improved on many fronts including the standard library, seems to have regressed in terms of memory consumption. This forced the team to reduce the default number of template arguments to 5 instead of the previous 10. As a result, gtest fails to compile where it passes 6 or more parameters to std::tuple, for example. A workaround is supported, with the caveat that increasing the compiler memory limit -using the /Zm
switch- might be necessary, in the form of a preprocessor macro: _VARIADIC_MAX
.
After passing /D_VARIADIC_MAX=10
to the compiler, not only does gtest compile cleanly, but so does all of WebKit. The fix is to add to our patch a small section:
if ($versionName eq "vs2012") { print $fh "\@echo Increasing vardiadic limit to 10 (_VARIADIC_MAX=10).\r\n"; $replace_string = "s/\\<PreprocessorDefinitions\\>_VARIADIC_MAX=10;/\\<PreprocessorDefinitions\\>/g"; # Delete _VARIADIC_MAX=10. print $fh "perl -p -i -e \"" . $replace_string . "\" \"" . $props_filename . "\"\r\n"; $replace_string = "s/\\<PreprocessorDefinitions\\>/\\<PreprocessorDefinitions\\>_VARIADIC_MAX=10;/g"; # Add _VARIADIC_MAX=10. print $fh "perl -p -i -e \"" . $replace_string . "\" \"" . $props_filename . "\"\r\n"; }
And we have a new patch that includes this fix and a couple of other improvements that builds WebKit with VS2010 and VS2012.