MSbuild构建顺序问题 - 预构建步骤先还是依赖项目先?

20
我有一个项目A依赖于项目B。项目A有一些预构建任务,这些任务依赖于项目B生成的某些文件。在Visual Studio中构建时没有问题。但是使用MSBuild.exe时,会出现问题,因为构建顺序是:
- A的预构建步骤 <- 因为B尚未编译而失败 - B被编译 <- 预计先执行 - 编译A
这是MSBuild的预期行为吗?有没有办法告诉MSBuild要先执行B再执行A的预构建步骤?
我正在使用VS2010 C#和C++/CLI。我不认为它提供了额外的信息,但是以下是调用方式:
Running process (C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBUILD.exe "..\..\..\dev\build\MyProj.sln" /t:Clean /p:Configuration=Release;Platform=Win32)

“PreBuildEvent:” 可以在 Visual Studio 的输出窗口中看到,在调用 Csc.exe 之前执行。基于这一点,我不理解问题。 - P.Brian.Mackey
我不确定,但你的问题是否类似于http://blogs.msdn.com/b/visualstudio/archive/2010/12/21/incorrect-solution-build-ordering-when-using-msbuild-exe.aspx? - Pavel Bakshy
@P.Brian.Mackey 构建VS解决方案和MSBuild.exe是独立的进程。 - M W
1
@PavelBakshy 我也看到了那篇文章,但它讨论的是稍微不同的问题。所讨论的问题是由于使用依赖设置指定某些项目依赖项而不是添加引用而引起的。这是关于我找不到详细信息的预构建步骤的问题。 - M W
4个回答

14

简短回答

删除你的构建事件,并在你的项目(.csproj)中添加类似以下内容的代码:

<Target Name="AfterResolveReferences">
  <Exec Command="echo helloworld" />
</Target>

更多信息

您可以在这里阅读有关自定义构建过程的内容:http://msdn.microsoft.com/en-us/library/ms366724%28v=vs.110%29.aspx

在ResolveReferences之前触发Before Build事件,因此如果您引用的项目在到达您的项目的BeforeBuild事件时尚未构建,则您的BeforeBuild事件将失败。

为了克服这个问题,您应该使用不同的入口点来自定义构建过程。在上面的示例中,我使用AfterResolveReferences,因为这将确保您引用的所有项目都已经构建完成。


我只能说谢谢!这个小提示帮我解决了许多问题。谁能想到预构建事件会在“解析引用”调用之前被触发呢。这个方法完美地运行了。 - Kevin Marshall

11
这是一个比较旧的问题,但我发现了一个简单的解决方案(它可能也适用于你)。只需添加。
<PreBuildEventDependsOn>ResolveReferences</PreBuildEventDependsOn>

之前

<PreBuildEvent>

不幸的是,必须在编辑器中完成此操作,因为VS编辑器不支持它(在15.6.2版本中)。


6

杰克的答案似乎有效,但我不喜欢的是VS UI不支持原生编辑.csproj,除了笨拙的“卸载项目、编辑项目(此时您无法像通常一样单击文件),重新加载项目”的模式以外。 我想要的是在依赖项目构建后触发预构建事件,并且在VS和MSBuild中可以正常工作。在与这个问题斗争了一段时间后,我在MSBuild 4.0中找到了适合我的解决方案。

无论我尝试了什么,都无法更改PreBuildEvents目标,在依赖项目完成构建后触发。所以我禁用了PreBuildEvents目标,并创建了一个混合自定义的PreBuildEvents目标,以在适当的时间运行:

<ItemGroup>
  <ProjectReference Include="..\YourProjectPath\YourProject.csproj">
    <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
  </ProjectReference>
</ItemGroup>
<Target Name="PreBuildEvent" AfterTargets="" BeforeTargets="" />
<Target Name="BastardPreBuildEvent" AfterTargets="ResolveReferences" BeforeTargets="CoreResGen">
  <Exec Command="$(PreBuildEvent)" />
</Target>

1
这个对我有用。我同意...这样做更好,因为它仍然支持Visual Studio PreBuild编辑器对话框。 - Mark Whitfeld
这个 'AfterTargets="" BeforeTargets="' 是防止 PreBuildEvent 在之前运行吗?还是只是因为你在里面有没有子元素的 <Target> ? - user145400
很可能,将AfterTargets和BeforeTargets设置为空是禁用了PreBuildEvent目标运行的原因。 - VeeTheSecond

1

这可能有点老了,但我最近遇到了同样的问题。Jack的回答是我试图使用的,但在Visual Studio加载项目时会调用ResolveReferences目标,这对我来说很糟糕,因为我正在执行一个相当长的过程,而我只想在构建之前执行。

我最终使用的解决方案与VeeTheSecond类似,但涉及较少:

<Target Name="BeforeBuild" DependsOnTargets="ResolveReferences">
    ... exec something using a dependant project's output exe ...
</Target>

这将强制 BeforeBuild 目标等待所有依赖项目实际完成构建,以便 exec 命令可以使用依赖项目的输出。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接