在MSBuild内的解决方案中循环项目
本文关键字:循环 项目 解决方案 MSBuild | 更新日期: 2023-09-27 18:03:55
在我工作的地方,我们有一个'核心'解决方案,其中包含许多提供不同实用功能的项目,这些项目通过nuget打包并发布到内部nuget服务器。为了从我们的CI中实现nuget打包,我们目前有一个MSBuild脚本,看起来像这样:
<Exec Command="nuget pack "$(ProjectRoot)'Domain'Domain.csproj" -Properties Configuration=$(Configuration)" />
<Exec Command="nuget pack "$(ProjectRoot)'Logging'Logging.csproj" -Properties Configuration=$(Configuration)" />
<Exec Command="nuget pack "$(ProjectRoot)'Logging.NLog'Logging.NLog.csproj" -Properties Configuration=$(Configuration)" />
<Exec Command="nuget pack "$(ProjectRoot)'Persistence'Persistence.csproj" -Properties Configuration=$(Configuration)" />
<Exec Command="nuget pack "$(ProjectRoot)'Persistence.NHibernate'Persistence.NHibernate.csproj" -Properties Configuration=$(Configuration)" />
我们大约有20个项目以这种方式打包,每次我们引入一个新项目打包时,我们都必须在MSBuild脚本中添加另一行。是否有可能使用MSbuild枚举解决方案中的项目,从而将此脚本压缩成类似…
<foreach project in solution>
<Exec Command="nuget pack project -Properties Configuration=$(Configuration)" />
</foreach>
另外,我们需要能够询问循环中的每个项目,以排除测试项目(这些都在Tests目录下,所以应该是微不足道的?)
EDIT:其他问题涉及在循环中执行msbuild任务的问题,但解决方案涉及在ItemGroup中手动枚举要循环的项,因此将导致稍微简单但仍然非常冗长的代码。我想尽量避免手工列举项目
您可以使用属性SolutionDir
和SolutionName
来定位解决方案文件,然后编写一个自定义目标来查找包含在解决方案中的所有项目。我是这样写的:
<Target Name="AfterBuild" DependsOnTargets="PublishNuGetPackages" />
<Target Name="PublishNuGetPackages">
<CollectNuGetProjects SolutionDir="$(SolutionDir)" SolutionName="$(SolutionName)">
<Output TaskParameter="NuGetProjects" ItemName="NuGetProjects" />
</CollectNuGetProjects>
<Message Text="Collected the following nuget projects: @(NuGetProjects)" Importance="high" />
<Exec Command="nuget pack "$(SolutionDir)'%(NuGetProjects.Identity)" -Properties Configuration=$(Configuration)" />
<!-- publish packages etc... -->
</Target>
<UsingTask TaskName="CollectNuGetProjects"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)'Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<SolutionName ParameterType="System.String" Required="true" />
<SolutionDir ParameterType="System.String" Required="true" />
<NuGetProjects ParameterType="System.String[]" Output="true" />
</ParameterGroup>
<Task>
<Reference Include="System.Linq" />
<Using Namespace="System" />
<Using Namespace="System.Linq" />
<Using Namespace="System.Text.RegularExpressions" />
<Code Type="Fragment" Language="cs">
<![CDATA[
var solutionFile = Path.Combine(SolutionDir, SolutionName + ".sln");
var solutionText = File.ReadAllText(solutionFile);
NuGetProjects = Regex.Matches(solutionText, @"""(?<projectFile>[^""]+?'.(csproj|wixproj|vcxproj))""")
.Cast<Match>()
.Select(m => m.Groups["projectFile"].Value)
.Where(p => !p.Contains(@"'Tests'"))
.ToArray();
]]>
</Code>
</Task>
</UsingTask>
还有自定义任务过滤掉位于文件夹Tests
中的项目,如您所希望的。