利用 GitHub Actions 编译集成 OpenClash 的 OpenWrt 固件

2022/03/17

为什么要自己编译固件

最主要的原因,是在原版 OpenWrt 系统中安装 OpenClash 及其依赖时会有报错信息,虽然实测不会影响正常使用,但是感觉自己有点轻微的强迫症,有报错就浑身难受,总感觉不完美、有点残缺。

除此之外,个人使用各种系统总喜欢原汁原味的,虽然国内很多高手的固件功能完善,完全能满足各种上网需求,但始终不是纯净原版系统。

目前来看,对于软路由的功能,我的需求很少,无外乎通过软路由实现局域网设备透明代理(说不定后面会有其他的),所以决定干脆自己编译一个基于原版 OpenWrt 并集成 OpenClash 的固件。

本地编译的尝试

在 Hyper-V 中创建了一个 Fedora 虚拟机,进行一次系统更新之后,根据 OpenWrt Wiki 安装好编译所需依赖:

sudo dnf --setopt install_weak_deps=False --skip-broken install \
bash-completion bzip2 gcc gcc-c++ git make ncurses-devel patch \
rsync tar unzip wget which diffutils python2 python3 perl-base \
perl-Data-Dumper perl-File-Compare perl-File-Copy perl-FindBin \
perl-Thread-Queue

随后,克隆 OpenWrtOpenClash 仓库到本地:

git clone [email protected]:openwrt/openwrt.git
git clone [email protected]:vernesong/OpenClash.git

并将 OpenClash 仓库中的 luci-app-openclash 文件夹复制到 OpenWrt 仓库中的 package 文件夹中去。

随后,在 OpenWrt 仓库根目录,执行以下命令更新库以及下载软件包并让它们在后续步骤中可用:

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

随后执行 make menuconfig 以生成映像生成配置。

make_menuconfig.png

在弹出的图形化配置页面中,执行以下自定义项目以集成 OpenClash 与中文语言包:

Target System > x86

Subtarget > x86_64

Target Images > squashfs
Target Images > Build GRUB EFI
Target Images > Use Console Terminal
Target Images > Gzip images
Target Images > Kernel size > 64
Target Images > Root size > 512

LuCI > Collections > LuCI
LuCI > Moudles > Translations - Chinese
LuCI > Modules > luci-compat
LuCI > Applications > luci-app-openclash

Base System - dnsmasq(取消勾选)

Network > Files Transfer > wget-ssl 
Network > Files Transfer > wget-nossl 

(另,此处的架构是针对 x86_64 Windows 系统的 Hyper-V 虚拟机环境的。)

保存退出之后,执行 make -j8 download V=s 进行预下载,完成后执行 make -j1 V=s 开始编译。

于是我满心企盼地等待着编译成功的消息传来,可结果却是花式三百六十度螺旋失败。经过一番网络搜索,发现踩了一个坑:Linux 系统语言被设置成了中文,因此直接在家目录的中文目录中进行编译,往往会产生不可预测的问题导致编译失败。于是我将系统语言调整为英文之后重新尝试编译——终于没出现之前的报错,编译得以继续进行——可当编译进行了大约两个小时之后,又有其他的错误导致编译失败。

又进行了多方搜索,多次尝试,未果。于是我果断决定转换赛道。

利用 GitHub Actions 云编译固件

这个方案,已经有很多高手搭建好了许多相当优秀的脚手架。经过比较,我选择 forkKFERMercerOpenWrt-CI 项目,并决定站在前人的肩膀上开展工作。

OpenWrt-CI 利用 GitHub Actions 实现了两大核心自动化功能:

  1. 根据条件自动同步上游代码;
  2. 根据条件自动触发 OpenWrt 固件编译。

OpenWrt-CI 默认采用 Lean 的 OpenWrt 分支作为上游,因为我不希望集成太多用不到的功能,所以将上游仓库修改为了原版 OpenWrt。

承接上文本地编译的步骤,执行 make menuconfig 命令并生成好配置文件之后,可继续执行:

./scripts/diffconfig.sh > mydiffconfig.txt

将所做配置增量保存到 mydiffconfig.txt。再将此文件内容写入 OpenWrt-CI 的 openwrt-ci.yml 文件,从而实现编译时加入 OpenClash。

与此同时,也要将 OpenClash 集成至 OpenWrt 源代码,这样 OpenWrt-CI 才有内容可编译。

fork 原版 OpenWrt 仓库,并在 feeds.conf.default 文件中加入一行 src-git small8 https://github.com/kenzok8/small-package,从而集成 kenzok8small-package 库。这个库包含了包括 OpenClash 在内的相当多常用 OpenWrt 插件,并每天同步上游保持最新状态。

将 fork 的 OpenWrt-CI 仓库中修改后的 merge-upstream.ymlopenwrt-ci.yml 两个文件上传至 fork 的 OpenWrt 仓库中的 .github/workflows 文件夹。固件编译过程将自动开始。

经过约一个小时四十分钟的等待,编译成功完成。编译后的固件可在 这里 下载。

workflows_openwrt-ci.png

相关仓库

参考资料

等等…