截止本文编写,wpa_supplicant的最新版本为2.9,本文将尝试交叉编译该软件以期在海思开发板上运行。
本文使用的测试环境为Hi3516EV200(arm-himix100-linux-) + Kubuntu20.04。
编译之前可能需要安装以下软件包:
sudo apt install pkg-config bison flex libdbus-1-dev
编译过程中若有其它缺失的软件包请自行安装,笔者的开发环境装的软件有点繁杂,难以精简出全部所需项目。
wpa_supplicant的编译依赖openssl、libnl和dbus,dbus又依赖expat,因此在编译wpa_supplicant之前需要首先交叉编译这四个库。
libssl源码下载地址:https://www.openssl.org/source/。当前使用openssl-1.1.1i。
解压源码包,在其目录下执行:
mkdir _install
./config no-asm no-shared no-async --prefix=$PWD/_install --cross-compile-prefix=arm-himix100-linux-
打开Makefile,搜索并删除“-m64”字段,保存并退出。而后执行:
make CC=arm-himix100-linux-gcc
make install
libnl提供应用层和驱动之间的IPC通信机制,当wpa_supplicant仅配置为使用Wext接口时,无需使用该库。参见 3. wpa_supplicant的裁剪 。
libnl源码下载地址:http://www.linuxfromscratch.org/blfs/view/svn/basicnet/libnl.html。当前使用libnl-3.5.0。
解压源码包,在其目录下执行:
mkdir _install
./configure --host=arm-himix100-linux --prefix=$PWD/_install --enable-static
make
make install
expat源码下载地址:https://sourceforge.net/projects/expat/files/expat/。当前使用expat-2.2.10。
解压源码包,在根目录下执行:
mkdir _install
./configure --prefix=$PWD/_install --host=arm-himix100-linux CC=arm-himix100-linux-gcc CXX=arm-himix100-linux-g++ --enable-shared --enable-static
make
make install
dbus源码下载地址:https://dbus.freedesktop.org/releases/dbus/。当前使用dbus-1.13.18。
解压源码包,在其目录下执行(expat路径需根据实际位置修改):
export PKG_CONFIG_PATH=$PWD/../expat-2.2.10/_install/lib/pkgconfig/
mkdir _install
./configure --prefix=$PWD/_install --host=arm-himix100-linux CC=arm-himix100-linux-gcc CXX=arm-himix100-linux-g++ --enable-shared --enable-static CFLAGS=-I../expat-2.2.10/_install/include LDFLAGS=-L../expat-2.2.10/_install/lib --disable-tests
make
make install
wpa_supplicant源码下载地址:Index of wpa_supplicant releases。当前使用wpa_supplicant2.9。
编译可参考:wpa_supplicant、Linux WPA/WPA2/IEEE 802.1X Supplicant。
解压源码包,修改.config文件,在文件对应位置添加交叉编译的dbus、libssl和libnl路径(路径需要根据库的实际位置进行修改):
说明:除了.config文件,这些环境变量也可以放在Makefile文件中,只要能够参与到最终的编译连接过程即可。
CFLAGS += -I../openssl-1.1.1i/_install/include
LIBS += -L../openssl-1.1.1i/_install/lib
CFLAGS += -I../libnl-3.5.0/_install/include
LIBS += -L../libnl-3.5.0/_install/lib
CFLAGS += -I../dbus-1.13.18/_install/include
LIBS += -L../dbus-1.13.18/_install/lib
LDFLAGS += -pthread
注意:静态链接时必须增加上段末句 LDFLAGS += -pthread 而非 LDFLAGS += -lpthread ,否则dbus、libssl和libnl无法找到链接到pthread线程库,错误诸如:
/home/wind/Documents/openssl-1.1.1i/_install/lib/libcrypto.a(b_sock.o): In function `BIO_gethostbyname': b_sock.c:(.text+0x54): warning: gethostbyname is obsolescent, use getnameinfo() instead. /home/wind/Documents/libnl-3.5.0/_install/lib/libnl-3.a(libnl_3_la-socket.o): In function `nl_write_lock': /home/wind/Documents/libnl-3.5.0/./include/netlink-private/netlink.h:259: undefined reference to `pthread_rwlock_wrlock' /home/wind/Documents/libnl-3.5.0/_install/lib/libnl-3.a(libnl_3_la-socket.o): In function `nl_write_unlock': ... /home/wind/Documents/openssl-1.1.1i/_install/lib/libcrypto.a(threads_pthread.o): In function `fork_once_func': threads_pthread.c:(.text+0x20): undefined reference to `pthread_atfork' /home/wind/Documents/openssl-1.1.1i/_install/lib/libcrypto.a(threads_pthread.o): In function `CRYPTO_THREAD_lock_new': threads_pthread.c:(.text+0x5c): undefined reference to `pthread_rwlock_init' /home/wind/Documents/openssl-1.1.1i/_install/lib/libcrypto.a(threads_pthread.o): In function `CRYPTO_THREAD_read_lock': threads_pthread.c:(.text+0x90): undefined reference to `pthread_rwlock_rdlock' /home/wind/Documents/openssl-1.1.1i/_install/lib/libcrypto.a(threads_pthread.o): In function `CRYPTO_THREAD_write_lock': threads_pthread.c:(.text+0xa4): undefined reference to `pthread_rwlock_wrlock' /home/wind/Documents/openssl-1.1.1i/_install/lib/libcrypto.a(threads_pthread.o): In function `CRYPTO_THREAD_unlock': threads_pthread.c:(.text+0xb8): undefined reference to `pthread_rwlock_unlock' /home/wind/Documents/openssl-1.1.1i/_install/lib/libcrypto.a(threads_pthread.o): In function `CRYPTO_THREAD_lock_free': threads_pthread.c:(.text+0xd8): undefined reference to `pthread_rwlock_destroy' /home/wind/Documents/openssl-1.1.1i/_install/lib/libcrypto.a(threads_pthread.o): In function `CRYPTO_THREAD_run_once': threads_pthread.c:(.text+0xfc): undefined reference to `pthread_once' ... /home/wind/Documents/dbus-1.13.18/_install/lib/libdbus-1.a(libdbus_1_la-dbus-sysdeps-pthread.o): In function `_dbus_platform_cmutex_new': dbus-sysdeps-pthread.c:(.text+0x3c): undefined reference to `pthread_mutex_init' /home/wind/Documents/dbus-1.13.18/_install/lib/libdbus-1.a(libdbus_1_la-dbus-sysdeps-pthread.o): In function `_dbus_platform_rmutex_new': dbus-sysdeps-pthread.c:(.text+0xbc): undefined reference to `pthread_mutexattr_init' dbus-sysdeps-pthread.c:(.text+0xcc): undefined reference to `pthread_mutexattr_settype' dbus-sysdeps-pthread.c:(.text+0xe0): undefined reference to `pthread_mutex_init' dbus-sysdeps-pthread.c:(.text+0xf0): undefined reference to `pthread_mutexattr_destroy' /home/wind/Documents/dbus-1.13.18/_install/lib/libdbus-1.a(libdbus_1_la-dbus-sysdeps-pthread.o): In function `_dbus_platform_cmutex_free': dbus-sysdeps-pthread.c:(.text+0x14c): undefined reference to `pthread_mutex_destroy' /home/wind/Documents/dbus-1.13.18/_install/lib/libdbus-1.a(libdbus_1_la-dbus-sysdeps-pthread.o): In function `_dbus_platform_rmutex_free': dbus-sysdeps-pthread.c:(.text+0x180): undefined reference to `pthread_mutex_destroy' /home/wind/Documents/dbus-1.13.18/_install/lib/libdbus-1.a(libdbus_1_la-dbus-sysdeps-pthread.o): In function `_dbus_platform_cmutex_lock': dbus-sysdeps-pthread.c:(.text+0x1b4): undefined reference to `pthread_mutex_lock' /home/wind/Documents/dbus-1.13.18/_install/lib/libdbus-1.a(libdbus_1_la-dbus-sysdeps-pthread.o): In function `_dbus_platform_rmutex_lock': dbus-sysdeps-pthread.c:(.text+0x1e0): undefined reference to `pthread_mutex_lock' /home/wind/Documents/dbus-1.13.18/_install/lib/libdbus-1.a(libdbus_1_la-dbus-sysdeps-pthread.o): In function `_dbus_platform_cmutex_unlock': dbus-sysdeps-pthread.c:(.text+0x20c): undefined reference to `pthread_mutex_unlock' /home/wind/Documents/dbus-1.13.18/_install/lib/libdbus-1.a(libdbus_1_la-dbus-sysdeps-pthread.o): In function `_dbus_platform_rmutex_unlock': dbus-sysdeps-pthread.c:(.text+0x238): undefined reference to `pthread_mutex_unlock' /home/wind/Documents/dbus-1.13.18/_install/lib/libdbus-1.a(libdbus_1_la-dbus-sysdeps-pthread.o): In function `_dbus_platform_condvar_new': dbus-sysdeps-pthread.c:(.text+0x284): undefined reference to `pthread_condattr_init' dbus-sysdeps-pthread.c:(.text+0x2a4): undefined reference to `pthread_condattr_setclock' dbus-sysdeps-pthread.c:(.text+0x2b8): undefined reference to `pthread_cond_init' dbus-sysdeps-pthread.c:(.text+0x2c8): undefined reference to `pthread_condattr_destroy' /home/wind/Documents/dbus-1.13.18/_install/lib/libdbus-1.a(libdbus_1_la-dbus-sysdeps-pthread.o): In function `_dbus_platform_condvar_free': dbus-sysdeps-pthread.c:(.text+0x328): undefined reference to `pthread_cond_destroy' /home/wind/Documents/dbus-1.13.18/_install/lib/libdbus-1.a(libdbus_1_la-dbus-sysdeps-pthread.o): In function `_dbus_platform_condvar_wait': dbus-sysdeps-pthread.c:(.text+0x368): undefined reference to `pthread_cond_wait' /home/wind/Documents/dbus-1.13.18/_install/lib/libdbus-1.a(libdbus_1_la-dbus-sysdeps-pthread.o): In function `_dbus_platform_condvar_wait_timeout': dbus-sysdeps-pthread.c:(.text+0x4bc): undefined reference to `pthread_cond_timedwait' /home/wind/Documents/dbus-1.13.18/_install/lib/libdbus-1.a(libdbus_1_la-dbus-sysdeps-pthread.o): In function `_dbus_platform_condvar_wake_one': dbus-sysdeps-pthread.c:(.text+0x520): undefined reference to `pthread_cond_signal' /home/wind/Documents/dbus-1.13.18/_install/lib/libdbus-1.a(libdbus_1_la-dbus-sysdeps-pthread.o): In function `_dbus_threads_lock_platform_specific': dbus-sysdeps-pthread.c:(.text+0x5a0): undefined reference to `pthread_mutex_lock' /home/wind/Documents/dbus-1.13.18/_install/lib/libdbus-1.a(libdbus_1_la-dbus-sysdeps-pthread.o): In function `_dbus_threads_unlock_platform_specific': dbus-sysdeps-pthread.c:(.text+0x5bc): undefined reference to `pthread_mutex_unlock' collect2: error: ld returned 1 exit status make: *** [Makefile:1914: wpa_supplicant] Error 1
诸如此类。
保存并退出。而后执行:
mkdir _install
cp defconfig .config
make CC=arm-himix100-linux-gcc
make install DESTDIR=$PWD/_install/
以上编译结果为动态链接,如需静态链接,只需在Makefile中对应项目的编译语句增加-static关键字再编译即可,例如:
wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs)
$(Q)$(LDO) -static $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS)
@$(E) " LD " $@
最后,可使用strip对应用程序进行“瘦身”:
arm-himix100-linux-strip wpa_supplicant
按照以上步骤编译出的静态链接的wpa_supplicant大小是5.3M(striped),对于使用SPI Nor Flash的嵌入式设备来说依旧非常大,因为通常我们只是连接一个AP而已。此时可根据需要对其进行裁剪,裁剪操作主要是通过注释掉 .config 文件中的配置项实现的(或者改Makefile)。
说明:以下裁剪操作使用MT7601U连接TL-W845N路由器进行测试。
注意:以下裁剪仅对wpa_supplicant进行了测试。
Wext(Wireless Extensions, 无线扩展接口)和nl80211都是目前Linux支持的无线网络配置接口,它们的区别网上有很多文章已经介绍了,总而言之,nl80211接口将会继承Wext的接力棒,逐渐成为Linux网络接口的主流选择。nl指的是netlink,nl80211接口通过netlink技术管理应用层和驱动的通信。
wpa_supplicant同时支持两种网络接口,但是在一些特定的场合例如连接某个特殊的热点或者内核的配置不同,我们只需要其中一种。因此可以通过裁剪接口的方式降低应用程序的体积。若需裁减掉802.11接口,可基于deconfig文件注释掉以下内容:
#CONFIG_DRIVER_NL80211=y
#CONFIG_LIBNL32=y
#CONFIG_SAE=y
#CONFIG_IEEE80211W=y
#CONFIG_IEEE80211R=y
#CONFIG_IEEE80211N=y
#CONFIG_IEEE80211AC=y
#CONFIG_DPP=y
同时,编译过程中不再需要链接libnl库。最终的编译结果为:
若需裁减掉Wext接口,则可基于deconfig文件注释掉以下内容:
#CONFIG_DRIVER_WEXT=y
此时的编译结果为:
当使用Wext接口时,wpa_supplicant的调用方式为:
wpa_supplicant -D wext -i wlan0 -c /etc/wpa.conf &
当使用nl80211接口时,-D参数则为nl80211,即:
wpa_supplicant -D nl80211 -i wlan0 -c /etc/wpa.conf &
通过选择使用的内核接口对程序进行裁剪,得到的应用程序依旧太大了。因此在裁减掉nl80211接口的基础上(支持该接口会使应用程序较支持Wext更大),根据目标需求(连接一个AP)继续注释以下项目:
#CONFIG_DEBUG_FILE=y # 添加对将调试日志写入文件的支持(/tmp/wpa_supplicant-log-#.txt)
#CONFIG_DRIVER_WIRED=y # 有线连接
#--------------------------------------------------
# 可用于通过wpa_supplicant控制AP模式操作。 应该注意的是,这
# 主要针对WPA2-Personal之类的简单情况,而hostapd可以支持更
# 复杂的配置(如具有外部RADIUS服务器的WPA2-Enterprise)。
#--------------------------------------------------
#CONFIG_AP=y # AP模式
#--------------------------------------------------
# 这可用于在wpa_supplicant中启用P2P支持。 有关P2P操作的更多
# 信息,请参见README-P2P。
#--------------------------------------------------
#CONFIG_P2P=y # P2P支持
#--------------------------------------------------
# 可以使用外部程序来控制消息中的其他信息交换,从而为P2P启用
# Wi-Fi显示扩展。
#--------------------------------------------------
#CONFIG_WIFI_DISPLAY=y # P2P的WiFi显示扩展
#CONFIG_IBSS_RSN=y
此时的编译结果为:
本文粗浅的尝试了wpa_supplicant2.9的交叉编译和基本裁剪操作,并且在Hi3516EV200(with MT7601U)平台上测试连接到路由器成功,受限于时间精力和学识,更进一步的裁剪未做尝试,因为已经足够满足当前需要了。
此外,如果只是希望按照常规方式连接到AP,可以尝试使用更早版本的wpa_supplicant程序,它们可能不需要依赖外部库且支持的功能更少,例如笔者曾编译过一个第三方裁减的wpa_supplicant0.8,最终的程序大小只有2.4MiB(not stripped), 774.1KiB(stripped)。
百度网盘链接:https://pan.baidu.com/s/1aXGivAiHUs1kQN1wveJlTw
提取码:pjr6
————2021-1-15~20@燕卫博————