Introduction
In software development it is not uncommon to have so called compiled resources in your project. These are resources which at some point requires compilation of an external tool, and examples include effect files for graphics programming, script files and files that needs to be converted from one format to another to be useful within the application.
In my case I was working on a graphics engine, and graphics engines often include what is called shaders (which are small programs that run on the graphics card) which are written in a c-like language and has to be compiled before they are useful to the graphics card. Previously I would simply compile these shaders every time the game loaded, but obviously this is tedious and time-consuming, as they often contain errors and you had to shutdown the application, fix the error and restart the application. "What if the shaders just could be compiled at the same time as the C# code and then then embedded into the assembly?" I started wondering, and how to do that is what this article will explain.
How it's done
This all may sound terribly complicated to achieve, but to my astonishment it was actually terribly easy to do! All you have to do is modify your MSBuild file, the .csproj file.
Here's all the code you'll need, just insert it somewhere inside the Project
tag:
<ItemGroup>
<AvailableItemName Include="BuildMyResource">
<Visible>false</Visible>
</AvailableItemName>
</ItemGroup>
<Target Name="BeforeBuild">
<Exec Command="MyCustomCompiler /input=%(BuildMyResource.FullPath) output=%(BuildMyResource.FullPath).output"
Outputs="%(BuildMyResource.Identity).output">
<Output TaskParameter="Outputs" ItemName="EmbeddedResource" />
</Exec>
</Target>
What this will do is three things:
1. It will add a Build Action (right click any file in the project, choose properties and on the top you have it) called BuildMyResource, which is what you want to set your resource files to.
2. These files will then be compiled before anything else happens in the build process, if the custom compiler fails the build process is canceled. An interesting thing to note is that if the error output is formatted correctly (as is the case with the fxc.exe effect compiler for shaders) the errors will actually show up in the errors list, just like errors in your C#/VB code.
3. The file the custom compiler outputs will be embedded into the assembly, and will be identified with PathToResource.output (for example, to read it as a stream; typeof(SomeClassInYourAssembly).Assembly.GetManifestResourceStream("MyAssembly.SomeResource.output");
)
Example
Here's the code I use to compile my effects
<ItemGroup>
<AvailableItemName Include="CompiledFX">
<Visible>false</Visible>
</AvailableItemName>
</ItemGroup>
<Target Name="BeforeBuild">
<Exec Command="fxc /T fx_2_0 /Fo %(CompiledFX.FullPath)o %(CompiledFX.FullPath)" Outputs="%(CompiledFX.Identity)o">
<Output TaskParameter="Outputs" ItemName="EmbeddedResource" />
</Exec>
</Target>
History
2010-02-09: Initial publish