天天看點

Buildroot建構指南--快速上手與實用技巧【轉】

Buildroot官方全英文使用手冊的連結是​​https://buildroot.org/downloads/manual/manual.html​​,需要知道每一個細節的朋友,可以仔細查閱,這篇文章隻是我自己從中提煉出來的一下快速上手的技巧。

如何在現有項目加入自己的APP

Buildroot從零開始建構的過程還是很複雜的,以後的文章會一步步介紹。我們先來看看如何在現有項目中加入一個自己的應用的建構方法,快速上手。實際上,快速添加應用包的方法,在官方網站也有一份英文文檔:​​https://buildroot.org/downloads/manual/manual.html#adding-packages​​  詳細的原理可以參考這篇文檔。

這裡以加入自己的demo_app應用為例,在mini2440_defconfig的項目下,加入demo_app的package,将demo_app的應用源代碼編譯生成到rootfs根檔案系統中。建構方法如下:

1.      在buildroot/package/ 下執行 mkdir demo_app  ,建立demo_app 的檔案夾

Buildroot建構指南--快速上手與實用技巧【轉】

Figure1 在package/ 目錄下建立demo_app/

2.      在demo_app 中touch Config.in , touch demo_app.mk 建立這兩個檔案,注意,檔案名很關鍵,demo_app.mk要小寫,而且不能亂取其它名字,因為Buildroot架構有一套根據命名,展開app package的規則,是以buildroot裡面建構項目,一定要遵守文章中的命名規則,否則會有各種報錯。

Buildroot建構指南--快速上手與實用技巧【轉】

Figure2  添加Config.in 與 demo_app.mk 檔案

3.      在package/Config.in 中加入 source "package/demo_app/Config.in" ,以便将demo_app 的配置檔案包含到Buildroot的package中來管理。

Buildroot建構指南--快速上手與實用技巧【轉】

Figure3  在packahe/Config.in 中加入demo_app的Config.in

4.      在package/demo_app/Config.in 這個類似Kconfig的配置檔案中,按照命名格式和​​Linux​​ Kernel 的 Kconfig檔案規範,加入自己的配置變量,參考代碼如下:

1. config BR2_PACKAGE_DEMO_APP
2. bool"demo app"
3. help
4. demo app to show      

這段配置中,命名規則也同樣重要,BR2_PACKAGE_DEMO_APP是demo_app 可被Buildroot識别編譯成package的配置變量。Package應用一定要以BR2_PACKAGE_作為開頭,以DEMO_APP即demo_app的大寫來填充這個變量名,這樣才能被Buildroot命名架構識别、展開,才能通過make menuconfig來配置。

bool是變量的類型,即隻要true(編譯選中,false(編譯未選中),兩種情況,和Kconfig的規則是一樣的,後面的字元串和help都是在make menuconfig時的提示文本。

實際上,在Config.in中,可以參考linux Kernel的Kconfig檔案,根據文法規範,加入自己的配置邏輯和其它可配置的變量(比如app的下載下傳位址連結),在此就不詳細說了,大家可以參考其它的package/的Config.in檔案的寫法,這裡隻說重點,就是BR2_PACKAGE_DEMO_APP這個變量一定要有,一定要被選上才能編譯。

5.      在demo_app.mk中,按照Makefile檔案的格式和文法規範,編寫demo_app的上層建構規則,demo_app.mk的參考代碼如下:

1. ################################################################################
2. #
3. # demo app
4. #
5. ################################################################################
6. DEMO_APP_VERSION = master
7. DEMO_APP_SITE_METHOD = git
8. DEMO_APP_SITE = /mnt/sdb/git_repo/demo_app
9. DEMO_APP_SOURCE = demo_app-$(DEMO_APP_VERSION).tar.gz
10. DEMO_APP_ALWAYS_BUILD = YES
11. DEMO_APP_INSTALL_STAGING = YES
12. DEMO_APP_CFLAGS =
13. DEMO_APP_LDFLAGS =
14. OUT_BIN = demo_app
15. DEMO_APP_MAKE_FLAGS += \
16. CROSS_COMPILE="$(CCACHE) $(TARGET_CROSS)" \
17. CC=$(TARGET_CC)      \
18. OUT_BIN=$(OUT_BIN)  \
19. AR=$(TARGET_AR)      \
20. STRIP=$(TARGET_STRIP) \
21. CFLAGS=$(DEMO_APP_CFLAGS) \
22. LDFLAGS=$(DEMO_APP_LDFLAGS) \
23. STAGING_DIR=$(STAGING_DIR)  \
24. TARGET_DIR=$(TARGET_DIR)
25. 
26. define DEMO_APP_BUILD_CMDS
27. $(MAKE) clean  -C $(@D)
28. $(MAKE) $(DEMO_APP_MAKE_FLAGS)  -C $(@D)
29. endef
30. 
31. define DEMO_APP_INSTALL_TARGET_CMDS
32. $(INSTALL) -m 0755 -D $(@D)/$(OUT_BIN)  $(TARGET_DIR)/usr/bin
33. endef
34. 
35. $(eval $(generic-package))      

注意,demo_app.mk并不能實際代替demo_app源代碼的Makefile檔案,它隻是一個上層的make檔案,告訴Buildroot,應該到哪個地方拿源代碼,應該如何解壓源代碼,應該給源代碼中的Makefile中的變量傳遞哪些編譯參數,編譯出來的庫和bin檔案,應該安裝到rootfs的哪個路徑下。具體demo_app源代碼是如何一步一步編譯的,還得靠demo_app源代碼本身的Makefile去做。

這段makefile代碼大概有什麼規範呢:

a)     所有的變量都已DEMO_APP_ 開頭,這樣Buildroot才能夠通過命名架構去解析

b)     _VERSION結尾的變量,是下載下傳demo_app源代碼的版本号, _SITE_METHOD結尾的變量是demo_app變量的下載下傳方法,_SITE結尾的變量是demo_app的下載下傳位址,其它的變量是幹嘛用的,可以慢慢查閱官方手冊。

c)      所有define 并以_CMDS結尾的代碼塊,類似函數的東西,實際上是建構過程中會被Buildroot架構執行的指令,這些指令到底有哪些,具體也得讀手冊。當然這些類似函數,開頭也得是DEMO_APP_, Buildroot中命名規則很重要,重要的話說三遍。

d)     _BUILD_CMDS結尾的函數,是建構過程函數,一般是給demo_app源代碼傳遞編譯和連結選項,調用源代碼的Makefile執行編譯。

e)     INSTALL_TARGET_CMDS結尾的函數,就是demo_app編譯完之後,自動安裝的執行,一般是讓Buildroot把編譯出來庫和bin檔案安裝到指定的目錄。

f)      $(eval$(generic-package)) 最核心的就是這個東西了,一定不能夠漏了,不然demo_app是編譯不出來的,這個函數就是把整個demo_app.mk建構腳本,通過Buildroot架構的方式,展開到Buildroot/目錄下的Makfile中,生成demo_app的建構目标(建構目标是什麼,還記得Makefile中的定義嗎?)。

g)     實際上,這些建構命名架構還有$(eval $(generic-package))這個黑魔法,都在package/pkg-generic.mk 這個檔案中,generic-package是這個檔案最後的調用的函數生成的,其它 _BUILD_CMDS,INSTALL_TARGET_CMDS這些函數如何被Buildroot架構嵌入的, 之前那些變量是如何被調用的,在package/pkg-generic.mk中都能找到,但是還是要一定的Makefile功底才能讀懂這個的,以後再解釋package/pkg-generic.mk的架構原理。

講了這麼多條規範,那麼這段makefile代碼大概是什麼意思呢?

這段代碼描述的流程是, 通過​​Git​​​  clone的方法從/mnt/sdb/git_repo/demo_app這個目錄下的​​git​​倉庫中拿到demo_app的源代碼-->傳遞編譯參數,并且編譯demo_app(DEMO_APP_BUILD_CMDS函數做的事情)-->把編譯出來的bin檔案安裝到$(TARGET_DIR)/usr/bin目錄下(DEMO_APP_INSTALL_TARGET_CMDS函數做的事情)。

為什麼我們自己不用寫從git倉庫下載下傳demo_app源代碼的函數呢,實際上是Buildroot幫我們寫好了,在package/ pkg-download.mk 檔案裡面,是以我們隻有通過DEMO_APP_SITE_METHOD和DEMO_APP_SITE設定下載下傳的方法和位址就可以。至于為什麼DEMO_APP_VERSION是master,了解git的朋友應該看得明白,就是git clone之後會checkout到master版本,其實也就是master分支最新的版本啦,當然也可以換成自己的版本号,前提是該版本号存在,能夠用git checkout 切換過去。

這段代碼的執行前提是要在Linux上搭建自己的git倉庫,維護自己的demo_app源代碼,在用Buildroot前,git倉庫是現成的。

但是不熟悉git 的朋友怎麼辦呢?其實還有其它方法,demo_app.mk的代碼稍做修改:

Buildroot建構指南--快速上手與實用技巧【轉】

Figure4  采用file方法下載下傳源代碼

主要,DEMO_APP_SITE_METHOD改成了file,這樣就不用建構git參考,可以用file,也就是直接cp的方法,把源代碼拷貝到buildroot中來。但是buildroot到哪裡去cp源代碼呢,實際上,這裡不是DEMO_APP_SITE = /mnt/sdb/git_repo/demo_app這個位址,這個地方被我注釋掉了。

