Добавление библиотек 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% рабочий раствор.