如何配置MSBuild中SDK包传递依赖:自身不导入资产,消费者可获取
我刚好踩过这个NuGet依赖配置的坑,核心是要分清当前项目构建时的资产使用规则和传递给下游消费者的依赖范围——NuGet默认会把你在PackageReference里的ExcludeAssets设置同步到生成的nuspec中,导致下游项目也继承了排除规则,所以我们需要绕开这个自动同步逻辑。
下面给你两种匹配不同场景的解决方案:
方案1:MySdk构建时完全不需要Trans的任何资产,仅声明传递依赖
如果你的MySdk只是需要把Trans作为传递依赖暴露给消费者,自身构建时完全不需要用到Trans的任何资产(包括build目标、运行时文件等),可以直接用这个配置:
<PackageReference Include="Trans" Version="1.0.*" ExcludeAssets="All" PrivateAssets="None" />
配置逻辑说明:
ExcludeAssets="All":告诉NuGet,当前MySdk项目构建时不使用Trans的任何资产,完全跳过导入。PrivateAssets="None":明确标记这个依赖是公开的,会完整传递给下游的Consumer项目,不会被隐藏。
生成的MySdk.nupkg的nuspec中,Trans的依赖会是无限制的完整声明:
<dependency id="Trans" version="1.0.0" />
这样Consumer.csproj引用MySdk时,会自动获取Trans的所有资产,包括你之前缺失的自定义构建目标。
方案2:MySdk需要使用Trans的部分资产,但排除build目标,同时让消费者获取全部资产
如果你的MySdk构建时需要用到Trans的部分资产(比如运行时文件、编译依赖),但不想导入它的build目标,同时又要让消费者能拿到Trans的所有资产,就需要自定义nuspec来脱离NuGet的自动生成规则:
- 创建自定义nuspec文件(比如
MySdk.nuspec):
<?xml version="1.0" encoding="utf-8"?> <package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd"> <metadata> <id>MySdk</id> <version>$version$</version> <!-- 用MSBuild变量传递版本号 --> <authors>Your Name</authors> <description>My SDK with controlled transitive dependency</description> <dependencies> <!-- 手动声明完整的Trans依赖,不添加任何include/exclude限制 --> <group targetFramework="net6.0"> <!-- 替换成你的项目目标框架 --> <dependency id="Trans" version="1.0.*" /> </group> </dependencies> </metadata> </package>
- 修改MySdk.csproj的配置:
<PropertyGroup> <GeneratePackageOnBuild>true</GeneratePackageOnBuild> <!-- 指定使用自定义nuspec文件 --> <NuspecFile>MySdk.nuspec</NuspecFile> <!-- 把项目版本号传递给nuspec的变量 --> <NuspecProperties>Version=$(Version)</NuspecProperties> </PropertyGroup> <ItemGroup> <!-- 仅在当前MySdk构建时排除Trans的build资产 --> <PackageReference Include="Trans" Version="1.0.*" ExcludeAssets="build" PrivateAssets="None" /> </ItemGroup>
配置逻辑说明:
ExcludeAssets="build":让MySdk构建时跳过Trans的build目标导入,满足当前项目的构建需求。- 自定义nuspec里的依赖声明没有添加任何限制,所以生成的MySdk.nupkg会告诉消费者:需要完整引用Trans的所有资产,不受当前项目排除规则的影响。
为什么你之前的配置不符合需求
你之前用ExcludeAssets="build"时,NuGet会自动把这个排除规则同步到生成的nuspec的include属性中(仅包含Runtime、Compile等类型,排除build),导致Consumer引用MySdk时,也会继承这个排除规则,无法获取Trans的build资产。上面的两种方案要么通过ExcludeAssets="All"避免生成限制规则,要么通过自定义nuspec手动声明完整依赖,完美绕开了这个问题。
内容的提问来源于stack exchange,提问作者Jeff

