第二章 簡單例程
? 本章會介紹幾個簡單的SCons構(gòu)建工程匾竿,以演示使用SCons在不同類型的系統(tǒng)上根據(jù)幾種不同的編程語言來構(gòu)建程序是多么容易币厕。
2.1 構(gòu)建簡單的C/C++程序
? 這是一個C語言版的“Hello, World” (文件名:hello.c):
int main() {
printf("Hello, world!\n");
return 0;
}
? 下面介紹如何使用SCons對其進(jìn)行構(gòu)建。新建一個SConstruct文件埂蕊,輸入一下內(nèi)容:
Program("hello.c")
? 這個簡單的SCons配置描述了兩條信息:工程的構(gòu)建類型(可執(zhí)行文件往弓、庫文件等)和待編譯文件(hello.c)。Program是一種編譯方法蓄氧,告訴SCons需要構(gòu)建一種可執(zhí)行文件函似。
? 就這樣,現(xiàn)在運行scons命令來構(gòu)建整個工程喉童。在POSIX平臺系統(tǒng)上撇寞,例如Linux或UNIX,你將會看到如下輸出:
> scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cc -o hello.o -c hello.c
cc -o hello hello.o
scons: done building targets.
? 在windows平臺堂氯,采用Micosoft Visual C++編譯器蔑担,你將會看到如下輸出:
C:\> scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cl /Fohello.obj /c hello.c /nologo
link /nologo /OUT:hello.exe hello.obj
embedManifestExeCheck(target, source, env)
scons: done building targets.
? 首先,您需要指定源文件的名稱咽白,并且SCons會根據(jù)源文件名正確推斷出要構(gòu)建的對象和可執(zhí)行文件的名稱啤握。
? 其次,相同的輸入SConstruct文件晶框,在兩個系統(tǒng)上會生成正確的輸出文件名排抬。(POSIX:hello.o和hello;WINDWOS:hello.obj和hello.exe)授段。這是一個簡單的例子蹲蒲,來說明SCOns如何編寫并構(gòu)建簡單的程序。
(請注意侵贵,對于本指南中所有的示例届搁,我們不會同時提供windows和Linux兩種輸出示例,除非有特殊說明窍育,否則輸出效果在兩個平臺上同樣有效)
2.2 構(gòu)建中間文件
? Program構(gòu)建方法只是SCons提供的眾多構(gòu)建方法之一卡睦,另外一種構(gòu)建方法是object,用以生成中間文件:
Object('hello.c')
? 現(xiàn)在你可以執(zhí)行scons命令蔫骂,去構(gòu)建整個工程么翰,在POSIX工程中這將會僅僅構(gòu)建hello.o。
> scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cc -o hello.o -c hello.c
scons: done building targets.
? 在windows平臺上辽旋,將會僅僅構(gòu)建出來hello.obj(采用Microsoft Visual C++ 編譯器):
C:\>scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cl /Fohello.obj /c hello.c /nologo
scons: done building targets.
2.3 簡單Java構(gòu)建
? SCons構(gòu)建Java工程也很簡單浩嫌,不像Program和Object這些構(gòu)建方法, Java構(gòu)建方法需要你指明構(gòu)建的輸出目標(biāo)路徑:
Java('classes', 'src')
? 如果src路徑包含了一個hello.java文件补胚,那么執(zhí)行scons命令后的輸出將會如下:
> scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
javac -d classes -sourcepath src src/hello.java
scons: done building targets.
? 我們會覆蓋更多的java編譯細(xì)節(jié)码耐,包含java架構(gòu)和其他類型的文件,詳見第26章溶其。
2.4 編譯后清除
? 采用SCons我們不需要增加特殊的指令在構(gòu)建后執(zhí)行清除操作骚腥,相反,你可以簡單使用-c或者--clean選項瓶逃,此時SCons會自動刪除構(gòu)建的文件束铭,所以你可以采用scons -c進(jìn)行構(gòu)建后的清理工作廓块,在POSIX平臺上輸出如下:
> scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cc -o hello.o -c hello.c
cc -o hello hello.o
scons: done building targets.
> scons -c
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Cleaning targets ...
Removed hello.o
Removed hello
scons: done cleaning targets.
? 在windows平臺上輸出如下:
C:\>scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cl /Fohello.obj /c hello.c /nologo
link /nologo /OUT:hello.exe hello.obj
embedManifestExeCheck(target, source, env)
scons: done building targets.
C:\>scons -c
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Cleaning targets ...
Removed hello.obj
Removed hello.exe
scons: donw cleaning targets.
? 請注意, SCons通過改變輸出來告訴你契沫,它在Cleaning targets ... 和 donw cleaning targets.
2.5 SConstruct文件
? SConstruct文件带猴,類似于Make系統(tǒng)中的Makefile文件,這是SCons讀取并控制編譯構(gòu)建的輸入文件懈万。
2.5.1 SConstruct文件是Python腳本
? SConstruct和Makefile的最大不同是:SConstruct文件是python腳本拴清,如果你不太熟悉python,也不用擔(dān)心会通,這本指南會詳細(xì)介紹Python的相關(guān)用法口予,保證您會高效地使用SCons,而且python也是非常簡單易學(xué)的涕侈。
? 使用Python作為腳本語言的一個方面是沪停,您可以在SConstruct中使用Python的注釋約定,將注釋放入文件中驾凶。也就是說牙甫,“#”和行尾之間的所有內(nèi)容都將被忽略:
# Arrange to build the "hello" program.
Program('hello.c') # "hello.c" is the source file.
? 在本指南剩余的部分您會發(fā)現(xiàn)调违,使用腳本語言可以大大簡化復(fù)雜的構(gòu)建過程窟哺。
2.5 SCons函數(shù)和構(gòu)建順序無關(guān)
? SConstruct有一點和一般python腳本不同,SCons函數(shù)的書寫調(diào)用順序技肩,并不影響SCons真實的構(gòu)建順序且轨,這點和Makefile有點相似。換句話說虚婿,當(dāng)你調(diào)用Program構(gòu)建時(或者其他構(gòu)建方法)旋奢,SCons并非在此刻構(gòu)建可執(zhí)行文件,相反然痊,這僅僅是告訴SCons你想要獲得一個可執(zhí)行文件的構(gòu)建結(jié)果至朗。舉例來說,需要構(gòu)建hello.c的源文件剧浸,SCons也僅僅是獲取了構(gòu)建可執(zhí)行文件hello和源碼hello.c之間的關(guān)系锹引。(在第6章會詳細(xì)介紹)
? 我們可以通過打印輸出,來區(qū)分SCons僅僅是調(diào)用構(gòu)建方法如Program獲取構(gòu)建信息唆香,還是真實構(gòu)建可執(zhí)行文件嫌变。通過python的print函數(shù),我們可以看到SCons的Program構(gòu)建過程:
print("Calling Program('hello.c')")
Program('hello.c')
print("Calling Program('goodbye.c')")
Program('goodbye.c')
print("Finished calling Program()")
? 當(dāng)執(zhí)行scons指令時躬它,我們可以看到輸出如下:
> scons
scons: Reading SConscript files ...
Calling Program('hello.c')
Calling Program('goodbye.c')
Finished calling Program()
scons: done reading SConscript files.
scons: Building targets ...
cc -o goodbye.o -c goodbye.c
cc -o goodbye goodbye.o
cc -o hello.o -c hello.c
cc -o hello hello.o
scons: done building targets.
? 注意到腾啥,SCons先構(gòu)建了goodbye,即使在SConstruct中優(yōu)先定義了hello。
2.6 降低SCons輸出詳細(xì)程度
? 你已經(jīng)知道了SCons構(gòu)建時的一些輸出信息:
C:\>scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cl /Fohello.obj /c hello.c /nologo
link /nologo /OUT:hello.exe hello.obj
embedManifestExeCheck(target, source, env)
scons: done building targets.
? 這些輸出信息描述了SCons的工作順序倘待,SCons會先讀取所有的配置文件(SConstruct和SConscript文件等)疮跑,其次才是構(gòu)建具體的目標(biāo)。這些輸出信息還會描述一些錯誤信息延柠,包括【配置文件讀取過程中的出錯和編譯執(zhí)行過程中的出錯等祸挪。
? 當(dāng)然,這些輸出結(jié)果會導(dǎo)致輸出比較混亂贞间,我們可以通過-Q參數(shù)來禁用:
C:\>scons -Q
cl /Fohello.obj /c hello.c /nologo
link /nologo /OUT:hello.exe hello.obj
embedManifestExeCheck(target, source, env)
? 因為我們希望本指南用戶重點關(guān)注SCons實際在做什么,所以我們將使用該-Q選項雹仿,從本指南中所有其他示例的輸出中刪除這些消息增热。