2016年10月8日 星期六

Qt for Native Client (and emscripten)

這篇是個失敗案例, 我沒能成功搞定我想做的事情。

對於 web 開發技術我還停留在 cgi 的時代, 看過《[科技]JavaScript的诞生与死亡(双语字幕)》這影片後, 對這樣的技術有興趣, 找了相關資料。

影片中提到的技術是把 c/c++ 程式碼編譯成 javascript, 在瀏覽器執行, 那是所的有 library 都可以嗎? 自然沒有這麼好的事情, gui library 只支援 sdl, 所以用 sdl 寫的程式才能享受這樣的福利。這也就是為什麼有些模擬器可以在瀏覽器執行的原因, 他們是用 sdl 寫的。

我個人使用的 gui framework 是 qt, 我馬上就想到 qt 也可以嗎?
答案是肯定的, Qt for Native Client (and emscripten) 就在說明如何辦到這件事。

Qt for Native Client 是什麼意思? 簡單來說就是用某種方式把 qt 編成另外一個編碼, 然後在瀏覽器上執行這種編碼的 qt 程式。
有幾個方法:
  • google 的 nacl
  • mozilla 的 emscripten
我個人偏愛 mozilla 的 emscripten, 可以編出 javascript code, 可在任意瀏覽器執行, 而 google 的 nacl 只能在 google chrome 上執行。

emscripten-qt是舊的, 可以參考, 但不要用這個, emscripten-qt 是 qt 4.x 已經過時, 而我花了不少時間也搞不出來。

google nacl

download google nacl_sdk,
執行 ./naclsdk install 安裝 nacl sdk。

export NACL_SDK_ROOT=/home/descent/mygit/nacl_sdk/pepper_49

git clone https://code.qt.io/qt/qtbase.git .
git checkout wip/nacl

./nacl-configure linux_pnacl release x86_64 -v # linux
./nacl-configure mac_pnacl release x86_64 -v # mac
make

download demo code:
https://github.com/msorvig/qt-nacl-manualtests.git 

qt-nacl-manualtests/window_widgets
qmake window_widgets.pro
make

執行
~/mygit/qtbase/bin/nacldeployqt --run window_widget.nexe
~/mygit/qtbase/bin/nacldeployqt --run digitalclock.nexe

fig 1 為 chrome 上執行畫面。

fig 1 . qt lineedit program, but cannot input text

mozilla emscripten


install emscripten sdk
Download and install emscripten

裡頭有 emcc, em++, 可以寫個 hello.cpp 來測試,

em++ -o h.html h.cpp

把 h.html 丟到瀏覽器試試, 中文也可以透過 cout 秀出。 疑! 怎麼沒程式碼, 拜託, hello world 不用我寫給你看吧!

git clone https://code.qt.io/qt/qtbase.git .
git checkout wip/nacl

export NACL_SDK_ROOT=/home/descent/mygit/emscripten
./nacl-configure emscripten release x86-64

還需要:

  • qt-everywhere-opensource-src-5.7.0/qtwebengine/src/3rdparty/chromium/ppapi
  • qt-everywhere-opensource-src-5.6.0/qtwebengine/src/3rdparty/chromium/ppapi (font_dev.cc)


當編譯錯誤時, 請參考錯誤訊息, 把相關的 ppai 檔案連結到相關目錄, 總之就是少了 qt-everywhere-opensource-src-5.6.0/qtwebengine/src/3rdparty/chromium/ppapi 這個程式碼。

descent@u64:js_qt$ ls qtbase/include/ppapi -l
lrwxrwxrwx 1 descent sambashare 89 Oct  7 09:31 qtbase/include/ppapi -> /home/descent/qt-everywhere-opensource-src-5.7.0/qtwebengine/src/3rdparty/chromium/ppapi/

descent@u64:ppapi_cpp$ ls -l /home/descent/mygit/emscripten/src/ppapi_cpp
lrwxrwxrwx 1 descent sambashare 93 Oct  7 09:49 /home/descent/mygit/emscripten/src/ppapi_cpp -> /home/descent/qt-everywhere-opensource-src-5.7.0/qtwebengine/src/3rdparty/chromium/ppapi/cpp/

font_dev.cc 要在 qt 5.6 的 qtwebengine/src/3rdparty/chromium/ppapi 才有
descent@u64:ppapi_cpp$ ls -l font_dev.cc 
lrwxrwxrwx 1 descent sambashare 108 Oct  7 09:50 font_dev.cc -> /home/descent/qt-everywhere-opensource-src-5.6.0/qtwebengine/src/3rdparty/chromium/ppapi/cpp/dev/font_dev.cc

最後我可以編譯出 qt-nacl-manualtests/window_widgets 的 window_widgets.html window_widgets.js 檔案, 可是無法在瀏覽器執行, 恨阿!
搞定, 原來也是要執行 nacldeployqt, 媽的勒!

export NACL_SDK_ROOT=/home/descent/mygit/nacl_sdk/pepper_49
~/mygit/qtbase/bin/nacldeployqt -q

-rw-rw-r-- 1 descent descent    95674941 Oct  7 14:07 analogclock.js
-rw-rw-r-- 1 descent sambashare     1131 Oct  7 14:07 index.html
-rw-rw-r-- 1 descent sambashare     9175 Oct  7 14:07 qtloader.js

90 Mb 的 analogclock.js, 很嚇人吧!

index.html 會呼叫 qtloader.js 來載入 analogclock.js。

會產生 index.html, fig 2, fig 3 是執行畫面。

fig 2. qt analogclock on chrome

fig 3. qt analogclock on firefox

不過似乎無法輸入, 也無法按下按鈕, 只有靜態網頁的話還真是可惜。而中文也無法正常秀出。

google 的 nacl, mozilla 的 emscripten 都需要改動 qt source, main 需要用 Q_WIDGETS_MAIN(app_init, app_exit) 取代。

而 main.cpp L42, 43 這兩個 header files 是需要的, 否則編譯不過。

main.cpp
 1 
41 #include <QApplication>
42 #include <QtGui>
43 #include <QtWidgets>
44 
45 #include "analogclock.h"
46 
47 #if 0
48 int main(int argc, char *argv[])
49 {
50 }
51 #endif
52 
53 void app_init(int argc, char **argv)
54 {
55 #if 0
56     window = new QWidget();
57     QLabel *label1 = new QLabel("Hello World");
58     QLabel *label2 = new QLabel("Bye World");
59     QLineEdit *lineEdit = new QLineEdit;
60     QPushButton *pushButton = new QPushButton("PuhsIt");
61     QVBoxLayout *layout = new QVBoxLayout;
62     layout->addWidget(label1);
63     layout->addWidget(lineEdit);
64     layout->addWidget(pushButton);
65     layout->addWidget(label2);
66     window->setLayout(layout);
67     window->show();
68 #endif
69     //QApplication app(argc, argv);
70     AnalogClock clock;
71     clock.show();
72     //return app.exec();
73 }
74 
75 void app_exit()
76 {
77     //delete window;
78 }
79 
80 Q_WIDGETS_MAIN(app_init, app_exit);

這兩個範例是我由 qt examples 修改而來

  • https://github.com/descent/qt-nacl-manualtests/analogclock
  • https://github.com/descent/qt-nacl-manualtests/tree/dev/lineedits


ref:
運用 Emscripten 移植遊戲 (上)

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。