Building Embeded Linux Systems (2) Building SDK with Buildroot

Building Embeded Linux Systems (2) Building SDK with Buildroot

基於之前文章製作的toolchain,本文使用buildroot搭建一個可用的sdk。原材料有:buildroot-2018.5,上文中製作的外部arm-gcc toolchain,可用的linux kernel源碼(linux-3.10),uboot源碼。
buildroot是一個用來搭建sdk的極好的開源工具。它功能很多,並且有詳細的文檔。本文只用到了一小部分功能,並只對我自己用到部分進行記錄和分享。

br2-external

buildroot提供了br2-external功能來添加外部定製的工程目錄。外部的目錄叫做external-tree。詳細的手冊地址是:
https://buildroot.org/downloads/manual/manual.html#br2-external-converting chapter 9。

建立工作路徑

sdk根目錄如圖下圖,其中dl是下載的源碼包所在目錄,是運行start.sh後生成的buildroot的一個目錄。buildroot-2018.05是buildroot源碼目錄,out是編譯工作目錄,platform是external-tree,toolchain是外部toolchain目錄。
在這裏插入圖片描述
platform是根據文檔中推薦的外部目錄結構建立的目錄層次。詳細見手冊
在這裏插入圖片描述

工作過程

在start.sh腳本中執行

make -C ${BUILD_ROOT_DIR} O=${OUT_DIR}  BR2_EXTERNAL=${PLATFORM_DIR} arm2416_defconfig

O是制定編譯工作目錄,BR2_EXETERNAL制定外部目錄。執行時會自動外部目錄configs下的arm2416_defconfig默認配置文件。在輸入BR2_EXTERNAL參數時 有
在這裏插入圖片描述
support/scripts/br2-external查找platform目錄下的external.desc 文件讀入name和desc
在這裏插入圖片描述
在out目錄下生成**.br-external.mk** 包含外部定製信息的幾個變量。BR2_EXTERNAL_MKS是外部的external.mk文件,作爲外部makefile的入口。還有是BR2_EXTERNAL_arm2416_PATH和BR2_EXTERNAL_arm2416_DESC,
下圖中會根據這兩個值生成kconfig需要包含的文件,這個將作爲外部kconfig的入口,它會source外部目錄下的Config.in 文件。
在這裏插入圖片描述
external.mk是這一條指令,還可以其他需要的。
在這裏插入圖片描述
外部Config.in的內容作爲一個例子可以是
在這裏插入圖片描述

其他

在platform需要建立local.mk,它包含一些本地定製化的makefile指令,比如需要使用本地的kernel和uboot就需要設置
在這裏插入圖片描述
設置這四個變量指示uboot和kernel的源碼都從本地制定路徑獲取。
在packages中建立了audio_sample例子package,這個屬於自己的package。audio_sample的audio_sample.mk文件和Config.in如下
在這裏插入圖片描述
在這裏插入圖片描述
執行start.sh後,進入out目錄執行make menuconfig,就可以修改配置,此時可以看到會生成如下external options
在這裏插入圖片描述
進入external options有
在這裏插入圖片描述
make menuconfig中可以修改的重要配置都有:
target options
build options :配置保存defconfig的路徑,配置dl下載源碼的路徑,host主機工具的路徑,外部local.mk的路徑
toolchain:配置外部toolchain的路徑,交叉編譯器的前綴,外部gcc的版本,kernel頭文件的版本,外部使用的C庫類型
kernel : 可以配置外部默認配置的路徑
target packages: 可以配置busybox使用的外部默認配置文件和其他需要的內部package
filesystem images: 可以配置使用的文件系統類型

buildroot 執行過程

buildroot將所有需要的mk腳本都include到頂層makefile中,它的所有主要功能都在頂層makefile中執行。
主要腳本:
support/kconfig: kconfig 解釋器目錄
support/scripts/br2-external: 生成external配置信息的shell腳本
support/misc/util.mk: 提供一些簡單的makefile函數,如去掉兩端空白,大小寫轉換等
boot/common.mk 是處理uboot等啓動相關package的makefile文件
linux/linux.mk是處理kernerl package的makefile文件。
fs/comon.mk: 構造rootfs的mk腳本,會包含fs//.mk,根據不同的rootfs類型配置,制定的腳本會執行。
system/system.mk:提供創建target rootfs目錄的makefile函數
package/Makefile.in: 處理不同類型package的頂層makefile會包含下面的
package/pkg-*.mk: 相應類型包的處理函數文件
pkg-utils.mk 提供pkgdir和pkgname函數

pkg-generic.mk

通用類型包是其他類型包的實現基礎。它爲目標板target package和主機host package提供編譯架構,通過pkg-generic.mk, 我們可以使用buildroot提供的軟件包構造目標板程序,也可以構造運行在host上的工具程序。
在這裏插入圖片描述
內部調用的inner-generic-package函數。它的依賴關係圖如下:
在這裏插入圖片描述
該依賴關係圖可以基本描述該函數的執行過程,其他細節需要到源碼中充實,尤其是可以在各個過程中間添加HOOK。
注意事項:
在make package-reconfigure 和 make package-rebuild都會有刪除.stamp_rsync的動作。也就是兩個指令都會進行源碼同步。因爲buildroot 中使用rsync -au u的作用是或略比原始文件新的修改文件。所以源碼同步動作在執行兩個指令時對於在build目錄下的修改都不會被覆蓋。所以這時如果希望恢復到source源碼的話,需要先make package-dirclean, 然後再make package.

目標文件系統目錄的構建

在使用pkg-generic時有幾個重要的變量。
$(2)_ADD_SKELETON_DEPENDENCY 設爲YES,是在編譯這個package時要先構造出目標文件系統的目錄結構。

ifeq ($(4),target)
ifeq ($$($(2)_ADD_SKELETON_DEPENDENCY),YES)
$(2)_DEPENDENCIES += skeleton
endif
ifeq ($$($(2)_ADD_TOOLCHAIN_DEPENDENCY),YES)
$(2)_DEPENDENCIES += toolchain
endif
endif

構造目標文件系統目錄時依賴skeleton,在package目錄下有skeleton目錄,還有skeleton-init-common和skeleton-init-sysv,在skeleton包中會添加skeleton-init-sysv的依賴,而skeleton-init-sysv依賴skeleton-init-common。
在pkg-virtual.mk中,這裏設置了skeleton對sysv的依賴。

ifeq ($(4),target)
$(2)_DEPENDENCIES += $$(call qstrip,$$(BR2_PACKAGE_PROVIDES_$(2)))

sysv目錄下config.in

config BR2_PACKAGE_SKELETON_INIT_SYSV
	bool
	select BR2_PACKAGE_HAS_SKELETON
	select BR2_PACKAGE_SKELETON_INIT_COMMON

config BR2_PACKAGE_PROVIDES_SKELETON
	default "skeleton-init-sysv" if BR2_PACKAGE_SKELETON_INIT_SYSV

sysv下.mk文件

SKELETON_INIT_SYSV_ADD_TOOLCHAIN_DEPENDENCY = NO
SKELETON_INIT_SYSV_ADD_SKELETON_DEPENDENCY = NO

SKELETON_INIT_SYSV_DEPENDENCIES = skeleton-init-common

SKELETON_INIT_SYSV_PROVIDES = skeleton

define SKELETON_INIT_SYSV_INSTALL_TARGET_CMDS
	$(call SYSTEM_RSYNC,$(SKELETON_INIT_SYSV_PKGDIR)/skeleton,$(TARGET_DIR))
endef

$(eval $(generic-package))

根目錄system目錄有構造目標文件系統相關的文件,其中skeleton是文件系統根目錄基本框架。其中system.mk 提供了構建目標文件系統相關的makefile函數。
skeleton-init-common包構建基本目錄層次,skeleton-init-sysv包添加sysv啓動相關的文件。

toolchain 依賴

在generic-package中toolchain依賴默認是開啓的,就是說所有的編譯對象都會依賴toolchain。 buildroot中的toolchain有兩種選擇內部toolchain和外部toolchain。
先以製作好的外部toolchain爲例。

$(2)_ADD_TOOLCHAIN_DEPENDENCY	?= YES

在toolchain/toolchain/toolchain.mk 中處理toolchain編譯target。 根據配置會依賴外部toolchain-external

ifeq ($(BR2_TOOLCHAIN_BUILDROOT),y)
TOOLCHAIN_DEPENDENCIES += toolchain-buildroot
else ifeq ($(BR2_TOOLCHAIN_EXTERNAL),y)
TOOLCHAIN_DEPENDENCIES += toolchain-external
endif
.......
$(eval $(virtual-package))

在toolchain/toolchain-external/pkg-toolchain-external.mk處理toolchain-external編譯target,在編譯toolchain-external的過程中會封裝toolchain,設置編譯器鏈接,拷貝toolchain sysroot, 編譯中間目錄staging是一個鏈接指向sysroot。

附上 bootlin buildroot trainning的鏈接,非常詳細。

重新構建rootfs快捷指令

在$(BR2_EXTERNAL)中添加兩條指令,rr和rp 用來重新構建rootfs.

rr:
	find $(BASE_DIR)/build/ -name "\.stamp_target_installed" -type f -print | xargs rm -f
	rm -rf $(BASE_DIR)/target
	$(MAKE) -C $(BASE_DIR)
	
rp:	
	find $(BASE_DIR)/build/ -name "\.stamp*" -type f -print | xargs rm -f
	rm -rf $(BASE_DIR)/target
	$(MAKE) -C $(BASE_DIR)

未完待續

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