HOWTO:在 Linux 下建立軟體套件

作者: Mendel Leo Cooper

最新版本:v1.91, 27

轉為 Wiki: Ping (ping 'at' pingyeh 'dot' net), 2003 年 11 月 27 日


這是份廣泛指引文件,可用來建立一般性 UNIX 軟體發行套件在 Linux 下.



  1. 簡介
  2. 結語
  3. 參考與進一步閱讀資料
  4. 從取得開始
  5. 使用 Make
  6. 克服困難
    1. 連結錯誤
    2. 其它問題
    3. 旋扭與微調
    4. 去哪取得進一步的協助
  7. 最後步驟
  8. 第一個例子: Xscrabble
  9. 第二個例子: Xloadimage
  10. 第三個例子: Fortune
  11. 哪裏可找到原始碼檔案

1. 簡介

很多軟體套件提供給各式 UNIX, 包括 Linux, 是將原始碼檔案壓縮成檔案(archives)而發行的. 相同的套件可以建立以便在不同對象的機器上執行, 並且這可節省些軟體成品而免於必須製造各種發行版本. 軟體套件的單一發行版本結果能執行在各式實體(incarnations), 像是在 Intel 機器, DEC Alpha, RISC 工作站, 甚至是電算主機. 但不幸的是, 這將建立軟體的工作推給了最終使用者(end user), 實際上是系統管理者, 即坐在鍵盤前的同志...你. 雖然這樣, 認真來說這過程並不是像它看起來那麼可怕或不可思議, 就像這指引所解說一樣.

2. 結語

總結, 百折不撓會使什麼都變成不一樣 (而且高難度挫折門檻明顯會有幫助). 使出全力,從失敗中獲得學習更是重要. 在每個過失的步伐, 每個失敗造就了能夠掌握 建立軟體藝術 的知識個體.

3. 參考與進一步閱讀資料

4. 從取得開始

你有下載或其它方式取得一個軟體套件. 最常見情況是它被打包起來 (tarred) 而且被壓縮 (gzipped), 成為 .tar.gz 或 .tgz 形式. 首先將它複製到一工作目錄. 然後用 untar 和 gunzip 處理它. 處理它最適合的命令是 tar xzvf filename, 這裏的 filename 當然是軟體檔名. 這種解開程序常常會安裝適當檔案在它所開啟的子目錄中. 注意的是如果套件名稱有 .Z 結尾, 那將要使用 uncompress PACKAGENAME, 然後再用 tar xvf PACKAGENAME 而不要用之前的步驟.

有時打包起來的檔案必須 untarred 且安裝自使用者的家目錄(home directory), 或者也許是在某個其它目錄, 像是套件設定資料所指定的. 假若你設法要 untar 它而得到的是錯誤訊息, 也許就是那原因. 讀一下套件文件, 特別是 README 和/或 Install 檔案, 如果存在, 編輯設定檔案和/或 Makefiles 如所需要的, 即與安裝指示符合. 注意的是通常 不 去更改 Imake 檔案, 因為這可能有未預期的結果. 某些軟體套件允許自動安裝程序,它是藉由執行 make install 來放置二元碼在適當系統位置.

偶而, 你可能需要使用 patch檔案,該檔案有列出原本的與新的原始檔案的差異, 來升級或加入臭蟲(bug)的修正至未打包(unarchived)的原始檔案. doc檔案與/或 README 檔案會告知你這算不算該情況. 對於使用 Larry Wall 的強力 修補(patch) 工具之正常的語法(syntax)是 patch patchfile.

你現在可以開始進行 建立 過程階段了.

5. 使用 Make

Makefile 是建立過程的重點. 在它的最簡單的形式, Makefile 就是個 script ,它是用來編譯或建立二元碼,套件的可執行部分. Makefile也可以提供軟體套件升級的工具,而不需要重新編譯每一個在套件中的原始檔案, 但其有不同的情況(或是不同的約定).

