Visual Studio如何确定是否必须启动MSBuild?

时间:2017-04-03 13:17:43

标签: c# visual-studio msbuild

我过去为C ++项目做过很多MSBuild定制。 MSBuild目标的输入输出属性用于确定是否必须执行目标。此外,Visual Studio使用.tlog文件(位于中间目录中)来确定是否必须调用MSBuild。

现在我正在开发一个C#项目。我写了一个简单的MSBuild目标,它将文件复制到输出目录:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="CopyMyFile" BeforeTargets="AfterBuild" Inputs="$(ProjectDir)File.dat" Outputs="$(TargetDir)FileRenamed.dat">
    <Copy SourceFiles="$(ProjectDir)File.dat" DestinationFiles="$(TargetDir)FileRenamed.dat" OverwriteReadOnlyFiles="true">
    </Copy>
  </Target>
</Project>

如果通过MSBuild.exe调用构建,目标将按预期工作。如果目标文件不存在或源文件已被修改,则复制该文件。

如果我在Visual Studio中调用构建,它将无法按预期工作。如果从输出目录中删除该文件,Visual Studio不会调用MSBuild。另一方面,即使没有进行其他更改,每次在修改源文件后构建项目时都会调用MSBuild。

Visual Studio似乎只是将项目中的每个文件与输出文件(.exe,.dll或.pdb)进行比较。如果项目中的任何文件比输出文件新,则调用MSBuild。在我的情况下,MSBuild不会更新.exe文件,因此会一次又一次地调用MSBuild。

在C ++项目中,此行为由.tlog文件控制。 C#项目中有类似的内容吗?

非常感谢!

2 个答案:

答案 0 :(得分:0)

答案可能是 no,与tlog机制没什么相似之处。我不是百分百肯定,也是因为奇怪的是你不能做一些非常基本的事情,因为这意味着MS基本上抛弃了C#(和类似的)项目的跟踪器东西,但没有用可以挂钩的东西替换它用户。

使用procmon你可以看到VS获取输出和输入文件的时间戳,但是我找不到干扰它作为输入和输出文件处理的内容的方法。看起来VS看起来直接包含在项目文件中的所有内容列表(即VS中显示的Reference / Content / Compile / ..项目组),而不是Taget的输入/输出中列出的内容,并且在开始时构建比较那些项目的timstamps。如果所有内容(好的,考虑到VS的所有内容)都是最新的,则不会为构建启动msbuild进程。

有一种解决方法,虽然不是很好:如果你添加一个'虚拟'内容项(例如右击项目 - >添加新项目 - >文本文件)并将其设置为始终被复制(右 - clik文本文件刚添加 - &gt;属性 - &gt;复制到输出目录 - &gt;总是复制)然后VS将始终启动构建,因此检查目标的输入与输出并运行,如果你删除了FileRenamed.dat。

答案 1 :(得分:0)

看来这是文献记载很少。 This site显示您可以轻松地连接命令行工具,同时利用tlog文件的增量功能。

为确保信息不会丢失,我将仅复制他们的用例,但是考虑到这一点,我认为很容易转变为您的需求。每次dcx都可以用例如data

1。创建定义.xml文件

  • 定义一个ItemType
  • ContentType链接到ItemType
  • 连接一个FileExtension
<?xml version="1.0" encoding="utf-8"?>
<ProjectSchemaDefinitions xmlns="http://schemas.microsoft.com/build/2009/properties">
  <!-- Associate DXCShader item type with .hlsl files -->
  <ItemType Name="DXCShader" DisplayName="DXC Shader" />
  <ContentType Name="DXCShader" ItemType="DXCShader" DisplayName="DXC Shader" />
  <FileExtension Name=".hlsl" ContentType="DXCShader" />
</ProjectSchemaDefinitions>

2。创建一个.targets文件

  • 包括.xml定义文件
  • 创建一个依赖于您的构建挂钩之一的Target(此处为ClCompile
  • 在目标中创建一个ItemGroup,将其用作CustomBuild的参数。 MessageCommandAdditionalInputsOutput是相关的元属性。
  • 使用 CustomBuild MinimalRebuildFromTracking="true"调用TrackerLogDirectory以包含tlog文件。 这部分是神奇的成分,如果您的依赖项是最新的,则使MSBuild跳过构建。
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <!-- Include definitions from dxc.xml, which defines the DXCShader item. -->
    <PropertyPageSchema Include="$(MSBuildThisFileDirectory)dxc.xml" />
    <!-- Hook up DXCShader items to be built by the DXC target. -->
    <AvailableItemName Include="DXCShader">
      <Targets>DXC</Targets>
    </AvailableItemName>
  </ItemGroup>

  <Target
    Name="DXC"
    Condition="'@(DXCShader)' != ''"
    BeforeTargets="ClCompile">

    <Message Importance="High" Text="Building shaders!!!" />

    <!-- Find all shader headers (.hlsli files) -->
    <ItemGroup>
      <ShaderHeader Include="*.hlsli" />
    </ItemGroup>
    <PropertyGroup>
      <ShaderHeaders>@(ShaderHeader)</ShaderHeaders>
    </PropertyGroup>

    <!-- Setup metadata for custom build tool -->
    <ItemGroup>
      <DXCShader>
        <Message>%(Filename)%(Extension)</Message>
        <Command>
          "$(WDKBinRoot)\x86\dxc.exe" -T vs_6_0 -E vs_main %(Identity) -Fh %(Filename).vs.h -Vn %(Filename)_vs
          "$(WDKBinRoot)\x86\dxc.exe" -T ps_6_0 -E ps_main %(Identity) -Fh %(Filename).ps.h -Vn %(Filename)_ps
        </Command>
        <AdditionalInputs>$(ShaderHeaders)</AdditionalInputs>
        <Outputs>%(Filename).vs.h;%(Filename).ps.h</Outputs>
      </DXCShader>
    </ItemGroup>

    <!-- Compile by forwarding to the Custom Build Tool infrastructure,
         so it will take care of .tlogs and error/warning parsing -->
    <CustomBuild
      Sources="@(DXCShader)"
      MinimalRebuildFromTracking="true"
      TrackerLogDirectory="$(TLogLocation)"
      ErrorListRegex="(?'FILENAME'.+):(?'LINE'\d+):(?'COLUMN'\d+): (?'CATEGORY'error|warning): (?'TEXT'.*)" />
  </Target>
</Project>