构建失败,因为从t4转换的类型在构建时找不到。

4
我有一个ASP.NET Core项目,其中包含一个由T4模板生成的类型IDataService。如果我手动让Visual Studio生成相应的.cs文件,然后构建项目,一切都很好:实现IDataService的各种类可以找到接口的类型,一切正常。
因为手动转换所有这些模板非常繁琐且容易出错(例如在从源代码控制克隆后),所以我修改了.csproj文件以在每次构建之前转换所有t4模板。这个方法是有效的:当我构建项目时,所有T4模板会生成最新的.cs文件。
然而,当IDataService.cs还不存在时,我构建项目,可以看到IDataService.cs在构建输出中被创建(实际文件也出现在文件夹中),但是构建失败,因为找不到类型或命名空间IDataService。如果我重新运行构建,则IDataService.cs已经存在于上一次构建中,并且一切都构建成功。
这里出了什么问题?为什么msbuild无法找到IDataService.cs,尽管它在那个构建过程中已经生成了它?
以下是构建输出(普通详细度):
Restoring NuGet packages...
To prevent NuGet from restoring packages during build, open the Visual Studio Options dialog, click on the NuGet Package Manager node and uncheck 'Allow NuGet to download missing packages during build.'
Committing restore...
Assets file has not changed. Skipping assets file writing. Path: C:\Users\Bar\source\repos\FooBar\Foo.WebApp\obj\project.assets.json
Restore completed in 246,75 ms for C:\Users\Bar\source\repos\FooBar\Foo.WebApp\Foo.WebApp.csproj.
1>------ Build started: Project: Foo.WebApp, Configuration: Debug Any CPU ------
1>Build started 20-10-2018 12:24:25.
1>Target TransformDuringBuild:
1>  Target ExecuteTransformations:
1>    Performing incremental T4 transformation
1>    Calculating whether transformed output is out of date...
1>    All outputs are up-to-date.
1>    Calculating whether transformed output is out of date...
1>    All outputs are up-to-date.
1>    Calculating whether transformed output is out of date...
1>    All outputs are up-to-date.
1>    Calculating whether transformed output is out of date...
1>    All outputs are up-to-date.
1>    Calculating whether transformed output is out of date...
1>    All outputs are up-to-date.
1>    Calculating whether transformed output is out of date...
1>    Transforming template Services\IDataService.tt...
1>    Performing incremental T4 preprocessing
1>Target _GetProjectReferenceTargetFrameworkProperties:
1>Target ResolveProjectReferences:
1>Target _HandlePackageFileConflicts:
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Collections.Immutable.dll' and 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.collections.immutable\1.5.0\lib\netstandard2.0\System.Collections.Immutable.dll'.  NETSDK1036: Choosing 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Collections.Immutable.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.DiagnosticSource.dll' and 'Reference:C:\Users\Bar\.nuget\packages\system.diagnostics.diagnosticsource\4.5.1\lib\netstandard1.3\System.Diagnostics.DiagnosticSource.dll'.  NETSDK1033: Choosing 'Reference:C:\Users\Bar\.nuget\packages\system.diagnostics.diagnosticsource\4.5.1\lib\netstandard1.3\System.Diagnostics.DiagnosticSource.dll' because AssemblyVersion '4.0.3.1' is greater than '4.0.3.0'.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Linq.Parallel.dll' and 'Reference:C:\Users\Bar\.nuget\packages\system.linq.parallel\4.3.0\ref\netstandard1.1\System.Linq.Parallel.dll'.  NETSDK1033: Choosing 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Linq.Parallel.dll' because AssemblyVersion '4.0.3.0' is greater than '4.0.0.0'.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.Metadata.dll' and 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.reflection.metadata\1.6.0\lib\netstandard2.0\System.Reflection.Metadata.dll'.  NETSDK1036: Choosing 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.Metadata.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Serialization.Xml.dll' and 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.runtime.serialization.xml\4.3.0\ref\netstandard1.3\System.Runtime.Serialization.Xml.dll'.  NETSDK1033: Choosing 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Serialization.Xml.dll' because AssemblyVersion '4.1.4.0' is greater than '4.1.1.0'.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:Microsoft.Win32.Registry.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.win32.registry\4.5.0\lib\netstandard2.0\Microsoft.Win32.Registry.dll'.  NETSDK1036: Choosing 'Platform:Microsoft.Win32.Registry.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Collections.Immutable.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.collections.immutable\1.5.0\lib\netstandard2.0\System.Collections.Immutable.dll'.  NETSDK1036: Choosing 'Platform:System.Collections.Immutable.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Diagnostics.DiagnosticSource.dll' and 'Runtime:C:\Users\Bar\.nuget\packages\system.diagnostics.diagnosticsource\4.5.1\lib\netstandard1.3\System.Diagnostics.DiagnosticSource.dll'.  NETSDK1033: Choosing 'Runtime:C:\Users\Bar\.nuget\packages\system.diagnostics.diagnosticsource\4.5.1\lib\netstandard1.3\System.Diagnostics.DiagnosticSource.dll' because AssemblyVersion '4.0.3.1' is greater than '4.0.3.0'.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Linq.Parallel.dll' and 'Runtime:C:\Users\Bar\.nuget\packages\system.linq.parallel\4.3.0\lib\netstandard1.3\System.Linq.Parallel.dll'.  NETSDK1033: Choosing 'Platform:System.Linq.Parallel.dll' because AssemblyVersion '4.0.3.0' is greater than '4.0.2.0'.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Reflection.Metadata.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.reflection.metadata\1.6.0\lib\netstandard2.0\System.Reflection.Metadata.dll'.  NETSDK1036: Choosing 'Platform:System.Reflection.Metadata.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Runtime.Serialization.Xml.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.runtime.serialization.xml\4.3.0\lib\netstandard1.3\System.Runtime.Serialization.Xml.dll'.  NETSDK1033: Choosing 'Platform:System.Runtime.Serialization.Xml.dll' because AssemblyVersion '4.1.4.0' is greater than '4.1.2.0'.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Security.AccessControl.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.security.accesscontrol\4.5.0\lib\netstandard2.0\System.Security.AccessControl.dll'.  NETSDK1036: Choosing 'Platform:System.Security.AccessControl.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Security.Cryptography.Cng.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.security.cryptography.cng\4.5.0\lib\netcoreapp2.1\System.Security.Cryptography.Cng.dll'.  NETSDK1036: Choosing 'Platform:System.Security.Cryptography.Cng.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Security.Principal.Windows.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.security.principal.windows\4.5.0\lib\netstandard2.0\System.Security.Principal.Windows.dll'.  NETSDK1036: Choosing 'Platform:System.Security.Principal.Windows.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:Microsoft.Win32.Registry.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.win32.registry\4.5.0\runtimes\unix\lib\netstandard2.0\Microsoft.Win32.Registry.dll'.  NETSDK1036: Choosing 'Platform:Microsoft.Win32.Registry.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:Microsoft.Win32.Registry.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.win32.registry\4.5.0\runtimes\win\lib\netstandard2.0\Microsoft.Win32.Registry.dll'.  NETSDK1036: Choosing 'Platform:Microsoft.Win32.Registry.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Security.AccessControl.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.security.accesscontrol\4.5.0\runtimes\win\lib\netcoreapp2.0\System.Security.AccessControl.dll'.  NETSDK1036: Choosing 'Platform:System.Security.AccessControl.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Security.Cryptography.Cng.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.security.cryptography.cng\4.5.0\runtimes\win\lib\netcoreapp2.1\System.Security.Cryptography.Cng.dll'.  NETSDK1036: Choosing 'Platform:System.Security.Cryptography.Cng.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Security.Principal.Windows.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.security.principal.windows\4.5.0\runtimes\unix\lib\netcoreapp2.0\System.Security.Principal.Windows.dll'.  NETSDK1036: Choosing 'Platform:System.Security.Principal.Windows.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Security.Principal.Windows.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.security.principal.windows\4.5.0\runtimes\win\lib\netcoreapp2.0\System.Security.Principal.Windows.dll'.  NETSDK1036: Choosing 'Platform:System.Security.Principal.Windows.dll' because it comes from a package that is preferred.
1>Target GenerateTargetFrameworkMonikerAttribute:
1>  Skipping target "GenerateTargetFrameworkMonikerAttribute" because all output files are up-to-date with respect to the input files.
1>Target _CoreGenerateRazorAssemblyInfo:
1>  Skipping target "_CoreGenerateRazorAssemblyInfo" because all output files are up-to-date with respect to the input files.
1>Target CoreGenerateAssemblyInfo:
1>  Skipping target "CoreGenerateAssemblyInfo" because all output files are up-to-date with respect to the input files.
1>Target CoreCompile:
1>  Using shared compilation with compiler from directory: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\Roslyn
1>  Services\DiagramDataService.cs(19,47,19,59): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>  Services\TestDataService.cs(9,36,9,48): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>  Controllers\GeneratedControllers\CharacterController.cs(22,36,22,48): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>  Controllers\GeneratedControllers\CharacterController.cs(20,26,20,38): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>  Controllers\GeneratedControllers\AuthorController.cs(22,33,22,45): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>  Controllers\GeneratedControllers\AuthorController.cs(20,26,20,38): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>  Controllers\GeneratedControllers\DiagramController.cs(22,34,22,46): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>  Controllers\GeneratedControllers\StorylineController.cs(22,36,22,48): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>  Controllers\GeneratedControllers\DiagramController.cs(20,26,20,38): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>  Controllers\GeneratedControllers\StorylineController.cs(20,26,20,38): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Done building target "CoreCompile" in project "Foo.WebApp.csproj" -- FAILED.
1>
1>Done building project "Foo.WebApp.csproj" -- FAILED.
1>
1>Build FAILED.
1>
1>Services\DiagramDataService.cs(19,47,19,59): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Services\TestDataService.cs(9,36,9,48): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Controllers\GeneratedControllers\CharacterController.cs(22,36,22,48): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Controllers\GeneratedControllers\CharacterController.cs(20,26,20,38): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Controllers\GeneratedControllers\AuthorController.cs(22,33,22,45): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Controllers\GeneratedControllers\AuthorController.cs(20,26,20,38): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Controllers\GeneratedControllers\DiagramController.cs(22,34,22,46): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Controllers\GeneratedControllers\StorylineController.cs(22,36,22,48): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Controllers\GeneratedControllers\DiagramController.cs(20,26,20,38): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Controllers\GeneratedControllers\StorylineController.cs(20,26,20,38): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>    0 Warning(s)
1>    10 Error(s)
1>
1>Time Elapsed 00:00:12.29
========== Build: 0 succeeded, 1 failed, 2 up-to-date, 0 skipped ==========

