天天看點

(轉)使用 SCons 輕松建造程式 

在軟體項目開發過程中,make 工具通常被用來建造程式。make 工具通過一個被稱為 Makefile 的配置檔案可以自動的檢測檔案之間的依賴關系,這對于建造複雜的項目非常有幫助,然而,編寫 Makefile 本身卻不是一件容易的事情。SCons 是一個用 Python 語言編寫的類似于 make 工具的程式。與 make 工具相比較,SCons 的配置檔案更加簡單清晰明了,除此之外,它還有許多的優點。本文将簡單介紹如何在軟體開發項目中使用 SCons,通過本文,讀者可以學習到如何使用 SCons 來建造自己的程式項目。

前言

make 這個工具自上個世紀 70 年代 Stuart Feldman 在貝爾實驗室開發出以來,就一直是類 UNIX 程式員的最愛之一。通過檢查檔案的修改時間,make 工具可以知道編譯目标檔案所要依賴的其他檔案。在複雜的項目中,如果隻有少數幾個檔案修改過,make 工具知道僅僅需要對哪些檔案重新編譯就可以確定目标程式被正确的編譯連結。這樣做的好處就是在編譯中,不僅可以節省大量的重複輸入,還可以確定程式可以被 正确的連結,縮短編譯的時間。雖然如此,但是為 make 工具編寫建造規則卻不是一件容易的事。它複雜的配置規則,即使是有經驗的開發者也望而生畏。make 工具的許多替代品便是以而誕生,SCons 就是是其中之一。SCons 是一個用 Python 語言編寫的類似于 make 工具的程式。與 make 工具相比較,SCons 的配置檔案更加簡單清晰明了,除此之外,它還有許多的優點。

回頁首

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 源代碼包(目前 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 安裝完成後,我們就可以使用 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 吧。