Включить дополнительные файлы в сборку, используя MSBuild ProjectReference? - PullRequest
0 голосов
/ 24 августа 2018

У меня есть библиотека классов, в которой есть несколько файлов, от которых она зависит, и эти файлы должны быть упакованы для развертывания в любом проекте, который зависит от этой библиотеки. Прямо сейчас это означает, что я должен настроить каждый из этих зависимых проектов, чтобы гарантировать, что они копируют файлы, в дополнение к добавлению библиотеки как MSBuild PrjectReference. Когда добавлено больше файлов, все проекты должны быть обновлены.

Я искал в Microsoft.Common.targets способ включения этих файлов в выходные данные собственного файла проекта библиотеки, поэтому любой проект, имеющий ссылку ProjectReference на библиотеку, будет автоматически получать файлы при выполнении сборки. , У меня еще ничего не получалось, но мне любопытнее, если это возможно. Похоже, что так и должно быть, и цель _CopyFilesMarkedCopyLocal даже учитывает неиспользуемый в противном случае элемент метаданных% (DestinationSubDirectory), который позволит настраивать размещение этих файлов, что было бы идеально.

Я полагаю, что мне не хватает, для построения проекта A, который зависит от проекта B, кусок, который добавляет выходные данные проекта B в элементы для сборки проекта A.

РЕДАКТИРОВАТЬ : комментарий Лео, я не заметил, что файлы, отмеченные CopyToOutputDirectory, также копируются в выходные каталоги зависимых проектов, потому что мы используем ItemGroups с именами, отличными от Content, EmbeddedResource, None и т. Д. Копаем глубже целевым объектом, который использует их, является GetCopyToOutputDirectoryItems, и он, кажется, рекурсивно вызывает задачу MSBuild для определения выходных данных проекта, поэтому я должен иметь возможность определить некоторую настраиваемую цель, которая может быть импортирована в наши проекты, которая добавляет наши пользовательские ItemGroups в цель GetCopyToOutputDirectoryItems, чтобы нам не приходилось использовать Content / None и т. д.

Однако цель, которая выполняет копирование - _CopyOutOfDateSourceItemsToOutputDirectoryAlways, к сожалению, не учитывающая% (DestinationSubDirectory), и поэтому все эти файлы копируются непосредственно в $ (OutDir).

Моя новая цель - выяснить, есть ли какой-нибудь способ добавить пользовательские файлы в ItemCopyLocalPaths ItemGroup зависимых проектов, чтобы они вместо этого копировались целью _CopyFilesMarkedCopyLocal, которая использует% (DestinationSubDirectory).

1 Ответ

0 голосов
/ 28 августа 2018

Добавляет настраиваемое действие сборки для ItemGroups в цель _CopyOutOfDateSourceItemsToOutputDirectoryAlways

Приведенный выше заголовок должен быть ближе к цели bwerks. В качестве теста мы могли узнать, что пользовательское действие сборки для ItemGroups не будет скопировано в выходной каталог, поэтому нам нужно наше пользовательское действие сборки для цели _CopyOutOfDateSourceItemsToOutputDirectoryAlways.

Для этого откройте файл Microsoft.Common.CurrentVersion.targets в папке MSBuild 15.0 C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets (убедитесь, что у вас достаточно прав и выполните его резервное копирование), найдите цель _CopyOutOfDateSourceItemsToOutputDirectoryAlways:

<Copy
    SourceFiles = "@(_SourceItemsToCopyToOutputDirectoryAlways)"
    DestinationFiles = "@(_SourceItemsToCopyToOutputDirectoryAlways->'$(OutDir)%(TargetPath)')"
    ...
        >

  <Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>

</Copy>

Тогда мы могли бы знать, что исходный файл копии @(_SourceItemsToCopyToOutputDirectoryAlways), поиск _SourceItemsToCopyToOutputDirectoryAlways в целевых объектах, вы найдете:

<ItemGroup>
  <_SourceItemsToCopyToOutputDirectoryAlways KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(ContentWithTargetPath->'%(FullPath)')" Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
  <_SourceItemsToCopyToOutputDirectory       KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(ContentWithTargetPath->'%(FullPath)')" Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
</ItemGroup>

Может знать, что исходный файл @(ContentWithTargetPath), продолжая искать ContentWithTargetPath в цели, в итоге мы получили следующее:

<AssignTargetPath Files="@(Content)" RootFolder="$(MSBuildProjectDirectory)">
  <Output TaskParameter="AssignedFiles" ItemName="ContentWithTargetPath" />
</AssignTargetPath>

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

Теперь , перейдите к нашему пользовательскому действию сборки, нам просто нужно добавить наше пользовательское действие сборки к ItemName="ContentWithTargetPath", поэтому добавьте следующее в файл Microsoft.Common.CurrentVersion.targets:

<AssignTargetPath Files="@(MyBuildAction)" RootFolder="$(MSBuildProjectDirectory)">
  <Output TaskParameter="AssignedFiles" ItemName="ContentWithTargetPath" />
</AssignTargetPath>

Сохраните это.

Для файла в файле проекта .csproj:

  <ItemGroup>
    <MyBuildAction Include="TextFile1.txt">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </MyBuildAction>
  </ItemGroup>

enter image description here

Надеюсь, это поможет.

...