某些特點是, Makefile 開啟 cc 或 gcc. 這實際上是個前處理器, C (or C++) 編譯器, 和 連結器, 按照那個順序. 這過程轉換原始碼(source)為可真正去執行的二元碼(binaries).

下指令 make 通常只要鍵入 make. 這通常建立討論中的套件所有需要的可執行檔. 然而, make 也做其他工作,像是安裝檔案至合適的目錄 (make install) 而且刪除舊的 object 檔案 (make clean). 執行 make -n 允許預覽建立過程, 就是列出所有 make 所喚起的(triggered)所有命令, 但沒有真的去執行它們.

只有在最簡單的軟體使用一般性的 Makefile. 較複雜的安裝需要根據函式庫(libraries), include 檔案以及你個別機器資源所在目錄來量身定製. 這特別是當需要 X11 libraries 來安裝建立時. Imake 和 xmkmf 可完成這樣的工作.

引用自 man page,Imakefile 是個模板(template)的 Makefile. imake 工具參考 Imakefile 根據你的系統造出合適的 Makefile. 然而,幾乎在所有的情況下,你要執行 xmkmf, 它是要下 imake 指令用的 shell script, 也就是個前端介面(front end). 察閱一下內附在軟體檔案間的 README 或 INSTALL 檔案以取得特別的指示. 至於更詳細的步驟分析,請閱讀 imake 和 xmkmf 的 man pages.

要知道的是 xmkmf 和 make 可能需要以 root 身分來下指令, 特別是當 make install 來搬移二元碼到 /usr/bin 或 /usr/local/bin 目錄. 以一般使用者的身分而不具 root 權力 來使用 make 將可能會導致 write access denied 的錯誤訊息, 因為你缺少寫入(write)至系統目錄的權限. 也檢查一下, 所造出來的二元碼對你與任何其他適用的使用者有適合的執行(execute)權限.

下指令 xmkmf 來使用 Imake 檔案, 建立一個新的而且適合你系統的 Makefile. 正常地下指令 xmkmf 都會附加 -a 引數, 因而自動地做 make Makefiles, make includes, 和 make depend 的動作. 這會設定變數(variables)和給定函式庫(library) 位置給編譯器和連結器. 有時會沒有 Imake 檔案, 引而代之的是有 INSTALL 和 configure 的 script, 也會到這樣的目的. 注意的是如果你要執行 configure, 那要下指令 ./configure 以確保在目前目錄下正確的 script configure 是被呼叫. 在大部分的情況, 在發行套件中的 README 檔案會說明安裝步驟.

通常一個好的方法是從外觀檢視一下 Makefile 是 xmkmf 或 其中一個安裝的 scripts 所造出來的. Makefile 正常下會為你的系統而修正, 但你偶而可能需要旋扭(tweak)或手動地修正錯誤.

你的一般安裝步驟將會是:

6. 克服困難

如果用 xmkmf 和/或 make 很成功沒有錯誤, 你可以著手於 next section. 然而, 在真實生活, 很少事情在第一次就正確的工作. 這就是當你的機智豐富時,要勇於嘗試.

6.1. 連結錯誤

6.2. 其它問題

6.3. 旋扭與微調

你可能希望檢查 Makefile 來確定有選用對你系統最佳編譯選項. 舉例來說, 設定 -O2 旗標來選最高層級的最佳化而 -fomit-frame-pointer 旗標來造最小二元碼 (雖然 debugging 會沒有打開). 除非你知道你在做什麼, 而且在任何情況下, 除非艱苦建立的工作已完成, 否則不要玩這些.

6.4. 去哪取得進一步的協助

在我的經驗, 大概25%的應用程式建立完全沒有困難. 另外大約50%能被說服的建立, 要付出努力的範圍從無聊到極為困難. 那仍然表示有某些套件無論如何都無法建立. 即使那樣, 那些 Intel ELF 和/或 a.out 二元碼, 也可能在 [WWW] Sunsite, [WWW] TSX-11 archive 或其它地方找到. 也許, 軟體的創造者可以提供編譯好的二元碼給你的特別的機器使用.

