嵌入式arm交叉编译移植bluez5.0最新教程

前言

        BlueZ是一个开源的蓝牙协议栈,它提供了Linux操作系统上的蓝牙支持。它包含了蓝牙协议的实现,包括L2CAP、RFCOMM、SDP、AVRCP、HID等协议,以及蓝牙核心规范的实现。BlueZ还提供了一些工具和库,以便开发者能够方便地使用蓝牙功能,例如命令行工具hcitool和hcidump,以及开发库libbluetooth和obexftp。BlueZ已经成为Linux系统上的标准蓝牙协议栈,被广泛应用于各种设备和应用中。

         bluez的移植过程由于需要链接许多其他的库,而这些库有的又有各自依赖的库,所以整个项目移植下来非常繁琐,网上的教程大多都复杂且混乱,正因为踩过这些坑,本文将换一种方式一步一步教你怎么编译bluez,但是涉及的东西还是比较多,所以bluez的编译需要耐心,这不是一下子就能搞好的,跟着我的思路,耐心去做,不要碰到一点问题就放弃了,花上几个小时的时间,相信最后无论结果如何你都会收获满满。

编译环境以及源码

ubuntu版本:16.04(新建的ubuntu镜像)

交叉编译器:arm-linux-gnueabihf-gcc

所用源码:

  • bluez-5.66
  • dbus-1.12.20
  • expat-2.5.0
  • glib-2.40.0
  • libffi
  • libical-1.0.1
  • ncurses-6.2
  • readline-7.0
  • zlib-1.3
  • cmake-3.20.0-linux-x86_64

所有源码还有编译好的bluez我已经上传至我的gitee,可直接下载

https://gitee.com/luo-honghua/bluez5.0-porting.git

cmake下载地址

Index of /files/v3.20 (cmake.org)

PC源码编译

用ubuntu的gcc编译,为什么呢?我一开始直接用arm去交叉编译,但是总是少这少那,编译不过,一头雾水,所以先用gcc去编译,如果缺少什么,可以直接安装,做这一步主要是让你了解编译bluez的一个过程到底依赖哪些东西,gcc编译过了,那么你再用交叉编译器去编译就清楚多了。如果对自己足够自信的话也可以省去这一步。

裁剪

进入源码目录,打开终端,建一个脚本auto.sh,输入以下内容

./configure --prefix=/opt/bluez/pc_install \
--mandir=/opt/bluez/pc_install/usr/share/man \
--sysconfdir=/opt/bluez/pc_install/etc \
--localstatedir=/opt/bluez/pc_install/var \
-enable-tools -enable-test --enable-experimental --enable-maintainer-mode --disable-udev \
--enable-library  --enable-shared=yes --enable-network --enable-health  \
--enable-cups  --enable-threads --enable-pie --enable-deprecated \

其中

  •  --prefix:最终目标文件生成路径
  • --mandir --sysconfdir --localstatedir这几个随便写个路径,不重要,直接像我一样放到最终目标文件生成路径下

然后执行,这个时候开始报错了

这里提示少了glib,我们直接安装

sudo apt-get install libglib2.0-dev

然后重新执行脚本

可以看到glib检查已经过了,但是少了dbus,同样的,直接安装

sudo apt-get install libdbus-1-dev

再次执行

这次少了libical,安装

sudo apt-get install libical-dev

再次执行

少了readline,安装

sudo apt-get install libreadline-dev

再次执行 

 少了rst2man,安装

sudo apt-get install python-docutils

再次执行

可以看到,裁剪已经通过了,通过上述操作,相信你已经了解了bluez编译所依赖的库了,同样的,arm编译的时候也差不多是这些,有些可以直接安装,但是有些需要也用交叉编译的库。

编译安装

直接编译

make -j4

会报错,但是不要一看到报错就放弃,根据其报错的提示,我们直接找到报错的代码去做修改,比如这里,直接找到monitor/btmon.rst,40行的位置,根据提示,这里不能用auto。要输入具体的数值,所以这里将auto改为10

再次编译

还是报错,这里是因为,列数不匹配,要输入对应列数的数值

 所以这里这样修改,再次编译

可以看到,虽然还是在报错,但是刚刚那个地方已经不报错了,接下来就是如法炮制,将其他地方都进行这样的修改

其中还会有一个这个问题

直接将下方:align: left这行删除即可

最后编译通过,进行安装

make install

最后在最终生成路径下生成这些

通过这一系列工作,bluez的pc编译就通过了,那么后续使用arm编译器编译就简单多了,为什么呢,因为使用arm编译器编译只需要将其中几个库替换为交叉编译生成的库就可以了,而且使用pc先编译还有一个好处,那就是代码无需再改了,pc可以编过,那么arm编译器也一定可以编过。

arm编译

通过上面的流程,其实我们已经知道需要哪些库的依赖了,所以我们一样按照上面的步骤来添加交叉编译的库,在编译之前,我们先建一个mypkconfig文件夹,后续将生成的pkconfig文件都复制到这个文件夹,这样后续编译一些库就不需要在裁剪的时候链接了,后面再详细解释。

可以看到,我的目录结构

  • arm_install:存放交叉编译生成的bluez
  • lib:存放源码交叉编译的生成的库
  • pc_install:存放pc编译生成的bluez
  • mypkconfig:库的环境变量
  • source:源码存放目录

拥有好的编译习惯会让工作更有条理清晰

glib库编译

在进行glib编译的前还需要先编译libffi和zlib这两个库,这两个比较简单

libffi编译

直接在libffi源码目录打开终端,输入命令

./configure --prefix=/opt/bluez/lib/libffi_install --host=arm-linux-gnueabihf CC=arm-linux-gnueabihf-gcc

其中

  •  --prefix:最终目标文件生成路径
  • --host:编译器平台,填写你的交叉编译器
  • CC:使用的c编译器,填写你的交叉编译器

后面这个就不做解释了,通过后直接编译安装

make -j4
make install
zlib编译

同样在源码目录下打开终端输入

export CC=arm-linux-gnueabihf-gcc
./configure --prefix=/opt/bluez/lib/zlib_install
make CC=arm-linux-gnueabihf-gcc -j4
make install

注意zlib不支持通过configure配置编译器,所以要手动来指定编译器。

glib编译

首先源码目录下新建一个文件glib.cache,然后输入以下内容

glib_cv_long_long_format=ll
glib_cv_stack_grows=no
glib_cv_have_strlcpy=no
glib_cv_have_qsort_r=yes
glib_cv_va_val_copy=yes
glib_cv_uscore=no
glib_cv_rtldglobal_broken=no
ac_cv_func_posix_getpwuid_r=yes
ac_cv_func_posix_getgrgid_r=yes

然后再建一个脚本文件auto.sh,输入以下内容

./configure --prefix=/opt/bluez/lib/glib_install \
CC=arm-linux-gnueabihf-gcc \
--host=arm-linux-gnueabihf \
LIBFFI_CFLAGS="-I/opt/bluez/lib/libffi_install/lib/libffi-3.0.9/include" \
LIBFFI_LIBS="-lffi -L/opt/bluez/lib/libffi_install/lib" \
ZLIB_CFLAGS="-I/opt/bluez/lib/zlib_install/include" \
ZLIB_LIBS="-lz -L/opt/bluez/lib/zlib_install/lib" \
--cache-file=glib.cache --disable-selinux  --disable-xattr --disable-libelf

其中

  • LIBFFI_CFLAGS:libffi头文件路径
  • LIBFFI_LIBS:libffi库文件路径
  • ZLIB_CFLAGS:zlib头文件路径
  • ZLIB_LIBS:zlib库文件路径

如果还不清楚可以输入./configure -h查看说明

接下来直接编译,如果出现以下报错

直接编辑gdate.c这个文件,加入一行代码

#pragma GCC diagnostic ignored "-Wformat-nonliteral"

然后重新编译安装

make -j4
make install

完成安装后,在生成目录下找到pkconfig文件,将其这个glib-2.0.pc和gthread-2.0.pc复制到上面我们新建的那个mypkconfig中,复制之前,注意先检查一下路径是否正确

DBus编译

dbus的编译需要先编译expat库

expat编译

源码目录下打开终端输入

./configure --prefix=/opt/bluez/lib/expat_install --host=arm-linux-gnueabihf CC=arm-linux-gnueabihf-gcc --enable-shared
make -j4
make install
DBus编译

源码目录下新建脚本auto.sh,输入内容

./configure --prefix=/opt/bluez/lib/dbus_install \
--host=arm-linux-gnueabihf \
CC=arm-linux-gnueabihf-gcc \
CXX=arm-linux-gnueabihf-g++  \
--with-xml=expat --without-x \
EXPAT_LIBS="-L/opt/bluez/lib/expat_install/lib -lexpat"  \
EXPAT_CFLAGS="-I/opt/bluez/lib/expat_install/include/" \
enable_selinux="no" --disable-tests

裁剪完后直接编译安装

make -j4
make install

同样的,将生成的pkconfig目录下的dbus-1.pc文件复制到mypkconfig目录下

libical编译

libical的编译有点不一样,需要使用cmake,而且对版本有要求。

cmake安装

我的免安装解压的,直接解压设置环境变量就可以直接使用

像我这里,给root用户设置环境变量,如果你是用sudo用户去编译,那就给sudo用户设置环境变量,设置环境变量这个我就不多说了,百度一查就知道了。

设置完环境变量记得source,让环境变量立即生效

完成后输入命令

cmake --version

如果显示版本是cmake version 3.20.0那就没问题 

libical编译

接着回来libical源码目录下,打开终端执行下面的命令

mkdir build
cd build
export CC=arm-linux-gnueabihf-gcc;export CXX=arm-linux-gnueabihf-g++
cmake -DCMAKE_INSTALL_PREFIX=/opt/bluez/lib/libical_install -DCMAKE_BUILD_TYPE=Release -DSHARED_ONLY=yes ..
make -j4
make install

完成后同样的将生成的libical.pc复制过去

readline编译

readline的编译需要ncurses库

ncurses编译
./configure --prefix=/opt/bluez/lib/ncurses_install --host=arm-linux-gnueabihf --with-shared
make -j4
make install

安装的时候会报错

这是因为strip的时候用的是ubuntu自带的strip,而不是arm-linux-gnueabihf-strip,strip的功能你百度一下就知道是什么了,但是这个不影响,我们要的只是动态库。

readline编译

源码目录创建脚本auto.sh

./configure \
--host=arm-linux-gnueabihf  \
CC=arm-linux-gnueabihf-gcc \
--prefix=/opt/bluez/lib/readline_install \
SHLIB_LIBS="-lncurses -L/opt/bluez/lib/ncurses_install/lib" \
SHLIB_CFLAGS="-I/opt/bluez/lib/ncurses_install/include" \

接着就是编译安装

make -j4
make install

要注意的是readline的生成没有pkconfig文件,所以后续编译bluez需要手动修改Makefile去指定

bluez编译

最后就是bluez的编译了,还是原来PC这份源码,先清除一下之前的裁剪配置

make distclean

然后修改auto.sh脚本内容,将编译器换成arm编译器,并且手动指定readline和ncurses的库文件路径

./configure --prefix=/opt/bluez/arm_install \
--host=arm-linux-gnueabi \
CC=arm-linux-gnueabihf-gcc \
--mandir=/opt/bluez/arm_install/usr/share/man \
--sysconfdir=/opt/bluez/arm_install/pc/etc \
--localstatedir=/opt/bluez/arm_install/var \
-enable-tools -enable-test --enable-experimental --enable-maintainer-mode --disable-udev \
--enable-library  --enable-shared=yes --enable-network --enable-health  \
--enable-cups  --enable-threads --enable-pie --enable-deprecated \
LDFLAGS="-L/opt/bluez/lib/readline_install/lib -L/opt/bluez/lib/ncurses_install/lib" \
CFLAGS="-I/opt/bluez/lib/readline_install/include" \

打开终端先设置pkconfig环境变量

export PKG_CONFIG_PATH=/opt/bluez/mypkconfig:$PKG_CONFIG_PATH

然后在执行auto.sh进行裁剪 ,完成后先不急着编译,打开Makefile,先检查一下pkconfig是否生效,看看路径是否正确

可以看到这里dbus、glib、ical都已经是链接的我们指定的路径。

还有一个地方要注意

找到这个位置,可以看虽然已经指定了路径,但是下面LIBS那里并没有链接上readline、ncurses这两个库,所以我们手动添加上

然后编译,会报错

这里是重复定义了,我们直接打开readline.h,根据报错信息,将重复定义的函数注释掉

再次编译还是会报错

这里是类型错了,同样的,找到这个文件,进行修改

根据定义类型,可以知道,这个是有符号64位,直接将%zd改为%lld

再次编译安装直接通过

 可以看到,成功生成了目标文件

至此,bluez的交叉编译完成

总结

        一开始面对bluez的编译是真的头疼,因为东西太多,而且网上的教程也比较杂,搞了一两天也没什么头绪,后面换了一个思路,先编译PC版的,可以后思路一下就清晰了,然后很快arm的就编出来了。

        希望我的文章对你有所帮助!

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值