如何在 MSBuild NuGet 包生成的 .nuspec 中注入自定义依赖项

2024-05-08

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

我能找到的最接近该用例的记录示例是从恢复图中替换一个库 https://learn.microsoft.com/en-us/nuget/reference/msbuild-targets#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作为依赖 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 之前操作 .nuspec 中的 XML?

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


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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 MSBuild NuGet 包生成的 .nuspec 中注入自定义依赖项 的相关文章

  • InvalidOperationException - 对象当前正在其他地方使用 - 红十字

    我有一个 C 桌面应用程序 其中我连续创建的一个线程从源 实际上是一台数码相机 获取图像并将其放在 GUI 中的面板 panel Image img 上 这必须是另一个线程 如它是控件的代码隐藏 该应用程序可以工作 但在某些机器上 我会在随
  • 使用 std::packaged_task/std::exception_ptr 时,线程清理程序报告数据争用

    我遇到了线程清理程序 TSan 的一些问题 抱怨某些生产代码中的数据争用 其中 std packaged task 通过将它们包装在 std function 中而移交给调度程序线程 对于这个问题 我简化了它在生产中的作用 同时触发 TSa
  • 注销租约抛出 InvalidOperationException

    我有一个使用插件的应用程序 我在另一个应用程序域中加载插件 我使用 RemoteHandle 类http www pocketsilicon com post Things That Make My Life Hell Part 1 App
  • 如何在 .NET Framework 2.0 中模拟“Func<(Of <(TResult>)>) 委托”?

    我尝试使用这个类代码项目文章 http www codeproject com KB threads AsyncVar aspx在 VB NET 和 NET Framework 2 0 中 除了这一行之外 所有内容似乎都可以编译Privat
  • 复制 std::function 的成本有多高?

    While std function是可移动的 但在某些情况下不可能或不方便 复制它会受到重大处罚吗 它是否可能取决于捕获变量的大小 如果它是使用 lambda 表达式创建的 它依赖于实现吗 std function通常被实现为值语义 小缓
  • 复制目录内容

    我想将目录 tmp1 的内容复制到另一个目录 tmp2 tmp1 可能包含文件和其他目录 我想使用C C 复制tmp1的内容 包括模式 如果 tmp1 包含目录树 我想递归复制它们 最简单的解决方案是什么 我找到了一个解决方案来打开目录并读
  • 使用 Newtonsoft 和 C# 反序列化嵌套 JSON

    我正在尝试解析来自 Rest API 的 Json 响应 我可以获得很好的响应并创建了一些类模型 我正在使用 Newtonsoft 的 Json Net 我的响应中不断收到空值 并且不确定我的模型设置是否正确或缺少某些内容 例如 我想要获取
  • 使用接口有什么好处?

    使用接口有什么用 我听说它用来代替多重继承 并且还可以用它来完成数据隐藏 还有其他优点吗 哪些地方使用了接口 程序员如何识别需要该接口 有什么区别explicit interface implementation and implicit
  • DbContext 和 ObjectContext 有什么区别

    From MSDN 表示工作单元和存储库模式的组合 使您能够查询数据库并将更改分组在一起 然后将这些更改作为一个单元写回存储 DbContext在概念上类似于ObjectContext 我虽然DbContext只处理与数据库的连接以及针对数
  • Qt - ubuntu中的串口名称

    我在 Ubuntu 上查找串行端口名称时遇到问题 如您所知 为了在 Windows 上读取串口 我们可以使用以下代码 serial gt setPortName com3 但是当我在 Ubuntu 上编译这段代码时 我无法使用这段代码 se
  • 如何在 Xaml 文本中添加电子邮件链接?

    我在 Windows Phone 8 应用程序中有一些大文本 我希望其中有电子邮件链接 例如 mailto 功能 这是代码的一部分
  • C# HashSet 只读解决方法

    这是示例代码 static class Store private static List
  • 外键与独立关系 - Entity Framework 5 有改进吗?

    我读过了several http www ladislavmrnka com 2011 05 foreign key vs independent associations in ef 4 文章和问题 https stackoverflow
  • AES 128 CBC 蒙特卡罗测试

    我正在 AES 128 CBC 上执行 MCT 如中所述http csrc nist gov groups STM cavp documents aes AESAVS pdf http csrc nist gov groups STM ca
  • “接口”类似于 boost::bind 的语义

    我希望能够将 Java 的接口语义与 C 结合起来 起初 我用过boost signal为给定事件回调显式注册的成员函数 这非常有效 但后来我发现一些函数回调池是相关的 因此将它们抽象出来并立即注册所有实例的相关回调是有意义的 但我了解到的
  • 如何设置 log4net 每天将我的文件记录到不同的文件夹中?

    我想将每天的所有日志保存在名为 YYYYMMdd 的文件夹中 log4net 应该根据系统日期时间处理创建新文件夹 我如何设置它 我想将一天中的所有日志保存到 n 个 1MB 的文件中 我不想重写旧文件 但想真正拥有一天中的所有日志 我该如
  • 动态添加 ASP.Net 控件

    我有一个存储过程 它根据数据库中存储的记录数返回多行 现在我想有一种方法来创建 div 带有包含该行值的控件的标记 如果从数据库返回 10 行 则 10 div 必须创建标签 我有下面的代码来从数据库中获取结果 但我不知道如何从这里继续 S
  • 调用堆栈中的“外部代码”是什么意思?

    我在 Visual Studio 中调用一个方法 并尝试通过检查调用堆栈来调试它 其中一些行标记为 外部代码 这到底是什么意思 方法来自 dll已被处决 外部代码 意味着该dll没有可用的调试信息 你能做的就是在Call Stack窗口中单
  • 使用 .NET Process.Start 运行时挂起进程 - 出了什么问题?

    我在 svn exe 周围编写了一个快速而肮脏的包装器来检索一些内容并对其执行某些操作 但对于某些输入 它偶尔会重复挂起并且无法完成 例如 一个调用是 svn list svn list http myserver 84 svn Docum
  • 从列表中选择项目以求和

    我有一个包含数值的项目列表 我需要使用这些项目求和 我需要你的帮助来构建这样的算法 下面是一个用 C 编写的示例 描述了我的问题 int sum 21 List

随机推荐