MSBuild在单个NuGet包中创建多个dll

MSBuild在单个NuGet包中创建多个dll,msbuild,visual-studio-2017,Msbuild,Visual Studio 2017,我有一个Visual Studio 2017解决方案,其中包含两个项目: Foo.csproj Foo.Core.csproj 这两个项目都针对多个框架:net452;netstandard1.2 Foo.csproj包括对Foo.Core.csproj的项目参考: <ItemGroup> <ProjectReference Include="..\Foo.Core\Foo.Core.csproj" /> </ItemGroup> NuGet开箱即

我有一个Visual Studio 2017解决方案,其中包含两个项目:

Foo.csproj
Foo.Core.csproj
这两个项目都针对多个框架:
net452;netstandard1.2

Foo.csproj包括对Foo.Core.csproj的项目参考:

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

NuGet开箱即用目前不直接支持这一点。您可以跟踪更新

但是,有几种方法可以创建这样的NuGet包

  • 使用“Nugetizer 3000”
  • 这是一个新开发的工具,通过安装
    numget.build.Packaging
    numget包,从项目和工程中构建numget包。你可以在它的GitHub wiki页面上找到一些文档,但由于它是一个非常新的项目,所以它周围没有太多文档或社区知识(!)(但是开发它的团队非常有用,如果你遇到问题,你可以将GitHub问题归档)

  • 在项目中添加自定义目标(2.0.0工具/VS 2017 15.3+):在csproj中创建一个项目,该项目将包括引用项目的输出DLL
  • 这种方法非常粗糙,因为它依赖于包目标使用的内部MSBuild项。它首先将
    标记为不从创建的nuget包中引用,如下所示:

    <ProjectReference Include="..\libA\libA.csproj" PrivateAssets="All"/>
    
    <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>
    
    <?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>
    
    请注意,这要求您将引用项目的所有
    项添加到生成包的项目中,因为它们将从生成的包中丢失,因为您有效地禁用了可传递引用行为

  • 创建自定义
    .nuspec
    文件
  • 在撰写本文时,这可能是最“受支持”的方式,但也是最复杂的方式。NuGet允许您通过在项目中设置
    属性,以及允许您传递替换令牌以解析
    .nuspec
    文件的
    属性,禁用生成的
    .nuspec
    文件的自动生成和文件的自动收集

    这通过如下方式修改项目文件来实现:

    <ProjectReference Include="..\libA\libA.csproj" PrivateAssets="All"/>
    
    <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>
    
    <?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包作为
    .nuspec
    文件中的
    元素添加,因为它们不再是从项目文件中的
    项自动生成的。有关更多详细信息,请参阅


    我最近正是为了这个目的创建了一个新的SDK。

    一直在努力解决同一个问题,建议的解决方法都不起作用(),我无法更改csproj以使用.netcore附带的新SDK

    幸运的是,nuget pack命令附带了-IncludeReferencedProjects选项(ref:),该选项正好可以: 指示生成的包应包含作为依赖项或包的一部分的引用项目。如果引用的项目具有与该项目同名的相应.nuspec文件,则该引用的项目将作为依赖项添加。否则,引用的项目将作为包的一部分添加

    不管*.nuspec文件是什么(此处不需要),将-IncludeReferencedProjects添加到pack命令中,引用的项目dll将与nuget dll一起包含

    nuget.exe pack yourProject.csproj -IncludeReferencedProjects
    

    Martin Ullrich提到的第二个选项是唯一一个与.NET标准一起开箱即用的选项,它允许“在构建时生成NuGet包”作为构建的一个组成部分

    然而,就像他提到的,它对dll有一个“硬编码”依赖关系,dll的确切名称是您希望存在的(在输出文件夹上),这可能会在将来咬到您。我找到了一个更好的替代方案,它在.NET标准中对我有效,无需任何其他修改

    为了完整起见,我将在这里引用它。 首先,编辑您的csproj,并为要包含的引用定义PrivateAssets标记:

    <ItemGroup>
      <ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj">
        <PrivateAssets>all</PrivateAssets>
      </ProjectReference>
    </ItemGroup>
    
    
    全部的
    
    然后将此添加到csproj中:

    <PropertyGroup>
    <TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
    </PropertyGroup>
    
    <Target Name="CopyProjectReferencesToPackage" DependsOnTargets="ResolveReferences">
        <ItemGroup>
            <BuildOutputInPackage Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference')->WithMetadataValue('PrivateAssets', 'all'))" />
        </ItemGroup>
    </Target>
    
    
    $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage
    

    该帖子还展示了如何在必要时将PDB包括在NuGet package选项中(我在这里省略了该选项)。

    我最近发现,如果在“
    2.0.0
    ”的.csproj文件中设置了元数据值,则无法在msbuild命令行中设置要替换的Nuspec属性的默认值然后你跑:

    msbuild myproject.csproj -t:pack -p:Configuration=Release -p:NuspecProperties=Configuration=Release;PackageVersion=1.2.3
    

    您的.nupgk文件仍将具有2.0.0版。令人烦恼的是,MS文档对此并不清楚,也没有显示任何错误。

    当我使用此方法时,没有任何项目的nuget包引用被添加到创建的
    .nupkg
    文件中。有什么想法吗?@Alireza-IncludeReferencedProjects将导入项目引用DLL,而不是nuget包引用。