第四章 編譯鏈接庫(kù)文件
? 大型軟件工程一般都是由很多庫(kù)文件構(gòu)成柒爸,采用SCons編譯庫(kù)文件是一件非常簡(jiǎn)單的事情。
4.1 編譯庫(kù)文件
? 您只需要采用Library的構(gòu)建方法代替Program即可:
Library('foo', ['f1.c', 'f2.c', 'f3.c'])
? SCons會(huì)自動(dòng)根據(jù)系統(tǒng)來(lái)創(chuàng)建合適的庫(kù)文件前綴和后綴晕翠,因此在POSIX或者Linux系統(tǒng)上嘹朗,上述示例將會(huì)構(gòu)建以下內(nèi)容(ranlib可能在某系系統(tǒng)中不會(huì)被調(diào)用):
> 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
? 在Windows系統(tǒng)中皱炉,編譯輸出將會(huì)如下所示:
C:\>scons -Q
cl /Fof1.obj /c f1.c /nologo
cl /Fof2.obj /c f2.c /nologo
cl /Fof3.obj /c f3.c /nologo
lib /nologo /OUT:foo.lib f1.obj f2.obj f3.obj
? 目標(biāo)文件的構(gòu)建規(guī)則和Program方法類似呢撞,如果你不特別指定目標(biāo)庫(kù)文件名稱,SCons將會(huì)從源文件列表中選擇第一個(gè)作為庫(kù)文件名稱条获,同時(shí)SCons還會(huì)自動(dòng)給庫(kù)文件加入前綴和后綴忠荞。
4.1.1 通過(guò)源文件或中間文件編譯
? 上述示例介紹了通過(guò)源文件列表構(gòu)建庫(kù)文件,SCons同樣也支持通過(guò)中間文件構(gòu)建帅掘,或者源文件和中間文件混在一起構(gòu)建也可以委煤。
Library('foo', ['f1.c', 'f2.o', 'f3.c', 'f4.o'])
? 同時(shí)SCons也會(huì)意識(shí)到,只有源文件才需要進(jìn)一步構(gòu)建成中間文件:
> 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
? 當(dāng)然修档,無(wú)論源文件還是中間文件碧绞,要想構(gòu)建成功,它們都必須真實(shí)存在吱窝。下一章節(jié)將會(huì)進(jìn)一步介紹關(guān)于Node Objects的相關(guān)內(nèi)容讥邻。
4.1.2 構(gòu)建靜態(tài)庫(kù)文件:StaticLibrary方法
? Library構(gòu)建方法構(gòu)建的是傳統(tǒng)靜態(tài)庫(kù),如果您想特別聲明構(gòu)建的是靜態(tài)庫(kù)文件院峡,則可以通過(guò)調(diào)用StaticLibrary來(lái)進(jìn)一步顯示聲明:
StaticLibrary('foo', ['f1.c', 'f2.c', 'f3.c'])
? 對(duì)于Library和StaticLibrary兴使,他們完全等價(jià),沒(méi)有任何區(qū)別照激。
4.1.3 構(gòu)建動(dòng)態(tài)庫(kù)文件(DLL):SharedLibrary方法
? 如果您想構(gòu)建動(dòng)態(tài)庫(kù)文件(POSIX系統(tǒng)发魄, WINDOWS系統(tǒng)是DLL文件),您可以采用SharedLibrary方法:
SharedLibrary('foo', ['f1.c', 'f2.c', 'f3.c'])
? 在POSIX系統(tǒng)上的輸出為:
> 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
? 在Windows系統(tǒng)上輸出為:
C:\>scons -Q
cl /Fof1.obj /c f1.c /nologo
cl /Fof2.obj /c f2.c /nologo
cl /Fof3.obj /c f3.c /nologo
link /nologo /dll /out:foo.dll /implib:foo.lib f1.obj f2.obj f3.obj
RegServerFunc(target, source, env)
embedManifestDllCheck(target, source, env)
? SCons在構(gòu)建時(shí)俩垃,會(huì)自動(dòng)添加-shared(POSIX)或者/dll(Windows系統(tǒng))編譯選項(xiàng)励幼,以保證編譯的正確性。
4.2 鏈接庫(kù)文件
? 鏈接是庫(kù)文件使用的最后一步口柳,您可以通過(guò)指明LIBS變量關(guān)鍵字苹粟,來(lái)指定需要鏈接的庫(kù)文件;通過(guò)指明LIBPATH變量關(guān)鍵字跃闹,來(lái)指定庫(kù)文件的查找路徑:
Library('foo', ['f1.c', 'f2.c', 'f3.c'])
Program('prog.c', LIBS=['foo', 'bar'], LIBPATH='.')
? 請(qǐng)注意嵌削,您不需要特別聲明庫(kù)文件的前綴(如lib),或者后綴(如.a或.lib)辣卒,SCons會(huì)自動(dòng)根據(jù)系統(tǒng)來(lái)查找相關(guān)前綴或后綴掷贾。
? 在POSIX或Linux系統(tǒng)中睛榄,上述編譯過(guò)程如下:
> 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
? 在Windows系統(tǒng)中荣茫,編譯輸出如下:
C:\>scons -Q
cl /Fof1.obj /c f1.c /nologo
cl /Fof2.obj /c f2.c /nologo
cl /Fof3.obj /c f3.c /nologo
lib /nologo /OUT:foo.lib f1.obj f2.obj f3.obj
cl /Foprog.obj /c prog.c /nologo
link /nologo /OUT:prog.exe /LIBPATH:. foo.lib bar.lib prog.obj
embedManifestExeCheck(target, source, env)
? 另外,如果依賴的庫(kù)文件只有一個(gè)场靴,您也可以直接指定LIBS變量啡莉,而不是列表形式:
Program('prog.c', LIBS='foo', LIBPATH='.')
Program('prog.c', LIBS=['foo'], LIBPATH='.')
? 上述兩種寫(xiě)法完全等價(jià)港准。
4.3 查找?guī)煳募篖IBPATH變量
? 默認(rèn)情況下,連接器只會(huì)在系統(tǒng)路徑中查找?guī)煳募中溃琒Cons可以通過(guò)用戶指定的LIBPATH變量浅缸,來(lái)查找用戶定義路徑:
Program('prog.c', LIBS = 'm',
LIBPATH = ['/usr/lib', 'usr/local/lib'])
? 這里推薦使用python的列表(list),因?yàn)閜ython是跨平臺(tái)的魄咕,這要遷移起來(lái)比較方便衩椒。當(dāng)然您也可以將搜索路徑放到一個(gè)字符串中,采用系統(tǒng)指定的分割符分開(kāi)哮兰,如POSIX系統(tǒng)中采用冒號(hào)毛萌,Windows系統(tǒng)中采用分號(hào):
# POSIX
LIBPATH = '/usr/lib:/usr/local/lib'
# Windows
LIBPATH = 'C:\\lib;D:\\lib'
? 請(qǐng)注意,python在Windows路徑中要求采用反斜杠轉(zhuǎn)義符喝滞。
? 當(dāng)鏈接器執(zhí)行時(shí)阁将,SCons會(huì)自動(dòng)創(chuàng)建合適的標(biāo)志,以便在和工程文件相同目錄下查找右遭,在POSIX或Linux系統(tǒng)中做盅,上述示例編譯輸出如下:
> scons -Q
cc -o prog.o -c prog.c
cc -o prog prog.o -L/usr/lib -L/usr/local/lib -lm
? 在Windows系統(tǒng)中,輸出如下:
C:\>scons -Q
cl /Foprog.obj /c prog.c /nologo
link /nologo /OUT:prog.exe /LIBPATH:\usr\lib /LIBPATH:\usr\local\lib m.lib prog.obj
embedManifestExeCheck(target, source, env)
? 整體而言窘哈,SCons會(huì)自動(dòng)根據(jù)系統(tǒng)不同吹榴,而創(chuàng)建不同的編譯選項(xiàng),以保證編譯輸出的正確性滚婉。