Openwrt编译从入门到入土

Insider Lv1

😡人生苦短,不要折腾Openwrt编译,编译不好往往不是你的问题,是源码混乱,网络狗屎,依赖管理差的问题

阅读本文前提

  • 一点点Linux基础使用
  • 一点点脑子
  • 一点点git使用
  • 非常不错的科学上网环境
  • 家里有矿,闲得发慌

本地编译

准备Linux环境

Ubuntu 20.04 LTS最佳

安装必需软件

1
sudo apt update -y
1
sudo apt full-upgrade -y
1
2
3
4
5
6
7
8
# 此处为LEDE的环境配置仅供参考,具体需要的软件包见仓库的文档说明
sudo apt install -y ack antlr3 asciidoc autoconf automake autopoint binutils bison build-essential \
bzip2 ccache cmake cpio curl device-tree-compiler fastjar flex gawk gettext gcc-multilib g++-multilib \
git gperf haveged help2man intltool libc6-dev-i386 libelf-dev libfuse-dev libglib2.0-dev libgmp3-dev \
libltdl-dev libmpc-dev libmpfr-dev libncurses5-dev libncursesw5-dev libpython3-dev libreadline-dev \
libssl-dev libtool lrzsz mkisofs msmtp ninja-build p7zip p7zip-full patch pkgconf python2.7 python3 \
python3-pyelftools python3-setuptools qemu-utils rsync scons squashfs-tools subversion swig texinfo \
uglifyjs upx-ucl unzip vim wget xmlto xxd zlib1g-dev

拉取源码

使用git clone拉取源码

1
git clone <源码链接>

源码仓库

lede :

https://github.com/coolsnowwolf/lede

immortalwrt :

https://github.com/immortalwrt/immortalwrt

openwrt:

https://github.com/openwrt/openwrt

添加软件源

每个仓库都有自己维护的软件源,里面不一定有需要的

这时候需要通过添加自定义源来加入更多软件

sed -i "<n>i src-git 名称 github仓库链接" feeds.conf.default

例如kenzo8的软件源

https://github.com/kenzok8/openwrt-packages

1
2
sed -i '1i src-git kenzo https://github.com/kenzok8/openwrt-packages' feeds.conf.default
sed -i '2i src-git small https://github.com/kenzok8/small' feeds.conf.default

更新并安装软件源

更新软件源

1
./scripts/feeds update -a

安装软件源

1
./scripts/feeds install -a

修改配置

图形化修改配置项

1
make menuconfig

整个界面预览

https://s2.loli.net/2024/06/30/gTRMqrJ4XAVPC95.png

图左上角为配置所在路径以及配置文件名称

https://s2.loli.net/2024/06/30/VfPEvusObTJAtlM.png

最下面的菜单栏,使用左右键选择功能,回车键使用功能
https://s2.loli.net/2024/06/30/cH1EdXketAx4rV3.png

其他四个选项用的比较少,都是顾名思义,不需要解释了,重点看看<Select>

<Select>选择上下键选择配置,使用回车键进入二级目录,使用空格键修改参数状态,也可以使用Y/N/M 包含/排除/模块化也就是编译不加入

参数状态说明

https://s2.loli.net/2024/06/30/Of4Qrne7DYbzjoB.png

[*] 编译加入

[ ] 编译排除

< > 编译排除

<M> 编译但不加入

<*> 编译并加入

使用/ 搜索配置项

https://s2.loli.net/2024/06/30/m1hnlauHrfwXRdJ.png

Help中有详细说明

  • 使用数字键跳转对应配置路径
  • 支持模糊搜索
    • 默认为搜索包含字符串的配置项
    • ^字符串 表示搜索已字符串开头的配置项
    • 字符串$表示搜索已字符串结尾的配置项

两次<ESC>用于回到上个界面

<?> 可以查看当前选择的配置项的说明

具体各个配置说明

