寫在前面
博主目前從事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官網:
在上面圖中,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系統發行版:
-
首先你需要初始化構建環境,以此來得到一些重要的環境變數,進入poky目錄,執行命令:
source oe-init-build-env build
,此時系統會建立一個構建目錄build(該目錄存放整個構建輸出內容,或者可以將其稱作構建環境),並跳轉到該目錄下。 -
使用vim開啟build/conf/local.conf檔案(該檔案提供一些全域性配置),增加兩行內容:
BB_NUMBER_THREADS = "4"
PARALLEL_MAKE = "-j 4"
這兩行內容分別是構建器使用的執行緒數,和編譯器(Make)使用的執行緒數,建議設定為小與系統實際能提供的最大執行緒數,否則預設使用最大執行緒數。這樣做的目的是避免執行緒數太多導致記憶體空間不足,以至於構建失敗,或者你也可以開啟交換記憶體來增加記憶體空間避免這一問題,方法見這篇部落格。
-
現在,你可以開始構建一個映象了,執行命令
bitbake core-image-sato
,這時你便開始構建一個帶使用者操作介面的Linux系統映象。當然了,大多數情況下,你一定會遇到一些構建錯誤,這時,你可以參考下這篇部落格,或者留言,之後我會盡可能做出回覆。 -
如果你成功構建完成,那麼恭喜你,你已經成功了一大半了。現在開始,你可以驗證你構建的映象是否能夠使用,執行命令
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/目錄下的作業系統映象,例如你可以看到下面的介面:
通過上面的步驟,你已經得到了一個利用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,在這個資料夾新建三個檔案,內容如下:
之後,我們將這三個檔案打包為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專案,可以參照第三節內容學習,另外,你也可以關注我,後續我會不定期的更新這方面的相關知識。