淺析busybox如何集成到openwrt

背景

近日添加了一個包到openwrt中,在此過程當中又對openwrt多了一些認識git

這個包自己自帶了kconfig,可直接在這個包裏面執行make menuconfig進行配置,而後執行makegithub

但要集成到openwrt中,就須要把這些配置項都集成到openwrt的配置中。shell

面對這種狀況,固然是要找個現成的例子作參考,首先想到的就是busybox。bash

如下以busybox爲例進行說明,源碼摘自github https://github.com/openwrt/openwrt/tree/master/package/utils/busyboxless

如何集成配置項

busybox自己也自帶了配置項,但實際上咱們卻能夠在openwrt的總的配置項中對其進行配置,而無需進入busybox目錄單獨對其作配置。佈局

經過查看busybox包的makefile,能夠看到,這個集成是這麼作的。
對於busybox原生的配置項不作改動,而是針對每一個配置項都另外生成一個對應的配置項,用於集成到openwrt中。
這些配置項在 openwrt/package/utils/busybox/config目錄中。並經過 openwrt/package/utils/busybox/Config.in 文件鏈接到openwrt配置項。下面結合代碼分析下。ui

從Makefile中能夠看到,對於openwrt來講,busybox包的配置,就來源於Config.inthis

文件 openwrt/package/utils/busybox/Makefile

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

先來看下openwrt/package/utils/busybox/Config.in這個總的配置文件。code

文件 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原生配置項的配置文件,以容許用戶徹底自定義這些配置。ip

先看不自定義配置的狀況。此時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 ,就能夠套用到其餘軟件包上了。

相關文章
相關標籤/搜索