我知道 Stack Overflow 上还有其他与NAnt和MSBuild相关的问题,但我找不到两者之间的直接比较,所以这里是问题所在。
什么时候应该选择 NAnt 而不是 MSBuild?哪个更适合什么?NAnt 更适合家庭/开源项目,MSBuild 更适合工作项目吗?两者中的任何一个是什么体验?
这周我做了一个类似的调查。这是我能够确定的:
南特:
微软构建:
主观差异: (YMMV)
MSBuild 对我来说(在 Windows 平台上)的主要吸引力之一是它作为 .NET 本身的一部分。这意味着任何安装了 Windows Update 的 Windows 机器都可以使用 MSBuild。除此之外,C# 编译器也是 .NET 本身的一部分,并且您拥有一个可以在干净的机器上构建项目的平台。无需安装 Visual Studio 庞然大物。另一方面,必须在触发构建之前显式安装 NAnt。
仅作记录,我过去曾在非平凡的构建中使用过 NMake、Make、Ant、Rake、NAnt 和 MSBuild(按此顺序)。我最喜欢的是 MSBuild,毫无疑问(我不喜欢它,因为“这就是 Visual Studio 使用的”)。恕我直言,它是一个非常被低估的构建工具。
我会将 NAnt 与 MSBuild 与过程编程和函数式编程之间的区别进行比较。NAnt 非常简单,你得到你所看到的。另一方面,MSBuild 需要更多的思考。学习曲线更陡峭。但是一旦你“得到它”,你就可以用它做一些了不起的事情。
因此,如果您也倾向于函数式或逻辑式编程,我建议您查看 MSBuild - 如果您愿意在看到切实结果之前投入一些时间和精力(当然,我也坚信投资最终会得到回报,并且您可以更有效地做更强大的事情)。
就个人而言,我将两者都用于同一个项目。
MSBuild 非常擅长构建 Visual Studio 解决方案和项目——这就是它的用途。
在我看来,NAnt 更容易手动编辑 - 特别是如果您已经了解 Ant。NAnt 可以使用 NAntContrib 非常轻松地调用 MSBuild。因此,我手工制作了一个 NAnt 脚本来执行复制构建文件、清理等操作 - 并调用 MSBuild 来执行实际的“将我的 C# 源代码转换为程序集”部分。
如果您想要一个示例,请查看我的Protocol Buffers 构建文件。(我不会声称这是一个很棒的 NAnt 脚本,但它确实可以完成这项工作。)
NAnt具有更多开箱即用的功能,但MSBuild具有更好的基本结构(项目元数据岩石),这使得构建可重用的 MSBuild 脚本变得更加容易。
MSBuild 需要一段时间才能理解,但一旦你完成它就会非常好。
学习资料:
KISS = 使用 MSBuild。
当你有一些可以开箱即用的东西时,为什么还要添加其他东西呢?当 MSBuild 到来时,NAnt 死了。Mono将有一个 MSBuild 实现,( xbuild )。
DRY = 使用 MSBuild。
问问自己你想从构建系统中得到什么?我想要一个我的IDE也使用的构建系统,而不是维护两个不同的配置。
就个人而言,我很想听听一些关于 NAnt 的真正论据,因为我想不出任何真正站得住脚的论据。
我注意到几张海报提到的一件事是必须手动编辑 .csproj(或 .vbproj 等)文件。
MSBuild 允许通过使用 .user 文件自定义这些 .*proj 文件。如果我有一个名为MyCreativelyNamedProject.csproj的项目并且想要自定义其中的 MSBuild 任务,我可以创建一个名为MyCreativelyNamedProject.csproj.user的文件并使用CustomBeforeMicrosoftCommonTargets和CustomAfterMicrosoftCommonTargets来自定义这些文件。
此外,NAnt 和 MSBuild 都可以通过自定义 MSBuild 任务和 NantContrib 扩展来定制。
因此,使用 NAnt 或 MSBuild 真的归结为熟悉:
还值得补充的是,MSBuild 几乎可以保证在所有新版本的.NET和 Visual Studio 发布后就可以使用,而 NAnt 可能会有一些滞后。
我在我的NAnt脚本调用 MSBuild 时都使用了这两种方法。我留在 NAnt 的主要原因是孤立。让我解释一下为什么我觉得这很重要:
将依赖项添加到您的项目。NAnt 构建文件对 Visual Studio 来说是陌生的(在我的情况下,我认为这是一个专业人士),因此 Visual Studio 不会尝试对它做任何事情。MSBuild 任务是嵌入的,因此是解决方案的一部分,可以引用其他 MSBuild 任务。我从其他人那里收到了源代码,却发现我无法构建,因为没有安装 MSBuild 社区任务。我发现特别令人沮丧的是,Visual Studio 无法构建并抛出一堆错误,让我在调试时失去了时间。尽管没有 MSBuild 任务的一些额外内容,但请求的构建可能已经进行(例如作为调试构建)。简而言之:如果可以避免的话,我不喜欢在我的项目中添加依赖项。
我不相信 Visual Studio,因为我可以扔掉它的开发团队。这可以追溯到 Visual Studio 的早期阶段,当时它会屠杀我的 HTML。例如,我仍然不使用设计器(在最近的一次会议上,我发现同事也这样做了)。我发现 Visual Studio 可以搞砸 DLL 文件中的依赖项和版本号(我无法复制这一点,但它确实在项目中始终如一地发生,并导致很多悲伤和浪费时间)。我采用了一个构建过程,它使用 Visual Studio 仅在调试模式下构建。对于生产,我使用 NAnt 以便从外部控制一切。如果我使用 NAnt 构建,Visual Studio 就不能再干扰了。
PS:我是一名网络开发人员,不进行 Windows 窗体开发。
虽然我对 MsBuild 不是很熟悉,但我的印象是双方的一些关键差异可以通过添加来补充:
我最近不得不在 Nant 构建一个 Silverlight 项目。我发现如果我只是用 MsBuild 来做这件事,生活会更轻松——我最终从 Nant 脚本中调用了一个 MsBuild 任务,所以我想混合和匹配这两者并没有什么不寻常的。
除此之外,我想这将是个人喜好的问题 - 显然,如果这是你的事,你可以从 Visual Studio 中管理 MsBuild 的部分/大部分功能。如果您更喜欢手工编写脚本,Nant 似乎更灵活,更适合,如果您来自 Java 世界,您可能对它很熟悉。
我最终都使用了。在重新设计我们的构建系统时,我遇到了一个棘手的问题。也就是说,我无法摆脱 .vcproj(和家庭),因为我们每个人都在使用 VS 来更新项目文件、设置和配置。因此,如果没有大量重复和容易出错的过程,我们就无法将构建系统基于一组新文件。
出于这个原因,我决定保留VS的'proj'文件并使用MSBuild(它们是MSBuild文件,至少VS2005和VS2008使用MSBuild项目文件)。对于其他一切(自定义配置、单元测试、打包、准备文档......)我使用了 NAnt。
对于持续集成,我使用了 CruiseControl。所以我们有触发 NAnt 作业的 CC 脚本,用于构建使用 MSBuild。
最后一点:MSBuild 不支持安装项目!因此,您只能调用 DevEnv.com 或直接使用 Visual Studio。这就是我最终做的事情,但我默认从所有解决方案配置中禁用了安装项目,因为开发人员通常不需要构建它们,如果他们这样做,他们可以手动选择构建它们。
我最近从 NAnt 切换到了 MSBuild,因为它能够构建 VS 解决方案。不过,我仍然偶尔使用 NAnt。
您可能还想查看类似于 NAntContrib的MSBuild 社区任务。
可用于 NAnt 的文档和教程使开始学习使用 NAnt 构建脚本变得更加容易。一旦我掌握了 NAnt 并创建了构建脚本,我就开始将这些知识转化为 MSBuild(我在 NAnt 中做了 X,我如何在 MSBuild 中做 X?)。Microsoft 的文档在有用之前通常假定具有相当高的知识水平。
从 NAnt 切换到 MSBuild 的原因是因为 MSBuild 更新。不幸的是,NAnt 的最后一个版本是在 2007 年 12 月 8 日,而 MSBuild 4.0 (.NET 4.0) 也离我们不远了。看起来 NAnt 项目已经死了。
如果您为刚开始学习使用 MSBuild 创建构建脚本的人找到了很好的文档,那么请跳过 NAnt 并直接使用 MSBuild。如果 NAnt 发布了新版本,那么我会考虑坚持使用 NAnt,但他们现在已经落后了。
我们两者都用。NAnt 负责所有“脚本”工作,例如复制、在IIS上部署、创建包,而 MSBuild 负责构建解决方案。然后我们可以通过新版本的 NAnt 避免不支持的 .NET 4.0 的问题。
NAnt 也更具可扩展性。如果我们想将部署脚本迁移到生产服务器,我们只需复制构建文件并安装正确版本的 .NET - csproj 文件没有 Visual Studio 问题:)
Manoj 的YDeliver是一个构建在 PSake 之上的构建框架。它具有一组丰富的库函数、定义工作流的能力,我们已经使用它将超过六个企业项目交付生产。
将它与TeamCity、CruiseControl或任何可以运行PowerShell的东西结合使用。
我们使用 FlubuCore。它是一个开源 C# 库,用于使用 C# 代码构建项目和执行部署脚本。
如何使用flubu的简单示例:
protected override void ConfigureTargets(ITaskContext session)
{
var compile = session.CreateTarget("compile")
.SetDescription("Compiles the solution.")
.AddTask(x => x.CompileSolutionTask())
.DependsOn("generate.commonassinfo");
}
您可以在此处找到有关 Flubu 以及如何开始的更多信息: choice-for-build-tool-msbuild-nant-or-something-else