以下是 .csproj 文件:

<Project>
  <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk.Web" />

  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
    <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
    <IsPackable>false</IsPackable>
    <SpaRoot>ClientApp\</SpaRoot>
    <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>

    <!-- Set this to true if you enable server-side prerendering -->
    <BuildServerSideRenderer>false</BuildServerSideRenderer>
  </PropertyGroup>

  <PropertyGroup>
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
  </PropertyGroup>

  <ItemGroup>
    <T4ParameterValues Include="SolutionDir">
      <Value>$(SolutionDir)</Value>
      <Visible>False</Visible>
    </T4ParameterValues>
    <T4ParameterValues Include="Configuration">
      <Value>$(Configuration)</Value>
      <Visible>False</Visible>
    </T4ParameterValues>
  </ItemGroup>

  <PropertyGroup>
    <TransformOnBuild>true</TransformOnBuild>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="2.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.1" />
  </ItemGroup>

  <ItemGroup>
    <!-- Don't publish the SPA source files, but do show them in the project files list -->
    <Compile Remove="ClientApp\dist\**" />
    <Content Remove="$(SpaRoot)**" />
    <Content Remove="ClientApp\dist\**" />
    <None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />
  </ItemGroup>

  <ItemGroup>
    <EmbeddedResource Remove="ClientApp\dist\**" />
    <None Remove="ClientApp\dist\**" />
  </ItemGroup>

  <ItemGroup>
    <None Remove="ClientApp\src\app\diagram-types.ts" />
    <None Remove="foobar.db" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\Foo.WebApp.Database\Foo.WebApp.Database.csproj" />
    <ProjectReference Include="..\Foo\Foo.csproj" />
  </ItemGroup>

  <ItemGroup>
    <Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
  </ItemGroup>

  <ItemGroup>
    <TypeScriptCompile Include="ClientApp\src\app\diagram-types.ts" />
  </ItemGroup>

  <ItemGroup>
    <None Update="Services\IDataService.tt">
      <Generator>TextTemplatingFileGenerator</Generator>
      <LastGenOutput>IDataService.cs</LastGenOutput>
    </None>
    <None Update="Services\DiagramDataService.tt">
      <Generator>TextTemplatingFileGenerator</Generator>
      <LastGenOutput>DiagramDataService.cs</LastGenOutput>
    </None>    
  </ItemGroup>


  <ItemGroup>
    <Compile Update="Services\IDataService.cs">
      <DesignTime>True</DesignTime>
      <AutoGen>True</AutoGen>
      <DependentUpon>IDataService.tt</DependentUpon>
    </Compile>
    <Compile Update="Services\DiagramDataService.cs">
      <DesignTime>True</DesignTime>
      <AutoGen>True</AutoGen>
      <DependentUpon>DiagramDataService.tt</DependentUpon>
    </Compile>    
  </ItemGroup>


  <Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
    <!-- Ensure Node.js is installed -->
    <Exec Command="node --version" ContinueOnError="true">
      <Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
    </Exec>
    <Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." />
    <Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
  </Target>

  <Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
    <!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build -- --prod" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build:ssr -- --prod" Condition=" '$(BuildServerSideRenderer)' == 'true' " />

    <!-- Include the newly-built files in the publish output -->
    <ItemGroup>
      <DistFiles Include="$(SpaRoot)dist\**; $(SpaRoot)dist-server\**" />
      <DistFiles Include="$(SpaRoot)node_modules\**" Condition="'$(BuildServerSideRenderer)' == 'true'" />
      <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
        <RelativePath>%(DistFiles.Identity)</RelativePath>
        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
      </ResolvedFileToPublish>
    </ItemGroup> 

  </Target>

  <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk.Web" />
  <Import Project="$(VSToolsPath)\TextTemplating\Microsoft.TextTemplating.targets" />
