Custom common target to build a solution

匿名 (未验证) 提交于 2019-12-03 03:05:02

问题:

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?

回答1:

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.



回答2:

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.



回答3:

Madgnome is probably right. But I wanted to add that you should not be editing the Microsoft.common.targets files. If you do so you risk having a different build process on that machine versus what everybody else has. In your case you could have created a new MSBuild file with just the RealClean target and placed it at C:\Program Files (x86)\MSBuild\v4.0\Custom.After.Microsoft.Common.targets or for 32 bit C:\Program Files\MSBuild\v4.0\Custom.After.Microsoft.Common.targets and essentially that would be the same as putting that file inside of Microsoft.Common.targets, except you don't have to modify that file.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!