我有一个很大的解决方案(〜450个项目),尽管我没有做任何更改,但有些项目却一遍又一遍地构建。
当我将构建输出的详细程度更改为diagnostic
时,它说:
项目“ ProjectA”不是最新的。缺少输入文件'C:\ Src \ Project.Core \ Bin \ Release \ ProjectB.dll'
ProjectA
取决于ProjectB
,并且我正在构建配置Debug
,所以Visual Studio为什么在ProjectB.dll
文件夹中检查文件Release
? ProjectB.dll
将被构建并复制到正确的文件夹中(调试)!
每个项目(c#和c ++)的输出路径都相同:
<OutputPath>$(SolutionDir)Bin\$(Configuration)\</OutputPath>
这只是一个例子。我的解决方案中的多个项目都有这种奇怪的行为。似乎是c ++项目造成了这种情况,但我没有明确的证据。
这是我对文件访问的Process Monitor分析:
更新1:
ProjectA(C#项目)使用ProjectReference
引用ProjectB(C ++项目):
<ProjectReference Include="..\..\ProjectB.vcxproj">
<Project>{F2F4C146-8A98-432B-BB9F-A06C4B4162CF}</Project>
<Name>ProjectB</Name>
</ProjectReference>
更新2:
.NET Core项目有以下设置:
针对.NET Framework的项目是否有类似的东西?
更新3:
好像C#项目的FastUpToDateCheck
的代码在csproj.dll
程序集中。由于它是本机程序集,因此我无法查看代码。真可惜。
答案 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.targets
(link)的某处添加以下代码以解决您的问题,更新检查将起作用。
发生的所有事情都是将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>