注意的是如果你取得預先編譯好的二元碼, 你會需要檢查是否與你的系統相容:

如果全都失敗, 你可以在合適的 新聞群組尋求幫忙, 像是在 [WWW] comp.os.linux.x[WWW] comp.os.linux.development. 萬一你只是不夠幸運的話, 嘿, 試試也是有趣的.

7. 最後步驟

讀一下軟體套件的文件來決定是否有某些環境變數需要設 (在 .bashrc 或 .cshrc) 以及 是否 .Xdefaults 和 .Xresources 檔案需要調整.

可能有個應用程式內定的檔案, 通常叫做 Xfoo.ad 在原本的 Xfoo 發行套件. 如果這樣, 編輯 Xfoo.ad 檔案適合你的機器, 然後重新命名 (mv) 成 Xfoo 而且 以 root 身分 安裝它到 /usr/lib/X11/app-defaults 目錄, 沒這樣做可能會造成軟體行為很奇怪, 甚至拒絕執行.

大多數的軟體套件附有一個或以上的格式化 man pages. 以 root 身分, 複製 Xfoo.man 檔案到合適的 /usr/man 目錄 (man1 - man9), 而根據那再重新命名. 舉例而言, 如果 Xfoo.man 結果是在 /usr/man/man4, 那應該命名為 Xfoo.4 (mv Xfoo.man Xfoo.4). 根據一般約定使用者的命令擺在 man1, 遊戲是在 man6, 而管理的套件是在 man8 (看一下 man 文件 以取得更詳細資料).當然,在你系統你可以不照這個約定, 只要你喜歡.

某些套件不會安裝二元碼(binaries)在合適的系統目錄, 換句話說, 他們沒有 install 選項在 Makefile 中. 如果是這情況, 你可以用 root 身分複製二元碼(binaries)到 usr/local/bin 目錄來手動安裝二元碼(binaries).

注意的是某些或全部上述步驟,在大部分情形下,應該會由 make install 來自動操作. 如果是這樣, README 或 INSTALL 文件檔會提到這個.

8. 第一個例子: Xscrabble

Matt Chapman的 Xscrabble 似乎像是個頗有趣的程式, 因為我曾是個貪婪的 Scrabble(拼字遊戲)玩家.我下載下,解壓, 而且建立它以 README 檔案中的下列步驟:

當然它不能正常運作...

我在 [WWW] comp.os.linux.x 的新聞群組詢問過, 而且有些人好心的指出似乎 Xt, Xaw, Xmu, 和 X11 libs 沒有讓連結器(linker)找得到. 嗯...

有兩個主要的 Makefiles, 而且在 src 目錄下的那個讓我感興趣. 在 Makefile 一行有定義 LOCAL_LIBS 成: LOCAL_LIBS = $(XAWLIB) $(XMULIB) $(XTOOLLIB) $(XLIB) 這所指的 libs 並沒有被連結器找到

找找下個指到 LOCAL_LIBS 的地方, 我看到該在 Makerfile 的495行:

而現在 LDLIBS 是什麼呢?

SYS_LIBRARIES 是:

是個! 就是這樣遺失 libraries.

大概連結器需要在 LOCAL_LIBS 之前看到 LDLIBS... 所以, 第一件事要嘗試去修改 Makefile 就是改寫在495行的 $(LOCAL_LIBS) 和 $(LDLIBS) , 所以它現在變成:

在上面的改後,我試著再次執行 make , 瞧, 它這次可正常跑了. 當然, Xscrabble 仍然需要一些微調(fine tuning]與玩弄(twiddling), 像是重新命名字典以及標註某些輔助的敘述在原始碼檔案之一, 但正因為那樣,它已給我好幾個小時的消遣.

