沫延说
沫延说

零基础编译OpenWrt看这一篇就够了

前言

在这个信息化产业遍地开花的时代,随着家庭宽带速率的不断提升,现有路由器厂商的解决方案逐渐不再能满足有进阶需求的用户,软路由解决方案应运而生,OpenWrt是其中比较有代表性的软件路由系统

OpenWrt官网提供了多种现成的解决方案供直接下载使用,这些现成的解决方案不仅包括精确到设备的OpenWrt系统固件,还包括了一些架构、平台的通用型OpenWrt系统固件。

本文最后修订时间:2023年1月29日。

我不希望你自行编译OpenWrt固件

你没看错,我写这篇文章的初衷并不是希望用户自行编译OpenWrt的固件,反而我希望用户使用官网现成提供的固件,原因如下:

1.自行编译与官方编译的固件在执行效率上没有差别

一般来说,官方更推荐我们使用ImageBuilder(固件生成器)去生成固件,固件生成器被用于仅次于源码交叉编译的方法,用于:

  1. 在较小的固件中容纳更多软件
  2. 设备仅有 32MB 或更少的 RAM,并且 没有opkg功能

使用固件生成器可以避免因不合理的配置导致的额外系统资源占用和降低系统运行效率的可能性。

如果您只想编译某个软件,也可以尝试使用OpenWrt SDK,这样可以节省部署编译环境期间的用时

2.自行编译OpenWrt固件需要花费大量的时间和精力

自行编译OpenWrt固件需要花费30分钟到3个小时不等的时间,这不仅对计算机配置有要求,更需要用户有足够的耐心去排错和补充依赖,

由于众所周知中国国际互联网拥堵和管制情况,会使编译失败率惊人的高,且国内镜像源并不能解决此问题,因为在编译初我们虽然可以使用国内镜像的feeds,但是feeds中各个组件需要通过git去获取源码,这并不是几个镜像就可以解决的事情

根据我的经验,用户增加越多的功能,编译成功的概率将会越低,且不可避免的使固件包容量变大,从OpenWrt 22.03版本开始,用户可能需要额外的步骤才能实现上传超过128MB大小的固件

3.需要有Linux基础

编译操作需要在兼容的Linux发行版本中进行,或者您可以使用特殊发行版本并自行解决依赖问题。

注:官方推荐交叉编译操作系统为Ubuntu版本为18.04、20.04和22.04,同时您也可以使用CentOS系统进行,但是官方的文档较少

 

综上所述,如果没有特别需求,我并不希望用户自行编译OpenWrt固件,但是如果您存在(不仅限于)以下几种情况,您只能选择自行编译这一种方式:

  1. 相较于通用固件,有较大的差异以至于无法启动OpenWrt,例如您使用的设备使用的是相对冷门的硬件,例如一些冷门的以太网接口,或您使用的设备需要其他特殊支持,例如增加人体交互设备支持、大容量存储以及更多的硬盘格式支持;
  2. 希望深度定制或优化代码;
  3. 所使用的的软件需要内核或驱动支持才可运行;

最后,如果你执意要自行编译OpenWrt,我还有几个好消息要告诉你

  1. 看到这篇文章,可以说大大增加了一次编译通过的成功率,如果完全按照本文走,编译成功是绝对的。
  2. 可以使用境外服务器进行编译,境外的云供应商提供相较于国内更加低廉的价格和更高的性能,最重要的是提供了更优质的编译网络
  3. 我已经独立开发了一个分之,名为BoltWrt,此固件更加适用于中国的网络环境和用户使用习惯,也欢迎有兴趣的朋友加入这个项目。

 

 

自行编译教程

1.搭建编译环境

1.1搭建虚拟环境

首先你需要一台Ubuntu系统的主机,使用Ubuntu是因为OpenWrt官方是基于这套系统执行交叉编译的,你可以用虚拟化技术来实现:搭建虚拟机或购买云主机,虚拟机方面我建议使用VMware的解决方案,云主机可以使用阿里云或Vultr的解决方案。

 

当你拥有了运行着Ubuntu系统的主机后,你需要登录一个非Root但有sudo权限的账户,使用虚拟机部署系统的用户在安装时的应该已经创建好了,使用云主机产品的用户可以通过adduser [用户名]命令创建,并通过命令允许新建立的用户有资格使用sudo命令

一切准备就绪,使用su [用户名]命令登录这个新建立的账户,可能需要用到的命令如下:

adduser openwrt
usermod -a -G sudo openwrt
su openwrt

 

如果你觉得麻烦,当然也有使用root账户进行的方式,只是出错的概率会增加:

同时,在make命令前,设置环境变量“FORCE_UNSAFE_CONFIGURE”的值为1,也就是执行命令:export FORCE_UNSAFE_CONFIGURE=1

本文案例使用Ubuntu 20.04操作系统

可供忽略的提示
keyboard_arrow_down

当使用root用户编译,下面所有命令中均无需使用sudo执行,因为本身就是root权限,但加上sudo也不会影响什么

1.2安装编译必需的依赖

这一步非常简单,依次执行指令,他会更新所有随系统附带的软件并安装相关依赖:

sudo apt update
sudo apt upgrade
sudo apt-get install build-essential ccache ecj fastjar file g++ gawk gettext git java-propose-classpath libelf-dev libncurses5-dev libncursesw5-dev libssl-dev python python2.7-dev python3 unzip wget python3-distutils python3-setuptools python3-dev rsync subversion swig time xsltproc zlib1g-dev

如果您使用Ubuntu 22.04,则请将最后一条命令替换为:

sudo apt install build-essential clang flex g++ gawk gcc-multilib gettext git libncurses5-dev libssl-dev python3-distutils rsync unzip zlib1g-dev file wget

此时开始,网络不行的用户的耐心和信心开始受到攻击,成就感和期待感同脸上的笑容一起逐渐消失

当然了,也许你需要临时配置一下代理:

配置临时环境变量http_proxy和https_proxy以实现本次ssh登录的网络代理

export http_proxy=http://yourproxyaddress:proxyport
export https_proxy=http://yourproxyaddress:proxyport

 

1.3拉取项目源码

此时你应该使用cd ~命令回到用户home目录下再进行操作,或者选择一个你喜欢的目录,

考虑到并非生产环境无需注重规范性,我就直接在home目录执行了

cd ~
git clone https://git.openwrt.org/openwrt/openwrt.git

此时你将拉取最新的源码,新到还没有正式发布,无论是OpenWrt官方还是我,都不建议你这样做,所以你需要使用-b参数,拉取正式版本源码,下两条指令将示例如何使用-b参数选择克隆文章发布时的最新版本22.03源码。

cd ~
git clone -b openwrt-22.03 https://github.com/openwrt/openwrt.git

至于如何获取到版本号:

您可以通过访问OpenWrt的github官网,查看其tab标签或在执行完`git clone https://git.openwrt.org/openwrt/openwrt.git`命令后,使用cd openwrt/命令进入源码目录,然后使用git tag命令来查看分支版本。

 

随后使用cd命令进入刚刚拉取的源码目录

如果你已经拉取过了,可以在项目根目录使用git pull重新拉取

1.4编译前准备

依次执行两条指令

./scripts/feeds update -a
./scripts/feeds install -a
如果报错权限问题
keyboard_arrow_down

请回退到上一级目录,输入chmod -Rf 777 openwrt

随后你已经做好了所有的编译前准备工作,使用下面一条指令定制OpenWrt

make menuconfig

终于来到了一个“可视化”界面,

左右控制按钮光标,Enter选择按钮光标,上下控制菜单光标,

通过空格或y/n切换菜单光标中的选项,

选项有三:

空,即为空。。。。

M,即为仅编译,不安装项(可以在部署完成后手动安装以降低固件大小)

*(星号),即为编译并安装

最后一定不要忘记save保存。

此步为了增加成功率,以保持信心和建立成就感,可以在选择好架构和固件格式后全默认先编译一遍。

2.开始编译

到了这里没有出现错误,你就可以开始编译了,如果你对你的网络质量没什么信心,可以先执行一下make download,将需要下载的数据准备好。

小经验
keyboard_arrow_down

执行过make download后在源码根目录会生成dl文件夹,该文件夹可备份以节省下次编译的下载时间

执行命令make即可开始交叉编译了(交叉编译的意思就是在一种系统编译另一种系统的可执行程序的行为)

make

当然了,如果你想提高一些速度,并且不担心出现问题(根据官方描述,多线程编译有可能会出现问题但我没有遇到过),可以使用-j [n]参数进行多线程编译,其中“n”替换为处理器线程数+1的值,例如云主机为2核心,则:

make -j 3

您也可以使用官方给出的“一步到位”命令:make -j $(($(nproc)+1))

 

如果直接执行make失败了,且报错信息均已排查没有问题,你通样可以使用-j参数强制将线程设为1,即:make -j 1

也可通过使用传递参数V=s打印更详细的编译日志,例如:执行make -j1 V=s

毕竟要编译那么长时间,一直盯着他有些无聊,可以将三个命令整合一下:

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

只要第一条命令返回“非”就会继续执行第二条

有个好玩儿的点
keyboard_arrow_down

根据官方文档给出的命令,传递-j参数时有时候有空格有时候又没有空格,即make -j4和make -j 4的区别

 

编译成功后,固件位于项目根目录下的bin文件夹内

 

3.再次编译

如果我们对OpenWrt进行了调整,需要再次编译固件,此时我们就需要清理首次编译时的一系列产物防止对下一次编译造成影响,具体清理命令如下:

仅清理编译结果(bin目录)
make clean

清理所有编译文件(除了.config、dl文件夹和feeds以外都清理)
make dirclean

清理所有编译文件以及相关依赖(完全清理干净,一键回到刚git clone下来的时候)
make distclean

 

如果您手动或使用make menuconfig对配置文件.config进行了调整,则需要执行make defconfig来自动调整配置文件

 

 

没有标签
首页      运维      Linux系统      零基础编译OpenWrt看这一篇就够了

Morton.L

文章作者

发表回复

textsms
account_circle
email

沫延说

零基础编译OpenWrt看这一篇就够了
前言 在这个信息化产业遍地开花的时代,随着家庭宽带速率的不断提升,现有路由器厂商的解决方案逐渐不再能满足有进阶需求的用户,软路由解决方案应运而生,OpenWrt是其中比较有代表性的…
扫描二维码继续阅读
2021-01-17