本文说明如何一步一步地从源码编译出自己的OpenWrt镜像,并升级到设备上。
准备工作
准备一个GNU/Linux, BSD 或 MacOSX 操作系统。并且,在环境中准备好以下官方教程中要求的工具:
https://openwrt.org/docs/guide-developer/toolchain/install-buildsystem
我的环境是Ubuntu22,执行
1 | sudo apt update |
编译系统
下载源码
下载代码:
1 | git clone https://github.com/openwrt/openwrt.git |
切换分支,一般选择最新的稳定版本:
1 | git branch -a |
下载软件包
运行./scripts/feeds update -a
命令,下载或更新在feeds.conf/feeds.conf.default
中定义的所有最新软件包。
受限于国内的访问国际互联网的环境中,feeds update这一步特别容易失败。可以通过以下几条方式来提高成功率:
git config --global http.postBuffer 524288000
git config --global http.lowSpeedLimit 1000
git config --global http.lowSpeedTime 600
以上配置的含义为:配置git缓冲区为500M,配置git访问超时的条件为:速率小于1KB/s,且持续600秒
运行./scripts/feeds install -a
命令使安装上述软件包在后续的make menuconfig
中生效。
配置编译选项
使用已有固件的编译配置
网络上已编译出的固件通常都会把编译配置一并提供(config.buildinfo或config.seed),可以直接使用。
我的目标机是一台小米WR30U,使用mtk的filogic芯片方案,从OpenWrt官网找到对应的编译配置并下载,置于OpenWrt工程根目录下的.config
文件中:
1 | wget https://downloads.openwrt.org/releases/23.05.0/targets/mediatek/filogic/config.buildinfo -O .config |
但这份配置中包含了filogic芯片方案的所有设备的配置,还需进行裁剪和修改。
menuconfig
在以上配置的基础上,运行make menuconfig
命令来完成进一步的自定义配置。完成后配置会更新至.config
文件中。
在Target Profile中,仅保留Xiaomi WR30U的设备支持(我的设备是Xiaomi Mi Router WR30U (112M UBI with NMBM-Enabled layout)),把其它设备的支持删除。
编译
使用make download
预先下载编译过程中需要的代码和依赖项等资源。
. . . . . . . 经过漫长的等待下载完成。到此为止,我们已做好了所有的编译准备。
正式开始编译吧,运行make
命令来构建固件。该命令将下载所有源代码和依赖项(即使之前已经make download
,也还有其它包需要下载),构建交叉编译工具链,然后为目标系统交叉编译出OpenWrt内核和应用程序。
1 | make -j4 V=s |
编译选项说明
-jN
: make命令可以加上-j参数用于指定使用多少cpu核编译,可以加速编译过程。例如:make download -j4
,make -j5
V=s
:make命令可以加上V=s可以输出更多的编译错误信息。
如果顺利的话,这里make完就可以编译出镜像了。但是实际不太可能完全顺利。每个人遇到的问题可能不一样。我遇到的问题和修复方法,我放在后面附录中。
编译输出
. . . . . . . 经过漫长的编译过程(我的环境中编了5个小时),编译结果存放于openwrt/bin/targets/
目录下。几类编译产出的镜像说明如下:
- factory:用于替换厂商的原厂固件,兼容原厂的安装包格式。通常使用原厂的web GUI进行升级。
- sysupgrade:用于升级替换已有的OpenWrt版本,这是最常用的镜像。
- initramfs-kernel:用于开发或特殊情况下的一次性引导,作为安装常规sysupgrade版本的过渡步骤。由于initramfs版本完全运行在RAM中,不会在闪存中存储任何设置,因此不适合用于操作性使用。
升级固件
主要参考刷机教程中提及的办法,在路由器断电后,用针按住 reset 不放,再接上电源,等待 10s 左右松开,就能进入 uboot。电脑用网线和 wr30u 的网口1连接,电脑在网络设置里将以太网设置为静态。IP地址:192.168.1.2,子网掩码:255.255.255.0,浏览器打开192.168.1.1访问uboot后台。
现在选择编译出的openwrt主程序(openwrt-23.05.0-mediatek-filogic-xiaomi_mi-router-wr30u-112m-nmbm-squashfs-sysupgrade.bin),upload 后 update 更新即可。
升级完成后,把网络连到LAN口上(非1口),在控制台上用ssh root@192.168.1.1登陆,可见已成功升级至编译出的OpenWrt固件。
也可以通过浏览器访问192.168.1.1,进入web管理页面,默认用户名密码是root/password
将自己编译的固件与从官方网站上下载的固件https://downloads.openwrt.org/releases/23.05.0/targets/mediatek/filogic/openwrt-23.05.0-mediatek-filogic-xiaomi_mi-router-wr30u-112m-nmbm-squashfs-sysupgrade.bin 升级后的结果做了一下对比,路由器功能完全一致。
附录
参考资料
- https://openwrt.org/docs/guide-developer/toolchain/use-buildsystem
- https://openwrt.org/faq/how_much_time_is_needed_for_compiling
- https://openwrt.org/faq/what_is_the_difference_between_the_different_image_formats
- https://github.com/coolsnowwolf/lede/issues/10817
编译失败记录
内核编译Warning
默认情况下,内核编译有加上-Werror选项,因此遇到Warning就会停下来。例如编译失败日志:
1 | /home/spencer/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_filogic/dmx_usb_module-19.12.1/dmx_usb.c: In function 'dmx_usb_write': |
于是找到-Werror
添加的地方,删除掉。即在openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_filogic/linux-5.15.132/Makefile
中,把以下这行注释掉:
1 | #KBUILD_CFLAGS-$(CONFIG_WERROR) += -Werror |
acl编译失败
遇到acl编译失败,到社区上搜索,已有高人给出了答案:
https://github.com/openwrt/packages/issues/21051
https://github.com/openwrt/packages/pull/21031/commits/dcc6d70f735474d49345d8d4b43a8098bb217220
cjdns编译失败
1 | cc1: note: someone does not honour COPTS correctly, passed 16 times |
解决办法:
https://github.com/coolsnowwolf/lede/issues/10817