adb服务在嵌入式ARM Linux平台移植全过程记录
ADB 服务在 NT98336 平台移植为例
全过程详解
Android Debug Bridge Daemon (adbd) Cross-Compilation Guide
基于 AOSP platform-tools-34.0.5 / Debian 源码包
目标平台: Novatek NT98336 (AArch64 Cortex-A53)工具链: aarch64-ca53-linux-gnueabihf 8.4 (glibc 2.30)目录
1. 概述与背景
2. 环境准备
2.1 主机环境要求
2.2 交叉工具链
2.3 工作目录结构
3. 源码获取
3.1 Debian 源码包方式 (推荐)
3.2 直接 AOSP 方式
4. 外部依赖交叉编译
4.1 OpenSSL 1.1.1w
4.2 Protobuf 3.21.12
4.3 Brotli / LZ4 / Zstd / libusb
4.4 libcap (可选)
5. 源码修补与兼容层
5.1 Debian 补丁
5.2 GCC 8.4 兼容性修复
5.3 BoringSSL → OpenSSL 兼容层
5.4 TLS 存根
5.5 IPv6 → IPv4 回退
5.6 VSOCK 移除
6. Android 支撑库编译
7. ADB 公共库 (libadb.a)
8. ADB 守护进程 (adbd)
9. 完整构建脚本
10. 部署与运行
10.1 部署文件
10.2 运行命令
10.3 验证方法
11. 常见问题与排错
12. 附录:关键文件清单
1. 概述与背景
Android Debug Bridge (ADB) 是 Android 开发中不可或缺的调试工具。本文将详细介绍如何将 ADB 守护进程 (adbd) 移植到 Novatek NT98336 嵌入式 Linux 平台上。NT98336 是一款基于 ARM Cortex-A53 的 SoC,运行 Buildroot 构建的嵌入式 Linux 系统 (glibc 2.30, Linux 4.19)。该平台未启用 IPv6,且没有 Android 运行时环境。关键约束
- 交叉工具链: aarch64-ca53-linux-gnueabihf 8.4 (GCC 8.4.0)
- 目标系统: Buildroot 2020.02, glibc 2.30, 无 IPv6
- ADB 源码: AOSP platform-tools-34.0.5 (通过 Debian 源码包 android-platform-tools_34.0.5)
- 网络限制: 主机可以访问 Debian 镜像,但无法直接访问 GitHub / AOSP
- 认证: auth_required = false (嵌入式 Linux 非 Android,跳过认证)
2. 环境准备
2.1 主机环境要求
- Linux 发行版 (Ubuntu 20.04+ / Debian 11+ 推荐)
2.2 交叉工具链
本项目使用 Buildroot 2020.02 生成的 aarch64-ca53-linux-gnueabihf 工具链,位于 /data/linux05/CrossCompiler/aarch64-ca53-linux-gnueabihf-8.4/。- aarch64-ca53-linux-gnu-gcc (C 编译器)
- aarch64-ca53-linux-gnu-g++ (C++ 编译器)
- aarch64-ca53-linux-gnu-ar (归档工具)
- aarch64-ca53-linux-gnu-ranlib (索引工具)
- aarch64-ca53-linux-gnu-strip (剥离符号)
aarch64-ca53-linux-gnu-gcc --version预期输出: aarch64-ca53-linux-gnu-gcc (crosstool-NG) 8.4.0
aarch64-ca53-linux-gnu-gcc -print-sysroot预期输出: 工具链 sysroot 路径
2.3 工作目录结构
构建输出目录
完整构建脚本
源码压缩包
交叉编译依赖安装目录
工作目录(解压、兼容层代码)
.o 目标文件
最终二进制
静态库
解压后的源码
│ ├── packages/modules/adb/ADB 核心源码
Android core 库
Android libbase
Android logging
│ ├── frameworks/native/libs/adbd_auth/adbd_auth
Debian 补丁
部署压缩包
本文档生成脚本
3. 源码获取
3.1 Debian 源码包方式 (推荐)
通过 Debian 源码包获取 ADB 源码,避免直接从 AOSP 下载(需翻墙):安装 dpkg-dev
sudo apt install dpkg-dev下载 Debian 源码包
dget -x http://deb.debian.org/debian/pool/main/a/android-platform-tools/android-platform-tools_34.0.5-1.debian.tar.xz或者使用 apt-get source
apt-get source android-platform-tools解压主源码
mkdir -p /path/to/src && cd /path/to/srctar xf ../android-platform-tools_34.0.5.orig.tar.xztar xf ../android-platform-tools_34.0.5-1.debian.tar.xz -C .补丁在 debian/patches/
3.2 直接 AOSP 方式
git clone https://android.googlesource.com/platform/packages/modules/adbgit clone https://android.googlesource.com/platform/system/coregit clone https://android.googlesource.com/platform/system/libbasegit clone https://android.googlesource.com/platform/system/logginggit clone https://android.googlesource.com/platform/frameworks/native切换到 tag android-14.0.0_r34 以获得 platform-tools-34.0.5 对应版本
注: 本移植基于 Debian 源码包版本,代码路径前缀为 src/packages/modules/adb/。4. 外部依赖交叉编译
所有外部依赖全部编译为静态库 (.a),安装到 $PREFIX (=build/sysroot)。以下路径均以工作目录顶层为基准。4.1 OpenSSL 1.1.1w
ADB 需要 OpenSSL 提供加解密功能(RSA 密钥、证书等),编译命令:tar xf ../downloads/openssl-1.1.1w.tar.gzexport CC=aarch64-ca53-linux-gnu-gccexport AR=aarch64-ca53-linux-gnu-arexport RANLIB=aarch64-ca53-linux-gnu-ranlib./Configure linux-aarch64 \--prefix=$PREFIX --libdir=lib \no-shared no-asm no-tests \4.2 Protobuf 3.21.12
ADB 使用 Protocol Buffers 作为序列化格式。需要编译两个版本:mkdir -p build/work/protobuf-host/buildcd build/work/protobuf-host/build取消交叉编译环境变量
unset CC CXX AR AS LD STRIP NM OBJDUMP CROSS_COMPILEexport CC=gcc CXX=g++ AR=ar RANLIB=ranlibcmake ../../protobuf-3.21.12/cmake \-DCMAKE_INSTALL_PREFIX=$PWD/.. \-Dprotobuf_BUILD_TESTS=OFF \-Dprotobuf_BUILD_PROTOC_BINARIES=ON \-Dprotobuf_BUILD_LIBPROTOBUF=OFF \-Dprotobuf_BUILD_LIBPROTOC=OFFmkdir -p build/work/protobuf-3.21.12/build_aarch64cd build/work/protobuf-3.21.12/build_aarch64-DCMAKE_SYSTEM_NAME=Linux \-DCMAKE_SYSTEM_PROCESSOR=aarch64 \-DCMAKE_C_COMPILER=aarch64-ca53-linux-gnu-gcc \-DCMAKE_CXX_COMPILER=aarch64-ca53-linux-gnu-g++ \-DCMAKE_INSTALL_PREFIX=$PREFIX \-Dprotobuf_BUILD_TESTS=OFF \-Dprotobuf_BUILD_PROTOC_BINARIES=OFF \4.3 Brotli / LZ4 / Zstd / libusb
brotli 1.0.9 cmake + 静态库 libbrotli*-static.alz4 1.9.4 make lib liblz4.azstd 1.4.8 make lib-mt libzstd.alibusb 1.0.24 configure + 静态 libusb-1.0.amkdir -p build/work/brotli-1.0.9/build_aarch64 && cd $_-DCMAKE_SYSTEM_NAME=Linux \-DCMAKE_SYSTEM_PROCESSOR=aarch64 \-DCMAKE_C_COMPILER=aarch64-ca53-linux-gnu-gcc \-DCMAKE_CXX_COMPILER=aarch64-ca53-linux-gnu-g++ \-DCMAKE_INSTALL_PREFIX=$PREFIX \cd build/work/libusb-1.0.24./configure --host=aarch64-ca53-linux-gnu \--enable-static --disable-shared \--enable-udev=no --enable-examples=no4.4 libcap (可选)
libcap 提供 Linux capabilities 支持。可从 Debian arm64 包直接提取静态库:下载 Debian arm64 libcap-dev 包
wget http://deb.debian.org/debian/pool/main/libc/libcap2/libcap-dev_2.66-5_arm64.debmkdir -p /tmp/libcap_extract && cd /tmp/libcap_extractar x ../libcap-dev_2.66-5_arm64.debcp usr/lib/aarch64-linux-gnu/libcap.a $PREFIX/lib/cp -r usr/include/sys $PREFIX/include/5. 源码修补与兼容层
5.1 Debian 补丁
Debian 源码包附带了针对 GCC 兼容性、架构适配等的一系列补丁,位于 debian/patches/series。应用方式:patch -p1 -N -r- < debian/patches/$patchdone < debian/patches/series5.2 GCC 8.4 兼容性修复
GCC 8.4 不支持 C++20 特性,需要以下适配:GCC 8.4 的 头文件缺失。提供 build/work/span 兼容头:// build/work/span - std::span C++17 backport// ... 提供 template class span { ... };GCC 8.4 的 std::string_view 没有 starts_with/ends_with 方法。提供 build/work/string_view_compat.h,在编译时通过 -include string_view_compat.h 全局注入。// build/work/string_view_compat.hinline bool starts_with(string_view sv, string_view prefix) {return sv.substr(0, prefix.size()) == prefix;GCC 8.4 不支持 CLANG 的线程安全注解宏:// build/work/thread_annotations_null.h#defineTHREAD_ANNOTATION_ATTRIBUTE__(x)d) __attribute__((uninitialized)) ICEGCC 8.4 在处理 __attribute__((uninitialized)) 与 VLA 时 Internal Compiler Error: expand_expr_real_1。移除该属性即可。5.3 BoringSSL → OpenSSL 兼容层
ADB 源码使用 BoringSSL (Google 的 OpenSSL fork) API。需要提供兼容层:// build/work/bssl_compat.htemplate using UniquePtr = std::unique_ptr;// 提供 BoringSSL 风格的 RAII 包装using CRYPTO_BUFFER = void;using SSL_CREDENTIAL = void;// build/work/openssl_compat.h// 提供 BoringSSL-only 函数: BN_le2bn, BN_bn2le_paddedstatic inline BIGNUM* BN_le2bn(const uint8_t* buf, size_t len, BIGNUM* bn) {return BN_lebin2bn(buf, len, bn);static inline int BN_bn2le_padded(uint8_t* out, size_t len, const BIGNUM* in) {// OpenSSL 的 BN_bn2lebinpadreturn BN_bn2lebinpad(in, out, len);5.4 TLS 存根
ADB 支持 TLS 加密配对 (adb over WiFi)。嵌入式平台不启用此功能,提供空实现:// build/work/tls_stubs.cppstd::unique_ptr TlsConnection::Create(TlsRole, std::string_view, std::string_view,int, const std::function&) {return nullptr; // TLS not supported on embedded Linux5.5 IPv6 → IPv4 回退
NT98336 内核未启用 IPv6,而 ADB 使用 AF_INET6 监听。修改 sysdeps/posix/network.cpp,添加 network_inaddr_any_server 实现,优先尝试 AF_INET (IPv4),失败后回退到 AF_INET6:// src/packages/modules/adb/sysdeps/posix/network.cppint network_inaddr_any_server(int port, int type, std::string* error) {for (bool ipv6 : {false, true}) {unique_fd s(socket(ipv6 ? AF_INET6 : AF_INET, type, 0));if (errno != EAFNOSUPPORT) {// setsockopt SO_REUSEADDR5.6 VSOCK 移除
NT98336 不支持 VM Sockets (AF_VSOCK)。修改 daemon/main.cpp,移除 vsock 监听地址,只保留 tcp:// src/packages/modules/adb/daemon/main.cppaddrs.push_back("tcp:" + port);addrs.push_back("vsock:" + port); // ← 删除addrs.push_back("tcp:" + port);6. Android 支撑库编译
编译 ADB 依赖的 Android 基础库为静态库:liblog.a system/logging/liblog/ 日志输出、logcat 兼容libbase.a system/libbase/ 文件 I/O、字符串、属性系统、错误处理libcutils.a system/core/libcutils/ Socket 辅助函数、配置、哈希表libcrypto_utils.a system/core/libcrypto_utils/ Android 公钥格式转换-D_GNU_SOURCE -DPLATFORM_TOOLS_VERSION='\"34.0.5\"' \-DADB_HOST=0 -DADB_VERSION='\"1:34.0.5\"' \-DPAGE_SIZE=4096 -DSSIZE_MAX=9223372036854775807L \-fno-exceptions -fno-strict-aliasing"CFLAGS="-std=gnu17 -D_Nonnull= -D_Nullable= -D_Null_unspecified= $BASE_CFLAGS"CXXFLAGS="-std=gnu++17 -Wno-narrowing -include bssl_compat.h $BASE_CFLAGS"7. ADB 公共库 (libadb.a)
libadb.a 包含 ADB 协议核心代码,被 adbd 和 adb 客户端使用。编译方式:libadb.a 包含以下源文件:
$ADB_SRC/adb_unique_fd.cpp$ADB_SRC/fdevent/fdevent.cpp$ADB_SRC/sysdeps/errno.cpp$ADB_SRC/sysdeps_unix.cpp$ADB_SRC/sysdeps/posix/network.cpp$ADB_SRC/fdevent/fdevent_epoll.cpp$ADB_SRC/crypto/rsa_2048_key.cpp$ADB_SRC/crypto/x509_generator.cpp$ADB_SRC/proto/*.pb.cc (protobuf 生成)$CORE_SRC/diagnose_usb/diagnose_usb.cpp8. ADB 守护进程 (adbd)
ADB 协议主循环
I/O 抽象
$ADB_SRC/adb_listeners.cpp监听器管理
调试跟踪
ADB 服务框架
Socket 抽象
Socket 规格解析
传输层
$ADB_SRC/transport_fd.cpp基于 fd 的传输
类型定义
入口 (已移除 VSOCK)
$ADB_SRC/daemon/transport_local.cppTCP 传输
$ADB_SRC/daemon/adb_wifi.cppWiFi (stub)
认证
USB 传输
$ADB_SRC/daemon/usb_ffs.cppUSB FunctionFS
$ADB_SRC/daemon/jdwp_service.cppJDWP (stub)
$ADB_SRC/daemon/logging.cpp日志
$ADB_SRC/daemon/file_sync_service.cpp文件同步
$ADB_SRC/daemon/services.cpp设备端服务
$ADB_SRC/daemon/shell_service.cppShell 服务
$ADB_SRC/libs/adbconnection/*.cppADB 连接
$CORE_SRC/libasyncio/AsyncIO.cpp异步 I/O
$ADBD_AUTH_SRC/adbd_auth.cpp认证框架
$CXX -o build/adbd build/obj/adbd/*.o \build/libadb.a build/libbase.a build/libcutils.a \build/liblog.a build/libcrypto_utils.a \-lcrypto -lssl -lprotobuf \-lbrotlidec-static -lbrotlienc-static -lbrotlicommon-static \-llz4 -lzstd -lusb-1.0 -lcap \-lpthread -lresolv -ldl -lrt \-pie -static-libstdc++ -static-libgcc \-Wl,-Bstatic -latomic -Wl,-Bdynamic9. 完整构建脚本
以下是完整的 build.sh 构建脚本。所有步骤已整合,运行一次即可完成编译。前提: build/downloads/ 目录下已放置所有依赖的源码压缩包。下载以下源码到 build/downloads/
android-platform-tools_34.0.5.orig.tar.xzandroid-platform-tools_34.0.5-1.debian.tar.xzlibcap-dev_2.66-5_arm64.deb (可选)cd /path/to/adb_aarch64-ca53首次编译前调整 TOPDIR 路径
修改 TOPDIR 为实际路径
bash build/build.sh 2>&1 | tee build.log成功输出:
[HH:MM:SS] === Build Complete ===
build/adbd: ELF 64-bit LSB pie executable, ARM aarch64
-rwxrwxr-x 6.4M build/adbd
10. 部署与运行
10.1 部署文件
主二进制 (6.4 MB, stripped)
部署脚本
systemd 服务文件
SysV init 脚本
在 PC 上
scp adbd-deploy.tar.gz root@192.168.8.116:/tmp/在设备上
tar xzf /tmp/adbd-deploy.tar.gz或者手动复制
10.2 运行命令
直接运行 (默认端口 5555)
指定端口 (非 root 时用高位端口)
ADBD_PORT=15555 /usr/bin/adbd调试模式
ADB_TRACE=transport ADBD_PORT=15555 /usr/bin/adbd 2>&1后台运行
ADBD_PORT=15555 nohup /usr/bin/adbd > /dev/null 2>&1 &10.3 验证方法
在设备上确认监听
netstat -tlnp | grep adbd预期输出: tcp 0 0 0.0.0.0:15555 0.0.0.0:* LISTEN pid/adbd
在 PC 上连接
adb connect 192.168.8.116:15555预期输出:
List of devices attached
192.168.8.116:15555 device
测试 ADB 命令
adb -s 192.168.8.116:15555 shell ls /adb -s 192.168.8.116:15555 push /etc/hosts /tmp/11. 常见问题与排错
Q: bind() 失败,Address family not supported by protocol目标内核未启用 IPv6。确保已应用 IPv6→IPv4 回退补丁 (见 5.5 节)。确认 build/obj/adbd 目录已清理后重新编译。Q: libatomic.so.1: cannot open shared object file目标系统缺少 libatomic。在链接时添加 -Wl,-Bstatic -latomic -Wl,-Bdynamic 将 libatomic 静态链接到 adbd。目标系统的 glibc 版本过低。检查工具链 sysroot 的 glibc 版本: ${TC_PREFIX}-gcc --print-sysroot 找到 libc.so.6 并运行 strings libc.so.6 | grep GLIBC。目标需要 glibc >= 2.29 (工具链自带 2.30)。Q: getentropy symbol not foundglibc 2.25 以下不支持 getentropy。需要目标 glibc >= 2.25。Q: adbd starts but "cannot connect" from PCQ: Protobuf compilation errors确保 protoc 版本与 libprotobuf 版本一致 (均为 3.21.12)。protobuf 目标库编译时需加 -fPIC 以支持 PIE 链接。Q: "already offline" in logs这是 handle_new_connection 中的正常初始化流程,传输层会自动切换为 online 状态,无需处理。12. 附录:关键文件清单
build/build.sh 完整构建脚本 (465 行)build/work/bssl_compat.h BoringSSL → OpenSSL RAII 兼容层build/work/openssl_compat.h BN_le2bn / BN_bn2le_padded 兼容函数build/work/tls_stubs.cpp TLS 空实现存根build/work/string_view_compat.h C++20 starts_with/ends_with 回退build/work/thread_annotations_null.h 线程安全注解禁用build/work/span std::span C++17 回退src/debian/patches/series Debian 补丁清单src/packages/modules/adb/sysdeps/posix/network.cpp IPv4 优先的 network_inaddr_any_serversrc/packages/modules/adb/daemon/main.cpp adbd 入口 (已移除 VSOCK)src/system/core/libcutils/socket_inaddr_any_server_unix.cpp 原始 IPv6-only 实现 (已回退)build/adbd 最终二进制 (6.4 MB, stripped)adbd-deploy.tar.gz 部署压缩包 (2.7 MB)更多精彩推荐:
具身智能时代:机器人开发全栈技术图谱与实战指南(2026版)