自动化创建NuGet包作为构建过程的一部分

63

我有一个自动化的构建过程,我希望扩展它,以便我可以构建通过NuGet分发的库。目前,运行nuget.exe创建包是手动操作。

最佳方法是如何设置VS 2010,使得我的NuGet包(*.nupkg)文件成为“发布”构建的最终结果?

请注意,我还有其他文件(内容和工具)用于某些包。而且,在大多数情况下,我将多个项目合并为单个NuGet包,以支持.NET 4、Silverlight和Phone 7。

(我应该澄清一下,现有的“自动化”过程是使用命令行构建解决方案的简单批处理文件运行程序。)

更新

我想刷新此讨论,因为问题尚未解决。虽然@pravin提供的链接很有帮助,但它并没有解决我有多个项目在单个包中以及其他内容(如PowerShell脚本、配置和源代码转换等)的问题。

我能想到的最好的例子是一个程序集,其中既有.NET 4版本又有Silverlight 5版本。它们以同一包的形式分发。我无法使用后期构建事件来创建该包,因为该包依赖于两个项目。


你尝试过吗:http://docs.nuget.org/docs/workflows/using-nuget-without-committing-packages - KMoraz
5
那与我的问题无关。该链接描述了使用NuGet包的工作流程,而我的问题与创建NuGet包有关。 - SonOfPirate
1
在发布版本中自动递增版本号也是不错的。 - Ufuk Hacıoğulları
9个回答

32

可以尝试创建一个自定义的MSBuild .proj文件。在自定义脚本中,您可以定义两个目标:第一个是对解决方案执行编译,第二个是在编译后执行并使用EXEC MSBuild任务调用nuget.exe命令行实用程序。接着,您需要更新批处理文件运行程序以执行msbuild可执行文件,并将您的自定义项目文件作为参数传入。如果您已经在批处理脚本中使用了MSBuild,则只需交换参数即可。您可以将自定义proj文件包含在解决方案项中。如果这样做,您可以在Visual Studio中添加外部工具引用来快速测试您的自定义脚本,以确保它正在构建和生成您所希望的软件包。

示例MSBuild

您可以将其用作起点:

<Project DefaultTargets="Compile" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
    <PropertyGroup>
      <SolutionFile></SolutionFile>
      <NugetExecutable>C:\PathToNuget\nuget.exe</NugetExecutable>
      <NuspecFile></NuspecFile>
    </PropertyGroup>

    <Target Name = "Compile">
        <MSBuild Projects="$(SolutionFile)" Properties="Configuration=Release" />
    </Target>

    <Target Name = "Package">
    <!-- You could use the MSBuild Copy task here to move the compiled code into
           a structure that fits your desired package format -->
      <Exec Command="&quot;$(NugetExecutable)&quot; pack $(NuspecFile)" />
    </Target>
</Project>

你可以像这样调用它:

"C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" Build.proj /p:SolutionFile=PathToSolution\App.sln;NuspecFile=foo.nuspec

你能提供一些参考资料,让我看看如何做到这点吗? - SonOfPirate
注意:上面的示例尚未经过全面测试,但这是您可能处理它的概念。MSDN上的MSBuild参考资料应该能够帮助您更充分地完善它。 - Josh Rack
5
我推荐使用 NuGetter。它使用和配置起来都更加简单 :) - H A

10

我已经在我的当前项目中实现了你想要实现的功能:

每个程序集都被构建成自己的合适的nuget包,并安装其依赖关系。

我通过在项目中创建一个专门用于制作nuget包的文件夹来解决此问题。在那里,我使用nuspec文件配置有关nupkg所需的信息。

在那里,我创建了所有Nuget包结构所需的文件夹和不变的文件。

我在项目中添加了后置构建步骤,将刚刚构建的文件复制到包文件夹中,并运行nuget.exe

所以它的流程是这样的:

  • 构建项目。
  • 将输出复制回项目的Package\Lib文件夹中。
  • 使用包文件夹中的nuspec文件运行nuget.exe
  • 将结果复制到与其它输出文件相邻的输出文件夹中。

nuget.exe 必须要么位于您系统上的固定文件夹中构建服务器上 (不太好的解决方案),或者包含在您的构建中(较好的解决方案)。

