對話 UNIX,第 12 部分: 自己動手完成項目
Unix® 系統中提供了數百個實用工具應用程序或者命令。其中一些命令可以操作文件系統,而其他的命令則用于查詢并控制操作系統本身。大量的命令提供了連接性,并且還有更豐富的命令可用于生成、交換、修改、篩選和分析數據。由于 UNIX 具有悠久而豐富的歷史,所以您也許能夠找到恰好合適的工具,以用于手頭的任務。
此外,當一個實用工具不能滿足需求時,您可以通過各種各樣的方式結合任何數量的 UNIX 實用工具,以創建您自己的工具。正如您在前面的部分中所看到的,可以利用管道、重定向和條件,直接在命令行中構建即時可用的工具,并且 Shell 腳本將小型的、易于學習的編程語言的強大功能與 UNIX 命令結合在一起,以構建可重用工具。
當然,在很多情況下,僅依靠命令行和 Shell 腳本是不夠的。例如,如果您必須部署一個新的守護進程以提供新的網絡服務,那么您可以使用一種表達能力更強的語言,如 C 或者 Python,以便自己編寫應用程序。并且,因為 Internet 上有許多應用程序是免費的(免費 意味著無需支付任何費用、得到自由條款的許可,或者兩者都有),所以您還可以下載、編譯并安裝適當的、有效的解決方案,以滿足您的需求。
UNIX(以及 Linux®)的許多版本都提供一種稱為包管理器 的特殊工具,用以在系統中添加、刪除和維護軟件。包管理器通常可以維護本地安裝的所有軟件的詳細目錄,以及一個或者多個遠程存儲庫 中所有可用軟件的目錄。您可以使用包管理器在存儲庫中搜索您所需要的軟件。如果存儲庫中包含您正在尋找的軟件,那么您只需要使用一個命令或者點擊幾下鼠標,就可以在您的系統中安裝一個新的包。
包管理器是非常有價值的。使用它,您可以刪除全部的包、更新現有的包,以及為任何包自動地檢測并實現任何先決條件。例如,如果您選擇了操作圖像的軟件,如可靠的 ImageMagick,但是您的系統中缺少處理 JPEG 圖像的庫,那么包管理器將在安裝您所選擇的包之前檢測并安裝缺少的內容。
然而,也可能存在這樣的情況,即您所需要的軟件是可獲得的,但它卻不包含于任何存儲庫中。由于包管理方式具有顯著的優勢,所以大多數軟件都提供了可以使用包管理器進行下載并安裝的形式。然而,因為 Unix 的版本和風格非常之多,所以很難針對每種特定的變體,以各種包管理器的格式提供每個應用程序。如果您的 UNIX 安裝是主流的,并受到大量擁護者的喜愛,那么您將更有可能找到預先構建的并且可供使用的軟件。否則,您就需要挽起袖子準備自己動手構建軟件了。
是的,年輕的絕地武士(《星球大戰》中的武士),是使用源代碼的時候了。
如同從沼澤中升起一架 X 翼戰斗機一樣,從源代碼構建軟件乍看起來可能是令人生畏的,特別當您不是軟件開發人員的時候。事實上,在大多數情況下,整個構建過程僅僅只需要少數幾條命令,其余的工作都是自動完成的。
當然,某些程序構建起來是非常復雜的(或者需要花費數小時來進行構建),并且在構建過程中需要進行人工介入。然而,即使這些程序通常是由一些容易構建的較小的塊構造而得到的,依賴關系的數量和構造的順序也會使構建過程變得復雜。一些程序還有許多您并不一定希望擁有的特性。例如,您可以構建 PHP,以便與新的網際協議版本 6 (IPv6) Internet 尋址方案進行互操作。如果您的網絡尚未采用 IPv6,則不需要包括這個特性。對大量選項進行的審查將使構建過程變得更加麻煩。
這個月,讓我們來研究如何構建一個典型的 UNIX 軟件應用程序。在繼續學習后面的內容之前,請確保系統中安裝了 C 編譯器,如 GNU 編譯器套裝(GNU Compiler Collection,GCC),以及常見的 UNIX 軟件開發工具套裝,包括 make、m4、pkg-config 和 awk。此外,請確保在您的 PATH 環境變量中包含了所有的開發工具。
軟件包中有價值的內容
作為一個說明性的和典型的示例,讓我們配置、構建并安裝 SQLite——一個實現結構化查詢語言(Structured Query Language,SQL)數據庫引擎的小型的庫。SQLite 不需要進行任何配置即可使用,并且可以完整地嵌入到任何應用程序中,而數據庫則包含在單個文件中。許多編程語言都可以調用 SQLite 以實現數據的持久化。SQLite 還包括一種用于管理 SQLite 數據庫的、名為 sqlite3 的命令行實用工具。
要開始學習這部分內容,首先下載 SQLite(請參見參考資料)。選擇最新的源代碼包,并將其下載到您的計算機中。(在撰寫本文時,SQLite 的最新版本是版本 3.3.17,于 2007 年4 月 25 日發布。)這個示例使用了 http://www.sqlite.org/sqlite-3.3.17.tar.gz 中存儲的文件。
在您獲得了該文件之后,請對其進行解壓縮。.tar.gz 擴展反映了該存檔文件是如何構造的。在這個示例中,它是一個壓縮了的 tar 存檔文件。后面的擴展 .gz,表示 gzip(壓縮);前面的擴展 .tar,表示 tar(一種存檔格式)。要提取該存檔文件的內容,只需要對其進行反向處理即可,也就是首先解壓縮,然后打開該存檔文件:
$ gunzip sqlite-3.3.17.tar.gz$ tar xvf sqlite-3.3.17.tar
這兩個命令在一個名為 sqlite-3.3.17 的新目錄中創建了原始源代碼的一個副本。順便說明一下,.tar.gz 文件格式是非常常見的(稱為 tarball),并且您可以使用 tar 命令直接解壓縮 tarball 文件:
$ tar xzvf sqlite-3.3.17.tar.gz
這一個命令和前面的兩個命令是等價的。
接下來,將目錄更改為 sqlite-3.3.17,并使用 ls,以列出其中的內容。您應該看到與清單 1 所示類似的清單:
清單 1. SQLite 包的清單
$ lsMakefile.in contrib publish.shMakefile.Linux-gcc doc spec.templateREADME ext sqlite.pc.inVERSION install-sh sqlite3.1aclocal.m4 ltmain.sh sqlite3.pc.inaddopcodes.awk main.mk srcart mkdll.shtclinstaller.tclconfig.guessmkopcodec.awk testconfig.sub mkopcodeh.awk toolconfigure mkso.sh wwwconfigure.acnotes
其中的源代碼和 SQLite 補充文件經過了很好組織,并且模擬了大部分的軟件項目分發源代碼的方式:
README 文件對該項目進行了描述,并且通常用于說明如何構建該軟件。(README 文件還詳細地介紹了使用條款,或者許可證、適用情況。許多項目的許可證代碼都符合 GNU 公共許可版本 2 中的條款,即所謂的“copyleft許可證。在許可證與您打算如何使用該軟件之間可能存在一定的沖突,如果您對此有任何疑問,最好請教一下合適的法律顧問。)
src 目錄中包含了相關的代碼。
test 目錄中包含了一組測試,以驗證該軟件的操作是否正確。在開始構建或者進行了任何修改之后,請運行這些測試,這樣可以增加對該軟件的信心。
contrib 目錄中包含核心 SQLite 開發團隊所沒有提供的附加軟件。對于像 SQLite 這樣的庫,contrib 中可能包含一些常用語言(如 C、Perl、PHP 和 Python)的編程接口。它可能還包括圖形用戶界面(GUI)包裝,以及更多的內容。
在其他文件中,Makefile.in、configure、configure.ac 和 aclocal.m4 用于生成在您的 Unix 版本中編譯 SQLite 軟件的腳本和規則。如果這個軟件足夠簡單,那么要編譯其代碼,可能只需要一條簡單的編譯命令即可。但是,因為存在如此之多的 UNIX 變種(Mac OS X、Solaris、Linux、IBM® AIX® 和 HP/UX 等等),所以必須對宿主計算機進行分析,以確定它的功能及其實現。例如,郵件閱讀應用程序可能會嘗試確定本地系統是如何存儲郵箱的,并包含對該格式的支持。
集中精力感受源代碼
下一個步驟是探查系統并配置該軟件,以便進行正確地構建。(您可以將這個步驟想象為裁剪一件衣服:這件衣服大小基本合適,但是需要進行一定的修改以使其更加時尚。)您需要進行自定義工作,并為使用 ./configure 本地腳本進行編譯做好準備。在命令行提示處,鍵入:$ ./configure
這個配置腳本進行了幾項測試,以證明您的系統是合格的。例如,在一臺 Apple MacBook 計算機上(其中運行著 FreeBSD® UNIX 的一個變種)運行 ./configure,將產生以下結果(請參見清單 2):
清單 2. 在 Mac OS X 上運行 ./configure 的結果
checking build system type... i386-apple-darwin8.9.1checking host system type... i386-apple-darwin8.9.1checking for gcc... gccchecking for C compiler default output file name... a.outchecking whether the C compiler works... yeschecking whether we are cross compiling... nochecking for suffix of executables...checking for suffix of object files... ochecking whether we are using the GNU C compiler... yeschecking whether gcc accepts -g... yeschecking for gcc option to accept ISO C89... none neededchecking for a sed that does not truncate output... /usr/bin/sedchecking for grep that handles long lines and -e... /usr/bin/grepchecking for egrep... /usr/bin/grep -Echecking for ld used by gcc... /usr/bin/ld...
這里,./configure 可以確定編譯和主機系統的類型(如果您采用交叉編譯的話,它可能不同),證實是否已經安裝了 GNU C 編譯器(GCC),并找到其余構建過程可能需要使用的實用工具的路徑。您可以瀏覽一下其余的輸出,但是您將看到一個較長的診斷信息列表,該列表從成功構造 SQLite 的角度分析了您的系統的特點。
注意: ./configure 命令可能 會失敗,特別是在無法找到一個先決條件的情況下(比如一個系統庫或者關鍵的系統實用工具)。
瀏覽 ./configure 的輸出,尋找其中不正常之處,如命令的專用或者本地版本,它可能并不適合于構建通用的應用程序,如 SQLite。作為一個示例,如果您的系統管理員安裝了 GCC 的 alpha 版本,并且 configure 工具首選使用該版本,那么您可以選擇手動地改寫這個選擇。要查看您可以改寫的選項的列表(該列表通常很長),可以鍵入 ./configure --help,如清單 3 中所示:
清單 3. 用于 ./configure 腳本的通用選項
$ ./configure --help...By default, `make install' will install all the files in`/usr/local/bin', `/usr/local/lib' etc. You can specifyan installation prefix other than `/usr/local' using `--prefix',for instance `--prefix=$HOME'.For better control, use the options below.Fine tuning of the installation DirectorIEs: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec]...
./configure --help 的輸出中包括配置系統使用的通用選項,以及僅與您正在構建的軟件相關的特定選項。要查看后者(較短)的列表,可以鍵入 ./configure --help=short(請參見清單 4):
清單 4. 要構建的軟件包所特定的選項
$ ./configure --help=shortOptional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-shared[=PKGS] build shared librarIEs [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --enable-threadsafe Support threadsafe operation --enable-cross-thread-connections Allow connection sharing across threads --enable-threads-override-locks Threads can override each others locks --enable-releasemodeSupport libtool link to release mode --enable-tempstore Use an in-ram database for temporary tables (never,no,yes,always) --disable-tcl do not build TCL extension --disable-readline disable readline support [default=detect] --enable-debug enable debugging & verbose explain
返回到 ./configure --help,最頂部的輸出顯示了可執行文件的缺省安裝目錄是 /usr/local/bin,庫文件的缺省安裝目錄是 /usr/local/lib,等等。許多系統使用一個替代的層次結構來存儲非核心軟件。
例如,許多系統管理員選擇使用 /opt 而不是 /usr/local 存儲本地添加的或者在本地進行了修改的軟件。如果您希望將 SQLite 安裝到與缺省目錄不同的其他目錄中,可以使用 --prefix= 選項指定該目錄。一種可行的方法(也是一種常見的方法,如果只有您一個人使用這個軟件包,或者如果您沒有 root 訪問權限以便在全局的范圍內安裝該軟件)是將該軟件安裝到您的 home 目錄中的層次結構中:$ ./configure --prefix=$HOME/sw
使用這個命令,構建過程的安裝部分將在 $HOME/sw 中(比如 $HOME/sw/bin、$HOME/sw/lib、$HOME/sw/etc、$HOME/sw/man,以及其他所需的目錄中)重新創建該軟件的層次結構。為了簡單起見,這個示例在缺省目標處安裝其代碼。
編譯代碼
./configure 的結果是一個與您的 Unix 版本兼容的 Makefile。名為 make 的開發實用工具將使用這個 Makefile,以執行編譯所需的步驟,并將代碼鏈接到一個可執行文件。您可以打開這個 Makefile 對其進行檢查,但不要對它進行編輯,因為如果您再次運行 ./configure,它將列出您所做的任何修改。
這個 Makefile 中包含需要編譯的源文件的列表,并且它還包括啟用或者禁用并選擇 SQLite 包中的某些代碼片段的常數。例如,如果 configure 工具檢測到了系統中合適的芯片,那么它可能會啟用 64位處理器特定的代碼。這個 Makefile 還說明了源文件之間的依賴關系,因此在一個非常重要的頭文件 (.h) 中進行的一項更改,可能會導致重新編譯所有的 C 源代碼。
您的下一個步驟是運行 make,以構建該軟件(請參見清單 5):
清單 5. 運行 make
$ makesed -e s/--VERS--/3.3.17/ ./src/sqlite.h.in | sed -e s/--VERSION-NUMBER--/3003017/ >sqlite3.hgcc -g -O2 -o lemon ./tool/lemon.ccp ./tool/lempar.c .cp ./src/parse.y ../lemon parse.ymv parse.h parse.h.tempawk -f ./addopcodes.awk parse.h.temp >parse.hcat parse.h ./src/vdbe.c | awk -f ./mkopcodeh.awk >opcodes.h./libtool --mode=compile --tag=CC gcc -g -O2 -I. -I./src -DNDEBUG -I/System/Lib rary/Frameworks/Tcl.framework/Versions/8.4/Headers -DTHREADSAFE=0 -DSQLITE_THREA D_OVERRIDE_LOCK=-1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -c ./src/alter.cmkdir .libsgcc -g -O2 -I. -I./src -DNDEBUG -I/System/Library/Frameworks/Tcl.framework/Vers ions/8.4/Headers -DTHREADSAFE=0 -DSQLITE_THREAD_OVERRIDE_LOCK=-1 -DSQLITE_OMIT_L OAD_EXTENSION=1 -c ./src/alter.c -fno-common -DPIC -o .libs/alter.o...ranlib .libs/libtclsqlite3.acreating libtclsqlite3.la
注意: 在上面的輸出中,添加了一些空白行,以便更好地突出顯示 make 發起的每個步驟。
make 實用工具檢查文件(頭文件、源代碼、數據文件和目標文件)的修改日期,并編譯合適的 C 源文件。最初,make 將重新編譯所有內容,因為不存在任何目標文件或者編譯目標。正如您可以看到的,用于編譯目標的規則還包括一些中間步驟,其中使用了一些相關的工具,如 sed 和 awk,以產生在后續的步驟中將要使用的頭文件。
執行 make 命令所得到的結果是一個完成的庫和 sqlite3 實用工具。
最好對您剛編譯的軟件進行測試,盡管這在每個包中并不是強制的,也沒有提供相應的內容。即便成功地構建 了您的軟件,也不一定就表示該軟件能夠正確地運行。
要測試您的軟件,可以再次運行 make,并使用 test 選項(請參見清單 6):
清單 6. 對軟件進行測試
$ make test...alter-1.1... Okalter-1.2... Okalter-1.3... Okalter-1.3.1... Okalter-1.4... Ok...Thread-specific data deallocated properly0 errors out of 28093 testsFailures on these tests:
成功了!該軟件構建成功,并且工作正常。如果其中一個或者多個測試用例失敗了,那么底部的總結(這里,它是空白的)將向您報告哪一項測試或者哪幾項測試需要進一步研究。
完成后的產品
如果您的軟件工作正常,那么最后一個步驟是將它安裝到您的系統中。同樣,使用 make,并指定 install 目標。要將軟件添加到 /usr/local,通常需要由 sudo 所提供的超級用戶(root)權限(請參見清單 7):
清單 7. 在您的本地系統中安裝軟件
$ sudo make installtclsh ./tclinstaller.tcl 3.3/usr/bin/install -c -d /usr/local/lib./libtool --mode=install /usr/bin/install-c libsqlite3.la /usr/local/lib /usr/bin/install-c .libs/libsqlite3.0.8.6.dylib /usr/local/lib/libsqlite3.0.8.6 .dylib.../usr/bin/install -c .libs/libsqlite3.lai /usr/local/lib/libsqlite3.la/usr/bin/install -c .libs/libsqlite3.a /usr/local/lib/libsqlite3.achmod 644 /usr/local/lib/libsqlite3.aranlib /usr/local/lib/libsqlite3.a.../usr/bin/install -c -d /usr/local/bin./libtool --mode=install /usr/bin/install -c sqlite3 /usr/local/bin/usr/bin/install -c .libs/sqlite3 /usr/local/bin/sqlite3/usr/bin/install -c -d /usr/local/include/usr/bin/install -c -m 0644 sqlite3.h /usr/local/include/usr/bin/install -c -m 0644 ./src/sqlite3ext.h /usr/local/include/usr/bin/install -c -d /usr/local/lib/pkgconfig;/usr/bin/install -c -m 0644 sqlite3.pc /usr/local/lib/pkgconfig;
相關文章:
