VS 2017 не выполняет быструю актуальную проверку, используется ли общий каталог bin для локальных сборок - PullRequest
0 голосов
/ 06 ноября 2019

Мы хотим использовать каталог shared bin для локальных сборок разработки аналогично тому, как он используется на сервере CI. Таким образом, полностью построенная ветвь нашего приложения занимает менее трети пространства. Это означает, что на наших небольших твердотельных накопителях может поместиться больше ветвей.

Итак, мы сделали это, и все работает нормально, за исключением того, что в VS 2017 IDE больше не используется современная эвристика быстрой проверки.

Итак, перед изменением, когда мы строили код во второй раз, выходные данные сборки сообщали что-то вроде этого:

========== Build: 0 succeeded, 0 failed, 94 up-to-date, 0 skipped ==========

То есть в IDE использовалась эвристика, решили, что все проекты обновлены (оченьбыстро) и полностью пропустил msbuild.

После изменения этого не происходит, IDE фактически передает все проекты в msbuild, что занимает около минуты, чтобы прожечь все проекты. На самом деле он не компилирует никакого кода, но теперь весь процесс занимает больше времени.

Это как если бы мы установили свойство DisableFastUpToDateCheck msbuild, за исключением того, что мы не установили.

Итак,как мы устраняем это? Я хочу вернуть эвристику.

РЕДАКТИРОВАТЬ 1

Я должен сказать несколько слов о том, как мы это сделали. Каждый проект импортирует специальный файл целей непосредственно перед импортом стандартных целей (например, Microsoft.CSharp.targets). Это было разработано за 15 дней до MSBuild, поэтому мы не используем Directory.Build.targets. В этом файле мы OutDir явно указали на какой-то общий каталог bin в рабочей области. Итак, все проекты указывают OutputPath как обычно, но он переопределяется с OutDir в этом специальном файле целей. Я думаю, что это основная причина потери эвристики - он смотрит только на csproj, поэтому видит OutputPath, но не OutDir. И поскольку в OutputPath двоичные файлы не найдены, эвристика не выполняется.

Я проверю эту гипотезу и, если она окажется верной, отправит этот комментарий в качестве моего ответа.

Ответы [ 2 ]

0 голосов
/ 09 ноября 2019

Это один из редких случаев, когда двоичный журнал бесполезен, потому что он создается msbuild, то есть слишком поздно. Нужно включить диагностическую сборку в Visual Studio, потому что первая строка будет из эвристики. Здесь указана причина, по которой проект построен. Все остальные журналы диагностики могут быть отброшены, но первая строка бесценна. Это привело меня к следующему решению:

Включение эвристики

Я добавил следующие цели в файл целей, который мы импортируем из каждого проекта. Те, кому не нужна обратная совместимость с MSBuild 14, могут добавить его в Directory.Build.Targets:

<Target Name="SatisfyVisualStudioFastUpToDateCheckHeuristic" AfterTargets="AfterBuild" Condition="'$(OutDir)' != '' And '$(GatedCheckIn)' != True">
    <ItemGroup>
        <Files Include="$(TargetFileName).config" Condition="'$(AppConfig)' != '' And Exists('$(AppConfig)')" />
        <Files Include="$(TargetName).pdb" />
        <Files Include="$(TargetName)$(TargetExt)" />
        <Files Include="@(IntermediateAssembly->'%(Filename)%(Extension)')" />
        <Files Include="$(_SGenDllName)" Condition="'$(_SGenDllCreated)'=='true'" />
        <Files Include="@(ReferenceCopyLocalPaths->'%(DestinationSubDirectory)%(Filename)%(Extension)')" />
        <Files Include="@(_SourceItemsToCopyToOutputDirectory->'%(TargetPath)')" />
    </ItemGroup>
    <MakeDir Directories="$(OutputPath)\%(Files.RelativeDir)" />
    <Touch Files="@(Files->'$(OutputPath)%(Identity)')" AlwaysCreate="true" ContinueOnError="true"/>
</Target>

<Target Name="CleanFakeOutputFiles" AfterTargets="AfterClean" Condition="'$(OutDir)' != '' And '$(GatedCheckIn)' != True">
    <RemoveDir Directories="$(OutputPath)" />
</Target>

Эта цель создает поддельные суррогатные выходные файлы нулевой длины в месте, ожидаемом эвристикой.

Последующее действие 1

Это может фактически привести к сбою сборки, если есть проекты, ссылающиеся на другие проекты как библиотеки DLL, а не как ссылки на проекты. Например, если проект Алиса ссылается на проект Боба так:

<Reference Include="Bob, Version=1.0.0.0, Culture=neutral, PublicKeyToken=..., processorArchitecture=MSIL">
  <SpecificVersion>False</SpecificVersion>
  <HintPath>..\Bob\bin\$(Configuration)\Bob.dll</HintPath>
</Reference>

Проблема в HintPath. Когда мы строим с общим бином и без поддельных суррогатных выходов, HintPath игнорируется, потому что это не приводит к существующему файлу. Таким образом, Bob.dll будет найден в общей папке bin и загружен оттуда. Но когда в bin\$(Configuration) есть подделки для удовлетворения эвристики, HintPath возвращает существующий файл, поэтому поиск Bob.dll заканчивается с подделкой нулевой длины. Очевидно, компиляция не удалась. Исправление заключается в том, чтобы либо изменить его на соответствующую ссылку проекта, либо исключить HintPath со всеми метаданными:

<Reference Include="Bob" />

Нужно ссылаться на Bob.dll так же, как мы ссылаемся на системные зависимости от GAC.

Последующее действие 2

На этом этапе должен сработать код и работает эвристика. За исключением случаев, он может сказать, что не может найти какую-то зависимость, например System.IO.dll. В этом случае необходимо проверить, выполняются ли следующие два условия:

  1. Проект ссылается на System.IO.dll из некоторого каталога, например пакетов NuGet.
  2. System.IO.dll находится вGAC и лучше подходит для целевой структуры.

В моем случае у меня было несколько проектов, ссылающихся на System.IO*, System.Runtime*, System.Security* и System.ValueTuple от NuGet, тогда как эти dll существуютв GAC благодаря наличию среды выполнения .NET 4.7.2 в системе. Эвристик просматривает эти ссылки в HintPath и ожидает найти их в папке bin\$(Configuration).

Однако сборка фактически берет их из GAC, и библиотеки DLL, на которые ссылается GAC, по умолчанию не копируются в целевой лоток. Следовательно, нет поддельных суррогатов, удовлетворяющих эвристике.

Мое решение состояло в том, чтобы заменить все эти ссылки NuGet соответствующими ссылками из GAC.

РЕДАКТИРОВАТЬ 1

Проблемы 1

Побочным эффектом последующего действия 1 является то, что больше не легко вернуться к локальным папкам bin, поскольку изменениек проекту ссылки dll не обратно совместимы.

Можно сохранить метаданные HintPath, но все они должны указывать на каталог общего хранилища, в этом случае он по-прежнему несовместим со старым способом.

Выпуск 2

Visual Studio перезаписывает .vs\config\applicationhost.config каждый раз при загрузке проекта веб-приложения. Что означает:

  • Когда решение открыто
  • Когда проект выгружается, затем перезагружается

Это большой облом, потому что часть общегоПодход bin заключается в обновлении путей в .vs\config\applicationhost.config с помощью сценариев. Но такое поведение VS делает его основной неприятностью.

0 голосов
/ 07 ноября 2019

Просто добавим некоторые подробности о I want the heuristic back.

1.Хмм, только что провёл несколько тестов и подтвердил, что ваш Edit1 правильный.

Мы можем просто воспроизвести ту же проблему на локальном компьютере, не используя общую папку. Если мы используем $(OutDir) в импортированных целях, поскольку VS всегда будет искать $(OutputPath), это влияет на нормальное поведение сборки. (Согласитесь с вашим Edit1, это должен быть хороший ответ!)

2. Чтобы решить проблему, мы должны избегать использования $(OutDir) для указания окончательного пути вывода. Так что мы можем использовать $(OutputPath), к сожалению Нет !

$(OutputPath) в файле проекта будет всегда переопределять то же имя $(OutputPath), определенное в импортированном файле xx.targets. См. this : Если проект содержит определение свойства, имя которого совпадает с именем свойства среды, свойство в проекте переопределяет значение переменной среды. .

Единственный возможный способ, который я могу себе представить, - это определить $(CustomPath) (представляет общую папку) в файле xx.targets и изменить все свойства OutputPath в xx.csproj на <OutputPath>$(CustomPath)\$(Configuration)</OutputPath>. Это может быть скучной работой, потому что у вас есть почти 100 файлов проекта: (

Полагаю, скучную работу трудно избежать, если мы не откажемся от пути к общей папке. Этот ответ немного отрицательный, но надеюсь, что это сделаетнекоторая помощь ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...