建立編譯環境 (Cross Compiler)

建立基本的 OpenWRT 程式編譯環境

Cross Compiler 的建立

為了在 OpenWRT 上執行所設計的程式,我們需要建立 cross-compiler (toolchain) 來進行程式的編譯,為了建立此環境,我們選用 Ubuntu 12.04 以及 Ubuntu 16.04 作為 VM 的作業系統,並按照官網的步驟,建立 cross-compiler 的環境。詳細的步驟可以參考:

(1) 在安裝好 Ubuntu 的 VM 上,一開始先取消 SED 的功能

$ unset SED

(2) 安裝需要的程式

$ sudo apt-get install build-essential subversion git-core libncurses5-dev zlib1g-dev gawk flex quilt libssl-dev xsltproc libxml-parser-perl mercurial bzr ecj cvs unzip

(3) 下載 OpenWRT 的環境。對於 AR300M 而言,這裡相對應的版本為15.05 branch (Chaos Calmer)。要注意的是,由於 Chaos Calmer 已不在主專案 (openwrt.git) 中, https://dev.archive.openwrt.org/wiki/GetSource 的指令是錯誤的。

$ git clone -b chaos_calmer git://github.com/openwrt/chaos_calmer.git

對於 AR750S,要下載 18.06 版的 OpenWRT,指令如下:

$ git clone git://github.com/openwrt/openwrt.git

由於一開始此操作文件是對 AR300M 製作,所以會以 Chaos Calmer 的版本為主。對於 AR750S 而言 (18.06),以下提及 chaos_clamer 的資料夾都會變成 openwrt,此資料夾的名稱和GIT專案中名稱一致。

在使用 git 時,-b 指定不同的分支,而後面的網址代表不同專案。考慮到版本不斷演進,通常 openwrt.git 中只有最新的方案。

[2022 更新] 18.06 版本的指令改成:

git clone -b openwrt-18.06 https://github.com/openwrt/openwrt.git

和之前指令有兩個差別: 加入 branch name, git 只支援 https

(4) 透過 git 取得 OpenWRT 的資料後,會產生一個相對應的資料夾 (chaos_calmer),在此,先更新 OpenWRT 的對應檔案:

$ cd chaos_calmer
$ ./scripts/feeds update -a
$ ./scripts/feeds install -a

如果遇到下列錯誤:fatal: unable to access 'https://my.git.com:port/user_name/project.git/': server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none

可以使用指令:export GIT_SSL_NO_VERIFY=1

來源:https://cynthiachuang.github.io/Git-Https-Server-Certificate-Verification-Failed-Solution/

(5) 接著,開始安裝 (make) 的準備

make menuconfig

Your display is too small to run Menuconfig!

It must be at least 19 lines by 80 columns.

make: *** [menuconfig] Error 1

這裡會一個錯誤訊息,似乎是VM的螢幕顯示尺寸問題,由於需要開起圖形化介面,當使用VirtualBox進行操作時,顯示的解析度無法調動。因此,設定介面無法正確顯示。

在這邊我的解決方案為透過putty登入該VM,方法為:

  1. 設定 NAT 網路,進行 port-port 的轉換。經過設定後,將12422 port 對應於 VM 的 22 port。

  2. 利用 putty 登入 VM (127.0.0.1:12422)。

這邊檢查了一下使用的晶片和 WiFi AP 所使用的晶片是否一致。在 OpenWRT 下查詢晶片內容的方法為: cat /proc/cpuinfo,透過指令,以AR-750S為例,我們可以看到如下的硬體資訊列表:

在系統資訊中,最重要的就是晶片組的資訊,AR-750S使用沒 Qualcomm QCA956X 的晶片,此處的規格必須和上述 menuconfig 的 Target System 設定一致。

記得在 Build the OpenWrt SDK 的選項不要包含,此介面也可以用以編輯燒錄時要使用的 OpenWRT 映像檔,不過目前並未測試此功能。

在安裝 OpenWRT 18.06 時,改用 Ubuntu 16.04 64bit 版本,就沒有顯示的問題,應該是 Ubuntu 12.04 的問題。只是要注意硬碟空間,在安裝時,我使用 20G 的硬碟空間,裝完後剩下不到 1G。使用 10G 的空間則會在make時出錯 (沒有足夠空間)。

(6) 執行 OpenWRT 的安裝,耗時數小時,安裝好占約 3GB 的硬碟空間 (chaos calmer)

$ make

此指會依序安裝不同的功能,安裝完後會顯示以下資訊:

(7) 完成後,cross-compiler 已經完成。在執行編譯前,我們需要預先宣告編譯環境,將 cross compiler 所在的資料夾加入 PATH 環境變數,將環境變數 STAGING_DIR 定義為資料夾 staging_dir 的所在路徑。指令如下:

$ export PATH=$PATH:~/chaos_calmer/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/
$ export STAGING_DIR=~/chaos_calmer/staging_dir/

export PATH=$PATH:~/dir/這個指令是把之後的資料夾加入PATH的路徑中,也就是產生一個開啟的捷徑,讓我們可以在家目錄下開啟 mips compiler,每一次安裝好後,路徑可能都不太一樣,舉例來說,18.06的路徑為: ~/openwrt/staging_dir/toolchain-mips_24kc_gcc-7.3.0_musl/bin/。對於不同版本的安裝,記得用TAB檢查一下安裝目錄。

這些設定每次重開機都必須重新執行。可以將此指令存入文件中,例如: initial_exp.sh。可以透過 source initial_exp.sh 來載入這些設定。或是寫入~/.bashrc 中,開機自動執行。

(8) 設定完成之後,在任意資料夾輸入 mips 之後,按兩下 TAB 鍵,應該會出現各種 cross-compiler,如下圖顯示:

(9) 進行 hello_world 的簡單測試

編譯好的 hello_world 不能在 Ubuntu 上執行,但是可以在 OpenWRT 系統上執行。透過 winscp,我們可以將編譯好的檔案移到 OpenWRT 平台上執行,結果顯示於下圖中。

Winscp 提供 Linux 和 Windows 之間的檔案傳送的圖形化介面,使用上只需要填入 IP 以及 port (通常為22),就可以透過圖形化介面傳輸檔案。請參考: https://winscp.net/eng/download.php

考慮到 Linux 和 Windows 系統的差別,執行的權限會在搬移檔案後需要設定。最簡單的方法就是使用 # chmod 777 filename,直接賦予檔案執行的權限。若是想要知道關於執行權限的設定,可以參考: http://linux.vbird.org/linux_basic/0210filepermission.php

package 的引入與環境建立

透過make menuconfig我們可以設定要額外編譯的 package,以 libnl-3 為例,我們可以從 Libraries 進入,並把相對應的 libnl package 勾選 (如下圖所示), 之後,再進行make

完成make之後,相對應的 package 出現於build_dir底下 (如下圖),其中,要引入的 header 檔位於include的資料夾內。

另一方面,編譯好的 .o/.a 檔則位於staging_dir資料夾中的usr/lib之下,透過取得 header 檔以及 .o/.a 檔的位置,我們就可以在進行 openwrt 程式開發時,引入額外的 package,進行較複雜的程式編譯。

當使用 gcc 引入編譯好的 .o/.a 檔時,若出現以下錯誤: /home/ofwrt/openwrt/staging_dir/target-mips_24kc_musl/usr/lib/libnl-3.a: file not recognized: file truncated 代表編譯的時候出現一些問題,可以試著重新make openwrt一次,並清理 (make clean) 原有專案後,有機會可以消除此問題。

外部 package 的編譯

考慮到版本問題,有時候我們也需要從 source code 開始進行編譯,相同的這樣的過程需要透過 cross compile 進行,我們以 openssl-1.0.2 為例進行說明。

一開始,先下載相對應的程式碼,並解壓縮:

$ wget https://www.openssl.org/source/openssl-1.0.2g.tar.gz
$ tar -zxf openssl-1.0.2g.tar.gz

接著,把檔案移到staging_dir底下

$ cd -R openssl-1.0.2g /home/ofwrt/openwrt/staging_dir/target-mips_24kc_musl/

進入openssl-1.0.2g資料夾下,並對其 config 檔進行設定:

$ cd openssl-1.0.2g
$ setarch i386 ./config --cross-compile-prefix=mips-openwrt-linux- shared no-asm

其中,設定包含以下內容:

  • shared: 產生 .so 的動態函式庫

  • no-asm: 取消 asm 功能

  • setarch i386: 在 32 bit 環境下進行編譯

  • --cross-compile-prefix=mips-openwrt-linux- 使用 cross-compile 進行編譯

完成後,執行make,執行後應會產生檔案如下圖所示:

使用file檢查所產生的libssl.so.1.0.0.

$ file libssl.so.1.0.0 
libssl.so.1.0.0: ELF 32-bit MSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, not stripped

可以看到,所產生的函示庫支援 mips 架構 (openwrt CPU 的計算架構)。若需要使用可以直接連接 .a 檔 (靜態函式庫),進行程式的開發。

Last updated