2007年5月19日星期六

避免cross-compile的陷阱:libtool

在Unix系統上,有個知名的 "make" 工具,可協助開發程式,但是隨著程式開發複雜度的提昇,已經很難用有限的 "make rules" 來滿足多變的需求,所以Cygnus/RedHat的Tom Tromey就設計autoconfautomake等工具,期望大幅降低異質性平台開發的困難。這也包含所謂的cross-compile,為了克服不同平台的函式庫編譯落差, libtool也被提出,立意甚好但往往讓我們遇到不少問題,比方說知名的hacker - Casey Marshall - 就在與這些上萬行的工具程式奮戰一段時間後,寫了篇短文 "Avoiding libtool minefields when cross-compiling"。autoconfautomake等工具最核心的想法就是希望編譯過程可以簡化成如下: (以x86下進行ARM-Linux程式編譯為例)

./configure --host=arm-linux \
--prefix=/usr \
--enable-shared \
--enable-Feature1 \
--disable-Feature2
筆者參與的若干自由軟體計畫中,也陸續導入此設計,如上的組態所示,我們指定cross-compile的對象為arm-linux,automake會依據特定條件去找尋與測試編譯環境,同時我們啟用Feature1與抑制Feature2,接著一堆上萬行的Makefile就會乖乖建構了。那麼,問題在哪呢?我們很常見到以下的編譯錯誤:
/bin/sh libtool --mode=link target-gcc -c -O2 -o libbar.so ... -lfoo
target-gcc -c -O2 -o libbar.so ... /usr/lib/libfoo.so
/usr/lib/libfoo.so: could not read symbols: File in wrong format
collect2: ld returned 1 exit status

很明顯,libtool被誤導,原本該尋找arch = arm的程式檔案,沒想到抓到host (x86)上的檔案,為何如此?我們隨便挑一個描述程式連結資訊的*.la檔案:
$ cat /usr/lib/libesd.la
# libesd.la - a libtool library file
# Generated by ltmain.sh - GNU libtool 1.5.6 (1.1220.2.95 2004/04/11 05:50:42) Debian: 224 $
#
# Please DO NOT delete this file!
# It is necessary for linking the library.

# The name that we can dlopen(3).
dlname='libesd.so.0'

# Names of this library.
library_names='libesd.so.0.2.36 libesd.so.0 libesd.so'

# The name of the static archive.
old_library='libesd.a'

# Libraries that this one depends upon.
dependency_libs=' -L/usr/lib /usr/lib/libaudiofile.la -lm'

# Version information for libesd.
current=2
age=2
revision=36

# Is this an already installed library?
installed=yes

# Should we warn about portability when linking against -modules?
shouldnotlink=no

# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''

# Directory that this library needs to be installed in:
libdir='/usr/lib'
再清楚不過,這肇因於將libdir指向Host/x86上的目錄下,但這些*.la檔案已經置放於 "staging" (工作區),於是我們可用GNU sed去更動。比方說 "staging" 目錄於 /tmp/rootfs,那麼:
sed -i~ -e "s;/usr;/tmp/rootfs/usr;"
這之間有頗多繁瑣的工作,還好OpenEmbeddedautoconfautomake,與libtool作了修正,所以大部分的Automake-based applications可以很容易透過OpenEmbedded去建構,但副作用則是需要re-generated,又,這樣的套件或應用程式往往佔多數,耗費的時間也相當可觀。

沒有留言: