我创建了一个自定义通用目标“RealClean”,它删除输出和“中间输出”目录中的每个文件。我将其放入 Microsoft.Common.targets 文件中。 当我在 csproj 上运行 MsBuild 时,一切都很好。 但是当我在 sln 上运行 MsBuild(仅引用 csproj 列表)时,出现以下错误
error MSB4057: The target "RealClean" does not exist in the project.
这是我输入的用于运行 MsBuild 的命令行
C:\Windows\Microsoft .NET\Framework\v3.5\MsBuild.exe /p:Configuration="Release";OutputPath="..\..\MSBuild.Referentiel.net35";nowarn="1591,1573" /t:RealClean mySolution.sln
有什么提示吗?
最佳答案
我遇到了同样的问题,但不想修改源代码树之外的内容才能使其正常工作。将文件添加到 C:\Program Files... 意味着您必须在每台开发计算机上手动执行此操作才能获得相同的行为。
我做了三件事:
1) 创建了一个自定义目标文件,通过将以下内容添加到每个项目文件中,我将其导入到解决方案中的每个 C# 和/或 VB/F# 项目中:
<!-- 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) 添加了一个 clean 目标,该目标在真正的 Clean 之后被调用(使用 MSBuild 4.0 中的 AfterTargets 属性):
<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) 在我的持续集成 MSBuild 项目中,我检查并确保所有 proj 文件都有 #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>
这可以防止开发人员忘记添加#1。您可以创建自己的项目模板,以确保所有新项目默认都有此模板。
这种方法的优点是设置新的源代码树登记除了获取当前源代码树之外不涉及任何其他内容。缺点是您必须在创建项目文件时对其进行一次编辑。
关于msbuild - 自定义通用目标来构建解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3397460/