Файлы содержимого NuGet v4 не копируются для вывода

У меня проблемы с копированием файлов NuGet для вывода с помощью интерфейса командной строки NuGet v4.

Моя структура каталогов выглядит так:

repo
repo\CodeAnalyzer.nuspec
repo\CodeAnalyzer.props
repo\contentFiles\any\any\StyleCop.ruleset

Вот мой файл CodeAnalyzer.props:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <PackageName>CodeAnalyzer</PackageName>
    <PackageVersion>0.1.0</PackageVersion>
  </PropertyGroup>
  <PropertyGroup>
      <CodeAnalysisRuleSet>StyleCop.ruleset</CodeAnalysisRuleSet>
  </PropertyGroup>
</Project>

И файл CodeAnalyzer.nuspec:

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
  <metadata>
    <id>CodeAnalyzer</id>
    <description>Provides standard code analyzer tooling and customisation.</description>
    <authors>Me</authors>
    <version>0.1.0</version>
    <dependencies>
      <dependency id="StyleCop.Analyzers" version="1.1.118" />
    </dependencies>
    <contentFiles>
      <files include="any/any/*" buildAction="Content" copyToOutput="true" flatten="false" />
    </contentFiles>
  </metadata>
  <files>
    <file src="contentFiles\any\any\StyleCop.ruleset" target="contentFiles" />
    <file src="CodeAnalyzer.props" target="build" />
  </files>
</package>

В CLI я упаковываю, используя:

.\nuget.exe pack .\CodeAnalyzer.nuspec

В полученном .nupkg есть каталог contentFiles с файлом StyleCop.ruleset, так что это работает.

Если я затем устанавливаю пакет в проект, он отлично улавливает зависимость StyleCop.Analyzers и ищет файл StyleCop.ruleset, поэтому файл .props в порядке.

Но файл StyleCop.ruleset никуда не помещается.

Похоже, я много раз пытался изменить buildActions на None / Content, copyToOutput на true / false, разные пути для элемента contentFiles.file и элемента file.file.

Изменить: потребляющий проект использует PackageReferences для пакетов NuGet, а не packages.config.


person jacob21    schedule 08.11.2019    source источник


Ответы (3)


contentFiles с PackageReference работает принципиально иначе, чем content с packages.config. С packages.config вы должны использовать инструменты (Visual Studio) для установки пакетов, а во время установки NuGet скопирует content в каталог проекта и любые другие необходимые изменения (например, указание Системе проектов изменить csproj). С packages.config восстановление концептуально отличается от установки, и все восстановление - это распаковка пакета в ожидаемом месте, чтобы сборки lib/<tfm>/*.dll были доступны во время компиляции.

С PackageReference можно вручную редактировать csproj, даже не зная об этом. Это означает, что когда NuGet выполняет восстановление, он не знает, был ли это первый раз восстановлен конкретный пакет для проекта или только первый раз на этом компьютере (фактически, NuGet даже не проверяет существующее состояние проект на машине, поэтому в настоящее время он не знает, был ли пакет ранее восстановлен в проекте на текущем компьютере). Хотя вы по-прежнему можете использовать инструменты (Visual Studio или dotnet add package), это не более чем удобный способ редактирования файла csproj. Это долгий путь к тому, чтобы сказать, что концепция «установка против восстановления» больше не существует в PackageReference. Осталось сейчас только восстановить.

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

Таким образом, contentFiles работает так: NuGet сообщает системе сборки о файлах, и они используются в качестве ссылок из папки глобальных пакетов. Во время сборки TFM .NET Framework или во время публикации TFM .NET Core файлы копируются в выходной каталог. Но они никогда не копируются в каталог проекта. При использовании Visual Studio они должны появиться в обозревателе решений, но если щелкнуть файл, чтобы открыть его, он откроется в режиме только для чтения, так как было бы плохо вносить изменения для конкретного проекта в папку глобальных пакетов, которая используется. по всем проектам на компьютере. Таким образом, концептуально это похоже на копирование файла при каждой сборке, и, чтобы отговорить разработчиков потребляющего проекта от внесения изменений, не нужно копировать файлы в каталог. Это также означает, что в системе контроля версий нужно меньше проверять.

Поскольку файл содержимого, который вы используете, является активом времени сборки, а не активом времени выполнения, я предлагаю contentFiles не подходящее место для размещения файла набора правил. Я бы просто поместил его в каталог build/ рядом с вашим файлом props. Поскольку ваш props файл не указывает путь к вашему файлу набора правил, я считаю, что он сообщает MSBuild искать в каталоге файла реквизита, поэтому он будет работать. В худшем случае поменяйте его на $(MSBuildThisFileDirectory)StyleCop.ruleset. Это при условии, что вы в порядке с проектами-потребителями, которые не могут изменить файл набора правил. Если вы хотите, чтобы они могли изменять файл, тогда NuGet не является подходящим механизмом доставки, и я предлагаю вам взглянуть на шаблоны новых элементов dotnet.

person zivkan    schedule 13.11.2019
comment
Да, я вчера сам все это проработал. Я пошел с .nuspec <contentFiles><files include="**/*.*" buildAction="None" copyToOutput="true" flatten="true" /></contentFile> и <file src="content\**" target="contentFiles\any\any" /> .. тогда в файле .props <CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)..\content\StyleCop.ruleset</CodeAnalysisRuleSet> .. невозможность редактировать файлы stylecop на самом деле идеальна, поскольку это предотвратит внесение случайных изменений людьми. Спасибо! - person jacob21; 13.11.2019

У меня была эта проблема, когда я внес много изменений, и ничего не работало. И, наконец, решено с помощью PackageReferences

В проектах packages.config используется content/ В проектах PackageReference используется contentFiles/

Вы можете найти больше о неизменяемом контенте здесь:

ContentFilesExample

nuget-contentFiles-demystified

  1. Существующий проект со ссылками на nuget через packages.config
  2. Установлен пакет NuGet с файлами содержимого
  3. Построить проект
  4. # P6 #
  5. Преобразование packages.config в PackageReferences
  6. Построить проект
  7. # P7 #

IDE - это Visual Studio 2017. Проект представляет собой проект приложения, что означает, что он находится в старом формате csproj.

Обновленный ответ

Атрибут GeneratePathProperty добавлен в PackageReference

<PackageReference Include="EO.Pdf" GeneratePathProperty="true">
    <Version>19.0.83</Version>
</PackageReference>

Проверьте свой \ obj \ .csproj.nuget.g.props, чтобы убедиться, что переменные созданы.

Переменные имеют префикс Pkg. Похоже, они автоматически создаются для всех пакетов nuget с папкой инструментов.

person Vignesh Kumar A    schedule 11.11.2019
comment
Да, наш проект уже использует PackageReferences в .csproj. Мы не используем packages.config. Я отредактирую вопрос, чтобы добавить это. - person jacob21; 11.11.2019
comment
@ jacob21 Я обновил ответ. Не могли бы вы также сослаться сюда - person Vignesh Kumar A; 11.11.2019
comment
К сожалению, это тоже не имело значения. - person jacob21; 12.11.2019

Вот еще один ответ, касающийся этого:

https://stackoverflow.com/a/68243917/56621

TL; DR - при упаковке файлов в пакет убедитесь, что вы следуете соглашению об именах any / any для целевых фреймворков / языков, иначе это не сработает.

person Alex from Jitbit    schedule 04.07.2021