我有一个脚本可以编译我的解决方案的所有项目(大约50个),如下所示
msbuild "myProjName.dproj" /t:build /p:config="Release" /fileLogger /flp:ErrorsOnly /nologo
这工作正常,但需要永远编译。为了使构建更快,我一直在尝试利用这里解释的'/ 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>
将这些添加到.groupproj,然后删除另一个 <Target>
指令以及 <Import>
指示。 (CodeGear.Group.Targets
定义一些目标以按正确顺序构建项目,并在要求仅构建项目的子集时构建依赖项,但它会覆盖 Build
, Clean
和 Make
.groupproj中定义的目标。)请注意,这只允许您构建所有项目,而不仅仅是子集。
BuildInParallel
在MSBuild 3.5中添加。 但是,由于.groupproj文件没有指定 ToolsVersion
属性,MSBuild将使用 MSBuild
版本2.0中定义的任务,不支持 BuildInParallel
。有两种方法可以解决这个问题:
- 加
ToolsVersion="3.5"
(或更高版本)到根 <Project>
.groupproj文件的元素。
- 用。运行MSBuild
/toolsversion:3.5
(要么 /tv:3.5
简而言之)命令行参数(/toolsversion
覆盖了 ToolsVersion
在所有项目文件中指定。)
执行此操作后,运行MSBuild /maxcpucount
(要么 /m
)参数和你的项目应该并行构建。但是,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>
您可以将此样式表应用于MSBuild(4.0或更高版本: XslTransformation
在MSBuild 4.0中添加了这个项目文件(其中 groupproj2parallel.xslt
是上面的XSLT文件):
<?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>
你需要指定 InputPaths
和 OutputPaths
显式在命令行上 /p:InputPaths="..." /p:OutputPaths="..."
,或通过指定它们 Properties
参数 MSBuild
任务。 (或者,您可以只对项目文件中的文件名进行硬编码。)
MSBuild为C#和Visual Basic项目提供的目标定义通过使用。来处理依赖项 <ProjectReference>
项目文件中定义的项目,而不是在解决方案文件中定义依赖项。 Delphi .dproj文件和C ++ Builder .cbproj文件不支持这个,作为底层 CodeGear.Common.Targets
不重复使用中定义的机器 Microsoft.Common.Targets
对于 <ProjectReference>
。
有两种方法可以构建Delphi项目: MSBuild
要么 DCC32.exe
。 MSBuild
建议作为项目文件(dproj
和 groupproj
)封装所有配置设置。
但是,有额外的头部使用 MSBuild
比较普通的 DCC32.exe
。此外,使用 MSBuild
建立德尔福项目组(.groupproj
)不会为多核CPU带来任何好处。构建性能与单核CPU相同。
以下是我建立290的统计数据 dproj
单个文件 groupproj
:
MSBuild a `groupproj` contains 290 `dproj` on 2C/4T CPU: ~100s
MSBuild a `groupproj` contains 290 `dproj` on 4C/8T CPU: ~100s
MSBuild 290 `dproj` run in multi-threads on 2C/4T CPU: ~121s
MSBuild 290 `dproj` run in multi-threads on 4C/8T CPU: ~50s
DCC 290 `dproj` run in multi-threads on 2C/4T CPU: ~37s
DCC 290 `dproj` run in multi-threads on 4C/8T CPU: ~24s
从阅读中,我们可以得出结论 MSBuild
引入额外的开销比较 DCC32
。要充分利用可用的CPU内核和线程, DCC32
是牺牲方便的项目配置封装设计的方法 .DPROJ
。
一个 msbuild
脚本来构建Delphi groupproj
并行可在 https://github.com/ccy/msbuild.delphi.parallel
有点偏离主题:您可以尝试使用IDE修订包的fastdcc部分来获得更快的构建:
http://andy.jgknet.de/blog/ide-tools/ide-fix-pack/
例如,我的构建时间为1分钟,下降到22秒!