這週末寫了一支開發工具 cc wrapper,連同之前寫的 ld wrapper,大概可以包一個開發工具套件吧。ld wrapper 可以降低連結出錯的機率,而 cc wrapper 可以修正檔案相依關係並提高編譯速度。
今天先介紹 ld wrapper。
在大型的專案常常遇到一個問題,就是拉了一大堆的函式庫進來編譯,這些函式庫裡面有些是 .a 有些是 .so,而不同的 .so 又可能拉了同一份的 .a 進來,或者某 .a 拉了另一個 .a。這時候如果沒注意版本控制和連結順序,就會在二進位檔案裡面埋下地雷,造成日後難以追蹤的問題。例如,A.so 拉了舊版 B.a,C.so 拉了新版 B.a,而程式會拉到 A.so 和 C.so,所以編譯的時候會需要連結這三個檔案。某天,程式出錯了,而用 gdb 從 C.so 追下去的時候,無法得知目前挖到的 B.a 是舊版還是新版。另外如果 D.a 會使用 E.a,則 D.a 也必須在 E.a 的前面。
要避免這個方法,有一個小技巧:永遠把 .a 放在 .so 的前面,另外先載入的也要放前面。這個小技巧聽起來簡單,但是要是面臨幾十個目錄,每個目錄都拉少則三五個,多則數十個函式庫來編譯,那檢查起來就很累人了。
我寫了一個 ld wrapper,來幫忙執行上面這項工作,而程式開發者不用作任何改變,只要把「假 ld」放在路徑之中優先於「真 ld」的位置,讓「假 ld」的 wrapper 來執行順序的檢查工作,如果沒問題再呼叫「真 ld」來連結,就可以避免因為連結順序而造成的問題啦。這個執行模式的點子來自 ccache。
附註:另一個方法是在 gcc 編譯的時候加上某個現在臨時想不以起來的參數,但是這樣會拉長編譯所需時間,所以不建議。

0 意見:
張貼意見