【 所有文章汇总】
前面几篇文章,主要讲解了蓝牙协议栈层面的内容,本篇来从源码层面来分析!
蓝牙协议栈,如何在代码层面将其落地?用的最多的就是开源的Bluez
所实现的蓝牙协议栈了!
Bluez
官网:http://www.bluez.org/
Bluez
的交叉编译较为复杂,其依赖的文件之多,不失为一个练习交叉编译的好机会!
本文我们旨在研究交叉编译的手法,以一敌百,了解交叉编译的底层方法。
最后,文末也描述一种简单的编译方法,仅供了解。
前往Bluez官网,下载
Bluez
源码包
目前最新的是Bluez5.6.5
版本,以该版本为案例进行分析。
wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.65.tar.xz # 下载Bluez
tar -xvf bluez-5.65.tar.xz # 解压bluez
cd bluez-5.64/ # 进入目录
首先,我们进入到bluez-5.65
后,查看README
文件,我们可以看到其依赖项:
In order to compile Bluetooth utilities you need following software packages:
- GCC compiler
- GLib library
- D-Bus library
- udev library (optional)
- readline (command line clients)
由上可知,欲安装Bluez
,需要对其依赖项进行逐一安装,下面我们依次进行安装!
mkdir bluez_output
cd bluez_output
export bluez_output=/home/dong/WorkSpace/Program/BlueZ/bluez_output #设置环境变量
GCC
交叉编译器,我们就直接忽略了哈……
GLib
是一个通用的、可移植的实用程序库,它提供了许多有用的数据类型、宏、类型转换、字符串实用程序、文件实用程序、主循环抽象等。
GLib官网:https://docs.gtk.org/glib
GLib下载地址:Gitlab下载、站点下载
我们下载的是
glib-2.46.2.tar.gz
新版本的
GLib
需要Meson
工具编译,因此我们这里使用2.46.2
版本的,可以通过cmake
编译
wget https://download.gnome.org/sources/glib/2.46/glib-2.46.2.tar.xz #下载GLib
tar -xvf glib-2.46.2.tar.xz # 解压
cd glib-2.46.2/ # 进入目录
然后手动创建arm-linux.cache
文件,手动写入下面内容:
touch arm-linux.cache # 创建文件, 添加下面内容
glib_cv_long_long_format=ll
glib_cv_stack_grows=no
glib_cv_working_bcopy=no
glib_cv_sane_realloc=yes
glib_cv_have_strlcpy=no
glib_cv_va_val_copy=yes
glib_cv_rtldglobal_broken=no
glib_cv_uscore=no
ac_cv_func_posix_getpwuid_r=yes
ac_cv_func_nonposix_getpwuid_r=no
ac_cv_func_posix_getgrgid_r=no
glib_cv_use_pid_surrogate=no
ac_cv_func_printf_unix98=no
ac_cv_func_vsnprintf_c99=no
ac_cv_path_GLIB_COMPILE_SCHEMAS=yes
然后接着执行下面命令:
./configure --prefix=$bluez_output CC="arm-linux-gnueabihf-gcc -I$bluez_output/include -L$bluez_output/lib" --host=arm-linux-gnueabihf --cache-file=arm-linux.cache
make -j8
make install
如果报错:error: format not a string literal, format string not checked
可以看下面两篇文章,有解决方案
https://www.cnblogs.com/yuandaozhe/p/14365389.html
https://blog.csdn.net/wwwyue1985/article/details/113359706
如果报错:fatal error: ffi.h: No such file or directory
表明了
GLib
仍需要依赖libffi
库,我们需要提前安装Libffi
libffi
是可移植外部函数接口库,是构建GLib
的先决条件。它是一个接口,允许用一种语言编写的代码调用用另一种语言编写的代码。
libffi下载路径:https://github.com/libffi/libffi/releases/
libffi下载版本:libffi-3.4.2.tar.gz
手动下载后,执行下面命令:
tar -zxvf libffi-3.4.3.tar.gz # 解压
cd libffi-3.4.3/ # 切换目录
./configure --prefix=$bluez_output CC="arm-linux-gnueabihf-gcc -I$bluez_output/include -L$bluez_output/lib" --host=arm-linux-gnueabihf
make -j8
make install
安装完
libffi
后,再次回到GLib
进行安装,可见报错:fatal error: zlib.h: No such file or directory说明
GLib
仍然依赖zlib
库,需要安装zlib
zlib是一个压缩库,是构建GLib的先决条件。
zlib下载地址:http://zlib.net/zlib-1.2.12.tar.gz
zlib下载版本:zlib-1.2.12.tar.gz
手动下载后,执行下面命令:
tar -zxvf zlib-1.2.12.tar.gz
cd zlib-1.2.12/
./configure --prefix=$bluez_output --includedir=$bluez_output/include --libdir=$bluez_output/lib
#vim Makefile 将CC变量改为自己的交叉编译器arm-linux-gnueabihf-gcc
CC=arm-linux-gnueabihf-gcc
LDSHARED=arm-linux-gnueabihf-gcc -shared -Wl,-soname,libz.so.1,--version-script,zlib.map
CPP=arm-linux-gnueabihf-gcc -E
AR=arm-linux-gnueabihf-ar
RANLIB=arm-linux-gnueabihf-ranlib
make -j8
make install
安装完zlib
后,再回头安装Glib
,即可完毕!
D-Bus
是一个用于进程间通信和协调的简单系统。
D-Bus
下载目录:https://dbus.freedesktop.org/releases/dbus/
D-Bus
下载版本:dbus-1.15.0.tar.xz
wget https://dbus.freedesktop.org/releases/dbus/dbus-1.15.0.tar.xz # 下载
tar -xvf dbus-1.15.0.tar.xz # 解压
cd dbus-1.15.0/ # 切换目录
_____________________________________________________________ # 先看下文
./configure --prefix=$bluez_output CC="arm-linux-gnueabihf-gcc -I$bluez_output/include -L$bluez_output/lib" --host=arm-linux-gnueabihf --enable-selinux=no --without-x # 生成Makefile
make -j8 # 编译
make install # 安装到对应目录
我们先不着急安装,查看一下README
和INSTALL
文件,发现D-bus
的安装,必须依赖Expat
库!
当然如果你直接安装,它也肯定会报错的,因为缺少所依赖的库!
Requisite:
- Gettext
- expat
Optional:
- libselinux (for SELinux integration)
- doxygen (for API documentation)
- xmlto or meinproc4 (for Spec & other XML documentation)
下面我们来安装Expat
库!
Expat
是一个用C编写的XML
解析器库,是D-Bus
守护进程所需的惟一依赖项。
Expat
下载路径:https://libexpat.github.io/,https://github.com/libexpat/libexpat/releases
Expat
下载版本:expat-2.4.9.tar.xz
tar -zvf expat-2.4.9.tar.gz
cd expat-2.4.9/
./configure --prefix=$bluez_output CC="arm-linux-gnueabihf-gcc -I$bluez_output/include -L$bluez_output/lib" --host=arm-linux-gnueabihf
make -j8
make install
此时,会在$bluez_output
目录下,看到安装后所生成的lib
和include
的一些文件
--enable-selinux=no
--without-x
是一些配置信息,不适用selinux
和x11
支持,否则可能会报错!
安装完expat
库后,我们回头安装D-bus
!
Readline
库提供了一组供应用程序使用的函数,并且允许用户在输入命令行时编辑它们。
下载地址:http://git.savannah.gnu.org/cgit/readline.git?h=devel
下载版本:readline-8.2.tar.gz
wget http://git.savannah.gnu.org/cgit/readline.git/snapshot/readline-8.2.tar.gz
tar -xvf readline-8.2.tar.gz
cd readline-8.2/
./configure --prefix=$bluez_output CC="arm-linux-gnueabihf-gcc -I$bluez_output/include -L$bluez_output/lib" --host=arm-linux-gnueabihf bash_cv_wcwidth_broken=yes
make -j8
make install
安装完之后,我们就来安装最后的大Boss
——``Bulez`
cd bluez-5.65/
mkdir output
./configure --prefix=$bluez_output CC="arm-linux-gnueabihf-gcc -I$bluez_output/include -L$bluez_output/lib" PKG_CONFIG_PATH=$bluez_output/lib/pkgconfig --host=arm-linux-gnueabihf --disable-systemd --disable-udev --disable-cups --disable-obex --enable-library
make SHLIB_LIBS=-lncurses -j8
make install
如果报类似以下错误:
collect2: error: ld returned 1 exit status
make[1]: *** [Makefile:5503: monitor/btmon] Error 1
/home/dong/WorkSpace/Program/BlueZ/bluez_output/lib/libreadline.so: undefined reference to `tputs'
/home/dong/WorkSpace/Program/BlueZ/bluez_output/lib/libreadline.so: undefined reference to `tgoto'
/home/dong/WorkSpace/Program/BlueZ/bluez_output/lib/libreadline.so: undefined reference to `tgetflag'
/home/dong/WorkSpace/Program/BlueZ/bluez_output/lib/libreadline.so: undefined reference to `UP'
/home/dong/WorkSpace/Program/BlueZ/bluez_output/lib/libreadline.so: undefined reference to `tgetent'
/home/dong/WorkSpace/Program/BlueZ/bluez_output/lib/libreadline.so: undefined reference to `tgetnum'
/home/dong/WorkSpace/Program/BlueZ/bluez_output/lib/libreadline.so: undefined reference to `PC'
/home/dong/WorkSpace/Program/BlueZ/bluez_output/lib/libreadline.so: undefined reference to `tgetstr'
/home/dong/WorkSpace/Program/BlueZ/bluez_output/lib/libreadline.so: undefined reference to `BC'
单看
Log
,肯定是readline
库中缺少一些东西,这些东西就是缺少了ncurses
库所导致的!
ncurses
是readline
所依赖的一个库
下载地址:http://ftp.gnu.org/pub/gnu/ncurses
下载版本:ncurses-6.3.tar.gz
wget https://ftp.gnu.org/pub/gnu/ncurses/ncurses-6.3.tar.gz
tar -zxvf ncurses-6.3.tar.gz
cd ncurses-6.3/
./configure --prefix=$bluez_output CC="arm-linux-gnueabihf-gcc -I$bluez_output/include -L$bluez_output/lib" CXX="arm-linux-gnueabihf-g++" --host=arm-linux-gnueabihf --without-cxx --without-cxx-binding --without-ada --without-manpages --enable-overwrite --without-debug --without-tests --with-shared --without-tests --without-progs
make -j8
make install
安装完ncurse
后,我们再次安装readline
,需要包含ncurse
库!
cd readline-8.2/
./configure --prefix=$bluez_output CC="arm-linux-gnueabihf-gcc -I$bluez_output/include -L$bluez_output/lib" --host=arm-linux-gnueabihf bash_cv_wcwidth_broken=yes
make SHLIB_LIBS=-lncurses -j8
make install
将ncurses
安装后,再次回到bluez
,执行安装步骤,并且引入ncurses
库!
cd bluez-5.65/
mkdir output
./configure --prefix=$bluez_output CC="arm-linux-gnueabihf-gcc -I$bluez_output/include -L$bluez_output/lib -lncurses" PKG_CONFIG_PATH=$bluez_output/lib/pkgconfig --host=arm-linux-gnueabihf --disable-systemd --disable-udev --disable-cups --disable-obex --enable-library
make -j8
make install
至此,Bluez
交叉编译结束!
简单一点的方法是什么?
就是通过构建工具来编译,直接通过类似于buildroot
等类似的构建工具,直接选中bluez
的外部包,直接编译也可以的:)