https://s2.loli.net/2024/06/30/MZYPsCyfvr3Gk68.png


一般首先需要修改

Target System 硬件架构 例如x86

Subtarget 处理器名称 例如n100

Target Profile 编译配置具体默认机器配置 一般 Multiple Deivces 表示该处理器型号所有机器都编译一遍

Target Images 编译固件类型 以及一些固件配置(固件最大大小等等)


谨慎修改

Enable experimental features by default 默认启用实验功能
Global build settings —> 全局构建设置 —> 高级打包配置,例如内核配置,一般不需要修改,除非想使用测试版内核或者一些高级打包配置


开发者使用的部分设置
Advanced configuration options (for developers) —> 高级配置选项 (供开发者使用) —>
Build the OpenWrt Image Builder 构建 OpenWrt 固件生成器
Build the OpenWrt SDK 构建 OpenWrt SDK
Package the OpenWrt-based Toolchain 打包OpenWrt基础工具链


个性化配置项
Image configuration —> 固件信息配置 —> 用于配置固件名称,默认IP,包含软件源等等
Base system —> 基本系统 —> Openwrt系统基础工具,例如busybox,dnsmasq,opkg,uci 等等
Administration —> 管理 —> Linux一些管理使用的工具配置,包含sudo,htop等常见工具
Boot Loaders —> 引导加载程序 —>boot引导编译配置,一般我们使用Github中发布的版本即可,除非你有自行修改boot的需求,小白不要碰
Development —> 开发 —> 开发者使用的工具编译选择,一边我们不需要选择,也不用管里面的内容,这个是用来编译开发相关工具使用的,例如gcc,make等等
Extra packages —> 额外软件包 —> 额外软件包,里面可以选择额外的软件配置,例如ipv6-helper 可以一键帮你配置ipv6的配置项,autosamba(自动配置SMB共享),automount (自动挂载),Nginx(网页服务器)等等
Firmware —> 硬件驱动 —> 在这里选择需要的WIFI驱动等等(一般默认配置就有,x86除外)
Fonts —> 字体 —>
Kernel modules —> 内核模块 —> 一些内核依赖配置,也是一般不需要手动修改,
Languages —> 语言 –→ 指的是编译语言,例如C++,GoLang ,Nodejs等等,用于语言相关配置,当需要xxx语言提供的工具时需要修改该配置,正常情况下无需修改
Libraries —> 库 —> 依赖库,很重要,但是我们一般不要手动改,容易出问题


我们重点需要修改的地方
LuCI —> LuCI —> WebUI界面的配置项,也就是我们配置后台插件的地方

  • Themes 后台主题配置,选择一个喜欢的主题,请保留bootstrap防止部分源码,其他主题无法使用

  • Applications 也就是后台图形化插件配置名称为luci-app-xxx,常见的插件说明见该帖子

    https://www.right.com.cn/forum/thread-344825-1-1.html


Mail —> 邮件 —> 不了解,应该邮件服务器系统的核心文件配置
Multimedia —> 多媒体 —> 多媒体相关的核心文件配置,例如ublock - netease music 的核心文件配置
Network —> 网络 —> 网络核心文件配置,DNS/VPN/Firewall等等网络相关的核心文件配置都在此处,一些网络工具也可以在此处配置例如tcping等
Sound —> 声音 –→ 顾名思义

Utilities —>Linux 工具 grep,ack等等

Xorg—>字体工具

设置路由器默认的 LAN IP

1
2
# 设置默认IP为 192.168.10.1
sed -i 's/192.168.1.1/192.168.10.1/g' package/base-files/files/bin/config_generate

替换默认主题

1
2
# 设置默认主题为 luci-theme-argon
sed -i 's/luci-theme-bootstrap/luci-theme-argon/' feeds/luci/collections/luci/Makefile

预下载工具

1
make download -j$(nproc)

首次编译

