分类: Python/Ruby
2015-07-24 15:51:34
今天移植zxing到开发板,发现zxing的编译是通过scons编译的,特此学习一下。这篇是在别人基础上修改的,原文网址是http://blog.csdn.net/sealyao/article/details/6402257,加以整理,又加上了一点自己的东西。
scons是一个Python写的自动化构建工具,和GNU make相比优点明显:
1、 移植性:python能运行的地方,就能运行scons。
3、 智能:Scons继承了autoconf/automake的功能,自动解析系统的include路径、typedef等;“以全局的观点来看所有的依赖关系”
2、 扩展性:理论上scons只是提供了python的类,scons使用者可以在这个类的基础上做所有python能做的事情。比如想把一个已经使用了Makefile大型工程切换到scons,就可以保留原来的Makefile,并用python解析Makefile中的编译选项、源/目标文件等,作为参数传递给scons,完成编译。
scons中可能出现的文件: SConstruct/Sconstruct/sconstruct和 SConscript
这个文件是scons工具必备的,是编译的配置文件,相当于make中的makefile文件。
scons将在当前目录以下次序 SConstruct,Sconstruct,sconstruct 来搜索配置文件,从读取的第一个文件中读取相关配置。
在配置文件SConstruct中可以使用函数SConscript()函数来定附属的配置文件。按惯例,这些附属配置文件被命名为”SConscript”,当然也可以使用任意其它名字。
1、Program:生成可执行文件
(1)、指定目标文件的名字
当你调用Program编译方法的的时候,它编译出来的程序名字是和源文件名是一样的。下面的从hello.c源文件编译一个可执行程序的调用将会在POSIX系统里编译出一个名为hello的可执行程序,在windows系统里会编译出一个名为hello.exe的可执行程序。Program('hello.c')如果你想编译出来的程序的名字与源文件名字不一样,你只需要在源文件名的左边声明一个目标文件的名字就可以了:Program('new_hello','hello.c')现在在POSIX系统里运行scons,将会编译出一个名为new_hello的可执行程序:% scons -Qcc -o hello.o -c hello.ccc -o new_hello hello.o
(2)、编译多个源文件通常情况下,你需要使用多个输入源文件编译一个程序。在SCons里,只需要就多个源文件放到一个Python列表中就行了,如下所示:Program(['prog.c','file1.c','file2.c'])运行scons编译:% scons -Qcc -o file1.o -c file1.ccc -o file2.o -c file2.ccc -o prog.o -c prog.ccc -o prog prog.o file1.o file2.o注意到SCons根据源文件列表中的第一个源文件来决定输出程序的名字。如果你想指定一个不同的程序名称,你可以在源文件列表的右边指定程序名,如下所示指定输出程序名为program:Program('program',['prog.c','file1.c','file2.c'])
(3)、使用Glob指定文件列表你可以使用Glob函数,定义一个匹配规则来指定源文件列表,比如*,?以及[abc]等标准的shell模式。如下所示:Program('program', Glob('*.c')) ,指定文件列表,编译该目录下所有的c文件。
(4)、指定单个文件以及文件列表有两种方式为一个程序指定源文件,一个是文件列表,使用方括号:Program('hello', ['file1.c', 'file2.c'])一个是单个文件:Program('hello', 'hello.c')也可以把单个文件放到一个列表中,Program('hello', ['hello.c'])(5)、使文件列表更易读对于单个文件,SCons函数支持两种方式。实际上,在内部,SCons把所有的输入都是看成列表的,只是在单个文件的时候,允许我们省略方括号。
为了更容易处理文件名长列表,SCons提供了一个Split函数,这个Split函数可以将一个用引号引起来,并且以空格或其他空白字符分隔开的字符串分割成一个文件名列表,示例如下:Program('program', Split('main.c file1.c file2.c'))或者src_files=Split('main.c file1.c file2.c')Program('program', src_files)同时,Split允许我们创建一个文件列表跨跃多行,示例如下:src_files=Split("""main.cfile1cfile2.c""")Program('program', src_files) ,可以理解为定义变量,并且给变量赋值。
(6)、关键字参数SCons允许使用Python关键字参数来标识输出文件和输入文件。输出文件是target,输入文件是source,示例如下:src_files=Split('main.c file1.c file2.c')Program(target='program', source=src_files)或者src_files=Split('main.c file1.c file2.c')Program(source=src_files, target='program')
(7)、编译多个程序如果需要用同一个SConstruct文件编译多个文件,只需要调用Program方法多次:Program('foo.c')Program('bar', ['bar1.c', 'bar2.c'])
(8)、在多个程序之间共享源文件在多个程序之间共享源文件是很常见的代码重用方法。一种方式就是利用公共的源文件创建一个库文件,然后其他的程序可以链接这个库文件。另一个更直接,但是不够便利的方式就是在每个程序的源文件列表中包含公共的文件,示例如下:Program(Split('foo.c common1.c common2.c'))Program('bar', Split('bar1.c bar2.c common1.c common2.c'))如果程序之间共享的源文件过多,可以简化:common=['common1.c', 'common2.c']foo_files=['foo.c'] + commonbar_files=['bar1.c', 'bar2.c'] + commonProgram('foo', foo_files)Program('bar', bar_files)
2、Object:生成目标文件
这个相当于是上个过程的中间环节,只是生成目标文件,并没有进行连接。
Object('hello.c') 编译hello.c目标文件,根据系统自动生成(hello.obj on Windows; hello.o on POSIX)
3、Library:生成静态/动态库文件
Library('foo', ['f1.c', 'f2.c', 'f3.c']) 编译library
SharedLibrary('foo', ['f1.c', 'f2.c', 'f3.c']) 编译 shared library
StaticLibrary('bar', ['f4.c', 'f5.c', 'f6.c']) 编译 static library
库的使用:需要指明LIBS指明名称,LIBPATH指明路径
Program('prog.c', LIBS=['foo', 'bar'], LIBPATH='.') 连接库,不需加后缀或是前缀,
4、SourceSignatures:判断源文件是否修改
SourceSignatures('MD5') 根据内容是否改变,默认方式
SourceSignatures('timestamp') 根据修改时间
5、TargetSignatures:判断目标文件是否改变
TargetSignatures('build') 根据编译结果
TargetSignatures('content') 根据文件内容,如果只是加了句注释,将不会被重新编译
6、Ignore:忽略依赖关系
Ignore(hello, 'hello.h') 忽略某个依赖关系
7、Depends:明确依赖关系
Depends(hello, 'other_file') 明确依赖关系
8、SConscript:scons的配置文件。
源文件的目录结构如下:
src:
| SConstruct
| test.cpp
| mA(目录):
| SConscript
| func.cpp
其中test.cpp为主文件,中调用func.cpp中定义的函数
SConstruct内容如下:
点击(此处)折叠或打开
点击(此处)折叠或打开
9.env:环境变量
环境变量用于设置在编译过程中的各种参数,可以用下面的SConstruct打印环境变量的所有信息(实际上env就是一个python字典)
可以使用如下的SConstruct查看环境变量的内容:
点击(此处)折叠或打开
点击(此处)折叠或打开
test.cpp和mA/func.cpp都引用了include/foo.h,test.cpp调用了mA/func.cpp的功能函数,其中include/foo.h中定义了一个包含string类型的类。
点击(此处)折叠或打开
不出意外的话上边的工程编译可以通过,但是运行的时候会Aborted。因为test.cpp,mA/func.cpp都使用了包含string类型的那个类,但是由于编译环境的不同,test.cpp认为string变量的大小是24字节, mA/func.cpp认为string变量的大小是4个字节(libstlport.a捣的鬼)。
解决问题的办法就是环境变量输出,修改SConstruct和mA/SConscript如下:
点击(此处)折叠或打开
参考博客:http://blog.csdn.net/andyelvis/article/category/948141