构建脚本:

Xcopy.exe /Y "$(TargetPath)" "$(ProjectDir)\Package\Lib" 
cd "$(ProjectDir)Package" 
"$(TargetDir)..\Buildscripts\Nuget.exe" pack MyPackage.nuspec xcopy /Y *.nupkg "$(TargetDir)" 

为了使用这个,你唯一需要注意的是决定在哪里检入nuget.exe。我在我的开发树的顶层创建了一个buildscripts文件夹。


1
如果你知道其他项目已经构建完毕,我相信你可以在后置构建步骤中复制它们的输出。 - Schwarzie2478
1
你的评论是关键 - “如果你知道它们已经被构建”。 - SonOfPirate
我认为构建启动有一定的顺序。否则,您可以配置始终作为最后一步构建的空项目。 - Schwarzie2478

7
我创建了一个 NuGet 项目类型 (.nuproj) 的 Visual Studio 扩展程序叫做 NuBuild,它可以实现你想要的功能。它允许你从 Visual Studio 和 MSBuild 中构建 NuGet 包。你可以从 gallery 安装它,或者从 github 获取源代码。

1
对于它与NuGetter相比的优点感到好奇 - RJB

7
如果你在TFS 2010环境中,NuGetter项目可以自动创建NuGet包,解决了这个问题。它会为整个构建创建一个包。实际上,它是一个TFS 2010构建工作流,通过调用带有一些参数的nuget.exe来完成工作。

虽然使用这种模式无法为每个项目生成一个NuGet包。有人在TFS 2010级别上做过吗? - Alex
NuGetter应该也能在TFS 2012上使用,但您需要将组件升级到TFS 2012。 - H A
NuGetter也被微软MVP Marcel de Vries在一个无关的视频中提及。对于它与NuBuild相比的优点很感兴趣。 - RJB

4

版本1.6增加了一个解决方案级选项,允许您将构建目标添加到每个项目中,因此您不必将软件包提交到源代码控制。虽然构建目标文件由所有项目使用,但仍作为每个单独项目的构建过程的一部分执行。这对于我需要生成包含多个项目的构建输出的单个软件包的情况没有帮助。 - SonOfPirate

1

一个简单的建议可能足够好用...只需将其作为Postbuild事件放入.csproj文件中:

  <PropertyGroup>
    <PostBuildEvent>$(SolutionDir)<YourPathToNugetHere>\NuGet.exe pack $(ProjectPath) -OutputDirectory ..\..\$(OutDir) -IncludeReferencedProjects -Symbols -Properties Configuration=$(Configuration)</PostBuildEvent>
  </PropertyGroup>

这将收集您的自定义 .nuspec 文件(文件名应与 .csproj 文件相同),并构建 .nupkg 包。

就是这样。

您甚至可以在Visual Studio项目设置中轻松完成此操作。


1

我认为这个插件是用于 Visual Studio 中的 IDE 构建,而不是 TFS 中的 MSBuild。我错了吗? - Prisoner ZERO
@PrisonerZERO - 它适用于IDE构建,但我还没有尝试过MSBuilds。 - habakuk

0

安装'NuGet.for.MSBuild' nuget包。不需要'.nuspec'文件,所需信息将从AssemblyInfo.cs中获取。

将构建设置为'Release'模式。构建完成后,nupkg文件将位于'bin/Release'文件夹中。

https://nuget4msbuild.codeplex.com/


0
据我所知,你不能这样做。
相反,应该做到规范化,并拥有一个适当的构建环境/流程,在提交/推送到主要仓库后触发构建脚本,执行以下操作:
  • 克隆/拉取更改。
  • 构建解决方案。
  • 构建包。
  • 将包上传到包服务器。
您可以在虚拟机上或现有的构建服务器上运行TeamCity、CruiseControl.NET或其他CI服务器。

1
你肯定可以。我已经为工作构建了几个库,这些库在构建过程中创建了一个NuGet包,并使用MSBuild脚本和NuGet命令行工具将其提交到我们公司的内部NuGet源作为发布构建过程的一部分。虽然我很高兴看到现在有一个帮助解决这个问题的库,但我还是要在下一个实验性构建阶段尝试一下它。 - Chris McGrath

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