编译开源软件时,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 ,也可以将程序拷贝到其他位置,或者其他机器上运行。





上一篇:SMSSDK验证码服务端校验接口


下一篇:ELF entry point和装载地址