Solution1.sln包含两个项目:
ProjectB有一个名为"Foo"的自定义目标.我想跑:
msbuild Solution1.sln/t:Foo
这将失败,因为ProjectA没有定义"Foo"目标.
有没有办法让解决方案忽略丢失的目标?(例如,如果特定项目不存在目标,则不执行任何操作)而不修改SLN或项目文件?
如果您不想编辑解决方案或项目文件,则可以使用两部分解决方案,并且您很高兴它可以从MSBuild命令行工作,但不能从Visual Studio工作.
首先,运行时出现的错误:
MSBuild Solution1.sln /t:Foo
Run Code Online (Sandbox Code Playgroud)
不是ProjectA不包含Foo目标,而是解决方案本身不包含Foo目标.正如@Jaykul所建议的那样,设置MSBuildEmitSolution环境变量将揭示解决方案metaproj中包含的默认目标.
使用metaproj作为灵感,您可以在解决方案文件旁边引入一个新文件"before.Solution1.sln.targets"(文件名模式很重要),内容如下:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Foo">
<MSBuild Projects="@(ProjectReference)" Targets="Foo" BuildInParallel="True" Properties="CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" SkipNonexistentProjects="%(ProjectReference.SkipNonexistentProjects)" />
</Target>
</Project>
Run Code Online (Sandbox Code Playgroud)
MSBuild元素大多只是从解决方案metaproj的Publish目标中复制而来.调整目标名称和任何其他详细信息以适合您的方案.
有了这个文件,你现在将得到ProjectA不包含Foo目标的错误.无论如何,ProjectB可能会也可能不会构建,具体取决于项目间的依赖关系.
因此,其次,为了解决这个问题,我们需要为每个项目提供一个空的Foo目标,然后在实际已经包含一个的项目中覆盖它.
我们通过引入另一个文件来实现这一点,例如"EmptyFoo.targets"(名称并不重要),如下所示:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Foo" />
</Project>
Run Code Online (Sandbox Code Playgroud)
然后我们通过运行带有额外属性的MSBuild来让每个项目自动导入此目标文件,例如:
MSBuild Solution1.sln /t:Foo /p:CustomBeforeMicrosoftCommonTargets=c:\full_path_to\EmptyFoo.targets
Run Code Online (Sandbox Code Playgroud)
或者在第一个目标文件中的MSBuild元素的Properties属性中包含CustomerBeforeMicrosoftCommonTargets属性,您可以在其中选择性地指定相对于$(SolutionDir)属性的完整路径.
但是,如果您愿意将Foo与任何默认解决方案目标(即构建,重建,清理或发布)一起运行,您可以获得一些灵感,了解MSBuild中的Web发布管道如何使用DeployOnBuild属性来调用在包含不支持发布的其他项目类型的解决方案中发布Web项目的目标.
有关before.Solution1.sln.targets文件的更多信息,请访问:http://sedodream.com/2010/10/22/MSBuildExtendingTheSolutionBuild.aspx
归档时间: |
|
查看次数: |
2577 次 |
最近记录: |