1
make -j$(nproc) || make -j$(nproc) V=s

如何排错

最后报错Error2,我们就从上往下翻,看到第一个Error就停下,然后回退大概Error看看上面几行是什么内容(可以直接将日志复制到文本编辑器,然后用Ctrl+F搜索日志Error )

例子1:

比如编译lede固件加入adguardhome报错信息如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Finding targets
go: ../../go.mod requires go >= 1.22.4 (running go 1.22.1; GOTOOLCHAIN=local)

Building targets
go: ../../go.mod requires go >= 1.22.4 (running go 1.22.1; GOTOOLCHAIN=local)

make[3]: *** [Makefile:87: /workdir/openwrt/build_dir/target-aarch64_cortex-a53_musl/adguardhome-0.107.51/.built] Error 1
make[3]: Leaving directory '/workdir/openwrt/feeds/kenzo/adguardhome'
time: package/feeds/kenzo/adguardhome/compile#0.15#0.13#0.28
ERROR: package/feeds/kenzo/adguardhome failed to build.
make[2]: *** [package/Makefile:116: package/feeds/kenzo/adguardhome/compile] Error 1
make[2]: Leaving directory '/workdir/openwrt'
make[1]: *** [package/Makefile:110: /workdir/openwrt/staging_dir/target-aarch64_cortex-a53_musl/stamp/.package_compile] Error 2
make[1]: Leaving directory '/workdir/openwrt'
make: *** [/workdir/openwrt/include/toplevel.mk:231: world] Error 2

此时我们需要关注的内容只有

1
2
3
4
5
6
7
8
Finding targets
go: ../../go.mod requires go >= 1.22.4 (running go 1.22.1; GOTOOLCHAIN=local)

Building targets
go: ../../go.mod requires go >= 1.22.4 (running go 1.22.1; GOTOOLCHAIN=local)

make[3]: *** [Makefile:87: /workdir/openwrt/build_dir/target-aarch64_cortex-a53_musl/adguardhome-0.107.51/.built] Error 1
make[3]: Leaving directory '/workdir/openwrt/feeds/kenzo/adguardhome'

显然提示需要go版本大于等于1.22.4,但我们的版本是1.22.1所以出错了,出错的地方是feeds/kenzo/adguardhome 这个源码,这时候我们有两种解决方案

  • 解决提出问题的人
    把adgardhome移除,比较暴力,但是最有效哈哈哈
  • 解决问题
    将go语言版本换成相应版本(不一定能解决,可能导致其他依赖报错)

例子2:

编译hysteria依赖报错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Finding targets

Building targets
../../../../../dl/go-mod-cache/github.com/apernet/quic-go@v0.44.1-0.20240520215222-bb2e53664023/http3/client.go:8:2: package log/slog is not in GOROOT (/workdir/openwrt/staging_dir/hostpkg/lib/go-cross/src/log/slog)
../../../../../dl/go-mod-cache/github.com/apernet/quic-go@v0.44.1-0.20240520215222-bb2e53664023/internal/wire/transport_parameters.go:10:2: package slices is not in GOROOT (/workdir/openwrt/staging_dir/hostpkg/lib/go-cross/src/slices)

make[3]: *** [Makefile:62: /workdir/openwrt/build_dir/target-aarch64_cortex-a53_musl/hysteria-app-v2.4.5/.built] Error 1
make[3]: Leaving directory '/workdir/openwrt/feeds/small/hysteria'
time: package/feeds/small/hysteria/compile#0.39#0.23#0.48
ERROR: package/feeds/small/hysteria failed to build.
make[2]: *** [package/Makefile:120: package/feeds/small/hysteria/compile] Error 1
make[2]: Leaving directory '/workdir/openwrt'
make[1]: *** [package/Makefile:114: /workdir/openwrt/staging_dir/target-aarch64_cortex-a53_musl/stamp/.package_compile] Error 2
make[1]: Leaving directory '/workdir/openwrt'
make: *** [/workdir/openwrt/include/toplevel.mk:230: world] Error 2

