Main

May 08, 2021

构建工具从 Make 到 Ninja

最近,我们把自研游戏引擎的构建工具从 GNU Make 迁移到了 Ninja

迁移动机是这样的:

我为引擎编写了最初的 Makefile ,它可以很好的工作在 MinGW / MacOSX / iOS 平台。把基本框架搭好以后,用起来也比较方便。但是,参与开发的同事一直有用 MSVC 开发的需求,而我们迟迟没有在 Makefile 的框架里增加 MSVC 的支持。用 MSVC 的同事一直在手工维护一个 MSVC 的项目。

渐渐的,同时维护 Makefile 和 MSVC 的工程成了一个负担。

实际上,现在惯用的方法都是用一个高阶的语言去描述项目构建流程,再翻译成不同平台下的构建脚本。即使用 GNU Make ,通常我们也是先用 Make 本身设计一个框架,在这个框架下去描述构建脚本,再让 Make 在不同平台下生成不同的流程。

如果不介意引入新的工具,那么 Autoconf ,CMake ,Premake 都可以解决这个问题。

July 07, 2009

GNU Make 下创建目录的问题

很多时候,我们的 Makefile 在工作的时候,往往需要把中间文件放在独立目录中。这个独立目录一开始又没有创建出来。所以,Makefile 就有责任创建它们。

正确的创建目录,对于 Make 来说可是一个头痛的事情。

直观的写法是让目标依赖目录。比如:

foo.c : out/foo.o

out/foo.o : out

out :
    mkdir $@

这样做的问题在于,out 作为一个特殊文件(目录文件),时间戳是不受控的。

如果你删除或添加新文件到 out 目录下,都会更改 out 的时间戳,这会进一步的影响其依赖的目标。

June 26, 2009

让 Make 递归所有子目录

最近同事提了一个需求,想方便的调用一个工具校验所有的 xml 文件(包括子目录下的)。我想了一下,最简单的方法是用 Make 来辅助完成这件事情。

问题在于,怎样让 Make 递归的处理所有子目录。因为 GNU Make 默认的 wildcard 只能枚举出当前目录的文件,而不能递归下去。

求助于 Shell 指令当然是一种方法,如果只考虑 unix 环境,我会用 shell 去做。在 Windows 下也有 for 语句可以使用。但我不想处理复杂的平台差异。所以就在 Make 内置的函数里想办法了。

October 16, 2008

IDE 不是程序员的唯一选择(终)

对于这个系列,我已经意兴阑珊了。时间拖的太长也不好。从一开始我就没打算写一个某某工具(GNU Make)的入门教程。本来是想给那些微软 IDE 深度中毒者展现一些不同的东西,顺便打破 Make 等 CUI 工具的神秘感。工具是为人服务的,不应该是用来给人增添麻烦的。IDE 是这样,RAD 工具是这样,那些 CUI 工具也是如此。如果你能熟悉工具背后的使用哲学,工具就能给你便捷。不同的工作需要不同的工具去做,不要拿着锤子,就想把一切都变成钉子。

既然每一类工具都拥有特别多的用户,而且这个用户群还不都是脑残,去看看不同领域总是好的。对于开发环境来说是这样,选择编程语言来说也是如此,又或者说到开发方式等等。

October 07, 2008

IDE 不是程序员的唯一选择(五)

国庆休完了,干了许多事情,几乎没闲着。接下来写这个系列,有点提不起兴致的感觉。

如果一直讲 GNU Make 的话,就有点离题了。本来我是想讲讲,离开 IDE ,程序员该如何处理问题的。Make 只是一个起点。写着写着,就已经写的足够的多,可又似乎什么都没讲出来。有心的同学应该已经找到 GNU Make 的中文手册自己去研究了,我想大家若结合自己做过的项目,会发现其中奥妙无穷。而比较乐意享受快餐文化的另一批同学,可能还在等我的下文。该怎么说?还是先引用 VIM 主页上介绍 vim 的一句话,

Vim isn't an editor designed to hold its users' hands. It is a tool, the use of which must be learned.

是的,Make 也是,更多的编程开发工具都是。既然是工具,就必须付出学习成本。如果你觉得使用某种工具不需要支付学习成本,那么你一定失去了一些东西。只不过,你未必意识的到而已。

