首页 > 解决方案 > 如何在生成的 MSBuild NuGet 包中注入自定义依赖项 .nuspec

问题描述

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

我能找到的这个用例最接近的记录示例是从还原图 中替换一个库,它建议您可以替换外部 NuGet 引用:

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

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

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

我正在尝试做类似的事情,项目应该针对本地构建,.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 中注入自定义依赖项?

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

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

标签: c#msbuildnuget

解决方案


到目前为止,您可能已经找到了另一个解决方案,但我通过向 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 项目使用,以防有人知道更简单的方法)。


推荐阅读