从NuGet包中排除目标框架。

5

我该如何在 nuspec(NuGet 包)生成中排除特定的目标框架?

这是我的 csproj 文件:

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFrameworks>netstandard2.0;net5.0;net5.0-windows</TargetFrameworks>
        <IsPackable>true</IsPackable>
    </PropertyGroup>

    <PropertyGroup Condition="'$(TargetFramework)' == 'net5.0-windows'">
        <IsPackable>false</IsPackable>
    </PropertyGroup>
</Project>

dotnet pack 命令生成一个包含所有目标框架的 NuGet 包,而不仅仅是 netstandard2.0net5.0

生成的 nuspec 文件:

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
  <metadata>
    <id>ExampleLibrary</id>
    <version>1.0.0</version>
    <authors>ExampleLibrary</authors>
    <description>Package Description</description>
    <dependencies>
      <group targetFramework="net5.0" />
      <group targetFramework="net5.0-windows7.0" />
      <group targetFramework=".NETStandard2.0" />
    </dependencies>
  </metadata>
</package>

1
我不知道这样的事情是否有意义。如果你的库使用了net5.0-windows中的某些特定内容,那么它将无法与netstandard2.0net5.0兼容。你真的需要在库中使用net5.0-windows吗? - Lukasz Szczygielek
该库针对 net5.0-windows,因为它具有用于 Windows 窗体的附加逻辑,但是可以通过项目引用来使用,无需 NuGet 包。 - ptp
2个回答

8
<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFrameworks>netstandard2.0;net5.0;net5.0-windows7.0</TargetFrameworks>
        <IsPackable>true</IsPackable>
        <GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);_ExcludeTargetFramework;_ExcludeTargetFrameworkDependency</GenerateNuspecDependsOn>
    </PropertyGroup>

    <Target Name="_ExcludeTargetFramework" AfterTargets="_GetTargetFrameworksOutput" BeforeTargets="_WalkEachTargetPerFramework">
        <ItemGroup>
            <_TargetFrameworks Remove="net5.0-windows7.0" />
        </ItemGroup>
    </Target>

    <Target Name="_ExcludeTargetFrameworkDependency" AfterTargets="_WalkEachTargetPerFramework" BeforeTargets="GenerateNuspec">
        <ItemGroup>
            <_FrameworksWithSuppressedDependencies Include="net5.0-windows7.0" />
        </ItemGroup>
    </Target>
</Project>


<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
  <metadata>
    <id>ExampleLibrary</id>
    <version>1.0.0</version>
    <authors>ExampleLibrary</authors>
    <description>Package Description</description>
    <dependencies>
      <group targetFramework="net5.0" />
      <group targetFramework=".NETStandard2.0" />
    </dependencies>
  </metadata>
</package>

0

删除所有的依赖项(包括 TargetFramework)

如果您想要删除所有依赖项(即所有目标框架),上述解决方案将不起作用。构建将失败,并出现以下错误:

error MSB4044: The "ResolvePackageAssets" task was not given a value for the required parameter "TargetFramework".

简单方法

如果您只想删除所有依赖项,可以使用SuppressDependenciesWhenPacking属性。

<PropertyGroup>
    <SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>
</PropertyGroup>

完全控制 Nuspec

另外,如果您想在第一轮生成后完全控制 Nuspec 的内容,可以使用 this 的变体:

<?xml version="1.0" encoding="utf-8"?>
<Project>

  <UsingTask
    TaskName="RemoveDependencies"
    TaskFactory="CodeTaskFactory"
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
    <ParameterGroup>
      <Nuspec ParameterType="System.String" Required="true"/>
    </ParameterGroup>
    <Task>
      <Reference Include="System.Xml"/>
      <Reference Include="System.Xml.Linq"/>
      <Using Namespace="System"/>
      <Using Namespace="System.IO"/>
      <Using Namespace="System.Xml.Linq"/>
      <Code Type="Fragment" Language="cs">
        <!-- Modify XML of the NuSpec -->
        <![CDATA[
            XElement doc = XElement.Load(Nuspec);
            var dependenciesElement = doc.Descendants(XName.Get("dependencies", "http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd")).FirstOrDefault();
            if (dependenciesElement != null)
            {
                dependenciesElement.Remove();
            }

            using (var textWriter = File.CreateText(Nuspec))
            {
                doc.Save(textWriter);
            }]]>
      </Code>
    </Task>
  </UsingTask>

  <!-- From https://dev59.com/NrDla4cB1Zd3GeqP8nge -->

  <!-- Disable nupkg generation before running pack -->
  <Target Name="__DisablePacking" BeforeTargets="GenerateNuspec" Condition="$(NuspecFile) == '' And $(IsPackable) != 'false'">
    <PropertyGroup>
      <ContinuePackingAfterGeneratingNuspec>false</ContinuePackingAfterGeneratingNuspec>
    </PropertyGroup>
  </Target>

  <!-- Remove .Net Standard 2.0 dependency as it's a native package -->
  <!-- Modify the generated nuspec file and rerun the pack target -->
  <Target Name="__ExcludeTargetFrameworkDependency" AfterTargets="Pack" Condition="$(NuspecFile) == '' And $(IsPackable) != 'false'">
    <!-- 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>

    <Message Importance="High" Text="Remove Dependencies from $(__NuspecFileName)" />
    <RemoveDependencies Nuspec="$(__NuspecFileName)" />

    <!-- Invoke the Pack target again with packing enabled -->
    <PropertyGroup>
      <ContinuePackingAfterGeneratingNuspec>true</ContinuePackingAfterGeneratingNuspec>
    </PropertyGroup>

    <MsBuild
            Projects="$(MSBuildProjectFullPath)"
            Targets="Pack"
            Properties="NuspecFile=$(__NuspecFileName);NoPackageAnalysis=true">
    </MsBuild>
  </Target>

</Project>

注:

  • GenerateNuspec目标同时执行生成和打包。要在生成nuspec后禁用打包,可以使用ContinuePackingAfterGeneratingNuspec属性。
  • Pack目标被调用两次(一次由用户,第二次由系统在第一次打包后)。
  • __ExcludeTargetFrameworkDependency依赖于Nuspec文件值为空以在第一次打包时执行并在第二次运行时不执行。如果为第一次运行提供了Nuspec文件(使用NuspecFile属性),它显然不起作用。
  • 请注意使用And $(IsPackable) != 'false'来避免在测试项目上调用该目标。
  • 所有NuGet目标,如GenerateNuspec,都位于C:\Program Files\dotnet\sdk\6.0.308\Sdks\NuGet.Build.Tasks.Pack\build\NuGet.Build.Tasks.Pack.targets中。
  • 所有.NET 6的NuGet任务,如PackTask,都位于C:\Program Files\dotnet\sdk\6.0.308\Sdks\NuGet.Build.Tasks.Pack\Desktop\NuGet.Build.Tasks.Pack.dll中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接