Yocto專案介紹及入門 -- 嵌入師工程師必備利器

chegxy發表於2021-02-09


寫在前面

博主目前從事BMC工作,由於公司要開發openbmc專案,所以要學習Yocto專案。截至目前,我已經學習了一段時間了,大致可以熟練使用Yocto專案進行嵌入式系統的開發,由於網上這方面的相關知識不太多,所以想盡綿薄之力為這方面的知識做一些補充。文中可能有所疏漏,歡迎留言指正,另外有興趣的同學也歡迎交流。

1. Yocto專案是什麼

Yocto專案本質是一個構建工具,其幫助開發者能夠快速地、簡單地設計一個基於Linux的系統。該專案由Linux基金會贊助,於2010年啟動。同時,在談到Yocto專案的時候,就不得不提到OpenEmbedded專案,該專案源於夏普的一個開源專案OpenZaurus(服務於SL-5000D),後來結合了其他幾個類似的嵌入式專案(Familiar Linux, OpenSIMpad),其目的是為嵌入式系統構建Linux發行版。OpenEmbedded專案維護了一個構建工具BitBake和一個後設資料層(詳細描述了構建一個Linux發行版所需要的包及構建過程)。Poky Linux是OpenEmbedded專案的一個擴充套件應用,同時也是Yocto專案的前身。在2011年的時候,OpenEmbedded專案宣佈於Yocto專案進行合作,共同維護BitBake以及一個核心資料層。

你可能想問它倆究竟區別在哪,其實它兩最終目標都是構建Linux發行版,但側重點不同,OpenEmbedded聚焦在尖端技術、菜譜和一大套針對不同硬體平臺的板支援包,而Yocto專案聚焦在構建系統本身和針對交叉開發的工具化上。如果還不明白,那你直接就可以理解為一個偏硬體,一個偏軟體,相輔相成。

另外,我希望你可以通過下面這幅圖加深對我之前說的話的理解,圖片來自Yocto官網:

Yocto專案介紹及入門 -- 嵌入師工程師必備利器

在上面圖中,poky是Yocto專案為開發者提供的一個開發樣例,使用者可以直接使用poky來生成一個Linux發行版映象,或者也可以通過擴充套件它來自定義映象。與此同時,poky中包含了一個核心後設資料,其詳細描述了構建一個Linux發行版所需要的包及構建過程,而它正是OpenEmbedded專案的一部分。

2. Yocto專案有什麼用

要說Yocto專案有什麼用處,實際上前一節已經說了個大概。如果現在你需要基於Linux系統設計一個定製版的發行版,那麼藉助於Yocto專案你可以通過修改一些菜譜和配置檔案(這些概念不懂沒事,之後會提到,你在這隻需知道這些檔案控制了構建Linux發行版系統的過程)非常簡單的構建出一個可用的發行版映象。又或者你現在有個小型嵌入式工控裝置,需要為其提供一個特別小的可執行Linux系統,那麼你也可以利用Yocto專案完成你的目的。

總之,借用Yocto官網的描述,Yocto專案就是一個工具,用於構建基於Linux的系統:

The project provides a flexible set of tools and a space where embedded developers worldwide can share technologies, software stacks, configurations, and best practices that can be used to create tailored Linux images for embedded and IOT devices, or anywhere a customized Linux OS is needed.

3. 如何快速上手Yocto專案

如果你之前曾今接觸過Yocto專案,那你肯定會抱怨過關於這方面網路資訊資源的匱乏。如果你真的對這個內容感興趣,你可以通過兩種學習路徑來理解和熟悉使用Yocto專案。

第一個學習路徑是我極為推薦的,那就是使用官網的學習手冊。這個手冊每次Yocto專案更新後,它也會隨之更新,因此內容是比較新的,不容易出現問題。但是問題就是內容是英文的,可能學起來稍微比較費時。

另外一個比較推薦的是通過Rudolf J. Streif寫的一本書《Embedded Linux Systems with the Yocto Project》,現在這本書已經被國內的一位大佬胥峰翻譯過來了,書名叫《嵌入式Linux系統開發:基於Yocto Project》。有點遺憾的是,該書是2018年出版的,所以文中有些內容已經有點過時了,所以需要讀者多注意一下。另外,如果有同學想要該書的電子版,可以留下郵箱。

最後,還要注意的是,不論哪種方法,文中都有大量的測試實驗,這些內容還請務必嘗試,最好可以舉一反三,我可以保證在學習完成之後你會有巨大的收穫。

4. 帶你通過Yocto專案編譯一個自定義映象檔案

在做這個實驗之前,你必須先確認一下你的系統是否達到這些要求:

型別 需求
構建主機CPU X86架構
記憶體容量 大於或者等於4GB,不低於1GB
網路 最好設定連線到外網的代理,沒有也沒關係,只不過構建時間會很長
系統 任意Linux發行版

如果確定達到了這些要求,那麼我們現在開始構建一個帶列印Hello World應用的桌面Linux系統發行版映象。

首先你需要預安裝一些Yocto工程會使用到的軟體包(以Ubuntu為例):

