经常需要移植各种软件包,标准的做法是使用发行版定制工具,如Yocto,详见Yocto的使用实例。但有些情况下,我们不得不手动去移植。 本文以移植openobex1.3为例,展现了移植的方方面面。 参考:http://blog.csdn.net/hclydao/article/details/51451725
1.理清依赖关系
- 我们为了获得目标库/程序,往往需要移植数个被依赖的库。以openobex1.3为例:
openobex
|
|--bluez-libs
|__bluez-utils
|
|--libusb
|__glib
| |__zlib
| |
| ?//此处视版本而定,有时glib会和dbus互相依赖
|__dbus
|__expat
- 通过网络资料可以知道各个库的依赖关系,如果网上没有也没关系,可以先编译,通过报错信息也可获知依赖内容
2.确定各个库的版本
- 这是最讲究的部分,库的版本直接决定了移植是否能够成功。一般原则如下
- 库的版本发布时间最好比开发环境稍早几年,比如开发板的内核是3.1x版本的,则bluez适合使用3.36版本
- 库的依赖库最好比自己稍旧一些,但也不能旧太多,比如expat就应该比dbus的版本旧一点
- 如果网络上有现成的移植方案,尽量完全套用,可以极大的提高移植成功率
- 基于以上原则,这里软件包选用的版本为
bluez-libs-3.36 expat-2.1.0. dbus-1.0.2 glib-2.24.2 bluez-utils-3.36 libusb-1.0.9
3.配置内核
- 为了让obex、bluez正常运行,仅仅移植库还不够,内核方面的支持也是必不可少的
- 使用menuconfig
首先令内核支持bluetooth,打开menuconfig
进入Device Drivers ---> USB support
选中host相关的选项
以及USB Physical Layer drivers子目录下的选项
进入Networking support
<*> Bluetooth subsystem support
进入Networking support ---> Bluetooth subsystem support
<*> RFCOMM protocol support
[*] RFCOMM TTY support
<*> BNEP protocol support
[*] Multicast filter support
[*] Protocol filter support
<*> HIDP protocol support
进入Networking support ---> Bluetooth subsystem support ---> Bluetooth device drivers
<*> HCI USB driver
< > HCI SDIO driver (NEW)
< > HCI UART driver (NEW)
<*> HCI BCM203x USB driver
<*> HCI BPA10x USB driver
< > HCI BlueFRITZ! USB driver (NEW)
< > HCI VHCI (Virtual HCI device) driver (NEW)
< > Marvell Bluetooth driver support
< > Marvell BT-over-SDIO driver
< > Atheros firmware download driver
4.编译流程
- 这里采用的软件包都不是很新,均未采用cmake,所以分为三步:config、make、make install
- 交叉编译时,最重要的是指定prefix,即安装目录,并且整个移植过程都不要使用root权限。如此一来即可防止将库、软件包错误地安装到本地ubuntu中,导致系统的崩溃。本文统一将prefix指定为/home/xxx/work/tmp_blue,源代码目录为/home/xxx/Downloads/now_bluez/
编译blue-lib
make distclean
./configure --prefix=/home/xxx/work/tmp_blue --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf CC=arm-linux-gnueabihf-gcc
make
make install
编译安装expat
make distclean
./configure --prefix=/home/xxx/work/tmp_blue --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf CC=arm-linux-gnueabihf-gcc
make
make install
编译安装zlib
make distclean
export TARGETMACH=arm-linux-gnueabihf
export CROSS=arm-linux-gnueabihf
export CC=${CROSS}-gcc
export LD=${CROSS}-ld
export AS=${CROSS}-as
./configure --prefix=/home/xxx/work/tmp_blue
make
make install
编译安装glib
make distclean
sudo apt-get install libglib2.0-dev
echo ac_cv_type_long_long=yes>arm-linux.cache
echo glib_cv_stack_grows=no>>arm-linux.cache
echo glib_cv_uscore=no>>arm-linux.cache
echo ac_cv_func_posix_getpwuid_r=yes>>arm-linux.cache
echo ac_cv_func_posix_getgrgid_r=yes>>arm-linux.cache
./configure --prefix=/home/xxx/work/tmp_blue --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf CC="arm-linux-gnueabihf-gcc -I/home/xxx/work/tmp_blue/include -L/home/xxx/work/tmp_blue/lib" --cache-file=arm-linux.cache
make
make install
编译安装dbus
在dbus-sysdeps-unix.c中添加
struct ucred
{
pid_t pid; /* PID of sending process. */
uid_t uid; /* UID of sending process. */
gid_t gid; /* GID of sending process. */
};
make distclean
rm arm-linux.cache
echo ac_cv_have_abstract_sockets=yes>arm-linux.cache
./configure --prefix=/home/xxx/work/tmp_blue --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf CC="arm-linux-gnueabihf-gcc -rdynamic -I/home/xxx/work/tmp_blue/include -L/home/xxx/work/tmp_blue/lib" --cache-file=arm-linux.cache --with-x=no --with-xml=expat GLIB_CFLAGS="-pthread -I/home/xxx/work/tmp_blue/include/glib-2.0 -I/home/xxx/work/tmp_blue/lib/glib-2.0/include -L/home/xxx/work/tmp_blue/lib -L/home/xxx/work/tmp_blue/lib/libgio-2.0 -L/home/xxx/work/tmp_blue/lib/libgobject-2.0 -L/home/xxx/work/tmp_blue/lib/libglib-2.0"
make install
编译安装libusb
make distclean
./configure --prefix=/home/xxx/work/tmp_blue --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf CC="arm-linux-gnueabihf-gcc -I/home/xxx/work/tmp_blue/include -L/home/xxx/work/tmp_blue/lib"
make
make install
编译bluez-utils
make distclean
sudo apt-get install libdbus-1-dev libdbus-glib-1-dev
sudo apt-get install byacc
sudo apt-get install flex
./configure --prefix=/home/xxx/work/tmp_blue --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf CC="arm-linux-gnueabihf-gcc -I/home/xxx/work/tmp_blue/include -I/home/xxx/work/tmp_blue/include/dbus1.0/dbus -I/home/xxx/work/tmp_blue/include/glib-2.0/glib -I/home/xxx/work/tmp_blue/include/glib-2.0 -I/home/xxx/work/tmp_blue/lib/glib-2.0/include -L/home/xxx/work/tmp_blue/lib -lbluetooth -ldbus-1 -lglib-2.0 -lgio-2.0 -lgobject-2.0" BLUEZ_CFLAGS=-I/home/xxx/work/tmp_blue/include/bluetooth BLUEZ_LIBS=-L/home/xxx/work/tmp_blue/lib --disable-audio --enable-serial --enable-test
编译安装openobex
make distclean
export XROOT=/home/xxx/work/tmp_blue
export PREFIX=$XROOT
export PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig
export HOST=arm-linux-gnueabihf
export LD=$HOST-ld
./configure --prefix=$PREFIX --host=$HOST --target=$HOST --with-gnu-ld=$LD BLUETOOTH_CFLAGS="-I/home/xxx/work/tmp_blue/include -I/home/xxx/work/tmp_blue/include/openobex -L/home/xxx/Downloads/now_bluez/openobex-1.3/ircp -L/home/xxx/Downloads/now_bluez/openobex-1.3/app -L/home/xxx/Downloads/now_bluez/openobex-1.3/lib -L/home/xxx/work/tmp_blue/lib" BLUETOOTH_LIBS="-L/home/xxx/work/tmp_blue/lib -lbluetooth" --enable-bluetooth CC="arm-linux-gnueabihf-gcc -I/home/xxx/work/tmp_blue/include -L/home/xxx/work/tmp_blue/lib" CC="arm-linux-gnueabihf-gcc -I/home/xxx/work/tmp_blue/include -I/home/xxx/work/tmp_blue/include/openobex -L/home/xxx/Downloads/now_bluez/openobex-1.3/ircp -L/home/xxx/Downloads/now_bluez/openobex-1.3/app -L/home/xxx/Downloads/now_bluez/openobex-1.3/lib -L/home/xxx/work/tmp_blue/lib" --enable-apps LDFLAGS="-L/home/xxx/Downloads/now_bluez/openobex-1.3/ircp -L/home/xxx/Downloads/now_bluez/openobex-1.3/app -L/home/xxx/Downloads/now_bluez/openobex-1.3/lib -L/home/xxx/work/tmp_blue/lib"
5.常见的错误
依赖库错误定位至编译环境
- 最常见的问题,就是编译时依赖库错误的定位到了编译环境ubuntu的目录中。比如编译dbus时,编译器会报和glib有关的错误,这是因为定位到了ubuntu中的glib,解决方法是在config时指定GLIB_CFLAGS=相关的内容
Makefile的编写未考虑交叉编译
- 这种错误很常见,比如某个版本dbus的Makefile中systemunitdir变量,它被硬编码为 /lib/systemd/system,这显然是编写者未考虑周全,应该改为systemunitdir = ${prefix}/lib/systemd/system
链接器无法识别库路径
- 这种情况下,较为妥当的解决方法是手动指定链接库。比如编译dbus时,为它指定了库的路径,但其仍然无法链接glib库,那么只能在config时手动为其指定库 -L/home/xxx/work/tmp_blue/lib/libglib-2.0
依赖关系混乱
- 有时两个库之间会互相依赖,比如两个库A和B,编译时有相互依赖的倾向。这也不是没有解决的办法,我们可以无视编译的错误,强行make、make install,先将可以编译成功的部分安装到目标目录中,然后再次编译两者,注意顺序是A、B、A、B。在第二次编译的时候,由于目标目录中安装了大部分的库,所以A和B很有可能编译通过。
软件包版本过老(环境过新)
- 运气好的情况下,可以通过网络资料修改源码来解决,比如本文中的dbus版本太老,不适应ubuntu编译环境,那么在代码中稍作修改即可。这是运气好的情况,而一般情况下,下软件包版本太久,基本就只能换一个了
暂时无法解决的编译错误
- 如果问题实在无法解决,不妨直接make、make install,忽略该报错,因为最终的功能实现可能并不依赖于报错的部分
- 如果仍无法解决,不妨更换软件包,换一个旧/新一点的,较大几率可以解决错误
软件运行时错误
- 首先检查文件系统内是否有相同的软件/库,如果有的话将其从文件系统中彻底清楚,用我们自己移植的完全替换
- 有的软件运行时会去特定路径寻找文件,比如dbus运行时会去/home/xxx/work/tmp_blue/中寻找库、配置文件,之所以会这样是由于编译时把prefix写入了软件内部。如何解决?运行时开发板上不会有该目录,解决方法是建立各种链接,以满足软件的需求
mkdir -p /home/xxx/work/tmp_blue/
ln -s /etc /home/xxx/work/tmp_blue/
ln -s /var /home/xxx/work/tmp_blue/
ln -s /usr/lib /home/xxx/work/tmp_blue/
6.使用openobex进行文件传输
- 修改/etc/dbus/system.conf文件第18行messagebus改为root;修改/etc/bluetooth/hcid.conf,将security后的user改为auto 将passkey后的”BlueZ”改为”0000”
- 手机向板子发送文件:
hciconfig hci0 up
hciconfig hci0 iscan
dbus-daemon --system
hcid -f /etc/bluetooth/hcid.conf -n -d &
sdptool add OPUSH
sdptool brower local
#查看opush的通道号,这里查出来是9
obex_test -b FF:FF:FF:00:00:00 9
s
#当s被输入后手机端发送文件,然后再次按s,即可接收文件
s
hciconfig hci0 up
hciconfig hci0 iscan
dbus-daemon --system
hcid -f /etc/bluetooth/hcid.conf -n -d &
sdptool search 0x1105
#查看手机的opush的通道号,这里查出来是12,
obex_test -b xx:xx:xx:xx:xx:xx 12
c
p /xxx/xxx xxx
|