September 25, 2008

IDE 不是程序员的唯一选择(四)

前面我们介绍了一些 Make 的基本知识以及 Make 的工作原理。如果同学们有兴趣的话,翻阅手册已经可以开始做许多事情了。而 GNU Make 更是有许多扩展,灵活应用便能发挥出超乎想象的威力。为了达到这些,Make 必须要有更多的一些可编程的能力。在处理不同的事务的时候,以不同的方式工作。在处理相同的事务时,又不必让编写 Makefile 的人机械性的重复。

今天,我们来谈谈 GNU Make 中的变量。这里提到的都是以 GNU Make 为基础,因为 Make 的各种变种太多,每种版本间都可能有一些细微的差别,但其基本原理是相通的。

September 24, 2008

IDE 不是程序员的唯一选择(三)

有了前面的介绍,相信好学的同学们对 make 已经有了一定的了解。

记住,编写 Makefile 也是构建整个软件的一部分,其重要性并不亚于编写 .c 或 .h 文件。当你用 IDE 的时候,是由 IDE 来生成相当于 Makefile 的文件。但是这个生成的过程并不是完全自动的,它是由你的鼠标点击、拖拽(把 .c 文件加入项目)、和填写一些表单、以及勾选编译选项完成的。

如果你的整个项目中其它源文件都是从键盘输入来编写的,那么 Makefile 也由手工编写就理所当然了。

如果你在用 C++ ,在用 C++ 中的 STL ,那么是不是应该搞清楚 STL 到底做了什么,怎么做到的,这些问题呢?这是用 C/C++ 语言编程的程序员的一个基本态度。即使不去研究透彻,至少也应该了解一些大致的原理吧。那么对于 Make 来说也是这样。我们应弄清楚 Make 到底如何在工作,我们在 Makefile 里写的每一行代码是什么含义。为什么可以帮我们完成那些工作。这个连载选择 Make 来展开,也正是因为 Make 的工作原理非常简单,方便我们学习。

越是简单的东西,越可以在其上做出各种奇妙的东西。Make 也是这样。但一开始就给出别人做好的完善的库,简单的用一下,会让我们迷失其真谛。相信我,最终,编写 Makefile 可以非常简单,善用工具、不必写任何多余的东西,甚至比在 IDE 里拖入几个源文件更简洁。但一开始,还是从繁琐开始,这些繁琐都是帮助你去理解,等你理解了自然能找到方法简化这些繁琐的工作。

云风绝非使用 Make 的高手,从某种意义上来说,也是一个入门者。写这个系列的时候,也需要去查阅文档确认是否写错。平时工作的时候,Makefile 文件通常也需要多次调试,才能正确的完成工作。也正是如此,才能体会到:怎样去理解和学习,容易跨过最初的门槛。

September 22, 2008

IDE 不是程序员的唯一选择(二)

话接上回,话说我们已经大致了解了 C 编译器的工作流程,知道了 IDE 在背后如何在驱动编译器生成代码。对于传统 IDE ,就是集成了编辑器、项目管理、编译器,和调试器等几个大件的一个庞然大物。其中 IDE 企图节省人力的最大的部分就是将源代码组织起来,自动生成其间的关系,调用编译器构建项目。

(此处删去几百字关于 IDE 优劣的讨论。因为我觉得这个话题会陷于无谓的争论,还是直入主题比较好。承接上篇的宗旨,本文只写给有兴趣学习相关知识却不知该如何入门的朋友。说服程序员放弃 IDE 不是本文的初衷。)

对于不太大的项目,比如学校里日常做作业。写一个 make.bat 文件管理你的 C 代码已经足够了。如果你用一些 windows style 的编辑器,比如流行的 editplus 之流,都可以配置相应的所谓 user tool,一键调用 .bat 构建出最终的程序。也可以设置捕获编译器的输出,方便的双击错误信息定位到源代码编译错误的地方。

