M1 环境下编译 OpenWRT

编译 OpenWRT 按理说不应该是一个艰难的过程,许多人在两三年前就开始玩起了软路由,理应留下了不少宝贵的经验,然而对于我而言却存在两大挑战。根据 Lead 大神的官方教程,推荐的编译环境是 x86 Ubuntu LTS,然而我却需要在 Mac 上完成。虽然官方教程里同样也有针对 Mac 的步骤,但是我自己比较怀疑这些步骤是否仍然适用于最新的 macOS(考虑到近年来 macOS 的迭代速度比较快,内部软件更新也比较频繁),其次教程针对的是 x86 环境也就是 Intel 芯片的 Mac,而我的电脑是 M1 Max 芯片的 MacBook Pro,运行的是最新 macOS Monterey 12.5。

理论上我有三个选项:1、按照 x86 Mac 环境下的教程进行编译,2、安装虚拟机运行 ARM Ubuntu LTS 进行编译,3、安装虚拟机运行 x86 Ubuntu LTS 进行编译。选项 3 虽然最为稳妥,但实际操作后感觉性能实在太差,从启动时间上来看,感觉比 ARM 版本的 Ubuntu LTS 起码慢二十倍以上,即便能编译成功,时间代价也足以让我放弃。相比之下,前两个选项能够充分发挥 M1 Max 芯片的速度优势,可以让我更快的试错纠错。

官方步骤

git clone https://github.com/coolsnowwolf/lede 
cd lede ./scripts/feeds 
update -a ./scripts/feeds 
install -a make menuconfig
make download -j8
make V=s -j1

Ubuntu 和 macOS 所遇到的坑及解决方案

go-bootstrap cannot be installed on linux/arm64 (darwin/arm64)

先在本机上安装好 go,然后编辑 .config 文件,修改 External bootstrap Go root directory 为 Go  的路径

macOS 下编译 OpenWRT(以失败告终)

首先按照官方的指南,编译 OpenWRT 需要创建一个大小写敏感的磁盘分区,然后通过 homebrew 安装好所有基础的依赖库,这个过程相对比较简单。

Mac: make[6]: *** No rule to make target '/Volumes/OpenWrt/lede/build_dir/target-x86_64_musl/linux-x86_64/cryptodev-linux-cryptodev-linux-1.12/ioctl.o', needed by '/Volumes/OpenWrt/lede/build_dir/target-x86_64_musl/linux-x86_64/cryptodev-linux-cryptodev-linux-1.12/cryptodev.o'.  Stop.

推测是部分 object 文件在 macOS 下没有找到对应的链接库,理论上应该可以找替代的对应版本,但是网上的内容少之又少,勉强解决了一个发现还有一堆这样的问题,因此便考虑暂时放弃 Mac 环境下的尝试。

ARM 版 Ubuntu LTS 下编译成功

首先虚拟机选择是小巧免费的 UTM 配合 Ubuntu 官方的 ARM 版镜像文件,在安装依赖时,就遇到 gcc-multilib g++-multilib libc6-dev-i386 这三个依赖无法找到的问题,但经过研究后发现可以使用以下库替代。

sudo apt install gcc-multilib-i686-linux-gnu gcc-multilib-s390x-linux-gnu gcc-multilib-x86-64-linux-gnu gcc-multilib-x86-64-linux-gnux32

sudo apt install g++-multilib-i686-linux-gnu g++-multilib-s390x-linux-gnu g++-multilib-x86-64-linux-gnu g++-multilib-x86-64-linux-gnux32

sudo apt install libc6-dev-i386-amd64-cross libc6-dev-i386-cross libc6-dev-i386-x32-cross

系统基础软件包

  • kernel modules/kmod-fs-hfs
  • kernel modules/kmod-fs-hfsplus
  • network/filesystem/netatalk
  • network/IP address and names/avahi-utils
  • network/IP address and names/cloudflare-ddns-v4*
  • utilities/filesystem/hfsfsck(这个配合 hfsplus 使用才能使得磁盘以读写模式挂载到系统,并且磁盘需要关闭 MacOS 扩展的日志式 Journaling)
  • utilities/editor/vim full

LUCI 软件包

  • `LUCI/themes(不能选 mod)`
  • luci-app-airplay2
  • luci-app-aliyundrive-*(fuse 非常好用,配合磁盘共享和 minidlna 可以让电视直接播放阿里云盘里的视频资源)
  • luci-app-aria2(选择 aria2 后,网页前端会自动选择 ariaNg)
  • luci-app-diskman(方便查看磁盘情况和挂载)
  • luci-app-frpc
  • luci-app-hd-idle
  • luci-app-minidlna
  • luci-app-netdata(方便实时查看系统负载)
  • luci-app-samba4
  • luci-app-usb-printer
  • luci-app-uugamebooster

Time Machine 和 Samba4

搞定 OpenWRT 编译后,Time Machine 的配置也着实让我费了一番功夫。在解决了 HFS+ 挂载磁盘只能 Readonly 的问题后,搞定 Time Machine 眼看只有一步之遥,找到官方的一份详细文档,按照其中步骤完成配置后,虽然运行正常,但我却发现无法备份第二台 Mac。

绕了一圈之后,才恍然发现 Samba4 原生就已经对 Mac 有很好的支持,并且实现了 Time Machine 的功能。因此也不必安装 netatalk 而是回到 OpenWRT 的编译配置菜单中,参考他人的经验,在 Extra packages 里取消勾选 autosamba,并在 LuCI - Applications 里取消勾选 luci-app-samba,并勾选 luci-app-samba4,最后在 Network 里取消 samba36-server

对于 Samba 4 的一些配置,官方有一个值得参考的文档以外,如果不想 OpenWRT 在 Mac 中显示为一台蓝屏的 PC,推荐使用我总结的一下配置:

[global]
	vfs objects = catia fruit streams_xattr
	fruit:metadata = stream
	fruit:model = RackMac
	fruit:encoding = native
	fruit:posix_rename = yes
	fruit:veto_appledouble = no
	fruit:nfs_aces = no
	fruit:wipe_intentionally_left_blank_rfork = yes
	fruit:delete_empty_adfiles = yes

至此,我的所有需求都得到了满足,家中的两台 Mac 都可以稳定的进行 Time Machine 备份,速度和稳定性都十分优秀,特别是在 2.5G 内网的有线连接下速度尤其喜人。在目前的配置下,软路由已经稳定运行了一个多月,没有遇到任何需要额外操心的问题,就此家庭网络的折腾之旅暂时告一段落。