make 這個工具自上個世紀 70 年代 Stuart Feldman 在貝爾實驗室開發出以來,就一直是類 UNIX 程序員的最愛之一。通過檢查文件的修改時間,make 工具可以知道編譯目標文件所要依賴的其他文件。在複雜的項目中,如果只有少數幾個文件修改過,make 工具知道僅僅需要對哪些文件重新編譯就可以確保目標程序被正確的編譯鏈接。這樣做的好處就是在編譯中,不僅可以節省大量的重複輸入,還可以確保程序可以被正確的鏈接,縮短編譯的時間。雖然如此,但是爲 make 工具編寫建造規則卻不是一件容易的事。它複雜的配置規則,即使是有經驗的開發者也望而生畏。make 工具的許多替代品便因此而誕生,SCons 就是是其中之一。SCons 是一個用 Python 語言編寫的類似於 make 工具的程序。與 make 工具相比較,SCons 的配置文件更加簡單清晰明瞭,除此之外,它還有許多的優點。
SCons 是一個開放源代碼、以 Python 語言編寫的下一代的程序建造工具。它最初的名字是 ScCons, 基於由 perl 語言編寫的 Cons 軟件開發而成,它在 2000 年 8 月獲得了由 Software Carpentry 舉辦的 SC 建造比賽的大獎。現在 ScCons 已經被改名爲 SCons,目的是爲了表示不再與 Software Carpentry 有聯繫,當然,還有一個目的,就是爲了更方便的輸入。
作爲下一代的軟件建造工具,SCons 的設計目標就是讓開發人員更容易、更可靠和更快速的建造軟件。與傳統的 make 工具比較,SCons 具有以下優點:
- 使用 Python 腳本做爲配置文件
- 對於 C,C++ 和 Fortran, 內建支持可靠自動依賴分析 . 不用像 make 工具那樣需要執行"make depends"和"make clean"就可以獲得所有的依賴關係。
- 內建支持 C, C++, D, Java, Fortran, Yacc, Lex, Qt,SWIG 以及 Tex/Latex。用戶還可以根據自己的需要進行擴展以獲得對需要編程語言的支持。
- 支持 make -j 風格的並行建造。相比 make -j, SCons 可以同時運行 N 個工作,而不用擔心代碼的層次結構。
- 使用 Autoconf 風格查找頭文件,函數庫,函數和類型定義。
- 良好的誇平臺性。SCons 可以運行在 Linux, AIX, BSD, HP/UX, IRIX, Solaris, Windows, Mac OS X 和 OS/2 上。
SCons 支持多種操作系統平臺,併爲各個系統製作了易於安裝的文件,因此在各個系統平臺上的安裝方法不盡相同,在 SCons 的官方網站上可以查每個平臺的具體安裝方法。如果 SCons 沒有爲你的系統製作相應的安裝包,你也可以下載 SCons 的源代碼,直接進行安裝。首先,從 SCons 的網站上下載最新的 SCons 源代碼包(目前 SCons 的最新版本是 2.0.1)。其次,解壓下載的源代碼。視下載的源代碼包的格式不同而有不同的方法,在 Windows 平臺上,可是使用 winzip 或者其他類似的工具解壓。在 Linux 平臺上,對於 tar 包,使用 tar 命令進行解壓,如:
$ tar -zxf scons-2.0.1.tar.gz |
然後切換進入解壓後的目錄進行安裝,如
$ cd scons-2.0.1 $ sudo python setup.py install |
命令執行如果沒有錯誤,那麼 scons 就被安裝到系統上了。對於 Linux 來說,scons 會默認安裝到 /usr/loca/bin 目錄下,而在 Windows 平臺上,則會被安裝到 C:\Python25\Scripts 下。
在 SCons 安裝完成後,我們就可以使用 SCons 來建造我們的程序或者項目了。像很多編程書籍那樣,在這裏我們也通過一個簡單的 helloscons 例子來說明如何使用 SCons。例子 helloscons 包含兩個文件 :
$ ls helloscons helloscons.c SConstruct |
其中 helloscons.c 是程序的源文件,SConstruct 是 scons 的配置文件,類似使用 make 工具時的 Makefile 文件,因此,爲了編譯你的項目,需要手工創建一個 SConstruct 文件(注意:文件名是大小寫敏感的)。不過,在編譯的時候不需要指定它。要編譯這個例子,切換到 helloscons 的目錄下,運行 scons 命令,如下:
$ cd helloscons/ $ scons scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... gcc -o helloscons.o -c helloscons.c gcc -o helloscons helloscons.o scons: done building targets. |
來查看一下運行 scons 命令後得到的結果 :
$ ls helloscons helloscons.c helloscons.o SConstruct |
建造結束後,得到了二進制文件 helloscons 以及編譯的過程中產生的一些以 .o 結尾的目標文件。試運行 helloscons 一下 , 會得到 :
$ ./helloscons Hello, SCons! |
現在讓我們回過頭來解析一下 helloscons 這個例子 . helloscons.c 是這個例子裏的唯一一個源代碼文件,它所做的事就是在控制檯上輸出一行簡單的"Hello,SCons", 它的源代碼如下:
清單 1. helloscons.c
#include <stdio.h> #include <stdlib.h> int main(int argc, char* argv[]) { printf("Hello, SCons!\n"); return 0; } |
作爲項目建造規則的配置文件 SConstruct 的內容如下 :
清單 2. SConstruct 文件
Program('helloscons.c') |
你可能很驚訝 SConstruct 的內容只有一行,然而事實確實如此,它比傳統的 Makefile 簡單很多。SConstruct 以 Python 腳本的語法編寫,你可以像編寫 Python 腳本一樣來編寫它。其中的 Program 是編譯的類型,說明你準備想要建造一個可執行的二進制程序,它由 helloscons.c 文件來生成。在這裏,沒有指定生成的可執行程序的名字。不過不用擔心,SCons 會把源代碼文件名字的後綴去掉,用來作爲可執行文件的名字。在這裏,我們甚至不需要像 Makefile 那樣指定清理的動作,就可以執行清理任務。在 SCons 中,執行清理任務由參數 -c 指定,如下 :
$ scons -c scons: Reading SConscript files ... scons: done reading SConscript files. scons: Cleaning targets ... Removed helloscons.o Removed helloscons scons: done cleaning targets. $ ls helloscons.c SConstruct |
如果你不想直接編譯可執行的二進制文件,那也沒有關係。SCons 支持多種編譯類型,你可以根據自己的需要,任意選用其中的一種。SCons 支持的編譯類型有:
- Program: 編譯成可執行程序(在 Windows 平臺上即是 exe 文件),這是最常用的一種編譯類型。
- Object: 只編譯成目標文件。使用這種類型,編譯結束後,只會產生目標文件。在 POSIX 系統中,目標文件以 .o 結尾,在 Windows 平臺上以 .OBJ 結尾。
- Library: 編譯成庫文件。SCons 默認編譯的庫是指靜態鏈接庫。
- StaticLibrary: 顯示的編譯成靜態鏈接庫,與上面的 Library 效果一樣。
- SharedLibrary: 在 POSIX 系統上編譯動態鏈接庫,在 Windows 平臺上編譯 DLL。
這個簡單的 SConstruct 的配置文件從一個側面說明了使用 SCons 來建造程序是多麼的簡單。在實際的項目開發中,程序的建造規則遠比 helloscons 這個例子複雜。不過,這些都不是問題,你可以像擴展你自己的 Python 腳本文件那樣去擴展 SConstruct. 如果你不想使用 SConstruct 爲你設置的默認可執行文件的名字,而是選擇你自己喜歡的名字,如 myscons,可以把 SConstruct 的內容修改爲 :
Program('myscons, 'helloscons.c') |
其中 myscons 就是你想要的可執行文件的名字,你可以把它換成任意你喜歡的名字,不過有點注意的是,這個名字必須放在第一位。然後在 helloscons 目錄下運行 scons 命令,就會得到 myscons 這個可執行文件,如下:
$ scons -Q gcc -o helloscons.o -c helloscons.c gcc -o myscons helloscons.o |
其中的 -Q 參數是減少編譯時的由 scons 產生的冗餘信息。如果你的項目由多個源文件組成,而且你想指定一些編譯的宏定義,以及顯式的指定使用某些庫,這些對於 SCons 來說,都是非常簡單的事情。我們的另外一個例子 helloscons2 很好的說明這種情況。 helloscons2 由 3 個源文件組成 , 它們是 helloscon2.c, file1.c, file2.c,另外指定了編譯的選項,同時還指定了使用哪些具體的庫。讓我們來看一下 helloscons2 的 SConstruct 文件 :
Program('helloscons2', ['helloscons2.c', 'file1.c', 'file2.c'], LIBS = 'm', LIBPATH = ['/usr/lib', '/usr/local/lib'], CCFLAGS = '-DHELLOSCONS') |
正如你想像的那樣,這樣一個配置文件並不複雜 . 該 SConstruct 文件指出,它將生成一個名叫 helloscons2 的可執行程序,該可執行程序由 helloscons2.c, file1.c 和 file2.c 組成。注意,多個源文件需要放在一個 Python 列表中。如果你的源程序代碼文件很多,有十幾個甚至上百個,那不要一個個的將他們都列出來,你可以使用 glob('*.c') 來代替源代碼列表。如下 :
Program('helloscons2', Glob('*.c') |
配置文件中 LIBS,LIBAPTH 和 CCFLAGS 是 SCons 內置的關鍵字,它們的作用如下:
- LIBS: 顯示的指明要在鏈接過程中使用的庫,如果有多個庫,應該把它們放在一個列表裏面。這個例子裏,我們使用一個稱爲 m 的庫。
- LIBPATH: 鏈接庫的搜索路徑,多個搜索路徑放在一個列表中。這個例子裏,庫的搜索路徑是 /usr/lib 和 /usr/local/lib。
- CCFLAGS: 編譯選項,可以指定需要的任意編譯選項,如果有多個選項,應該放在一個列表中。這個例子裏,編譯選項是通過 -D 這個 gcc 的選項定義了一個宏 HELLOSCONS。
運行 scons 命令的時候,可以看到這些變量如何被使用的,讓我們執行一下 scons 命令 :
$ scons -Q gcc -o file1.o -c -DHELLOSCONS file1.c gcc -o file2.o -c -DHELLOSCONS file2.c gcc -o helloscons2.o -c -DHELLOSCONS helloscons2.c gcc -o helloscons2 helloscons2.o file1.o file2.o -L/usr/lib -L/usr/local/lib -lm |
scons 命令的輸出顯示了可執行程序 helloscons2 如何由多個源文件而生成,以及在 SConstruct 中定義的 LIBS,LIBPATH 和 CCFLAGS 如何被使用。可見,即使對於複雜的項目,SCons 的編譯配置文件也很簡單。除此之外,SCons 也提供了很多功能以適應不同的需要,如果讀者想更深入的瞭解如何使用 SCons,可以參考 SCons 的幫助手冊。
本文簡單介紹了 SCons 的特點,如何安裝 SCons,以及通過例子來說明如何在項目中使用 SCons。作爲下一代的軟件建造工具,SCons 使用 Python 語言作爲配置文件,不但功能強大,而且簡單易用,對於跨平臺的項目,非常適合。如果你厭煩了 make 工具的那種複雜的編寫規則,嘗試一下新鮮的 SCons 吧。