</Project>
1个回答

4

我已经成功让它工作了,但我不太确定原因。我认为msbuild会收集要构建的文件,然后转换t4模板,最后编译收集的文件,因此不包括作为T4转换的一部分生成的文件。

项目文件列出了每个生成文件的<Compile>元素,并在“Update”属性中列出文件名。将该属性更改为“Include”将导致文件被包含在构建中,但这引入了一个新问题:如果文件尚不存在,则构建将起作用,但在随后的构建中,由于位于项目目录中,MSBuild将隐式包含这些文件,并通过项目文件显式包含,从而导致构建错误。

现在我已经在每个元素上使用Condition属性来检查文件是否已经存在:如果存在,则不包含该文件(因为msbuild已经隐式完成了),如果不存在,则包含该文件(因为msbuild不知道它)。这是生成的.csproj文件:

<Project>
  <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk.Web" />

  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
    <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
    <IsPackable>false</IsPackable>
    <SpaRoot>ClientApp\</SpaRoot>
    <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>

    <!-- Set this to true if you enable server-side prerendering -->
    <BuildServerSideRenderer>false</BuildServerSideRenderer>
  </PropertyGroup>

  <PropertyGroup>
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
  </PropertyGroup>

  <ItemGroup>
    <T4ParameterValues Include="SolutionDir">
      <Value>$(SolutionDir)</Value>
      <Visible>False</Visible>
    </T4ParameterValues>
    <T4ParameterValues Include="Configuration">
      <Value>$(Configuration)</Value>
      <Visible>False</Visible>
    </T4ParameterValues>
  </ItemGroup>

  <PropertyGroup>
    <TransformOnBuild>true</TransformOnBuild>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="2.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.1" />
  </ItemGroup>

  <ItemGroup>
    <!-- Don't publish the SPA source files, but do show them in the project files list -->
    <Compile Remove="ClientApp\dist\**" />
    <Content Remove="$(SpaRoot)**" />
    <Content Remove="ClientApp\dist\**" />
    <None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />
  </ItemGroup>

  <ItemGroup>
    <EmbeddedResource Remove="ClientApp\dist\**" />
    <None Remove="ClientApp\dist\**" />
  </ItemGroup>

  <ItemGroup>
    <None Remove="ClientApp\src\app\diagram-types.ts" />
    <None Remove="foobar.db" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\Foo.WebApp.Database\Foo.WebApp.Database.csproj" />
    <ProjectReference Include="..\Foo\Foo.csproj" />
  </ItemGroup>

  <ItemGroup>
    <Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
  </ItemGroup>

  <ItemGroup>
    <TypeScriptCompile Include="ClientApp\src\app\diagram-types.ts" />
  </ItemGroup>

  <ItemGroup>
    <None Update="Services\IDataService.tt">
      <Generator>TextTemplatingFileGenerator</Generator>
      <LastGenOutput>IDataService.cs</LastGenOutput>
    </None>
    <None Update="Services\DiagramDataService.tt">
      <Generator>TextTemplatingFileGenerator</Generator>
      <LastGenOutput>DiagramDataService.cs</LastGenOutput>
    </None>    
  </ItemGroup>


  <ItemGroup>
    <Compile Condition="!Exists('Services\IDataService.cs')" Include="Services\IDataService.cs">
      <DesignTime>True</DesignTime>
      <AutoGen>True</AutoGen>
      <DependentUpon>IDataService.tt</DependentUpon>
    </Compile>
    <Compile Condition="!Exists('Services\DiagramDataService.cs')" Include="Services\DiagramDataService.cs">
      <DesignTime>True</DesignTime>
      <AutoGen>True</AutoGen>
      <DependentUpon>DiagramDataService.tt</DependentUpon>
    </Compile>    
  </ItemGroup>


  <Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
    <!-- Ensure Node.js is installed -->
    <Exec Command="node --version" ContinueOnError="true">
      <Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
    </Exec>
    <Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." />
    <Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
  </Target>

  <Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
    <!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build -- --prod" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build:ssr -- --prod" Condition=" '$(BuildServerSideRenderer)' == 'true' " />

    <!-- Include the newly-built files in the publish output -->
    <ItemGroup>
      <DistFiles Include="$(SpaRoot)dist\**; $(SpaRoot)dist-server\**" />
      <DistFiles Include="$(SpaRoot)node_modules\**" Condition="'$(BuildServerSideRenderer)' == 'true'" />
      <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
        <RelativePath>%(DistFiles.Identity)</RelativePath>
        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
      </ResolvedFileToPublish>
    </ItemGroup> 

  </Target>

  <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk.Web" />
  <Import Project="$(VSToolsPath)\TextTemplating\Microsoft.TextTemplating.targets" />
</Project>

现在我可以从Git克隆项目,构建和重新构建任意次数,所有内容都会自动生成并包含在构建中。

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