admin管理员组

文章数量:1530518

OpenWrt包管理器

前言:

这个笔记是记录学习OpenWrt包管理器的流水账,章节逻辑不紧密,内容不全面,新手学习心得,知识点难免存在错误,只是希望对初次接触OpenWrt的新同学有所帮助,同时请各位牛人修正笔记中的错误。致谢!

吐血的学习经历

初次接触OpenWrt,对它真是无从下手,不得要领。通过网络搜索相关内容,上面都是千篇一律地介绍说“这是一个智能路由器系统”……,这和代码管理没有半毛钱关系啊,看了很多资料,没有一点头绪,让初次接触OpenWrt这个新手,有些抓狂,郁闷了一段时间。后来直到厚着脸皮去请教前辈同事,经过他们指点,再加上实际动手操作,才对OpenWrt有了一些肤浅的理解。
学习OpenWrt的包管理方法,要遵守一个原则,就是首先要学习它的软件包管理思想,不能一上来就学习一些命令的操作,也不要死磕某个命令的含义,这样的学习结果是只见树木,不见森林,最后只是会熟练地操作一下命令,处于似懂非懂的状态。

OpenWrt介绍

OpenWrt是一个Linux的嵌入式设备的发行版,起初它是专门为智能路由器设备领域服务的操作系统。它很容易从零开始构建出一个智能路由器或者服务器设备。它完全采用模块化设计,不断地推出补丁和驱动,主要特点是扩展性高,很容易加入设计者的软件包,而无需编译整个系统。
OpenWrt提供了SDK软件包,可以编译每个运行软件,并以包的形式进行安装和卸载。SDK特点如下:

  • 代码中仅包含第三方的开源包的链接地址。
  • 当指定特定平台后,编译时会自动下载源码,并以打补丁方式满足设计需求,可以修改Makefile来下载最新软件包。最后对软件包进行编译。
  • 以OPKG格式安装升级包。
  • 使用LuCI最为用户管理界面

我们公司内部仅仅使用了OpenWrt一小部分功能,就是如何管理软件包。实际上它的软件包管理思想不复杂,就是通过一些配置文件(如feed.conf脚本),对数据包路径的配置和描述,再通过feed命令先安装必要的基础软件包,最后通过配置文件中指定的位置,从网络仓库中拉取配数据包到本地,最后进行编译。

举个不太恰当的例子,就像在家里点外卖一样,你既想吃小龙虾,又想吃面包,还要喝两瓶啤酒,那就要先在手机本地app端填写菜单,然后推送给商家。小龙虾和面包以及啤酒属于不同的商铺,所以菜单中下单的地址就不同。菜单点好后,你的菜就会从不同的商铺送过来。OpenWRT的对软件管理就像是通过菜谱点菜一样,根据需要配置菜单,基础软件包就像是外卖小哥,可以为我们提供处理数据的方法。

通过这个不太恰当的举例,对于新手来说,至少不再迷失在“智能路由器”这个迷雾中,这个点非常重要,甚至比学会数个feed命令都重要。

如何编译系统

接下来不会首先对OpenWrt相关内容进行阐述,以至于让新手再次迷失在理论阐述中。我们直接开始讲如何编译系统,通过操作,首先对编译过程中的原理进行简要的阐述,这样对整体有个了解和把控,然后再去钻研细节。
在进行编译系统之前,首先我们要克隆(项目分支)相关文件到本地,其中重要的目录是“toolchain”、“dl”、“feeds”、“tarage”、“packge”等。

在克隆到本地的文件之中,有一个叫“feed.conf”的文件,这个文件中描述了我们当前平台的内核源码地址、各种软件包地址、应用程序地址等等。这个配置文件,来源于具体的项目配置文件。如当前的下棋机器人的配置文件是:“feeds.conf.yyydetect”,那么在编译之前,我们先要把这个文件拷贝成“feed.conf”文件。即:cp feeds.conf.yyy.conf。在我们当前的开发环境中,实际上开发环境公司已经准备好了,如git、Subversion等工具都安装了。我们先不去了解这个环节,直接进入配置和编译的步骤。

分三步进行编译:

第一步:更新和安装软件包

./scripts/feeds update -a       #更新最新包定义
./scripts/feeds install -a      #安装所有的可选包

这两个feed命令什么意思呢?
意思是,它将安装扩展代码包的编译选项,并对所需要的所有扩展软件包下载和安装。这样我们再运行“make menuconfig”的时候,扩展包才能在配置界面中更新,我们才有机会去选择这些配置选项。

