为什么MSBuild重建共享项目?

Mzu*_*ark 5 c# msbuild visual-studio

我试图通过仅编译一次共享项目来加速一组解决方案的编译.这是我的问题的简化描述.

我有两个解决方案 - one.sln和two.sln.它们都包含共享项目shared.csproj.我在Visual Studio中打开两个解决方案,清除它们,然后构建one.sln,然后构建two.sln.构建two.sln时,不会重新生成shared.dll,这是我期望的行为.

为了自动执行此过程,我创建了一个msbuild .proj文件(如下所示).当我在.proj文件上调用msbuild时,会为两个解决方案重新编译shared.dll.我究竟做错了什么?

<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>
Run Code Online (Sandbox Code Playgroud)

Che*_*rra 3

IIRC,之所以引用被编译两次,是因为它在两个解决方案中都被声明为引用项目。因此两者都会调用其引用的构建目标。我就是这么理解的。

为参考项目创建项目组

  <!--Project reference-->
  <ItemGroup>
    <ProjectReference Include="refProject\refProject.csproj">
      <Targets>Build</Targets>
    </ProjectReference>
  </ItemGroup>
Run Code Online (Sandbox Code Playgroud)

添加目标来构建参考

  <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>
Run Code Online (Sandbox Code Playgroud)

不幸的是,MSBuild 任务不将引用作为参数。我建议创建代表每个所需项目的 itemGroup。就像是

  <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>
Run Code Online (Sandbox Code Playgroud)

并创建一个目标来构建项目,并使用编译过的引用

  <!--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>
Run Code Online (Sandbox Code Playgroud)