【问题标题】:Building the same solution using msbuild and devenv interchangeably交替使用 msbuild 和 devenv 构建相同的解决方案
【发布时间】:2014-03-28 02:20:22
【问题描述】:

这种情况经常发生,我首先使用 msbuild 在命令行上构建一些解决方案,运行了一段时间,然后发现我需要更改和调试它。所以,我在 Visual Studio 中打开它并最终在 Visual Studio 中构建它。

发生的情况是 VS 重建了解决方案的相当多部分,即使我什么也没做!

深入研究会发现以下内容:

在 Visual Studio 中构建会生成空的 cs 文件并将它们注入到 Compile 项目组中。 自然,它们比已构建的二进制文件更新,因此 devenv.exe 会重建大量项目.感谢TemporaryGeneratedFile_[guid] in /obj/debug breaking build

这真是太糟糕了。我通过重命名Microsoft.WorkflowBuildExtensions.targets 文件禁用了这种行为——我不做工作流。

我想我可以侵入 CoreCompileDependsOn 并以某种方式中和来自 Microsoft.WorkflowBuildExtensions.targets 的 GenerateCompiledExpressionsTempFile 目标,但这必须在 190 个项目中完成!这是一个严重的变化。

devenv.exe 似乎关心某些文件总是被复制到输出目录,即使 msbuild 不认为这是一个问题。

确实,这里是 devenv.exe 构建日志中的一行:

Project 'HRCore.Tests' is not up to date. Project item 'C:\abc\UI\HRCore.Tests\HRImport\Import_missing_state_county.xml' has 'Copy to Output Directory' attribute set to 'Copy always'.

那又怎样? msbuild 不关心它,但 devenv 关心它。此文件不是 HRCore.Tests 的依赖项,msbuild 做对了。

与此同时,我将其从 Always 更改为 PreserveNewest

无论如何,我很想知道如何消除这些差异。

例如,即使在使用 msbuild 构建时也将 BuildingInsideVisualStudio 设置为 true 是否是个好主意?

有什么想法吗?

附言

我们同时构建 .NET 和 Silverlight。控制台应用程序、dll 和 Web 应用程序。

【问题讨论】:

  • 对此我有点惊讶 - 最近我一直在尝试设置自定义构建步骤,因为 VS 和 MSB 有不同的增量构建方法,但我认为 VisualStudio 更聪明。可能是您在某些项目中进行了一些稍微奇怪的设置,使其想要复制周围的东西
  • 不要那么肯定。检查您是否有Microsoft.WorkflowBuildExtensions.targets 文件。如果你这样做 - 请放心,你的 obj 目录包含我提到的奇怪文件。接下来尝试使用诊断设置在 VS 中编译 - 你会看到 VS 抱怨项目不是最新的,因为某些文件总是复制到输出中。

标签: visual-studio visual-studio-2012 msbuild


【解决方案1】:

由于对$(BuildingInsideVisualStudio) 的显式检查,.targets 文件确实导致 Visual Studio 和命令行 MsBuild 之间的行为不同:

  <PropertyGroup>
    <PrepareResourcesDependsOn>
      ValidationExtension;
      ExpressionBuildExtension;
      $(PrepareResourcesDependsOn)
    </PrepareResourcesDependsOn>
  </PropertyGroup>

  <PropertyGroup>
    <!-- Explicit check for Visual Studio here -->
    <CoreCompileDependsOn Condition="'$(BuildingInsideVisualStudio)' == 'true'">
        GenerateCompiledExpressionsTempFile;
        $(CoreCompileDependsOn)
    </CoreCompileDependsOn>   
  </PropertyGroup>

该显式检查使临时文件生成发生在我的配置中的 Visual Studio 中。制作这些文件是为了让您在 Visual Studio 中运行时可以单步执行和调试它们。

可以通过在项目文件中重写 &lt;GenerateCompiledExpressionsTempFilePathForEditing /&gt; 来关闭该行为,以便在命令行上明确清除它的值。

/p:GenerateCompiledExpressionsTempFilePathForEditing=''

这是保护这种行为的条件:

 <Target Name ="GenerateCompiledExpressionsTempFile" 
      Condition = "'$(GenerateCompiledExpressionsTempFilePathForEditing)' != ''">  

查看 MsBuild 路径,您应该可以通过在命令行上传递 /p:DisableWorkflowCompiledExpression=true 来完全关闭编译表达式的生成。

您还可以覆盖CoreCompileDependsOn 并从中删除GenerateCompiledExpressionsTempFile; 项。

在编辑器内部构建时出现“特殊行为”真的很可惜。最后,我总是错误地让 Visual Studio 表现得像 MsBuild,而不是相反。当BuildingInsideVisualStudio 为真时,许多其他目标将假定特殊服务或主机编译器的可用性,让MsBuild 认为它在Visual Studio 中而实际上并非如此似乎是一个非常糟糕的主意。

【讨论】:

  • 你用的是什么版本的VS?
  • 我安装了 2010~2015RC。但是有问题的目标文件位于 .NET 框架目录中,所以我认为更好的问题是,您的目标是哪个框架版本。这些示例来自 v4.0 框架目录。
【解决方案2】:

此页面上的另一个有用的解决方案建议了几种替代方案,其中最好的方法显然是从CoreCompileDependsOn 属性中删除GenerateCompiledExpressionsTempFile 目标。不幸的是,该属性是一个 MSBuild property,而不是 MSBuild item,因此删除它的特定部分并不完全简单。[注 1.]

这也许就是为什么@jessehouwing 继续提出其他方法来阻止 Microsoft.WorkflowBuildExtensions 目标运行 - 因此将这三个烦人的.cs 文件添加到每个编译中,即通过调整目标在决定做什么时检查的一些环境 MSBuild 值。

所以现在我的小贡献...为什么要操纵不受欢迎的目标考虑的因素,试图欺骗它不运行,而您可以简单地将整个目标本身清空? p>

只需将以下行添加到您的 .csproj 项目文件的底部:

    ...etc...
    <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
    <Target Name="GenerateCompiledExpressionsTempFile" />          <!-- add this line -->
</Project>



注意事项:
1. 在 MSBuild 中当然可以从属性中删除分隔项,例如使用内联 $([System.String]::Replace(...))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-16
    • 2011-05-08
    • 1970-01-01
    • 2010-12-06
    • 2011-09-09
    • 1970-01-01
    • 2012-09-21
    相关资源
    最近更新 更多