在Ubuntu 16.04用Linaro交叉编译工具链构建树莓派3 Raspbian版gattlib失败求指导
树莓派3 Raspbian系统gattlib交叉编译详细步骤(Ubuntu 16.04 + Linaro工具链)
我之前帮不少开发者解决过树莓派交叉编译gattlib的问题,结合你的场景(Ubuntu 16.04 + Linaro工具链 + Raspbian for Pi3),给你整理一套经过验证的步骤,你可以一步步尝试:
1. 搭建交叉编译环境
首先得确保Linaro ARM工具链正常可用,Ubuntu 16.04可以直接通过包管理器安装,或者手动下载指定版本:
- 方式一:通过apt安装官方工具链
sudo apt-get update sudo apt-get install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
- 方式二:手动下载Linaro工具链(适配Raspbian的稳定版本,比如7.3)
# 从Linaro官方下载对应版本的arm-linux-gnueabihf工具链包 # 解压到系统目录 sudo tar -xvf gcc-linaro-7.3.1-2018.05-x86_64_arm-linux-gnueabihf.tar.xz -C /opt/ # 添加到环境变量 export PATH=/opt/gcc-linaro-7.3.1-2018.05-x86_64_arm-linux-gnueabihf/bin:$PATH
- 验证工具链是否生效:
arm-linux-gnueabihf-gcc --version
能正常输出版本信息就说明环境没问题。
2. 准备Raspbian Sysroot(关键!多数失败根源)
Sysroot是树莓派系统的根文件系统副本,交叉编译时需要它来找到目标平台的头文件和库,有两种获取方式:
- 方式一:从你的树莓派直接拷贝(最准确)
在树莓派上执行打包命令:
sudo tar -czf raspbian-sysroot.tar.gz --exclude=/proc --exclude=/sys --exclude=/dev --exclude=/tmp --exclude=/run /
然后通过scp传到Ubuntu机器:
scp pi@<你的树莓派IP>:/home/pi/raspbian-sysroot.tar.gz . sudo tar -xvf raspbian-sysroot.tar.gz -C /opt/
- 方式二:下载预编译的Raspbian镜像提取Sysroot(适合没有树莓派的情况)
# 从树莓派官方下载适配Pi3的Raspbian稳定版本镜像(比如Stretch) unzip <你的Raspbian镜像文件名>.zip # 挂载镜像分区提取文件 sudo mkdir -p /opt/raspbian-sysroot sudo kpartx -av <你的Raspbian镜像文件名>.img sudo mount /dev/mapper/loop0p2 /mnt sudo cp -a /mnt/* /opt/raspbian-sysroot/ # 卸载清理 sudo umount /mnt sudo kpartx -dv <你的Raspbian镜像文件名>.img
- 修复Sysroot内的失效软链接:
拷贝后的Sysroot会有很多软链接失效,需要修复:
# 修复几个常见的库链接 sudo sed -i 's/^\(lib\)\(.*\)\.so$/\1\2.so.1/' /opt/raspbian-sysroot/usr/lib/arm-linux-gnueabihf/libblkid.so sudo sed -i 's/^\(lib\)\(.*\)\.so$/\1\2.so.1/' /opt/raspbian-sysroot/usr/lib/arm-linux-gnueabihf/libmount.so sudo sed -i 's/^\(lib\)\(.*\)\.so$/\1\2.so.1/' /opt/raspbian-sysroot/usr/lib/arm-linux-gnueabihf/libuuid.so # 批量修复所有失效软链接 find /opt/raspbian-sysroot/usr/lib/arm-linux-gnueabihf -type l -exec bash -c 'file="{}"; target=$(readlink "$file"); if [ ! -e "/opt/raspbian-sysroot/usr/lib/arm-linux-gnueabihf/$target" ]; then sudo ln -sf "$target" "$file"; fi' \;
3. 安装编译依赖
- 主机Ubuntu上安装编译工具和依赖:
sudo apt-get install cmake libbluetooth-dev libreadline-dev
- 目标树莓派上的依赖(需提前安装在树莓派,再同步到Sysroot):
在树莓派上执行:
sudo apt-get install libbluetooth-dev libreadline-dev
如果是用预编译镜像的Sysroot,也可以直接在Ubuntu上通过QEMU模拟安装,但直接在树莓派上安装更简单可靠。
4. 获取gattlib源码
# 克隆gattlib官方仓库 git clone https://github.com/labapart/gattlib.git cd gattlib # 建议切换到稳定版本,避免分支上的不稳定问题 git checkout v0.2.0
5. 配置CMake交叉编译参数
创建编译目录并配置CMake,这一步是核心,要指定目标平台、工具链和Sysroot:
mkdir build && cd build cmake .. \ -DCMAKE_SYSTEM_NAME=Linux \ -DCMAKE_SYSTEM_PROCESSOR=arm \ -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc \ -DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ \ -DCMAKE_SYSROOT=/opt/raspbian-sysroot \ -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \ -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \ -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \ -DGATTLIB_BUILD_EXAMPLES=ON # 可选,开启示例程序编译
如果配置成功,会输出Configuring done和Generating done的提示,没有报错就可以继续。
6. 编译与安装
# 用多核心加速编译 make -j$(nproc) # 将编译好的库和头文件安装到Sysroot,方便后续部署到树莓派 sudo make install DESTDIR=/opt/raspbian-sysroot # 或者单独打包编译产物,方便传输 mkdir -p ../gattlib-pi3 cp -r /opt/raspbian-sysroot/usr/local/include/gattlib ../gattlib-pi3/ cp /opt/raspbian-sysroot/usr/local/lib/libgattlib.so* ../gattlib-pi3/ cp /opt/raspbian-sysroot/usr/local/bin/gatttool* ../gattlib-pi3/
7. 部署到树莓派
把打包好的编译产物传到树莓派:
scp -r ../gattlib-pi3 pi@<你的树莓派IP>:/home/pi/
然后在树莓派上完成安装:
sudo cp /home/pi/gattlib-pi3/include/gattlib/* /usr/local/include/ sudo cp /home/pi/gattlib-pi3/libgattlib.so* /usr/local/lib/ sudo cp /home/pi/gattlib-pi3/gatttool* /usr/local/bin/ sudo ldconfig # 更新系统库缓存
常见问题排查
- CMake找不到蓝牙库:检查Sysroot内
/opt/raspbian-sysroot/usr/lib/arm-linux-gnueabihf/libbluetooth.so是否存在,若缺失,在树莓派上安装libbluetooth-dev后重新生成Sysroot。 - 编译时头文件找不到:确认CMake的
CMAKE_SYSROOT路径正确,且CMAKE_FIND_ROOT_PATH_MODE_INCLUDE设置为ONLY。 - 链接时出现未定义符号:检查所有依赖是否都是ARM架构的,或者Sysroot内的库是否完整。
内容的提问来源于stack exchange,提问作者Paul Tomov
相关产品推荐
相关产品推荐

