Я тестировал это только в самом базовом сценарии c, поэтому, возможно, для проекта с множественным таргетингом потребуется его модификация, и, возможно, проекты в стиле, отличном от sdk, работают иначе, чем проекты в стиле sdk, но:
исследование
Единственная важная вещь, которую вам нужно знать при исследовании чего-либо MSBuild, - это двоичный вывод журнала , который просматривается с помощью MSBuild Structed Log Viewer .
Итак, я запустил dotnet new console
и dotnet add package NuGet.Versioning
, потому что мне действительно нужно выполнять сравнения SemVer2 в консольном приложении. Теперь я запускаю dotnet build -bl
и start msbuild.binlog
.
В средстве просмотра журналов MSBuild ищу имя сборки из пакета и слово copy. В моем случае я искал «скопировать nuget.versioning.dll» и нашел один результат. Нажав на нее, я вижу, что сообщение было выведено задачей с именем «Копировать», которая выполнялась в целевом объекте с именем «_CopyFilesMarkedCopyLocal». Щелкнув Task Copy в дереве, он открывает текстовое представление Microsoft.Common.CurrentVersion.targets в строке, которая запускает задачу Copy, и я вижу следующее:
<Copy
SourceFiles="@(ReferenceCopyLocalPaths)"
DestinationFiles="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')"
SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
Retries="$(CopyRetryCount)"
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
UseHardlinksIfPossible="$(CreateHardLinksForCopyLocalIfPossible)"
UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyLocalIfPossible)"
Condition="'$(UseCommonOutputDirectory)' != 'true'"
>
Обратите внимание на пункт назначения DestinationFiles="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')"
. Хорошо, DestinationSubDirectory
звучит многообещающе. Проверяя параметры задачи копирования, элемент DestinationFiles не имеет установленного DestinationSubDirectory
, поэтому, похоже, я могу просто установить его на любой относительный путь, который я хочу.
Давайте поищем, где находятся элементы ReferenceCopyLocalPaths
определены. Я вижу два результата поиска для «AddItem ReferenceCopyLocalPaths», но, проверяя «стек вызовов» обоих из них, я вижу, что они оба находятся под целью с именем «ResolveReferences».
Последнее, так как этот вопрос Что касается сборок, поступающих из PackageReference, я хочу быть особенно осторожным, поэтому я смотрю на элемент ReferenceCopyLocalPaths и замечаю, что у него есть элемент метаданных с именем NuGetPackageId.
Итак, теперь:
- Я хочу запустить свою собственную цель после цели ResolveReferences
- Я хочу, чтобы она обновляла элементы ReferenceCopyLocalPaths
- , где определены метаданные NuGetPackageId
- установить DestinationSubDirectory на некоторый путь
решение
Добавьте эту цель в свой csproj:
<Target Name="CopyPackageAssembliesToSubFolder" AfterTargets="ResolveReferences">
<ItemGroup>
<ReferenceCopyLocalPaths Condition=" '%(ReferenceCopyLocalPaths.NuGetPackageId)' != '' "
Update="%(ReferenceCopyLocalPaths)"
DestinationSubDirectory="libs\" />
</ItemGroup>
</Target>
Теперь, когда я запускаю dotnet clean ; dotnet build
, я вижу, что в каталоге bin есть папка libs/
с NuGet. Versioning.dll.