【问题标题】:How to inject a custom dependency in an MSBuild NuGet pack generated .nuspec如何在生成的 MSBuild NuGet 包中注入自定义依赖项 .nuspec
【发布时间】:2018-12-13 13:25:17
【问题描述】:

我正在尝试迁移到使用 MSBuild Pack 支持使用 .csproj 生成项目 NuGet 包,在开发过程中本地 .dll 用于构建项目,但它们需要被替换/使用 MSBuild “打包”项目时,交换为在生成的 .nuspec 中引用外部 NuGet 包。

我能找到的与此用例最接近的记录示例是 Replacing one library from a restore graph ,它建议您可以替换外部 NuGet 引用:

<PackageReference Include="Newtonsoft.Json" Version="9.0.1">
  <ExcludeAssets>All</ExcludeAssets>
</PackageReference>

这会覆盖包以引用本地 .dll:

<Reference Include="Newtonsoft.Json.dll" />

我正在尝试做一些类似的事情,项目应该针对本地 .dll's 构建,这些本地 .dll's 作为从依赖 TeamCity/CI 构建中注入的工件:

<Reference Include="..\..\lib\net45\ServiceStack.Interfaces.dll" />
<Reference Include="..\..\lib\net45\ServiceStack.Text.dll" />
<Reference Include="..\..\lib\net45\ServiceStack.Common.dll" />

但是当按照文档使用ExcludeAssets=All 时:

<PackageReference Include="ServiceStack.Common" Version="5.0.0">
  <ExcludeAssets>All</ExcludeAssets>
</PackageReference>

PackageReference 不会在生成的依赖列表中导出,例如:

<group targetFramework=".NETFramework4.5" />

我最接近获得首选行为的是使用ExcludeAssets="compile",因此我的本地项目不会针对它进行构建,除非此行为也会在 .nuspec 中导出:

<group targetFramework=".NETFramework4.5">
  <dependency id="ServiceStack.Common" version="5.4.0" exclude="Compile,Build,Analyzers" />
</group>

我只想避免在本地构建它,而是将它作为正常依赖项导出。这种方法的另一个问题是我需要它来引用一个尚未发布到 NuGet 的包(因为所有包都以锁步方式发布),例如:

<!-- v5.5.0 is the new version to publish -->
<PackageReference Include="ServiceStack.Common" Version="5.5.0" ExcludeAssets="compile"/>

构建失败,找不到未发布的包:

[NU1102] Unable to find package ServiceStack.Common with version (>= 5.5.0)

实际上,我需要以某种方式在生成的 .nuspec 中“注入”我需要的确切依赖项和版本,以便将其包含在生成的 .nuspec 依赖项列表中,例如:

<group targetFramework="net45">
  <dependency id="ServiceStack.Common" version="5.5.0" />
</group>
<group targetFramework=".netstandard2.0">
  <dependency id="ServiceStack.Common" version="5.5.0" />
</group>

我们如何在 MSBuild 生成的 .nuspec 中注入自定义依赖项?

有什么方法可以像上面一样手动声明&lt;dependency/&gt;,以便仅在 MSBuild/NuGet 打包项目时使用?否则有没有办法对生成的 .nuspec 应用一些 XML 转换,以便我可以在打包/压缩之前在 .nuspec 中操作 XML?

基本上,我只对在“pack”目标运行时注入依赖项感兴趣,因此它在所有其他目标中都被忽略/惰性。