需要关注的地方

1
2
3
4
5
6
7
8
Finding targets

Building targets
../../../../../dl/go-mod-cache/github.com/apernet/quic-go@v0.44.1-0.20240520215222-bb2e53664023/http3/client.go:8:2: package log/slog is not in GOROOT (/workdir/openwrt/staging_dir/hostpkg/lib/go-cross/src/log/slog)
../../../../../dl/go-mod-cache/github.com/apernet/quic-go@v0.44.1-0.20240520215222-bb2e53664023/internal/wire/transport_parameters.go:10:2: package slices is not in GOROOT (/workdir/openwrt/staging_dir/hostpkg/lib/go-cross/src/slices)

make[3]: *** [Makefile:62: /workdir/openwrt/build_dir/target-aarch64_cortex-a53_musl/hysteria-app-v2.4.5/.built] Error 1
make[3]: Leaving directory '/workdir/openwrt/feeds/small/hysteria'

此时如果发现问题我们看不懂,就把内容复制到GPT问就行了

https://s2.loli.net/2024/06/30/sJuytMxpLiSoUrN.png

当然也有可能GPT给出的解决方案并不能够解决问题,我们需要自行Google搜索一下

以上问题也是两种解决方法

  • 移除hysteria依赖
  • 找到slog/slices所需的go版本并替换(不一定能解决,可能导致其他依赖报错)

例子3:

路径中包含空格

1
2
3
4
5
6
find: The relative path 'Files/Bandizip/' is included in the PATH environment variable, which is insecure in combination with the -execdir action of find.  Please remove that entry from $PATH
make[2]: *** [package/Makefile:73: package/install] Error 1
make[2]: Leaving directory '/home/insider/lede'
make[1]: *** [package/Makefile:111: /home/insider/lede/staging_dir/target-aarch64_cortex-a53_musl/stamp/.package_install] Error 2
make[1]: Leaving directory '/home/insider/lede'
make: *** [/home/insider/lede/include/toplevel.mk:231: world] Error 2

WSL编译

如果你是使用WSL编译,由于 WSL 的 PATH 中包含带有空格的 Windows 路径,有可能会导致编译失败,也就是上面的报错,请使用

1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin make -j$(nproc)

如果你新添加软件源,百分之99的问题是依赖冲突导致的,如果没有添加,那么百分之99是你网络太烂了,连接不上Github仓库,你能访问≠你连接上了,github.com和github的内容分发仓库不是一个域名,有些时候域名不一样,可能被GFW屏蔽了,剩下的才有可能是上游源码BUG

二次编译

更新源码

1
git pull

更新软件源

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

只是修改软件配置

1
make clean

修改架构,例如x86→MTK ARM

1
make dirclean

从头开始修改配置

1
rm -rf ./tmp && rm .config && rm .config.old

下载软件包

1
make download -j$(nproc)

编译固件

1
make -j$(nproc)

添加单独软件包(进阶)

1
git clone <软件包项目地址> package/<软件包名>

单独编译软件(进阶)

1
make ./package/<软件包名>/compile

编译完成

