openwrt 中busybox 的配置

近日添加了一個包到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 ,就可以套用到其他軟件包上了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章