一、前言
MT7688 + node.js 的組合相信一定吸引了不少人,可是呢!當我們需要用 npm 安裝 node mdoule 的時候,可能會遇到一些問題。第一個是直接在 target 下 npm 指令安裝(以下target 即指 MT7688 本身的環境),因為資源不若 host PC,安裝的速度會稍微慢一點。
第二個問題是,如果在 target 上安裝時,遇到需要 node-gyp rebuild 的情況,那就無解了,原因是 target 上沒有 node-gyp、也沒有 native toolchain 在上面。遇到這個情況時,我們只能移駕到 Host PC 上,先 npm 安裝完 module,再將 module 打包一下,用 ssh copy (scp) 丟到 target 上。
第三個問題,當你在 Host PC 上先裝 node module 時,如果遇到 node-gyp 需要 rebuild native add-on 的時候( *.c, 或 *.cpp 檔),你 build 完的東西只能在 Host PC (x86) 的架構上跑,丟到 mips 的架構上當然就 GG 了啊!!
那怎麼辦咧?當然,腦袋一閃過的念頭,當然就是準備好 cross toolchain,在 Host 上交叉編譯能在 MT7688 MIPS 架構下執行的檔案。
可是第四個問題來了,雖然 MTK 官網有提供 cross toolcahin 跟 SDK,可是咧,我發現事情好像沒有那麼簡單啊~~啊啊啊~ 因為你還必須先準備好 mips platform 的 v8 引擎,之後再拿它去編出 mips 架構下的 node.js。雖然在網路上能找的到一些交叉編譯的討論,可是,不是資料有點舊,不然就是 v8 版本與 node 版本選擇的問題,還有大端小端、要以硬體浮點還是軟體浮點支援編譯的問題。
二、緣起
前兩天餐敘,特別跟 MT7688 掃雷大隊長 Fred (XDDD.... 傳說中全身都是雷的男人!!) 請教關於如何在 host 上交叉編譯 node modules 的問題,聽起來這目前也是相當頭痛的問題呀!不只掃雷大隊頭痛,我個人也很頭痛呀!畢竟我自己手邊正好有個 project,正好就是有這個問題!實在不解不行!於是,偶也想要湊個熱鬧,在一旁當個搖旗吶喊的小小掃雷隊員 (搖屁股....)~ 科科~然後我就寫了一支 script,想說讓 MT7688 交叉編譯環境的準備可以比較自動化一點,它會自己去下載 SDK 以及相應版本的 v8 與 node.js~ 所以,你只要「一鍵給它按下去」,等個差不多20分鐘,靜待那一堆東西編譯完,這樣子交叉編譯環境就準備好了!這個交叉環境只是一個工作目錄,編過一次就不需再編,以後就能在這個目錄下一直使用 ./npm_install.sh 這支指令稿來安裝能跑在 mips 上的 node module。
好啦!其實就是想對 MT7688 的社群做一點小小的貢獻。其實我也不知道這件事有沒有人做過,至少我在茫茫網海撈了一圈,實在是找不到什麼參考資料啊!
三、環境摘要
Host:Ubuntu 14.04 LTS x86_64 (MTK 給的 toolchain 是 host 在此平台,所以請準備一下)
Target:MT7688, MIPS24KEc, little endian
node 版本:0.12.7
npm 版本: 2.11.3
v8 版本:3.28.71 (patch 19)
四、環境準備
(1) 先確認你的 Host 有裝以下套件,如果不知道,就都裝一下$ sudo apt-get install subversion build-essential gcc-multilib g++-multilib
這些套件的主要用於從repo抓source、建置工具與函式庫(以及在64位元平台編譯32位元架構會用到)
(2) 確認你的 Host 目前的 node 版本為 0.12.7,npm 版本為 2.11.3。若版本不符,指令稿會提示你安裝正確版本。我習慣用 n 這個版本管理器安裝不同版本的 node:
$ sudo n 0.12.7
$ sudo npm install -g npm@2.11.3
(3) Clone 一下 mt7688-cross 這個專案 (或直接到 github 下載 zip 直接解開使用亦可)
~$ git clone https://github.com/simenkid/mt7688-cross.git
~$ cd mt7688-cross
~/mt7688-cross$ (這裡就是之後要執行交叉編譯的工作目錄)
(4) 執行環境準備指令稿,這個指令會進行一些編譯工作,視你的電腦性能,大概需要20分鐘左右。
~/mt7688-cross$ ./create_env.sh
附帶一提,編譯完後,/linkit/opt 目錄下放的就是可以在 MT7688 MIPS 架構下跑的 node.js 與 npm。若您想要編譯不同版本的 node,可參考指令稿內的步驟(或直接修改也可以)。目前 mt7688-cross 是直接鎖死對應到MT7688目前官方的 node 與 npm 版本。
(5) 上一個步驟完成,之後要交叉編譯 node module 的環境也就準備好了,以後不需再執行 ./create_env.sh 了。以後就是直接進來此工作目錄,進行下一步 mips 版本的 node module 安裝即可。
(6) 在工作目錄下,以 ./npm_install.sh xxx 或 ./npm_install.sh xxx@version 安裝某 module,以下是安裝 serialport 模組的例子
~/mt7688-cross$ ./npm_install.sh serialport
(7) 安裝完後的 module 會直接打包成 tar.gz 壓縮檔,放在工作目錄的 /node_modules_mips 底下,請 scp 丟到 MT7688 解開就可以用啦! 如果需要自動化 scp,歡迎各位朋友自己改一下指令稿~
五、serialport 執行範例
(1) 在 host 上將壓縮檔 scp 丟到 target(2) 在 target 上解壓縮,這個範例是解到 app/node_modules 目錄下
(3) 在 /app 下寫一支測試程式 app.js
這裡我就先省略啦~ serialport 是跑得起來, 但是我不會用arduino..... \___/
所以 "/dev/ttyS0" 接給 atmega 那一段,我就沒測啦~
不過你可以試試看 "/dev/ttyS2",哈哈,會收到有東西就對了,我不知道ttyS2是系統上的terminal還是誰在用啦~ 原本想要再測一下別的module,但是我好累哦!公司今天大掃除~
我要先去洗澡啦!之後有example我再放上來吧!!
[ 我有個小問題:有人知道 duo 的 UART TX/RX2 是否有驅動起來掛在 /dev/tty???。有人知道的話,再拜託跟我講一下!]
六、後記
這邊有幾點想再補充一下:(1) 如果要安裝的module是跟硬體強烈相關的(例如module會操作到SoC的gpio),若module作者沒有提供架構相關的程式碼,那麼 rebuild 還是會失敗喔! 只能建議 module 作者加入 MT7688 platform 的支援囉~~
(2) 如果 module build 時所需的 library,SDK 中並沒有提供函式庫,build 也會fail~ 這可能要 MTK 去處理啦~~ 畢竟有些module預設的投入平台可能是 PC或比較強大的嵌入式平台,資源比較有限的平台的身材我猜都有雕塑過啦~
(3) 如果 addon 是一些跟平台不相關的演算法、logics,應該是都編得過。
(4) MT7688 在初始化 node program 時有稍微慢一點,跟 Fred 討論似乎是初始化的問題。在這邊提供一些我的study,我猜這似乎是 v8 的問題。在網路上看到 mips cross-compile 的資料大多較舊,都是編譯 node v0.10 左右的版本,它搭的 v8 支援 no floating point mode。不過,v8自 v3.18 起已經強制都需要使用 FPU,若 MPU 不支援 hard FPU,v8 會採取軟體模擬浮點運算。我在其他地方有看到關於v8採用soft FP 的性能確實是大有問題的(抱歉, 我忘記存下鏈結了),會比用hard FP慢上許多(印象中差了將近100倍,恩,印象中....)。關於這一點,因我並非很專業,涉略也不深,純屬我的猜測,提供大家做參考。
(5) script 指令稿歡迎大家自己修改成符合你需要的情況哦! 如果發現使用中出了問題,再麻煩請讓我知道,讓我能繼續把它修改得更好哦!那如果編譯不過,是我以上講的問題,那真的是找我也沒用啦~ XDDDD....
(6) 若你只想要交叉編譯工具的環境變數設定,請參考 env.sh 檔
(7) github 上面的 README.MD 還沒有時間寫,等我有空再補完囉!最近真的寫太多文件,都快吐了!
謝謝大家!祝大家 7688 玩得愉快~
註:此指令稿的靈感與參考源自 Build your own Node.js package with the linino toolchain