由於第一次搞嵌入式,交叉編譯DirectFB費了一些周折。
首先記錄下編譯的過程
1 準備源文件包,下載freetype2.4.4和DirectFB-1.4.11.tar.gz,解壓。
2 交叉編譯安裝freetype
export CC=arm-none-linux-gnueabi-gcc
指定交叉編譯器。(我用的交叉編譯器來自source G++)
./configure --host=arm-linux --prefix=/opt/freetype/
make
make install
freetype安裝完畢
3 交叉編譯directfb
export LDFLAGS=-L/opt/freetype/lib
export CFLAGS="-g -I/opt/freetype/include"
./configure --host=arm-linux --prefix=$PREFIX --with-gfxdrivers=none --with-inputdrivers=all --disable-png --disable-jpeg --disable-zlib --enable-sdl=no --enable-gif=no --disable-x11
make
make install
交叉編譯directfb完畢。
4 修改/etc/bash.bashrc 把新安裝的庫的路徑,LD_LIBRARY_PATH ,PKG_CONFIG_PATH , PATH 設置完畢。
source /etc/bash.bashrc 使路徑生效。
5 交叉編譯自己的程序。
arm-none-linux-gnueabi-gcc `pkg-config --cflags --libs directfb`fb.c -o fb
交叉編譯成功 。
總結:期間遇到的一些問題
1 要交叉編譯自己的程序,需要先交叉編譯所依賴的庫
2 如何交叉編譯庫
在網上查找學習後,通過如下命令並不成功
./configure --host=arm-linux --prefix=$PREFIX --with-gfxdrivers=none --with-inputdrivers=all --disable-png --disable-jpeg --disable-zlib --enable-sdl=no --enable-gif=no --disable-x11
原因:在執行configure時 指定了 --host=arm-linux 但是沒有指定交叉編譯器,系統沒有找到交叉編譯器,貌似就用了gcc編譯,最後並未生成arm-linux的庫,在編譯後續的庫時鏈接會找不到合適的庫。需要先
export CC=arm-none-linux-gnueabi-gcc
指定交叉編譯器。
3 交叉編譯好庫之後 設置好路徑後就可以交叉編譯程序了。
下面引用一篇關於交叉編譯鏈接庫配置的文章
交叉編譯的時候不能使用本地(i686機器,即PC機器,研發機器)機器上的庫,但是在做編譯鏈接的時候默認的是使用本地庫,即/usr/lib,/lib兩個目錄。因此,在交叉編譯的時候,要採取一些方法使得在編譯鏈接的時候找到需要的庫。
首先,要知道:編譯的時候只需要頭文檔,真正實際的庫文檔在鏈接的時候用到。 (這是我的理解,假如有不對的地方,敬請網上各位大俠指教) 然後,講講如何在交叉編譯鏈接的時候找到需要的庫。
(1)、交叉編譯時候直接使用-L和-I參數指定搜索非標準的庫文檔和頭文檔的路徑。例如:
arm-linux-gcc test.c -L/usr/local/arm/2.95.3/arm-linux/lib -I/usr/local/arm/2.95.3/arm-linux/include
(2)、使用ld.so.conf文檔,將用到的庫所在文檔目錄添加到此文檔中,然後使用ldconfig命令刷新緩存。
(3)、使用如下命令:
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/arm/2.95.3/arm-linux-lib
參見《ld.so.conf 文檔和PKG_CONFIG_PATH變量》這篇文章。
通過環境變量LD_LIBRARY_PATH指定動態庫搜索路徑(!)。
通過設定環境變量LD_LIBRARY_PATH也可以指定動態庫搜索路徑。當通過該環境變量指定多個動態庫搜索路徑時,路徑之間用冒號":"分隔。
不過LD_LIBRARY_PATH的設定作用是全局的,過多的使用可能會影響到其他應用程序的運行,所以多用在調試。(LD_LIBRARY_PATH 的缺陷和使用準則,可以參考《Why LD_LIBRARY_PATH is bad》 )。通常情況下推薦還是使用gcc的-R或-rpath選項來在編譯時就指定庫的查找路徑,並且該庫的路徑信息保存在可執行文件中,運行時它會直接到該路 徑查找庫,避免了使用LD_LIBRARY_PATH環境變量查找。
(4)、交叉編譯時使用軟件的configure參數。例如我編譯minigui-1.3.3,使用如下配置:
#!/bin/bash
rm -f config.cache config.status
./configure --build=i686-linux --host=arm-linux --target=arm-linux /
CFLAGS=-I/usr/local/arm/2.95.3/arm-linux/include /
LDFLAGS=-L/usr/local/arm/2.95.3/arm-linux/lib /
--prefix=/usr/local/arm/2.95.3/arm-linux /
--enable-lite /
--disable-galqvfb /
--disable-qvfbial /
--disable-vbfsupport /
--disable-ttfsupport /
--disable-type1support /
--disable-imegb2312py /
--enable-extfullgif /
--enable-extskin /
--disable-videoqvfb /
--disable-videoecoslcd
這裏我配置了CFLAGS和LDFLAGS參數,這樣一來,我就不用去修改每個Makefile裏-L和-I參數了,也不用再去配置LD_LIBRARY_PATH或改寫ld.so.conf文檔了。
Linux下動態庫使用小結
1. 靜態庫和動態庫的基本概念
靜態庫,是在可執行程序連接時就已經加入到執行碼中,在物理上成爲執行程序的一部分;使用靜態庫編譯的程序運行時無需該庫文件支持,哪裏都可以用,但是生成的可執行文件較大。動態庫,是在可執行程序啓動時加載到執行程序中,可以被多個可執行程序共享使用。使用動態庫編譯生成的程序相對較小,但運行時需要庫文件支持,如果機器裏沒有這些庫文件就不能運行。
2. 如何使用動態庫
如何程序在連接時使用了共享庫,就必須在運行的時候能夠找到共享庫的位置。linux的可執行程序在執行的時候默認是先搜索/lib和/usr/lib這兩個目錄
Makefile預定義變量
含義
$*
不包含擴展名的目標文件名稱。
$+
所有的依賴文件,以空格分開,並以出現的先後爲序,可能包含重複的依賴文件。
$<
第一個依賴文件的名稱。
$?
所有的依賴文件,以空格分開,這些依賴文件的修改日期比目標的創建日期晚。
$@
目標的完整名稱。
$^
所有的依賴文件,以空格分開,不包含重複的依賴文件。
$%
如果目標是歸檔成員,則該變量表示目標的歸檔成員名稱。例如,如果目標名稱爲
mytarget.so(image.o),則 $@ 爲 mytarget.so,而 $% 爲 image.o。
AR
歸檔維護程序的名稱,默認值爲 ar。
ARFLAGS
歸檔維護程序的選項。
AS
彙編程序的名稱,默認值爲 as。
ASFLAGS
彙編程序的選項。
CC
C 編譯器的名稱,默認值爲 cc。
CFLAGS
C 編譯器的選項。
CPP
C 預編譯器的名稱,默認值爲 $(CC) -E。
CPPFLAGS
C 預編譯的選項。
CXX
C++ 編譯器的名稱,默認值爲 g++。
CXXFLAGS
C++ 編譯器的選項。
FC
FORTRAN 編譯器的名稱,默認值爲 f77。
FFLAGS
FORTRAN 編譯器的選項。