Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом документе объясняется, как создавать пакеты, которые работают для проектов, предназначенных для .NET (5+), где управляемая сборка .NET использует платформу Invoke (P/Invoke) из управляемого языкового проекта .NET, с средой выполнения .NET с использованием путей проверки для загрузки и поиска собственной библиотеки.
Если вы хотите поддерживать платформа .NET Framework с пакетом, ознакомьтесь с разделом о проектах, предназначенных для платформа .NET Framework. Как правило, лучше всего упаковать собственные props и целевые файлы MSBuild, а также самостоятельно обрабатывать целевые объекты сборки и публикации. Не используя NuGet и встроенную функцию среды выполнения .NET, необходимо иметь достаточно знаний в MSBuild и системах сборки для соответствующих типов проектов.
Хотя NuGet имеет contentFiles/
функцию, не рекомендуется использовать эту функцию, так как она не поддерживает выбор на уровне RID и поэтому не участвует в функциях проверки путей среды выполнения .NET.
Общие сведения
Сначала мы рассмотрим пакеты ссылок на проект.
Когда приложение публикуется для определенного идентификатора среды выполнения (RID), ресурсы пакетов NuGet для этого RID будут скопированы в выходной каталог.
Когда приложение публикуется без определенного RID, все содержимое RID будет опубликовано в подкаталогах, и {project}.deps.json
создается файл, который загружает среда выполнения .NET, чтобы определить, какой каталог следует использовать в качестве пути проверки.
Кроме того, помните, что .NET 8 вводит критические изменения в отношении того, как он определяет совместимые идентификаторы RID из .deps.json
файла и какие идентификаторы RID распознаются пакетом SDK.
Общие сведения о выборе ресурса пакета NuGet
Существует три типа ресурсов в файле NuGet, наиболее релевантных для этого сценария: компиляция, среда выполнения и собственные ресурсы.
Полный список типов активов см. в документации по управлению ресурсами зависимостей в PackageReference
проектах.
Вид актива | Краткое описание |
---|---|
Компиляции | Управляемые сборки, передаваемые компилятору. ref/{tfm}/ Значение , если оно существует, в противном случае lib/{tfm}/ . |
среда выполнения | Управляемые сборки, скопированные в выходной каталог. runtimes/{rid}/lib/{tfm}/ Значение , если оно существует, в противном случае lib/{tfm}/ . |
native | Собственные библиотеки, скопированные в выходной каталог. runtimes/{rid}/native/ . |
Во всех случаях NuGet выбирает наиболее совместимый каталог для заданной платформы RID и Target Framework, а только файлы в этом каталоге копируются.
Поэтому вы не можете поместить общие ресурсы в унаследованный RID (например), так как any
если какой-либо другой RID является лучшим совпадением, any
содержимое RID не будет считаться.
Сведения о реализации выбора ресурсов NuGet см. в разделе NuGet.Client
" ManagedCodeConventions.cs
Файл".
Компиляция ресурсов
Ресурсы компиляции передаются компилятору и поэтому должны содержать только сборки .NET.
NuGet будет выбирать ресурсы компиляции из ref/{tfm}/
и, если этот каталог не существует, он будет возвращаться к lib/{tfm}
{tfm}
целевой платформе, которая является ближайшей платформой, которая соответствует проекту, ссылающемся на пакет.
Однако в этом сценарии создания пакета .NET с собственными библиотеками рекомендуется использовать ref/
, так как если lib/
используется, NuGet будет думать, что пакет совместим с проектами с использованием packages.config
, но эти проекты завершаются ошибкой во время выполнения, так как собственные файлы не будут скопированы.
Компилятор .NET создает предупреждения, когда сборка предназначена для другой архитектуры, отличной от целевой для текущей компиляции, поэтому потребители пакетов будут иметь лучший интерфейс, если целевые ref/
сборки или lib/
сборки AnyCPU
.
Если сборка содержит много управляемого кода, а не только определения методов P/Invoke, вы можете сэкономить место, сделав ref/
сборку эталонной сборкой, но обязательно включите ее ref/
в пакет, а не lib/
.
Таким образом, нет возможности предоставлять разные сборки во время компиляции для разных идентификаторов RID, вам потребуется предоставить одну область API для всех идентификаторов RID и выполнять проверка среды выполнения (например, создание).PlatformNotSupportedException
Ресурсы среды выполнения
Ресурсы среды выполнения — это управляемые сборки .NET, скопированные в выходной каталог при сборке и публикации, а пакет SDK для .NET создает deps.json
все сведения о ресурсах, зависящих от RID.
NuGet будет выбирать ресурсы среды выполнения из runtimes/{rid}/lib/{tfm}/
, и если это не существует, он будет возвращаться к lib/{tfm}/
.
Сначала выбирается лучший {rid}
каталог, а затем {tfm}
.
Однако в этом сценарии создания пакета .NET с собственными библиотеками рекомендуется использовать runtimes/
, так как если lib/
используется, NuGet будет думать, что пакет совместим с проектами с использованием packages.config
, но эти проекты завершаются ошибкой во время выполнения, так как собственные ресурсы не будут скопированы.
Собственные ресурсы
Собственные ресурсы также копируются в выходной каталог при сборке и публикации и присутствуют в deps.json
файле.
NuGet выберет собственные runtimes/{rid}/native/
ресурсы из каталога.
Примечание.
Пакет SDK для .NET неструктурирует любую структуру runtimes/{rid}/native/
каталогов при копировании в выходной каталог.
Подведем итог
Как создать все собственные библиотеки двоичных файлов из область этого документа. Предполагается, что все собственные двоичные файлы и сборки .NET были завершены и скопированы на компьютер для упаковки.
При упаковке с целевым объектом пакета MSBuild NuGet можно включить произвольные файлы в произвольные пути пакета с помощью Pack="true" PackagePath="{path}"
метаданных в элементах MSBuild.
Например, <None Include="../cross-compile/linux-x64/libcontoso.so" Pack="true" PackagePath="runtimes/linux-x64/native/" />
.
Рассмотрим пакет Contoso.Native
, предоставляющий API contoso.dll
.NET для Windows, libcontoso.dylib
OSX и libcontoso.so
Linux с помощью [DllImport("contoso")]
.
Содержимое пакета должно быть (за исключением файлов, необходимых для открытых соглашений об упаковке)
Пример 1
Если Contoso.Native
он построен как AnyCPU:
Contoso.Native.1.0.0.nuspec
ref/net8.0/Contoso.Native.dll
runtimes/any/lib/net8.0/Contoso.Native.dll
runtimes/linux-arm64/native/libcontoso.so
runtimes/linux-x64/native/libcontoso.so
runtimes/osx-arm64/native/libcontoso.dylib
runtimes/osx-x64/native/libcontoso.dylib
runtimes/win-arm64/native/contoso.dll
runtimes/win-x64/native/contoso.dll
ref/
Хотя и runtimes/any/lib
копии Contoso.Native.dll
могут быть дедупликированы в один lib/net8.0/Contoso.Native.dll
файл, это не рекомендуется, так как NuGet считает, что этот пакет совместим с проектами с использованиемpackages.config
, и эти проекты завершаются ошибкой во время выполнения, когда собственный contoso.dll
код не найден.
Пример 2
Если Contoso.Native
имеется какие-либо различия между архитектурами.
Например, но не ограничивается, используя код разности для разных идентификаторов, или использование #if
<PlatformTarget>
(или что-либо другое, которое приводит -platform:
к передаче компилятору) со значением, отличным от AnyCPU
значения.
Contoso.Native.1.0.0.nuspec
ref/net8.0/Contoso.Native.dll
runtimes/linux-arm64/lib/net8.0/Contoso.Native.dll
runtimes/linux-arm64/native/libcontoso.so
runtimes/linux-x64/lib/net8.0/Contoso.Native.dll
runtimes/linux-x64/native/libcontoso.so
runtimes/osx-arm64/lib/net8.0/Contoso.Native.dll
runtimes/osx-arm64/native/libcontoso.dylib
runtimes/osx-x64/lib/net8.0/Contoso.Native.dll
runtimes/osx-x64/native/libcontoso.dylib
runtimes/win-arm64/lib/net8.0/Contoso.Native.dll
runtimes/win-arm64/native/contoso.dll
runtimes/win-x64/lib/net8.0/Contoso.Native.dll
runtimes/win-x64/native/contoso.dll
Пример 3
Если Contoso.Native
имеется условная компиляция для каждой операционной системы, но не на архитектуру ЦП.
Contoso.Native.1.0.0.nuspec
ref/net8.0/Contoso.Native.dll
runtimes/linux/lib/net8.0/Contoso.Native.dll
runtimes/linux-arm64/native/libcontoso.so
runtimes/linux-x64/native/libcontoso.so
runtimes/osx/lib/net8.0/Contoso.Native.dll
runtimes/osx-arm64/native/libcontoso.dylib
runtimes/osx-x64/native/libcontoso.dylib
runtimes/win/lib/net8.0/Contoso.Native.dll
runtimes/win-arm64/native/contoso.dll
runtimes/win-x64/native/contoso.dll
Проекты, предназначенные для платформа .NET Framework
.NET развивалась с течением времени, вызывая несовместимость проекта и пакета при использовании определенных функций.
Как описано выше, предполагается, что проект, использующий пакет, предназначен для .NET 5 или более поздней версии, или .NET Core (netcoreapp
), который использует максимальные функции для упрощения содержимого пакета максимально возможно.
Проекты, предназначенные для .NET Standard, не особенно относятся к этому документу, так как эти проекты могут быть только библиотеками классов, которые нельзя запускать напрямую.
Однако проекты, предназначенные для платформа .NET Framework, могут использовать либо проекты стилей SDK, либо проекты стилей, отличные от пакета SDK, либо использовать PackageReference
packages.config
пакеты NuGet.
Все эти сочетания имеют разные уровни поддержки и накладывают ограничения на авторов пакетов, которые хотят поддерживать проекты платформа .NET Framework с помощью пакета.
Мы рекомендуем разделить пакет на 3 пакета.
Первым является метапакет (пакет без содержимого или ресурсов, только зависимостей от других пакетов), который имеет зависимости от одного из двух других пакетов в зависимости от целевой платформы.
Второй пакет содержит .NET 5+ ref/*
и runtimes/*
ресурсы, как описано выше.
Последний пакет будет содержать платформа .NET Framework ресурсы и не будет использовать ref/*
соглашения или runtime/*
соглашения.
Это связано с поддержкой системы сборки (частичной) для этих соглашений NuGet, но среда выполнения работает достаточно по-разному, чтобы избежать ее, чтобы максимально повысить совместимость проектов.
Пакет с платформа .NET Framework собственными библиотеками должен иметь пользовательские целевые объекты MSBuild и файлы props в разделе buildTransitive/<tfm>/<package ID>.[props|targets]
.
Например, buildTransitive/net472/Contoso.Native.targets
.
Для поддержки packages.config
проектов также есть файл build/<tfm>/<package ID>.[props|targets]
, который импортирует buildTransitive
файл.
Этот скрипт MSBuild должен скопировать собственную библиотеку в подкаталоги.
Кроме того, собственные библиотеки должны иметь разные имена файлов для каждой архитектуры ЦП, поэтому их можно скопировать в один каталог.
Наконец, у управляемой библиотеки, которая использует P/Invoke для вызова в собственную библиотеку, она должна иметь проверка среды выполнения, чтобы определить, в какой платформе работает текущий исполняемый файл (x86, x64 или ARM64), а затем P/Invoke в собственную библиотеку с правильным именем файла или правильным подкаталогом.
Проекты стилей SDK, предназначенные для платформа .NET Framework
Когда пакет SDK для .NET создает проект, предназначенный для платформа .NET Framework, если один из RuntimeIdentifier
них или PlatformTarget
задан, пакет SDK для .NET установит другое свойство соответствующим значением, а содержимое пакета runtimes/<rid>
(в соответствии с соглашениями NuGet) будет скопировано в выходной каталог.
Если проект не задан или не заданRuntimeIdentifier
, но любой пакет содержит содержимое RID, пакет SDK для .NET будет иметь значение x86
PlatformTarget
.PlatformTarget
Поэтому проекты стилей ПАКЕТА SDK, предназначенные для платформа .NET Framework, будут использоваться AnyCPU
только по умолчанию, если ни один из пакетов не содержит определенное содержимое RID.
dotnet build -r <rid>
или publish
эквивалент (например, dotnet publish -r win-arm64
) можно использовать для явной сборки или публикации для определенной платформы.
Для поддержки AnyCPU
проектов авторы пакетов не должны использовать соглашения в своем пакете и должны использовать runtimes/
файлы целевых объектов ИЛИ props MSBuild, как описано выше.
Проекты, не относящиеся к пакету SDK, предназначенные для платформа .NET Framework сPackageReference
При тестировании проекта, отличного от пакета PackageReference
sdk, с помощью runtimes/*
соглашения происходит следующее поведение.
Если конфигурация проекта предназначена для платформы "Любой ЦП", сборка не будет копировать какие-либо определенные ресурсы RID из пакета, и приложение завершится сбоем во время выполнения.
С помощью Configuration Manager Visual Studio проекты .NET можно изменить на целевые объекты x64, x86 или ARM64, а не "Любой ЦП", в этом случае приложение будет работать правильно во время выполнения.
Для поддержки AnyCPU
проектов авторы пакетов должны использовать файлы целевых объектов и props MSBuild, как показано выше.
packages.config
Исходный стиль восстановления NuGet, packages.config
не поддерживает ref/*
или runtimes/*
соглашения.
Поэтому авторы пакетов должны создавать собственные реквизиты MSBuild и целевые файлы для поддержки проектов, которые по-прежнему используются packages.config
.