第二步:编译配置

make defconfig

这个命令是对编译工具是否齐全进行检查,最终会把编译配置写入“.config”文件中。

第三步:开始编译
编译阶段又分几个步骤,即从网络上下载模块代码、检查编译工具链、编译三个步骤。

make V=99 -j128 download                             #下载模块代码
make V=99 -j128 tools/compile                          #编译工具链
make V=99 -j128 toolchain/compile                     #编译工具链
make V=99 -j128 && echo "success." || make V=99 -j1    #编译代码

在模块编译时,首先下载代码压缩包,解压代码,打补丁,再根据一些设置选项配置来生成Makefile,再根据Makefiel进行编译。在编译过程中必须保持联网状态,第三方的代码不再自己代码库中,需要在编译时从第三方服务器中下载。

关于OpenWrt顶层目录介绍

通过对上面的编译过程的了解,已经对OpenWrt有个直观的认识了,现在可以对OpenWrt进行比较深入的了解了。
下面先介绍OpenWrt的目录组成
OPKG(OpenWRT Package)是一个轻量快速的软件包管理系统。用来管理软件包的下载、安装、升级、卸载和查询功能,并处理软件包的依赖关系。
openwrt整个目录结构分两部分,从官方下载而来的源代码目录称之为原始目录,将编译后生成的目录称之为生成目录。

原始目录
  1. scripts
    存放了一些脚本,使用了bash,python,perl等多种脚本语言.编译过程中,用于第三方软件包管理的feeds文件也是在这个目录当中.在编译过程中,使用到的脚本也统一放在这个目录中.
  2. tools
    编译时,主机需要使用一些工具软件,tools里包含了获取和编译这些工具的命令。软件包里面有Makefile文件,有的还包含了patch。每个Makefile当中都有一句$(eval $(call HostBuild)),这表明编译这个工具是为了在主机上使用的.
  3. config
    存放着整个系统的配置文件
  4. docs
    包含了整个宿主机的文件源码的介绍, 里面还有Makefile为目标系统生成docs.使用make -C docs/可以为目标系统生成文档.
  5. toolchain
    交叉编译链,这个文件中存放的就是编译交叉编译链的软件包.包括:binutils,gcc,libc等
  6. target
    openwrt的源码可以编译出各个平台适用的二进制文件,各平台在这个目录里定义了firmware和kernel的编译过程。
  7. package
    存放了openwrt系统中适用的软件包,包含针对各个软件包的Makefile。openwrt定义了一套Makefile模板.各软件参照这个模板定义了自己的信息,如软件包的版本、下载地址、编译方式、安装地址等。在二次开发过程中,这个文件夹我们会经常打交道. 事实上,通过./scripts/feed update -a和./scripts/feed install -a的软件包也会存放在这个目录之中.
  8. include
    openwrt的Makefile都存放在这里。文件名为 *.mk 。这里的文件上是在Makefile里被include的,类似于库文件.这些文件定义了编译过程.
  9. 其他
    主要目录就是前面提及的8个,剩下的是单个文件.
    9.1 Makefile:
    在顶层目录执行make命令的入口文件.
    9.2 rules.mk
    定义了Makefile中使用的一些通用变量和函数
    9.3 Config.in
    在include/toplevel.mk中我们可以看到,这是和make menuconfig相关联的文件.
    9.4 feeds.conf.default
    是下载第三方一些软件包时所使用的地址
    9.5 LICENSE & README
    即软件许可证和软件基本说明.其中README描述了编译软件的基本过程和依赖文件.
生成目录

