0

我正在编写一个 MSBuild 脚本,它的工作是构建一个解决方案,然后将两个项目的构建输出复制到一个统一的目录中。很简单。

我正在使用Copy任务执行此操作。像这样:

<ItemGroup>
    <OutputFiles1 Include="Project1\bin\Release\*.*" />
    <OutputFiles2 Include="Project2\bin\Release\*.*" />
</ItemGroup>

<Target CopyOutput>
    <Copy SourceFiles="@(OutputFiles1)" DestinationFolder="DeployOutput" />
    <Copy SourceFiles="@(OutputFiles2)" DestinationFolder="DeployOutput" />
</Target>

我遇到的问题是:这两个ItemGroup元素包含构建脚本启动时的目录内容,而不是解决方案构建完成时的目录内容。

因此,例如,如果我在 Project1 中添加对新程序集的引用,然后运行构建,则 DeployOutput 目录不包含该新程序集,因为它在构建开始时不存在于项目输出目录中。但是如果我再次运行构建,文件就在那里并被复制。

这种行为似乎是设计使然,但我不确定如何在不生成批处理文件或类似的东西来完成复制的情况下完成我的任务。

4

1 回答 1

3

经典的msbuild 评估顺序问题:项目根目录中的项目和属性基本上是在解析时评估,在任何目标运行之前。但是,将它们放在目标中,并在目标运行时对它们进行评估。这对您的情况更好,因为您还可以确保一个目标一个接一个地运行,从而使第一个目标看到后者产生的输出。插图:

<ItemGroup>
  <OutputFiles1 Include="Project1\bin\Release\*.*" />
</ItemGroup>

<Target Name="BuildIt">
  <Message Text="OutputFiles1=@(OutputFiles1 )" />
  <MSBuild Projects="Project1.vcxproj" Targets="Build" />
</Target>

<Target Name="Copy" DependsOnTargets="BuildIt">
  <ItemGroup>
    <ActualOutputFiles1 Include="Project1\bin\Release\*.*" />
  </ItemGroup>
  <Message Text="OutputFiles1=@(OutputFiles1)" />
  <Message Text="ActualOutputFiles1=@(ActualOutputFiles1 )" />
</Target>

运行 Copy 目标时(并且输出目录仍然为空),您将获得如下输出

OutputFiles1=
.... build output ....
OutputFiles1=
ActualOutputFiles1=Project1\bin\Release\a.dll;......

OutputFiles1 始终为空,因为在评估时输出目录为空。然而,ActualOutputFiles1 是在构建之后评估的,因此它包含输出目录的内容。

于 2015-12-11T09:09:19.177 回答