RAD Studio XE4 applies the following rule, but it can also apply to earlier or later versions. Also, dependencies defined in .groupproj will not be respected by this method. There were no cross-project dependencies in .groupproj, which I tried to parallelize, so I did not understand how to do this.
When you create a .groupproj file with MSBuild using a Build , Clean or Make target, the assembly does not start in parallel because these targets use the CallTarget task to accomplish other goals, but CallTarget does not execute its goals in parallel.
To build separate projects in parallel, an MSBuild project must use one MSBuild task to create multiple projects at the same time. Objectives should be defined as follows:
<Target Name="Build"> <MSBuild Projects="@(Projects)" BuildInParallel="true"/> </Target> <Target Name="Clean"> <MSBuild Targets="Clean" Projects="@(Projects)" BuildInParallel="true"/> </Target> <Target Name="Make"> <MSBuild Targets="Make" Projects="@(Projects)" BuildInParallel="true"/> </Target>
Add them to .groupproj, then remove the other <Target> directives as well as the <Import> directive. ( CodeGear.Group.Targets defines some goals for building projects in the correct order and for creating dependencies when you request to create only a subset of projects, but it overrides the Build , Clean and Make goals defined in .groupproj.) Note that this allows Create only all projects, not just a subset.
BuildInParallel was added in MSBuild 3.5. However, since .groupproj files do not specify the ToolsVersion attribute, MSBuild will use the MSBuild Task, as defined in version 2.0, which does not support BuildInParallel . There are two ways to fix this:
- Add
ToolsVersion="3.5" (or later) to the root <Project> element of your .groupproj file. - Launch MSBuild with the
/toolsversion:3.5 command line /toolsversion:3.5 (or /tv:3.5 for short) ( /toolsversion overrides ToolsVersion specified in all project files.)
After that, start MSBuild with /maxcpucount (or /m ), and your projects should build in parallel. However, RAD Studio does not handle the project group correctly, so you can provide the file with a different extension so that it makes it clear that this is not a standard RAD Studio project group (any extension that ends with proj ).
The following XSLT stylesheet performs the conversion described above:
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" exclude-result-prefixes="msbuild" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" xmlns:msbuild="http://schemas.microsoft.com/developer/msbuild/2003" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="//msbuild:Project"> <xsl:copy> <xsl:attribute name="ToolsVersion">3.5</xsl:attribute> <xsl:apply-templates select="@* | node()"/> <Target Name="Build"> <MSBuild Projects="@(Projects)" BuildInParallel="true"/> </Target> <Target Name="Clean"> <MSBuild Targets="Clean" Projects="@(Projects)" BuildInParallel="true"/> </Target> <Target Name="Make"> <MSBuild Targets="Make" Projects="@(Projects)" BuildInParallel="true"/> </Target> </xsl:copy> </xsl:template> <xsl:template match="//msbuild:Target"> </xsl:template> <xsl:template match="//msbuild:Import"> </xsl:template> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
You can apply this stylesheet with MSBuild (4.0 or later: XslTransformation was added to MSBuild 4.0) using this project file (where groupproj2parallel.xslt is the XSLT file above):
<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Target Name="Build" Inputs="$(InputPaths)" Outputs="$(OutputPaths)"> <XslTransformation XmlInputPaths="$(InputPaths)" XslInputPath="groupproj2parallel.xslt" OutputPaths="$(OutputPaths)" /> </Target> </Project>
You need to explicitly specify InputPaths and OutputPaths on the command line using /p:InputPaths="..." /p:OutputPaths="..." or by specifying them in the Properties parameter of MSBuild . (Alternatively, you can simply copy the file names to the project file.)
The goal definitions provided by MSBuild projects for C # and Visual Basic handle dependencies using the <ProjectReference> elements defined in the project files instead of defining the dependencies in the solution file. Delphi.dproj files and C ++ Builder.cbproj files do not support this, because the underlying CodeGear.Common.Targets does not reuse the mechanism defined in Microsoft.Common.Targets for <ProjectReference> .