[Openwrt编译] 1. 如何编译一个Openwrt固件?
别人编译固件没有自己想要的插件?安装插件困难?害怕有后门?版本太老无法升级?插件太多?不用担心,本系列是一个编译教程贴旨在教会大家编译属于自己的Openwrt固件,没有什么比编译一个自己专用的固件更让人激动的了。
开始之前先解释一下“编译”这个词的意思,“编译”就是一个从源代码转换为可以运行的二进制程序的过程,主要由计算机自动完成,只需铺垫好环境,并且启动编译,随后耐心等待完成即可。而Openwrt的编译有一点不太一样,因为一个操作系统的组成组件较多,所以不仅要编译还要将其打包在一起才是我们常说的固件。
本篇教程以 Lean‘s Openwrt 为例,不同分支的openwrt编译步骤大同小异,主要步骤等都会写在对应源码的github描述页面上,请仔细查阅。
1:你需要有linux命令行操作的基本知识才能看懂本篇教程
如:ls(列出当前文件夹下的文件),cd(进入某某目录),rm(删除文件)等命令的用法
2:还可能需要进行创建一个linux虚拟机(VMware Workstation)
3:根据情况还需要一个能让编译机科学上网的环境
如果你是第一次编译
选择编译机的操作系统
不同的分支中推荐的操作系统可能不一样,比如Lean‘s Openwrt推荐使用debian 11或者是Ubuntu LTS(长期支持版)你可以采用对应分支推荐的操作系统,拿不准用哪个可以直接选择debian或者是Ubuntu(选哪个都行,差别不大)
安装编译依赖的软件
以下代码块里的内容应该在linux的命令行内输入
“不要使用root用户进行编译” Lean’s Openwrt的描述页这样强调,可能做了特别配置在root权限下会出现问题,所以请使用普通用户登录
1 | sudo apt update -y |
↑ 更新软件包列表,不更新会影响之后的操作,sudo是提升权限的意思,安装软件需要root用户的权限才行,输入后会询问当前用户的登录密码。
1 | sudo apt full-upgrade -y |
↑ 更新软件包
1 | 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 libglib2.0-dev libgmp3-dev libltdl-dev libmpc-dev libmpfr-dev libncurses5-dev libncursesw5-dev libreadline-dev libssl-dev libtool lrzsz mkisofs msmtp nano ninja-build p7zip p7zip-full patch pkgconf python2.7 python3 python3-pyelftools libpython3-dev qemu-utils rsync scons squashfs-tools subversion swig texinfo uglifyjs upx-ucl unzip vim wget xmlto xxd zlib1g-dev python3-setuptools |
↑ 安装编译会使用的软件包
不同分支的openwrt要求的软件包可能不一样,也可能会跟随源码更新而有所增删,所以安装软件包时应该按照你想编译的分支要求修改安装软件包包命令。
比如:sudo apt install -y 软件包1 软件包2 软件包3
下载源代码,添加额外的软件包并更新feeds
1 | cd ~ |
↑使用 cd ~ 进入到自己的家目录,注意cd和~中间应该有一个空格
1 | git clone https://github.com/coolsnowwolf/lede |
↑ 下载源代码,下载好后会出现一个叫lede的文件夹,你可以使用ls命令查看当前目录下的文件夹。
你可能想编译其他版本的openwrt,你需要将以上命令中的链接修改为其他的链接
如:git clone 链接
例子:git clone https://github.com/openwrt/openwrt
另外,不同的仓库名称可能会创建不同名称的文件夹,在例子中创建的文件夹名就会叫openwrt,也就是说文件夹名就是仓库的名字
如果代码拉取失败可以直接删除目录,删除命令:rm -fr 目录名 ( 删除后无法恢复,请务必小心使用,谨防误删 )
1 | cd lede |
↑ 使用 “cd 文件夹名” 进入lede文件夹,cd后面应该有一个空格
现在你可以选择编辑 feeds.conf.default 文件添加新的软件包(之后会有单独的一篇文章讲解如何导入额外的软件包)
1 | ./scripts/feeds update -a |
↑ 更新feeds,可能会因为与github连接不稳定导致失败,我建议多执行几次,如果能得到以下结果就是成功了(可能不会以中文提示)
1 | ./scripts/feeds install -a |
↑安装feeds
如果提示以下WARNING,就再执行几次,如果提示依旧存在,表示缺少一些软件包,只有缺少你需要使用的软件包才会影响编译,你可以去找代码维护者反馈问题,或者是尝试补齐缺失的软件包。
格式:WARNING: Makefile ‘package/feeds/软件源/已有的软件包/Makefile’ has a dependency on ‘缺少的软件包’, which does not exist.
如果提示软件包有重复,如: WARNING: Not overriding core package ‘软件包’; use -f to force 则不用担心,无视即可。
配置编译选项
1 | make menuconfig |
↑ 将会进入编译配置菜单,在这个菜单里你需要选择为哪个设备编译固件,还可以选择你想要预装的插件,调整可用空间等。(make menuconfig会另发文章讲解)
配置完成之后将会生成一个.config文件,如果你使用云编译那么之后的步骤就不需要看了,只需要将.config这个文件取出上传到云编译的仓库里,你可以使用winscp或者其他软件/方式将这个文件取出,注意:这是一个隐藏文件,要使用ls -a命令才能看见
下载dl库
1 | make download -j8 |
下载一些东西(我不知道这是在下什么),要等上一会
开始编译
你可以在以下三种方式选一个使用
1 | make -j$(nproc) |
它们的作用都是开始编译,但是有一点不同,“V=s” 和 “V=99” 差不多,意思是输出更加详细的信息。另外 “-j1” 代表使用1个线程编译,以此类推 “-j2” 就是两个线程,而“-j$(nproc)” 有多少线程就用多少线程编译,速度最快
那应该选哪一个呢?
我个人更推荐使用make -j$(nproc) 全线程快速编译,不加 “V=s” 或者 “V=99” 这样会只输出简单信息,简单信息格式整齐且简短很容易发现错误。
但是使用全线程编译,出现错误后可能不会立即停止,错误信息会被其他信息盖过去或格式被打乱,影响判断问题所在,这时候就应该使用 make -j1 单线程编译了,还是输出简单信息,但是使用单线程哪里出错就会在哪里停止,这样错误信息就可以很容易的发现了。
如果发现的错误信息不够详细时,你就可以选择make V=s -j1了,一般给开发者汇报编译错误的日志时应该使用这种。
编译完成后固件会在输出到哪个目录?
会输出到bin/targets下(也在源码目录下)里面会有几层目录进入后会看到固件,如果找不到就表明编译失败了。
第二次编译需要怎样操作?
因为有之前的基础,第二次编译就简单很多了(前提是你没把第一次的东西删了……)
先用cd命令进入上次的源码目录,如果是按照本教程那就应该使用 “cd ~/lede” (~代表家目录,实际位置在 “/home/你的用户名/”下)
然后依次执行以下步骤(每次复制出其中一行运行)
1 | git pull |
执行 git pull 时也有可能出现代码合并相关问题,可以尝试自行解决,也可以直接删除源码目录重新拉取(拉取后按第一次编译来)
如果你不需要重新配置(比如:为另一个设备编译固件,重新选择插件或主题什么的)就跳过 “rm -rf ./tmp && rm -rf .config” 和 “make menuconfig” 两行,这样将会使用上次的make menuconfig配置编译。
如果你是云编译,还是在make menuconfig这步之后就不用看了,只需取出.config文件即可。
还是看不太明白/不想编译怎么办?
不是所有人都愿意下精力去编译一个软件,天无绝人之路,还是有点点鼠标就能定制一个固件的地方
https://openwrt.ai(热心网友kiddin9提供)
小心!定制固件的过程不是透明的,与直接下载他人固件类似,都有植入后门的可能。
另外还有源码维护者提供的固件下载站,这里提供的固件不太可能植入后门,但是固件能定制的空间有限
https://firmware-selector.immortalwrt.org(immortalwrt官方提供)
https://firmware-selector.openwrt.org/(openwrt官方提供)