pythonscons
A. scons 怎麼忽視某個.c文件
介紹,scons用的是python語法。需要安裝python和scons後才能運行,能夠跨平台。比較automake自動生成makefile文件,scons可以認為直接是make的功能,因為只需要執行scons命令就等於執行了make的功能。
現在有一個hello.c的文件。
新建一個SConstruct文件,是一個python腳本文件。
Program('hello.c') 編譯hello.c並生成.o文件和可執行文件
Object('hello.c') 編譯hello.c但只生成生成.o文件
這兩個方法都是python的method。
如果想執行clean操作,我們不需要再象makefile那樣指名make clean語句,而是直接執行scons -c 或者scons -clean就可以。程序會根據SConstruct文件內容自動清除。
SConstruct的讀取和執行順序是彼此獨立的,直接看以下例子。
SConstruct文件內容:
print "Calling Program('hello.c')"
Program('hello.c')
print "Calling Program('goodbye.c')"
Program('goodbye.c')
print "Finished calling Program()"
B. 請教Scons python 編譯問題
一、概述
scons是一個Python寫的自動化構建工具,和GNU make相比優點明顯:
1、移植性:python能運行的地方,就能運行scons
2、擴展性:理論上scons只是提供了python的類,scons使用者可以在這個類的基礎上做所有python能做的事情。比如想把一個已經使用了Makefile大型工程切換到scons,就可以保留原來的Makefile,並用python解析Makefile中的編譯選項、源/目標文件等,作為參數傳遞給scons,完成編譯。
3、智能:Scons繼承了autoconf/automake的功能,自動解析系統的include路徑、typedef等;「以全局的觀點來看所有的依賴關系」
二、scons文件
scons中可能出現的文件:
SConstruct,Sconstruct,sconstruct,SConscript
scons將在當前目錄以下次序 SConstruct,Sconstruct,sconstruct 來搜索配置文件,從讀取的第一個文件中讀取相關配置。
在配置文件SConstruct中可以使用函數SConscript()函數來定附屬的配置文件。按慣例,這些附屬配置文件被命名為」SConscript」,當然也可以使用任意其它名字。
三、scons的命令行參數
scons: 執行SConstruct中腳本
scons -c clean
scons -Q 只顯示編譯信息,去除多餘的列印信息
scons -Q --implicit-cache hello 保存依賴關系
--implicit-deps-changed 強制更新依賴關系
--implicit-deps-unchanged 強制使用原先的依賴關系,即使已經改變
四、SConstruct提供的方法
1、Program:生成可執行文件
Program('hello.c') 編譯hello.c可執行文件,根據系統自動生成(hello.exe on Windows; hello on POSIX)
Program('hello','hello.c') 指定Output文件名(hello.exe on Windows; hello on POSIX)
Program(['hello.c', 'file1.c', 'file2.c']) 編譯多個文件,Output文件名以第一個文件命名
Program(source = "hello.c",target = "hello")
Program(target = "hello" , source = "hello.c")
Program('hello', Split('hello.c file1.c file2.c')) 編譯多個文件
Program(Glob("*.c"))
src = ["hello.c","foo.c"];Program(src)
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
庫的使用:
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內容如下:
[cpp]view plain
subobj=SConscript(['mA/SConscript'])
obj=subobj+Object(Glob("*.cpp"))
Program("test",list(obj))
- SConscript內容 :
obj=Object(Glob("*.cpp"))
Return("obj")
- 上例中,在主目錄中執行 scons就可以編譯整個"工程"。SConstruct編譯主目錄中的test.cpp,並通過SConscript編譯mA目錄下的源文件,並最終生成可執行文件;SConscript用於編譯mA中的func.cpp並把生成的func.o傳遞給主目錄的SConstruct。
env=Environment()
dict=env.Dictionary()
keys=dict.keys()
keys.sort()
forkeyinkeys:
print"constructionvariable='%s',value='%s'"%(key,dict[key])
- 環境變數的使用:
- env = Environment() #創建默認的環境變數,默認scons會按編譯器的默認選項來進行編譯
- import os
- env = Environment(CC = 'gcc',CCFLAGS = '-O2') #創建並設置環境 變數
- env.Program('foo.c')
env=Environment()
flags=env.ParseFlags(['-pthread-I/usr/include/stlport','-L.'])
env.MergeFlags(class_flags)
subobj=SConscript(['mA/SConscript'])
obj=subobj+env.Object(Glob("*.cpp"))
env.Program("test",list(obj),LIBS=['libstlport.a'])
obj=Object(Glob("*.cpp"))
Return("obj")
env=Environment()
flags=env.ParseFlags(['-pthread-I/usr/include/stlport','-L.'])
env.MergeFlags(class_flags)
Export('env')
subobj=SConscript(['mA/SConscript'],exports='env')
obj=subobj+env.Object(Glob("*.cpp"))
env.Program("test",list(obj),LIBS=['libstlport.a'])
- mA/SConscript:
[cpp]view plain
10.env:環境變數
環境變數用於設置在編譯過程中的各種參數,可以用下面的SConstruct列印環境變數的所有信息(實際上env就是一個python字典)
可以使用如下的SConstruct查看環境變數的內容:
[cpp]view plain
環境變數的復制:
env = Environment(CC = 'gcc')
opt = env.Clone(CCFLAGS = '-O2')
dbg = env.Clone(CCFLAGS = '-g')
環境變數的替換:
env = Environment(CCFLAGS = '-DDEFINE1')
env.Replace(CCFLAGS = '-DDEFINE2')
env.Program('foo.c')
環境變數的輸入輸出:用於統一多目錄源文件的編譯選項,如:
src:
| SConstruct
| libstlport.a
| test.cpp
| include(目錄):
| foo.h
| mA(目錄):
| SConscript
|func.cpp
test.cpp和mA/func.cpp都引用了include/foo.h,test.cpp調用了mA/func.cpp的功能函數,其中include/foo.h中定義了一個包含string類型的類。
SConstruct如下:
[cpp]view plain
mA/SConscrip如下:
[cpp]view plain
不出意外的話上邊的工程編譯可以通過,但是運行的時候會Aborted。因為test.cpp,mA/func.cpp都使用了包含string類型的那個類,但是由於編譯環境的不同,test.cpp認為string變數的大小是24位元組, mA/func.cpp認為string變數的大小是4個位元組(libstlport.a搗的鬼)。
解決問題的辦法就是環境變數輸出,修改SConstruct和mA/SConscript如下:
SConstruct:
[cpp]view plain