Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom common target to build a solution

I created a custom common target "RealClean" which remove every files in the output and "intermediate output" directory. I put it in the Microsoft.Common.targets file. When I run MsBuild on my csproj everything is fine. But when I run MsBuild on my sln (which just references a list of csproj) I have the following error

error MSB4057: The target "RealClean" does not exist in the project.

Here is the command line I enter to run MsBuild

C:\Windows\Microsoft .NET\Framework\v3.5\MsBuild.exe /p:Configuration="Release";OutputPath="..\..\MSBuild.Referentiel.net35";nowarn="1591,1573" /t:RealClean mySolution.sln

Any hint?

like image 422
Benjamin Baumann Avatar asked Aug 03 '10 14:08

Benjamin Baumann


2 Answers

I had the same issue but didn't want to modify things outside of the source tree in order to get this to work. Adding files to C:\Program Files... means that you have to do this manually on every dev machine to get the same behavior.

I did three things:

1) Created a Custom targets file which I import into every C# and/or VB/F# project in my solution by adding the following to each proj file:

<!-- Rest of project file -->

<PropertyGroup Condition="'$(SolutionDir)' == '' or '$(SolutionDir)' == '*undefined*'">
    <!-- Relative path to containing solution folder -->
    <SolutionDir>..\</SolutionDir>
</PropertyGroup>
<Import Project="$(SolutionDir)CommonSettings.targets" />

2) Added a clean target which gets called after the real Clean (using the AfterTargets attribute from MSBuild 4.0):

<Target Name="CleanCs" AfterTargets="Clean">
    <Message Text="Deep cleaning C# project..." />
    <CreateItem Include="$(OutDir)**\*.*; $(ProjectDir)\obj\**\*.*; $(IntermediateOutputPath)**\*.*"
                            Exclude="**\bin\**\*.vshost.exe; $(IntermediateOutputPath)**\*.log">
        <Output TaskParameter="Include" ItemName="AfterClean_FilesToDelete"/>
    </CreateItem>
    <Delete Files="@(AfterClean_FilesToDelete)" />
    <CreateItem Include="$(ProjectDir)\obj\" >
        <Output TaskParameter="Include" ItemName="AfterClean_DirectoriesToDelete" />
    </CreateItem>
    <CreateItem Include ="$(ProjectDir)\bin\" Condition="'$(TargetExt)' != '.exe'" >
        <Output TaskParameter="Include" ItemName="AfterClean_DirectoriesToDelete"/>
    </CreateItem>
    <RemoveDir ContinueOnError="true" Directories="@(AfterClean_DirectoriesToDelete)" />
</Target>

3) In my continuous integration MSBuild project I check and make sure that all proj files have #1:

<ItemGroup>
    <!-- Exclude viewer acceptance tests as they must compile as x86 -->
    <CheckProjects_CsProjects Include="**\*.csproj" />
</ItemGroup>
<Target Name="CheckProjects">
    <!-- 
        Look for C# projects that don't import CommonSettingsCs.targets 
    -->
    <XmlRead XPath="//n:Project[count(n:Import[@Project[contains(string(), 'CommonSettingsCs.targets')]]) = 0]/n:PropertyGroup/n:AssemblyName/text() "
        XmlFileName="%(CheckProjects_CsProjects.Identity)"
        Namespace="http://schemas.microsoft.com/developer/msbuild/2003"
        Prefix="n" >
        <Output TaskParameter="Value" ItemName="CheckProjects_CsMissingImports"/>
    </XmlRead>
    <Error Text="Project missing CommonSettingsCs.targets: %(CheckProjects_CsMissingImports.Identity)"
                 Condition="'%(CheckProjects_CsMissingImports.Identity)' != ''" />
</Target>

This prevents developers from forgetting to add #1. You could create your own project template to ensure that al new projects have this by default.

The advantage to this approach is setting up a new source tree enlistment doesn't involve anything more than getting the current source tree. The downside is that you have to edit the project files once when you create them.

like image 171
Ade Miller Avatar answered Oct 12 '22 23:10

Ade Miller


To work on solution file, MSBuild creates a temporary MSBuild project file containing only some targets like Build and Clean. So you can't call your custom target on a solution file.

like image 41
Julien Hoarau Avatar answered Oct 12 '22 23:10

Julien Hoarau