./bin/target/*/*. 目录中寻找固件

云编译

😋 Github公共资源有限,请大家不要滥用

当你完成了本地编译,确认配置无误,固件正常使用后可以尝试云编译节省本地资源占用,同时可以用于固件同步上游源码使用,或者是你的电脑性能太差了,网络环境太差了,你想要使用云资源解决,那么当你make menuconfig完成后可以使用云编译(调试报错起来非常麻烦),我认为此时你应该去挣钱买更好的电脑和梯子而不是编译Openwrt😓

https://github.com/P3TERX/Actions-OpenWrt

使用该模板创建仓库

修改.github/workflows/openwrt-builder.yml 为以下配置,根据其中注释信息自行修改配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#
# https://github.com/P3TERX/Actions-OpenWrt
#
# File: .github/workflows/openwrt-bulder.yml
# Description: Build OpenWrt using GitHub Actions
#
# Copyright (c) 2019-2024 P3TERX <https://p3terx.com>
#
# This is free software, licensed under the MIT License.
# See /LICENSE for more information.
#
# 二次修改: @NakanoSanku

name: OpenWrt Builder

on:
repository_dispatch:
workflow_dispatch:

env:
# 源码仓库
REPO_URL: https://github.com/coolsnowwolf/lede
# 源码仓库分支,根据自己拉取的源码仓库调整
REPO_BRANCH: master
FEEDS_CONF: feeds.conf.default
# 配置文件在项目的相对位置
CONFIG_FILE: .config
# 在feeds update前执行的shell脚本,一般用于自定义软件源,参数为shell脚本文件在项目中的相对位置
DIY_P1_SH: diy-part1.sh
# 在加载完CONFIG_FILE后执行的shell脚本,一般用于自定义一些参数信息,参数为shell脚本文件在项目中的相对位置
DIY_P2_SH: diy-part2.sh
UPLOAD_BIN_DIR: false
UPLOAD_FIRMWARE: true
TZ: Asia/Shanghai

jobs:
build:
# 修改为20.04 更适合编译Openwrt
runs-on: ubuntu-20.04

steps:
- name: Checkout
uses: actions/checkout@main

- name: 安装环境
env:
DEBIAN_FRONTEND: noninteractive
run: |
sudo rm -rf /etc/apt/sources.list.d/* /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL
sudo docker image prune --all --force
sudo -E apt-get -qq update
sudo -E apt-get -qq install ack antlr3 asciidoc autoconf automake autopoint binutils bison build-essential bzip2 ccache cmake cpio curl device-tree-compiler fastjar flex gawk gettext gcc-multilib g++-multilib git gperf haveged help2man intltool libc6-dev-i386 libelf-dev libfuse-dev libglib2.0-dev libgmp3-dev libltdl-dev libmpc-dev libmpfr-dev libncurses5-dev libncursesw5-dev libpython3-dev libreadline-dev libssl-dev libtool lrzsz mkisofs msmtp ninja-build p7zip p7zip-full patch pkgconf python2.7 python3 python3-pyelftools python3-setuptools qemu-utils rsync scons squashfs-tools subversion swig texinfo uglifyjs upx-ucl unzip vim wget xmlto xxd zlib1g-dev
sudo -E apt-get -qq autoremove --purge
sudo -E apt-get -qq clean
sudo timedatectl set-timezone "$TZ"
sudo mkdir -p /workdir
sudo chown $USER:$GROUPS /workdir

- name: 拉取源码
working-directory: /workdir
run: |
df -hT $PWD
git clone $REPO_URL -b $REPO_BRANCH openwrt
ln -sf /workdir/openwrt $GITHUB_WORKSPACE/openwrt

- name: 执行DIY_P1_SH
run: |
[ -e $FEEDS_CONF ] && mv $FEEDS_CONF openwrt/feeds.conf.default
chmod +x $DIY_P1_SH
cd openwrt
$GITHUB_WORKSPACE/$DIY_P1_SH

- name: 更新软件源
run: cd openwrt && ./scripts/feeds update -a

- name: 安装软件源
run: cd openwrt && ./scripts/feeds install -a

- name: 加载CONFIG_FILE并执行DIY_P2_SH
run: |
[ -e files ] && mv files openwrt/files
[ -e $CONFIG_FILE ] && mv $CONFIG_FILE openwrt/.config
chmod +x $DIY_P2_SH
cd openwrt
$GITHUB_WORKSPACE/$DIY_P2_SH

- name: 下载Package
id: package
run: |
cd openwrt
make defconfig
make download -j8
find dl -size -1024c -exec ls -l {} \;
find dl -size -1024c -exec rm -f {} \;

- name: 编译固件
id: compile
run: |
cd openwrt
echo -e "$(nproc) thread compile"
make -j$(nproc) || make -j1 || make -j1 V=s
echo "status=success" >> $GITHUB_OUTPUT
grep '^CONFIG_TARGET.*DEVICE.*=y' .config | sed -r 's/.*DEVICE_(.*)=y/\1/' > DEVICE_NAME
[ -s DEVICE_NAME ] && echo "DEVICE_NAME=_$(cat DEVICE_NAME)" >> $GITHUB_ENV
echo "FILE_DATE=_$(date +"%Y%m%d%H%M")" >> $GITHUB_ENV

- name: 检查空间占用
if: (!cancelled())
run: df -hT

- name: 上传bin文件夹
uses: actions/upload-artifact@main
if: steps.compile.outputs.status == 'success' && env.UPLOAD_BIN_DIR == 'true'
with:
name: OpenWrt_bin${{ env.DEVICE_NAME }}${{ env.FILE_DATE }}
path: openwrt/bin

- name: 进入bin/targets移除Packages编译文件
id: organize
if: env.UPLOAD_FIRMWARE == 'true' && !cancelled()
run: |
cd openwrt/bin/targets/*/*
rm -rf packages
echo "FIRMWARE=$PWD" >> $GITHUB_ENV
echo "status=success" >> $GITHUB_OUTPUT

