原來簡單介紹了一種項目自動編譯的工具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是一個影響程序執行的值的集合。
1,外部環境 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')