tab*_*sko 13 delphi msbuild delphi-xe6
我有一个脚本可以编译我的解决方案的所有项目(大约50个),如下所示
msbuild "myProjName.dproj" /t:build /p:config="Release" /fileLogger /flp:ErrorsOnly /nologo
Run Code Online (Sandbox Code Playgroud)
这工作得很好,但需要永远编译.为了使构建更快,我一直在尝试利用这里解释的'/ maxcpucount'开关利用现代多核机器的所有潜力:http://msdn.microsoft.com/library/bb651793.aspx
我在我的4核CPU开发机器上得到了相同的编译时间.没有性能上升.
显然,这只能在项目需要构建依赖项时才能工作.然后其他"工人"将并行构建这些依赖项目作为主要项目.所以我试图在delphi中构建一个项目组并将所有项目添加到它中,然后在这个.groupproj上运行msbuild命令,但它仍然像往常一样慢.
有没有人用msbuild同时构建多个项目?如果是,你可以给我一个解释吗?
谢谢!
以下内容适用于RAD Studio XE4,但也可能适用于早期版本或更高版本.此外,此方法不会遵守.groupproj中定义的依赖关系.我尝试并行化的.groupproj没有项目间的依赖关系,所以我没有弄清楚如何处理这个问题.
当你建立一个使用同一个的MSBuild文件.groupproj Build,Clean或Make目标,构建不平行运行,因为这些目标用CallTarget任务来执行其他目标,但CallTarget在平行而不能执行其目标.
为了并行构建单独的项目,MSBuild项目必须使用单个MSBuild任务一次构建多个项目.目标必须定义如下:
<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>
Run Code Online (Sandbox Code Playgroud)
将这些添加到.groupproj,然后删除其他<Target>指令以及<Import>指令.(CodeGear.Group.Targets定义了一些目标,建立项目以正确的顺序,当你问到只建项目的一个子集来建立依赖关系,但它覆盖Build,Clean并Make在.groupproj定义的目标.)请注意,这只是让你建立所有项目,而不仅仅是一个子集.
BuildInParallel在MSBuild 3.5中添加了.但是,由于.groupproj文件未指定该ToolsVersion属性,因此MSBuild将使用MSBuild2.0版中定义的任务,该任务不支持BuildInParallel.有两种方法可以解决这个问题:
ToolsVersion="3.5"(或更高版本)添加到<Project>.groupproj文件的根元素./toolsversion:3.5(或/tv:3.5简称)命令行参数运行MSBuild (/toolsversion覆盖ToolsVersion所有项目文件中指定的.)执行此操作后,使用/maxcpucount(或/m)参数运行MSBuild,您的项目应并行构建.但是,RAD Studio无法正确处理此转换后的项目组,因此您可能希望为该文件指定一个不同的扩展名,以明确它不是标准的RAD Studio项目组(任何以此结尾的扩展名proj都可以).
以下XSLT样式表执行上述转换:
<?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">
<!-- Do not copy -->
</xsl:template>
<xsl:template match="//msbuild:Import">
<!-- Do not copy -->
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
您可以XslTransformation使用此项目文件(groupproj2parallel.xslt以上是上面的XSLT文件)将此样式表应用于MSBuild(4.0或更高版本:在MSBuild 4.0中添加):
<?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>
Run Code Online (Sandbox Code Playgroud)
您需要在命令行上指定InputPaths并OutputPaths显式指定/p:InputPaths="..." /p:OutputPaths="...",或者在任务的Properties参数上指定它们MSBuild.(或者,您只需在项目文件中对文件名进行硬编码即可.)
MSBuild for C#和Visual Basic项目提供的目标定义通过使用<ProjectReference>项目文件中定义的项来处理依赖项,而不是在解决方案文件中定义依赖项.Delphi .dproj文件和C++ Builder .cbproj文件不支持此功能,因为底层CodeGear.Common.Targets不会重用Microsoft.Common.Targetsfor中定义的机制<ProjectReference>.
有点题外话:您可以尝试 IDE 修复包的 fastdcc 部分来获得更快的构建: http://andy.jgknet.de/blog/ide-tools/ide-fix-pack/ 例如,我有一个构建时间从 1 分钟缩短至 22 秒!