Reputation: 51
I'm managing a C++ project in VS2010 and want to have ALL .cpp files run through an external tool before going to the C++ compiler. All signs seem to indicate this is possible. See, for example, here.
Since this will happen over multiple projects, it makes sense to put this functionality in a property sheet and then just importing this property sheet everywhere. Before I touched the property sheet, it looked like this in its entirety:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<ExtensionsToDeleteOnClean>...</ExtensionsToDeleteOnClean>
<CustomBuildBeforeTargets>ClCompile</CustomBuildBeforeTargets>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>...</AdditionalIncludeDirectories>
<ForcedIncludeFiles>%(ForcedIncludeFiles)</ForcedIncludeFiles>
</ClCompile>
<Link>
<AdditionalDependencies>...</AdditionalDependencies>
</Link>
<Outputs>...</Outputs>
</CustomBuildStep>
</ItemDefinitionGroup>
</Project>
As per the above linked document, I have added the following lines:
<Project>
<PropertyGroup>
...
<CustomBuildBeforeTargets>ClCompile</CustomBuildBeforeTargets>
</PropertyGroup>
...
<ItemGroup>
<CustomBuild Include="*.cpp">
<Message>Running Custom Build Step</Message>
<Command>dummy</Command>
<Outputs>dummy</Outputs>
</CustomBuild>
</ItemGroup>
</Project>
This appears to have no effect, and my custom build tool never runs before ClCompile. I have tried various ways of moving things around and renaming tags (the Xml editor complains that CustomBuild isn't even valid according to the schema, for example), but nothing works.
What am I doing wrong?
Upvotes: 4
Views: 1620
Reputation: 346
Alternatively you can save yourself wildcard usage by simply running an Exec task on every included ClCompile.
<Target Name="ProcessClCompileFiles" BeforeTargets="ClCompile" Condition="'@(ClCompile)'!=''">
<Message Text="== Starting processing cpp files ==" Importance="High"/>
<Exec Command="echo processing %(ClCompile.filename)%(ClCompile.extension) & ////YOUR COMMAND HERE////" />
</Target>
As a note. This requires the ClCompile itemgroup to be initialised before this Target. if you were to create a target that dynamically adds ClCompile, you'd have to ensure that this happens before this Target is called.
Another note is that these Exec tasks will always run if there are any items in the ClCompile itemgroup. If you have a condition where it should skip them (eg, already processed), use Condition="A=B"
For easy reference, here's how to validate it hasn't created a file and if it created a file; if the file is out of date:
Condition="!Exists('$(OutDir)%(Filename)%(Extension)') OR ($([System.DateTime]::Parse('%(ClCompile.ModifiedTime)').Ticks) > $([System.IO.File]::GetLastWriteTime('$(OutDir)%(Filename)%(Extension)').Ticks))"
Upvotes: 0
Reputation: 664
Although this is a very old question, I will attempt to answer it.
The Include attribute expects to find *.cpp files in the Project directory. If there are no .cpp files in the Project directory, then this CustomBuild "Task" will never kick in.
What the OP could have done was
<CustomBuild Include="**\*.cpp">
<Message>Custombuild kicking in</Message>
<Command>echo %(Identity)</Command>
<Outputs>dummy</Outputs>
</CustomBuild>
instead of
<CustomBuild Include="*.cpp">
...
and he would have performed the CustomBuild action on all the .cpp files in all the subdirectories of the project directory, and not just the .cpp files waiting to be compiled.
If the .cpp files are not availble under the Project directory (can happen when such a project directory structure is used) then the OP must explicitly point to the right "root" directory.
Upvotes: 1