在Gentoo下交叉編譯 “Sometimes it pays to stay in bed in Monday, rather than spending the rest of the week debugging Monday’s code. “ – Dan Salomon 前幾天攬了個“髒活”,交叉編譯raspbian的檔案系統鏡像。好久沒幹過這麼繁瑣的 事了,寫篇日誌分享一下gentoo下如何更好的解決交叉編譯問題。 www.2cto.com 嵌入式系統的編譯環境為某個平台開發軟體,首先需要一個編譯環境。一般來說,編譯環境包括三部分:工具 鏈/運行環境/編譯方法。對於嵌入式系統來說,常見的編譯環境有三種: 本地環境。如很流行的Ubuntu for ARM,利用官方製作好的目標機鏡像(通常包含了 編譯環境),直接在目標機上編譯/安裝軟體,與PC機開發完全一樣。這種方法簡單省 事。缺點也顯而易見,編譯速度慢,耗時間長度,特別是較大的軟體包(如xbmc)的時候, 程式員不是停下來喝杯咖啡就可以收攤,恐怕得打場通宵dota後才能看到結果 了…(或許distcc能有所改善) 虛擬環境。在PC上建立目標機的虛擬環境,如QEMU-ARM,然後chroot到虛擬環境 中編譯/安裝軟體。這種方法利用了PC的處理能力,速度比本地環境要快得多,但 QEMU並不能完美的類比目標機環境,如不支援某些系統調用等,這可能導致它不能 正確的編譯某些軟體。 交叉編譯。為目標機交叉編譯軟體,這是最常規的辦法,也是上面兩種方法實現的基 礎。說交叉編譯是“髒活”,是因為需要手工解決軟體包的所有依賴問題,手工編譯 每一個軟體包,並且解決軟體包對目標機相容問題… 看網上鋪天蓋地關於求教/指導 某個軟體包如何正確交叉編譯就知道,有多少程式員在被它虐? gentoo下的交叉編譯gentoo是一個metadistribution,從原始碼構建整個系統,同時支援很多不同的體 系如alpha/arm/hppa/ppc/sh/sparc/s390等,也為交叉編譯提供了便利的工具,這是 其它二進位發行版沒有辦法比擬的(scratchbox也顯得弱爆了)。 gentoo下的交叉編譯通過crossdev和portage來實現。portage帶來的好處是自 動解決依賴和自動升級更新系統,跟本機環境一樣。 製作工具鏈crossdev用來製作交叉工具鏈,並且還提供了交叉編譯環境下的emerge的輔助指令碼。如 下編譯arm平台的工具鏈: $ sudo crossdev -t arm-supertux-linux-gnueabi這樣,crossdev最終製作了符合“gentoo規範”的arm交叉編譯器。 運行環境crossdev產生/usr/arm-supertux-linux-gnueabi/目錄作為目標系統 $buildroot。編譯後產生的目標會被emerge到$buildroot,編譯時間依賴的環境(如 連結庫/標頭檔/pkgconfig等)也都在$buildroot。 交叉編譯有了工具鏈/運行環境,使用的crossdev封裝過的emerge,就可以自由的emerge了。 如交叉編譯bash: $ sudo emerge-arm-supertux-linux-gnueabi -avu bashporage會自動把bash的依賴如ncurses/readline一起emerge到$buildroot。 交叉編譯就是變得如此簡單… 碰到的問題站在巨人的肩膀上可以看的更遠,前提是我們先要爬上巨人的肩膀。portage是一個快 速更新迭代的系統,並不完美,維護者沒有辦法測試每個軟體包的所有相容性。所以, 當你想安裝一個圖形環境如$emerge -avu enlightenment時,很可能會出現錯誤。但 portage提供了細粒度的控制協助解決這樣的問題。下面是我碰到過一些情形和解決方 法: 由於軟體包的環境變數引起的問題,如連結庫指向了/usr/bin,而非 $buildroot。可以配置$buldroot/etc/portage/env/目錄下相應的文 件,portage會自動source該檔案,從而改變編譯時間的環境。 portage沒有包含該軟體或portage自身的bug引起,如預設使能了某個在目標機 平台不能使用的特性。建立一個針對目標機的overlay,自己編寫相應軟體包的 ebuild檔案指導portage進行交叉編譯。 當某個軟體包分階段編譯時間,如perl編譯時間先產生miniperl,通過miniperl最 後產生perl目標映像。由於miniperl被交叉編譯器產生目標機的映像,正常情況 下不能主機環境中繼續運行產生最終的目標映像。這就要藉助qemu-arm+binfmt模 擬目標機環境,讓miniperl在主機環境中也能無縫的運行。 從形式上看,處理上面幾種情況,也是“髒活”。不僅需要瞭解該軟體包的編譯環境, 還需要瞭解portage的原理,還要知道ebuild的書寫文法。但是,與傳統的交叉編譯 方式比起來,這是一勞永逸的工作,別人使用我的運行環境和overlay,即不需再做什 麼就能產生最終的目標機系統。 三年前,使用以上的方法上製作了gentoo+xserver+enlightenment的目標機系統,並 在mini2440的開發板上運行起來。這種方法也大大減少了編譯目標機系統中200+的軟 件包的編譯時間和維護工作量。