# BitBake & Yocto Project --- ## 1. Yocto Project Overview * **Yocto Project** 是一個 Linux 基金會主導的開源計畫,旨在提供一套可重複、可客製化且跨架構的嵌入式 Linux 開發工具鏈 * **核心組件**: * **BitBake**:核心 Build Engine * **OpenEmbedded-Core (OE-Core)**:基礎 Metadata 集合,包含 recipes, classes 與 configs * **Poky**:Yocto 的 Reference System,集成了 BitBake、OE-Core 與範例 Metadata,是開發者的起手點 --- ## 2. Core Concepts & Components ### 2.1 BitBake (Build Engine) * 基於 Python 開發的任務排程工具。雖然功能類似 `GNU Make`,但專為大規模嵌入式系統設計 * **主要特性**: * 解析 Metadata(`.bb` 檔案),計算 Task Dependency(如 fetch → compile) * 支援跨平台並行處理 (Parallel Execution) * **與 GNU Make 的差異**: * 具備 **Class 繼承機制** (`.bbclass`)。 * 任務腳本可混用 Python 與 Shell Script。 * 引入 **Shared State Cache (sstate-cache)** 機制,大幅優化重複建構的速度。 ### 2.2 Recipes (.bb files) * 描述單一軟體套件如何建構的「藍圖」 * **重要變數 (Key Variables)**: * `PN` / `PV`:Package Name 與 Version * `LICENSE` & `LIC_FILES_CHKSUM`:定義授權並透過 md5/sha256 校驗碼確保授權文件的完整性 * `SRC_URI`:Source code 來源路徑(支援 Git, HTTP, local files 等) * `DEPENDS`:Build-time dependencies(編譯時期的相依性) * `RDEPENDS`:Runtime dependencies(執行時期的相依性) ### 2.3 Classes (.bbclass files) * 封裝可重用的建構邏輯(例如 `cmake`, `autotools`) * **關鍵語法**: * `inherit`:讓 Recipe 直接繼承類別定義好的功能 * `addtask`:定義任務的執行順序 * `EXPORT_FUNCTIONS`:允許 Recipe 覆寫 (override) 或擴充 Class 裡的 function ### 2.4 Configuration Files (.conf) * `local.conf`:開發者的本地設定(例如 `MACHINE` 型號、`DL_DIR` 下載路徑) * `layer.conf`:定義 Layer 的搜尋路徑與優先權 (`BBFILE_PRIORITY`) * `bitbake.conf`:系統全域設定(例如 `${bindir}`, `${libdir}` 等路徑定義與編譯器參數) --- ## 3. GNU Make vs. BitBake | 項目 | GNU Make | BitBake | | --- | --- | --- | | **建構規則** | Makefile | Recipe (`.bb`) | | **規則擴充** | 手動加入 Makefile | Recipe Append (`.bbappend`) | | **設定檔** | Makefile 或 環境變數 | Configuration (`.conf`) | | **繼承機制** | 無 | Class (`.bbclass`) | | **腳本語言** | Shell | Shell + Python | --- ## 4. Build Workflow & Tasks ### 4.1 Standard Task Order BitBake 會依照以下順序執行預設任務: 1. **do_fetch**:抓取 Source code 2. **do_unpack**:解壓縮檔案到工作目錄 3. **do_patch**:套用 `.patch` 檔案 4. **do_compile**:執行編譯流程(如 `make` 或 `gcc`) 5. **do_install**:將產物安裝到臨時目錄(`${D}`) 6. **do_package**:將檔案切分成各個 Packages (如 debug, doc, main)。 7. **do_build**:完成所有流程 ### 4.2 Cache Mechanism * **sstate-cache**:BitBake 會紀錄每個 Task 的輸入(Checksum),若輸入未變動,則直接從 Cache 抓取結果,避免重複編譯消耗時間 --- ## 5. Components Summary Table | Component | Format | Role | Key Features | | --- | --- | --- | --- | | **BitBake** | Engine | Build Task Scheduler | Parallel execution, Dependency handling | | **Recipes** | `.bb` | Build Blueprints | Define `SRC_URI`, `DEPENDS`, etc. | | **Append Files** | `.bbappend` | Customization | **Override or extend existing recipes** | | **Classes** | `.bbclass` | Reusable Logic | Use `inherit` to simplify recipes | | **Configuration** | `.conf` | Settings | Machine type, Layer priority, Paths | | **Layers** | Folder | Modular Container | Organize Metadata; Priority based | --- ## 6. Example: Hello World ### 6.1 下載 BitBake repository ```bash git clone https://git.openembedded.org/bitbake ``` ![image](https://hackmd.io/_uploads/BylvKylXWg.png) BitBake 核心資料夾結構和功能說明: * bin/:執行檔工具,包含核心的bitbake 指令 * classes/:共用建構邏輯,存放 .bbclass 檔案 * conf/:預設設定檔,例如核心的 bitbake.conf * contrib/:輔助腳本,額外的工具與幫助程式碼 * doc/:說明文件,BitBake 的技術手冊 * lib/:核心函式庫,BitBake 運作所需的 Python 核心程式碼 ### 6.2 File structure: ```text project/ ├── classes/ │ └── base.bbclass # 定義基礎 Tasks (fetch, compile...) ├── conf/ │ └── bitbake.conf # 定義全域變數 (Compiler, Paths) ├── recipes/ │ └── hello/ │ ├── files/ │ │ ├── hello.c # Source code │ │ └── LICENSE # License file │ └── hello_1.0.bb # Recipe description ``` #### bitbake.conf ![image](https://hackmd.io/_uploads/Sy1uGVrm-l.png) #### base.bbclass ![image](https://hackmd.io/_uploads/HyJcX4H7We.png) * 利用 addtask 指令定義 Task 順序:fetch → unpack → compile → install #### hello_1.0.bb ![image](https://hackmd.io/_uploads/r1RzBESQZl.png) * Metadata & Compliance: * LICENSE 與 LIC_FILES_CHKSUM:強制定義軟體授權並進行 MD5/SHA256 校驗 * Source Tracking:透過 SRC_URI 指定本地或遠端資源路徑 * 任務自定義: * do_compile:明確定義編譯行為,利用全域變數執行交叉編譯 * do_install:定義產物分發邏輯,將 Binary 搬移至預計的映像檔根目錄下對應的路徑 #### hello.c ```bash #include <stdio.h> int main(void){ printf("Hello, world from Bitbake!\n"); return 0; } ``` ### 6.3 compile ```bash bitbake hello ``` --- ## 7. Common Commands 開發中常用的 BitBake 指令: * **Debug 環境變數**: ```bash bitbake <recipe> -e ``` * **Verbose Mode**: ```bash bitbake <recipe> -v ``` * **分析相依性圖表**: ```bash bitbake <recipe> -g ``` * **查詢 Layers**: ```bash bitbake-layers show-layers ``` --- ## 8. Troubleshooting 在 BitBake 開發過程中,遇到報錯可以先檢查以下幾點: * **Python 版本不相容**: ![image](https://hackmd.io/_uploads/HJasNygXWx.png) * **原因**:BitBake 核心是基於 Python 3 運作,若系統預設 Python 版本過舊或使用的 Python 3 版本低於該 Yocto 版本的要求,解析 Metadata 時會報錯 * **對策**: 1. **版本檢查**:執行 `python3 --version` 確認版本。 2. **環境初始化**:確保有執行 `source oe-init-build-env`,這會自動設定正確的 `PATH` 3. **使用 Pyenv**:建立獨立的 Python 虛擬環境或使用 `pyenv` 切換版本,避免污染全域環境 ```bash git clone https://github.com/pyenv/pyenv.git ~/.pyenv echo 'export PYENV_ROOT="/build_2/charlie/.pyenv"' >> ~/.bashrc echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc echo 'eval "$(pyenv init -)"' >> ~/.bashrc source ~/.bashrc pyenv install -v 3.9.0 pyenv global 3.9.0 ``` ![image](https://hackmd.io/_uploads/SJ7PwkeQZg.png) * **LIC_FILES_CHKSUM 不符合**: * **現象**:`do_populate_lic` 報錯 * **原因**:授權檔案內容變動或 md5 填錯 * **對策**:使用 `md5sum <file>` 重新計算並更新 Recipe * **SRC_URI 找不到檔案**: * **現象**:`do_fetch` 失敗 * **原因**:檔案沒放在 `files/` 子目錄下,或檔名大小寫不一 * **對策**:確認檔案路徑,或檢查 `FILESPATH` 變數 * **清除快取重新建構**: ```bash bitbake <recipe> -c cleanall # 刪除所有產物與下載的 sourc ```