专栏首页QB杂货铺浅析busybox如何集成到openwrt

浅析busybox如何集成到openwrt

背景

近日添加了一个包到openwrt中,在此过程中又对openwrt多了一些认识

这个包本身自带了kconfig,可直接在这个包里面执行make menuconfig进行配置,然后执行make

但要集成到openwrt中,就需要把这些配置项都集成到openwrt的配置中。

面对这种情况,当然是要找个现成的例子做参考,首先想到的就是busybox。

以下以busybox为例进行说明,源码摘自github https://github.com/openwrt/openwrt/tree/master/package/utils/busybox

如何集成配置项

busybox本身也自带了配置项,但实际上我们却可以在openwrt的总的配置项中对其进行配置,而无需进入busybox目录单独对其做配置。

通过查看busybox包的makefile,可以看到,这个集成是这么做的。 对于busybox原生的配置项不做改动,而是针对每个配置项都另外生成一个对应的配置项,用于集成到openwrt中。 这些配置项在 openwrt/package/utils/busybox/config目录中。并通过 openwrt/package/utils/busybox/Config.in 文件连接到openwrt配置项。下面结合代码分析下。

从Makefile中可以看到,对于openwrt来说,busybox包的配置,就来源于Config.in

文件 openwrt/package/utils/busybox/Makefile

define Package/busybox/config
    source "$(SOURCE)/Config.in"
endef

先来看下openwrt/package/utils/busybox/Config.in这个总的配置文件。

文件 openwrt/package/utils/busybox/Config.in

if PACKAGE_busybox

config BUSYBOX_CUSTOM
    bool "Customize busybox options"
    default n
        help
          Enabling this allows full customization of busybox settings.
          Note that there are many options here that can result in a build
          that doesn't work properly.  Enabling customization will mark your
          build as "tainted" for the purpose of bug reports.
          See the variables written to /etc/openwrt_release

          Unless you know what you are doing, you should leave this as 'n'

    source "Config-defaults.in"        #引入默认配置项的值

    if BUSYBOX_CUSTOM             #当选择了自定义配置项时
        source "config/Config.in"       #引入对应于busybox原生配置项的配置文件,允许用户完全自定义
    endif

config BUSYBOX_USE_LIBRPC
    bool
    default y if BUSYBOX_CUSTOM && BUSYBOX_CONFIG_FEATURE_HAVE_RPC
    default y if !BUSYBOX_CUSTOM && BUSYBOX_DEFAULT_FEATURE_HAVE_RPC

endif

这里面定义了一个BUSYBOX_CUSTOM配置项,当不选中时,就只引入默认配置"Config-default.in",当选中时,就再引入config目录下对应于busybox原生配置项的配置文件,以允许用户完全自定义这些配置。

先看不自定义配置的情况。此时Config.in就只引入了Config-defaults.in,打开这个文件,可以看到,里面是一系列以BUSYBOX_DEFAULT开头的配置项,如

文件 openwrt/package/utils/busybox/Config-defaults.in

config BUSYBOX_DEFAULT_HAVE_DOT_CONFIG
    bool
    default y
config BUSYBOX_DEFAULT_DESKTOP
    bool
    default n
config BUSYBOX_DEFAULT_EXTRA_COMPAT
    bool
default n

这些其实就是对应到busybox本身的所有配置项的。只是名字略有不同。最终,在Makefile中,会将这些配置项转换为busybox本身的配置文件。即

文件 openwrt/package/utils/busybox/Makefile

define Build/Configure
    grep 'CONFIG_BUSYBOX_$(BUSYBOX_SYM)' $(TOPDIR)/.config | sed -e "s,\\(# \)\\?CONFIG_BUSYBOX_$(BUSYBOX_SYM)_\\(.*\\),\\1CONFIG_\\2,g" > $(PKG_BUILD_DIR)/.config
    yes 'n' | $(MAKE) -C $(PKG_BUILD_DIR) $(MAKE_FLAGS) oldconfig
endef

从总的配置文件中,滤出所有CONFIG_BUSYBOX_$(BUSYBOX_SYM)开头的配置项,并通过sed将前缀CONFIG_BUSYBOX_$(BUSYBOX_SYM)去掉,生成用于busybox编译的.config文件。再执行一遍make oldconfig,以自动处理掉一些配置不合适的情况,修正最终的.config文件。

其中这个$(BUSYBOX_SYM)变量,也是在Makefile中赋值的。

文件 openwrt/package/utils/busybox/Makefile

BUSYBOX_SYM=$(if $(CONFIG_BUSYBOX_CUSTOM),CONFIG,DEFAULT)

这样就清楚了。busybox的makefile中,在未选中CONFIG_BUSYBOX_CUSTOM的情况下,BUSYBOX_SYM的值为DEFAULT,则将CONFIG_BUSYBOX_DEFAULT_xxx过滤出来,处理为busybox最终的配置项。这些CONFIG_BUSYBOX_DEFAULT_xxx是在Config-defaults.in文件中配置好的。

在选中了CONFIG_BUSYBOX_CUSTOM的情况下,则最终将CONFIG_BUSYBOX_CONFIG_xxx过滤出来使用。

