Compiling Visual C++ 2010 Projects on a Build Server

Last week I was configuring the build server to compile its first Visual C++ 2010 project. I took the approach of using MsBuild on the project file (.vcxproj) as I am already doing it with the .NET projects. This worked just fine on my development machine with Visual Studio 2010 installed. It soon turned out not to be as easy as I expected it to be. The build failed as follows:

C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppBuild.targets(297,5): 
warning MSB8003: Could not find WindowsSDKDir variable from the registry. 
TargetFrameworkVersion or PlatformToolset may be set to an invalid version number.

C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Platforms\Win32\Microsoft.Cpp.Win32.Targets(57,5): 
error MSB6006: "CL.exe" exited with code -1073741515.

My first thought was that there were some files missing since there was no Visual Studio installed on the build machine. Running the build command in a regular command prompt resulted in the same error after an additional message box popped up:

The program can't start because mspdb100.dll is missing from your computer. Try reinstalling the program to fix this problem.

This was to be expected. Even on my development machine it is necessary to start the build from the Visual Studio Command Prompt for it to work. Its replacement on the build machine is Windows SDK 7.1 Command Prompt, part of Microsoft Windows SDK for Windows 7 and .NET Framework 4. From this command prompt the build worked flawlessly on the build machine as well. It seems we're getting closer to the source of the problem… The command prompt is initialized by first calling SetEnv.cmd from the Windows SDK installation directory (by default in C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin) to set the required environment variables. By doing the same in the build script before calling MsBuild should do the trick for the continuous integration server as well.

Well, here lied the real problem. To simplify CruiseControl.NET project configuration the build scripts are written in NAnt. Calling a batch script from NAnt is not a problem of course, there is the exec task for doing that, but any changes to the environment variables are preserved only for the duration of this task. This means we haven't achieved anything by calling SetEnv.cmd before the msbuild task since any changes made by it are lost. The only way to make this work is by creating another batch script which calls both SetEnv.cmd and MSBuild immediately after it:

call "C:\Program Files\Microsoft SDKs\Windows\v7.1\bin\Setenv.cmd" /Release /x86
msbuild myproj.vcxproj /verbosity:minimal

It's not ideal but it's the only way I could make it work. Fortunately this batch script shouldn't be changing much since everything else is configured inside the project file. I'd still prefer a solution which would allow calling MsBuild directly from NAnt though.

Copyright
Creative Commons License