- name: 上传bin/targets中的文件
uses: actions/upload-artifact@main
if: steps.organize.outputs.status == 'success' && !cancelled()
with:
name: OpenWrt_firmware${{ env.DEVICE_NAME }}${{ env.FILE_DATE }}
path: ${{ env.FIRMWARE }}

Actions→选择相应workflows→Run workflows 没有报错的话等待1h左右就能从actions中下载打包好的编译文件

详细关于Github Workflows玩法,敬请期待( 画饼中)

编译过程中的一些坑

版本选择

编译前请先使用git log 查看更新日志,如果发现大更新,请立即回退上个版本

例如大雕在这个版本加入6.1内核,千万先别用,过段时间再更新,先回退,否则就是纯纯小白鼠

实现git checkout 命令就能回退了

如果想切换回主线版本就使用git checkout master 可以回到主分支,再使用git pull更新源码即可

feeds安装过程中警告缺少依赖

make menuconfig的时候如果啥都没有请忽略,如果有就复制完整日志向仓库提供iusse

编译完成后想精简部分组件

不熟悉的小伙伴前往别直接make menuconfig继续编辑,此时你取消luci的组件不会自动取消一些核心文件,导致处理luci全编译了,精简了但是没完全精简,只是没了最小的界面组件

熟悉的话可以查看该luci组件的仓库一般会提供依赖关系,通过/ 在make menuconfig界面查找不需要的依赖文件并取消勾选

不熟悉的就rm .config&&rm .config.old 然后再重新make menuconfig 但是如果是默认配置提供的配置,你就只能使用上面那种方式删除不必要的组件了

make download过程中卡在utils-linux上

说明大概率是网络环境问题,编译过程中请全程保持稳定的科学上网环境

想回退到一开始拉取源码的仓库状态

暴力的方法就是rm -rf 然后git clone 比较干净

据说make distclean 就可以了,我感觉不够彻底哈哈哈,被不小心删除的文件不会变回来

依赖冲突我该如何解决

  1. 删除冲突组件
  2. 向作者仓库提iusse

二次编译命令的顺序问题

是先进行make menuconfig再进行make clean然后才make

  • Title: Openwrt编译从入门到入土
  • Author: Insider
  • Created at : 2024-06-30 09:25:55
  • Updated at : 2024-06-30 09:42:24
  • Link: https://blog.katetseng.icu/2024/06/30/Openwrt编译从入门到入土/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments