MSBuild несколько dll в одном пакете NuGet

у меня есть решение Visual Studio 2017, которое содержит два проекта:

Foo.csproj
Foo.Core.csproj

оба этих проекта нацелены на несколько фреймворков:net452;netstandard1.2

Фу.csproj включает ссылку на проект Foo.Ядро.csproj файл:

<ItemGroup>
    <ProjectReference Include="..Foo.CoreFoo.Core.csproj" />
</ItemGroup>

когда я создаю пакет NuGet для Foo.csproj, я хочу, чтобы файл nupkg включал обе эти сборки.

в настоящее время происходит то, что пакет NuGet, который создается, имеет Foo.dll, а затем NuGet зависимость от Фу.Ядро (которого не существует).

как я могу создать один пакет NuGet с помощью msbuild это будет включать обе сборки?

для справки это команда, которую я сейчас использую (которая не работает так, как я хочу):

msbuild /p:restore,pack Foo.csproj

2 ответов


в настоящее время это напрямую не поддерживается NuGet из коробки. Вы можете следовать этот вопрос GitHub для обновления.

однако существует несколько способов создания такого пакета NuGet.

  1. используйте "Nugetizer 3000"

это недавно разработанный инструмент для создания пакетов NuGet из проектов и работ путем установки NuGet.Build.Packaging пакет nuget. Вы можете найти некоторую документацию по нему на своей странице GitHub wiki, но так как это очень новый проект, вокруг него еще мало документации или знаний сообщества(!) (но команда, разрабатывающая его, очень полезна, вы можете подать вопросы GitHub, если вы застряли).

  1. добавление пользовательской цели в проект (2.0.0 tooling / VS 2017 15.3+): создайте элемент в csproj, который будет включать выходную DLL проекта

этот подход очень хакерский, поскольку он опирается на внутренний элемент MSBuild, который используют целевые объекты пакета. Он работает, сначала отметив <ProjectReference> чтобы не ссылаться на созданный пакет nuget следующим образом:

<ProjectReference Include="..\libA\libA.csproj" PrivateAssets="All"/>

затем вы можете добавить это в проект включить созданный libA.dll в пакете nuget:

<PropertyGroup>
  <TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);IncludeP2PAssets</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>
<Target Name="IncludeP2PAssets">
  <ItemGroup>
    <BuildOutputInPackage Include="$(OutputPath)\testprivatelib.dll" />
  </ItemGroup>
</Target>

обратите внимание, что для этого требуется добавить все <PackageReference> элементы ссылочного проекта на проект, из которого вы создаете пакет, поскольку они будут отсутствовать в сгенерированном пакете, поскольку вы фактически отключили транзитивную ссылку поведение.

  1. создать пользовательское

на момент написания, это, вероятно, самый "поддерживаемый" способ, но и самый сложный. NuGet позволяет отключить автоматическую генерацию результирующего .nuspec файл и автоматический сбор файлов, установив <NuspecFile> собственность в вашем проекте, вместе с <NuspecProperties> свойство, которое позволяет передавать токены замены для разбора .

это работает изменив файл проекта следующим образом:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard1.4</TargetFramework>
    <NuspecFile>$(MSBuildThisFileDirectory)$(MSBuildProjectName).nuspec</NuspecFile>
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="..\LibB\LibB.csproj" />
  </ItemGroup>

  <Target Name="SetNuspecProperties" BeforeTargets="GenerateNuspec">
    <PropertyGroup>
      <NuspecProperties>$(NuspecProperties);id=$(AssemblyName)</NuspecProperties>
      <NuspecProperties>$(NuspecProperties);config=$(Configuration)</NuspecProperties>
      <NuspecProperties>$(NuspecProperties);version=$(PackageVersion)</NuspecProperties>
      <NuspecProperties>$(NuspecProperties);description=$(Description)</NuspecProperties>
      <NuspecProperties>$(NuspecProperties);authors=$(Authors)</NuspecProperties>
    </PropertyGroup>
  </Target>
</Project>

это будет автоматически искать С тем же именем, что и проект (somelib.csproj =>somelib.nuspec) и передать ему некоторые свойства. Свойства создаются в целевом объекте, чтобы иметь доступ к полностью разрешенным и дефолтным свойствам, таким как PackageVersion.

на .nuspec файл может выглядеть так:

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
  <metadata>
    <id>$id$</id>
    <version>$version$</version>
    <authors>$authors$</authors>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>$description$</description>
    <dependencies>
      <group targetFramework=".NETStandard1.4">
        <dependency id="NETStandard.Library" version="1.6.1" exclude="Build,Analyzers" />
      </group>
    </dependencies>
  </metadata>
  <files>
    <file src="bin$config$\netstandard1.4\*.dll" target="lib\netstandard1.4\" />
  </files>
</package>

обратите внимание, что вы должны добавить все ссылочные пакеты NuGet как <dependency> элемент в .nuspec файл, так как они больше не генерируются автоматически из <PackageReference> элементы в файле проекта. Обратитесь к Ссылка NuSpec для получения более подробной информации.

недавно я создал пример проекта на GitHub, демонстрирующий использование пользовательского именно для этой цели.


боролся с той же проблемой, и ни один из предложенных обходных путей не работал (https://github.com/NuGet/Home/issues/3891) и я не мог изменить csproj, чтобы использовать новый SDK.netcore.

к счастью, команда NuGet pack поставляется с опцией-IncludeReferencedProjects (ref:https://docs.microsoft.com/en-us/nuget/tools/cli-ref-pack) который делает именно это: " указывает, что встроенный пакет должен включать ссылки проекты либо как зависимости, либо как часть пакета. Если ссылочный проект имеет соответствующий .файл nuspec, который имеет то же имя, что и проект, затем этот ссылочный проект добавляется как зависимость. В противном случае указанный проект добавляется как часть пакета."

независимо от *.файл nuspec (здесь не требуется), add-IncludeReferencedProjects к команде pack и ссылочные библиотеки DLL проекта будут включены вместе с nuget файл DLL.

nuget.exe pack yourProject.csproj -IncludeReferencedProjects