directory.build.props: правильно связать внешние файлы содержимого, хранящиеся в многоуровневой папке, в .csproj - PullRequest
0 голосов
/ 13 марта 2020

Проведя пару дней, я здесь, чтобы обратиться за помощью.

Вот ситуация: из-за увеличения размера git хранилища наши сборки занимают слишком много времени. Большая часть времени тратится на извлечение большого набора файлов перед сборкой. Перед сборкой наш рабочий процесс Jenkins очистит рабочее пространство, чтобы убедиться в отсутствии остатков предыдущей сборки. Оказалось, что эти большие файлы содержимого не часто меняются. Итак, я разделил их в другой каталог со схожей структурой папок моих существующих файлов исходного кода. Эти файлы содержимого хранятся в другом хранилище и извлекаются только при необходимости. Итак, вот моя структура папок:

    **ContentFiles**
       \ConsoleApp1\Content\TestData
                               New Bitmap Image.bmp
                               abc.xyz
                               cosoleDep1.txt
       \Model\ConsoleApp2\Files
                          readme.txt
                          readme2.txt
       \Model\Tools\ConsoleApp3\Packages
                                New Bitmap Image.bmp
                                New Text Document.txt
    **Sources**
       \ConsoleApp1
                    ConsoleApp1.csproj
       \Model\ConsoleApp2
                    ConsoleApp2.csproj
       \Model\Tools\ConsoleApp3
                    ConsoleApp3.csproj
       ConsoleApp1.sln
       Directory.Build.props

Теперь для создания сборки некоторые из этих файлов должны быть включены в исходный файл проекта (.csproj), а другие - в соответствующую выходную папку для упаковки и выполнения модульного тестирования. , Я выбрал вариант использования файла Directory.Build.props для создания связи по мере необходимости. Итак, добавлен Directory.Build.props на уровне root источников со следующим сценарием.

<Project  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    <PropertyGroup>
        <ContentFilesDir>$(MSBuildThisFileDirectory)\ContentFiles\</DependencyDir>
    </PropertyGroup>

    <ItemGroup>
        <ContentFiles Include="$(ContentFilesDir)\**\$(MSBuildProjectName)\**\*.*"/>
    </ItemGroup>

    <ItemGroup>
       <Content Include="@(ContentFiles)"  >
            <Link>%(RecursiveDir)\%(Filename)%(Extension)</Link>
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
            <Visible>True</Visible>
        </Content>

    </ItemGroup>
</Project>

Благодаря этому файлу каждый проект связывает файлы содержимого в соответствующей папке, соответствующей проекту. имя в других местах. Файлы содержимого правильно копируются в выходную папку. Хотя некоторые файлы не следует копировать в выходную папку, пока игнорируйте этот случай.

Теперь проблема: структура папок не соответствует ожиданиям, и я не знаю, как это исправить. Если вы видите, имя папки верхнего уровня также включено в ссылку.

ConsoleApp1
       \ConsoleApp1  <----
                   \Content
                    New Bitmap Image.bmp
                   \TestData
                         abc.xyz
                         cosoleDep1.txt
ConsoleApp2
       \Model\ConsoleApp2  <----  
                   \Files
                          readme.txt
                          readme2.txt
ConsoleApp3
       \Model\Tools\ConsoleApp3 <----
                   \Packages
                             New Bitmap Image.bmp
                             New Text Document.txt

Я пытаюсь получить следующее (без projectName в качестве родителя для файлов содержимого):

ConsoleApp1
            \Content
                  New Bitmap Image.bmp
                  \TestData
                      abc.xyz
                      cosoleDep1.txt
Model\ConsoleApp2
              \Files
                 readme.txt
                 readme2.txt
Model\Tools\ConsoleApp3
              \Packages
                    New Bitmap Image.bmp
                    New Text Document.txt

интересующие здесь строки являются фильтром <ContentFiles Include="$(ContentFilesDir)\**\$(MSBuildProjectName)\**\*.*"/> и <Link>%(RecursiveDir)\%(Filename)%(Extension)</Link>. Я полагаю, что %(RecursiveDir) извлекает элемент из списка, а имя начинается с последнего обратного знака sh, который включает имя проекта. Поэтому список, который он обрабатывает, должен быть в правильном формате. Как я могу изменить фильтр, чтобы удалить этот уровень, когда проекты находятся в многоуровневой структуре папок?

Обязательные требования : Файлы содержимого должны отображаться в проекте как связанные файлы в соответствующих проектах. Если я использую какие-либо задачи, то это будет выполняться только во время задачи сборки, и это может сработать, но не будет отображаться в файлах проекта

Очень признателен за вашу помощь.

1 Ответ

0 голосов
/ 14 марта 2020

Узнав немного больше, как это работает, я пришел к следующему. Надеюсь, что это помогает другим. Предложения приветствуются !!

<Project  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <SourceDirName>Sources</SourceDirName>
        <DependencyDirName>Dependencies</DependencyDirName>
        <RootDir>$(MSBuildThisFileDirectory)</RootDir>
        <DependencyDir>$([MSBuild]::NormalizePath($(MSBuildThisFileDirectory)..\Repo1\$(DependencyDirName)))</DependencyDir>
        <SourceDir>$([MSBuild]::NormalizePath($(MSBuildThisFileDirectory)..\Repo2\$(SourceDirName)))</SourceDir>
        <MSBuildProjectDirName>$([System.IO.Directory]::GetParent($(MSBuildProjectFullPath)).Name)</MSBuildProjectDirName>
    </PropertyGroup>

    <ItemGroup>
        <DepFiles Include="$(DependencyDir)\**\$(MSBuildProjectDirName)\**\*.*"></DepFiles>
    </ItemGroup>

    <Target Name="Test" BeforeTargets="CopyFilesToOutputDirectory">
        <Message Importance="Low" Text="MSBuildThisFileDirectory $(MSBuildThisFileDirectory)"/>
        <Message Importance="Low" Text="SourceDirName            $(SourceDirName)"/>
        <Message Importance="Low" Text="DependencyDirName        $(DependencyDirName)"/>
        <Message Importance="Low" Text="RootDir                  $(RootDir)"/>
        <Message Importance="Low" Text="DependencyDir            $(DependencyDir)"/>
        <Message Importance="Low" Text="SourceDir                $(SourceDir)"/>
        <Message Importance="Low" Text="MSBuildProjectDirName    $(MSBuildProjectDirName)"/>

        <Message Importance="Low" Text="@(DepFiles->Count())"/>
        <Message Importance="Low" Text="@(DepFiles)->$([System.String]::Copy('%(FullPath)'))"/>
        <Message Importance="Low" Text="@(DepFiles)->$([System.String]::Copy('%(FullPath)').Replace($(DependencyDir), $(SourceDir)))"/>
        <Message Importance="Low" Text="@(DepFiles)->$([System.String]::Copy('%(FullPath)').Replace($(DependencyDir), $(SourceDir)).Replace($(MSBuildProjectDirectory),''))"/>
    </Target>

    <ItemGroup>
            <Content Include="@(DepFiles)" Condition="'@(DepFiles->Count())' > 0">
                <Link>$([System.String]::Copy('%(FullPath)').Replace($(DependencyDir), $(SourceDir)).Replace($(MSBuildProjectDirectory),''))</Link>
                <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
            <Visible>True</Visible>
        </Content>

    </ItemGroup>
</Project>
...