在我的工作地点,我们有一个'核心'解决方案,其中包含许多项目,这些项目提供不同的实用程序功能,这些功能通过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目录下,所以应该是微不足道的?)
编辑: Other questions处理循环中执行msbuild任务的问题,但解决方案涉及手动枚举要在ItemGroup中循环的项目,所以会导致稍微简单但仍然非常冗长的代码。如果可能的话,我想避免手工列举项目。
答案 0 :(得分:1)
您可以使用属性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
中的项目。