如何在将文件添加到部件之前转换文件



我想做以下事情:

(项目是WPF的用户控制库)

  • 加一堆。FX(着色器源代码)文件作为资源添加到项目中(生成操作)
  • 将每个转换为。PS文件(编译的着色器)。EXE实用程序
  • 使用生成的文件代替输入的文件

我一直想写一个CustomTool,不幸的是,Visual Studio从未见过该工具,正如文章中提到的那样。在这篇文章中,据说有时它没有被看到,但在我的情况下,它每次都被翻译为

我还研究了MSBuild Transforms,但我真的不确定它是否适合该任务。

这样做的目的是包含着色器文件源代码并在构建时对其进行转换,而不是从命令行手动构建它们并每次将它们放到项目中。

你知道怎样才能做到这一点吗?欢迎任何方法

编辑

感谢@Luaan:回答

public class CompileEffectTask : Task
{
    public string[] Files { get; set; }
    public override bool Execute()
    {
        if (Files != null)
        {
            foreach (string file in Files)
            {
                if (file != null)
                {
                    Log.LogMessage(MessageImportance.High, file);
                    string s = @"C:Program Files (x86)Windows Kits8.1binx86fxc.exe";
                    string changeExtension = Path.ChangeExtension(file, "ps");
                    string arguments = string.Format("/T ps_3_0 /Fo "{0}"" + " " + ""{1}"", changeExtension,
                        file);
                    Log.LogMessage(MessageImportance.High, arguments);
                    var process = new Process
                    {
                        StartInfo = new ProcessStartInfo(s, arguments)
                    };
                    process.Start();
                    process.WaitForExit();
                }
            }
        }
        return true;
    }
}

MSBuild部分:

  <UsingTask TaskName="CompileEffectTask" AssemblyFile="D:HLSLCompiler.dll" />
  <PropertyGroup>
    <BuildDependsOn>
      MyCustomTarget1;
      $(BuildDependsOn);
    </BuildDependsOn>
  </PropertyGroup>
  <Target Name="MyCustomTarget1">
    <Message Text="CompileEffectTask started" Importance="high" />
    <Message Text="Compiling FX files ..." Importance="high" />
    <CompileEffectTask Files="@(CompileEffectTask)"/>
    <Message Text="Adding resulting .PS files as resources ..." Importance="high" />
    <ItemGroup>
      <Resource Include="***.ps" />
    </ItemGroup>
  </Target>
  <Target Name="AfterBuild">
    <CreateItem Include="***.ps">
      <Output TaskParameter="Include" ItemName="DeleteAfterBuild" />
    </CreateItem>
    <Delete Files="@(DeleteAfterBuild)" />
  </Target>

(仍然需要一些清洁,但它可以工作:D)

事实上,自定义工具确实可以工作,但它们的设置相当棘手——它们是Visual Studio的COM扩展。然而,对于您的案例,更好的解决方案是自定义生成目标或预生成事件——自定义工具(代码生成器)更适合生成代码(文本),而不是二进制文件。

因此,预构建事件是一个简单的事件。这只是在项目开始构建之前运行的一些脚本。您可以在项目属性中找到它。最简单的方法是将所有.fx文件放在一个目录中,在预构建事件中,只需对每个文件调用fxc.exe

现在,构建目标更酷了。它们允许您将自己的构建操作添加到文件中,以及其他操作。所以你只需要在文件的Build action中选择CompileEffect,神奇的事情就发生了。

目标文件可以很简单:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <AvailableItemName Include="CompileEffect"></AvailableItemName>
  </ItemGroup>
</Project>

或者,您可以直接将ItemGroup部分放在项目文件中(否则,您可能希望包含此目标文件)。

接下来,您希望将任务设置为构建的一部分:

<PropertyGroup>
  <BuildDependsOn>
    MyCompileTarget;
    $(BuildDependsOn);
  </BuildDependsOn>
</PropertyGroup>

这基本上是说"先运行我的构建目标,然后再运行任何你想要的"。

现在,对于大楼:

<Target Name="MyCompileTarget">
  <CompileEffectTask
      ProjectDirectory="$(ProjectDir)"
      Files="@(CompileEffect)"
      RootNamespace="$(RootNamespace)">
  </CompileEffectTaskTask>
</Target>

Visual Studio如何知道CompileEffectTask是什么?

<UsingTask TaskName="MyAssembly.CompileEffectTask" 
           AssemblyFile="C:MyAssembly.dll"/>

然后您只需要实现编译器任务本身。

现在,如果你只想调用一个可执行文件或批处理脚本,你甚至不需要这个自定义任务,因为MSBuild中有很多内置任务(MSBuild社区任务中甚至更多)。Exec任务应该工作:

<Target Name="MyCompileTarget">
  <Exec Command="fxc.exe @(CompileEffect)" />
</Target>

你可能需要在那里写一个for循环,我不完全确定。你可以做很多事情来定制项目构建,http://msdn.microsoft.com/en-us/library/0k6kkbsd.aspx(尤其是Task refecence部分)是一个相当好的开端。

相关内容

  • 没有找到相关文章

最新更新