Добавление библиотек x86 и x64 в пакет NuGet
Я создал библиотеку, которая зависит от CEFsharp, которая требует создания библиотеки для определенных платформ. Таким образом, поддержка AnyCPU не поддерживается.
Теперь я хочу упаковать это в NuGet. Насколько я понимаю, вы должны поместить эти файлы в папку сборки и иметь файл .targets
, который выбирает правильную DLL для ссылки. Итак, я закончил с пакетом NuGet, выглядящим следующим образом:
lib
monodroid
MyLib.dll
xamarin.ios10
MyLib.dll
net45
MyLib.dll (x86)
build
net45
x86
MyLib.dll (x86)
x64
MyLib.dll (x64)
MyLib.targets
Я помещаю внутри файла .targets
следующее:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="PlatformCheck" BeforeTargets="InjectReference"
Condition="(('$(Platform)' != 'x86') AND ('$(Platform)' != 'x64'))">
<Error Text="$(MSBuildThisFileName) does not work correctly on '$(Platform)' platform. You need to specify platform (x86 or x64)." />
</Target>
<Target Name="InjectReference" BeforeTargets="ResolveAssemblyReferences">
<ItemGroup Condition="'$(Platform)' == 'x86' or '$(Platform)' == 'x64'">
<Reference Include="MyLib">
<HintPath>$(MSBuildThisFileDirectory)$(Platform)\MyLib.dll</HintPath>
</Reference>
</ItemGroup>
</Target>
</Project>
Пока все хорошо. Теперь к проблеме. Добавляя этот NuGet к новому проекту WPF, я вижу ссылку на библиотеку, которая появляется в файле .csproj
, например:
<Reference Include="MyLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d64412599724c860, processorArchitecture=x86">
<HintPath>..\packages\MyLib.0.0.1\lib\net45\MyLib.dll</HintPath>
<Private>True</Private>
</Reference>
Хотя я ничего не вижу о файле .targets
. Это еще способ сделать это с помощью NuGet 3? Я сделал что-то не так? В настоящее время это не удается во время выполнения при запуске x64 из-за ссылки на x86 lib.
Ответы
Ответ 1
После того, как я слишком долго пробовал это, я понял это.
По-видимому, файлы build.prop и build.target должны иметь то же имя, что и пакет NuGet, иначе он не будет добавлен в файл csproj.
EDIT:
Я создал небольшой репозиторий github, в котором показано, как использовать это для вашего собственного проекта.
Он демонстрирует решение с тремя проектами: одно для iOS для Android и Net45, которое предназначено как для x86, так и для x64.
Обратите внимание, что в .props файле. Пути указывают на структуру папок распакованного NuGet. Таким образом, эти пути сопоставляются с тем, что вы положили в свой файл nuspec.
Итак, как и в репо, вы определяете nuspec как:
<?xml version="1.0"?>
<package>
<metadata>
<id>My.Awesome.Library</id>
<version>1.0.0</version>
<title>My Awesome Library</title>
<description>Herpa Derpa</description>
</metadata>
<files>
<file src="My.Awesome.Library.Droid\bin\Release\My.Awesome.Library.*"
target="lib\monodroid70" />
<file src="My.Awesome.Library.iOS\bin\Release\My.Awesome.Library.*"
target="lib\xamarin.ios10" />
<file src="My.Awesome.Library.Net45\bin\x64\Release\My.Awesome.Library.*"
target="build\x64" />
<file src="My.Awesome.Library.Net45\bin\x86\Release\My.Awesome.Library.*"
target="build\x86" />
<file src="My.Awesome.Library.Net45\bin\x86\Release\My.Awesome.Library.*"
target="lib\net45" />
<file src="My.Awesome.Library.props" target="build\net45" />
</files>
</package>
Я помещал свои файлы x86 в файлы build\x86
и x64 в build\x64
. В этом случае имя сборки папки может быть в любом случае для этих файлов. Здесь важно, что файл реквизита, ниже точек в этих папках для соответствующих платформ.
Я не уверен, имеет ли значение x86 lib в lib\net45
значение. Вы можете поэкспериментировать с этим. Файл реквизита должен выбрать правильный для вас.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Reference Include="My.Awesome.Library" Condition="'$(Platform)' == 'x86'">
<HintPath>$(MSBuildThisFileDirectory)..\x86\My.Awesome.Library.dll</HintPath>
</Reference>
<Reference Include="My.Awesome.Library" Condition="'$(Platform)' == 'x64'">
<HintPath>$(MSBuildThisFileDirectory)..\x64\My.Awesome.Library.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
В этом случае $(MSBuildThisFileDirectory)
будет папкой build\net45\
, убедитесь, что ваш путь правильно указывает на dll. Здесь важна папка build\net45
. Так NuGet автоматически импортирует цели и файлы реквизита.
Также обратите внимание, что имя My.Awesome.Library
довольно непротиворечивое. Важно то, что имя вашего файла реквизита соответствует идентификатору пакета NuGet. В противном случае кажется, что NuGet не будет импортировать его.
Ответ 2
Есть несколько вещей, с которыми я не согласен с этим решением. Файл nuspec не должен иметь никакой информации <Files>
если вы используете файловую структуру по умолчанию, добавляя файлы в папку nuget. Но если вы хотите запустить nuget файлы из своей папки решений, тогда это необходимо
лучшее содержание nuspec:
<?xml version="1.0"?>
<package>
<metadata>
<id>YourProjectName</id>
<version>1.0.0</version>
<authors>John Doe</authors>
<title>Your Project Name</title>
<description>Herpa Derpa</description>
</metadata>
</package>
Я также не согласен с тем, что он имеет.dll в папке build
, они должны быть в вашей папке lib
а в папке build
должны быть .targets
ваши .targets
и .props
файлы. Здесь упоминается документация для nuget.
Также папка lib
предназначена для.dll, которые находятся в ваших ссылках. Во- вторых,.dlls добавлены к вашей build
папки являются дополнительной библиотеки DLL, которые могут необходимы в некоторых случаях-подобно тому, как SQlite делает это для него - interop
библиотеки DLL. Поэтому в этом случае лучшее место для их хранения находится в папке lib.
Улучшенная структура папок:
- nuget
-- project.nuspec
-- build
---- YourProjectName.props
---- YourProjectName.targets
-- lib
--- <x64>
---- YourProjectName.dll
--- <x86>
---- YourProjectName.dll
.props:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Reference Include="YourProjectName" Condition="'$(Platform)' == 'x86'">
<HintPath>$(MSBuildThisFileDirectory)x86\YourProjectName.dll</HintPath>
</Reference>
<Reference Include="YourProjectName" Condition="'$(Platform)' == 'x64'">
<HintPath>$(MSBuildThisFileDirectory)x64\YourProjectName.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
.targets содержимое файла:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="PlatformCheck" BeforeTargets="InjectReference"
Condition="(('$(Platform)' != 'x86') AND ('$(Platform)' != 'x64'))">
<Error Text="$(MSBuildThisFileName) does not work correctly on '$(Platform)' platform. You need to specify platform (x86 or x64)." />
</Target>
<Target Name="InjectReference" BeforeTargets="ResolveAssemblyReferences">
<ItemGroup Condition="('$(Platform)' == 'x86' or '$(Platform)' == 'x64') and '$(TargetFrameworkVersion)'=='v4.6'">
<Reference Include=" YourProjectName ">
<HintPath>$(MSBuildThisFileDirectory)..\..\lib\net46\$(Platform)\ YourProjectName.dll</HintPath>
</Reference>
</ItemGroup>
</Target>
</Project>
Вы можете проверить, что выше работало, открыв ваш файл nuspec с помощью приложения Nuget Package Manager APP и проверив все файлы, которые вы добавили. Теперь, когда вы добавляете их в проект, он будет загружать dll в соответствии с выбранной архитектурой для проекта, на который он ссылался. Также обратите внимание, что в файле целей он вызывает ошибку, если выбран "Любой процессор" и информирует пользователя о том, что они должен выбирать между x86 и x64
РЕДАКТИРОВАТЬ:
Один момент, который не был хорошо прояснен, - это имя.target и.props должно быть таким же, как имя файла пакета nuget (что также означает версию). Как без этого, двойная ссылка появится при повторном открытии визуальной студии.
Ответ 3
Чтобы прояснить все решение, это способ, которым он работает идеально для меня
файл .nuspec
<?xml version="1.0"?>
<package>
<metadata>
<id>YourProjectName</id>
<version>1.0.0</version>
<authors>John Doe</authors>
<title>Your Project Name</title>
<description>Herpa Derpa</description>
</metadata>
</package>
Структура папок
-- project.nuspec
-- build
---- YourProjectName.props
---- YourProjectName.targets
-- tools
--- <x64>
---- YourProjectName.dll
--- <x86>
---- YourProjectName.dll
файл .props
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Reference Include="YourProjectName" Condition="'$(Platform)' == 'x86'">
<HintPath>$(MSBuildThisFileDirectory)..\tools\x86\YourProjectName.dll</HintPath>
</Reference>
<Reference Include="YourProjectName" Condition="'$(Platform)' == 'x64'">
<HintPath>$(MSBuildThisFileDirectory)..\tools\\x64\YourProjectName.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
файл .targets
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="PlatformCheck" BeforeTargets="BuildOnlySettings"
Condition="(('$(Platform)' != 'x86') AND ('$(Platform)' != 'x64'))">
<Error Text="$(MSBuildThisFileName) does not work correctly on '$(Platform)' platform. You need to specify platform (x86 or x64)." />
</Target>
</Project>
Это 100% рабочий раствор.