很多开源项目可能无法直接使用,需要有人通过编译产出成品才能使用,或者你想修改代码后测试验证,那么都需要通过编译来完成,本篇文章为初入门的技术爱好者讲解 OpenWrt 编译相关的基础知识,常见问题等。
编译概念
什么是编译?
一个程序是由人编写的,编写而成的文件称为“源代码”文件,这个文件本质上就是纯文本文件,里面是人类能看懂的字符内容(称为高级语言),但计算机系统是看不懂的,计算机只认识 0和1 (称为机器语言),而要想作为程序运行,则必须要将源代码文件转换为操作系统能看懂的文件(称为可执行文件),这个转换的过程就称为“编译”。
编译流程
“编译”在整个程序开发过程中,只是其中一个简单的环节,只需要执行几个简单的命令,然后等待“编译器”自动执行完毕即可。
编译常见问题
正常情况下,编译只需要简单的命令,然后等待编译完成即可。
但仍然可能会遇到编译失败,这和程序作者有关,这个程序是给什么平台用、作者的编译环境是什么、作者最新的代码修改是否出现了笔误、网络原因导致文件下载损坏等等,这些都是可能的影响因素。
即便是看似同类型的操作系统,有时也不一定能编译成功,比如常见的 Centos 和 Ubuntu,虽然都是 Linux 系统,但它们的软件并不能通用,而且在一个系统编译成功,可能在另一个系统就会编译失败。
遇到编译错误时,就需要检查错误日志,分析原因,有时可能还需要调整部分源代码来解决编译错误,这往往需要一定程度的技术经验积累才能解决,并不是靠复制粘贴几个命令就能解决的。
编译所需条件
虽然编译对于程序员等专业技术人员来说是最简单的步骤,但是如果你只是一个外行,或者技术经验尚浅的学生,那么仍然需要具备一些基础条件,否则你将事倍功半,编译的目的是将源代码转换为程序,虽然你无需编写代码,但是为了编译成功,你至少需要学会看懂部分与编译有关的代码,要明白编译时需要哪些依赖项、正确的编译步骤等,否则你就属于无头苍蝇到处乱撞,就算误打误撞编译成功,也很可能因为你错误的编译步骤等,导致程序出现本不应该出现的功能异常等。
玩转编译至少需要:具备一定程度的英语阅读理解能力,有较大的耐心,自学能力强,逻辑思维较强,一定程度的 Linux 相关使用经验,熟练掌握了现代计算机基础知识。
如果你只是为了解决自己的 DIY 需求,并且不愿意投入精力和时间去学习相关的各类知识,只是寄希望于翻阅几篇教程,靠复制粘贴几个命令,或简单的点几下鼠标就搞定一切,那你来错了地方,也选错了方向。
对于连基础计算机知识都懒得学的同学,或忙得没时间学基础知识的上班族,不想自学,又想玩技术 DIY ,最好的选择是找专业人士提供技术服务,只要钱给到位,一切问题都能解决。
程序开发流程
通过上面的流程图,不难发现,编译其实只是程序开发的其中一环,而且是最简单的一环,只需使用少许固定的编译命令即可,甚至可以使用脚本来执行自动化编译。
正确的反馈问题
程序员开发一款软件后,并不能保证百分百没有任何问题,所以需要反复进行“测试”与“调试”步骤,不断改进和修复软件,而开源软件项目往往因为程序员的时间精力有限,只能做到有限的软件“测试”与“调试”,无法针对各类复杂的应用环境进行全面测试,所以如果你是开源项目的用户,想要出力做贡献,除了提供“资金支持”,你至少还可以提供“测试”反馈,以帮助开发者完善软件。
什么样的反馈信息才能真正帮助开发者?
当你使用某个软件发生错误现象时,这时你应该收集系统日志、当前系统安装的软件列表、当前运行的进程信息、这个软件当前的配置文件、你执行了哪些操作、问题是否能百分百复现、相关截图说明、屏幕录像等等,诸如此类对排查问题有帮助的信息都应该收集起来,然后提供给开发者,这样开发者才能排查问题原因,如果你提供的信息足够详细且准确,开发者甚至只需要翻阅你提供的反馈信息就能找到问题所在,很快就能着手开始修复工作,能极大的减少开发者的工作量。
OpenWrt 编译准备
Windows 用户
一台配置够用的电脑(内存至少8G)
下载并安装 VMware Workstation Pro
下载 Ubuntu 20.04.2 64 位安装镜像。
已连接国际互联网。
Linux 用户
安装编译所需依赖。
已连接国际互联网。
部署编译环境
1. 打开VMware新建虚拟机:CPU 配置为实际核心数,内存至少 4G,硬盘至少 60G。
2. 选择 Ubuntu 安装镜像,启动虚拟机开始安装系统,选择自动分区,最小化安装即可。
3. 登录虚拟机 Ubuntu 系统,安装编译所需的软件包。
sudo apt-get update sudo apt install -y build-essential ccache ecj fastjar gawk \ gettext git java-propose-classpath libelf-dev libncurses5-dev \ libncursesw5-dev libssl-dev python-is-python2 python2.7-dev \ python3-distutils python3-setuptools subversion swig xsltproc \ upx-ucl libtinfo5 g++-multilib qemu-utils curl sudo apt-get clean
4. 任意进入一个目录,开始下载所需的软件项目。
新手请注意:编译 OpenWrt 时的操作,均不要追加 sudo 命令,目录不要使用中文,否则会百分百导致编译失败。
OpenWrt官网项目:
git clone https://github.com/openwrt/openwrt.git
OpenWrt-Life项目:
git clone https://git clone -b openwrt-21.02 https://github.com/ikghx/openwrt-life.git
5. 进入源代码目录,更新并安装软件库。
./scripts/feeds update -a ./scripts/feeds install -a
6. 打开编译菜单界面,按个人需要进行定制。
make menuconfig
7. 执行编译命令
make
8. 等待编译完成,编译成功后会在源代码目录生成 “bin” 目录,内含固件和配套的软件ipk包,首次编译耗时预计3-6小时,根据你的网络速度有关。
OpenWrt 其它常用编译命令
多线程加速编译,例如系统配备了4核心处理器。
make -j4
编译时显示详细信息,用于排查编译错误。
make V=s
打开内核菜单界面,按需定制内核功能。
make kernel_menuconfig
清除当前编译机型的软件编译目录,以便快速测试软件更改。
make clean
清空所有编译目录,以便开始全新编译。
make dirclean
检查已选择的项目,相关编译文件是否有明显错误。
make check
仅下载已选择项目的源码包。
make download
导入已经配置好的 .config 文件,用于快速应用编译配置,以跳过执行 make menuconfig
make defconfig
刷新补丁文件,排查是否有补丁文件错误,能自动修正细微差异。
# 刷新软件包补丁,并显示详细信息。 make package/samba4/refresh V=s # 刷新当前编译机型的内核补丁,并显示详细信息。 make target/linux/refresh V=s
单独编译某个软件包。
# 编译指定软件包,并显示详细信息。 make package/samba4/compile V=s # 清理指定软件包编译目录,并显示详细信息。 make package/samba4/clean V=s
OpenWrt 自编译固件使用官网软件源
一些初入门的技术爱好者,觉得 OpenWrt 官网固件不合心意,想使用源代码自行编译,却又不敢过多修改 OpenWrt 的源代码,害怕弄巧成拙出现新的Bug,于是想仅仅自定义一些简单参数,比如默认 LAN 口IP、默认分区大小、集成几个软件等等个性化固件参数,然后让自己编译的固件直接使用 OpenWrt 的官网软件源。
这种情况遇到的问题是,自行编译的固件内核校验码与官网软件源不同,安装内核模块时会提示内核版本不匹配,导致安装失败,编译时你即使选择了所有软件包,最终编译出来的内核校验码也是与官网不同的,因为官网固件的编译方式不同,具体原因这里就略过。
要想解决这个问题也很简单,只需要将内核版本号固定为官网一样的即可。
首先根据自己需要下载对应的官网发行版源码,例如下载 19.07.5 发行版源码。
git clone -b v19.07.5 https://github.com/openwrt/openwrt.git
然后添加固定的内核校验码(vermagic 值),
打开 openwrt/include/kernel-defaults.mk,搜索 .vermagic
会找到这样一行:grep ‘=[ym]’ $(LINUX_DIR)/.config.set | LC_ALL=C sort | mkhash md5 > $(LINUX_DIR)/.vermagic
将这行代码替换为:cp $(TOPDIR)/.vermagic $(LINUX_DIR)/.vermagic
然后根据自己编译的机型平台,找到对应的官网软件源内核 vermagic 值,例如:x86_64
然后在 OpenWrt 源代码目录新建一个文件 .vermagic,里面写入OpenWrt 官网软件源的 vermagic 值即可。
接着你就可以开始执行编译命令了,编译完毕后的固件就能直接使用 OpenWrt 官网软件源。
让自编译固件使用镜像软件源
从 OpenWrt 官网下载页面可以看到,有很多软件源镜像站点,你可以选择一个最快的软件源镜像站,将固件默认的软件源地址改为镜像软件源地址,这样刷机完毕后就无需再手动修改软件源地址了。
打开 openwrt/include/version.mk, 搜索 $(if $(VERSION_REPO),$(VERSION_REPO)
将此行代码中的网址替换为镜像软件站的地址即可,例如使用“上海交通大学”的镜像站。
关于软件源的使用技巧
很多初入门的 OpenWrt 用户有一个误解,以为第三方编译的固件完全无法使用 OpenWrt 的官网软件源,其实本质上来说只要第三方固件编译时没有修改编译库,且内核版本基本相同,那么都是可以正常使用官网软件源的。
例如 GL-iNet 路由器的固件就是基于 OpenWrt 的,想自行安装某些软件时,发现其缺少很多内核模块,首先查看 GL-iNet 的固件内核版本号,假如为:4.14.209,那么你只需要从 OpenWrt 官网软件源手动下载所需的对应版本的内核模块,然后使用强制安装命令安装即可,完全可以正常运行,没有任何问题。
其它非 kmod 开头的常规软件,更是可以直接在线安装,只需修改 “OPKG 配置” ,添加软件源地址即可。
这类与内核模块无关的软件,只需要固件是使用 musl 库编译的即可安装使用,和内核版本无关。
基于 OpenWrt 的第三方编译的固件,只有在两种情况下才真正无法使用 OpenWrt 的官网软件源,
一种是修改了编译库,默认是使用 musl 库编译,但是被改为了使用 glibc 库,
一种是内核版本差异太大,比如 4.9 与 4.14 ,这种大版本差异也是完全没办法使用的。
总结
理论上来说编译确实简单,但前提条件是源代码文件已非常完善,然后只需执行简单的编译命令就能成功,对于 OpenWrt 的编译,并不是你想的那么简单,因为 OpenWrt 属于一个整合系统,其是由大量的各类独立的软件组合而成,各个软件之间都或多或少互有关联,牵一发而动全身,加上这是开源系统,各个开发者各显神通,功能差异、版本不一、编译环境也各不相同,导致时常出现编译问题,也称为“系统碎片化”,如果你想要随心所欲的玩转 OpenWrt,实际上你需要有深厚的技术功底,有强大的代码纠错与整合能力。
有些基于 OpenWrt 修改而成的商业路由器系统,往往都采用很旧的系统版本,而且几乎不升级,这是因为很多商业路由器的驱动程序只能使用旧内核版本,而且为了降低维护成本,源代码不会做大更新,甚至不更新,只对使用过程中发现的错误进行修复。
文章来源:https://iyzm.net/openwrt/176.html
本文章由作者:佐须之男 整理编辑,原文地址: OpenWrt编译入门教程基础概念入门编译常见问题