Цикл проектов в решении в MSBuild

1

На моем месте работы у нас есть "Core" решение, содержащее ряд проектов, предоставляющих разные функции утилиты, которые упаковываются через nuget и публикуются на внутреннем сервере nuget. Чтобы получить пакет nuget из нашего CI, в настоящее время у нас есть сценарий MSBuild, который выглядит так:

<Exec Command="nuget pack &quot;$(ProjectRoot)\Domain\Domain.csproj&quot; -Properties Configuration=$(Configuration)" />
<Exec Command="nuget pack &quot;$(ProjectRoot)\Logging\Logging.csproj&quot; -Properties Configuration=$(Configuration)" />
<Exec Command="nuget pack &quot;$(ProjectRoot)\Logging.NLog\Logging.NLog.csproj&quot; -Properties Configuration=$(Configuration)" />
<Exec Command="nuget pack &quot;$(ProjectRoot)\Persistence\Persistence.csproj&quot; -Properties Configuration=$(Configuration)" />
<Exec Command="nuget pack &quot;$(ProjectRoot)\Persistence.NHibernate\Persistence.NHibernate.csproj&quot; -Properties Configuration=$(Configuration)" />

У нас около 20 проектов упакованы таким образом, и каждый раз, когда мы представляем новый проект, который должен быть упакован, мы должны добавить еще одну строку в сценарий MSBuild. Можно ли перечислить проекты в решении с помощью MSbuild и таким образом сконденсировать этот скрипт на что-то вроде...

<foreach project in solution>
    <Exec Command="nuget pack project -Properties Configuration=$(Configuration)" />
</foreach>

Кроме того, нам нужно было бы допросить каждый проект в цикле, чтобы исключить тестовые проекты (все они находятся в каталоге Tests, поэтому это должно быть тривиально?)

EDIT: Другие вопросы касаются проблемы выполнения задач msbuild в цикле, но решения включают в себя ручную перечисление элементов, которые будут зацикливаться в ItemGroup, поэтому это приведет к немного более простому, но все же очень сложному коду. Я хочу избежать перечисления проектов вручную, если это возможно.

Теги:
msbuild

1 ответ

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 &quot;$(SolutionDir)\%(NuGetProjects.Identity)&quot; -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 как вы хотели.

  • 0
    Спасибо за этот @sburg, даст ему шанс!
  • 0
    Только что проверил, работает угощение! Спасибо :)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню