• 浅析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 ,就可以套用到其他软件包上了。

  • 相关阅读:
    springboot中,使用redisTemplate操作redis
    【转】手把手教你 Mockito 的使用
    【转】Java JUnit 单元测试小结
    【转】如何使用MAT分析内存泄漏
    free命令中的buffer和cached的比较(转)
    【转】java comparator 升序、降序、倒序从源码角度理解
    打印日志的10个建议
    hadoop控制map个数(转)
    Java工具库:
    Scala工具库
  • 原文地址:https://www.cnblogs.com/zqb-all/p/10263335.html
Copyright © 2020-2023  润新知