Visual Studio 2017会一遍又一遍地构建项目

时间:2019-01-14 16:11:14

标签: c# c++ visual-studio msbuild

我有一个很大的解决方案(〜450个项目),尽管我没有做任何更改,但有些项目却一遍又一遍地构建。

当我将构建输出的详细程度更改为diagnostic时,它说:

  

项目“ ProjectA”不是最新的。缺少输入文件'C:\ Src \ Project.Core \ Bin \ Release \ ProjectB.dll'

ProjectA取决于ProjectB,并且我正在构建配置Debug,所以Visual Studio为什么在ProjectB.dll文件夹中检查文件ReleaseProjectB.dll将被构建并复制到正确的文件夹中(调试)!

每个项目(c#和c ++)的输出路径都相同:

<OutputPath>$(SolutionDir)Bin\$(Configuration)\</OutputPath>

这只是一个例子。我的解决方案中的多个项目都有这种奇怪的行为。似乎是c ++项目造成了这种情况,但我没有明确的证据。

这是我对文件访问的Process Monitor分析:

enter image description here

更新1:

ProjectA(C#项目)使用ProjectReference引用ProjectB(C ++项目):

<ProjectReference Include="..\..\ProjectB.vcxproj">
   <Project>{F2F4C146-8A98-432B-BB9F-A06C4B4162CF}</Project> 
   <Name>ProjectB</Name>
</ProjectReference>

更新2:

.NET Core项目有以下设置:

enter image description here

针对.NET Framework的项目是否有类似的东西?

更新3:

好像C#项目的FastUpToDateCheck的代码在csproj.dll程序集中。由于它是本机程序集,因此我无法查看代码。真可惜。

2 个答案:

答案 0 :(得分:0)

问题不是您的所有项目都在解决方案文件( .sln)中。 假设您正在使用项目引用。即<ProjectReference
当某些项目在解决方案文件(
.sln)中,并且它们引用解决方案文件之外的另一个项目时,MSBuild将构建另一个项目,但不使用您正在构建的配置。它总是或通常(错误)将使用您使用的相反配置进行构建。

超级骗子烦人的错误。

作为一种变通办法,您可以只声明一个包含所有项目的ItemGroup,并将其直接传递给MSBuild,而根本不使用任何解决方案。

<ItemGroup>
   <Files Include="**\*.csproj" />
   <Files Include="**\*.vcxproj" />
</ItemGroup>

<Target Name="Build">
   <MSBuild Projects="@(Files)" Properties="Configuration=Debug" />
</Target>

如果它们全部使用<ProjectReference,则MSBuild将自动确定它们的内置顺序。

或者您可以创建一个包含所有内容的解决方案。

答案 1 :(得分:0)

我遇到了与您相同的问题。我没有修复程序-只是一种可与msbuild 15及更高版本一起使用的解决方法。与您相同,我发现没有办法将正确的目标输出路径从clr项目传递到csproj ProjectReference元素或其任何目标。

Directory.Build.targetslink)的某处添加以下代码以解决您的问题,更新检查将起作用。

发生的所有事情都是将dll从OutputPath复制到IntermediateOutputPath,这使FastUpToDateCheck可以找到它。

即使我认为它是“ hacky”,我也没有发现这样做的问题。如果您具有非常“非标准”的构建路径/配置,则可能会导致问题

  <Target Name="CopyClrToProjectOutputForFastUpToDateCheck" AfterTargets="AfterBuild" Condition="'$(CLRSupport)' == 'true' And '$(Language)' == 'C++'">
    <Message Text="Copying CLR Project output to intermeidate output path so that csprojs have the change to do fastuptodatecheck  $(OutputPath)$(TargetFileName) to $(IntermediateOutputPath)$(TargetFileName)"/>
    <Copy SourceFiles=" $(OutputPath)$(TargetFileName)"               DestinationFiles="$(IntermediateOutputPath)$(TargetFileName)" />
  </Target>