【问题标题】:MSBuild multiple dll in a single NuGet packageMSBuild 在单个 NuGet 包中的多个 dll
【发布时间】:2017-12-12 02:41:31
【问题描述】:

我有一个包含两个项目的 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>

当我为 Foo.csproj 生成 NuGet 包时,我希望 nupkg 文件包含这两个程序集。

当前发生的情况是,创建的 NuGet 包具有 Foo.dll,然后是 Foo.Core 的 NuGet 依赖项(不存在)。

如何使用msbuild 生成包含两个程序集的单个 NuGet 包?

作为参考,这是我当前正在使用的命令(它不能按我的意愿工作):

msbuild /p:restore,pack Foo.csproj

【问题讨论】:

    标签: msbuild visual-studio-2017


    【解决方案1】:

    NuGet 目前不直接支持开箱即用。您可以关注this GitHub issue 获取更新。

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

    1. 使用“Nugetizer 3000”

    这是一个新开发的工具,用于从项目构建 NuGet 包,并通过安装 NuGet.Build.Packaging nuget 包来工作。你可以在它的 GitHub wiki 页面上找到一些关于它的文档,但由于它是一个非常新的项目,还没有太多关于它的文档或社区知识(!)(但是开发它的团队非常有帮助,你可以提交 GitHub如果你卡住了问题)。

    1. 在项目中添加自定义目标(2.0.0 tooling / VS 2017 15.3+):在 csproj 中创建一个项目,其中将包含引用项目的输出 DLL

    这种方法非常笨拙,因为它依赖于包目标使用的内部 MSBuild 项。它首先将 &lt;ProjectReference&gt; 标记为不被创建的 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>
    

    请注意,这需要您将所引用项目的所有 &lt;PackageReference&gt; 项添加到您从中生成包的项目中,因为您有效地禁用了传递引用行为,因此生成的包中会丢失它们。

    1. 创建自定义.nuspec 文件

    在撰写本文时,这可能是最“受支持”的方式,但也是最复杂的方式。 NuGet 允许您通过在项目中设置&lt;NuspecFile&gt; 属性以及允许您传递替换标记以解析@987654334 的&lt;NuspecProperties&gt; 属性来禁用生成的.nuspec 文件的自动生成和文件的自动收集@文件。

    这可以通过像这样修改项目文件来实现:

    <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>
    

    这将自动查找与项目同名的.nuspec 文件 (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 包作为 &lt;dependency&gt; 元素添加到 .nuspec 文件中,因为这些包不再从项目文件中的 &lt;PackageReference&gt; 项中自动生成。详情请参阅NuSpec Reference

    我最近为此创建了一个example project on GitHub demonstrating the use of a custom .nuspec file

    【讨论】:

      【解决方案2】:

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

      但是,就像他提到的那样,它对 dll 具有“硬编码”依赖项,该 dll 具有您期望的确切名称(在输出文件夹中),这可能会在将来咬住您。我找到了一个更好的替代方案,它在 .NET Standard 中对我有用,无需任何其他修改 on this post

      为了完整起见,我将在这里引用它。 首先,您编辑您的 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>
      

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

      【讨论】:

        【解决方案3】:

        一直在努力解决同样的问题,建议的解决方法均无效 (https://github.com/NuGet/Home/issues/3891),我无法更改 csproj 以使用 .netcore 附带的新 SDK。

        幸运的是,nuget pack 命令带有 -IncludeReferencedProjects 选项(参考:https://docs.microsoft.com/en-us/nuget/tools/cli-ref-pack),它可以做到这一点: “表示构建的包应该包含引用的项目作为依赖项或包的一部分。如果引用的项目具有与项目同名的对应 .nuspec 文件,则将该引用的项目添加为依赖。否则,引用的项目将作为包的一部分添加。"

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

        nuget.exe pack yourProject.csproj -IncludeReferencedProjects
        

        【讨论】:

        • 当我使用这个方法时,没有一个项目的nuget包引用被添加到创建的.nupkg文件中。有什么想法吗?
        • @Alireza -IncludeReferencedProjects 将导入项目引用 dll 而不是 nuget 包引用。
        【解决方案4】:

        我最近发现您不能在 msbuild 命令行中为要替换的 Nuspec 属性设置默认值,例如如果在“&lt;Version&gt;2.0.0&lt;/Version&gt;”的 .csproj 文件中设置了元数据值并且您运行:

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

        您的 .nupgk 文件仍然是 2.0.0 版本。令人讨厌的是,MS 文档对此并不清楚,也没有显示错误。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-07-26
          • 1970-01-01
          • 2023-03-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多