Hello again! My name is Li Shao. I am a Software Design Engineer in Test in the Visual C++ group.
As one of my colleagues, Marian Luparu, has blogged in detail about, and Soma has mentioned in his recent blog as well, one of the important features we have in VS2010 is to enable C++ customers to build C++ applications using MSBuild. MSBuild (Microsoft Build Engine) is an extensible, XML-based build engine first shipped with Visual Studio 2005 and the .NET Framework 2.0. It is a core part of .NET Framework 2.0/3.0/3.5. It gives developers full control of their build process and provides a new XML based project file format. .NET languages such as Visual Basic (VB) and Visual C# (VC#) have migrated to MSBuild as their project and build systems in Visual Studio 2005.
Currently, C++ uses its own build system: VCBuild. VCBuild and MSBuild have many differences. Here are a couple of key differences:
1. The Build logic in MSBuild is expressed in MSBuild target files which are accessible by the end uses. The build logic for VCBuild is encapsulated inside the binaries.
2. VCBuild is made specific for building C++ application. MSBuild on the other hand, is more flexible and extensible. It can be extended to accomplish many different tasks without changes to MSBuild engine.
Over the last year, I’ve spent most of my time working in a team tasked to migrate the C++ build system from VCBuild to MSBuild. A large chuck of the work we need to do for this migration is to create “tasks” for all the native tools we support in VCBuild. Tasks are reusable units of executable code used by MSBuild projects to perform build operations. There’s a library of common tasks provided with MSBuild. You can take a look at this link to know what the available tasks are. You can also create your own task by authoring a managed type that implements the ITask Interface. Here is an MSDN example on how to create your own tasks.
In VCBuild, we support these set of native tools:
o cl.exe
o link.exe
o lib.exe:
o rc.exe
o midl.exe
o mt.exe
o xsd.exe
o xdcmake.exe
o bscmake.exe
To have MSBuild support for building native applications, new tasks need to be made for each of the tools. These tasks map the commonly used switches or the switches currently exposed through project system property page to the properties on the tasks.
There are situations that you know what switches you would like to pass to the tools but you need to figure out what MSBuild properties to use. To find the complete mapping of the properties and their representative switches, you can take a look of the XAML files under %programfiles%\MSBuild\Microsoft.Cpp\v4.0. These XAML files express the mapping between properties and switches and their usage. Each of the XAML files represents one tool.
o CL.XML
o Link.XML
o Lib.XML
o RC.XML
o MIDL.XML
o MT.XML
o XSD.XML
o XDCMake.xml
o BSCmake.xml
This is a snippet in CL.XML:
<StringListProperty Name="AdditionalIncludeDirectories" Category="General" Switch="I">
- <StringListProperty.DisplayName>
<sys:String>Additional Include Directories</sys:String>
</StringListProperty.DisplayName>
- <StringListProperty.Description>
<sys:String>Specifies one or more directories to add to the include path; separate with semi-colons if more than one. (/I[path])</sys:String>
</StringListProperty.Description>
</StringListProperty>
From here, you can see that “AdditionalDirectories” maps to switch “I”. In the project file (.vcxproj is the new MSBuild based C++ project file), you can specify:
<ClCompile>
<AdditionalIncludeDirectories>include1;include2;include3</AdditionalIncludeDirectories>
</ClCompile>
It will be translated to this command line for CL:
/I:”include1” /I:”include2” /I:”include3”
We have also exposed some new switches, for example /MP. This is the XAML definition of the /MP switch
- <BoolProperty Name="MultiProcessorCompilation" Category="General" Switch="MP">
- <BoolProperty.DisplayName>
<sys:String>Multi-processor Compilation</sys:String>
</BoolProperty.DisplayName>
- <BoolProperty.Description>
<sys:String>Multi-processor Compilation</sys:String>
</BoolProperty.Description>
<Argument Property="ProcessorNumber" IsRequired="false" />
</BoolProperty>
- <IntProperty Name="ProcessorNumber" Category="General">
- <IntProperty.DisplayName>
<sys:String>Number of processors</sys:String>
</IntProperty.DisplayName>
- <IntProperty.Description>
<sys:String>Number of processors.</sys:String>
</IntProperty.Description>
</IntProperty>
In you project file, you can specify:
<CLCompile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ProcessorNumber>4</ProcessorNumber>
</ClCompile>
The command line for cl will contain /MP4.
In the old project files, we use enum values to specify the properties that can take different values. For example, in old project file, you have “TargetMachine="1"” specifying “/MACHINE:X86” while in new project file, you can do the following which is more readable.
<Linker>
<TargetMachine>MachineX86</TargetMachine>
<Linker>
In link.xml, you can see the following is part of the definition for “TargetMachine”.
<EnumProperty Name="TargetMachine" Category="Advanced">
- <EnumValue Name="MachineIA64" Switch="MACHINE:IA64">
- <EnumValue.DisplayName>
<sys:String>MachineIA64</sys:String>
</EnumValue.DisplayName>
</EnumValue>
- <EnumValue Name="MachineX64" Switch="MACHINE:X64">
- <EnumValue.DisplayName>
<sys:String>MachineX64</sys:String>
</EnumValue.DisplayName>
</EnumValue>
- <EnumValue Name="MachineX86" Switch="MACHINE:X86">
- <EnumValue.DisplayName>
<sys:String>MachineX86</sys:String>
</EnumValue.DisplayName>
</EnumValue>
</EnumProperty>
It defines the properties for /MACHINE:X86, /MACHINE:x64 and /MACHINE:IA64. In addition to these, “TargetMachine” also defines the properties for /MACHINE:ARM, /MACHINE:EBC, /MACHINE:MIPS, /MACHINE:MIPS16, /MACHINE:MIPSFPU, /MACHINE:MIPSFPU16, /MACHINE:SH4, /MACHINE:THUMB.
Like the old project system, the majority of the properties in the XAML files are also exposed through the property page UI in the new project system. Take “TargetMachine” as an example again, since it is defined in linker.XML as:
<EnumProperty Name="TargetMachine" Category="Advanced">
With its “Category” attribute as “Advanced”, you can expect to find “TargetMachine” at the linker tool/Advanced page.
That’s it for this blog. Hope you will find it helpful. Please let us know if you have any feedback when using MSBuild to build C++ applications.
Happy Holidays!
Li Shao