試誤編譯法

我當年初入 linux 界時,對自行編譯軟體一直有障礙, 到現在對 linux 已經很熟悉了, 自行編譯絕大多數軟體應該都沒問題了。 除了稍微了解通行的編譯流程, 最簡單的做法就是依編譯時的錯誤訊息, 去 google 或去 apt 裝缺少的函式庫。 雖然實行起來有點蠢,但的確是有用的, 絕大多數軟體都能這樣編譯起來。

前言

初入 linux 時,對自行編譯軟體一直有種恐懼感, 除了對命令列還不太熟悉,就是曾經在剛開始用 ubuntu 時, 試著編譯過 purple line, 一個讓 pidgin 能連上 line 的模組。 記得搞了很久很麻煩,最後好像是有成功, 總之讓我留下了不小的陰影。

到現在隨著越來越深入,對 linux 和各工具鏈的了解, 自認已經可以用試誤法編譯出絕大多數的開源專案了。 頂多就是花很久時間,和要裝很多函式庫很佔空間; 有時發現很基礎的東西不合,幾乎要自己編譯系統, 就會放棄或用 docker 或其它虛擬機解決。

makefile

用最簡單的 Makefile 來舉例。 夠簡單的專案就一個 make 就編譯的起來了, 中間如果會有缺什麼函式庫,gcc 丟錯誤訊息, 基本上都看得出來缺什麼。

如果知道是缺 libxxx.so.xxx 之類的檔名, 可以直接用 apt-file search libxxx.so 搜檔名, 看套件管理系統有沒有。 apt file 可以搜各套件提供了什麼檔案,不只是套件名稱, 有時候從函式庫名字看不出來套件名是什麼。

如果錯誤訊息看不懂,可以直接把整句丟去 google, 如果是夠大的專案,通常找得到 stack overflow 的討論串, 就看有沒有解法。 當然最好還是能直接看專案的說明文件, 看需要哪些函式庫先裝好, 不然這樣一直用試誤法覺得自己有點蠢。

之後看要不要 make install 安裝。 如果只是要用一二次,可以直接執行就好了,不用安裝到系統。 也可以自己看 make install 是執行哪些程式,自己手動裝。 但有時用 gnu tool chain 系的自動產生的 makefile 太醜,會看不懂。 可以看有沒有提供 make uninstall, 如果有就能放心裝下去,不用怕不知道怎麼解除安裝。

gnu tool chain

如果比較複雜的會需要用到 ./configure 來檢測環境, 產生 makefile。這是比較常見的, 一般有缺什麼東西在 configure 就會報錯退出, 就裝好再 configure 一次。

之後用 configure 的 makefile 可能不會太好看, make 時會跳很多訊息,有時我也不清楚有沒有 make 成功, 就直接 echo $? 看上一個命令的返回值, 也就是看 make 是正常退出還是錯誤退出, 如果是正常就會是 0,代表編譯成功了。

有時代包衭的大專案,常見用 gnu tool chain, 也就是 autoconf 系列工具, 會需要裝 autoconf 這支程式。 通常專案內會有 autogen.sh 之類的執行檔, 自動化一些編譯前要做的事。

meson ninja

最近碰到的比較新的專案是用 meson 和 ninja。 我用 meson 一直鬼打牆,用 apt 裝的被抱怨太舊, 用 pip 裝的在 sudo 執行時一直出問題。 用二個的一般專案會有寫怎麼 build,就照作就好。

docker

最近在交大用 gipsy 來算 gnss, 教授表示 gipsy 要在 linux 下運作, 他們也不太會裝。 之後我花了半天把 gipsyx 裝好, 二天把 gipsy-oasis 裝好。

但 gipsy 是運行時會相依很多函式庫的程式, 而且很多還有鎖版本; gipsyx 的 python 腳本都編譯成 byte code *.pyc , 而 python byte code 在各版本是不相容的。 總之最簡單的作法,就是挑軟體發行時的linux版本來裝, 之後可以再把軟體裝好後那一刻整個系統備份下來, 也就是 docker 的作法了。

裝 gipsy-oasis 遇到比較多問題, gipsy-oasis 的程式除了核心的 fortran, 還用了很多 perl 和 csh 的腳本, 而且架構組合很複雜。

我裝好 gipsyx 後跑 verify.py 腳本驗證, 如果哪個函式庫有問題,因為全都是 python, 從 log 就能直接看到從哪個腳本 throw 出 error, 就算 error 看不懂,也能直接去看 python code 問題在哪。

但 gipsy oasis 的程式是一個混一個, 一大堆 perl csh 互相呼叫。 在 verify.py 和其它被他呼叫的 perl 或 csh 測試, 有時呼叫會存 stderr,但不可能每行命令都檢查, 所以就會有這一行錯了所以沒有產出某個檔案, 又過幾行 code 才跳出某檔案不存在的錯誤。

但誰知道那檔案為什麼不存在? 我根本還沒用過 gipsy oasis, 也就不會知道各指令的意思, 也就不知道哪個指令應產出該檔案卻出錯了。 而且因為包了很多層,原始層可能丟出numpy 不存在, 但外面那層的log是誤差超過門檻, 之類八竿子打不著的訊息。