1. 为什么需要在aarch64平台交叉编译avahi最近在折腾一个嵌入式项目需要在aarch64架构的开发板上部署avahi服务。avahi是个挺有意思的东西它是开源的Zeroconf实现简单说就是能让设备在局域网内自动发现彼此不需要手动配置IP地址。想象一下你家里有打印机、NAS、智能音箱等各种设备avahi能让它们自动找到对方就像给每个设备装了个自动名片交换器。但问题来了开发板资源有限没法直接在上面编译avahi。这时候就需要交叉编译——在x86电脑上编译出能在aarch64开发板上运行的程序。这个过程就像在中国工厂生产销往美国的产品需要按照美国标准来调整生产线。我刚开始尝试时踩了不少坑比如依赖库缺失、编译参数不对、链接错误等等折腾了好几天才搞定。下面就把完整过程分享出来希望能帮你少走弯路。2. 搭建交叉编译环境2.1 安装交叉编译工具链工欲善其事必先利其器。首先需要准备aarch64平台的交叉编译工具链。我用的是Linaro提供的GCC 7.5版本这个版本比较稳定兼容性也好。安装步骤很简单wget https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/aarch64-linux-gnu/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz mv gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu ~/chain_tools/然后创建环境变量配置文件gcc_7.5.sh#!/bin/sh export PATH/home/yourname/chain_tools/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin:$PATH export ARCHarm64 export CROSS_COMPILEaarch64-linux-gnu-注意这里有几个容易出错的地方路径中的yourname要替换成你的实际用户名解压后的工具链目录名很长建议重命名为简短名称记得给脚本加执行权限chmod x gcc_7.5.sh2.2 准备依赖库avahi依赖几个关键库需要先交叉编译好expatXML解析库libdaemon守护进程库dbus进程间通信系统建议按这个顺序编译因为后面的库会依赖前面的。我刚开始尝试时顺序搞反了结果各种报错浪费了不少时间。3. 交叉编译依赖库3.1 编译expat-2.6.4expat是个轻量级XML解析库avahi用它来解析配置文件。下载源码后编译过程如下wget https://sourceforge.net/projects/expat/files/expat/2.6.4/expat-2.6.4.tar.xz tar -xvf expat-2.6.4.tar.xz cd expat-2.6.4/ source ~/env/gcc_7.5.sh ./configure --hostaarch64-linux-gnu \ CCaarch64-linux-gnu-gcc \ CXXaarch64-linux-gnu-g \ --prefix$(pwd)/../expat_install \ --enable-shared \ --enable-static make -j$(nproc) make install编译完成后安装目录会生成在expat_install下包含bin、include、lib等子目录。特别注意后面的dbus编译会用到这个路径建议记下来。3.2 编译libdaemon-0.14libdaemon提供了守护进程相关的功能。编译时遇到个坑老版本的config.sub和config.guess文件可能不认识aarch64平台需要更新wget https://0pointer.de/lennart/projects/libdaemon/libdaemon-0.14.tar.gz tar -xvf libdaemon-0.14.tar.gz cd libdaemon-0.14/ # 更新平台识别文件 wget -O ./config.sub https://git.savannah.gnu.org/gitweb/?pconfig.git;ablob_plain;fconfig.sub;hbHEAD wget -O ./config.guess https://git.savannah.gnu.org/gitweb/?pconfig.git;ablob_plain;fconfig.guess;hbHEAD chmod x config.guess config.sub # 设置编译环境 export CCaarch64-linux-gnu-gcc export CXXaarch64-linux-gnu-g echo ac_cv_func_setpgrp_voidyes config.cache ./configure --hostaarch64-linux-gnu \ --prefix$(pwd)/../libdaemon_install \ --config-cache make -j$(nproc) make install这里有个小技巧--config-cache参数可以缓存配置检查结果加快后续重新配置的速度。编译完成后同样记下安装路径libdaemon_install。3.3 编译dbus-1.3.0dbus是Linux下常用的进程间通信机制avahi用它来发布服务信息。编译时需要指定之前编译的expat路径wget https://dbus.freedesktop.org/releases/dbus/dbus-1.3.0.tar.gz tar -xvf dbus-1.3.0.tar.gz cd dbus-1.3.0/ source ~/env/gcc_7.5.sh ./configure --prefix$(pwd)/../dbus1.3.0_install \ --enable-testsno \ --hostaarch64-linux-gnu \ --disable-selinux \ CFLAGS-I/home/yourname/project/expat_install/include \ LDFLAGS-L/home/yourname/project/expat_install/lib make -j$(nproc) make install特别注意CFLAGS和LDFLAGS中的路径要替换成你实际的expat安装路径如果遇到权限问题可能需要用chmod修改目录权限编译时间较长耐心等待4. 交叉编译avahi4.1 准备avahi源码avahi的版本选择很重要我推荐使用v0.8稳定分支git clone https://github.com/avahi/avahi.git cd avahi git checkout v0.84.2 配置编译环境avahi的配置比较复杂需要设置很多环境变量source ~/env/gcc_7.5.sh # 设置头文件和库路径 export CPPFLAGS-I/home/yourname/project/expat_install/include \ -I/home/yourname/project/dbus1.3.0_install/include/dbus-1.0/dbus export CFLAGS-I/home/yourname/project/expat_install/include \ -I/home/yourname/project/dbus1.3.0_install/include/dbus-1.0/dbus export LDFLAGS-L/home/yourname/project/expat_install/lib \ -L/home/yourname/project/dbus1.3.0_install/lib \ -Wl,-rpath-link,/home/yourname/project/dbus1.3.0_install/lib \ -Wl,-rpath,/home/yourname/project/dbus1.3.0_install/lib export LIBS-ldbus-1 -lpthread -lrt export PKG_CONFIG_PATH/home/yourname/project/dbus1.3.0_install/lib/pkgconfig export PKG_CONFIG_LIBDIR/home/yourname/project/dbus1.3.0_install/lib4.3 配置和编译avahiavahi有很多可选功能嵌入式环境下我们只需要核心功能./autogen.sh ./configure --hostaarch64-linux-gnu \ --prefix$(pwd)/build-aarch64 \ --with-distroarchlinux \ --localstatedir$(pwd)/log \ --with-xmlnone \ --with-avahi-userroot \ --with-avahi-grouproot \ --disable-qt3 --disable-qt4 --disable-qt5 \ --disable-gtk --disable-gtk3 \ --disable-python --disable-mono --disable-pygobject \ --disable-doxygen --disable-manpages \ --disable-libevent --disable-FEATURE \ --disable-glib --disable-gobject \ --disable-daemon --disable-dnsconfd \ --disable-utils --disable-gdbm \ --enable-autoipd \ DBUS_CFLAGS-I/home/yourname/project/dbus1.3.0_install/include/dbus-1.0 \ -I/home/yourname/project/dbus1.3.0_install/lib/dbus-1.0/include \ DBUS_LIBS-L/home/yourname/project/dbus1.3.0_install/lib \ -ldbus-1 -lpthread -lrt \ -Wl,-rpath-link,/home/yourname/project/dbus1.3.0_install/lib \ -Wl,-rpath,/home/yourname/project/dbus1.3.0_install/lib \ LIBDAEMON_CFLAGS-I/home/yourname/project/libdaemon_install/include \ LIBDAEMON_LIBS-L/home/yourname/project/libdaemon_install/lib -ldaemon make -j$(nproc) make install4.4 常见问题解决在实际编译过程中我遇到了几个典型问题链接错误提示找不到libdbus-1.so.3 解决方法确保LDFLAGS中正确设置了库路径特别是-Wl,-rpath-link参数头文件缺失编译时提示找不到dbus头文件 解决方法检查CFLAGS和CPPFLAGS中的头文件路径是否正确版本不兼容某些函数未定义 解决方法确认所有依赖库版本匹配特别是dbus和expat的版本5. 部署到aarch64平台编译完成后在avahi目录下的build-aarch64文件夹中就是交叉编译好的程序。需要将整个文件夹拷贝到目标板的文件系统中。部署时要注意保持目录结构不变确保动态库路径正确可能需要设置LD_LIBRARY_PATH环境变量测试avahi是否工作./build-aarch64/sbin/avahi-daemon -D如果一切正常你应该能在局域网中看到设备广播的服务信息。我在实际项目中用这个方案成功实现了多个嵌入式设备的自动发现功能大大简化了网络配置工作。