在Linux系统上做过c/c++开发的同学们都知道一个项目工程管理工具:make和Makefile。
make 这个工具自上个世纪 70 年代 Stuart Feldman 在贝尔实验室开发出以来,就一直是类 UNIX 程序员的最爱之一。
通过检查文件的修改时间,make 工具可以知道编译目标文件所要依赖的其他文件。在复杂的项目中,如果只有少数几个文件修改过,make 工具知道仅仅需要对哪些文件重新编译就可以确保目标程序被正确的编译链接。这样做的好处就是在编译中,不仅可以节省大量的重复输入,还可以确保程序可以被正确的链接,缩短编译的时间。
虽然如此,但是为 make 工具编写建造规则却不是一件容易的事。它复杂的配置规则,即使是有经验的开发者也望而生畏。
那么,今天介绍一个它的同类产品,也可以说是升级产品:Scons,它做的事情跟make一样,但更简单,更容易。
Scons是一个开放源码、以Python语言编码的自动化构建工具,可用来替代make编写复杂的makefile。并且scons是跨平台的,只要scons脚本写的好,可以在Linux和Windows下随意编译。
SCons 的设计目标就是让开发人员更容易、更可靠和更快速的建造软件。
与传统的 make 工具比较,SCons 具有以下优点:
在 SCons 的官方网站上可以查每个平台的具体安装方法。
Win平台的下载和安装就不说了。
Linux下下载tar包,执行以下命令即可:
tar -zxf scons-2.0.1.tar.gz
cd scons-2.0.1
sudo python setup.py install
对于 Linux 来说,scons 会默认安装到 /usr/loca/bin 目录下,而在 Windows 平台上,则会被安装到 C:\Python25\Scripts 下。
这里通过一个简单的示例来说明。
一个hello.c源文件,一个SConstruct文件,后面再解释。
% ls
hello.c SConstruct
% cat hello.c
#include <stdio.h>
int main(void)
{
printf("hello, world!\n");
return 0;
}
运行Scons,得到如下:
% scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
gcc -o hello.o -c hello.c
gcc -o hello hello.o
scons: done building targets.
% ls
hello hello.c hello.o SConstruct
% ./hello
hello, world!
就是这样,程序编译完成了。到这里Scons似乎与make没有什么两样,同样的操作,只是把scons换成make,SConstruct换成Makefile。
对,不同的地方就在于,下面的展示:
% cat SConstruct
Program("hello.c")
哈哈,你没看错,就这一行,编译就完成了!!!
事实确实如此,它比传统的 Makefile 简单很多。SConstruct 以 Python 脚本的语法编写,你可以像编写 Python 脚本一样来编写它。
其中的 Program 是编译的类型,说明你准备想要建造一个可执行的二进制程序,它由 hello.c 文件来生成。
在这里,没有指定生成的可执行程序的名字,SCons 会把源代码文件名字的后缀去掉,用来作为可执行文件的名字。
我们甚至不需要像 Makefile 那样指定清理的动作,就可以执行清理任务。在 SCons 中,执行清理任务由参数 -c 指定,如下 :
% scons -c
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Cleaning targets ...
Removed hello.o
Removed hello
scons: done cleaning targets.
% ls
hello.c SConstruct
如果你不想直接编译可执行的二进制文件,那也没有关系。SCons 支持多种编译类型,你可以根据自己的需要,任意选用其中的一种。
SCons 支持的编译类型有:
如果不想使用 SConstruct 为你设置的默认可执行文件的名字,而是选择你自己喜欢的名字,如 myhello,可以把 SConstruct 的内容修改为 :
Program('myhello', 'helloscons.c')
其中 myscons 就是你想要的可执行文件的名字.
% scons -Q
gcc -o hello.o -c hello.c
gcc -o myhello hello.o
其中,-Q 参数是减少编译时的由 scons 产生的冗余信息。
如果你的项目由多个源文件组成,而且你想指定一些编译的宏定义,以及显式的指定使用某些库,这些对于 SCons 来说,都是非常简单的事情。我们的另外一个例子 helloscons2 很好的说明这种情况。 helloscons2 由 3 个源文件组成 , 它们是 helloscon2.c, file1.c, file2.c,另外指定了编译的选项,同时还指定了使用哪些具体的库。让我们来看一下 helloscons2 的 SConstruct 文件 :
Program('helloscons2', ['helloscons2.c', 'file1.c', 'file2.c'],
LIBS = 'm',
LIBPATH = ['/usr/lib', '/usr/local/lib'],
CCFLAGS = '-DHELLOSCONS')
该 SConstruct 文件指出,它将生成一个名叫 helloscons2 的可执行程序,该可执行程序由 helloscons2.c, file1.c 和 file2.c 组成。注意,多个源文件需要放在一个 Python 列表中。如果你的源程序代码文件很多,有十几个甚至上百个,那不要一个个的将他们都列出来,你可以使用 glob(’*.c’) 来代替源代码列表。如下 :
Program('helloscons2', Glob('*.c'))
配置文件中 LIBS,LIBAPTH 和 CCFLAGS 是 SCons 内置的关键字,它们的作用如下:
运行 scons 命令的时候,可以看到这些变量如何被使用的,让我们执行一下 scons 命令 :
$ scons -Q
gcc -o file1.o -c -DHELLOSCONS file1.c
gcc -o file2.o -c -DHELLOSCONS file2.c
gcc -o helloscons2.o -c -DHELLOSCONS helloscons2.c
gcc -o helloscons2 helloscons2.o file1.o file2.o -L/usr/lib -L/usr/local/lib -lm
以上只是入门,还有更多知识等待学习。
如,通过Environment指定编译环境,env = Environment(CC = 'g++')
,指定使用g++编译程序。
示例如下:
env = Environment(CC = 'g++')
env.Program("client", "client.c", LIBS = 'm', CPPPATH = '../include', CCFLAGS = '-std=c++11')