如果想摆脱鼠标(纯键盘操作对于基于命令行的工作方式来说,非常的有效率。毕竟写程序最终也得靠键盘的。),可以考虑使用 vim 。不要惧怕学习新事物。任何被公认优秀的工具,都有学习的价值。vim 属于有一定学习门槛,但一旦掌握(一般程序员可能需要一周左右的时间熟悉),威力无穷的那种。我的另一个同事强烈推荐 emacs ,我没怎么用过。如果你打算写 10 年以上的程序,花上几天时间学习一个无数程序员公认好用的工具,这项投资我个人认为是非常值得的。

September 21, 2008

IDE 不是程序员的唯一选择(一)

我心目中,这篇文章的目标读者应该是在 Windows 下完全使用 Visual Studio 或 Borland C++ Builder (现在还有人在用么?)等系列 IDE 开发软件的 C/C++ 程序员。

我并不打算从 GNU Make 这种工具的使用写起,因为如果以上提到的这类同学如果都开始看 gmake 的文档(现在翻译工作已经有人做了),应当已经脱离了纯粹 IDE 开发的人群。本文只是一篇非常初步的入门文章,如果你已经使用过类似 gnu make 的工具构建自己的项目,那么完全不必看下去了。

不可否认,IDE 对于软件开发领域,是一项伟大的发明。它极大的降低了软件开发的门槛。但是另一方面,IDE 也限制了程序员们创造软件的手段。这些限制还包括了平台限制,工具选择,甚至新的编译技术,编程语言的选择。所以 IDE 绝对不是程序员的唯一选择,如果你现在作为一个程序员,完全不能离开 IDE 工作。那么,是时候接触一些新东西了。

如果你大约知道一点相关的知识,但是对用 make 工具去构建项目充满了鄙视和厌恶,云风不期望通过这篇文章改变你的想法。因为我不想花太多笔墨来介绍其好处。我个人认为,那些好处,一旦你认真的采用这种开发方式,是显而易见的。

August 30, 2007

make 使用笔记

我们的项目使用的构建工具,从今年初开始,从 boost jam 转移到 gnu make 。

makefile 写起来并不是一件轻松的事情,但是 make 的规则比 jam 要简单许多(比 boost jam 更简洁易懂),很符合 unix 的 KISS 美学。学会用 make 以后,编程方式可以得到极大的扩展,比用 IDE 的时代要灵活许多。尤其是可以用大量的使用自生成代码,或是用工具去生成数据文件,这些在 IDE 里做会相对麻烦。我们的开发,也不用局限在少数几种语言上了。

make 这个工具,我基本上是边学边用的,遇到什么问题临时想个方法弄一下。这最终导致 makefile 看起来很丑陋。但没有关系,写 makefile 跟写程序一样,以后可以不断重构。况且使用 makefile 本身,就很容易做任何自动化的工作了。

今天随便写几个最近遇到的问题,以及解决方案。

December 15, 2005

又让 bjam 郁闷了一把

早上到公司,同事告诉我 jamfile 又写错了 :( 在一个上级目录创建出来的 static lib 在下几级目录上想引用的时候,如果逐级在 project 里标上 <library> 就会出错。

这才发现,原来 jamfile 会完全 inherit 父目录上的 jamfile 的 project 属性。这点对 <include>这个 feature 做的很好。inherit 后会加一级 .. 但是 <library> 却不行。(原来我一直用 <source> 的,今天查代码才知道还有个 <library> 的 feature)

December 13, 2005

让 bjam 支持 fx 文件的编译

我们新的项目已经不再使用 VC 的 IDE ,而当初选择一个合适的 make 工具很花了一番工夫。最开始想用 makefile , 大家都用的。后来觉得很繁琐,不是很适合我们这个项目。然后选择了<a href="http://www.perforce.com/jam/jam.html">jam</a>。(当然其间也试过 Ant 等,在此不表) 花了很长一段时间熟悉 jam 的语法,和 C 也极大的不同。好不容易学会点了,同事怂恿我试试 <a href="http://www.boost.org/tools/build/v2/">bjam</a>,方知道 boost 那帮人的确 BT ,把 jam 这个小玩具的功能发挥到此般。看了人家给 jam 扩展的脚本,自己也就打消了在 jam 的基础上弄出点东西的想法,还是直接拿来用吧。