在buildroot/下 makemenuconfig --> Build options -->Mirrors and Download locations 可以看到以下的畫面:

Buildroot建構指南--快速上手與實用技巧【轉】

Figure5  設定file方法cp檔案的路徑

隻有按照上面的格式,也就是file:// + 你的檔案絕對路徑的位址的格式配置這個選項,然後儲存,就OK,之後Buildroot就知道去該路徑下找源代碼包了。

另外記得,一定要把demo_app的源代碼壓縮包儲存到該路徑下,并且名字一定要和DEMO_APP_SOURCE變量的名字一樣哦!

Buildroot建構指南--快速上手與實用技巧【轉】

Figure6  demo_app 源代碼的存放路徑

6.      demo_app的源代碼

demo_app就是一個hello world 程式參考的makefile和源代碼如下:

其中Makefie會被demo_app.mk中的DEMO_APP_BUILD_CMDS函數調用,Makefie中的變量參數的值都可以通過DEMO_APP_BUILD_CMD傳入。

Buildroot建構指南--快速上手與實用技巧【轉】

Figure7 demo_app 的Makefie

Buildroot建構指南--快速上手與實用技巧【轉】

Figure8  demo_app.c 源代碼

7.      建構方法

a). make mini2440_defconfig  --> makemenuconfig --> Target packages下選中demo app --> make demo_app

Buildroot建構指南--快速上手與實用技巧【轉】

Figure9  menuconfig中選中 demo app,

make demo_app這個指令,實際上是隻是編譯demo_app以及demo_app依賴鍊上的package, 當然,toolchain會被所有package依賴,是以buildroot會先編譯toolchain。

編譯完成後,會發現buildroot/output/build/目标下的demo_app-master目錄,即demo_app編譯後現場,以及在buildroot/output/target/usr/bin/目錄下,安裝好的編譯出來的demo_appbin檔案。并且确實是ARM交叉工具鍊編譯出來的。

Buildroot建構指南--快速上手與實用技巧【轉】

Figure10  demo_app 源代碼編譯現場路徑

Buildroot建構指南--快速上手與實用技巧【轉】

Figure11  安裝好的demo_app  bin檔案

至此,在Buildroot中添加app package的過程就完成了。

如何編譯基于現有項目的最小系統

Buildroot 一次make all要把整個系統編譯出來,真麻煩,我隻想要一個可以boot起來的最小系統,不需要什麼其它package,它有什麼快捷方式可以辦到嗎?這個當然問buildroot,我們可以這麼做。

make help 看看buildroot怎麼說

Buildroot建構指南--快速上手與實用技巧【轉】

Figure12 make help 之後的buildroot系統提示

以下是buildroot的help指令提示,其中有一項是

make  allnopackageconfig

在make xxx_defconfig 之後,執行make allnopackageconfig,那麼再make all就可以隻編toolchain,boot,kernel,busybox,rootfs這個幾個能構成系統啟動的最小系統的子產品。

當然,在make mini2440_defconfig時,由于mini2440的toolchain是toolchain-buildroot,即buildroot從零開始制作工具鍊,而不是toolchain-external,即buildroot使用已經制作好的工具鍊,這樣的話,如果toolchain還沒有在前一次生成,則make allnopackageconfig 再make all之後編譯過程會報錯,因為制作零制作toolchain需要編譯某些package作為原材料,而這些package被make allnopackageconfig去掉了。

已經制作好工具鍊,或者采用toolchain-external模式的情況下,make allnopackageconfig 編譯最小系統是沒用問題的。

Buildroot實用技巧與指令

最後看看buildroot有哪些實用技巧:

make help

-之前示範過了,列印出幫助菜單

make show-targets

-         顯示出本次配置所要編譯所有的目标,這些目标可以單獨作為子產品,用 make <pkg-target> 指令進行單獨編譯。從這條指令的顯示結果來看,mini2440_defconfig需要編譯uclibc(微型C庫),busybox等目标,當然demo_app也是一個編譯目标,是我在menocunfig時候加進去的,是以可以用make demo_app來編譯。

Buildroot建構指南--快速上手與實用技巧【轉】

Figure13  make show-targets 的顯示結果

make <pkg-target>

-         單獨編譯某個pkg子產品以及其依賴的子產品,比如make demo_app

make pkg-rebuild

-         重新編譯pkg

make  pkg-extract

-         隻下載下傳解壓pkg,不編譯,pkg解壓後放在 output/build/目錄對應的pkg-dir目錄下

make pkg-source

-         隻下載下傳某pkg,然後不做任何事情

其它還有很多快捷指令,在package/pkg-generic.mk中都能找到,這些快捷指令實際是是由pkg-指令這種命名架構合成的,更詳細的内容請參考手冊和package/pkg-generic.mk。

Buildroot建構指南--快速上手與實用技巧【轉】