SCons 第三章 簡化構建過程

第三章 簡化構建過程

? 在本章節(jié)中兼雄,通過幾個簡單的SCons工程構建示例疑苔,向您展示無論是哪種編程語言规丽,亦或哪種系統(tǒng)平臺份企,軟件構建都將會是一件非常簡單的事情也榄。

3.1 指定編譯輸出文件

? 當調用Program構建方法時,它會構建和源代碼文件(多份則采取第一個文件)相同名稱的輸出文件司志,因此如果源代碼是hello.c甜紫,則構建出來的可執(zhí)行文件則為hello(POSIX平臺)降宅,或者hello.exe(WINDOWS平臺)。

Program('hello.c')

? 如果您想編譯出不同名稱的可執(zhí)行文件囚霸,則需要在源文件的前面腰根,指明輸出名稱即可(如new_hello):

Program('new_hello', 'hello.c')

? (Scons需要先指明目標文件名稱,后面才是源文件邮辽,這樣做的目的是和大多數(shù)的編程語言保持一致唠雕,python也是如此:“program = source files”)

? 現(xiàn)在執(zhí)行scons指令則會得到new_hello的編譯輸出:(POSIX平臺)

> scons -Q
cc -o hello.o -c hello.c
cc -o new_hello hello.o

? 得到new_hello.exe的編譯輸出:(WINDOWS平臺)

C:\> scons -Q
cl /Fohello.obj /c hello.c /nologo
link /nologo /OUT:new_hello.exe hello.obj
embedManifestExeCheck(target, source, env)

3.2 編譯多個源文件

? 現(xiàn)在知道了如何編譯單個源文件,但是大多數(shù)情況下吨述,需要構建的工程岩睁,是由多個源文件構成,而非單一文件揣云,因此多源文件編譯時捕儒,需要將文件名放入一個python列表(list)中:

Program(['prog.c', ['file1.c', 'fil2.c'])

? 編譯輸出為:(POSIX平臺)

> 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 prog prog.o file1.o file2.o

? (WINDOWS平臺)

C:\>scons -Q
cl /Fofile1.obj /c file1.c /nologo
cl /Fofile2.obj /c file2.c /nologo
cl /Foprog.obj /c prog.c /nologo
link /nologo /OUT:program.exe prog.obj file1.obj file2.obj
embedManifestExeCheck(target, source, env)

3.3 采用Glob創(chuàng)建列表

? 您也可以采用Glob函數(shù)匹配所有符合條件的源文件,匹配原則采用標準腳本通配符“*”邓夕,“?”刘莹。[abc]將匹配a,b,c;[!abc]將匹配除abc意外的任意字符焚刚。這使得多個源文件的構建變得簡單了很多点弯。

Program('program', Glob('*.c'))

? SCons的幫助手冊有更多關于Glob函數(shù)的具體用法細節(jié),可以參考矿咕。

3.4 單一文件構建 VS 文件列表構建

? 構建工程目前有兩種形式抢肛,一種是采用文件列表,一種是采用單一文件直接構建的方式:

# 文件列表
Program('hello', ['file1.c', 'file2.c'])

# 單一文件
Program('hello', 'hello.c')

? 當然您也可以在文件列表中碳柱,只存儲一份文件:

Program('hello', ['hello.c'])

? 其實SCons內(nèi)部都是將源文件以列表的形式存儲捡絮,只是為了方便起見,允許用戶直接輸入單一文件莲镣。

重要提示

? 盡管SCons支持多種輸入方式福稳,但是python語言更為嚴格,因此在進行l(wèi)ist和string格式的文件相加則會產(chǎn)生python語法錯誤:

common_sources = ['file1.c', 'file2.c']
# 下述代碼將會報錯瑞侮, string和list相加
Program('program1', common_sources + 'program1.c')
# 下述代碼正確的圆, list與list相加
Program('program2', common_sources + ['program2.c'])

3.5 讓列表文件易于讀寫

? 對于文件列表而言,其缺點是每一個文件名稱都需要用引號包起來区岗,無論是單引號還是雙引號略板,當列表比較長時,看起來都比較麻煩慈缔。SCons提供了很多工具函數(shù)使得這一工作變得很簡單叮称。

? SCons提供了Split函數(shù)用于分割字符串文件中的一個或多個空格,亦或一個或多個tab,分割后以文件列表的形式存儲:

Program('program', Split('main.c file1.c file2.c'))

? (如果您熟悉python的話瓤檐,您會發(fā)現(xiàn)這和python標準字符串string模板的split()函數(shù)很相似赂韵,但是和split()不同的是,Split()不需要輸入一定為string挠蛉,其他輸入也可以(如列表)祭示,它會自動將其進行分割成列表,確保輸出格式的正確性谴古。)

? 直接將Split()函數(shù)嵌入到Program中质涛,顯得比較粗魯,可以進一步采用臨時變量增加代碼的可讀性:

src_files = Split('main.c file1.c file2.c')
Program('program', src_files)

? 最后掰担,Split函數(shù)不關系輸入中有多少個空格汇陆,因此您可以跨行編輯列表,進一步提高可讀性:

src_file = Split("""" main.c
                      file1.c 
                      file2.c""")
Program('program', src_files)

? 請注意带饱,在此示例中毡代,我們使用了Python的“三重引用”語法,該語法允許一個字符串包含多行勺疼。三個引號可以是單引號或雙引號教寂。

3.6 關鍵字參數(shù)

? SCons同樣支持輸入或輸出文件的關鍵字定義。輸出文件的關鍵字是target执庐,輸入源文件的關鍵字是source:

src_files = Split('main.c file1.c file2.c')
Program(target='program', source=src_files)

? 因為關鍵字已經(jīng)指明了該參數(shù)的含義酪耕,因此關鍵字的順序不做要求:

src_files = Split('main.c file1.c file2.c')
Program(source=src_files, target='program')

? 是否選擇使用關鍵字,以及采用關鍵字時的順序指定轨淌,這些都是是個人喜好因妇,SCons不做特殊要求。

3.7 編譯多個工程

? 如果您想采用同一個SConstruct文件猿诸,構建多個工程,最簡單的方式是調用Program多次構建:

Program('foo.c')
Program('bar', ['bar1.c', 'bar2.c'])

? SCons則會輸出如下:

> scons -Q
cc -o bar1.o -c bar1.c
cc -o bar2.o -c bar2.c
cc -o bar bar1.o bar2.o
cc -o foo.o -c foo.c
cc -o foo foo.o

? 請注意狡忙,SCons不一定按照您在SConstruct文件中指定程序的順序來構建梳虽。 但是,SCons確實認識到必須先構建各個目標中間文件灾茁,然后才能構建最終輸出程序窜觉。

3.8 多工程編譯共享中間文件

? 代碼復用是常見的編程方式,創(chuàng)建庫文件(動態(tài)或靜態(tài)庫)是廣為人知的一種方式北专。具體庫文件的創(chuàng)建參見后續(xù)章節(jié)禀挫。

? 同一份源碼文件對應多個工程,最直接的方式是每個工程都加入該源碼:

Program(Split('foo.c common1.c common2.c'))
Program('bar', Split('bar1.c bar2.c common1.c common2.c'))

? 當采用這種方式構建時拓颓,SCons會意識到common1.c和common2.c的復用语婴,因此會將其僅僅編譯一份中間文件,盡管生成的目標文件分別鏈接到各自的中間文件:

% scons -Q
cc -o bar1.o -c bar1.c
cc -o bar2.o -c bar2.c
cc -o common1.o -c common1.c
cc -o common2.o -c common2.c
cc -o bar bar1.o bar2.o common1.o common2.o
cc -o foo.o -c foo.c
cc -o foo foo.o common1.o common2.o

? 如果兩個或多個程序共享許多公共源文件,則可以將公共源文件創(chuàng)建為一個列表砰左,以便維護和更改匿醒。同時采用python的+運算符進行其他列表的擴充:

common = ['common1.c', 'common2.c']
foo_files = ['foo.c'] + common
bar_files = ['bar1.c', 'bar2.c'] + common
Program('foo', foo_files)
Program('bar', bar_files)

? 這和前面的寫法是完全等價的。

3.9 構建方法參數(shù)的覆蓋

? 您也可以通過在構建方法(如Program等)中增加對應參數(shù)缠导,或關鍵字參數(shù)廉羔,來指定相關的參數(shù),最終參數(shù)會以此為準僻造。

env.Program('hello', 'hello.c', LIBS=['gl', 'glut'])

? 或者生成一個非標準后綴的動態(tài)庫:

env.SharedLibrary('word', 'word.cpp',
SHLIBSUFFIX='.ocx',
LIBSUFFIXES=['.ocx'])

? 您也可以采用parse_flags關鍵字將命令行樣式參數(shù)合并到適當?shù)臉嬙熳兞恐斜锼1纠龑ⅰ痠nclude‘增加到CPPPATH變量中, 將‘EBUG’加入到CPPDEFINES變量中,以及將'm'加入到LIBS變量中:

enc = Program('hello', 'hello.c', parse_flags='-Iinclude -DEBUG -lm')

? 在對構建方法的調用中髓削,不會克隆編譯環(huán)境竹挡,而是通過調用OverrideEnvironment(), 它會創(chuàng)建一個整個Environment()更輕便編譯環(huán)境。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蔬螟,一起剝皮案震驚了整個濱河市此迅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌旧巾,老刑警劉巖耸序,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鲁猩,居然都是意外死亡坎怪,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門廓握,熙熙樓的掌柜王于貴愁眉苦臉地迎上來搅窿,“玉大人,你說我怎么就攤上這事隙券∧杏Γ” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵娱仔,是天一觀的道長沐飘。 經(jīng)常有香客問我,道長牲迫,這世上最難降的妖魔是什么耐朴? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮盹憎,結果婚禮上筛峭,老公的妹妹穿的比我還像新娘。我一直安慰自己陪每,他們只是感情好影晓,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布镰吵。 她就那樣靜靜地躺著,像睡著了一般俯艰。 火紅的嫁衣襯著肌膚如雪捡遍。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天竹握,我揣著相機與錄音画株,去河邊找鬼。 笑死啦辐,一個胖子當著我的面吹牛谓传,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播芹关,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼续挟,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了侥衬?” 一聲冷哼從身側響起诗祸,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎轴总,沒想到半個月后直颅,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡怀樟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年功偿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片往堡。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡械荷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出虑灰,到底是詐尸還是另有隱情吨瞎,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布穆咐,位于F島的核電站关拒,受9級特大地震影響,放射性物質發(fā)生泄漏庸娱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一谐算、第九天 我趴在偏房一處隱蔽的房頂上張望熟尉。 院中可真熱鬧,春花似錦洲脂、人聲如沸斤儿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽往果。三九已至疆液,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間陕贮,已是汗流浹背堕油。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留肮之,地道東北人掉缺。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像戈擒,于是被迫代替她去往敵國和親眶明。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容

  • 一筐高、Python簡介和環(huán)境搭建以及pip的安裝 4課時實驗課主要內(nèi)容 【Python簡介】: Python 是一個...
    _小老虎_閱讀 5,729評論 0 10
  • http://python.jobbole.com/85231/ 關于專業(yè)技能寫完項目接著寫寫一名3年工作經(jīng)驗的J...
    燕京博士閱讀 7,558評論 1 118
  • Python語言特性 1 Python的函數(shù)參數(shù)傳遞 看兩個如下例子搜囱,分析運行結果: 代碼一: a = 1 def...
    時光清淺03閱讀 482評論 0 0
  • Python語言特性 1 Python的函數(shù)參數(shù)傳遞 看兩個如下例子,分析運行結果: 代碼一: a = 1 def...
    伊森H閱讀 3,054評論 0 15
  • 一生中柑土,總有那么幾年蜀肘,要練習一個人生活。有時候需要左支右絀冰单、三頭六臂幌缝,以及十八般武藝。有時候诫欠,很累涵卵。有時候,很孤獨...
    Kainna閱讀 246評論 -1 1