來(lái)源:公眾號(hào)【魚鷹談單片機(jī)】,ID ??:emOsprey
Yocto 是什么?很多道友第一次聽到時(shí)估計(jì)都是一臉懵逼。當(dāng)初魚鷹從領(lǐng)導(dǎo)處了解這個(gè)技術(shù)時(shí),完全不知道是什么,只能摸著石頭過(guò)河。
?buildroot辛酸史
在此之前,領(lǐng)導(dǎo)剛剛讓魚鷹學(xué)習(xí)了 buildroot 編譯內(nèi)核鏡像,因?yàn)槲覀冇袀€(gè)老項(xiàng)目的鏡像就是用它編譯的。
以前這些鏡像都是老外維護(hù)(魚鷹目前在世界500強(qiáng)外企,有時(shí)間聊聊在外企這些年學(xué)到了啥,歡迎關(guān)注魚鷹談單片機(jī)),我們只要從指定地址獲取鏡像,用工具燒錄SD卡鏡像就行。
后面領(lǐng)導(dǎo)想國(guó)內(nèi)也能維護(hù)鏡像,能自己編譯鏡像,于是讓魚鷹學(xué)習(xí)鏡像編譯(以前和領(lǐng)導(dǎo)聊過(guò)發(fā)展方向,知道魚鷹想往 Linux 方向發(fā)展,因此給了機(jī)會(huì))。
Buildroot 很多年前魚鷹也了解過(guò),也編譯過(guò),感覺不是特別難,覺得任務(wù)應(yīng)該很快能完成。
但沒(méi)想到,搞了半個(gè)多月才搞定,印象最深刻的就是 2.5 G左右的開源資源下載。以前編譯鏡像時(shí),從來(lái)沒(méi)遇到這些問(wèn)題,都是半天到一天左右就搞定了。
現(xiàn)在想想,有這兩點(diǎn)原因:
1、那些年,github 可以正常上網(wǎng),很多國(guó)外資源都能輕松下載。
2、目前的鏡像依賴的開源庫(kù)太多,也太老了,以前只是為了學(xué)習(xí)Linux內(nèi)核,只要基礎(chǔ)的組件就行。
因此很順利編譯 uboot、內(nèi)核、文件系統(tǒng)(鏡像三大件)。
現(xiàn)在有些資源下載實(shí)在太慢,只能各種找資源,另外從 gitee 中轉(zhuǎn),總算是下載完成了(還好支持離線下載安裝方式)。
但是 qt 這個(gè)功能最終還是沒(méi)裝上,不知道啥原因,因?yàn)椴恢匾蜎](méi)管了。
另外很多資源有指定的 hash 值,你只能下載相同 hash 值的資源,否則即使你修改了 hash 值適配新資源,最終可能導(dǎo)致系統(tǒng)不兼容。
還有 buildroot 環(huán)境本身的安裝也有點(diǎn)麻煩,也需要時(shí)間熟悉。
?Yocto苦難史
后來(lái)轉(zhuǎn) Yocto 開發(fā)后,發(fā)現(xiàn)學(xué)習(xí)難度比 buildroot 上升了十倍,資源(硬盤空間)消耗差不多也是十倍,但是熟悉后,簡(jiǎn)直 TMD 就是為嵌入式而生。
當(dāng)時(shí)自己的 Ubuntu 是 18.04,因?yàn)橛袀€(gè)老項(xiàng)目的編譯需要這個(gè)版本才能正常編譯。
而 Yocto 的推薦系統(tǒng)應(yīng)該是 20.04 以上,最少剩 120 G硬盤空間:
IMX_YOCTO_PROJECT_USERS_GUIDE.pdf
魚鷹不想重裝Ubuntu系統(tǒng)(那個(gè)時(shí)候還不知道用 docker),于是走了一個(gè)岔路,遇到各種軟件不兼容問(wèn)題,比如 gcc (只能下載源碼重新安裝)、python,有些推薦安裝的軟件版本無(wú)法順利安裝。repo 工具本身由于國(guó)內(nèi)網(wǎng)絡(luò)環(huán)境原因,也得使用國(guó)內(nèi)鏡像才順利。
最后生成 SDK 時(shí),又卡在最后一步,沒(méi)找到 dnf 這個(gè)python工具,還好通過(guò)別的命令生成了工具鏈,否則如果卡在編譯鏡像的最后一步,就麻煩大了(后面 docker 解決以上痛點(diǎn))。
bitbake meta-toolchain
總之,問(wèn)題很多。幾天時(shí)間,雖然開發(fā)環(huán)境問(wèn)題解決了(有了docker,半天不用就能搞定),但是和 buildroot 一樣,下載問(wèn)題又遇到了,這次更狠,直接 30 G 資源下載(因?yàn)閲?guó)內(nèi)基本不使用 Yocto,即使用,imx6ull 居多,所以很難找到合適的)。
搞得魚鷹一點(diǎn)脾氣也沒(méi)有,只能向供應(yīng)商求助,拿到了他手里提前下載好的資源。
這樣資源齊全了,終于可以開始編譯了。
編譯過(guò)程還算正常,只是相比 buildroot,編譯賊慢,資源消耗極大(非常簡(jiǎn)單的一個(gè)進(jìn)程,可能需要幾百 M 資源,這也能看出為啥整個(gè)鏡像需要100多G空間了)。
這里有個(gè)賊好用的命令,可以在出現(xiàn)錯(cuò)誤時(shí),不會(huì)立即打斷,繼續(xù)運(yùn)行其它任務(wù)。
bitbake?xxx?-k
另外推薦一個(gè)Yocto入門視頻:B站:iMX6ULL采用Yocto構(gòu)建嵌入式Linux系統(tǒng)
總之開發(fā)環(huán)境搭建、資源提前下載好后,編譯也算相當(dāng)順利了。
三大件一個(gè)不缺,同時(shí)還能生成 SD 卡鏡像。
為什么 Yocto 這么難學(xué),資源消耗這么大,還是這么多大廠都在用?
比如 NXP、BMW、Amazon 、Facebook (Meta)、 General Electric 等。
對(duì)于現(xiàn)代計(jì)算機(jī)而言,資源消耗已經(jīng)不是大問(wèn)題,可維護(hù)性、靈活性、定制性、兼容性、生態(tài)才是首先要考慮的問(wèn)題。而這些 Yocto 都具備了。
靈活性和定制性:Yocto項(xiàng)目提供了靈活的工具集和開發(fā)環(huán)境,允許開發(fā)者自由選擇資源的使用,或者完善特定的組件(包括這些組件的特定版本)。這種靈活性使得開發(fā)者可以根據(jù)自己的需求定制Linux發(fā)行版,從而滿足特定硬件平臺(tái)的需求。
避免重復(fù)工作:Yocto項(xiàng)目鼓勵(lì)跨各種應(yīng)用程序和設(shè)備類型的創(chuàng)新,支持多種硬件架構(gòu),如x86、ARM、RISC-V、PPC和MIPS等。通過(guò)共享技術(shù)、軟件堆棧、配置和最佳實(shí)踐,Yocto項(xiàng)目幫助開發(fā)者避免從零開始,減少重復(fù)工作和不必要的維護(hù)。
強(qiáng)大的構(gòu)建系統(tǒng):Yocto項(xiàng)目的核心是BitBake,這是一個(gè)高效的任務(wù)調(diào)度器和執(zhí)行系統(tǒng),能夠處理復(fù)雜的依賴關(guān)系,并優(yōu)化構(gòu)建過(guò)程。BitBake能夠確保構(gòu)建任務(wù)按正確的順序執(zhí)行,從而提高構(gòu)建效率和可預(yù)測(cè)性。
豐富的生態(tài)系統(tǒng):Yocto項(xiàng)目擁有一個(gè)活躍的社區(qū)和豐富的文檔資源,這為開發(fā)者提供了強(qiáng)大的支持。社區(qū)成員包括硬件制造商、操作系統(tǒng)供應(yīng)商和獨(dú)立顧問(wèn),他們共同為項(xiàng)目貢獻(xiàn)資源和信息,形成了一個(gè)強(qiáng)大的生態(tài)系統(tǒng)。
標(biāo)準(zhǔn)化和兼容性:Yocto項(xiàng)目提供了標(biāo)準(zhǔn)化的構(gòu)建流程和工具,這有助于不同開發(fā)者和團(tuán)隊(duì)之間的協(xié)作。通過(guò)使用Yocto項(xiàng)目,開發(fā)者可以確保他們的定制Linux系統(tǒng)在不同硬件平臺(tái)上具有高度的兼容性和可移植性。
優(yōu)化的資源利用:Yocto項(xiàng)目允許開發(fā)者精確地創(chuàng)建嵌入式設(shè)備所需的內(nèi)容,只需添加設(shè)備絕對(duì)需要的功能支持或包。這有助于優(yōu)化系統(tǒng)性能,減少不必要的資源占用,從而為嵌入式和物聯(lián)網(wǎng)設(shè)備提供更高效的解決方案。
可維護(hù)性和可擴(kuò)展性:Yocto項(xiàng)目的設(shè)計(jì)允許用戶使用自主開發(fā)的操作系統(tǒng)或商業(yè)操作系統(tǒng),在遷移時(shí)不會(huì)丟失優(yōu)化或功能。此外,商業(yè)操作系統(tǒng)也可以使用Yocto項(xiàng)目作為上游資源,從而確保最大化代碼重用。
支持多種構(gòu)建目標(biāo):Yocto項(xiàng)目不僅可以用于創(chuàng)建Linux發(fā)行版,還可以為裸機(jī)開發(fā)生成實(shí)時(shí)操作系統(tǒng)(RTOS)工具鏈,如Zephyr項(xiàng)目所做的那樣。
以上是 AI 給出的答案。
下面再結(jié)合魚鷹實(shí)際開發(fā)經(jīng)驗(yàn)談?wù)劄樯?Yocto 大法好。
1、開發(fā)環(huán)境
docker 技術(shù)解決了環(huán)境搭建問(wèn)題,因此環(huán)境搭建不再是問(wèn)題。
年少不知docker好
2、可以編譯各種代碼
我們知道,一個(gè)項(xiàng)目,涉及到各種編程語(yǔ)言,比如 C/C++、Python、Java 等,涉及各種平臺(tái),比如 u-boot、Linux、MCU、qt,各種架構(gòu)?,arm、risc-v,x86 等,而 Yocto 可以把這些代碼都編譯好,放在一個(gè)壓縮包里面,直接拿就行了。
而且同一套 meta,可以輕松編譯?x86 和 arm,這樣在沒(méi)有arm板的情況下也能進(jìn)行一些開發(fā)調(diào)試工作,自動(dòng)化測(cè)試也更容易。
3、支持 qemu 調(diào)試
原生支持 qemu 調(diào)試,不過(guò)這一塊魚鷹沒(méi)搞太懂,搞懂了,對(duì)開發(fā)效率又是一大提高了。
4、定制化
重點(diǎn)來(lái)了,估計(jì)這個(gè)才是各個(gè)大廠喜歡 Yocto 的原因。
很多時(shí)候,我們的工作是建立在別人的基礎(chǔ)上,比如我想在 ubuntu 里面加一個(gè) qt 界面。
這個(gè)時(shí)候,如果已經(jīng)有現(xiàn)成的 Ubuntu,那搞個(gè) qt 就簡(jiǎn)單許多了。
同理類似,Yocto 項(xiàng)目里面有很多Linux發(fā)行版,包含各種組件(可能有幾百上千個(gè)),完全可以自主添加或刪除某些組件,并且這些組件版本也有社區(qū)負(fù)責(zé)維護(hù)更新。
比如某個(gè)工具 vim 的某個(gè)版本,需要 Linux 內(nèi)核某個(gè)版本以上才行,這些常用工具的兼容性,都會(huì)被處理好,你只要下載一個(gè)poky(Yocto的參考實(shí)現(xiàn))發(fā)行版,指定某個(gè)版本,就能編譯出整個(gè)鏡像(就是下載的時(shí)候,可能又要花一些時(shí)間了,因?yàn)榭赡芤蕾嚨慕M件版本不同,需要重新下載)。芯片廠家也會(huì)在這些基礎(chǔ)上,添加自己的特殊化定制。
另外除了整個(gè)鏡像的特殊化定制,單個(gè)組件,單條代碼都能修改。
最常用的,比如修改設(shè)備樹、內(nèi)核代碼、驅(qū)動(dòng),這些都會(huì)以補(bǔ)丁的形式添加到基礎(chǔ) Linux 代碼中(不會(huì)修改源碼)。
而如果要升級(jí) Linux 內(nèi)核到最新版本,也非常容易,一般 poky 會(huì)同步最新內(nèi)核,同時(shí)會(huì)把依賴的組件一并升級(jí),這樣在你的項(xiàng)目修改可能就只是一個(gè) Poky 的一個(gè)commit 修改而已(如果修改了內(nèi)核代碼,可能需要同步修改一下),但是那些組件,比如 vim、nano、ssh 等工具會(huì)同步升級(jí),不需要你關(guān)心。
Yocto生成的鏡像也有多種選擇,比如
core-image-minimal:這是一個(gè)非常基礎(chǔ)的鏡像,包含必要的系統(tǒng)工具和Linux內(nèi)核,適合作為定制更復(fù)雜系統(tǒng)的基礎(chǔ)
core-image-sato:這是一個(gè)為桌面環(huán)境優(yōu)化的標(biāo)準(zhǔn)鏡像,包含了更多的軟件包和工具,適合用于桌面或展示設(shè)備
core-image-full-cmdline:這個(gè)鏡像包含了完整的命令行工具集,但不包含圖形界面,適合需要完整命令行環(huán)境的嵌入式設(shè)備
core-image-multimedia:這個(gè)鏡像包含了多媒體相關(guān)的軟件包,適合需要音頻和視頻處理能力的設(shè)備
你可以選擇在這些鏡像基礎(chǔ)上添加自定義的功能。
并且如果有些組件代碼,你不喜歡,也可以隨時(shí)修改,這種修改不會(huì)修改源碼,而是以補(bǔ)丁的形式修改到另一個(gè)編譯環(huán)境中,這樣可以保證源碼的純粹。
5、項(xiàng)目實(shí)用性
你有一塊 Linux 板子V1,根據(jù)當(dāng)前硬件適配了代碼,發(fā)現(xiàn)有些問(wèn)題,需要改硬件,變成 V2,另外可能還有其它 MCU 的代碼也需要同步修改,而老版本板子也有在用。
如何處理這些依賴問(wèn)題。
古老的方法是,人工維護(hù)兩個(gè)環(huán)境依賴差異,高級(jí)一點(diǎn)通過(guò)腳本或者 repo 工具維護(hù)。
而 yocto 借助 kas 工具,可以完美處理這種情況,meta 倉(cāng)庫(kù)里面同一個(gè)分支可以同時(shí)擁有兩款板子的信息,只要在編譯前,setup 自己需要的機(jī)器類型就可以把對(duì)應(yīng)的依賴處理好,再也不會(huì)出現(xiàn)Linux 和 mcu 不兼容情況了。
而且使用 kas 可以在 V1 的基礎(chǔ)上進(jìn)行 V2 的差異修改,只要把差異加上就行,避免重復(fù)造輪子,或拷貝或切分支。
6、SDK
可以輕松生成各種SDK,安裝后適用于上層應(yīng)用開發(fā),而不需要占用太多空間,這樣不會(huì)因?yàn)橐粋€(gè)小小的功能而安裝整個(gè) Yocto 開發(fā)環(huán)境了。
標(biāo)準(zhǔn)SDK(Standard SDK):這種SDK包含了用于應(yīng)用程序開發(fā)的工件,無(wú)論是引導(dǎo)加載程序、Linux內(nèi)核開發(fā),還是其他用戶空間軟件。它提供了一個(gè)交叉開發(fā)工具鏈和庫(kù),這些工具和庫(kù)是針對(duì)特定圖像優(yōu)化的。你可以使用標(biāo)準(zhǔn)SDK獨(dú)立開發(fā)和測(cè)試代碼,這些代碼旨在運(yùn)行在某個(gè)目標(biāo)機(jī)器上。
可擴(kuò)展SDK(Extensible SDK):除了包含標(biāo)準(zhǔn)SDK的所有功能外,可擴(kuò)展SDK還提供了工具,允許你輕松地向圖像中添加新的應(yīng)用程序和庫(kù),修改現(xiàn)有組件的源代碼,在目標(biāo)硬件上測(cè)試更改,并輕松地將應(yīng)用程序集成到OpenEmbedded構(gòu)建系統(tǒng)中??蓴U(kuò)展SDK安裝在任何機(jī)器上,并且可以用來(lái)開發(fā)應(yīng)用程序、圖像和內(nèi)核。
本地SDK(Native SDK):這種SDK的目標(biāo)是在目標(biāo)設(shè)備上運(yùn)行,適用于那些功能足夠強(qiáng)大的嵌入式設(shè)備,可以作為開發(fā)環(huán)境使用的情況。本地SDK包括頭文件、庫(kù)和工具鏈,允許在目標(biāo)設(shè)備上直接進(jìn)行應(yīng)用程序的開發(fā)和測(cè)試。
交叉開發(fā)SDK(Cross-development SDK):這種SDK用于在開發(fā)主機(jī)中生成目標(biāo)機(jī)器的二進(jìn)制文件。它包含了交叉編譯工具鏈、庫(kù)、頭文件和二進(jìn)制文件,以及可能的其他實(shí)用程序和應(yīng)用程序。
這才是真正的大雜燴,包含了嵌入式軟件所需的資源,開發(fā)、編譯、調(diào)試,全給你考慮好了,你值得擁有。
7、生態(tài)
有很多meta開源,拿來(lái)就能用,很多芯片廠商也有適配 Yocto 環(huán)境,擁有眾多開發(fā)者維護(hù) Yocto,生態(tài)好。
最后在聊聊缺點(diǎn)
1、資源消耗大(每個(gè)任務(wù)都有單獨(dú)的編譯環(huán)境)。
2、開始編譯時(shí)速度非常慢,因?yàn)樗枰谥鳈C(jī)上編譯各種工具。
3、入門困難,學(xué)習(xí)曲線陡峭,但適合復(fù)雜項(xiàng)目的維護(hù)工作。
4、資源嵌套深,不容易找,也不容易理解編譯過(guò)程。