編譯開源軟件時,prefix, sysroot, DESTDIR怎麼整

開發環境ubuntu12.04,x86_64,gcc4.6

arm板子環境armeabi,32bit,gcc5.3


以shell裏面經常用到的file程序爲例子

從ftp://ftp.astron.com/pub/file/上面下載源代碼,因爲我的ubuntu使用的是file5.09,不支持編譯最新版本的file.5.25,所以我就下載file5.09了。


如果是從源代碼編譯安裝file程序,應該這樣做:

./configure
make
sudo make install

沒啥好說的


如果我沒有root權限,不是sudo組的,或者想把file安裝到其他目錄,怎麼辦呢?有兩種情況:

第一種,錯誤的方法

./configure
make
make install DESTDIR=/home/tree/tools

編譯完了,使用DESTDIR參數指定了一個安裝路徑,也沒什麼難理解的。運行/home/tree/tools/bin/file /home/tree/tools/bin/file:

/home/tree/tools/bin/file: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=0x1be35519b339d86fd2d4f73686b27c3573bdd988, not stripped

這不可以運行嘛,怎麼能說是錯誤的方法呢?確實可以運行,但是如果你

sudo mv /usr/share/misc/magic.mgc{,.bak}
然後就發現你的/home/tree/tools/bin/file用不了了,即使你重新編譯安裝也用不了了,所以說這是一種錯誤的方法。

仔細看/home/tree/tools/bin/file的錯誤提示(可以使用/home/tree/tools/bin/file -v查看file需要的magic file的路徑),說找不到/usr/share/misc/magic.mgc,肯定找不到,因爲你編譯安裝的被magic.mgc安裝在/home/tree/tools/share/misc/magic.mgc。

file程序使用絕對路徑去找它需要的magic file,誰知道你把magic file安裝到哪裏了(測試前需要刪除/usr/share/misc/magic.mgc,這是系統自帶的,/home/tree/tools/bin/file會使用一個默認值去找這個文件,編譯安裝前刪除它,防止干擾),所以用不了,如果file程序使用相對路徑去找magic file的話,是可以正確運行的。

第二種方法,當然是正確的方法了

./configure --prefix=/home/tree/tools
make
make install
挺像的吧,即使你刪除了/usr/share/misc/magic.mgc,編譯出來的file也是可以正確運行的,毫無壓力。vi config.log查看一下:
prefix='/home/tree/rootfs'
datarootdir='${prefix}/share'
datadir='${datarootdir}'
pkgdatadir='$(datadir)/misc'

vi src/Makefile.am可以看到:

MAGIC = $(pkgdatadir)/magic
AM_CPPFLAGS = -DMAGIC='"$(MAGIC)"'
--prefix參數被用來拼接目錄,然後定義MAGIC宏傳遞給file程序,file從這個目錄裏面找magic file(當然,file也會從一些默認的位置查找magic file,自己看源碼)

可以這樣理解,--prefix爲程序運行所需的目錄的前綴,默認爲/usr,經過和/bin, /etc, /lib等拼接後,指定程序運行時需要dlopen的.so存放的位置,配置文件/數據文件存放的位置等

DESTDIR指定安裝程序的前綴,默認爲空,程序最終將安裝到DESTDIR/prefix的位置,裏面有bin/file, share/misc/magic.mgc等。

ps:如果將tools文件夾重命名了,file程序就用不了了,原理很簡單,file程序找不到/home/tree/tools/share/misc/magic.mgc了,所以程序中使用這種絕對路徑的方式是有一些不便之處的,不能將程序安裝到任意位置了,使用相對路徑就可以解決這個問題。


那麼--build, --host, --target又是什麼鬼呢?

--build指定編譯機器的架構,configure程序基本上可以自己猜出來這個值,不用設置

--host指編譯出來的程序,運行在哪裏,默認值爲--build

--target指編譯出來的程序,處理什麼平臺的文件,默認爲--host

比如編譯x86_64程序,在x86_64上編譯,編譯出來的程序運行在x86_64上面,處理x86_64的文件,不用指定這三個參數,默認都爲x86_64-unknown-linux-gnu這樣的

編譯交叉編譯工具鏈,在x86_64上編譯,編譯出來的程序運行在x86_64上面,處理arm的文件,需要修改--target=arm-unknown-linux-gnueabi這樣的

使用交叉編譯工具鏈編譯arm程序,在x86_64上編譯,編譯出來的程序運行在arm上面,處理arm的文件,需要修改--host=arm-unknown-linux-gnueabi,--target默認和--host相同,可以不指定(注意configure時需要指定CC=arm-unknown-linux-gnueabi)


好了,我們來編譯一個arm版本的file程序玩玩吧:

CC=arm-unknown-linux-gnueabi ./configure --prefix=/home/tree/rootfs
make
make install

能用不,不能用。把file,libmagic.so,magic.mgc拷貝到arm板子上,提示找不到magic file /home/tree/rootfs/share/misc/magic.mgc,能找到纔怪了呢,那是編譯機器上面的路徑,那麼怎麼玩呢?

CC=arm-unknown-linux-gnueabi ./configure --prefix=/usr
make
make install DESTDIR=/home/tree/rootfs/usr
這個才能用,arm版本的file覺得我應該去/usr/share/misc/magic.mgc裏面找文件,剛好能找到。如果make install時不指定DESTDIR,就會把arm程序安裝到編譯機器的/usr目錄了,順便還沒有安裝權限。
再把file, libmagic.so, magic.mgc文件拷貝到板子上去,發現可以正常使用了。


還有一個參數,--with-sysroot,整啥的?

一般是交叉編譯才能用得到的,包括編譯交叉編譯工具鏈和使用交叉編譯編譯arm程序,用於指定從編譯器從哪裏找所要的.so, .h什麼的,不指定--with-sysroot的話,就會找編譯機器的/usr/include, /usr/lib下面的東西。編譯arm程序去找x86_64的頭文件,那肯定是有問題的,如果有一些硬件平臺相關的文件,纔會暴露出問題,否則也看不出來有什麼問題,比如之前編譯的arm版本的file程序,就沒有--with-sysroot參數。


總結一下,交叉編譯arm的程序,--prefix必需設置爲/usr這樣的,不能夠帶編譯機器的絕對路徑,必需指定--with-sysroot=${arm_rootfs},必需使用DESTDIR=${arm_rootfs}去make install,${arm_rootfs}是你的arm的rootfs的路徑,需要設置一下。

編譯x86_64程序,程序很可能使用了--prefix去拼接一些目錄,使用絕對路徑去查找一些文件,這種情況下,不能夠使用DESTDIR參數,也不能隨便將編譯出來的程序放到別的文件夾下面去運行;如果沒使用絕對路徑查找文件,而是使用相對路徑,那麼可以指定DESTDIR ,也可以將程序拷貝到其他位置,或者其他機器上運行。





發佈了31 篇原創文章 · 獲贊 11 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章