visual-studio - 包含编译文件(增量构建)

标签 visual-studio msbuild csproj

我有一个增量build设置,如下所示:

  <ItemGroup>
    <MyInput Include="$(MyInput)" />
    <UpToDateCheckInput Include="@(MyInput)" />
    <UpToDateCheckBuilt Include="$(MyOutput)" />
  </ItemGroup>

  <Target Name="MyCodeGen"
          BeforeTargets="PreBuildEvent"
          DependsOnTargets="ResolveReferences"
          Inputs="@(MyInput);$(MSBuildThisFileFullPath);$(MyCodegenExe)"
          Outputs="$(MyOutput)">
    <Exec Command="$(MyCodegenExe) $(MyCodegenParams)" />
    <ItemGroup>
      <Compile Remove="$(MyOutput)" />
      <Compile Include="$(MyOutput)" />
    </ItemGroup>
  </Target>
目标生成单个 .cs 文件 $(MyOutput)需要在当前项目中包含和编译。请注意在目标中我首先删除然后包含此文件。
  • 在第一次构建时,目标按预期运行。
  • 在第二次构建时,目标没有按预期运行。但是 MSBuild 仍然可以编译,因为 $(MyOutput) “自上次最新检查以来已被修改”。
  • 在第三次构建时,一切都是最新的。

  • 如何在第二次构建中获得“一切都是最新的”结果?

    最佳答案

    无条件地包含文件应该可以工作。例如,在 Microsoft.CSharp.targets 导入之后的默认 C# 项目模板中使用这些行:

    <ItemGroup>
      <MyInput Include="in.txt" />
    </ItemGroup>
    <PropertyGroup>
      <MyOutput>Generated.cs</MyOutput>
    </PropertyGroup>
    <Target Name="MyCodeGen" BeforeTargets="PreBuildEvent" DependsOnTargets="ResolveReferences"
            Inputs="@(MyInput);$(MSBuildThisFileFullPath)"
            Outputs="$(MyOutput)">
      <ReadLinesFromFile File="@(MyInput)">
        <Output TaskParameter="Lines" ItemName="MyInputlines"/>
      </ReadLinesFromFile>
      <Message Text="CODEGEN lines @(MyInputlines)" />
      <WriteLinesToFile File="$(MyOutput)" Lines="@(MyInputlines)" Overwrite="True" />
    </Target>
    <ItemGroup>
      <Compile Include="$(MyOutput)"/>
    </ItemGroup>
    
    在命令行上运行 msbuild/v:d 的结果是(仅显示 MyCodeGen Target 的输出):
    第一次运行的输出(Generated.cs 还不存在):
    Target "MyCodeGen" in project "my.csproj" (target "PreBuildEvent" depends on it):
    Building target "MyCodeGen" completely.
    Output file "Generated.cs" does not exist.
    Using "ReadLinesFromFile" task from assembly "Microsoft.Build.Tasks.Core, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
    Task "ReadLinesFromFile"
    Done executing task "ReadLinesFromFile".
    Task "Message"
      CODEGEN lines using System;
    Done executing task "Message".
    Using "WriteLinesToFile" task from assembly "Microsoft.Build.Tasks.Core, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
    Task "WriteLinesToFile"
    Done executing task "WriteLinesToFile".
    Done building target "MyCodeGen" in project "my.csproj".
    
    第二/第三/...运行的输出:
    Target "MyCodeGen" in project "my.csproj" (target "PreBuildEvent" depends on it):
    Skipping target "MyCodeGen" because all output files are up-to-date with respect to the input files.
    Input files: in.txt;my.csproj
    Output files: Generated.cs
    Done building target "MyCodeGen" in project "my.csproj".
    
    修改in.txt后build的输出:
    Target "MyCodeGen" in project "my.csproj" (target "PreBuildEvent" depends on it):
    Building target "MyCodeGen" completely.
    Input file "in.txt" is newer than output file "Generated.cs".
    Using "ReadLinesFromFile" task from assembly "Microsoft.Build.Tasks.Core, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
    Task "ReadLinesFromFile"
    Done executing task "ReadLinesFromFile".
    Task "Message"
      CODEGEN lines using System.Linq;
    Done executing task "Message".
    Using "WriteLinesToFile" task from assembly "Microsoft.Build.Tasks.Core, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
    Task "WriteLinesToFile"
    Done executing task "WriteLinesToFile".
    Done building target "MyCodeGen" in project "my.csproj".
    
    在此之后运行的输出:
    Target "MyCodeGen" in project "my.csproj" (target "PreBuildEvent" depends on it):
    Skipping target "MyCodeGen" because all output files are up-to-date with respect to the input files.
    Input files: in.txt;my.csproj
    Output files: Generated.cs
    Done building target "MyCodeGen" in project "my.csproj".
    
    如果这对您不起作用,则可能是例如您用来生成文件的过程与 msbuild 不能很好地配合,因为它没有正确更新时间戳。例如。仅复制比项目文件旧的现有文件将导致 Generated.cs 的时间戳比 $(MSBuildThisFileFullPath) 输入旧,因此目标将始终运行。

    关于visual-studio - 包含编译文件(增量构建),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69397117/

    相关文章:

    c# - SSDT 部署后脚本 - 运行文件夹中的所有脚本

    visual-studio - 如何从 .proj 文件制作 visual studio 解决方案文件

    xml - 以编程方式修改 .csproj 文件

    MSBuild:如何在没有内部版本号的情况下在 Visual Studio 项目中添加库引用?

    visual-studio-2008 - 如何获取项目 csproj 的默认命名空间(VS 2008)

    c# - 我可以在 tfs 上检查我的 cs 项目属性吗?

    visual-studio - VS2005 "Add New Item..."对话框 - 默认项

    c# - 在 Visual Studio 中设置 SSL 证书

    android - Xamarin 初学者 + 独立 VS 2015

    c# - 在 MsBuild 中,PropertyGroup 和 ItemGroup 有什么区别