如果你發現bug、不清楚的章節、打印錯誤或其他建議,請郵件告知我,我的郵箱是 `sunnogo@gmail.com `。
注意:由於task 和recipe 是BitBake 的基礎概念。 個人覺得翻譯成任務和配方不免有誤解之處,因此文中基本不對這兩個詞做翻譯。 類似的還有configure。
序言 1.1 關於本教程 如果你閱讀本教程,說明你已經知道BitBake 是一種類似make 的構建工具,主要用於OpenEmbedded 和Yocto 工程構建Linux 發行版本。 你可能也已經意識到BitBake 的學習曲線有點陡,本文可讓這個曲線變平緩一些。
本文不會告訴你BitBake 的一切,但是會嘗試解釋使用BitBake 時用到的一些基本功能。 理解這些基礎可幫助你開始寫自己的BitBake recipe。
1.2 本教程的目標 本教程展示如何創建一個最小工程,並一步步擴展,說明BitBake 如何運作。
1.3 致謝 感謝 Tritech 給我時間準備本文檔。 同時感謝大家在 問題跟踪站點 報告的問題與打印錯誤。
1.4 反饋 如果你發現bug、不清楚的章節、打印錯誤或其他建議,請使用issue tracker https://bitbucket.org/a4z/bitbakeguide/issues,不需要註冊。 同時也可以使用本文底部的Disqus評論功能。
BitBake 2.1 什麼是BitBake 以下內容有助於理解BitBake:
基本上,BitBake是一個Python程序,它由用戶創建的配置驅動,可以為用戶指定的目標執行用戶創建的任務,即所謂的配方(recipes)。
2.1.1 Config、tasks 與recipes 通過一種BitBake 領域特定語言寫Config、tasks 與recipes,這種語言包含變量與可執行的shell、python 代碼。 所以理論上,BitBake 可以執行代碼,你也可以用BitBake 做除構建軟件之外的事情,但是並不推薦這麼做。
BitBake 是一種構建軟件的工具,因此有一些特殊的功能,比如可以定義依賴關係。 BitBake 可以解決依賴關係,並將其任務以正確順序運行。 此外,構建軟件包通常包含相同或相似的任務。 比如常見的任務:下載源代碼包,解壓源代碼,跑configure,跑make,或簡單的輸出log。 Bitbake 提供一種機制,可通過一種可配置的方式,抽象、封裝和重用這個功能。
配置BitBake BitBake可以從這裡下載: https://github.com/openembedded/bitbake。 選擇一個版本的分支,並下載 zip。 解壓zip包,可找到一個bitbake-$version目錄。
注意:本文使用的Bitbake版本是bitbake-1.22,因此適合本教程的bitbake版本應該大於或等於1.22。 注意:譯者使用bitbake-1.27.0,因此文中樣例為1.27.0版本bitbake樣例。 提示:如果使用Yocto,則不需要安裝BitBake,Yocto源代碼本身捆綁了BitBake。 Yocto要求你source一個腳本,這個腳本和我們這裡做的一樣,安裝BitBake到我們的環境中。
3.1 安裝BitBake 安裝過程很簡單:
添加bitbake-$version/bin 目錄到PATH 添加bitbake-$version/lib 目錄到PYTHONPATH 即執行:
1 2 export PATH =/path/to/bbtutor/bitbake/bin:$PATH export PYTHONPATH =/path/to/bbtutor/bitbake/lib:$PYTHONPATH
這基本和yocto init 腳本一致。 yocto init 腳本同時也創建build 目錄,我們將在一會兒創建。
首先檢測是不是一切正常、bitbake 是否安裝成功。 通過執行以下bitbake 命令:
運行結果應該類似:
1 BitBake Build Tool Core version 1.27.0
3.2 BitBake 文檔 最實際的版本帶有源代碼。
在終端中,cd 到bitbake-$version/doc 目錄並執行以下命令,生成doc/bitbake-user-manual/bitbake-user-manual.html。
1 make html DOC =bitbake-user-manual
這個文檔可與本教程並行閱讀,在讀完本教程後也需要閱讀該文檔。
yocto工程文檔 也有一個bitbake章節。
創建工程 4.1 Bitbake 工程佈局 通過BitBake 工程通過layers 目錄與一個build 目錄組織,layer 目錄包含配置文件和meta data。
4.1.1 Layer 目錄 Layer 目錄包含配置、任務和目標描述。 常用meta-'something' 命名Layer 目錄。
4.1.2 Build 目錄 Build 目錄是bitbake 命令被執行的地方。 在這裡,BitBake 期望能找到其初始配置文件,並將其生成的所有文件放在這個目錄。
為了讓BitBake 運行時出現有任何錯誤,我們需要創建一個build 目錄和一個layer 目錄,並在此存放一些需要的配置文件。
4.2 最小工程 最小的配置看起來像這樣:
1 2 3 4 5 6 7 8 9 10 11 bbTutorial/ ├── build │ ├── bitbake.lock │ └── conf │ └── bblayers.conf └── meta-tutorial ├── classes │ └── base.bbclass └── conf ├── bitbake .conf └── layer.conf
需要創建這4 個文件:
bblayers.conf base.bbclass bitbake.conf layer.conf 4.2.1 需要的配置文件 首先描述需要的文件,然後簡要說明其內容。
build/conf/bblayers.conf
,BitBake 在其工作目錄(即build 目錄)期望找到的第一個文件。 現在我們以以下內容創建一個bblayers.conf:
1 2 3 BBPATH := "${TOPDIR}" BBFILES ?= "" BBLAYERS = "/path/to/meta-tutorial"
meta-tutorial/conf/layer.conf
,每個layer 需要一個conf/layer.conf 文件。 現在我們以以下內容創建它:
1 2 BBPATH .= ":${LAYERDIR}" BBFILES += ""
meta-tutorial/classes/base.bbclass
meta-tutorial/conf/bitbake.conf
現在,這些文件可以從BitBake 安裝目錄中獲取。 這些文件位於文件夾bitbake-$version/conf 和bitbake-$version/classes中。 只需將它們複製到tutorial 項目中。
4.2.2 創建文件的一些注意事項 build/conf/bblayers.conf
添加當前目錄到BBPATH,TOPDIR 被BitBake 設置為當前工作目錄。 初始設置BBFILES 變量為空,Recipes 在後面會添加。 添加我們meta-tutorial 的路徑到BBLAYERS 變量。 當BitBake 開始執行時,它會搜索所有給定的layer 目錄,以便獲得其他配置。 meta-tutorial/conf/layer.conf
LAYERDIR 是BitBake 傳給其所加載Layer 的變量。 我們添加該路徑到BBPATH 變量。 BBFILES 告訴BitBake recipes 在哪,現在我們沒有添加任何東西,但是一會兒我們會改變它。 注意事項。 “.=” 和“+=” 以不添加空格、添加空格的方式,將追加值附給一個變量。
conf/bitbake.conf
conf/bibake.conf 包含一系列我們討論的變量。
classes/base.bbclass
一個*.bbclass文件包含共享功能。 我們的base.bbclass包含一些我們一會兒使用的log函數,以及一個buld任務。 並不是很有用,但是BitBake有需求,因為如果沒有任何具體業務時,BitBake默認需求的。 我們隨後將改變此功能。
4.2.3 BitBake 搜索路徑 對於BitBake來講,有許多BBPATH非法和文件路徑。 這說明如果我們告訴BitBake探索一些路徑時,它會搜索BBPATH。 我們添加TOPDIR和LAYERDIR到BBPATH,放在classes/base.bbclass或conf/bitbake.conf中的任意一個。 當然,我們會添加meta-tutorial目錄。 編譯目錄不應含有通用文件。 只有像local.conf對實際編譯是有效的,後面我們會用到local.conf。
第一次運行 創建上述四個配置文件後,在終端cd 到build 目錄,這是我們的工作目錄。 我們一直在build 目錄運行bitbake 命令,以便bitbake 可以找到相應的conf/bblayers.conf 文件。
現在, 在build目錄 ,不帶任何參數運行bitbake命令:
如果先前的步驟正確,則控制台會輸出:
1 Nothing to do . Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.
這沒什麼用,但是一個好的開始。
這裡介紹一個很有用的命令標誌:輸出一些debug信息。 執行 bitbake -vDD
,然後查看其輸出,它告訴我們大量關於BitBake如何動作的信息。
1 2 3 4 5 6 7 8 9 10 11 DEBUG: Found bblayers.conf ( ~/bbTutorial/ build /conf/ bblayers.conf) DEBUG: LOAD ~/bbTutorial/ build /conf/ bblayers.conf DEBUG: Adding layer ~/bbTutorial/ meta-tutorial DEBUG: LOAD ~/bbTutorial / meta-tutorial /conf/ layer.conf DEBUG: LOAD ~/bbTutorial/ meta-tutorial /conf/ bitbake.conf DEBUG: BB configuration INHERITs: 0 : inheriting ~/bbTutorial/ meta-tutorial /classes/ base.bbclass DEBUG: BB ~/bbTutorial/ meta-tutorial /classes/ base. bbclass: handle(data, include) DEBUG: LOAD ~/bbTutorial/ meta-tutorial /classes/ base.bbclass DEBUG: Clearing SRCREV cache due to cache policy of: clear DEBUG: Using cache in '~/bbTutorial/build/tmp/cache/local_file_checksum_cache.dat' DEBUG: Using cache in '~/bbTutorial/build/tmp/cache/bb_codeparser.dat'
你在註意到BitBake 創建了一個bitbake.log 文件和一個tmp 目錄?
1 2 sunyongfeng @openswitch -OptiPlex- 380 :~/workshop/test/tutorial/build $ ls bitbake.lock conf tmp
提示,所有的樣例代碼都可從 https://bitbucket.org/a4z/bitbakeguide 獲取。 本樣例在ch04。
第一個recipe BitBake需要recipes定義要做些什麼,現在這裡什麼都沒有。 我們可以通過 bitbake -s
確認運行時什麼也沒做:
1 2 3 4 5 6 7 8 9 sunyongfeng @openswitch -OptiPlex- 380 :~/workshop/test/tutorial/build $ bitbake -s ERROR: no recipe files to build, check your BBPATH and BBFILES? Summary: There was 1 ERROR message shown, returning a non-zero exit code. NOTE: Not using a cache. Set CACHE = <directory> to enable. Recipe Name Latest Version Preferred Version =========== ============== ================= sunyongfeng @openswitch -OptiPlex- 380 :~/workshop/test/tutorial/build $
這告訴我們兩個信息:
沒有定義任何cache; BitBake 真的沒事可做,只顯示了一個空的recipe 列表 5.1 cache 位置 BitBake 緩存meta data 在一個目錄,即cache 目錄。 這會幫助加速後面執行的命令。
我們可通過簡單添加一個變量到bitbake.conf 文件,解決cache 找不到的問題。 因此,我們編輯meta-tutorial/conf/bitbake.conf 文件,並在底部添加:
1 CACHE = "${TMPDIR}/cache/default"
添加後運行 bitbake -s
的結果:
1 2 3 4 sunyongfeng@openswitch-OptiPlex- 380 :~ /workshop/ test /tutorial/ build$ bitbake -s ERROR: no recipe files to build, check your BBPATH and BBFILES? Summary: There was 1 ERROR message shown, returning a non-zero exit code.
注意:在實現項目中,比如Yocto,這些變量已經設置好,我們不用關心。 通常cache 路徑由不同的變量組成,在名稱中包含實際的構建配置,如debug 或release。
下一步是添加一個recipe,需要兩個步驟:
使bitbake 可以找到recipes 寫第一個recipe 5.2 添加一個recipe 到tutorial layer BitBake 需要知道一個layer 提供哪些recipes,可通過編輯meta-tutorial/conf/layer.conf 文件,使用通配符告訴BitBake 加載所有的recipe:
1 2 BBPATH .= ": ${LAYERDIR} " BBFILES += " ${LAYERDIR} /recipes-*/*/*.bb"
現在可以使用先前在build/conf/bblayers.conf 定義的變量。 recipe 文件的擴展名是.bb,如果我們通過通配符的方式,只用一行就可以告訴BitBake 加載所有recipes。
通常recipes 有自己的目錄,並以groups 的形式收集在一起,也就是說把有關聯的recipes 放在同一個目錄。
注意:通常使用recipes-'group' 命令這些目錄,這裡group 名表示一個category 或一些程序。
現在BitBake 已經知道從哪找recipe,我們可以開始添加第一個recipe 了。
按通常的做法,我們創建目錄meta-tutorial/recipes-tutorial/first,並在此創建第一個recipe。 Recipe 文件也有通用的命名方法:{recipe}_{version}.bb
5.3 創建第一個recipe 和task 我們的第一個recipe 只打印一些log 信息。 將它放在tutorial group,版本為0.1。 所以我們的第一個recipe 是: meta-tutorial/recipes-tutorial/first/first_0.1.bb
1 2 3 4 5 DESCRIPTION = "I am the first recipe" PR = "r1" do_build () { echo "first: some shell script running as build" }
task do_build 覆蓋base.bbclass 中的全局build task。 PR 是內部修訂數據,在每次修訂後應被更新。 設置description 可解釋該recipe 的用途。 如果上面都做對了,可以通過 bitbake -s
列出可用的recipes。
1 2 3 4 5 6 7 sunyongfeng@openswitch-OptiPlex -380 :~/workshop/test/tutorial/build$ bitbake -s Parsing recipes: 100 % |####################### ################################################## #######| Time: 00 : 00 : 00 Parsing of 1 .bb files complete ( 0 cached, 1 parsed). 1 targets, 0 skipped, 0 masked, 0 errors. Recipe Name Latest Version Preferred Version == ========= ============== ================= first : 0.1 -r1
然後就可以執行 bitbake first
編譯first組件。
1 2 3 4 5 6 7 sunyongfeng@openswitch-OptiPlex -380 :~/workshop/test/tutorial/build$ bitbake first Parsing recipes: 100 % |######################## ################################################## ######| Time: 00 : 00 : 00 Parsing of 1 .bb files complete ( 0 cached, 1 parsed). 1 targets, 0 skipped, 0 masked, 0 errors. NOTE: Resolving any missing task queue dependencies NOTE : Preparing RunQueue NOTE: Executing RunQueue Tasks NOTE: Tasks Summary: Attempted 1 tasks of which 0 didn 't need to be rerun and all succeeded.
現在檢查tmp/work/first-0.1-r1/temp 目錄,裡面有一些有趣的文件:
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 sunyongfeng @openswitch -OptiPlex- 380 :~/workshop/test/tutorial/build $ ls -al tmp/work/first- 0 . 1 -r1/temp/ total 20 drwxrwxr-x 2 sunyongfeng sunyongfeng 4096 10 月 20 11 : 19 . drwxrwxr-x 3 sunyongfeng sunyongfeng 4096 10 月 20 11 : 19 .. lrwxrwxrwx 1 sunyongfeng sunyongfeng 18 10 月 20 11 : 19 log.do_build -> log.do_build. 17314 -rw-rw-r-- 1 sunyongfeng sunyongfeng 123 10 月 20 11 : 19 log.do_build. 17314 -rw-rw-r-- 1 sunyongfeng sunyongfeng 37 10 月 20 11 : 19 log.task_order lrwxrwxrwx 1 sunyongfeng sunyongfeng 18 10 月 20 11 : 19 run.do_build -> run.do_build. 17314 -rwxrwxr-x 1 sunyongfeng sunyongfeng 909 10 月 20 11 : 19 run.do_build. 17314 sunyongfeng @openswitch -OptiPlex- 380 :~/workshop/test/tutorial/build $ cat tmp/work/first- 0 . 1 -r1/temp/log.do_build. 17314 DEBUG: Executing shell function do_build first: some shell script running as build DEBUG: Shell function do_build finished sunyongfeng @openswitch -OptiPlex- 380 :~/workshop/test/tutorial/build $ cat tmp/work/first- 0 . 1 -r1/temp/log.task_order do_build ( 17314 ): log .do_build. 17314 sunyongfeng @openswitch -OptiPlex- 380 :~/workshop/test/tutorial/build $ cat tmp/work/first- 0 . 1 -r1/temp/run.do_build bb_exit_handler() { ret= $? case $ret in 0 ) ;; *) case $BASH_VERSION in "" ) echo "WARNING: exit code $ret from a shell command." ;; *) echo "WARNING: ${BASH_SOURCE[0]}:${BASH_LINENO[0]} exit $ret from " $BASH_COMMAND "" ;; esac exit $ret esac } trap 'bb_exit_handler' 0 set -e export HOME= " /home/sunyongfeng" export SHELL= "/bin/bash" export LOGNAME= "sunyongfeng" export USER= "sunyongfeng" export PATH= "/home/sunyongfeng/ops-build.test/yocto/poky/scripts:/home/sunyongfeng/ops-build.test/ yocto/poky/bitbake/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games: /snap/bin" export TERM= "linux" do_build() { echo "first: some shell script running as build" } cd '/home/sunyongfeng/workshop/test/tutorial/build' do_build ret= $? trap '' 0 exit $?
Classes 和functions 下一步將:
添加一個class 添加一個使用class 的recipe 探索functions 6.1 創建mybuild class 創建一個不同的build函數,並共享。 先在tutorial layer創建class,如 meta-tutorial/classes/mybuild.bbclass
:
1 2 3 4 5 6 7 8 addtask build mybuild_do_build () { echo "running mybuild_do_build." } EXPORT_FUNCTIONS do_build
在base.class 中,我們添加了一個build task,它也是一個簡單的shell 函數。 mybuild_do 前綴的依據是class 中task 定義的規範classname_do_functionname。
EXPORT_FUNCTIONS 使該build 函數可被這個class 的使用者使用,如果不添加這行,則它不會覆蓋base class 中的build 函數。
現在,已可在第二個recipe 中使用這個class。
6.2 在第二個recipe 中使用myclass 這裡添加一個小目標,在build 任務前先運行一個patch 函數,這裡需要一些python 的用法。
依據bitbake的命名規範,我們添加一個新的recipe目錄,並在該目錄內添加一個recipe文件 meta-tutorial/recipes-tutorial/second/second_1.0.bb
:
1 2 3 4 5 6 7 8 9 10 11 12 13 DESCRIPTION = "I am he second recipe" PR = "r1" (1) inherit mybuild (2) def pyfunc(o): (3) print dir (o) python do_mypatch () { (4) bb.note ( "runnin mypatch" ) pyfunc(d) (5) } addtask mypatch before do_build (6)
像first recipe 那樣定義DESCRIPTION 和PR; 繼承mybuild class,讓myclass_do_build 成為默認build task; 純python 函數pyfunc 獲取一些參數,並根據該入參運行python dir 函數; bitbake python 函數my_patch 添加並註冊成一個task,該task 要在build 函數前執行。 mypatch 函數調用pyfunc 函數,並傳入全局bitbake 變量d。 d (datastore) 由bitbake 定義,並一直可用。 mypatch 函數被註冊成一個task,並要求在build 函數前執行。 這就是一個使用python 函數的樣例。
注意:函數部分的內容在bitbake 手冊3.4 節。
6.3 探索recipes 和tasks 現在我們有兩個recipes 可用,可探索一些新的bitbake 命令選項。 我們可以獲取BitBake 運行時recipes 及其tasks、控製過程的信息。
6.3.1 顯示recipes 和tasks 列表 1 2 3 4 5 6 7 8 sunyongfeng@openswitch-OptiPlex -380 :~/workshop/test/tutorial/build$ bitbake -s Parsing recipes: 100 % |####################### ################################################## #######| Time: 00 : 00 : 00 Parsing of 2 .bb files complete ( 0 cached, 2 parsed). 2 targets, 0 skipped, 0 masked, 0 errors. Recipe Name Latest Version Preferred Version == ========= ============== ================= first : 0.1 -r1 second : 1.0 -r1
如果想看某個recipe提供哪些tasks,可以通過 bitbake -c listtasks recipe_name
查看:
1 2 3 4 5 6 7 8 9 10 11 sunyongfeng@openswitch-OptiPlex -380 :~/workshop/test/tutorial/build$ bitbake -c listtasks second Parsing recipes: 100 % |##################### ################################################## #########| Time: 00 : 00 : 00 Parsing of 2 .bb files complete ( 0 cached, 2 parsed). 2 targets, 0 skipped, 0 masked, 0 errors. NOTE: Resolving any missing task queue dependencies NOTE: Preparing RunQueue NOTE: Executing RunQueue Tasks do_showdata do_build do_mypatch do_listtasks NOTE: Tasks Summary: Attempted 1 tasks of which 0 didn 't need to be rerun and all succeeded.
6.4 執行tasks 或完整構建 有些選項可在recipes 執行builds 或特定任務時使用。
構建一個recipe。 使用 bitbade recipe-name
執行該recipe的所有tasks。 執行一個task。 使用 bitbake -c your-task recipe-name
只運行recipe中的某個task。 構建所有recipe。 使用 bitbake world
運行所有recipes的所有tasks。 可以玩玩這些命令,看會出現什麼。
6.4.1 確認構建過程中的log Bitbake 創建一個tmp/work 目錄存放所有的log 文件。 這些log 文件包含一些有趣的信息,值得一學。 第一次執行完bitbake world ,其輸出為:
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 sunyongfeng@openswitch-OptiPlex-380:~/workshop/test/tutorial/build$ bitbake world Parsing recipes: 100% |######################## ################################################## ######| Time: 00:00:00 Parsing of 2 .bb files complete (0 cached, 2 parsed). 2 targets, 0 skipped, 0 masked, 0 errors. NOTE: Resolving any missing task queue dependencies NOTE : Preparing RunQueue NOTE: Executing RunQueue Tasks NOTE: Tasks Summary: Attempted 3 tasks of which 0 didn't need to be rerun and all succeeded. sunyongfeng@openswitch-OptiPlex-380:~/workshop/test/tutorial/build$ tree tmp /work/ tmp/work/ ├── first-0.1-r1 │ └── temp │ ├── log.do _build -> log.do_ build.17657 │ ├── log.do _build.17657 │ ├── log.task_ order │ ├── run.do _build -> run.do_ build.17657 │ └── run.do _build.17657 └── second-1.0-r1 ├── second-1.0 └── temp ├── log.do_ build -> log.do _build.17659 ├── log.do_ build.17659 ├── log. do_mypatch -> log.do_mypatch.17656 ├── log.do_mypatch.17656 ├── log.task_order ├── run.do_build -> run.do_build.17659 ├── run.do_build.17659 ├── run.do_mypatch - > run.do_mypatch.17656 └── run.do_mypatch.17656
這些log 文件包含很多有用的信息,比如BitBake 如何運行,執行tasks 輸出了什麼。
BitBake layers 典型BitBake 工程包含多個layer。 通常layer 包含一個特定主題,比如基礎系統、圖像系統等。 一些工程可以包括不止一個構建目標,每個目標由不同的layers 組成。 例如,構建一個帶GUI 組件或不帶GUI 組件的Linux 發行版本。
Layers 可以被使用、擴展、配置,也可能部分覆蓋已有的layers。 這很重要,因為它允許根據實際要求重用或自定義。
多個layers 共同動作是通用的例子,因此我們會添加一個額外的層次到工程。
7.1 添加一個layer 通過以下步驟添加一個新的layer:
創建一個新的layer 目錄 創建layer 配置 告訴BitBake 有新的layer 添加recipes 到layer 7.1.1 添加新的layer 目錄 創建一個新的目錄叫meta-two:
1 2 sunyongfeng @openswitch -OptiPlex- 380 :~/workshop/test/tutorial $ ls build meta-tutorial meta-two
7.1.2 配置新layer 添加meta-two/conf/layer.conf 文件,該文件和tutorial layer 的一樣:
1 2 BBPATH .= ": ${LAYERDIR} " BBFILES += " ${LAYERDIR} /recipes-*/*/*.bb"
7.1.3 告訴BitBake 有新的layer 編輯build/conf/bblayers.conf,擴展BBLAYERS 變量:
1 2 3 4 BBLAYERS = " \ ${TOPDIR} /../meta-tutorial \ ${TOPDIR} /../meta-two \ "
bitbake-layer 命令 通過 bitbake-layer
命令檢查新layer配置。 首先使用show-layers選項,顯示該工程的layers、layers路徑和優先級。 這裡優先級都是0,後面會嘗試改一下。
1 2 3 4 5 sunyongfeng @openswitch -OptiPlex- 380 :~/workshop/test/tutorial/build $ bitbake-layers show-layers layer path priority ======================= ================================================== = meta-tutorial /home/sunyongfeng/workshop/test/tutorial/build/../meta-tutorial 0 meta-two /home/sunyongfeng/workshop/test/tutorial/build/../meta-two 0
bitbake-layers 命令還有其他有用的選項,可通過-h 選項顯示。
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 sunyongfeng@openswitch-OptiPlex- 380 :~/workshop/test/tutorial/build$ bitbake-layers -h usage: bitbake-layers [-h] [-d] [-q] <subcommand> ... BitBake layers utility optional argument s: -h, -- help show this help message and exit -d, -- debug Enable debug output -q, --quiet Print only errors subcommand s: <subcommand> show-layers show current configured layers add -layer Add a layer to bblayers. conf remove -layer Remove a layer from bblayers. conf show-overlayed list overlayed recipes (where the same recipe exists in another layer) show -recipes list available recipes, showing the layer they are provided by show-appends list bbappend files and recipe files they apply to flatten flatten layer configuration into a separate output directory. show-cross-depends Show dependencies between recipes that cross layer boundaries. layerindex-fetch Fetches a layer from a layer index along with its dependent layers, and adds them to conf /bblayers. conf . layerindex-show-depends Find layer dependencies from layer index . Use bitbake-layers <subcommand> -- help to get help on a specific command
7.3 擴展layer 配置 在layer 的layer.conf 文件中,定義優化級和其他配置值。 為配置layer 的優先級,需要添加新的定義到已有的layer.conf。 以meta-tutorial/conf/layer.conf 開始,添加:
1 2 3 4 5 BBFILE_COLLECTIONS += "tutorial" BBFILE_PATTERN_tutorial = "^${LAYERDIR}/" BBFILE_PRIORITY_tutorial = "5"
使用的變量在BitBake 使用手冊有很好的說明,這裡不重複。
模式應是清楚的,這裡定義layer 名,並使用這個名字做為其他變量的後綴。 這種在BitBake 變量名中使用用戶定義的域後綴機制,在BitBake 的很多地方可以看到。
同樣的,修改meta-two/conf/layer.conf:
1 2 3 4 5 BBFILE_COLLECTIONS += "tutorial" BBFILE_PATTERN_tutorial = "^${LAYERDIR}/" BBFILE_PRIORITY_tutorial = "5"
如果此時運行bitbake-layers show-layers,結果是:
1 2 3 4 5 sunyongfeng @openswitch -OptiPlex- 380 :~/workshop/test/tutorial/build $ bitbake-layers show-layers layer path priority ======================= ================================================== = meta-tutorial /home/sunyongfeng/workshop/test/tutorial/build/../meta-tutorial 5 meta-two /home/sunyongfeng/workshop/test/tutorial/build/../meta-two 5
共享和重用配置 截止目前,我們使用classes 和config 文件封裝配置和tasks。 但是還有更多的方法重用和擴展tasks 和配置:
class 繼承 bbappend 文件 include 文件 為說明如何使用這些方法,我們將添加class 到layer-two,新的class 將介紹一個configure-build 鏈並使用class 繼承重用現存的mybuild class。 然後在新的recipe 中使用這個新class,最後通過append 方法擴展現有的recipe。
8.1 class 繼承 為實現configure-build 鏈,這裡創建一個class,該class 繼承mybuild,並簡單添加一個configure task,讓build task 依賴configure task。
meta-two/classes/confbuild.bbclass
:
1 2 3 4 5 6 7 8 9 10 11 inherit mybuild ( 1 ) confbuild_do_configure () { ( 2 ) echo "running configbuild_do_configure." } addtask do_configure before do_build ( 3 ) EXPORT_FUNCTIONS do_configure ( 4 )
以mybuild class 為基礎; 創建新的函數; 定義函數的順序,configre 在build 之前; export 剛創建的函數使之可用。 然後創建third recipe使用confbuild class。 meta-two/recipes-base/third_01.bb
:
1 2 3 DESCRIPTION = "I am the third recipe" PR = "r1" inherit confbuild
這時運行 bitabke third
會執行configure和build task。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 sunyongfeng@openswitch-OptiPlex-380:~/workshop/test/tutorial/build$ bitbake third Parsing recipes: 100% |######################## ################################################## ################################################## ##########| Time: 00:00:00 Parsing of 3 .bb files complete (0 cached, 3 parsed). 3 targets, 0 skipped, 0 masked, 0 errors. NOTE: Resolving any missing task queue dependencies NOTE: Preparing RunQueue NOTE: Executing RunQueue Tasks NOTE: Tasks Summary: Attempted 2 tasks of which 0 didn't need to be rerun and all succeeded. sunyongfeng@openswitch-OptiPlex-380:~/workshop/test/tutorial/ build$ cat tmp/work/third-01-r1/temp/ log.do _build log.do_ configure log.task _order run.do_ build.19728 run.do _configure.19726 log.do_ build.19728 log.do _configure.19726 run.do_ build run.do _configure sunyongfeng@openswitch-OptiPlex-380:~/workshop/test /tutorial/build$ cat tmp/work/third-01-r1/temp/log.task_ order do _configure (19726): log.do_ configure.19726 do _build (19728): log.do_ build.19728 sunyongfeng@openswitch- OptiPlex-380:~/workshop/test/tutorial/build$ cat tmp/work/third-01-r1/temp/log.do _configure DEBUG: Executing shell function do_ configure running configbuild _do_ configure. DEBUG: Shell function do _configure finished sunyongfeng@openswitch-OptiPlex-380:~/workshop/test/tutorial/build$ cat tmp/work/third-01-r1/temp/log.do_ build DEBUG: Executing shell function do _build running mybuild_ do _build. DEBUG: Shell function do_ build finished
8.2 bbappend 文件 append文件可以添加函數到已有class中,而不需要創建一個新class。 它向同名class添加append文件的文本。 需要設置layer配置,才能加載到對應的append文件。 因此需要改變layer的配置,添加加載*.bbappend文件的配置到BBFILES變量。 例如: meta-two/conf/layer.conf
:
1 2 BBFILES += " ${LAYERDIR} /recipes-*/*/*.bb \ ${LAYERDIR} /recipes-*/*/*.bbappend"
現在擴展已有的first recipe,讓它在build task前先運行一個patch函數。 為做對比,將對應的recipe和append文件放到meta-two/recipes-base/first目錄。 meta-two/recipes-base/first/first_0.1.bbappend
:
1 2 3 4 5 python do_patch () { bb.note ( "first:do_patch" ) } addtask patch before do_build
此時若列出first recipe 的task 列表,可以看到patch task。 運行bitbake first 可看到運行了patch 和build。
添加前:
1 2 3 4 5 6 7 8 9 10 sunyongfeng@openswitch-OptiPlex -380 :~/workshop/test/tutorial/build$ bitbake -c listtasks first Parsing recipes: 100 % |##################### ################################################## #########| Time: 00 : 00 : 00 Parsing of 3 .bb files complete ( 0 cached, 3 parsed). 3 targets, 0 skipped, 0 masked, 0 errors. NOTE: Resolving any missing task queue dependencies NOTE: Preparing RunQueue NOTE: Executing RunQueue Tasks do_showdata do_build do_listtasks NOTE: Tasks Summary: Attempted 1 tasks of which 0 didn 't need to be rerun and all succeeded.
添加append 文件後:
1 2 3 4 5 6 7 8 9 10 11 sunyongfeng@openswitch-OptiPlex -380 :~/workshop/test/tutorial/build$ bitbake -c listtasks first Parsing recipes: 100 % |##################### ################################################## #########| Time: 00 : 00 : 00 Parsing of 3 .bb files complete ( 0 cached, 3 parsed). 3 targets, 0 skipped, 0 masked, 0 errors. NOTE: Resolving any missing task queue dependencies NOTE: Preparing RunQueue NOTE: Executing RunQueue Tasks do_showdata do_build do_listtasks do_patch NOTE: Tasks Summary: Attempted 1 tasks of which 0 didn 't need to be rerun and all succeeded.
運行bitbake first 結果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 sunyongfeng@openswitch-OptiPlex-380:~/workshop/test/tutorial/build$ bitbake first Parsing recipes: 100% |######################## ################################################## ######| Time: 00:00:00 Parsing of 3 .bb files complete (0 cached, 3 parsed). 3 targets, 0 skipped, 0 masked, 0 errors. NOTE: Resolving any missing task queue dependencies NOTE : Preparing RunQueue NOTE: Executing RunQueue Tasks NOTE: Tasks Summary: Attempted 2 tasks of which 0 didn't need to be rerun and all succeeded. sunyongfeng@openswitch-OptiPlex-380:~/workshop/test/tutorial/build$ cat tmp /work/first-0.1-r1/temp/ log.do _build log.do_ listtasks.20111 run.do _build run.do_ listtasks.20111 log.do _build.20152 log.do_ patch run.do _build.20152 run.do_ patch log.do _listtasks log.do_ patch.20151 run.do _listtasks run.do_ patch.20151 log.do _listtasks.20001 log.task_ order run.do _listtasks.20001 sunyongfeng@openswitch-OptiPlex-380:~/workshop/test/tutorial/build$ cat tmp/work/first-0.1-r1/temp/log.task_ order do _listtasks (20001): log.do_ listtasks.20001 do _listtasks (20111): log.do_ listtasks.20111 do _patch (20151): log.do_ patch.20151 do _build (20152): log.do_ build.20152 sunyongfeng@openswitch-OptiPlex-380:~/workshop/test/tutorial/build$
提示:如果你願意,現在就可以構建一個recipe,使用confbuild class 和一個append 文件,運行patch、configure 和build 任務。
8.3 include 文件 BitBake 有兩種指令引用文件:
include filename
,這是一種可選引用,如果filename 找不到,不會有error 產生; require filename
,如果filename 沒找到,會產生error。 值得一提的是,include 和require 都是在BBPATH 中指定的目錄查找filename。
8.3.1 添加local.conf 用於引用文件 BitBake 工程通常使用bitbake.conf 引用一個位於build 目錄內的local.conf 文件。 local.conf 文件可能包含一些當前構建目標相關的特殊設置。 典型的樣例是Yocto 的設置。
這裡模仿local.conf 的典型應用,讓bitbake.conf require 引用local.conf,添加以下內容到meta-tutorial/conf/bitbake.conf:
1 2 require local . conf include conf /might_exist. conf
如果此時執行構建命令,BitBake 會產生類似以下的錯誤信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 sunyongfeng@openswitch-OptiPlex-380:~/workshop/ test / tutorial /build$ bitbake world ERROR : Traceback (most recent call last): File "/home/sunyongfeng/ops-build.test/yocto/poky/bitbake/lib /bb/cookerdata.py" , line 175, in wrapped return func(fn, * args ) File "/home/sunyongfeng/ops-build.test/yocto/poky/bitbake/lib/bb/cookerdata.py" , line 185, in parse_config_file return bb. parse .handle(fn, data, include ) File "/home/sunyongfeng/ops-build.test/yocto/poky/bitbake/lib/bb/parse/__init__.py" , line 107, in handle return h ['handle'](fn, data, include ) File " /home/sunyongfeng/ops-build.test/yocto/poky/bitbake/lib/bb/parse/parse_py/ConfHandler.py" , line 148, in handle statements.eval(data) File "/home/sunyongfeng/ops- build.test/yocto/poky/bitbake/lib/bb/parse/ast.py " , line 39, in eval statement.eval(data) File "/home/sunyongfeng/ops-build.test/yocto/poky/bitbake /lib/bb/parse/ast.py" , line 61, in eval bb. parse .ConfHandler. include (self.filename, s, self.lineno, data, "include required" ) File "/home/sunyongfeng/ops-build.test/yocto/poky/bitbake/ lib/bb/parse/parse_py/ConfHandler.py" , line 98, in include raise ParseError( "Could not %(error_out)s file %(fn)s" % vars(), parentfn, lineno) ParseError: ParseError at / home/sunyongfeng/workshop/ test / tutorial /build/../meta- tutorial / conf /bitbake. conf :53: Could not include required file local . conf ERROR : Unable to parse conf /bitbake. conf : ParseError at /home/sunyongfeng/workshop/ test / tutorial /build/../meta- tutorial / conf /bitbake. conf :53: Could not include required file local . conf
添加一個local.conf 文件到build 目錄可解決此問題。 注意include 語句包含的文件可有可無。
使用變量 可定義變量並在recipes 中使用,讓BitBake 具有很強的靈活性。 可將可配置部分使用變量的方式編寫recipe,這種recipe 的用戶可以給出那些將由recipe 使用的變量值。 一個典型的例子是給recipe 傳遞額外的配置或標誌。 通過正確使用變量,不需要編輯和更改recipe,因為某些函數只需要一些特殊的參數。
9.1 全局變量 全局變量可以通過使用者設置,recipe 可以使用。
9.1.1 定義全局變量 剛才已經創建一個空的local.conf,現在在這個文件加一些變量。 比如添加一行:
1 MYVAR = "hello from MYVAR"
9.1.2 訪問全局變量 可以在recipes或classes中訪問MYVAR變量。 這裡創建一個新的recipes組recipes-vars,及一個recipe myvar。 meta-two/recipes-vars/myvar/myvar_0.1.bb
:
1 2 3 4 5 6 7 8 9 10 11 12 DESCRIPTION = "Show access to global MYVAR" PR = "r1" do_build(){ echo "myvar_sh: ${MYVAR} " ( 1 ) } python do_myvar_py () { print "myvar_py:" + d.getVar( 'MYVAR' , True) ( 2 ) } addtask myvar_py before do_build
在類bash 語法中訪問變量; 通過全局數據存儲訪問變量。 現在運行 bitbake myvar
,檢查tmp目錄的輸出,則可以看到我們確實訪問了全局MYVAR變量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 sunyongfeng@openswitch-OptiPlex-380:~/workshop/test/tutorial/build$ bitbake myvar Parsing recipes: 100% |######################## ################################################## ######| Time: 00:00:00 Parsing of 4 .bb files complete (0 cached, 4 parsed). 4 targets, 0 skipped, 0 masked, 0 errors. NOTE: Resolving any missing task queue dependencies NOTE : Preparing RunQueue NOTE: Executing RunQueue Tasks NOTE: Tasks Summary: Attempted 2 tasks of which 0 didn't need to be rerun and all succeeded. sunyongfeng@openswitch-OptiPlex-380:~/workshop/test/tutorial/build$ sunyongfeng@ openswitch-OptiPlex-380:~/workshop/test/tutorial/build$ cat tmp/work/myvar-0.1-r1/temp/log.task _order do_ myvar _py (4595): log.do_ myvar _py.4595 do_ build (4596): log.do _build.4596 sunyongfeng@openswitch-OptiPlex-380:~/workshop/test/tutorial/build$ cat tmp/work/myvar -0.1-r1/temp/log.do_ myvar _py DEBUG: Executing python function do_ myvar _py myvar_ py:hello from MYVAR DEBUG: Python function do _myvar_ py finished sunyongfeng@openswitch-OptiPlex-380:~/workshop/test/tutorial/ build$ cat tmp/work/myvar-0.1-r1/temp/log.do _build DEBUG: Executing shell function do_ build myvar _sh: hello from MYVAR DEBUG: Shell function do_ build finished
9.2 本地變量 典型的recipe 只包含一些本地變量,這些變量用於其繼承的classes 中的函數設置。
先創建 meta-two/classes/varbuild.bbclass
:
1 2 3 4 5 6 7 varbuild_do_build () { echo "build with args: ${BUILDARGS} " } addtask build EXPORT_FUNCTIONS do_build
然後在 meta-two/recipes-vars/varbuld/varbuild_0.1.bb
中使用:
1 2 3 4 5 6 7 DESCRIPTION = "Demonstrate variable usage \ for setting up a class task" PR = "r1" BUILDARGS = "my build arguments" inherit varbuild
運行 bitbake varbuild
,輸出的log顯示build任務使用了recipe設置的變量值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 sunyongfeng@openswitch-OptiPlex-380:~/workshop/test/tutorial/build$ bitbake varbuild Parsing recipes: 100% |######################## ################################################## ######| Time: 00:00:00 Parsing of 5 .bb files complete (0 cached, 5 parsed). 5 targets, 0 skipped, 0 masked, 0 errors. NOTE: Resolving any missing task queue dependencies NOTE : Preparing RunQueue NOTE: Executing RunQueue Tasks NOTE: Tasks Summary: Attempted 1 tasks of which 0 didn't need to be rerun and all succeeded. sunyongfeng@openswitch-OptiPlex-380:~/workshop/test/tutorial/build$ cat tmp /work/varbuild-0.1-r1/temp/log.task _order do_ build (4760): log.do _build.4760 sunyongfeng@openswitch-OptiPlex-380:~/workshop/test/tutorial/build$ cat tmp/work/varbuild-0.1-r1/temp/log.do_ build DEBUG: Executing shell function do _build build with args: my build arguments DEBUG : Shell function do_ build finished sunyongfeng@openswitch-OptiPlex-380:~/workshop/test/tutorial/build$
這是使用BitBake的典型方法。 通用task 由class 定義,比如下載源代碼、configure、make 和其他操作,recipe 設置這些task 所需要的變量。
附目錄樹 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 sunyongfeng ./ build ├── bitbake.lock ├── conf │ └── bblayers.conf └── local.conf ./meta- tutorial ├── classes │ ├── base.bbclass │ └── mybuild. bbclass ├── conf │ ├── bitbake.conf │ └── layer.conf └── recipes-tutorial ├── first │ └─ ─ first_0. 1 . bb └── second └── second_1. 0 . bb ./meta-two ├── classes │ ├── confbuild. bbclass │ └── varbuild. bbclass ├── conf │ ├── bitbake.conf │ └── layer.conf ├── recipes- base │ ├── first │ │ └── first_0 . 1 . bbappend │ └── third │ └── third_01. bb └── recipes-vars ├── myvar │ └── myvar_0. 1 . bb └── varbuild └── varbuild_0. 1 . bb 14 directories, 17 files
總結 以上是本教程的所有內容,感謝你一直看到這裡,希望你喜歡。 學習完教程,你應該對BitBake的基本概念有基本理解。 本教程涉及的內容有:
BitBake 是一個執行python 和shell 腳本的引擎; 常見的BitBake 工程設計與一些默認文件的位置; BitBake 使用的5 種文件類型(.bb,.bbclass,.bbappend,.conf 和include 文件); BitBake 函數和task,說明如何組織、分組和調用它們; BitBake 變量及其基本使用方法。 熟悉這些內容後,希望你可以開始使用類似Yocto 的工程,並繼續深入理解。
沒有留言:
張貼留言