以前的文章:《一次搞定交叉編譯》 給你們講了如何安裝交叉編譯工具鏈,搭建交叉編譯環境。linux
這篇文章主要教你們如何正確的去編譯 Linux Kernel、U-Boot 這些著名的開源軟件。shell
也許不少同窗會說:編譯是小 case 啊,我都 make 過成千上萬次了!網絡
但是你是否有思考過,你編譯的時候每個步驟、執行的每個命令.....架構
它背後隱藏的原理是什麼?工具
爲何要這麼作?flex
你的方法是最高效最科學的嗎?ui
你的方法是否潛藏着漏洞?搜索引擎
換一個環境、換一個平臺,若是編譯的過程當中遇到了莫名其妙的錯誤,你是否知道從哪裏去找突破口?spa
這就是這篇文章要告訴你的。命令行
仍是以 i.MX 的內核爲例。
其實過程很簡單,基本上兩個命令搞定:
make ARCH=arm imx_v7_defconfig make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
第一個命令是配置,第二個命令是編譯。
可是這背後卻隱藏着不少小細節須要咱們去注意。
配置內核的命令是 make ARCH=chiparch xxx_defconfig
,第一個參數 ARCH=chiparch 用來指定芯片的架構,第二個參數 xxx_defconfig 用來指定此次編譯對應的配置文件,好比針對 i.MX六、i.MX7 這些芯片的 Linux Kernel,配置命令是這樣的:
make ARCH=arm imx_v7_defconfig
若是編譯 i.MX8 相關的內核的話,配置命令大概是這樣的:
make ARCH=arm64 defconfig
這個命令會從指定的 defconfig 文件裏面加載配置,寫入到 .config 文件中。內核編譯的時候就是根據 .config 文件的內容來決定哪些模塊編譯,哪些模塊不編譯的。
make 後面的兩個參數是怎麼來的?
由於 Linux Kernel 支持大量不一樣架構的芯片、好比 arm、arm6四、x8六、mips、risc-v 等等,還支持成千上萬的功能特性,在編譯的時候咱們並不須要把內核支持的全部芯片和功能都編譯進去,這樣編譯出來的內核鏡像會很是的龐大。並且 Kernel 中有至關一部分代碼是針對特定架構的,好比啓動階段的初始化代碼、每一個架構都有本身特定的設置,這部分代碼大部分是彙編寫的,並且相互不兼容:
因此,Linux 內核提供了 defconfig 機制 ,開發者們能夠根據本身的芯片、開發板特性本身決定內核中哪些功能須要打開,哪些功能能夠關閉,生成一個和本身硬件相關的 defconfig 文件,下次編譯的時候加載。這些 defconfig 文件放在 arch/chiparch/configs 下面:
因此在配置的時候,咱們須要指定具體的 ARCH、Kernel 的 Kbuild 系統才能在對應的目錄下找到你指定的 defconfig 文件。若是沒有指定 ARCH、通常默認會去 x86 目錄下去找。
由於 i.MX六、 i.MX7 是 Arm32 ,因此對應的 ARCH 爲 arm,i.MX8 是 Arm64,因此對應的 ARCH 爲 arm64.
另外須要說明一點的是,你們能夠看到 arm 和 mips 目錄下 defconfig 文件很是多,而比較新的一些架構,好比arm64,risc-v 目錄下,只有惟一的一個 defconfig 文件,這和 Linux Kernel 目前的開發風格轉變有關:再也不鼓勵你們提交一堆亂七八糟的 defconfig 文件, 儘可能只使用一個通用的 defconfig 文件,這裏面儘可能打開內核啓動須要的模塊,而對內核啓動影響不大的模塊,以模塊的形式編譯。在這個設計思想下,Arm32 下面有一個通用的 multi_v7_defconfig, Arm64 和 risc-v 對應的 defconfig 文件名都叫作 defconfig。因此若是如今你想爲一個新的芯片提交它本身的 defconfig 文件到 mainline 分支,是不會被接受的,Linux 社區的 Maintainer 會告訴你,把你須要打開的特性加到通用的 defconfig 裏面。
固然,咱們在本地作開發的時候,通常不會這樣玩,咱們仍是會根據本身的芯片和特定產品形態,建立獨立的 defconfig 文件,這樣方便深度裁剪。
這個配置文件是如何生成的呢?
咱們通常在一個現有配置文件的基礎上,根據產品需求,經過 make menuconfig
命令加減配置,而後再經過 make savedefconfig
命令生成新的配置文件:
好比我須要打開 drivers/gpu/drm/imx/dw_hdmi-imx.c
這個 HDMI 驅動,經過查看該 C 文件同目錄下 Makefile,能夠發現它依賴 DRM_IMX_HDMI
這個配置項:
make ARCH=arm menuconfig
對於對內核還不怎麼熟悉的同窗來講,如何找到 DRM_IMX_HDMI
這個配置的位置呢?別急,menuconfig 界面也是能夠搜索關鍵字的:
按 / 鍵,就是 ? 下面那個鍵,會彈出下面的界面:
而後在選擇框裏面輸入要查找的關鍵字,敲 Enter 就會出現結果:
這裏只有一個匹配的選項,因此咱們直接在鍵盤上按 1 鍵,就會跳到對應的選項開關處:
而後打開對應的選項便可,<*> 號表示直接編譯進內核,<M> 表示以模塊的方式編譯,< > 則表示不編譯。
按 ↑ ↓ 上下移動光標,按 ← → 光標在最下面左右移動。
配置完成後選 <Exit> 退出。這時候能夠看到 DRM_IMX_HDMI
這個選項的配置已經生效了:
而後執行 make savedefconfig
命令,生成新的配置文件,並用該文件覆蓋舊文件。
有人可能會疑問,爲何要用 make savedefconfig
來生成一箇中間的 defconfig 文件呢,直接用 .config 去覆蓋不是也能夠嗎?
答案是: make savedefconfig
命令生成的 defconfig 文件更精簡,更易讀。
編譯內核
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
這是最通用的編譯內核的命令,第一個告訴內核要編譯 arm 架構,第二個參數指定用什麼交叉編譯工具去編譯。編譯成功的結果大概是這樣的:
最終編譯後的鏡像是壓縮過的 zImage。
同時全部的 dts 文件也會被編譯成 dtb。
固然,若是爲了編譯的快,咱們還能夠啓動並行編譯,好比:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j8
就是同時有 8 個編譯進程在運行,並行數目設置多少最合適,這個通常取決與你用來編譯的電腦有多少 CPU,以及內存夠不夠大,通常數據能夠設置的和 CPU 個數相等,或者 2 倍。
有人會說,爲何我看到的有些開發板的編譯說明文檔和這個不太同樣,好比下面這個:
這是由於,部分廠家的Kernel,爲了知足本身的固件升級設計,作了一些特殊的打包和修改,你雖然看到的編譯命令不同了,其實他們都是基於最基本的編譯命令作的封裝定製。
它在 Makefile 裏面指定了 ARCH 和 CROSS_COMPILE, 因此make 的時候就不須要指定這兩個參數了。
而後經過這個修改,當開發者執行 make xxx.img 這種模式的命令的時候,會自動編譯 zImage,並經過mkkrnlimg 這個命令對 zImage 打包生成 kernel.img。 而且對經過 resource_tool 這個命令對 dtb 也進行了打包。
Linux Kbuid 系統還執行不少其餘的 make 命令,能夠經過 make help 來查看:
U-Boot 的編譯步驟和 Linux Kernel 很是相似,也是兩步:
make mx6ull_14x14_evk_defconfig make CROSS_COMPILE=arm-linux-gnueabihf-
惟一的差異是,U-Boot 在編譯的時候不須要指定 ARCH 選項,這是 U-Boot 的編譯系統相比 Linux Kbuid 的要給改進點。其實目前最新的 U-Boot 編譯系統也是基於 Linux Kbuild 設計的,一樣支持 make menuconfig 命令,有對應的 defconfig 文件,在 configs 目錄下。
另一個區別是,U-Boot 也有本身的 dtb,可是最終編譯完的 U-Boot 會和 dtb 合併在一塊兒。
咱們在編譯軟件的時候,常常會遇到各類奇奇怪怪的報錯,有些是軟件自己有 Bug(對於 Linux Kernel、U-Boot 這類比較知名的開源項目,這種Bug 比較少見)、有些是由於編譯環境裏面缺乏一些依賴工具(這種狀況很常見)。
對於剛接觸的新人來講,一條 make
命令敲下去,發現蹦出來一堆莫名其妙的錯誤,是很使人沮喪的。
可是不要怕,雖然你是新人,這也不要緊,由於如今是互聯網時代,對於那些普遍使用的開源項目,你踩到的坑基本都有不少人踩到過,並且這個世界有那麼多樂於分享的人:他們遇到問題,勇敢的去分析,尋求解決方法,而後分享出來,他們是這個數字世界的熱和光。
因此,若是你遇到一個本身能看得懂搞得定的問題,那很簡單,直接去搞定便可,而後若是你樂意,能再寫一篇分享心得就更好了。若是你遇到了一個像天書同樣,本身徹底看不懂的報錯,也沒關係,最實用的解決方案就是:直接把這個錯誤複製出來,粘貼到你的搜索引擎裏,點下下一步,開始搜索便可,一條條耐心的去看,通常運氣都不會太差。
固然,搜索引擎的選擇也是一門學問,若是你用到是百度,能搜到答案最好,若是搜不到,你還能夠試試 Bing、Stackoverflow、Github、若是你能用 Google,那就更好了。
相信我,這個方法能解決你所遇到的大部分問題。
好比 我在執行 make ARCH=arm imx_v7_defconfig
就提示 failed 了:
仔細分析這個日誌,咱們會發現最開始有這樣一個異常提示:/bin/sh: 1: bison: not found
通常在分析異常的時候,比較有效的方法是找到最開始報出異常的地方,先解決掉,而後再看是否是最終問題被解決掉了,其實大部分時候都是這樣的,把最早冒頭的問題解決掉,後面全部的問題都被打掉了。
若是你能看懂這個異常提示,其實你會發現它是說 shell 在執行 bison 這個命令的時候,發現這個命令找不到。
試試在命令行執行下 bison
這個命令,會發現以下提示:
而後按照提示 sudo apt install bison
安裝便可解決。
若是你看不出來,也不要緊,用前面提到的終極解決方案,直接把這條提示覆制到百度裏搜搜看:
運氣比較好,太多人和我踩了一樣的坑,前三條鏈接任意打開一個,點進去都能找到答案:
sudo apt install bison
安裝完後再次執行 make ARCH=arm imx_v7_defconfig
,bison 的報錯沒了,但是又蹦出來另一個錯誤:
和前面同樣,仍是直接 複製——》粘貼——》搜索:
踩坑的不止我一個啊,打開任意一個連接,就能找到解決辦法:
sudo apt install flex
而後再次執行 make ARCH=arm imx_v7_defconfig
,終於成功了。
而後執行 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
開始編譯, 發現又報錯了:
直接用前面提到的三部曲:複製——》粘貼——》搜索:
打開這些連接,你會找到答案:
sudo apt install libssl-dev
再次開始編譯,好不容易編譯到最後,又挑出來一個錯誤:
相信到這裏你已經知道該怎麼作了,沒錯,仍是 複製——》粘貼——搜索:而且你會很快找到解決問題的方法:
sudo apt-get install lzop
繼續編譯,終於成功了:
其實這篇文章與其說是講述 Linux Kernel 和 U-Boot 的編譯步驟,不如說是告訴你們一種在開發過程當中,遇到本身不懂的問題,如何去利用網絡來尋找答案的方法,但願能給你一點啓發。
更多原創請掃碼關注公衆號:HackforFun