在我们编译完成后除了下载的源码文件,多出来的部分很明显就是编译过程中新生成的。

  1. feeds
    openwrt的附加软件包管理器的扩展包索引目录,简单来说就是下载管理软件包的.默认的feeds下载有packages、management、luci、routing、telephony。如要下载其他的软件包,需打开源码根目录下面的feeds.conf.default文件,去掉相应软件包前面的#号,然后更新源:
    ./scripts/feeds update -a
    ./scripts/feeds install -a
  1. build_dir
    在前面的原始目录中,我们提到了host工具,toolchain工具还有目标文件.openwrt将在这个目录中展开各个软件包,进行编译.所以这个文件夹中包含3个子文件夹:
    1) host 在该文件夹中编译主机使用的工具软件
    2) toolchain-XXX 在该文件夹中编译交叉工具链
    3) target-XXX 在此编译目标平台的目标文件,包括各个软件包和内核文件.
  2. bin
    保存编译完成后的二进制文件,包括:完整的bin文件,所有的ipk文件.
  3. dl
    在编译过程中使用的很多软件,刚开始下载源码并没有包含,而是在编译过程中从其他服务器下载的,这里是统一的保存目录
  4. staging_dir
    用于保存在build_dir目录中编译完成的软件.所以这里也和build_dir有同样的子目录结构. 比如,在target-XXX文件夹中保存了目标平台编译好的头文件,库文件.在我们开发自己的ipk文件时,编译过程中,预处理头文件,链接动态库,静态库都是到这个子文件夹中.
    6.tmp
    从名字来看,是临时文件夹.在编译过程中,有大量中间临时文件需要保存,都是在这里.
    7.logs
    这个文件夹,有时可以看到,有时没有.这是因为这个文件夹保存的是,编译过程中出错的信息,只有当编译出错了才会出现.我们可以从这里获取信息,从而分析我们的软件编译为什么没有完成.
编译脚本

目录scripts是关于编译脚本的文件,不同的脚本功能不同,如:

scripts/download.pl脚本是下载编译软件包源码的。
scripts/feeds是扩展软件包工具,用于下载

和安装编译扩展软件包工具等等。

编译扩展机制feeds

传统的开发中,当编译某个软件时,先去检查依赖是否安装,如果没有安装将报错,然后手动去安装依赖。

OpenWrt通过feeds机制,会自动检查依赖,提高了开发效率。具体的做法是,把开发所需要的软件包工具的更新地址写入feeds中,在访问时提供一个统一的访问接口,这样用户不用关心软件包的存储位置。它由两部分组成,即扩展包位置配置文件feeds.conf.default和脚本工具feeds。操作命令就是上面提到的:

./scripts/feeds update -a #更新最新包定义
./scripts/feeds install -a #安装所有的可选包

软件包的定义

