我以前为我的C ++项目做了很多MSBuild定制。 MSBuild目标的Input和Output属性用于确定是否必须执行目标。此外,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#项目中有类似的东西吗?
非常感谢!
答案可能是否定的,与tlog机制没什么相似之处。我不是百分百肯定,也是因为奇怪的是你不能做一些非常基本的事情,因为这意味着MS基本上抛弃了C#(和类似的)项目的跟踪器东西,但没有用可以挂钩的东西替换它由用户。
使用procmon你可以看到VS获取输出和输入文件的时间戳,但是我找不到一种方法来干扰它作为输入和输出文件的处理方式。看起来VS看起来直接包含在项目文件中的所有内容列表(即VS中显示的Reference / Content / Compile / ..项目组),而不是Taget的输入/输出中列出的内容,并且在开始时构建比较那些项目的timstamps。如果所有内容(以及考虑到VS的所有内容)都是最新的,则不会为构建启动msbuild进程。
有一个解决方法,虽然不是很好:如果你添加一个'虚拟'内容项(例如右键单击项目 - >添加新项目 - >文本文件)并将其设置为始终被复制(刚刚添加的右clik文本文件) - >属性 - >复制到输出目录 - >始终复制)然后VS将始终启动构建,因此检查目标的输入与输出,如果删除了FileRenamed.dat则运行。
看起来这个文档很难记录。 This site显示您可以轻松地连接命令行工具,同时提升tlog文件的增量功能。
为了确保信息不会丢失,我只是复制他们的用例,但看着它,我认为很容易转化为您的需求。每次出现的dcx
都可以被替换为例如data
.xml
fileItemType
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>
.targets
file.xml
定义文件Target
(这里:ClCompile
)ItemGroup
,它将作为你的CustomBuild
的参数。 Message
,Command
,AdditionalInputs
和Output
是相关的元属性。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>