$ sudo apt install gawk wget git-core diffstat unzip texinfo gcc-multilib
$ sudo apt install build-essential chrpath socat cpio python3 python3-pip python3-pexpect 
$ sudo apt install xz-utils debianutils iputils-ping python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev 
$ sudo apt install pylint3 xterm

其次,我們還需要克隆一個Yocto專案到本地:

$ git clone git://git.yoctoproject.org/poky

到此為止,你已經得到了一個完整的Yocto專案demo,直接構建該工程,你可以得到一個Linux系統發行版:

  1. 首先你需要初始化構建環境,以此來得到一些重要的環境變數,進入poky目錄,執行命令:source oe-init-build-env build,此時系統會建立一個構建目錄build(該目錄存放整個構建輸出內容,或者可以將其稱作構建環境),並跳轉到該目錄下。

  2. 使用vim開啟build/conf/local.conf檔案(該檔案提供一些全域性配置),增加兩行內容:

BB_NUMBER_THREADS = "4"
PARALLEL_MAKE = "-j 4"

這兩行內容分別是構建器使用的執行緒數,和編譯器(Make)使用的執行緒數,建議設定為小與系統實際能提供的最大執行緒數,否則預設使用最大執行緒數。這樣做的目的是避免執行緒數太多導致記憶體空間不足,以至於構建失敗,或者你也可以開啟交換記憶體來增加記憶體空間避免這一問題,方法見這篇部落格

  1. 現在,你可以開始構建一個映象了,執行命令bitbake core-image-sato,這時你便開始構建一個帶使用者操作介面的Linux系統映象。當然了,大多數情況下,你一定會遇到一些構建錯誤,這時,你可以參考下這篇部落格,或者留言,之後我會盡可能做出回覆。

  2. 如果你成功構建完成,那麼恭喜你,你已經成功了一大半了。現在開始,你可以驗證你構建的映象是否能夠使用,執行命令runqemu tmp/deploy/images/qemux86-64/bzImage-qemux86-64.bin tmp/deploy/images/qemux86-64/core-image-sato-qemux86-64.ext4 。此時,系統將會使用預設引數啟動你剛剛構建的位於build/tmp/deploy/images/qemux86-64/目錄下的作業系統映象,例如你可以看到下面的介面:

Yocto專案介紹及入門 -- 嵌入師工程師必備利器

通過上面的步驟,你已經得到了一個利用poky製作的樣例映象,接下來,我們要為這個映象嵌入一個我們要用的軟體包。
首先,先建立一個自己的層(一般在頂級目錄下,以meta開頭的目錄都叫層,每個層都是獨立的,因此為了避免汙染其他層,我們建立自己的層),進入poky頂層目錄,執行命令mkdir meta-mylayer

對於每個層,都需要有自己層的配置檔案,用於告訴構建器層中菜譜檔案的位置及其他內容,因此我們提供這樣一個檔案,進入meta-mylayer目錄中,新建一個資料夾conf,並在該目錄下新建一個layer.conf檔案,其內容如下:

BBPATH .= ":${LAYERDIR}"
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
            ${LAYERDIR}/recipes-*/*/*.bbappend \
           "

BBFILE_COLLECTIONS += "mylayer"
BBFILE_PATTERN_mylayer := "^${LAYERDIR}/"
BBFILE_PRIORITY_mylayer = "5"

除此之外,我們需要提供helloworld的原始碼包,在meta-mylayer目錄中新建資料夾recipes-apps,並進入該目錄,新建資料夾hello-1.0,在這個資料夾新建三個檔案,內容如下:

Yocto專案介紹及入門 -- 嵌入師工程師必備利器

之後,我們將這三個檔案打包為hello-1.0.tar.gz,並存放到hello-1.0目錄下。

隨後,我們需要設計軟體包菜譜,這個菜譜告訴了構建器從哪裡找包,並如何編譯安裝到映象中,在recipes-apps目錄下新建hello_1.0.bb菜譜檔案,其內容如下:

SUMMARY = "Simple Hello World Application"
DESCRIPTION = "A test application to demonstrate how to create a recipe \
              by directly compiling C files with BitBake."

# a category this package belong to
SECTION = "examples"
# this package is optional, lacking of it doesn't cause error
PRIORITY = "optional"

LICENSE = "MIT"
LIC_FILES_CHKSUM = "\
    file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

SRC_URI = "file://hello-1.0.tar.gz"

# S = "${WORKDIR}"
# fix WARN_QA error
TARGET_CC_ARCH += "${LDFLAGS}"

do_compile() {
    ${CC} -c helloprint.c
    ${CC} -c hello.c
    ${CC} -o hello hello.o helloprint.o
}

do_install() {
    install -d ${D}${bindir}
    install -m 0755 hello ${D}${bindir}
}

最後,我們將這個包新增到映象中,在檔案meta/recipes-sato/images/core-image-sato.bb或者build/conf/local.conf中新增一行內容IMAGE_INSTALL += " hello "。重新構建映象bitbake core-image-sato,測試時,你可以發現多出了一個新的命令hello。

我希望能通過這個簡單的例項讓大家對Yocto有個初步的認識,如果想繼續深入瞭解Yocto專案,可以參照第三節內容學習,另外,你也可以關注我,後續我會不定期的更新這方面的相關知識。

相關文章