接下来看自定义的情况。自定义的情况其实也很清晰,就是引入了config目录下的配置项。 这些配置项,跟busybox源码中的布局和内容完全一致,区别只是配置项的名字都为BUSYBOX_CONFIG开头,且默认值均为对应的BUSYBOX_DEFAULT_开头的配置项。记得吗,这些BUSYBOX_DEFAULT_开头的配置项都是在Config-default.in中配置的。如下例子

文件 openwrt/package/utils/busybox/config/init/Config.in

config BUSYBOX_CONFIG_INIT
    bool "init"
    default BUSYBOX_DEFAULT_INIT
    select BUSYBOX_CONFIG_FEATURE_SYSLOG
    help
init is the first program run when the system boots.

也就是说,当用户需要自定义的时候,引入了BUSYBOX_CONFIG_xxx的配置项,但其默认值还是用的已经配置好的。此时要自定义的就是在这个基础上做修改。

最终用户的配置就体现在BUSYBOX_CONFIG_xxx的配置项上。 如上文所述,在选中了CONFIG_BUSYBOX_CUSTOM的情况下,BUSYBOX_SYM的值为CONFIG,则将CONFIG_BUSYBOX_CONFIG_xxx过滤出来,处理为busybox最终的配置项。

配置项文件的生成

搞清楚了如何集成之后,接下来的问题就是,这些BUSYBOX_DEFAULT_xxx 和 BUSYBOX_CONFIG_xxx 的配置文件,是怎么来的,如此多的配置项,肯定不可能时手工修改的,必然有自动化处理。

是的,这些BUSYBOX_CONFIG_xxx配置项,就是从busybox本身的配置项生成而来。而这些BUSYBOX_DEFAULT_xxx的默认配置值,其实就是从一份配置好的busybox.config文件生成而来。在busybox的包中,就提供了两个脚本 convert_defaults.pl 和 convert_menuconfig.pl,用来生成配置项和默认配置值

使软件包随配置项改变而重新编译

一般软件包在编译过一次之后,如果源码没有改动,则下次make无须重新编译。

但对于busybox这种包,源码未变,配置改变了的话,也是需要重新编译的。 现在的问题在于,用户修改配置项,是在openwrt的.config修改,根本不会改动到busybox这个目录下的文件。 那么busybox包就需要有一个方法,来监控配置项的变动。如果配置项变化,则需要重新编译。如何监控呢?从makefile中也可以找到答案

文件 openwrt/package/utils/busybox/Makefile

ifeq ($(DUMP),)
  STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell grep '^CONFIG_BUSYBOX_' $(TOPDIR)/.config | mkhash md5)
endif

此处设置了STAMP_CONFIGURED变量,这个变量的值,是将.config中所有CONFIG_BUSYBOX_滤出,再做md5得到的值。一旦这些配置项发生变化,则md5的值会改变,STAMP_CONFIGURED的值也会改变。编译包的时候,就能判断出需要重新编译。

具体的,STAMP_CONFIGURED值是在package.mk中使用。这里还有其他的类似变量,只要改变了,就说明需要重新执行对应的操作。如STAMP_CONFIGURED,STAMP_BUILT,STAMP_INSTALLED等。

这个配置项,也会在软件包的编译目录体现出来。如果没有对其赋值,则在编译目录下,可看到名字类似 .configured_yyy 的隐藏文件。

对其进行赋值之后,这个文件的形式会变成 .configured_yyy_622f380fff06dde988852308f044653b 这种形式,后面跟着的就是由配置项生产的md5值。

结语

分析清楚了busybox的套路之后,修改下 convert_defaults.pl 和 convert_menuconfig.pl ,就可以套用到其他软件包上了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 记一次nor flash固件烧录速度优化

    某个方案使用的是spinor作为存储介质,每次烧录新固件都耗时数分钟,为了提高效率,需要对其进行优化。

    zqb_all
  • spi-mem: 为SPI存储器生态带来一些一致性

    在本文中,我们将介绍关于spi-mem Linux内核框架的工作,该框架将允许在SPI NOR设备和常规SPI设备以及SPI NAND设备上复用SPI控制器驱动...

    zqb_all
  • busybox syslog介绍

    可通过设置/etc/syslog.conf具体配置不同log的处理规则,以下的简单配置,将log全部写到/var/log/messages和控制台

    zqb_all
  • Sharding-Jdbc源码探究-读写分离

    主从配置中主从的属性逗号理解,也好找到使用的地方,对props是在哪且如何使用的呢? 我找到了这个类:

    老梁
  • knative serving 组件分析

    knative 部署完成后可以在 knative-serving namespace 下看到创建出的组件:

    田飞雨
  • FPGA系统性学习笔记连载_Day10 【流水灯实验】

    本系列为FPGA系统性学习学员学习笔记整理分享,如有学习或者购买开发板意向,可加交流群联系群主。

    FPGA技术江湖
  • 一段代码看懂Promise

    程序员不务正业
  • ES6新特性

    由于ES6在一些低版本的浏览器上无法运行,需转成ES5之前的版本兼容,以下有几种方案可以自动转换

    jinghong
  • 何谓架构?

    在这个知识分享的爆炸时代,鉴于java生态的完整和繁荣,各种框架、中间件和工具包供我们使用。连新培训出来的人都知道ssm,微服务、集群、多线程、队列、高并发等技...

    孙玄@奈学教育
  • Golang NotesGo 语言环境安装

    Clive

扫码关注云+社区

领取腾讯云代金券