gpt4 book ai didi

delphi - 通过MSBuild并行编译delphi项目

转载 作者:行者123 更新时间:2023-12-03 14:37:07 29 4
gpt4 key购买 nike

我有一个脚本可以编译我的解决方案的所有项目(大约 50 个),如下所示

msbuild "myProjName.dproj" /t:build /p:config="Release" /fileLogger /flp:ErrorsOnly /nologo

这工作得很好,但编译需要很长时间。为了加快构建速度,我一直在尝试使用此处解释的“/maxcpucount”开关来利用现代多核机器的所有潜力:http://msdn.microsoft.com/library/bb651793.aspx

我在 4 核 CPU 开发机器上得到了大约相同的编译时间。没有性能提升。

显然这只有在项目需要构建依赖项时才有效。然后,其他“ worker ”将并行构建这些依赖项项目作为主要项目。因此,我尝试在 delphi 中构建一个项目组,并将所有项目添加到其中,然后在此 .groupproj 上运行 msbuild 命令,但它仍然像以前一样慢。

你们中有人实现过使用 msbuild 同时构建多个项目吗?如果是的话你能给我一个解释吗?

谢谢!

最佳答案

以下内容适用于 RAD Studio XE4,但也可能适用于早期或更高版本。此外,此方法不会遵守 .groupproj 中定义的依赖项。我尝试并行化的 .groupproj 没有项目间依赖关系,因此我不知道如何处理这个问题。

当您使用 MSBuild 使用 Build 构建 .groupproj 文件时, CleanMake目标,构建不会并行运行,因为这些目标使用 CallTarget执行其他目标的任务,但是 CallTarget不并行执行其目标。

为了并行构建单独的项目,MSBuild 项目必须使用单个 MSBuild task一次构建多个项目。目标必须这样定义:

  <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 定义了一些目标,以正确的顺序构建项目,并在您要求仅构建项目的子集时构建依赖项,但它会覆盖 BuildCleanMake 中定义的目标.groupproj。)请注意,这仅允许您构建所有项目,而不仅仅是一个子集。

BuildInParallel was added in MSBuild 3.5.但是,由于 .groupproj 文件未指定 ToolsVersion属性,MSBuild 将使用 MSBuild 2.0版本中定义的任务,不支持BuildInParallel 。有两个选项可以解决此问题:

  1. 添加ToolsVersion="3.5" (或更高版本)到根 <Project> .groupproj 文件的元素。
  2. 使用 /toolsversion:3.5 运行 MSBuild (或简称 /tv:3.5)命令行参数( /toolsversion 覆盖所有项目文件中指定的 ToolsVersion。)

完成此操作后,使用 /maxcpucount 运行 MSBuild (或 /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>

您可以使用此项目文件(其中 XslTransformation 是上面的 XSLT 文件)将此样式表应用于 MSBuild(4.0 或更高版本: groupproj2parallel.xslt 已在 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>

您需要指定InputPathsOutputPaths在命令行上显式使用 /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并行编译delphi项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26408966/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com