如果說Linux 系統鏡像是你想吃的一桌飯菜,那麼Yocto 就是一家餐廳,Poky 就是廚房,BitBake 就是廚師。那麼,如果我們想定制自己的Linux,我們應該學會怎麼用好BitBake,或者說把我們的意圖告訴BitBake。總而言之,如果你想定制Linux 系統的願望跟你想吃一桌好吃的飯菜一樣強烈的話(或者更強烈),你應該好好了解了解BitBake。
1. 認識BitBake
OE BitBake是一個軟件組建自動化工具程序,像所有的build工具一樣(比如make,ant,jam)控制如何去構建系統並且解決構建依賴。但是又區別於功能單一的工程管理工具(比如make),bitbake不是基於把依賴寫死了的makefile,而是收集和管理大量之間沒有依賴關係的描述文件(這裡我們稱為包的配方),然後自動按照正確的順序進行構建。oe代表OpenEmbedded,而openembedded是一些用來交叉編譯,安裝和打包的metadata(元數據)。
OpenEmbedded是一些腳本(shell和python腳本)和數據構成的自動構建系統。腳本實現構建過程,包括下載(fetch)、解包(unpack)、打補丁(patch)、配置(configure)、編譯(compile)、安裝(install)、打包(package)、staging、做安裝包(package_write_ipk )、構建文件系統等。
OE 編譯順序:
do_setscene
do_fetch
do_unpack
do_path
do_configure
do_qa_configure
do_compile
do_stage
do_install
do_package
do_populate_staging
do_package_write_deb
do_package_write
do_distribute_sources
do_qa_staging
do_build
do_rebuild
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
注意:do_compile 這些函數都是在OpenEmbedded 的classes 中定義的,而bitbake 中並沒有對這些進行定義。這說明,bitbake 只是OE 更底層的一個工具,也就是說,OE 是基於bitbake 架構來完成的。
數據主要提供兩個方面的信息:
- 特定軟件包的構建信息
怎樣獲取源代碼和補丁?怎樣構建,用Makefile還是Autotool?需要向目標編譯環境輸出哪些文件?需要安裝哪些文件?每個軟件包都需要描述文件。事實上,每個軟件包的不同版本都有一個描述文件。 - 軟件包之間的依賴關係
構建軟件包A需要先構建什麼主機平台工具,什麼目標平台工具?軟件包A在編譯時依賴哪些軟件包?軟件包A在運行時依賴哪些軟件包?一個目標應包含那些軟件包,這些依賴關係把幾百個軟件包聯繫在一起,構成了一個完整的系統。
基於bitbake,OE可以滿足以下所有要求:
- 解決交叉編譯
- 解決包之間的依賴關係
- 必須支持包的管理(tar,rpm,ipk)
- 必須支持將包作成鏡像
- 必須支持高度的可定制性,以滿足不同的機器,主機發行版和架構需求
- 編寫元數據必須是容易的,並且可重用性要好
OE 的主要功能是為各種工程項目的需要編譯源碼。不管是什麼工程,以下任務都是需要做的:
- 下載源碼包,還有其他的系統支持文件(比如初始化腳本)
- 解壓源碼包,然後打上需要的補丁
- 如果需要,對軟件包進行配置(比如運行configure 腳本)
- 編譯所有的東西
- 把編譯好的文件打成各種格式的包,然後準備安裝
其實這些並沒有什麼不尋常的,困難的是:
- 交叉編譯:交叉編譯是困難的,大部分軟件包根本不支持交叉編譯,OE 裡包含的都是支持交叉編譯的。
- 目標系統和主機是不同的:這意味著你不能編譯一個程序就直接運行它,因為它要運行在目標板上。很多軟件包在編譯的時候會編譯並且運行一些幫助或者測試程序,這在交叉編譯時會導致失敗。
- 工具鏈總是很難編譯的,交叉工具鏈更是如此。通常情況下,你可能會選擇去下載一個別人做好的,但是使用OE你就不需要如此。在OE裡整個工具鏈在編譯系統的時候都會被創建,OE
的這種方式或許在開始的時候會帶來一些困難和不便。但是如果你需要打上補丁或者對工具鏈做些調整就會很容易。
當然,除此之外,OE 還有很多的功能,其中包括:
- 同時支持glibc 和uclibc
- 只使用OE 一個工具你就可以為多種目標機器構建系統
- 自動編譯一切構建時和編譯時依賴的包
- 直接創建各種可以在目標機器上直接運行的鏡像(包括jffs2、ext2.gz、squashfs 等等)
- 支持各種打包格式
- 自動構建交叉工具鏈
- 支持構建“本地包”(本地包指為了完成編譯而給主機編譯的包,最終不會用到目標板上)
2. 文件系統裡的OpenEmbedded
OE環境中最重要的目錄有3個:
(1)放工具的bitbake目錄
(2)放元數據的目錄
(3)執行構建的build目錄
2.1 bitbake 目錄
這個目錄裡的是我們的廚師(或理解為烹飪工具)——bitbake,我們使用它,但通常不需要訪問、修改它。
2.2 元數據目錄
在poky 中元數據目錄是meta,Openmoko 中元數據目錄是openembedded。在元數據目錄中,有3個目錄裡是真正的元數據,它們是:classes、conf 和packages。
2.2.1 packages 目錄
所有的配方(recipes)文件(後綴為.bb)都放在package目錄,每個相對獨立的軟件包或構建任務在package目錄下都有自己的子目錄。在一個子目錄中可以有多個配方(recipes)文件,它們可能是同一個軟件包的不同版本,也可能描述了基於同一個軟件包的不同構建目標。
有的配方(recipes)簡單,有的配方(recipes)複雜。簡單的配方僅描述一個軟件包的構建,最複雜的是要求構建文件系統的配方,這個配方文件本身並不長,甚至還很短,但它通過依賴關係將幾百個甚至幾千個其它配方文件捲入了構建過程。packages目錄的images子目錄下就是這些要求構建文件系統的配方(recipes)。
2.2.2 classes 目錄
這個目錄放的是配方(recipes)的類文件(後綴為.bbclass)。類文件包含了一些bitbake 任務的定義,例如怎麼配置、怎麼安裝。配方文件繼承類文件,也就繼承了這些任務的定義。例如:我們如果增加一個使用autotool 的軟件包,只要在配方文件中繼承autotools.bbclass:
inherit autotools
bitbake就知道怎樣使用autotool工具配置、編譯、安裝了。所有的配方文件都自動繼承了base.bbclass。base.bbclass提供了大部分bitbake任務的默認實現。
一個配方文件可以繼承多個類文件。以後的文章會介紹bitbake的任務,屆時會更詳細地討論bitbake的繼承。目前,我們只要知道繼承類文件是一種構建過程的複用方式就可以了。
2.2.3 conf 目錄
conf 目錄包含編譯系統的配置文件(後綴為.conf)。bitbake 在啟動時會執行bitbake.conf,bitbake.conf 會裝載用戶提供的local.conf,然後根據用戶在local.conf 中定義的硬件平台(MACHINE)和發布目標(DISTRO)裝載machine 子目錄和distro 子目錄的配置文件。machine 子目錄裡是與硬件平台相關的配置文件,distro 子目錄裡是與發布目標相關的配置文件。配置文件負責設置bitbake 內部使用的環境變量,這些變量會影響整個構建過程。
2.3 build 目錄
build是我們烹飪嵌入式系統的地方(可以想像成餐館的大廚房),整個構建過程就是在build目錄的tmp子目錄完成的。build目錄的conf子目錄裡是用戶的配置文件local.conf。
tmp目錄有7個子目錄:cache、cross、rootfs、staging、work、deploy和stamps目錄。其中cache是bitbake內部使用的緩存目錄。cross是構建過程中產生的交叉編譯器(所謂交叉編譯器就是在主機平台運行,用於編譯目標平台代碼的編譯器)。rootfs是製作文件系統映像前臨時建立的根文件系統。我們的工作中通常不需要訪問這3個目錄,我們訪問比較多的是其它4個目錄:staging、work、deploy和stamps目錄。
2.3.1 staging 目錄
軟件包B在構建時可能依賴軟件包A提供的頭文件、庫文件,也可能要使用軟件包C生成的工具。staging目錄就是放這些輸出文件的地方。
我們必須在配方文件中用“DEPENDS”變量聲明構建時的依賴關係。bitbake就會在構建軟件包B前先構建軟件包A和軟件包C,並將軟件包B需要的頭文件、庫文件、和工具放在staging目錄。這樣,在構建軟件包時,就可以從staging目錄得到需要的頭文件、庫文件和工具。
2.3.2 work 目錄
所有軟件包的解包、打補丁、配置、編譯、安裝等工作都是在work目錄進行的。所以work目錄包含了整個嵌入式系統的完整源代碼。
work目錄下按照硬件平台、發行人、目標平台的不同又分了幾個目錄。所有軟件包都被放在對應的子目錄中,每個軟件包都有一個獨立的目錄。因為軟件包總是根據一個配方文件構建的,所以軟件包所在的目錄就是對應配方文件的工作目錄。在討論bitbake和配方文件時我們還會回來,更仔細地觀察配方文件的工作。
2.3.3 deploy 目錄
這是保存輸出成果的目錄。其中images 目錄保存構建成功後產生的文件系統映像、內核映像,ipk 目錄保存每個軟件包的安裝包。我們在修改、構建軟件包後,可以在目標平台手工安裝ipk 目錄下的對應安裝包,確認沒有問題後,再製作文件系統映像。
2.3.4 stamps 目錄
和work 目錄類似,stamp 目錄也按照硬件平台、發行人、目標平台的不同又分了幾個子目錄。軟件包在完成每個bitbake 任務後都會在對應子目錄裡touch 一個對應任務的時間戳,有時我們會手工刪除某個軟件包的時間戳,強制bitbake 重新構建這個軟件包。
2.3.5 sources 目錄
OE 環境的sources 目錄是一個儲藏間,用來放從網上下載的源代碼包。fetch 任務負責下載代碼,放到sources 目錄。
3. BitBake 命令
3.1 查看bitbake 命令
$ bitbake -h
Usage: bitbake [options] [recipename/target recipe:do_task ...]
Executes the specified task (default is 'build') for a given set of target recipes (.bb files).
It is assumed there is a conf/bblayers.conf available in cwd or in BBPATH which
will provide the layer, BBFILES and other configuration information.
Options:
-h,
-b BUILDFILE,
Execute tasks from a specific .bb recipe directly.
WARNING: Does not handle any dependencies from other
recipes.
-k,
target that failed and anything depending on it cannot
be built, as much as possible will be built before
stopping.
-a,
providers where possible.
-f,
any existing stamp file).
-c CMD,
available depend on the metadata. Some examples might
be 'compile' or 'populate_sysroot' or 'listtasks' may
give a list of the tasks available.
-C INVALIDATE_STAMP,
Invalidate the stamp for the specified task such as
'compile' and then run the default task for the
specified target(s).
-r PREFILE,
Read the specified file before bitbake.conf.
-R POSTFILE,
Read the specified file after bitbake.conf.
-v,
-D,
than once.
-n,
-S SIGNATURE_HANDLER,
Dump out the signature construction information, with
no task execution. The SIGNATURE_HANDLER parameter is
passed to the handler. Two common values are none and
printdiff but the handler may define more/less. none
means only dump the signature, printdiff means compare
the dumped signature with the cached one.
-p,
-s,
-e,
with information about where variables were
set/changed.
-g,
targets in the dot syntax.
-I EXTRA_ASSUME_PROVIDED,
Assume these dependencies don't exist and are already
provided (equivalent to ASSUME_PROVIDED). Useful to
make dependency graphs more appealing
-l DEBUG_DOMAINS,
Show debug logging for the specified logging domains
-P,
-u UI,
ncurses - default knotty).
-t SERVERTYPE,
Choose which server type to use (process or xmlrpc -
default process).
connecting to a remote server.
floating revisions have changed or not.
(cooker) process.
-B BIND,
and everything needed, built.
Connect to the specified server.
-m,
-w WRITEEVENTLOG,
Writes the event log of the build to a bitbake event
json file. Use '' (empty string) to assign the name
automatically.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
3.2 bitbake 常用命令
BitBake 參數 | 描述 | 示例 | 備註 |
---|
<target> | 直接編譯/執行一個recipe | bitbake core-image-minimal | |
-c <task> <target> | 執行某個recipe 的某個任務 | bitbake -c build glibc | 示例表示執行glibc的do_build任務
<task> 表示要執行的任務: fetch表示從recipe中定義的地址拉取軟件到本地 compile表示重新編譯鏡像或軟件包 deploy表示部署鏡像或軟件包到目標rootfs內 cleanall表示清空整個構建目錄 |
-c listtasks <target> | 顯示某個recipe 可執行的任務 | bitbake -c listtasks glibc | 如果你不確定target 支持哪些任務,就可以用listtasks 來查詢 |
-b <xx.bb> | 用BitBake直接執行這個.bb文件 | bitbake -b rtl8188eu-driver_0.1.bb | 單獨編譯rtl8188eu-driver 任務 |
-k | 有錯誤發生時也繼續構建 | | |
-e <target> | 顯示當前的執行環境 | 查找包的原路徑:
bitbake -e hello | grep ^SRC_URI 查找包的安裝路徑:
bitbake -e hello | grep ^S= | |
-s | 顯示所有可以bitbake 的包 | bitbake -s | grep hello | 例如如果自己在一個Layer下面安裝了一個hello.bb,可以查看hello 這個package 能否被bitbake |
-v | 顯示執行過程 | | |
-vDDDD | 打印一些調試信息(v 後面可以加多個D) | bitbake -vDDDD -c build glibc | |
-g <target> | 顯示一個包在BitBake 時與其他包的依賴關係,生成依賴圖 | bitbake -g glibc | 在當前目錄生成一些文件: task-depends.dot(任務之間的依賴關係) package-depends.dot(運行時的目標依賴) pn-depends.dot(構建時的依賴) pn-buildlist(包含需要構建的任務列表)
*.dot文件可以通過xdot工具打開 |
3.3 使用舉例
單獨編譯kernel、模塊、設備樹
MYS-6ULX-IOT 開發闆對應的kernel 是linux-mys6ulx:
$ bitbake -c menuconfig -f -v linux-mys6ulx
$ bitbake -c compile -f -v linux-mys6ulx
$ bitbake -c compile_kernelmodules -f -v linux-mys6ulx
$ bitbake -c deploy -f -v linux-mys6ulx
也有一些資料用virtual/kernel 來指定kernel,命令變成這樣了:
$ bitbake -c menuconfig virtual/kernel
$ bitbake -c compile -f -v virtual/kernel
$ bitbake -c compile_kernelmodules -f -v virtual/kernel
$ bitbake -c deploy -f -v virtual/kernel
通過sources/meta-myir-imx6ulx/conf/machine/include/mys6ulx-base.inc和
sources/meta-myir-imx6ulx/conf/distro/include/myir-imx-preferred-evn.inc文件,我們可以看出一些端倪:
MACHINE_ARCH_FILTER = "virtual/kernel"
IMX_DEFAULT_KERNEL = "linux-mys6ulx"
IMX_DEFAULT_KERNEL_mx6ul = "linux-mys6ulx"
IMX_DEFAULT_KERNEL_mx6ull = "linux-mys6ulx"
PREFERRED_PROVIDER_virtual/kernel ??= "${IMX_DEFAULT_KERNEL}"
單獨編譯u-boot
$ bitbake -c compile -f -v u-boot-mys6ulx
$ bitbake -c deploy -f -v u-boot-mys6ulx
編譯文件系統
$ bitbake core-image-minimal
$ bitbake core-image-base
$ bitbake fsl-image-gui
$ bitbake fsl-image-qt5
$ bitbake fsl-image-multimedia
清除編譯結果
$ bitbake -c clean -v linux-mys6ulx
清除還包括clean、cleanall、cleanstate
參考
http://blog.sina.com.cn/s/blog_7880d3350102wvio.html
https://www.kancloud.cn/digest/yocto/138623
Yocto Project上的BitBake用戶手冊:
https://www.yoctoproject.org/docs/1.6/bitbake-user-manual/bitbake-user-manual.html
資料來源: https://blog.csdn.net/lu_embedded/article/details/80634368