NuGet 默認只支持一個菜一個菜打包,不支持套餐打包。當對一個 csproj 項目進行 nuget 打包時(比如使用 dotnet pack 命令),只會將當前項目 build 出來的 dll 程序集文件打包進 nupkg 文件,而所引用項目的 dll 文件不會被打包進去。要解決這個問題需要在 csproj 文件中添加專門的 msbuild 配置,這篇隨筆分享一下剛學到的新姿勢。
之前我們是通過 _PackageFiles 配置實現的,但要一個一個手寫要打包進去的程序集文件名稱,既麻煩又容易出錯,有點追求的程序員都不喜歡這樣的解決方法。
<ItemGroup>
<_PackageFiles Include="$(OutputPath)\Cnblogs.UCenter.DTO.dll">
<BuildAction>None</BuildAction>
<PackagePath>lib\$(TargetFramework)\</PackagePath>
</_PackageFiles>
<_PackageFiles Include="$(OutputPath)\Cnblogs.UCenter.ValueObjects.dll">
<BuildAction>None</BuildAction>
<PackagePath>lib\$(TargetFramework)\</PackagePath>
</_PackageFiles>
</ItemGroup>
昨天在 stackoverflow 上找到了更簡單優雅的基於 BuildOutputInPackage 配置的解決方法。
<PropertyGroup>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>
<Target Name="CopyProjectReferencesToPackage" DependsOnTargets="ResolveReferences">
<ItemGroup>
<BuildOutputInPackage Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference'))" />
</ItemGroup>
</Target>
除此之外,還需要對所引用的項目添加 <PrivateAssets>all</PrivateAssets>
設置。
<ItemGroup>
<ProjectReference Include="..\Cnblogs.UCenter.DTO\Cnblogs.UCenter.DTO.csproj">
<PrivateAssets>all</PrivateAssets>
</ProjectReference>
<ProjectReference Include="..\Cnblogs.UCenter.ValueObjects\Cnblogs.UCenter.ValueObjects.csproj">
<PrivateAssets>all</PrivateAssets>
</ProjectReference>
</ItemGroup>
不然安裝這個包時 nuget 就會通過 nuget 源找所引用項目的 nuget 包。
NU1102: Unable to find package Cnblogs.UCenter.DTO with version (>= 2.4.2)
加了 PrivateAssets 設置,就會在當前 NuGet 包的 lib 文件夾找對應的程序集文件。