你可以寄 e-mail [WWW] Matt Chapman, 而且從他的 [WWW] home page 下載 Xscrabble.

9. 第二個例子: Xloadimage

這個例子提出較簡單的問題. xloadimage 程式加入到我的圖形工作組似乎是很有用. 我從一本由 Mui 和 Quercia 所著的好書 X User Tools 所附的 CD 上的原始碼目錄(source directory), 直接複製 xloadi41.gz 檔案下來. 如預期的, 用 tar xzvf 解開所有檔案. 然而, make 出現了令人討厭的錯誤而且中斷.

這錯誤訊息含有最根本的線索.

看一下檔案 image.h 的23行.

啊哈! 在 xloadimage, wchar_t 原始碼的某處已經重複定義了在標準 include 檔案 stdlib.h 已定義的東西. 首先試試將在 image.h 的23行標註(commenting out)起來, 也許 stdlib.h include 是不大需要的

此時, build 過程沒有任何重大錯誤. xloadimage 程式現在功能都正常.

10. 第三個例子: Fortune

最後例子需要某些 C 程式設計知識. 大部分的 Linux 軟體是用 C 寫的, 而且至少學點 C 明顯的對任何想軟體安裝的人會有助益.

惡名昭彰的(notorious) fortune 程式在每次 Linux 開機起來時秀出幽默的諺語 fortune cookie. 不幸地 (有雙關意思的), 設法在 Red Hat 發行套件 2.0.30 的核心下建立,出現了 一堆嚴重的錯誤.

看一下 fortune.c, 有關聯的幾行在這.

我們需要找出 dirent 的 structure, 但它沒有宣告(declared)在 fortune.c 檔案中, 想用 grep dirent 來秀出是否在其它原始碼的檔案中, 但也沒有. 然而, 在 fortune.c 檔的最上方有下列這行.

這似乎是系統函式庫的 include 檔案, 所以要找 dirent.h 的合理位置是在 /usr/include. 事實上, dirent.h 的確有在 /usr/include 中, 但該檔沒有包含 dirent 的 structure. 然而, 參考另一個 dirent.h 檔.

最後, 去 /usr/include/linux/dirent.h, 我們可找到我們所需要宣告的 structure.

足夠地確定, 這個 structure 宣告沒有包含 d_namelen, 但有一對與其相當的選擇. 其中最可能的是 d_reclen, 因為 這個 structure member 表示某樣東西的 length 而且它是 short integer. 其他大略, d_ino, 可能是 inode number, 判斷它的 name 和 type. 事實上, 我們大概是處理 directory entrystructure, 而元素表示檔案屬性, 它的名稱, inode, 和 length (以 blocks 作單位). 這似乎對我們的猜想很合理.

我們編輯檔案 fortune.c, 而且改變在551行和553行的 d_namelen 變成 d_reclen. 再試試 make all. Success. 這次建立沒有錯誤. 我們現在能夠從 fortune 獲得 cheap thrills

11. 哪裏可找到原始碼檔案

現在你很渴望的使用你最新獲得的知識來加入一些工具和其它好東西到你的系統, 你可以在線上找到它們, [WWW] Linux Applications and Utilities Page, 或者在很合理價位的 CD ROM 的檔案, 藉由 [WWW] Red Hat, [WWW] InfoMagic, 以及其它的.

一個眾多原始碼的寶庫是在 [WWW] comp sources UNIX archive.

很多 UNIX 原始碼發表在 [WWW] alt.sources 新聞群組. 如果你要找特別的原始碼包裝的, 你可以貼在相關的 [WWW] alt.sources.wanted 新聞群組. 另外一個不錯的地方是查看 [WWW] comp.os.linux.announce 新聞群組. 要取得在 [WWW] Unix sources 的通信論壇, 請寄個 subscribe 訊息到那.

至於 [WWW] alt.sources 新聞群組的檔案是在下面 ftp 站:

last edited 2004-12-25 08:45:57 by PingYeh