zoukankan      html  css  js  c++  java
  • 浅析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 ,就可以套用到其他软件包上了。

  • 相关阅读:
    【Lintcode】112.Remove Duplicates from Sorted List
    【Lintcode】087.Remove Node in Binary Search Tree
    【Lintcode】011.Search Range in Binary Search Tree
    【Lintcode】095.Validate Binary Search Tree
    【Lintcode】069.Binary Tree Level Order Traversal
    【Lintcode】088.Lowest Common Ancestor
    【Lintcode】094.Binary Tree Maximum Path Sum
    【算法总结】二叉树
    库(静态库和动态库)
    从尾到头打印链表
  • 原文地址:https://www.cnblogs.com/zqb-all/p/10263335.html
Copyright © 2011-2022 走看看