系统程序员成长计划-工程管理(一)
转载时请注明出处和作者联系方式
文章出处:http://www.limodev.cn/blog
作者联系方式:李先静 <xianjimli at hotmail dot com>
到目前为止本书的上半部分已经完成了。在上半部分中,我们学习了基本的数据结构、算法和设计思想。在进行深入学习之前,我们把前面所写的代码整理成一个通用的函数库,这个函数可能在以后的工作中用得着。
前面我们写的Makefile非常简单,大概类似下面的内容:
all:
gcc -Wall -g -DDARRAY_TEST darray.c -o darray_test
gcc -Wall -g -DDLIST_TEST dlist.c -o dlist_test
gcc -Wall -g linear_container_test.c -L./ -lcontainer -o container_test
gcc -Wall -g invert_ng.c -DINVERT_TEST -L./ -lcontainer -o invert_ng_test
gcc -Wall -g invert.c -DINVERT_TEST -L./ -lcontainer -o invert_test
gcc -Wall -g -shared darray.c dlist.c linear_container_darray.c linear_container_dlist.c -o libcontainer.so
clean:
rm *test *.so
这个简单的Makefile,对于我们学习编程已经够了,因为我们写的函数库没有真正的用户,只要测试程序通过就好了。但是作为一个真正的软件包,你还要考虑下列因素:
o 依赖规则。前面我们没有写编译依赖规则,不管源文件有没有变化,反正全部编译一遍。对于小程序来说用不了多少时间,那没有问题,而一些大模块可能要花上几十分钟,那就不可接受了。
o 不同平台之间的差异。 同是支持POSIX标准的unix-like操作系统,多多少少都有些不同。即使同样是Linux,发行版本不一样,或者libc(除了glibc外还有 几种轻量级libc)不一样,或者使用的桌面环境(如KDE和GNOME)不一样,都会给编写跨平台软件来带一些困难。我们在编写软件时已经考虑到了可移 植性问题,但是去检查编译环境就也是件麻烦的事。
o 交叉编译。在嵌入式环境中,我们在PC上编译在设备上运行的程序,或者在x86上编译在powerpc上运行的程序,这都是属于交叉编译。交叉编译产生不同于编译机器的机器码,这要求编译时使用不同(版本)的编译器。
o 同时为多个平台编译。比如编译一个在PC上运行的模拟环境和在ARM板子上实际运行的版本。在前面的Makefile里,编译生成的文件全部放在一个目录下,一次只能编译一个版本,切换到另外一个版本时,你要清除所有文件重新编译。
o 调用者如何使用。一个软件包肯定不是孤独存在的,一定有另外的函数库或应用程序使用它。调用者怎么知道这个软件包安装在哪里呢?有的安装在/usr下,有的安装在/usr/local下,还有的安装到用户目录下。不知道安装在哪里,又怎样去链接它呢?
o Makefile的复杂度。要用Makefile解决上述问题,Makefile一定变得非常复杂。有兴趣的读者可以研究一下Firefox、Linux 和Android的Makefile,这些Makefile可不是一般人可以写出来的,普通开发人员通常不愿意花几周时间去写Makefile吧。
其实这些问题都不用担心,因为开源界的前辈们早就遇到过了,并用非常巧妙的方式解决了它们。接下来,我们一起学习automake/autoconf,看看它是如何解决这些问题的。