程式編譯中怎麼樣調試configure
來源:
IBM DW中國
作者:
Peter Seebach
時間:
2007-04-22
點擊:
[收藏
] [投稿
]
,但是測試程式錯誤地認為缺少這個函數。
當 autoconf
的目標為主流平台(特別是各種 Linux,但是還包括主要的 Unix 發行版本)時,極少出現有 bug 的測試,這種有 bug 的測試通常是在那些沒用被廣泛測試過的平台或編譯器上運行測試的結果。例如,UnixWare 上的 gcc
不會發生前面的 bug;只是在使用系統本身的開發包進行編譯時間才會發生。通常,最簡單的解決辦法是在 configure
中注釋掉相應的測試,並直接設定出問題的環境變數。
編譯器不真正工作
有時 configure
前階段選擇的編譯器標記可以連結可執行檔,但最終產生的可執行檔卻不能運行,這是一個特别致命的錯誤。這會導致測試無緣無故地失敗。例如,如果您使用的連結器命令是錯誤的,雖然您可能會正確地進行了連結,但卻不能運行。到完成本文時, configure
指令碼還不能發現這一錯誤,所以只有那些需要目標程式啟動並執行測試才會報告失敗。這對調試來說是非常不可思議的,但是通過 config.log 指令碼可以弄明白是哪裡出了問題。例如,在一個測試系統中,我得到了這樣的輸出:
清單 5. 測試 config.log 輸出
configure:5644: checking for working memcmp configure:5689: gcc -o conftest -g -O2 -fno-strength-reduce -I/usr/X11R6/include -L/usr/X11R6/lib conftest.c -lXaw -lXext -lSM -lICE -lXmu -lXt -lX11 -lcurses >&5 configure:5692: $? = 0 configure:5694: ./conftest Shared object "libXaw.so.7" not found configure:5697: $? = 1 configure: program exited with status 1
|
真正錯誤在於,編譯器需要一個單獨的標記來告訴它 /usr/X11R6/lib 需要在搜尋目錄列表中出現,這樣在運行時才可以找到動態連結程式庫。無論怎麼樣,這是第一個這樣的測試,它真正運行編譯過的測試程式,而不是程式編譯成功後就停止。這是一個非常精妙的問題。
在這個系統中,解決的方法是添加
-Wl,-R/usr/X11R6/lib
到 CFLAGS
變數中。命令列:
$ CFLAGS="-Wl,-R/usr/X11R6/lib" ./configure
允許 configure
正確地運行這個測試。
這對交叉編譯尤其不利,因為您可能不能運行實際上是由交叉編譯器建立的可執行程式。最近的 autoconf
版本都盡量避免要求測試程式實際啟動並執行測試。
找到缺少的庫和 include
使用 configure 指令碼的另一個常見的問題是,如果一個特定的軟體包安裝到了一個非常規的位置, configure
將無法找到它。好的 configure
指令碼通常允許您指定所需要的檔案的路徑,因為它們可能被安裝到與眾不同的位置。例如,許多 configure
指令碼用一個標準的方法來告訴指令碼到何處去尋找 X 庫:
清單 6. 尋找 X 庫
X features: --x-includes=DIR X include files are in DIR --x-libraries=DIR X library files are in DIR
|
如果這樣仍不行,您還可以嘗試使用完全強制的方法:指定需要的編譯器標記為您的 CC
環境變數或者是 CFLAGS
環境變數的一部分。
其他技巧
如果開發人員給出了 autoconf
用於產生 configure
指令碼的 configure.in
檔案,一個工作區將運行最新版本的 autoconf
。可能這樣就可以了,但即使不能很好地工作,這也可以解決一些問題。這樣做的目的是更新用到的特定測試;它在舊版本的 configure
中可能就是一個引發問題的 bug。就此而言,如果您是這種情形下的開發人員,請一定要發布您所用到的 configure.in
檔案。
如果您經常要反覆調整您傳遞到 configure
的參數,而且您並不擅長 shell 命令列編輯,那麼可以做一個封裝器指令碼,這個指令碼以適當的參數調用 configure
。經過一些調整和一些失敗的測試後,您的指令碼可能會是這樣:
清單 7. 封裝器指令碼
./configure --with-package=/path/to/package / --enable-widget / --disable-gizmo / --with-x=29 / --with-blah-blah-blah CFLAGS="-O1 -g -mcpu=i686 -L/usr/unlikely/lib / -I/usr/unlikely/include -Wl,-R/usr/unlikely/lib"
|
相對於一遍又一遍地在命令列中輸入,將指令碼放在一起將很方便 —— 而且以後您還可以引用它,或者將它的一個拷貝寄給別人。
開發健壯的 configure 指令碼
一分預防勝似十分治療。要使 configure
指令碼工作的最好方法就是在產生它的時候儘力確保它不會出錯。
當嘗試構建一個健壯的 configure
指令碼時,最需要注意的實際上很簡單。永遠不要去測試那些您並不真正需要的內容。不要測試 sizeof(char)
;因為在 C 中 sizeof
操作符返回字元大小的對象,以用來儲存一些內容, sizeof(chare)
永遠是 1 (即使是在那些字元位元大於 8 的那些機器上)。絕大部分情況下,沒有理由去測試是否有權使用自 1989 版本標準出現以後的
ANSI/ISO C 中的函數或者標準的 C 標頭檔是否可用。更糟的是當標準的特性存在時還去測試非標準的特性。不要測試