宏定义以“Package/”开头,即Package开头的定义,用于“make menuconfig”选择和编译生成的软件包。每一个软件包有一个Makefiel,所有的软件包代码编译过程是一样的,只是编译的参数不同而已。还有以“Build/”开头的,用于代码的编译。
在OpenWrt增加软件包
OpenWrt扩展性强,可以任意在其中增加支持的相关软件包,也可以增加自定义软件包,只要遵守OpenWrt的软件包管理的规定,很容易实现。基本原理就是通过几个Makefile和OpenWrt建立关联,Makefile需要遵循OpenWrt的约定。
步骤如下:

  1. 在package目录下建立一个文件夹(xxx)
  2. 在文件夹中增加一个Makefile
    Makefile要遵循OpenWrt的规定,软件包的Makefile必须包含下面的3个.mk文件,分别为:
     include $(TOPDIR)/rules.mk
     include $(INCLUDE_DIR)/kernel.mk
     include $(INCLUDE_DIR)/package.mk
    编写软件包的基本信息,这些软件包的信息均以PKG_开头,其意思和作用如下:
     PKG_NAME表示软件包名称,将在menuconfig和ipkg可以看到。
     PKG_VERSION表示软件版本号。
     PKG_RELEASE表示Makefile的版本号
     PKG_SOURCE表示源代码的文件名。
     PKG_SOURCE_URL表示源代码的下载网站位置。@SF表示在sourceforge网站,@GNU表示在GNU网站,還有@GNOME、@KERNEL。
    用户程序和内核模块的定义不一样。用户软件件包使用Package,內核模块使用KernelPackage。
  3. 包含&更新最新包的定义并且安装软件包
    make package/symlinks 或者
    ./scripts/feeds update -a
    ./scripts/feeds install -a
  4. 选择软件包
    通过配置界面选择可用的软件包(刚才更新的软件包),才能编译到OpenWrt中。配置界面和Linux的make menuconfig界面相似。通过命令 make menuconfig调出配置界面。
    make menuconfig
  5. 编译软件包
    编译命令如下
    make package/xxx /{clean,compile} V=s
    Open WRT内核打补丁
    打补丁步骤
    进入Openwrt目录, make target/linux/clean V=99,将内核清理干净。
    make target/linux/clean V=99
    将内核应用所有patch并生成最新代码到build_dir目录下。
    make target/linux/prepare V=99
    进入最新kernel的source code目录。
    cd build_dir/linux-ar71xx_generic/linux-x.x.x
    新建965-ipheth-iphone5-6-support.patch,并指定保存目录到patches/platform/下
    quilt new platform/965-x.x.x.patch
    编辑ipheth.c
    quilt edit drivers/net/usb/ipheth.c
    保存patch
    quilt refresh。
    进入Openwrt目录,将patch应用,此时会生成新patch,到target/linux/ar71xx/patches-3.3/下查看
    make target/linux/update V=99
    patch-* 子目录包含应用于每个,OpenWrt 目标的内核补丁。所有补丁都应命名为“NNN-lowercase_shortname.patch”
    并分为以下几类:
    0xx - 上游向后移植
    2xx - 内核构建 / 配置 / 头文件补丁
    3xx - 架构特定补丁
    4xx - mtd 相关补丁(子系统和驱动程序)
    5xx - 文件系统相关补丁
    6xx - 通用网络补丁
    7xx - 网络 / phy 驱动程序补丁
    8xx - 其他驱动程序
    9xx - 未分类的其他补丁
    所有补丁都必须以一种潜在的上游方式提供,这意味着:
     它们必须包含适当的主题
     它们必须包含正确的提交消息,解释它们更
     它们必须包含有效的 Signed-off-by 行
    常用的命令如下
    quilt series 查看所有patch。
    quilt top 查看栈顶patch(即,最后应用的patch)。
    quilt applied 查看已应用的patch。
    quilt unapplied 查看未应用的patch。
    quilt files 查看patch关联的文件。
    quilt diff 对比修改的文件。
    quilt new 新建patch文件。
    quilt delete 删除patch文件。
    quilt add 将文件的当前状态与Patch联系起来。对文件的修改,diff内容会增加到patch中。
    quilt remove 解除文件与Patch的关联,patch中针对此文件的diff内容会从patch中删除。
    quilt push patch 入栈。即选择patch并应用。或者说导入patch。
    quilt pop patch 出栈。撤销,导出patch,patch文件并不删除。
    quilt import 从他处导入patch。
    quilt edit 编辑当前文件,包含了quilt add操作,并针对top patch。
    quilt refresh 保存当前patch。
    OpenWrt的Makefile分析
    在Makefile开头,将openwrt顶层目录下的rules.mk文件中的内容和include目录下的kernel.mk、package.mk导入进来。ules.mk文件中定义了许多重要变量。
    #Makefile 文件
    include $(TOPDIR)/rules.mk
    include $(INCLUDE_DIR)/kernel.mk
    include $(INCLUDE_DIR)/package.mk
    PKG_XXX系列变量
    PKG_NAME -软件包的名字, 在 menuconfig 和 ipkg 显示
    PKG_VERSION -软件包的版本
    PKG_RELEASE -makefile 的版本对于从git上下载的软件包,以下这些变量定义是必须的
    PKG_REV -要下载的软件包在svn/git上的版本号
    PKG_SOURCE -要下载的软件包的名字,一般是由 PKG_NAME 和 PKG_VERSION 组成
    PKG_SOURCE_URL -下载这个软件包的链接
    PKG_SOURCE_SUBDIR -源代码目录名
    PKG_SOURCE_VERSION -源代码版本号,用于对从git下载的源代码进行MD5检查
    PKG_SOURCE_PROTO -源代码的下载方式,即svn/git
    PKG_CONFIG_DEPENDS -定义了选择这个软件包时指定的配置选项
    PKG_BUILD_DIR -真正编译当前软件包的目录
    下面是feeds支持的方法类型:
    src-bzr通过使用bzr从数据源的pxiaath/URL下载数据
    src-cpy通过从数据源path拷贝数据
    src-darcs通过使用darcs从数据源path/URL下载数据
    src-hg通过使用hg从数据源path/URL下载数据
    src-link创建一个数据源path的symlink
    src-svn通过使用svn从数据源path/URL下载数据
    其他杂记
    编译方法和参数设置:编译OpenWrt(在顶层目录下)
    更新包
    make package/symlinks
    配置包
    make menuconfig
    编译模块(k016wifi模块名称)
    make package/k016/{clean,compile} V=s
    make package/k016/clean V=s
    make package/k016/compile V=s
    参数解释
    make V=99 #V=99表示输出详细的debug信息
    make world #表示编译所有
    make j=2 V=99 #如是多核CPU,加j=2 选项理论上能加快编译速度
    make -j 2 V=99 #可加快编译速度(不推荐使用)

本文标签: 管理器OpenWRT