Hack: Parallel MSBuilds from within the Visual Studio IDE
There were a number of interesting comments from my post on Faster Builds with MSBuild using Parallel Builds and Multicore CPUs.
Here's a few good ones, and some answers. First,
Is the developer that sits inside of VS all day debugging able to take advantage of the same build performance improvements?
Yes, I think. This post is about my own hack to make it work.
@Scott, there are still people using VS2005 and .Net 2.0 (our employers are either too cheap to upgrade or we work in non-profit[my case]) So it would be nice for posts like this to clearly denote that these are things only available in the 3.0/3.5+ world. Or should I just assume that .Net 2.0 is dead?
Certainly 2.0 is not dead, considering that 3.5 is still built on the the 2.0 CLR. Additionally, if you're a 2.0 shop, there's really no reason not to upgrade to VS2008 and get all the IDE improvements while still building for .NET 2.0SP1 as MSBUild supports multitargeting.
However, the underlying question here is, "why are you teasing me?" as this gentleman clearly wants faster builds on .NET 2.0. Well, this trick under VS2008 still works when building 2.0 stuff.
If you're using a Solution File (SLN) it's automatic, and if you're using custom MSBuild files, you can build .NET 2.0 stuff with the 3.5 MSBuild by putting
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
under a <PropertyGroup> in your C# project. Then you can use /m and get multiproc builds. Not much changes though, because either way your build output is running on CLR2.0. (.NET 3.0 and .NET 3.5 use CLR2.0 underneath.) You will get some warnings if you try to use v3.0/v3.5 types.
It's true that parallel managed code compilation lags behind unmanaged.
Welcome, msbuild, to the 21st century. ;-) GNU make has the -j switch (the equivalent to /m here) _at least_ since the early-to-mid 1990's. We use its mingw port to drive Visual Studio 2003's commandline interface to build vcproj files and to handle dependencies, and since we got multi-core build machines, our build times have improved tremendously (we're talking about roughly 2,5 million SLOCs).
There's a number of reasons for that. For example, Visual Basic is compiling in the background all the time while you're typing in VS using a non-reentrant in-proc compiler. The in-proc C# compiler is the same way.
The Multicore MSBuild with VS Hack
This trick is unsupported because it hasn’t been tested. Off the top of our collective head, I can’t think of why it wouldn’t work OK, at least if your solution is all VB/C#. Having VC projects in your solution, especially if there are project references with the VB/C# projects, would probably not work so well. That’s because VC projects are not native MSBuild format in VS2008.
To start with, this is a totally obvious hack. We'll add an External Tool to Visual Studio to call MSBuild, then add some Toolbar buttons.
First, Tools | External Tools. We'll add MSBuild, pointing it to the v3.5 .NET Framework folder. Then, we'll add /m to the arguments for multi-proc and /v:m (where the v is verbosity and the m is minimal) to tone down MSBuild's chattiness. Finally, we'll check the Use Output Window box and set the initial directory to the current Solution's Directory.
Next, we'll right click on the Toolbar, and hit Customize.
Then, from the Commands tab, drag the number of the newly added External Tool (mine is #3) to the Toolbar. I also added a little Lode Runner icon to the button. Additionally, I added a Clean Solution option, just because I like it handy.
You can also re-map Ctrl-Shift-B if it makes you happy, but I used Ctrl-Shift-M, mapping it to the Tools.ExternalCommand, again, in my case it is #3.
At this point, I can now run MSBuild out-of-proc from inside Visual Studio.
What DOESN'T Work
The only thing that doesn't work for me so far is that the errors reported by MSBuild don't appear neatly parsed in the Error List. For some, this may be a deal breaker. However, the good news is that if you double click on the errors in the Output Window you WILL get taken automatically to the right file and line number which is all I personally care about. Still, sucks.
Gotchas for this Hack
If you're building against a SLN file you can use Project References or manually specified project dependencies otherwise MSBuild has no way to figure out the dependencies and you might get "file locked" or other weird concurrency errors.
Also, even if Project to Project references are set up, sometimes project authors are a bit sloppy (I've done this) and inadvertently access the same file in multiple projects, which can cause spurious file locking/access errors. If you see this behavior, turn off multiproc.
Note also that while you can do builds with MSBuild like this, if you get F5 and start a debug session the VS in-process compilers will do a quick build. It WILL figure out that it doesn't need to do anything, but it will check.
Hey, it's NOT faster for me?
If you have a small solution (<10 projects) and/or your solution is designed such that each project "lines up" in a dependency chain rather than a dependency tree, then there will be less parallelism possible.
If you're using a small number of projects, or you're using Visual Basic on small projects, which is compiling in the background anyway, you might not get big changes. Additionally, remember that we're shelling out n new instances of MSBuild, while VS compiles using the in-process versions of the languages compilers. With a small number of projects, in-proc single-core might be faster.
I've got 900 Projects and Visual Studio is Slow, what's the deal?
"Doctor, doctor, it's hurts what I do that!"
"Then don't do that"
Seriously, yes, there are limits. Personally, if you have more than 50 or so projects, it's time to break them out into sub-system SLN files, and keep the über-solution just for the build server.
The team is aware that if you have hundreds of projects in a solution VS totally breaks down. I, and many others, have made suggestions of things like a "tree of projects" where you could build from one point down, and there's ways you can simulate this with multiple-configurations, but it's kinda lame right now if you have a buttload of projects.
Here's a post I did three years ago called How do you organize your code? and I think it still mostly works today. I was using NAnt at the time, but the same concepts apply to MSBuild. Forgive me now, as I quote myself:
Every 'subsystem' has a folder, and usually (not always) a Subsystem is a bigger namespace. In this picture there's "Common" and it might have 5 projects under it. There's a peer Common.Test. Under CodeGeneration, for example, there's 14 projects. Seven are sub-projects within the CodeGeneration subsystem, and seven are the NUnit tests for each. The reason that you see Common and Common.Test at this stuff is that they are the 'highest." But the pattern follows as you traverse the depths. Each subsystem has it's own NAnt build file, and these are used by the primary default.build.
This is not only a nicer way to lay things out for the project, but also for the people on the project, most of whom are not making cross-subsystem changes.
Action Item for you, Dear Reader
If you have feedback then email the MSBuild team at msbuild@ (you know the company name) and they will listen. I warned them you might be emailing, so be nice. If you DEEPLY want multi-proc builds in the next version of Visual Studio, flood them with your (kind) requests. They are aware of ALL these issues and really want to make things better.
It's interesting as I've been at MSFT about 7 months now to realize that for something like multi-proc builds to work it involves (all) the Compiler Teams, the VS Tooling Teams, and the MSBuild folks. Each has to agree it's important and work towards the goal. Sometimes this is obvious and easy, and other times, less so.
Thanks for Dan Moseley, Cliff Hudson and Cullen Waters for their help!
Related Links
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter
Thank you for taking the time to post this solution. I've got 4 cores sitting around and will now be a build junkie and get this all figured out.
Best to you,
Karl
You can also parallelize compliing of translation units for C++, http://blogs.msdn.com/vcblog/archive/2007/03/12/multi-processor-builds-in-orcas.aspx
Jason - Yes, C++ has been like this for a few years now.
Also, folks, why does no one who says a negative or mean thing ever leave a link or their full name?
Anyway, wasn't trying to bring you down, just pointing out the real-life issues of some people/companies not being able to afford the latest version all the time. Isn't that the case, or have we lost you to the internal bubble once and for all? S M I L E Y
Microsoft doesn't want to charge for Visual Studio or any product in the developer ecosystem. In fact, they tried giving away software for free and it landed them on the wrong side of ten years of lawsuits.
So instead, they officially charge a list price for all of this stuff and then bend over backwards to give it away. I literally have 14 fully legit copies of VS2008; email me with your address and I can send you one [portman dot wills at willsllc dot com].
The sham list price of Studio is not a valid reason for an organization not to upgrade.
@Scott, re: "...I just bought my own and deducted it" - if only deducting the cost actually made it free! Sadly, it doesn't.
@PWillis, re: "The sham list price of Studio is not a valid reason for an organization not to upgrade." - Give me a plan that I can take to my boss that will net us two dozen legal copies of VS 2008 Professional at no cost, and I will gladly recommend it.
None of this takes into account that cost is not the only reason that organizations choose not to upgrade. My company simply refuses to be on the leading edge of any new technology. They will only use established, proven, stable technologies. When VS 2005 was released, there were serious problems in the WinForms designer with projects that were upgraded from VS 2003. The IDE team claimed that this was because the designer was "better", in that it detected problems in the form that 2003 didn't. But that doesn't change the fact that when we upgraded to VS 2005, we lost the ability to design most of our forms (and no, we had not made manual changes to the designer code). The upshot is that while VS 2008 obviously has a lot of great features that we would like to take advantage of, we have learned through experience to be very careful how we handle IDE upgrades.
With all that said, I would like to reiterate Angelfire's original request (with a slight modification): Please make it clear which versions of VS (or anything else for that matter) you are referring to when you post about options and features, so that those of us stuck in the past by choice or necessity don't get excited for nothing.
I see a similar trend on the MSDN forums, where moderators and answerers (who are likely to have the latest and greatest versions) often answer questions assuming that the asker also has the latest version, sometimes even when the original question explicitly states that an older version is being used. There seems to be a little snobbishness developing among the .NET elite in that regard, which is unfortunate.
This assumption that everyone will immediately upgrade to the last and greatest IDE as soon as it is released has some unfortunate side-effects, such as a large number of IDE bugs being fixed for future versions but not for current versions. "Just upgrade to the new version" they say, apparently ignorant or uncaring of the fact that they are asking us to pay good money to fix problems in an IDE for which we already paid!
Sorry for that digression; just some observations which have been on my mind lately.
David Nelson (not the Dave above)
Full name and contact info included
Scott, I notice this number keeps dropping . . .
:-)
David Nelson - I see your issue, but I'm a little surprised by this statement "The company I currently work for won't even consider buying MSDN subscriptions." Are you paying full retail? Why would anyone NOT buy MSDN subscriptions for their devs? Think of the money you'd save for $2k/yr/person. I'm not trolling, I'm *honestly* interested. Is this a small company? How old are you computers? Monitors? If I'm out of touch, I must have been out of touch for YEARS before I started at Microsoft because even the independent consultants I know basically make two purchases a year, a computer and an MSDN subscription.
I don't know exactly what we're paying; I do know that we buy individual licenses for VS. I also know that when I brought up the idea of MSDN subscriptions a couple of months ago, the response was (basically) "why would we pay all that extra money every year for subscriptions when all we need are some Visual Studio licenses?" Since I didn't have a good answer at the time, I had to let it drop. What should I have said? I don't pretend to know much about MSDN licenses; the one time I looked into buying a personal MSDN license, I was so confused after 3 days of investigating that I just gave up. Are we missing something that could be saving us a bunch of money?
Alternatively, you could use VS2008 Express, which is free. VS2008 Standard is $260 and VS2008 Pro is $855. See, if you're talking $855, just pay the $1200, and you're all set on the renewal. MSDN is a very good deal (although Express is free and very functional).
Depending on how complex your projects are, you might be able to use Express: http://msdn2.microsoft.com/en-us/vstudio/aa700921.aspx for comparison and list of features.
I have actually recommended that we use Express to get started in .NET 3.5, and truthfully it would probably be just fine for a lot of what we do. My biggest problem with it (that I can remember at the moment) is that you can't switch between thread or process contexts while paused in the debugger. Makes debugging multi-threaded apps or multi-app solutions virtually impossible. Looking at the product comparison though, it looks to me like we wouldn't need pro; we don't need crystal reports or remote debugging, and we can do without a full-blown xslt designer. So we could probably be just as happy with standard, and its a lot cheaper. I will consider recommending that for the round of VS 2008 licenses that we will (hopefully) be buying soon.
regarding the post "How do you organize your code?" could you take into consideration an updated version?
Perhaps also talking a bit about tool migration (e.g. from NAnt to MSBuild) if you faced it.
Thanks.
thanks for the example of doing this targeting .Net2.0. Being the guy who made the silly remark (and forgetting that 3.0/3.5 is just 2.0+) I appreciate your effort to be as helpful and transparent as possible.
On the issues of the cost of VS 2008 (i tried to go to the Seattle Launch event... was full up no candy for me) I appreciate the MSFT effort to put the tools in the hands of Devs..... its unfortunate when those who really would love to get them can't put them to use. I did however discover that this version of MSBuild comes with 2008 Express, which is awesome (the express editions are getting better but I would love for them to accept addins/ MVC templates etc... )
As to not leaving my real name.... I'm just that way... have been for a long time....however I do always include my email :)
I've tried adding the following parameter to the msbuild command-line, but it didn't work:
/p:Configuration=$(ConfigurationName)
The $(ConfigurationName) variable is available in pre/post-build scripts, but it seems like it isn't defined when launching an external tool...
Thanks!
Pascal
IF '$(COMPILEASP)'== '1' ($(WINDIR)\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler.exe -nologo -v /<appName> )
... i see *significant* tweak-compile-debug speed increase on mult-core.
Microsoft (R) Build Engine Version 3.5.21022.8
[Microsoft .NET Framework, Version 2.0.50727.1434]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
D:\Source\*****.sln : error MSB4126: The specified solution configuration "Debug|MCD" is invalid. Please specify a valid solution configuration using the Configuration and Platform properties (e.g. MSBuild.exe Solution.sln /p:Configuration=Debug /p:Platform="Any CPU") or leave those properties blank to use the default solution configuration.
I had to explicitly specify the configuration. Is there anyone to pull the configuration dynamically?
-Josh
Comments are closed.
Ah, the life of a 'softie - where the software is free and the problems just go away with each 'New Project...' :-)