Устранить зависимости NuGet внешнего проекта.NET 4.7 с помощью целей MSBuild

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

Таким образом, прежде чем строить наши проекты, нам нужно построить подпроект. Это делается путем добавления пользовательской цели сборки в цель BeforeBuild каждого проекта, и, похоже, работает. Однако, подпроект не будет построен без восстановления зависимостей NuGet.

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

Каждая из этих внешних зависимостей проекта указана в пользовательской ItemGroup, например:

<ItemGroup> <ExternalDependantProjects Include= "..\<subfolder>\<project>\<project>.csproj" /> </ItemGroup>

Мы пытались решить эту проблему, добавляя пользовательские цели сборки, которые вызываются целью BeforeBuild каждого проекта. Сначала мы попытались использовать ResolveNuGetPackageAssets в качестве цели сборки, но обнаружили, что это поддерживается только в netcore, в то время как мы нацелены на net47.

Теперь мы пытаемся написать пользовательскую цель сборки, которая восстановит зависимости NuGet во внешнем проекте. Мы попробовали простой подход, вот так: <Exec Command="nuget restore @(ExternalDependantProjects)" /> и несколько более сложная и хакерская попытка PowerShell: <Exec Command="powershell.exe -command &quot;&apos;@(ExternalDependantProjects, '&apos; &apos;')&apos; | foreach { nuget restore $_ }&quot;" />

В обоих случаях он просто пытается восстановить пакеты основного проекта, а не внешних проектов. Кажется, что @(ExternalDependantProjects) равно пустому, и поэтому новый аргумент не добавляется. Использование показало, что @(ExternalDependantProjects) ничего не возвращает. Тем не менее, он работает как параметр "Projects", когда мы вызываем MSBuild "Build" target. Итак, я подозреваю, что мы используем параметр Item неправильно? Возможно, есть некоторый синтаксис для доступа к свойству Include элемента?

Однако я не уверен, что это сработает, если мы сможем решить эту проблему. Мы протестировали с помощью команды восстановления nuget в подпроекте и всегда получаем ответ, что все пакеты в packages.conf установлены. Тем не менее,.. \ packages \ из этого внешнего проекта пуст, а packages.conf указывает полдюжины пакетов (они также отсутствуют в "References" в VS, и HintPath ссылок правильно переходит в..\packages).

Таким образом, мы сбиты с толку по трем направлениям: как мы ссылаемся на путь включения элемента ExternalDependentProjects из целей MSBuild, почему NuGet не восстанавливает CLI, и является ли это даже правильным способом решения этой проблемы? Мы спустились совсем не по тому пути?

2 ответа

Решение

Как мы ссылаемся на путь включения элемента ExternalDependentProjects из целей MSBuild, почему NuGet не может восстановить CLI, и является ли это даже правильным способом решения этой проблемы? Мы спустились совсем не по тому пути?

Вы должны написать свою собственную цель сборки с опцией -OutputDirectory, поэтому пользовательская цель сборки должна быть такой:

  <Target Name="BeforeBuild">
      <Exec Command="nuget restore @(ExternalDependantProjects) -OutputDirectory ..\<subfolder>\packages" />
  </Target>

С этой целью пакет NuGet для внешних проектов будет успешно восстановлен.

Кроме того, значение @(ExternalDependantProjects) не равно пустому, вы можете использовать целевой эхо это значение.

Ниже мой тестовый образец, вы можете обратиться к подробной информации:

ExternalpProject это имя подпапки, TestExternalProject это имя внешнего проекта.

<ItemGroup>
  <ExternalDependantProjects Include= "..\ExternalpProject\TestExternalProject\TestExternalProject.csproj" />
</ItemGroup> 

<Target Name="BeforeBuild">
  <Message Text="Restore package for Externalp Project" Importance="high"></Message>
  <Exec Command="nuget restore @(ExternalDependantProjects) -OutputDirectory ..\ExternalpProject\packages" />
</Target>

<Target Name="AfterBuild">
  <Message Text="Display the value of ExternalDependantProjects" Importance="high"></Message>
  <Message Text="@(ExternalDependantProjects)"></Message>
</Target>

NuGet обнаруживает проекты package.config для восстановления из файла решения. Если все проекты находятся в файле решения и вы запускаете nuget.exe restore <solution file> они должны быть восстановлены независимо от того, что происходит в файлах проекта.

В качестве обходного пути для любого пользовательского сценария вы можете написать сценарий для обнаружения всех файлов packages.config в папке, а затем вызвать nuget.exe restore <packages.config> -SolutionDirectory <solution root> на файлы напрямую. Для восстановления packages.config единственной необходимой частью является обнаружение списка id / версий из файлов packages.config, чтобы их можно было загрузить и извлечь в папку пакетов уровня решения.

Я также предлагаю использовать ссылки проекта с ReferenceOutputAssembly=false обеспечить, чтобы проекты создавались в нужном вам порядке и без ссылок друг на друга. См.: https://blogs.msdn.microsoft.com/kirillosenkov/2015/04/04/how-to-have-a-project-reference-without-referencing-the-actual-binary/

Другие вопросы по тегам