When looking at the file's properties in Visual Studio (2010 and above), it is possible to set the Item Type in the General section. For instance, for C++, the item type is "C/C++ compiler".
There is a "Custom Build Tool" type available, but it has to be completely configured for each file falling in that category.
My questions are:
I found the answer using the following references:
Integrating a compiler/assembler in VS ; Using NASM with Visual Studio 2010
by perilbrain on CodeProject : http://www.codeproject.com/Articles/410776/Integrating-a-compiler-assembler-in-VS-Using-NASMPlatform Extensibility - Part 1
by Pavan Adharapurapu on MSDN Blogs: https://learn.microsoft.com/en-us/archive/blogs/vsproject/platform-extensibility-part-1Platform Extensibility - Part 2
by Pavan Adharapurapu on MSDN Blogs: https://learn.microsoft.com/en-us/archive/blogs/vsproject/platform-extensibility-part-2MSBuild API Reference
on MSDN : https://msdn.microsoft.com/en-us/library/dn715758(v=vs.121).aspx`It turns out that a full setup is quite complicated, so I'll limit my answer to answering my two initial questions with minimalist steps:
In the project file (vcxproj
), include a new build definition (there is probably a way to include it system-wide, but I haven't looked into it yet):
<ImportGroup Label="ExtensionTargets">
<Import Project="mybuild.targets" />
</ImportGroup>
This can go right before the closing </Project>
.
Create a text file called mybuild.targets
in the same folder as the vcxproj
file.
Insert the following in mybuild.targets
:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PropertyPageSchema
Include="$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml" />
</ItemGroup>
</Project>
This targets file refers to a xml file with more details ($(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml
which refers in this example to mybuild.xml). Create mybuild.xml
.
Insert the following in mybuild.xml
:
<?xml version="1.0" encoding="utf-8"?>
<ProjectSchemaDefinitions xmlns="http://schemas.microsoft.com/build/2009/properties"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<ItemType Name="MYBUILD" DisplayName="My Custom Build" />
</ProjectSchemaDefinitions>
What we just did: The project file now includes a new target definition (mybuild.targets
). This file would normally hold more information about how execute the actual build, but here it contains only an include to a mybuild.xml
file. This mybuild.xml
file contains a new item type definition called with internal name MYBUILD
and display name My Custom Build
. When the project is reopened in Visual Studio, a new item type will be available in the Item Type list. Selecting it sets the type of this item to MYBUILD
and since we have no rule defined for that kind of item at this point, it will simply be ignored from the build.
This is done in two steps:
Associate the file extension to a content type. This is done by adding an entry in mybuild.xml
like this:
<FileExtension Name="*.myext" ContentType="MYBUILD" />
Associate the content type to the item type. This is done by adding an entry in mybuild.xml
like this:
<ContentType Name="MYBUILD" DisplayName="My Custom Build" ItemType="MYBUILD" />
At this point, mybuild.xml
looks like this:
<?xml version="1.0" encoding="utf-8"?>
<ProjectSchemaDefinitions xmlns="http://schemas.microsoft.com/build/2009/properties"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<ItemType Name="MYBUILD" DisplayName="My Custom Build" />
<FileExtension Name="*.hh" ContentType="MYBUILD" />
<ContentType Name="MYBUILD" DisplayName="My Custom Build" ItemType="MYBUILD" />
</ProjectSchemaDefinitions>
What we just did: Visual Studio now knows that the extension .myext
contains data of type MYBUILD
. It also knows that files with content of type MYBUILD
are items of type MYBUILD
. Once the project is reopened in Visual Studio, when adding files with the extension .myext
, Visual Studio will automatically set the item type to "My Custom Build" for these files.
At this point, we have a file extension that is associated to a custom item type. We need to associate that item type with a set of build rules.
Associate the item type to a build target. In mybuild.targets
Add the following in the same ItemGroup as our PropertyPageSchema:
<AvailableItemName Include="MYBUILD">
<Targets>_MYBUILD</Targets>
</AvailableItemName>
So that it now looks like this:
<ItemGroup>
<PropertyPageSchema
Include="$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml" />
<AvailableItemName Include="MYBUILD">
<Targets>_MYBUILD</Targets>
</AvailableItemName>
</ItemGroup>
Define the custom target. This is where you would map all the properties and variables that should be used to configure the build task. In the next step, we will use a build task that uses a command line template, so in our target, we will configure the actual command line. This goes right below the ItemGroup
defined in the previous step:
<Target Name="_MYBUILD">
<MYBUILD CommandLineTemplate="explorer $(IntDir)"></MYBUILD>
</Target>
Our command line will simply open an explorer window.
Declare a custom build task. This goes right after the Target
from the previous step:
<UsingTask TaskName="MYBUILD" TaskFactory="XamlTaskFactory" AssemblyName="Microsoft.Build.Tasks.v4.0">
<Task>$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml</Task>
</UsingTask>
Here, we refer to a task that will be defined in our mybuild.xml
file.
In mybuild.xml
, add the following rule:
<Rule Name="MYBUILD" PageTemplate="tool" DisplayName="My Custom Build" Order="200"/>
What we just did: We mapped the custom item type to a custom target, and a custom build task which opens an explorer window. When we build .myext
files, we can now expect Visual Studio to pop an explorer window.
There are ways to add configuration fields in the property window, map them to variables and use them to configure a task. This is not covered here but discussed in the links provided at the top.