原来简单介绍了一种项目自动编译的工具cmake,不过它基本是针对与c++程序而设计的,我感觉cmake已经很方便了,比写Makefile要舒服多了,最近又看到一个scons,瞬间感觉scons才是真爱啊。
scons简介
SCons 是一个开放源代码、以 Python 语言编写的下一代的程序建造工具。它最初的名字是 ScCons, 基于由 perl 语言编写的 Cons 软件开发而成,它在 2000 年 8 月获得了由 Software Carpentry 举办的 SC 建造比赛的大奖。现在 ScCons 已经被改名为 SCons,目的是为了表示不再与 Software Carpentry 有联系,当然,还有一个目的,就是为了更方便的输入。
使用
先安装:
最简单的:
sudo apt-get install scons
当然你也可以去下载压缩包再自己安装。
一,SConstruct 文件
它是scons用来控制编译的文件,类似MakeFile,是一个Python脚本,它告诉scons做什么,而不是严格的规定scons做这件事的步骤。
二,scons 运行选项
运行:scons
1,-c 就是清理你创建的文件,就是make clean
2, -Q 就是省略自带的一堆废话,只显示编译过程
三,SConstrcut文件编写基础
1.scons支持的编译类型
scons支持的编译类型有
Program: 编译成可执行程序
Object :只编译成目标文件,使用这种类型,编译结束后,只会产生目标文件,.o文件。
Library :编译成库文件,scons默认编译的库是指静态链接库
StaticLibrary :显式的编译成静态链接库,与上面的Library效果一样
SharedLibrary :编译成动态库
2.指定目标名,且编译多个文件
Program('hello',['file.c','file2.c']), //生成可执行文件hello
3.可以使用Glob编译所有匹配的文件
Program('hello',Glob('*.c')),
4.使用Split,以空白字符为分割符,将字符串分割。
Program('hello',Split("main.c file1.c file2.c")),
5.文件中的关键字
CCFLAGS 指定编译选项
LINKFLAGS 指定链接选项
CPPDEFINES指定预编译器
LIBS 指定所需要链接的库文件
LIBPATH 指定库文件(lib)的搜索路径
CPPPATH 指定[.h,.c,.cpp]等文件的搜素路径
Program('hello',['hellosons.c','file.c'],
LIBS = 'pthread',
LIBPATH = ['/usr/lib','/usr/local/lib'],
CCFLAGS = ['-g ','-Wall'],
CPPPATH = ['/usr/include','hello/src'])
6.使用Environments
一个environment是一个影响程序执行的值的集合。
外部环境 External Environment
外部环境是运行Scons时,用户的环境变量,他们可以通过os.environ获取
6.1.构建环境
Construction Environment :它包含一些变量,这些变量会影响Scons构建目标的行为。
env = Environment() //创建,(name,value)集合
for item in env.Dictionary():
print '(%s:%s)' %(item,env[item]) //查看内容
env['cc'] //查看变量
env.subst('$CC') //查看变量,如果subset变量不存在时报告错误。
//修改环境变量
env.Clone //拷贝一个环境变量
env.Replace //替换一个已经存在的环境变量
env.SetDefault //为一个没有被定义的变量设置默认值
env.Append(CCFLAGS = '-g') //为一个已存在的环境变量增加一个值
env.AppendUnique //为一个环境变量添加一个唯一的值
flags = {'CCFLAGS':'-option -O3 -O1'}
env.MergeFlags(flags) //合并环境变量
6.2.执行环境
Execution Environment:用于Scons执行外部命令,以构建一个或多个目标。当Scons构建一个目标文件时,它说使用的外部环境和执行Scons 时的环境变量是不同的。scons 使用$ENV构建变量中存储的目录作为它执行命令的外部环境变量
//在构建环境中显示初始化PATH
path = ['usr/local/bin','/bin','/usr/bin']
env = Environment(ENV = {'PATH':path}) //只设置了ENV
env['ENV']['PATH'] = ['usr/local/bin','/bin','/usr/bin']
//从外部环境初始化PATH
import os
env = Environment(ENV = {'path':os.environ['PATH']})
//使用env.PrependENVPath 和env.AppendENVPath
env.PrependENVPath('PATH','/usr/local/bin') //插入到'$PAHT'第一个位置
7.控制目标文件的路径
使用Install:
test = env.Program('test.cpp')
env.Install('bin',test) //放入到bin目录
在指定目标名的时候指定其目录
env.Program('bin/test','test.cpp')
//将目标放到其他目录下,并修改名字
test = env.Program('test.cpp')
env.InstallAs('bin/testapp',test) //执行文件改为testapp
8.一份代码构建多个版本的Target
一份源码,要构建它的debug版本,又要构建release版本
//需要为不同的版本指定不同的obj名字,否则会冲突
opt = Environment(CCFLAGS ='-O2')
dbg = Environment(CCFLAGS = '-g')
o = opt.Object('foo-opt','foo.c') //生成foo-opt.o
opt.Program(o)
d = dbg.Object('foo-dbg','foo.c') //生成foo-dbg
dbg.Program(d)
这只是一些简单介绍,如果你熟悉Python,就可以随心所欲的编写你要的效果,以前学的python早忘光了。
9.范例参考
这里我贴上实验室的SConstruct文件,大家做个简单参考,我也在学习。
#SConstuct file for Shelf
libs = Split("Ice IceUtil pthread boost_program_options boost_filesystem " +
"boost_regex boost_system pqxx log4cxx dl ENM"),
env = Environment(CCFLAGS = ["-g", "-Wall"],
LINKFLAGS = ["-rdynamic"],
CPPPATH = ["#src", "/usr/local/include/coral"],
LIBS = libs,
SLICEPATH = ["/usr/share/Ice-3.5.1/slice"])
#check library
from SCons.SConf import *
def check_flags():
e = Environment()
conf = Configure(e)
for lib in libs[0]:
if not conf.CheckLib(lib):
print "Can't find library ", lib, " exiting..."
Exit(1)
conf.Finish()
check_flags()
obj = env.Object(["src/ConfigLoader.cpp",
"src/Service.cpp",
"src/Template.cpp",
"src/Resource.cpp",
"src/Persistent.cpp",
"src/Plugin.cpp",
"src/Main.cpp"])
import os
def build_slice2cpp(target, source, env):
cmd = "slice2cpp"
for src in source:
cmd += " " + str(src)
tdir = str(source[0]).rpartition("/")[0]
if tdir:
cmd += " --output-dir " + tdir
if "SLICEPATH" in env:
for path in env["SLICEPATH"]:
cmd += " -I" + path
return os.system(cmd)
builder = Builder(action = build_slice2cpp, src_suffix = ".ice")
env.Append(BUILDERS = {"Slice": builder})
env.Slice(["src/Shelf.h", "src/Shelf.cpp"], "src/Shelf")
ice_obj = env.Object("src/Shelf.cpp")
env.Program("slf", [obj, ice_obj])
Export('env')
SConscript('src/plugins/SConscript')
Export('ice_obj')
SConscript('src/tests/SConscript')