第五章 編譯節(jié)點對象
? 在SCons內(nèi)部絮宁,所有的文件和路徑都被看作是節(jié)點(Nodes)派敷,我們可以采用這種方式讓您的SConscript腳本更加便于遷移和閱讀曼追。
5.1 返回目標(biāo)節(jié)點列表的編譯方法
? 所有的構(gòu)建方法返回一個節(jié)點對象列表押赊,這些節(jié)點可以被用作其他構(gòu)建方法的參數(shù)抠刺。
? 舉例而言,如果我們想要構(gòu)建兩個中間文件阱飘,他們采用不同的編譯參數(shù):
Object('hello.c', CCFLAGS='-DHELLO')
Object('goodbye.c', CCFLAGS='-DGOODBYE')
? 將上述兩個中間文件連接在一起斥杜,構(gòu)建最終的輸出文件,一種方式是將上述輸出中間文件放入一個列表中沥匈,作為Program的參數(shù):
Object('hello.c', CCFLAGS='-DHELLO')
Object('goodbye.c', CCFLAGS='-DGOODBYE')
Program(['hello.o', 'goodbye.o'])
? 這樣做在跨平臺方面會存在問題蔗喂,因為在Windows平臺上,生成的中間文件是hello.obj和goodbye.obj咐熙,而非hello.o和goodby.o弱恒。
? 較好的處理方式是將Object的構(gòu)建輸出存入變量中,這樣我們可以不斷在列表后追加新的內(nèi)容棋恼,將其作為Program的輸入:
hello_list = Object('hello.c', CCFLAGS='-DHELLO')
goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE')
Program(hello_list + goodbye_list)
? 這樣SConstruct腳本的跨平臺性可以得到保證返弹,其在Linux平臺輸出如下:
> scons -Q
cc -o goodbye.o -c -DGOODBYE goodbye.c
cc -o hello.o -c -DHELLO hello.c
cc -o hello hello.o goodbye.o
? Windows平臺輸出如下:
C:\>scons -Q
cl /Fogoodbye.obj /c goodbye.c -DGOODBYE
cl /Fohello.obj /c hello.c -DHELLO
link /nologo /OUT:hello.exe hello.obj goodbye.obj
embedManifestExeCheck(target, source, env)
? 后續(xù)將會介紹更多的編譯節(jié)點的使用方法。
5.2 明確創(chuàng)建文件和路徑節(jié)點
? 值得一提的是爪飘,SCons明確了文件節(jié)點和路徑節(jié)點的不同义起,SCons支持File 和Dir兩個函數(shù),用于返回文件和路徑節(jié)點:
hello_c = File('hello.c')
Program(hello_c)
classes = Dir('classes')
Java(classes, 'src')
? 通常情況下师崎,您不需要手動調(diào)用File或Dir默终,因為調(diào)用構(gòu)建方法時,會自動將輸入作為文件或目錄的名稱犁罩,并將其轉(zhuǎn)換為一個Node對象齐蔽。除非您需要明確SCons的節(jié)點類型,比如在調(diào)用構(gòu)建方法或者需要調(diào)用特殊文件或路徑樹的時候床估。
? 有時候含滴,您可能在無法明確編譯系統(tǒng)環(huán)境的前提下,需要一個輸入丐巫,這可能是文件也可能是一個路徑谈况,此時SCons提供了一個Entry函數(shù)勺美,用于返回一個文件節(jié)點或者路徑節(jié)點。
xyzzy = Entry('xyzzy')
? 這里返回的xyzzy節(jié)點碑韵,將會在其第一次被調(diào)用的時候赡茸,轉(zhuǎn)化為文件節(jié)點或路徑節(jié)點。
5.3 打印節(jié)點文件名稱
? 大多數(shù)情況下我們需要調(diào)用節(jié)點去打印其內(nèi)部的文件名稱祝闻,但是請注意此時的對象是節(jié)點列表占卧,而非文件對象,因此打印的時候需要增加下標(biāo)訪問:
object_list = Object('hello.c')
program_list = Program(object_list)
print("The object file is: %s"%object_list[0])
print("The program file is: %s"%program_list[0])
? 在POSIX系統(tǒng)輸出如下:
> scons -Q
The object files is: hello.o
The program file is: hello
cc - o hello.o -c hello.c
cc -o hello hello.o
? 在Windows系統(tǒng)輸出如下:
C:\>scons -Q
The object file is: hello.obj
The program file is: hello.exe
cl /Fohello.obj /c hello.c /nologo
link /nologo /OUT:hello.exe hello.obj
embedManifestExeCheck(target, source, env)
? 請注意联喘,在上面的示例中屉栓,object_list[0]從列表中提取了一個實際的Node對象,Python的print語句將該對象轉(zhuǎn)換為要打印的字符串耸袜。
5.4 將節(jié)點對象轉(zhuǎn)換為字符串
? 如上節(jié)介紹所示,我們可以直接打印節(jié)點的文件信息牲平,但是如果您想得到一個節(jié)點字符串堤框,而非列表,則可以通過python內(nèi)置的str函數(shù)實現(xiàn)纵柿。舉例而言蜈抓,如果您希望使用Python的os.path.exists來確認(rèn)文件是否存在,您可以采用如下方式:
import os.path
program_list = Program('hello.c')
program_name = str(program_list[0])
if not os.path.exists(program_name):
print("%s doses not exist!"%program_name)
? 此時昂儒,在POSIX系統(tǒng)中將會得到如下輸出:
> scons -Q
hello does not exist!
cc -o hello.o -c hello.c
cc - o hello hello.o
5.5 GetBuildPath: 通過節(jié)點或字符串獲取路徑
? env.GetBuildPath(file_or_list)返回節(jié)點或者字符串(描述路徑)的路徑沟使,當(dāng)然輸入?yún)?shù)也可以是列表,這將會返回路徑的列表信息渊跋。如果輸入是單個節(jié)點的話,則相當(dāng)于調(diào)用了str(node)。字符串參數(shù)可以被初始化在Environment函數(shù)參數(shù)列表中寺旺,此時將會被傳遞到后續(xù)的調(diào)用函數(shù)中:
env = Environment(VAR="value")
n = File("foo.c")
print(env.GetBuildPath([n, "sub/dir/$VAR"]))
? 打印信息如下:
> scons -Q
['foo.c', 'sub/dir/value']
scons: '.' is up to date
? GetBuildPath函數(shù)也可以被默認(rèn)的Environment環(huán)境調(diào)用男窟,而非特殊指定。