Chapter 3. Less Simple Things to do with builds
在这章中,你将看到一些简单的编译配置例子。
3.1 Specifying the name of the target (output) file
=====
当你使用 Program 来编译工程,默认的输出文件的名字和源文件同名。
Program('hello.c')
如果想使用别的输出名,只要在源文件名的左侧指定即可。Scons中要求目标文件第一个出现,然后是源文件。
Program('new_hello', 'hello.c')
% scons -Q
cc -o hello.o -c hello.c
cc -o new_hello hello.o
3.2 compiling multiple source file
=====
在实际工程中,肯定需要编译不止一个源文件。在 SCons 中就需要把源文件放在一个Python 列表中。
Program(['prog.c', 'file1.c', 'file2.c'])
% scons -Q
cc -o file1.o -c file1.c
cc -o file2.o -c file2.c
cc -o prog.o -c prog.c
cc -o prog prog.o file1.o file2.o
在 SCons 中会自动推导出目标文件名为第一个源文件名,在这里就是prog.c。和前面类似,如果想指定一个不同的目标文件名,把列表向右移,第一项为指定输出文件名。
Program('program', ['prog.c', 'file1.c', 'file2.c'])
% scons -Q
cc -o file1.o -c file1.c
cc -o file2.o -c file2.c
cc -o prog.o -c prog.c
cc -o program prog.o file1.o file2.o
3.3 making a list of files with Glob
=====
有时一个一个指定源文件列表会比较繁琐,比如在一个文件夹内有100个源文件。这时可以用 SCons 的 Glob 函数来自动匹配一些指定的函数名。比如可以编译文件夹内所有的.c文件。
Program('program', Glob('*.c'))
3.4 specifying single files vs. lists of files
=====
我们已经知道了两种指定源文件列表的方式。一种是。
Program('hello', ['file1.c', 'file2.c'])
另一种是。
Program('hello', 'hello.c')
当然也可以只在列表里面放一个源文件。
Program('hello', ['hello.c'])
虽然字符串和列表的形式这里都能工作,但实际上,Scons 把他们都当做列表来处理。在 Python 中,列表和字符串不能直接相加,而列表之间可以。所以当你想往源文件列表中增加一个源文件的时候,就不能用字符串的形式。
Program('program1', common_sources + 'program1.c')
# 这里就会报错,因为试图 列表和字符串 相加
而应该使用如下的形式。
Program('program2', common_sources + ['program2.c'])
3.5 making lists of files easier to read
=====
使用列表的方式组织源文件的一个缺点是不易阅读,每个源文件都要用引号括起来。SCons 和 Python 都提供了处理这种情况的函数。在 Scons中,使用 Split 函数可以将字符串转换成列表,字符串中以空格作为每个元素的分隔。
Program('program', Split('main.c file1.c file2.c'))
这个实际上和 Python中的 split() 函数类似,split则更为灵活。把源文件列表一长串都放进Program中显得不美观,可以使用一个变量来存放源文件列表。
src_files = Split('main.c file1.c file2.c')
Program('program', src_files)
Split 函数对空格的多少并不关心,所以还可以写成这样。
src_files = Split("""main.c
file1.c
file2.c""")
Program('program', src_files)
3.7 compiling multiple programs
=====
可以在一个SConstruct文件里面编译输出多个目标。只需调用Program多次即可。
Program('foo.c')
Program('bar', ['bar1.c', 'bar2.c'])
% scons -Q
cc -o bar1.o -c bar1.c
cc -o bar2.o -c bar2.c
cc -o bar bar1.o bar2.o
cc -o foo.o -c foo.c
cc -o foo foo.o
值得注意的是,SCons并不是按照Program函数的顺序来编译的,实际上时按照依赖关系来决定编译顺序的。
3.8 sharing source files between multiple programs
=====
在程序之间复用代码是很常见的事,其中一种方法就是使用库,然后在程序编译时链接。这在第四章中将详述。
然而,一种更为直接的方法是直接包含相同的源文件。
Program(Split('foo.c common1.c common2.c'))
Program('bar', Split('bar1.c bar2.c common1.c common2.c'))
% scons -Q
cc -o bar1.o -c bar1.c
cc -o bar2.o -c bar2.c
cc -o common1.o -c common1.c
cc -o common2.o -c common2.c
cc -o bar bar1.o bar2.o common1.o common2.o
cc -o foo.o -c foo.c
cc -o foo foo.o common1.o common2.o
如果两个程序之间共享了很多的源文件,一个一个写出未免太麻烦,这时,使用python的语法解决一下就行了。
common = ['common1.c', 'common2.c']
foo_files = ['foo.c'] + common
bar_files = ['bar1.c', 'bar2.c'] + common
Program('foo', foo_files)
Program('bar', bar_files)