我有一个包含两个项目的Visual Studio 2017解决方案:
Foo.csproj
Foo.Core.csproj
这两个项目都针对多个框架:net452;netstandard1.2
Foo.csproj包含对Foo.Core.csproj的项目引用:
<ItemGroup>
<ProjectReference Include="..\Foo.Core\Foo.Core.csproj" />
</ItemGroup>
当我为Foo.csproj生成NuGet包时,我希望nupkg文件包含这两个程序集。
目前发生的是创建的NuGet包具有Foo.dll,然后是Foo.Core上的NuGet依赖(不存在)。
如何使用包含两个程序集的msbuild
生成单个NuGet包?
作为参考,这是我目前正在使用的命令(我的工作方式不正常):
msbuild /p:restore,pack Foo.csproj
答案 0 :(得分:18)
NuGet目前尚未直接支持此功能。您可以按this GitHub issue进行更新。
但是,有几种方法可以创建这样的NuGet包。
这是一个新开发的工具,可以通过安装NuGet.Build.Packaging
nuget包来从项目和工作中构建NuGet包。你可以在它的GitHub wiki页面上找到一些关于它的文档,但由于它是一个非常新的项目,它周围没有太多的文档或社区知识(!)(但开发它的团队非常有帮助,你可以提交GitHub如果你遇到问题就会出问题。
这种方法非常糟糕,因为它依赖于包目标使用的内部MSBuild项。它的工作原理是首先将<ProjectReference>
标记为不能从创建的nuget包中引用,如下所示:
<ProjectReference Include="..\libA\libA.csproj" PrivateAssets="All"/>
然后,您可以将其添加到项目中,以将生成的libA.dll
包含在nuget包中:
<PropertyGroup>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);IncludeP2PAssets</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>
<Target Name="IncludeP2PAssets">
<ItemGroup>
<BuildOutputInPackage Include="$(OutputPath)\testprivatelib.dll" />
</ItemGroup>
</Target>
请注意,这需要您将引用项目的所有<PackageReference>
项添加到生成包的项目中,因为它们会从生成的包中丢失,因为您已经有效地禁用了传递引用行为。
.nuspec
文件在撰写本文时,这可能是最“支持”的方式,但也是最复杂的方式。 NuGet允许您通过在项目中设置.nuspec
属性以及允许您通过替换的<NuspecFile>
属性来禁用自动生成生成的<NuspecProperties>
文件和自动文件收集用于解析.nuspec
文件的标记。
这可以通过修改项目文件来实现:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.4</TargetFramework>
<NuspecFile>$(MSBuildThisFileDirectory)$(MSBuildProjectName).nuspec</NuspecFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\LibB\LibB.csproj" />
</ItemGroup>
<Target Name="SetNuspecProperties" BeforeTargets="GenerateNuspec">
<PropertyGroup>
<NuspecProperties>$(NuspecProperties);id=$(AssemblyName)</NuspecProperties>
<NuspecProperties>$(NuspecProperties);config=$(Configuration)</NuspecProperties>
<NuspecProperties>$(NuspecProperties);version=$(PackageVersion)</NuspecProperties>
<NuspecProperties>$(NuspecProperties);description=$(Description)</NuspecProperties>
<NuspecProperties>$(NuspecProperties);authors=$(Authors)</NuspecProperties>
</PropertyGroup>
</Target>
</Project>
这将自动查找与项目名称相同的.nuspec
文件(somelib.csproj
=&gt; somelib.nuspec
),并将一些属性传递给它。属性在目标中创建,以便能够访问完全解析和默认的属性,如PackageVersion
。
.nuspec
文件可能如下所示:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
<id>$id$</id>
<version>$version$</version>
<authors>$authors$</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$description$</description>
<dependencies>
<group targetFramework=".NETStandard1.4">
<dependency id="NETStandard.Library" version="1.6.1" exclude="Build,Analyzers" />
</group>
</dependencies>
</metadata>
<files>
<file src="bin\$config$\netstandard1.4\*.dll" target="lib\netstandard1.4\" />
</files>
</package>
请注意,您必须将所有引用的NuGet包添加为<dependency>
文件中的.nuspec
元素,因为这些不再自动从项目文件中的<PackageReference>
项生成。有关详细信息,请参阅NuSpec Reference。
我最近为此目的创建了example project on GitHub demonstrating the use of a custom .nuspec
file。
答案 1 :(得分:1)
由于遇到了同样的问题,没有建议的解决方法起作用(https://github.com/NuGet/Home/issues/3891),我无法更改csproj以使用.netcore附带的新SDK。
幸运的是,nuget pack命令带有-IncludeReferencedProjects选项(参考:https://docs.microsoft.com/en-us/nuget/tools/cli-ref-pack),该选项正是这样做的: “表示所构建的软件包应包括作为依赖项或作为软件包一部分的被引用项目。如果被引用项目具有与该项目同名的相应.nuspec文件,则该被引用项目将被添加为依赖性。否则,引用的项目将作为软件包的一部分添加。“
无论* .nuspec文件如何(此处不需要),都将-IncludeReferencedProjects添加到pack命令,并且所引用的项目dll将与nuget dll一起包含。
nuget.exe pack yourProject.csproj -IncludeReferencedProjects
答案 2 :(得分:0)
Martin Ullrich提到的第二个选项是唯一可以与.NET Standard即用的选项,它允许“在生成时生成NuGet软件包”作为生成的组成部分。
但是,就像他提到的那样,它对dll的名称具有“硬编码”依赖关系,而您希望它的确切名称(在输出文件夹中)会在将来对您造成影响。我找到了一个更好的替代方法,它在.NET Standard中对我有用,而无需进行任何其他修改on this post。
出于完整性考虑,我在这里引用。 首先,您要编辑csproj并为要包含的引用定义PrivateAssets标签:
<ItemGroup>
<ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj">
<PrivateAssets>all</PrivateAssets>
</ProjectReference>
</ItemGroup>
然后将其添加到csproj:
<PropertyGroup>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>
<Target Name="CopyProjectReferencesToPackage" DependsOnTargets="ResolveReferences">
<ItemGroup>
<BuildOutputInPackage Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference')->WithMetadataValue('PrivateAssets', 'all'))" />
</ItemGroup>
</Target>
该帖子还显示了必要时如何将PDB包括在NuGet软件包选项中(在此省略)。
答案 3 :(得分:0)
我最近发现您不能为要在msbuild命令行中替换的Nuspec属性设置默认值,例如如果在“ <Version>2.0.0</Version>
”的.csproj文件中设置了元数据值,则运行:
msbuild myproject.csproj -t:pack -p:Configuration=Release -p:NuspecProperties=Configuration=Release;PackageVersion=1.2.3
您的.nupgk文件仍将具有2.0.0版本。令人烦恼的是,MS文档尚不清楚,并且没有错误显示。