2015年6月1日 星期一

Chrome NaCL 開發心得小記

目前開發到一半, 先加減記一下。之後有多什麼心得再來補充。

為什麼要用 NaCL

自然是方便重用既有的 C/C++ 程式啦。

雜項

  • NaCL 無法在本機檔案中執行 (file://...)。web pages、Chrome Web App、 Chrome Extension 才能用 NaCL。若要在本機試 web pages 的話, 需要跑 local web server。NaCL SDK 內有附一個 local web server, Getting Started 的範例用 make serve 執行 local web server。建議先玩 Getting Started 裡面的兩個範例, 了解 NaCL 的架構。
  • 有支援 POSIX 和 ptherad, 還算堪用, 不過 port Linux 的程式時會遇到很多 Linux 才有但 POSIX 沒有的程式碼 (網路、時間、pthread 各式各樣都有)。
  • 分成 PNaCL (編成 bitcode 執行檔, 使用前再轉成執行檔) 和 NaCL (native binary)。若需要放到 Chrome Web Store, 後者比較不方便, 得編多份不同平台的 binary
  • 得用 NaCL SDK 附的工具, 我試過用 nm 和 ar 都無效, 改用 NaCL SDK 附的 llvm-nm 和 llvm-ar 才有正常結果。
  • 若想使用 stdio 的函式 (如 FILE 相關函式), 要另外使用 nacl_io library。需要在 Makefile 補上 -I$(NACL_SDK_ROOT)/include -I$(NACL_SDK_ROOT)/include/pnacl-lnacl_io

除錯

參考資料: 官方文件

1. 基本的除錯方式是透過 stderr 導到執行 Chrome 的 terminal (預設行為), 或寫到 DevTools 的 console (透過 /dev/console1 ~ 3)。

但是導到 DevTools console 的輸出會被限制行寬, 超出的字會被截掉。還有由於 stderr 是 unbuffered, 輸出會亂掉, 若想將 stderr 導到 /dev/console1, C/C++ 程式內記得改設 stderr 為 line buffer ( setlinebuf(stderr) )

2. 開發 extension 時, 即使沒需求, 也可考慮加個 background page, 這樣可以長駐在 Chrome 內, 方便寫 log 到 background page 的 console, 用 DevTools 觀察 console 的 log 除錯。

3. 可以用 NaCL SDK 附的 nacl-gdb attch 到使用 NaCL 的 process, 但是手續頗麻煩的。但是不用 gdb, native code 出錯時更麻煩。

參考資料: Running nacl-gdb

我一開始在 Mac OS X + Pepper 42 試失敗, 後來在 Linux + Pepper 43 試成功了。不確定和平台或版本是否有關, 先前有遇到 Mac OS X + Pepper 42 的 bug (使用 nacl_io library 後, 輸出到 stderr 的資料沒有顯示在執行 Chrome 的 terminal 上), 但在 Linux + Pepper 43 沒事。

以開發 Chrome extension 為例:

  • 執行 Chrome 要加參數 --enable-nacl-debug --no-sandbox
  • 編譯時用 -O0 -g
  • 需要設一些 gdb 參數, 我包成兩個 script, 放在 native code 專案的根目錄:
$ cat run_gdb.sh 
#!/bin/bash

if [ "$NACL_SDK_ROOT" = "" ]; then
        echo "Please set the env variable NACL_SDK_ROOT"
        exit 1
fi

echo -e "\033[1;33m"
echo "Please ensure that Chrome is run with --enable-nacl --enable-nacl-debug --no-sandbox"
echo "Ref: https://developer.chrome.com/native-client/devguide/devcycle/debugging"
echo -e "\033[m"

cd $(dirname $0)
ROOT=$(pwd)
cd ../../
${NACL_SDK_ROOT}/toolchain/linux_x86_glibc/bin/i686-nacl-gdb -x sync/nacl/nacl.gdb
$ cat nacl.gdb 
target remote localhost:4014
remote get nexe my.nexe
file my.nexe
remote get irt my.irt
nacl-irt my.irt

先重新載入 extension, 再執行 run_gdb.sh, 成功後會出現 gdb 的 prompt。注意, 執行 Chrome 有加 --enable-nacl-debug 時, 就一定要跑 nacl-gdb, 因為 Chrome 會停住 NaCL process, 等著被 gdb attach。

2 則留言:

  1. 我要說的是,POSIX 不相容的問題,你可以試試 NaCl SDK team 做的 nacl_io,應該可以省下你一些功夫。我自己沒用過,因為我們 team 在 nacl_io 出來之前就做了自己的 posix_translation (https://chromium.googlesource.com/arc/arc/+/master/src/posix_translation/)。不過我猜別的 project 不見得可以拿去就直接用。

    回覆刪除
  2. nacl_io, 還不錯用, 用了以後除了不能在 main thread 用 stdio 的東西外, 其它部份用起來就和原本一樣

    回覆刪除

在 Fedora 下裝 id-utils

Fedora 似乎因為執行檔撞名,而沒有提供 id-utils 的套件 ,但這是使用 gj 的必要套件,只好自己編。從官網抓好 tarball ,解開來編譯 (./configure && make)就是了。 但編譯後會遇到錯誤: ./stdio.h:10...