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

时间:2018-12-13 13:25:17

标签: c# msbuild nuget

我正尝试迁移到使用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" />

我正在尝试执行类似的操作,在该项目中,应根据从依赖的TeamCity / CI构建中作为工件注入的本地.dll's进行构建:

<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”目标时注入依赖项感兴趣,因此在所有其他目标中都将其忽略/插入。

3 个答案:

答案 0 :(得分:0)

有趣的问题,当我环顾四周寻找答案时 我在Stackoverflow

中找到了另一个讨论

其中一条注释-表示pack命令仅适用于4.6及更高版本的框架项目-不适用于4.5。

.Net Standard 2.0必须基于Microsoft的this博客条目来匹配4.6.1

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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