`

scons 学习

阅读更多

scons 学习
作者:Sam(甄峰) sam_code@hotmail.com

http://www.scons.org/

Sam有个好朋友是做游戏的,整天嘲笑做嵌入式的用的工具多土多原始。gdb不是图形化,DDD又没VC调试好用,只会写Makefile等等。
刚好最近有需要使用scons。所以Sam准备学习之以回击这种挑衅。呵呵。

scons简介:
scons是一个Python写的自动化构建工具,从构建这个角度说,它跟GNU make是同一类的工具。

scons与其它工具最显著的差别就是:scons配置文件是Python script.

它的思想是跟GNU make完全不同的。GNU make的核心是“依赖关系”,我要做的事情,就是告诉系统,一个目标依赖什么东西,并且,当被依赖的东西发生变化时,我要做什么。
例如:
all: main.c
$(CC) $(CFLAGS) $(LFLAGS) main.c -o BT_remote -lbluetooth -lBluetooth_remote -lm -lpthread
意思是:all依赖于main.c。 如果main.c有了变化,作下面这些事。


这样做可以解决相当多的问题,但是也带来了一个最大的问题:我如何判别这个目标依赖什么?

对于一个两个,甚至十几个文件,我当然还比较容易搞清楚,谁依赖谁。但是当文件有成百上千个时,要分清楚谁依赖谁可就没这么容易了。尤其是C/C++头文件的依赖,如果手工分析的话,工程量可是不小。为了解决这个问题,GNU又提供了另外一套工具:Automake,使用程序来分析依赖性,然后辅助你产生 makefile。

于是乎,就有人想了,既然如此,我干吗费那劲,用程序分析依赖性,然后生成一个文件,再交给另外一个程序去处理呢?既然依赖性需要用程序来分析,那么就直接交给构建工具本身去做不就好了吗?对的,这是一个非常自然的思路,于是,Java世界有了Ant,而 Python世界有了scons。

scons就是这样一个构建工具:你告诉它要做的任务,以及完成这个任务需要的输入,以及这个任务产生的输出,怎么做这个任务(当然其中就包括依赖性分析),就交给工具本身完成。


例 1:
只有一个 test.c文件,需要编译成可执行文件。
创建SConstruct,内容为:
Program('test.c')
这句话透露2层意思:
1.编译方法:想要编译成什么类型。(Program:可执行文件)
2.哪个东西想编译(test.c)
#scons
% scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cc -o test.o -c test.c
cc -o test test.o
scons: done building targets.

clean:
#scons -c
则把编译出的东西又删除了,类似make clean


例2:
只有一个文件,想编译成object文件。
Object('test.c')
1. 编译方法:想要编译成什么类型。(Object: .o文件)
2.哪个东西想编译(test.c)

#scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cc -o hello.o -c hello.c
scons: done building targets.

清空:
#scons -c
则把编译出的东西又删除了,类似 make clean

例3:
有多个.c文件,并想指定生成的程序名:
Program('program', ['prog.c', 'file1.c', 'file2.c'])
生成可执行文件 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

甚至可以这样写:
common_sources = ['file1.c', 'file2.c']
Program('program2', common_sources + ['program2.c'])



例4:
有很多个.c文件,不想一个一个指定,类似Makefile中 *.o: *.c
Program('test', Glob('*.c'))


不管使用common_sources = ['file1.c', 'file2.c'] 还是Program('test1.c'....'testn.c')
每个文件名都需要被单或者双引号包起来。这太不方便了。
SCons 提供了Split函数
Program('program', Split('main.c file1.c file2.c'))
或:
src_files = Split('main.c file1.c file2.c')
Program('program', src_files)



例5:
SCons还对 output file和source file有关键字,可以用来指定

src_files = Split('main.c file1.c file2.c')
Program(target = 'program', source = src_files)
因为有关键字指定,多以可以换前后:
Program(source = src_files, target = 'program')


例6:
创建库:
Library('foo', ['f1.c', 'f2.o', 'f3.c', 'f4.o'])
#scons -Q
cc -o f1.o -c f1.c
cc -o f3.o -c f3.c
ar rc libfoo.a f1.o f2.o f3.o f4.o
ranlib libfoo.a

例7:建立静态和动态库:
静态库:其实使用Library也是建立静态库。
StaticLibrary('foo', ['f1.c', 'f2.c', 'f3.c'])
动态库:
SharedLibrary('foo', ['f1.c', 'f2.c', 'f3.c'])

% scons -Q
cc -o f1.os -c f1.c
cc -o f2.os -c f2.c
cc -o f3.os -c f3.c
cc -o libfoo.so -shared f1.os f2.os f3.os

例8:使用静态和动态库:
使用$LIBS 来指定库,使用$LIBPATH 指定库位置。
Library('foo', ['f1.c', 'f2.c', 'f3.c'])
Program('prog.c', LIBS=['foo', 'bar'], LIBPATH='.')
% scons -Q
cc -o f1.o -c f1.c
cc -o f2.o -c f2.c
cc -o f3.o -c f3.c
ar rc libfoo.a f1.o f2.o f3.o
ranlib libfoo.a
cc -o prog.o -c prog.c
cc -o prog prog.o -L. -lfoo -lbar


Program('prog.c', LIBS = ['m'], LIBPATH = ['/usr/lib', '/usr/local/lib'])
% scons -Q
cc -o prog.o -c prog.c
cc -o prog prog.o -L/usr/lib -L/usr/local/lib -lm




以BTX为例使用scons:
Sam 创建了一个SConstruct,(类似于GNU make的Makefile文件,是scons的默认文件名).

Sam首先想生成 BTX library.
然后想将library 和 main.c和成一个可执行文件:BTX_Test
内容如下:
#指定生成文件名为:libBTX.a. 由BTX.c生成的。-I'/opt/hisilicon/toolchains/arm-uclibc-linux-soft/include -I../include
StaticLibrary('BTX', ['BTX.c'], CPPPATH=['/opt/hisilicon/toolchains/arm-uclibc-linux-soft/include', '../include'])
Program('BTX_Test', ['main.c'], CPPPATH=['/opt/hisilicon/toolchains/arm-uclibc-linux-soft/include', '../include'], LIBS=['BTX','blu\etooth','pthread'], LIBPATH=['.', '/usr/lib'])

#scons
提示之不到bluetooth库,Sam在 /usr/lib中将 libbluetooth.so 软连接到libbluetooth.so.2。
于是编译成功,所以,Sam觉得Scons和 Makefile很类似,只需要编译时指定-I ,-L, -l就好了。对应关系如下:
-I:CPPPATH=['/opt/hisilicon/toolchains/arm-uclibc- linux-soft/include', '../include']
-L:LIBPATH=['.', '/usr/lib']
-l: LIBS=['BTX','bluetooth','pthread']
CPPPATH,LIBPATH,LIBS,CC等从:
http://www.scons.org/doc/1.2.0/HTML/scons-user/a4774.html#cv-CPPPATH 中找到
同时请注意,最好在每个关键字赋值后面都跟 [],里面有多个时用逗号分开。


X5 Version:
StaticLibrary('BTX', ['BTX.c'], CC=['/opt/hisilicon/toolchains/arm-uclibc-linux-soft/bin/arm-uclibc-linux-gcc'], CPPPATH=['/opt/his\ilicon/toolchains/arm-uclibc-linux-soft/include', '../include'])
Program('BTX_Test', ['main.c'], CC=['/opt/hisilicon/toolchains/arm-uclibc-linux-soft/bin/arm-uclibc-linux-gcc'], CPPPATH=['/opt/his\ilicon/toolchains/arm-uclibc-linux-soft/include', '../include'], LIBS=['BTX','bluetooth','pthread'], LIBPATH=['./', '../resource/']\)



scons只需要描述任务,并不需要指定依赖关系,甚至我们都没有指出头文件,但是你修改BTX.h的时候仍然会触发构建。这是因为scons内部有个scanner,可以帮助扫描包含文件的关系。
我们还发现,这里我们根本没有指定编译器,也没有指定编译选项,但scons仍然很聪明的选择了gcc. 这是因为scons内置提供了很多编译器及其对应选项的选择,然后对于不同的平台,会有一个默认项。



Environments:
Scons有3种环境变量:
1. External Environment
2. Construction Environment
3. Execution Environment

当想要使用External Environment,必须通过os.environ。这意味着首先要加入:
import os
之后就可以在SConscript文件中使用os.environ来初始化 construction environments 为用户环境变量了。

1.创建Construction Environment
env = Environment()

例如:
import os
env = Environment(CC = 'gcc', CCFLAGS = '-O2')
env.Program('foo.c')



最重要的环境变量是:Construction Environment
它在复杂的工程中非常重要,例如,不同的源文件需要不同的编译选项。或者不同的可执行程序需要链接不同的库。scons提供Construction Environment。让我们可以创建不同的Construction Environment来创建不同的编译选项。

1. 创建Construction Environment ,使用Environment function。
env = Environment() 所有的Construction Environment 项目值全用scons自己找到的。
env = Environment(CC = 'gcc', CCFLAGS = '-O2') ,其他的与上一个相同,但只有CC和CCFLAGS 自定义。

2. 察看Construction Environment 每个项目值:注[1]
需要使用Dictionary() function
env = Environment()
dict = env.Dictionary()
keys = dict.keys()
keys.sort()
for key in keys:
print "construction variable = '%s', value = '%s'" % (key, dict[key])
打印所有Construction Environment项目。








scons中Python模块的导入:
1. import os
os 模块包含普遍的操作系统功能。如果你希望你的程序能够与平台无关的话,这个模块是尤为重要的。即它允许一个程序在编写后不需要任何改动,也不会发生任何问题,就可以在Linux和Windows下运行。一个例子就是使用os.sep可以取代操作系统特定的路径分割符。


os.name 字符串指示你正在使用的平台。比如对于Windows,它是'nt',而对于Linux/Unix用户,它是'posix'。
os.getcwd() 函数得到当前工作目录,即当前Python脚本工作的目录路径。
os.getenv()和os.putenv()函数分别用来读取和设置环境变量。
os.listdir()返回指定目录下的所有文件和目录名。
os.remove()函数用来删除一个文件。
os.system() 函数用来运行shell命令。
os.linesep字符串给出当前平台使用的行终止符。例如,Windows使用'\r\n',Linux使用' \n'而Mac使用'\r'。
os.path.split()函数返回一个路径的目录名和文件名。
os.environ Shell variables
这里重点说os.environ:
它应该是Linux环境变量。

例 1:
想要得到当前Linux环境变量 PATH,LD_LIBRARY_PATH,HOME等。(这与前面讲的环境变量对应起来了)

#导入OS模块
import os
#创建一个Construction Environment
env=Environment()
print "HOME: ", os.environ["HOME"]
则打印结果为HOME:/home/sam。这样就得到了Linux环境变量。

例 2:
想要用当前Linux环境变量ARMGCC来设置toolchain.

首先:在Linux下:
export ARMGCC=arm-linux-gcc

之后,修改config
#导入OS模块
import os
#创建一个Construction Environment
env=Environment()
if os.environ.has_key('ARMGCC'):
env.Replace(CC = os.environ['ARMGCC'])
则使用arm-linux-gcc取代了Construction Environment中的CC。



2. import sys
sys模块包含系统对应的功能.sys模块包含了与Python解释器和它的环境有关的函数.
import sys
if sys.byteorder == 'little' or env['PLATFORM'] == 'win32':
env.Append(CPPDEFINES = ['LSB_FIRST'])


3. import platform
platform得到编译信息:
platform.processor() ---i686
platform.python_build()---('r251:54863', 'Jun 4 2007 15:03:52')
platform.python_compiler()----'GCC 3.4.4 20050721 (Red Hat 3.4.4-2)'
platform.python_version()----'2.5.1'
platform.release()----'2.6.9-22.ELsmp'
platform.system()----'Linux'
platform.version()----'#1 SMP Mon Sep 19 18:32:14 EDT 2005'
platform.uname()----('Linux', 'nec', '2.6.9-22.ELsmp', '#1 SMP Mon Sep 19 18:32:14 EDT 2005', 'i686' , 'i686')
platform.machine()----'i686'
platform.libc_ver()----('glibc', '2.0')




注[1]:
所有Construction Variables可以在下面找到:
Construction Variables可用在:
1. CPPPATH,LIBS,LIBPATH。(在BTX例子中可见)
2. Construction Environment(env=Environment)中的项目。

Appendix A. Construction Variables

分享到:
评论

相关推荐

    scons 2.4.0 用户指南

    《SCons 2.4.0 用户指南》是针对该版本...通过学习和理解这些知识点,开发者能够充分利用SCons 2.4.0的特性,提高软件构建的效率和灵活性,同时降低维护成本。无论是大型项目还是小型工程,SCons都能提供强大的支持。

    scons-mdk.zip

    《使用SCons构建MDK工程:从源码到串口通信》 ...通过学习和实践这个示例,开发者可以提升构建效率,减少手动操作带来的错误,同时也能更好地理解和利用SCons的高级功能,为自己的嵌入式项目带来更高效的开发流程。

    scons指南中文翻译

    尽管SCons的学习曲线可能较陡,因为它需要了解如何调用特定的函数来设置构建过程,但对Python基础熟悉的用户会更容易上手。 SCons用户指南分为多个部分,详细介绍了如何使用SCons进行构建和安装。首先,指南涵盖了...

    scons2.5.0用户手册

    SCons是一个开源的构建工具,它被设计为更加灵活的替代传统构建工具如make。SCons使用Python语言编写脚本来定义构建规则,这种方式使得构建...通过用户手册,用户可以高效地学习如何使用SCons来进行项目构建和管理。

    scons2-2-0

    在学习和使用SCons的过程中,理解其基本概念如Builder、Environment、Target和Source是很关键的。Builder定义了如何处理特定类型的文件,Environment包含了编译和链接的设置,而Target和Source分别代表了生成的目标...

    scons-2.4.0.zip

    此外,SCons社区提供的文档和在线资源也是学习和解决问题的重要途径。 总的来说,SCons是一个强大且灵活的自动化构建工具,尤其适合处理大型、跨平台的项目。通过熟练掌握SCons,开发者可以提高构建效率,减少手动...

    scons-3.0.5.zip

    通过深入学习SCons的API和文档,你可以定制自己的构建流程,以适应各种复杂的需求。 总之,SCons是一个强大且灵活的构建工具,它的Python基础使其易于学习和扩展。在Windows环境下,"scons-3.0.5.zip"为你提供了一...

    scons脚本文档

    通过学习SCons的API、Man、Usr和Design文档,开发者可以有效地管理和优化他们的软件构建流程,提高开发效率,减少错误,实现跨平台的无缝构建。对于任何使用SCons的团队来说,掌握这些知识都是至关重要的。

    自动化编译工具scons简介

    与传统的Make、CMake等构建工具相比,SCons在易用性、跨平台性和灵活性方面具有显著优势,但可能对不熟悉Python的开发者来说学习曲线稍陡峭。 总结,SCons作为一个强大的自动化编译工具,通过其Python基础、跨平台...

    scons-2.3.3.tar.gz

    《SCons:构建自动化工具详解》 在软件开发过程中,构建工具起着至关...通过学习和掌握SCons,开发者可以更高效地管理和构建自己的项目,特别是对于像jsoncpp这样需要编译的库,SCons能简化整个流程,提高开发效率。

    scons-user.pdf

    SCons是一个基于Python的软件构建工具,它提供了一种简单、灵活且可扩展的方式来自动化编译过程。与传统的构建工具如Make相比,SCons通过定义一...对于希望深入学习和掌握SCons的用户,这份指南无疑是一个宝贵的资源。

    Scons使用手册

    总的来说,SCons是一个功能强大的构建系统,它既适合新手快速学习和使用,又能满足高级用户构建复杂工程的需求。通过使用Python脚本语言和声明式的构建规则,SCons为软件开发人员提供了一种更简单、更高效、更灵活的...

    scons-2.3.1.tar.gz

    3. **Python语法**:SCons使用Python语法,使得构建脚本更易理解和维护,而Makefile的语法较为复杂,学习曲线较陡峭。 三、SCons在OpenWRT中的应用 OpenWRT是一个高度模块化的、小巧的Linux发行版,广泛应用于...

    scons-2.5.1.tar.gz

    《SCons:构建自动化工具详解》 SCons,全称为Software Construction Tool,是一个开源的、跨平台的构建自动化...通过学习和熟练掌握SCons,开发者能够更好地管理和控制软件的构建流程,减少手动操作,提升工作效率。

    scons-2.1.0.tar.gz

    此外,SCons的社区活跃,提供了丰富的教程和文档,使得学习和解决问题变得相对容易。对于初学者,可以通过官方文档和示例项目来快速上手。 总的来说,SCons作为一个强大的构建工具,不仅简化了构建过程,还提高了...

    SCons 2.3.6用户指南 英文

    SCons的构建过程是基于Python脚本的,也就是说,SCons的构建脚本实际上是一个Python程序,这就意味着用户可以利用Python强大的功能来编写构建脚本,包括条件语句、循环和函数等,而不需要学习和使用特定于SCons的...

    scons api手册文档

    SCons(Software Construction Tools)是一个开源的构建工具,它使用Python语言编写,用于替代传统的构建系统...通过深入学习和应用这些知识,开发者可以高效地构建跨平台的软件项目,并实现自动化、可扩展的构建流程。

    新一代编译软件scons

    通过SCons,开发者可以利用熟悉的Python语法来定义构建规则,这极大地降低了学习成本并提高了生产力。 #### SCons的主要特性 1. **使用Python作为配置语言**:SCons使用Python编写构建脚本,这意味着开发者可以...

    Scons用户手册V4.3.0

    通过学习SCons用户手册,开发者能够掌握构建大型复杂项目的技巧,充分利用SCons的灵活性和强大功能,提高软件开发的效率和质量。手册还会提供详尽的示例和最佳实践,帮助读者理解和应用SCons的各个方面。

Global site tag (gtag.js) - Google Analytics