[OpenWrt] 为 x86_64 平台编译自己的 OpenWrt

OpenWrt 是一个十分著名的嵌入式 Linux 发行版,被广泛使用在家庭路由器的魔改上。其前身是 Linksys 被迫开源的 WRT54G 固件。

最近几天买了一个 Intel J1900 CPU 的板子,集成了四张千兆网卡,于是就打算拿来跑 OpenWrt x86。但是呢,OpenWrt 官方放出的 x86_64 固件中使用的标准库是 uClibc,一个面向嵌入式 Linux 系统的小型的 C 标准库。可是手里的硬件确实正儿八经的 BayTrail CPU,使用 uClibc 未免感觉太憋屈了。不仅如此,绝大多数编译好的二进制软件都是使用 GNU C Library,同时 uClibc 没有提供对 glibc 的兼容,所以即便我是 x86 的 CPU,所有软件也都需要使用 OpenWrt 重新编译,很繁琐。于是,打算重新编译自己的 OpenWrt。

首先是获得源码,需要注意的是 git.openwrt.com 上的代码已经很久没有更新了,所有代码都应该从 GitHub 上取得。

git clone -b v15.05.1 https://github.com/openwrt/openwrt.git
cd openwrt

当然还要准备一下依赖:

sudo apt-get install build-essential subversion libncurses5-dev zlib1g-dev gawk gcc-multilib flex git-core gettext libssl-dev

然后更新 OpenWrt 的软件列表:

./scripts/feeds update -a
./scripts/feeds install -a

并生成默认配置:

make defconfig

然后就可以开始配置了:

make menuconfig

这里面大多数内容都没什么好说的,如果不明确就去搜索。不过强烈推荐激活 Global build settings 中的 Select all kernel module packages by default,软件没编译可以随时 make menuconfig && make,但是内核模块如果重新编译就不得不将板子上已经部署好的 OpenWrt 完全替换,因为每一次编译内核和内核模块都是与之前不兼容的。当然 CPU 和 SSD 足够大的话你顺手选上 Select all userspace packages by default 是最好的。至于 C 标准库的选择,可以在 Advanced configuration options > Toolchain Options > C Library implementation 中修改。如果你选择了很多包内置到 rootfs 时,默认的 IMG 文件可能不够用,此时你就需要修改 Target Images 中的 Root filesystem partition size,和 ext4 中的 Maximum number of inodes in root filesystem。

完成之后,保存并退出。准备修改内核配置:

make kernel_menuconfig

这里面大部分都不需要编辑,但是 OpenWrt 默认的配置没有提供对 AHCI 的支持,我们需要自己将他选中。同时多线程啊大内存什么的,自己看着改改。

以上步骤准备完成了之后,开始下载需要的各种源码包,此处建议使用全局代理或者 VPN,以避免不必要的麻烦。

make download -j100

期间如果出现下载失败或是其他异常导致中断,你可以 make download V=s 查看详细输出,并手动下载对应的包,保存至 dl 目录下。若校验和一致,就不会再去下载了。

最后就是编译啦,OpenWrt Buildroot 首先回去编译 toolchain,然后编译内核和软件包。

make

或者使用多线程加速:

make -j24 # if you have 2 * E5 26xx

如果过程中出现错误,同样是使用 make V=s -j1 编译,并等着看错误输出。如果想睡觉时编译呢,可以将编译日志重定向到文件中来方便查看问题:

make V=s | tee buid.log