Как я могу создать управляемый пакет NuGet для поддержки проектов С++/CLI?

Я сделал пакет NuGet, который хорошо работает, когда я использую его из проекта С#. Он содержит DLL в каталоге lib/net40, а DLL добавляется в качестве ссылки.

Теперь, когда NuGet поддерживает С++, как я могу изменить свой пакет, чтобы DLL можно было добавить в качестве управляемой ссылки в проекте С++/CLI? Я не могу найти учебники, объясняющие это. Если я попытаюсь просто добавить пакет как есть, я получаю следующую ошибку:

Вы пытаетесь установить этот пакет в проект, который нацелен на "Native, Version = v0.0", но пакет не содержит ссылок на сборки или файлов содержимого, совместимых с этой инфраструктурой.

Можно подумать, что решение состоит в том, чтобы поместить файлы в lib/native, но согласно http://docs.nuget.org/docs/reference/support-for-native-projects, это не поддерживается. Кроме того, просто размещение DLL непосредственно под lib не похоже на что-либо.

По-видимому, я должен сделать это с помощью файла .props или .targets в файле build/native, но что мне нужно поместить в эти файлы, чтобы сделать это?

Ответ 1

Как Патрик О'Хара написал, NuGet не будет вносить изменения в проект С++/CLI для вас. См. Ошибка GitHub NuGet/Home # 1121 - Невозможно установить управляемые пакеты в проект CLI. Однако, используя утилиту командной строки NuGet, NuGet.exe, вы можете загрузить и распаковать нужный пакет NuGet.

Для полного примера здесь были шаги, которые я предпринял для добавления ссылки на OptimizedPriorityQueue 1.0.0 в Visual Studio 2013 Проект С++/CLI:

  • Откройте консоль диспетчера пакетов, если он еще не открыт (ИНСТРУМЕНТЫ > Диспетчер пакетов NuGet > Консоль диспетчера пакетов).
  • В консоли диспетчера пакетов установите пакет NuGet.CommandLine:

    Install-Package NuGet.CommandLine
    

    (Примечание. На момент написания этой статьи последняя версия NuGet.CommandLine - 2.8.6. Возможно, она отличается от вас.)

  • В папке проекта теперь должен быть XML файл .nuget\packages.config со следующим содержимым:

    <?xml version="1.0" encoding="utf-8"?>
    <packages>
      <package id="NuGet.CommandLine" version="2.8.6" />
    </packages>
    
  • В текстовом редакторе, таком как Notepad ++, добавьте элемент <package> для нужного пакета. В этом случае я добавил:

    <package id="OptimizedPriorityQueue" version="1.0.0" />
    

    .. внутри элемента <packages>.

  • Откройте командную строку (я открыл VS2013 Developer Command Prompt, но регулярная командная строка должна работать.)

  • cd в папку проекта.
  • Выполните следующую команду, изменив номер версии NuGet.CommandLine, если она отличается:

    .\packages\NuGet.CommandLine.2.8.6\tools\NuGet.exe Install -NonInteractive -OutputDirectory packages .nuget\packages.config
    

    Для меня выход был:

    Installing 'OptimizedPriorityQueue 1.0.0.0'.
    Successfully installed 'OptimizedPriorityQueue 1.0.0.0'.
    All packages listed in packages.config are already installed.
    
  • Щелкните правой кнопкой мыши проект в Visual Studio и выберите Свойства. В разделе Общие свойствa > Ссылки нажмите кнопку Добавить новую ссылку и hellip;.
  • Выберите Обзор с левой стороны. Рядом с диалоговым окном "Добавить ссылку" ОК и "Отмена" есть кнопка Обзор & hellip;. Щелкните это, чтобы открыть диалог выбора файла.
  • Перейдите к DLL файлам, которые NuGet распакован в подкаталог packages вашей папки проекта, и нажмите кнопку Добавить. Нажмите ОК, чтобы закрыть диалоговое окно "Добавить ссылку".
  • Теперь вы можете использовать сборку в своем проекте С++/CLI:

    using namespace Priority_Queue;
    
    //...
    

Ответ 2

Как упоминалось в ответе на этот порт (Nuget не будет устанавливать Entity Framework в проект С++/CLI), NuGet не будет вносить изменения в С++/CLI для вас. Однако он загрузит и распакует зависимость для вас. Мы используем его из командной строки как часть наших зависимостей make. Командная строка будет выглядеть примерно так:

/.NuGet/NuGet.exe
      Install 
      -NonInteractive 
      -ConfigFile $ENV{SRC_ROOT}/.nuget/NuGet.config 
      -OutputDirectory $ENV{SRC_ROOT}/packages 
      $ENV{SRC_ROOT}/packages.config

Обратите внимание, что параметры командной строки отделяются друг от друга до строки, чтобы упростить чтение. Также мы решили проверить NuGet на наш исходный элемент управления в папке .NuGet. Цель заключалась в том, чтобы упростить настройку сборщика для различных сред (не все из которых используют Visual Studio). После запуска этой команды в первый раз вы должны вручную добавить зависимости в свой проект С++/CLI.
Надеюсь, что это поможет.

Ответ 3

Кажется, что на самом деле есть возможность включить "обычные" пакеты NuGet и автоматически ссылаться на проекты С++/CLI, используя следующие шаги (по крайней мере, с NuGet >= 2.5):

  • Добавьте (или измените) файл build\<ProjectName>.targets к вашему проекту, который будет упакован, и поместите в него следующий контент (обязательно замените <AssemblyName> на фактическое значение):

    <?xml version="1.0" encoding="utf-8" ?>
    <Project ToolsVersion="4.0"
             xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <!-- for C++/CLI projects only -->
      <ItemGroup Condition="'$(Language)' == 'C++'">
        <Reference Include="<AssemblyName>">
          <!--
            this .targets file is installed next to the assembly,
            so we do not have to figure out any versions or paths here ourselves
          -->
          <HintPath>
            $(MSBuildThisFileDirectory)..\lib\native\<AssemblyName>.dll
          </HintPath>
        </Reference>
      </ItemGroup>
    </Project>
    
  • В .nuspec упакованного проекта добавьте одну или несколько записей file, чтобы разместить сборку в каталоге lib\native\ на целевой машине:

    <package>
      <metadata>
        ...
      </metadata>
      <files>
        ...
        <!--
          add a copy of the assembly to lib\native to prevent NuGet
          from complaining about incompatible native projects
        -->
        <file src="bin\$configuration$\$id$.dll" target="lib\native\" />
        <file src="bin\$configuration$\$id$.xml" target="lib\native\" />
    
        <!-- don't forget about the .targets file containing the reference -->
        <file src="build\$id$.targets" target="build\" />
      </files>
      ...
    </package>
    

Даже если NuGet не добавляет ссылки на сборки проектов С++/CLI, он по-прежнему вставляет любые файлы .props и .targets, предоставляемые пакетом. И пользовательская цель с шага 1 добавит ссылку на нашу упакованную сборку.

Один недостаток этого решения, насколько я мог видеть, заключается в том, что ссылка, добавленная таким образом, не отображается в разделе Commpon Properties/Framework and References проекта С++/CLI. Могут также быть и другие, поэтому используйте их на свой страх и риск...

Ответ 4

Установщик пытается добавить ссылку на себя в проект запуска С#. Перед запуском проекта С# выполните проект запуска в решении. Создайте фиктивный проект С#, если у вас его нет

Ответ 5

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