为什么MSBuild会重新构建共享项目?

5
我正在尝试通过只编译共享项目一次来加速一组解决方案的编译。这是我的问题的简化描述。
我有两个解决方案——one.sln和two.sln。它们都包括共享项目shared.csproj。我在Visual Studio中打开这两个解决方案,清理它们,然后构建one.sln,再构建two.sln。当构建two.sln时,不会重新生成shared.dll,这是我期望的行为。
为了自动化此过程,我创建了一个msbuild .proj文件(如下所示)。当我在.proj文件上调用msbuild时,shared.dll将为BOTH解决方案重新编译。我做错了什么?
<Project ToolsVersion="4.0" 
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
         DefaultTargets="Build">
    <ItemGroup>
        <Solution Include="C:\one.sln"/>
        <Solution Include="C:\two.sln"/>
    </ItemGroup>
    <Target Name="Build">
      <MSBuild Projects="@(Solution)" Targets="Build" RunEachTargetSeparately="false" StopOnFirstFailure="true" />
    </Target>
 </Project>
3个回答

3
据我所知,参考项目编译两次的原因是它在两个解决方案中都声明为参考项目。因此,两个解决方案都将调用其参考项的构建目标。这就是我理解的方式。
为参考项目创建一个Itemgroup。
  <!--Project reference-->
  <ItemGroup>
    <ProjectReference Include="refProject\refProject.csproj">
      <Targets>Build</Targets>
    </ProjectReference>
  </ItemGroup>

添加目标以构建参考资料

  <Target Name="ComputeProjectReference" Inputs="@(ProjectReference)" Outputs="%(ProjectReference.Identity)__Forced">
    <MSBuild Projects="@(ProjectReference)" Targets="%(ProjectReference.Targets)">
      <Output TaskParameter="TargetOutputs" ItemName="ResolvedProjectReferences"/>
    </MSBuild>
  </Target>

  <Target Name="AfterProjectReference"  AfterTargets="ComputeProjectReference">
    <CreateItem Include="@(ResolvedProjectReferences)">
      <Output TaskParameter="Include" ItemName="CopyFiles" />
    </CreateItem>

    <Copy SourceFiles="@(CopyFiles)" DestinationFolder="$(AssemblyName)\$(OutputPath)" SkipUnchangedFiles="false"  />

    <ItemGroup>
      <NewAssemblies Include="$(AssemblyName)\$(OutputPath)%(CopyFiles.FileName)%(CopyFiles.Extension)" />
    </ItemGroup>

  </Target>

很遗憾,MSBuild任务不接受引用作为参数。我建议创建代表每个所需项目的itemGroups,类似于:

  <ItemGroup>
    <CompileA Include="ConsProject\Program.cs" />
    <CompileA Include="ConsProject\Properties\AssemblyInfo.cs" />
    <CompileA Include="ConsProject\Properties\Settings.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTimeSharedInput>True</DesignTimeSharedInput>
      <DependentUpon>Settings.settings</DependentUpon>
    </CompileA>
  </ItemGroup>

  <ItemGroup>
    <CompileB Include="OtherProject\Program.cs" />
    <CompileB Include="OtherProject\Properties\AssemblyInfo.cs" />
    <CompileB Include="OtherProject\Properties\Settings.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTimeSharedInput>True</DesignTimeSharedInput>
      <DependentUpon>Settings.settings</DependentUpon>
    </CompileB>
  </ItemGroup>

创建一个目标,使用一次编译的引用来构建项目。
  <!--Build Process-->
  <Target Name="Build" DependsOnTargets="ComputeProjectReference" >
    <Csc Sources="@(CompileA)" References="@(NewAssemblies)" TargetType="exe" OutputAssembly="$(AssemblyName)\$(OutputPath)\$(AssemblyName).exe" />

    <Csc Sources="@(CompileB)" References="@(NewAssemblies)" TargetType="exe" OutputAssembly="$(AssemblyName)\$(OutputPath)\$(AssemblyName).exe" />

  </Target>

1
我找到了共享项目为什么在每次解决方案中都要重新编译的原因。我们在每个项目中都有一个后构建步骤,用于对目标文件进行代码签名。在每个先前编译项目之后,.dll文件比.pdb文件更新,所以它会重新编译该项目。我通过使用/v:d开关进行详细记录,然后在输出中搜索“completely”来查找为什么每次都要完全构建项目。

0

Visual Studio 可能会使重建过程变得有些难以理解,因为它有一个“快速更新检查器”,其中包含自定义启发式算法。您可以通过在注册表键中启用快速更新检查程序的详细信息,了解项目正在重新构建的原因:

Visual Studio 2017(必须运行)[2]

New-ItemProperty              `
 -Name U2DCheckVerbosity      `
 -PropertyType DWORD -Value 1 `
 -Path HKCU:\Software\Microsoft\VisualStudio\15.0\General -Force

Visual Studio 2015

New-ItemProperty              `
 -Name U2DCheckVerbosity      `
 -PropertyType DWORD -Value 1 `
 -Path HKCU:\Software\Microsoft\VisualStudio\14.0\General -Force

在构建日志中,您应该能够看到以下消息:

项目“Caliburn.Micro.Silverlight.Extensions”不是最新的。 项目项“C:\ dev \ projects \ Caliburn.Micro.Silverlight.Extensions \ NavigationBootstrapperSample.cs.pp”的“复制到输出目录”属性设置为“始终复制”。

[1] https://blogs.msdn.microsoft.com/kirillosenkov/2014/08/04/how-to-investigate-rebuilding-in-visual-studio-when-nothing-has-changed/

[2] https://visualstudioextensions.vlasovstudio.com/2017/06/29/changing-visual-studio-2017-private-registry-settings/ Visual Studio 2017使用私有注册表


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