【问题讨论】:

    标签: c# msbuild nuget


    【解决方案1】:

    您现在可能已经找到了另一种解决方案,但我通过向 csproj 添加一些自定义目标“成功”了这一点。这个解决方案确实让我觉得也许我不应该这样做。

    步骤是

    • 在包生成目标之前注入一个步骤,禁用 nupkg 生成
    • 在修改生成的nuspec文件的包生成目标后注入一步,再次调用包生成目标。

    我在下面修改了我的修复程序,以便注入帖子中提到的依赖项。我在这里禁用了验证(NoPackageAnalysis=true)。您可以将其放在 .target 文件中并从 csproj 中导入。

    <Project>
    
      <!-- Disable nupkg generation before running pack -->
      <Target Name="__DisablePacking" BeforeTargets="GenerateNuspec" Condition="$(NuspecFile) == ''">
        <PropertyGroup>
          <ContinuePackingAfterGeneratingNuspec>false</ContinuePackingAfterGeneratingNuspec>
        </PropertyGroup>
      </Target>
    
      <!-- Modify the generated nuspec file and rerun the pack target -->
      <Target Name="__EnablePackingAndInjectDependencies" AfterTargets="Pack" Condition="$(NuspecFile) == ''">
        <!-- Get the nuspec file name -->
        <PropertyGroup>
          <_NugetPackOutputAsProperty>@(NuGetPackOutput)</_NugetPackOutputAsProperty>
        </PropertyGroup>
        <ItemGroup>
          <_NugetPackOutputAsItem Remove="@(_NugetPackOutputAsItem)"/>
          <_NugetPackOutputAsItem Include="$(_NugetPackOutputAsProperty.Split(';'))" />
        </ItemGroup>
        <PropertyGroup>
          <__NuspecFileName>%(_NugetPackOutputAsItem.Identity)</__NuspecFileName>
        </PropertyGroup>
    
        <!-- Create an updated dependencies, with the net46 dependencies copied to a native group -->
        <PropertyGroup>
          <__NuSpecUpdatedDependencies>
            <group targetFramework="net45">
              <dependency id="ServiceStack.Common" version="5.5.0" />
            </group>
            <group targetFramework=".netstandard2.0">
              <dependency id="ServiceStack.Common" version="5.5.0" />
            </group>
          </__NuSpecUpdatedDependencies>
        </PropertyGroup>
    
        <!-- Poke them back in -->
        <XmlPoke XmlInputPath="$(__NuspecFileName)"
                 Value="$(__NuSpecUpdatedDependencies)"
                 Query="/n:package/n:metadata/n:dependencies"
                 Namespaces="&lt;Namespace Prefix='n' Uri='http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd' /&gt;">
        </XmlPoke>
    
        <!-- call the pack operation again -->
        <PropertyGroup>
          <ContinuePackingAfterGeneratingNuspec>true</ContinuePackingAfterGeneratingNuspec>
        </PropertyGroup>
    
        <Msbuild
          Projects="$(MSBuildProjectFullPath)"
          Targets="Pack"
          Properties="NuspecFile=$(__NuspecFileName);NoPackageAnalysis=true">
        </Msbuild>
      </Target>
    </Project>
    
    

    (我希望注入一个 native0.0 框架依赖项,以便我的包可以被 c++/cli 项目使用,以防有人知道更简单的方法)。

    【讨论】:

      【解决方案2】:

      有趣的问题,当我四处寻找答案时 我在Stackoverflow找到了另一个讨论

      其中一个 cmets - 有迹象表明 pack 命令仅适用于 4.6 及更高版本的框架项目 - 而不是 4.5。

      .Net Standard 2.0 必须根据来自 Microsoft 的 this 博客条目匹配 4.6.1

      【讨论】:

      • 我正在使用最新的 VS v15.8.4 中的 MSBuild 来打包一个多目标项目,我不想在 .NET v4.5 中运行 .NET Standard .dll,它们是单独的构建。其他一切正常,更改为&lt;TargetFrameworks&gt;net461;netstandard2.0&lt;/TargetFrameworks&gt; 无济于事,我只是不知道如何将惰性自定义依赖项注入生成的 .nuspec。
      • 我参考的评论部分说MSBUILD包在低于4.6的框架下不起作用
      • 在我必须构建的 Nuget 包中 - 注入自定义依赖项 - 我不得不使用
        我不相信它不再适用于 v4.5 是准确的,我正在使用它来构建多目标 .NET v4.5 / .NET Standard 2.0 包很好,有仅引用 NuGet 包的项目没有问题。是的,有添加自定义依赖项的钩子,但无论如何我都看不到注入自定义 NuGet 依赖项列表(即除了它们推断的依赖项之外)。
      • .Net Standard 2.0 是框架 4.6.1 - 在四处寻找时,我发现了一些关于包锁的东西 - 这可能对你有帮助,也可能对你没有帮助 - 但页面顶部表明某些部分可能仅适用于 Win10 的 Windows 目标 - 不确定它是否适用于此处 docs.microsoft.com/en-us/nuget/consume-packages/…
      【解决方案3】:
      <?xml version="1.0"?>
      <package >
      <metadata>
      <id>FIK.DAL</id>
      <version>$version$</version>
      <title>FIK.DAL .NET</title>
      <authors>$author$</authors>
      <owners>Imamul Karim</owners>
      <license type="expression">MIT</license>
      <projectUrl>https://github.com/imamulkarim/FIK.DAL</projectUrl>
      
      <requireLicenseAcceptance>false</requireLicenseAcceptance>
      <description>A Simple SQL Query Generator Using ADO.NET Provider with SqlClient</description>
      <releaseNotes>SQLite Library Bug</releaseNotes>
      <copyright>$copyright$</copyright>
      <tags>ADO.NET SQL QUERY Generator</tags>
      </metadata>
      <files>
      <file src="bin\Debug\System.Data.SQLite.DLL" target="lib\net40"></file>
      </files>
      </package>
      

      https://docs.microsoft.com/en-us/nuget/reference/nuspec

      【讨论】:

      • 这个答案真的和问题无关。
      • 我添加了另一个库 SQLite.DLL 作为依赖项。
      • 我看不出这是如何导致依赖项在还原后引用外部 NuGet 包的。它只是将一个文件添加到包中。
      • 请在这里查看我已经发布了一个库。 nuget.org/packages/FIK.DAL.SQLite 显示 .NETStandard 2.0 作为参考。
      猜你喜欢
      相关资源
      最近更新 更多
      热门标签