当我意识到大多数语言的主要构建工具/系统使用的语言与基础编程语言本身所使用的语言不同时,我最近一直在为Nodejs项目使用一些构建工具。
例如,make不使用C或C ++编写脚本,而ant(也不是Maven)不使用Java作为脚本语言。
诸如Ruby之类的较新语言的确将相同的语言用于诸如rake之类的构建工具,这对我来说很有意义。但是,为什么情况并非总是如此?拥有使用与基础语言不同的语言的构建工具的优势是什么?
make
再次写完(无论如何用C实现)?
当我意识到大多数语言的主要构建工具/系统使用的语言与基础编程语言本身所使用的语言不同时,我最近一直在为Nodejs项目使用一些构建工具。
例如,make不使用C或C ++编写脚本,而ant(也不是Maven)不使用Java作为脚本语言。
诸如Ruby之类的较新语言的确将相同的语言用于诸如rake之类的构建工具,这对我来说很有意义。但是,为什么情况并非总是如此?拥有使用与基础语言不同的语言的构建工具的优势是什么?
make
再次写完(无论如何用C实现)?
Answers:
编写使用C或Java之类的语言作为脚本语言的构建工具并非没有可能。但是,构建工具得益于使用更多的声明性脚本语言。想象一下用C编写makefile(或build.xml或其他内容)的痛苦和样板。
构建工具得益于DSL的使用,而DSL并不是一个特别好的选择。对于构建工具而言,C 太笼统,并且过于关注容易出错和底层的细节。例如,您不想关心构建工具中的显式内存管理!因此,即使使用类似C的语法,您也可能会在脚本编写工具中使用垃圾回收,这时为什么不简单地使用专用DSL?
可以使用Ruby是有道理的,因为它是比C或Java更高级,更具声明性的语言。另请参阅:Gradle,sbt。
Imagine the pain and boilerplate of writing a makefile (or build.xml, or whatever) in C.
想象一下尝试在声明性XML脚本中表达非平凡的条件逻辑(您知道,标准命令性内容)的痛苦和混乱。哦,等等,您不必想象;您可能不得不处理它,而且可能是一团糟,不是吗?对于声明性脚本语言来说,构建是最糟糕的选择之一,因为严重的问题很快就会变成声明性限制,而问题又不够简单,不需要构建工具。
让我们给您一个真实的例子。
大约15年前,我致力于将用C语言编写的大型系统从Unix移植到Windows,这大约需要300万行代码。为了给您一些扩展的概念,在我们的某些Unix系统(RS6000)上编译花费了24小时以上,而Windows可以在大约4小时内完成编译。
(我们还用自己的解释语言编写了200万行代码,但是由于从未为文件处理而设计,因此决定不将其语言用于构建系统。此外,我们还需要一个构建系统来编译实现我们语言的C代码)
在构建系统是用Shell脚本和make文件混合编写的时候,这些文件不能移植到Windows上-因此,我们决定编写自己的构建系统。
我们本可以使用C,但是我们决定使用python,原因很少。(我们同时也在python中重写了源代码控制系统,这与构建系统非常集成,因此开发人员可以共享用于检入模块的目标文件。)
我们的大多数代码都可以使用一些简单的规则(从文件的命名约定驱动)(对于所有平台,Windows,VMS和Unix的6个版本来说,只有几千行python)可以构建。
当RegEx在不同平台上的C系统之间不是很标准时,Python就内置了RegEx。
一些模块需要自定义构建步骤,Python允许动态加载类文件。我们基于文件夹中具有魔术名称的python文件,允许使用自定义类来构建模块(lib)。 这就是使用python的杀手级原因。
我们考虑过Java,但当时还没有在所有平台上发布。
(我们的源代码控制系统的UI使用了Web浏览器,因为该浏览器可在所有平台上移植。这距离我们建立互联网连接已有6个月了。我们必须通过X25下载浏览器!)
这个问题的简短答案是,这就是构建工具。一种自动使用其他工具的工具,目的是从某些源文件构建最终产品。如果我们使用与产品本身相同的语言来编写构建脚本,那么我们将进入特定于语言的工具领域,而这些工具将不能以相同的方式被视为构建工具。
这就提出了一个问题-编译器为什么不提供像make这样的工具所习惯的构建自动化?对此的答案仅仅是因为make存在。Unix的哲学“做一件事情,做好一件事情”表明,提供此功能不是编译器的责任。就是说,我个人经历了很多麻烦事,因此有兴趣尝试提供自己的引用-不引用“本机”构建系统的编译器。
有关以此方式设计的编译器的示例,请参见Jon Blow的Jai(尚未发布),该语言旨在替代C ++。在此收集了有关编译器的讨论和演示的链接。该语言编译为在编译器中运行的字节码,而编译为二进制是标准库提供的功能,可从字节码访问。目的是允许在语言的本机语法内进行构建自动化和元编程。
*查看Microsoft的Visual Studio将为您展示相反哲学的示例。:)
首先,构建工具是一个工具,就像“ gcc”,“ ls”,“ awk”或“ git”一样。您向工具提供输入(文件名,参数等),它将相应地做一些事情。
所有这些工具都允许您以应该足够容易编写和理解的方式传递输入。对于特定的构建工具,输入是一个配方文件,该文件描述了您的项目从源文件到成品的过程。
如果您的食谱很简单,只需传递包含要使用的项目和编译器的文件夹,那么声明性的“语言”就足够了。一旦配方变得越来越复杂,逻辑越来越多,使用声明性语言来处理它就会变得很麻烦,并且会使用更多通用语言。
现在应该很明显,仅仅因为它们具有不同的目的和要求,用于编写构建配方的语言与用于编写产品代码的语言之间就没有联系了。甚至在编写构建工具所用的语言与应该编写构建配方的“语言”之间都没有任何联系。始终使用最佳工具来完成工作!