C++ ときどき ごはん、わりとてぃーぶれいく☆

USAGI.NETWORKのなかのひとのブログ。主にC++。

Native Client // C++へ帰る日。ネイティブの空を遠いウェブの地からも仰ぎ見よう!

一般論としてよく、女子はキラキラしたものが好きだと言われる。たぶん同様に私の場合はマシンネイティブな対象が好きなんだと思う。HTMLとかJavaScriptとか、心の故郷から遠すぎる旅路が長くなると帰りたくなる、C++へ。例えまだ帰り付く街が03だったとしても、clang++3.1がまだ開発中だったとしても。しかし、Native Clientを使えばこのネイティブから遠く離れたHTMLという文書を中心として構築される世界にワームホールを開いて故郷の空を仰ぎ見る事ができる。私は最近になって漸く実際にChromiumでBastionやRime Bertaを動作させてみた。そこに見た空はWebGLが見せる架空では無く、紛れもないネイティブな空であった。

前置きはこのくらいにして、実際に Arch Linux で Native Client を始める手立てについてメモを残す事にする。

差し当たりの資料は下記の文書。先ずはその中の初め、SDKの導入から。

環境は以下の通り。

LH-MAIN /tmp/nacl_sdk% uname -a                  
Linux LH-MAIN 3.3.2-1-ARCH #1 SMP PREEMPT Sat Apr 14 09:48:37 CEST 2012 x86_64 AMD Phenom(tm) II X4 940 Processor AuthenticAMD GNU/Linux

手順 1 Python2 を使えるか?

LH-MAIN /tmp% python2 --version
Python 2.7.2

問題ない。

手順 2 SDK を入手せよ & 手順 3 アーカイブを展開せよ

先ずはSDKを導入しなければ作り始める事は出来ない。
手順には.zipへの直リンが示されている。

LH-MAIN /tmp% wget http://commondatastorage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk/nacl_sdk.zip
LH-MAIN /tmp% unzip nacl_sdk.zip
LH-MAIN /tmp% cd nacl_sdk
LH-MAIN /tmp/nacl_sdk% 

何が入っているのやら unzip して見ると、SDKのインストーラーがbashスクリプトと不自由なWindowsの.batで収まっていた。
最終的にはsdk_update.pyが呼ばれる仕掛けになっている。

LH-MAIN /tmp/nacl_sdk% ls **  
-rwxr-x--- 1 usagi users 601  3月 22 08:29 naclsdk
-rwxr-x--- 1 usagi users 575  3月 22 08:29 naclsdk.bat

sdk_cache:
合計 4.0K
drwxr-xr-x 2 usagi users   60  4月 18 14:24 .
drwxr-xr-x 4 usagi users  120  4月 18 14:24 ..
-rw------- 1 usagi users 1.2K  3月 22 08:29 naclsdk_manifest2.json

sdk_tools:
合計 56K
drwxr-xr-x 2 usagi users  100  4月 18 14:24 .
drwxr-xr-x 4 usagi users  120  4月 18 14:24 ..
-rw-r----- 1 usagi users 1.5K  3月 22 08:29 LICENSE
-rwxr-x--- 1 usagi users  12K  3月 22 08:29 cygtar.py
-rwxr-x--- 1 usagi users  38K  3月 22 08:29 sdk_update.py

ちなみに、Arch Linuxを使っているのならAURにPKGBUILDのエントリーを見付けられる。

しかしPKGBUILDを覗き見ると入手するSDKに特定のバージョンが振られていて、パッケージの更新も1年以上前。念の為、これは使わないで措く事にしよう。

なお、ドキュメントにあったURLの.zipの中身もpython2をpythonと呼びだすように書いてある。たぶん私の環境ではここでpython3が実行されてコケるのだろうな…。もう慣れたが、何時もながらこの問題には、なぜ互換性の無い処理系を同じコマンドエイリアスで動作する様にしているやら理解に苦しむ。

手順 4 `./naclsdk list` せよ

LH-MAIN /tmp/nacl_sdk% ./naclsdk list
  File "/tmp/nacl_sdk/sdk_tools/sdk_update.py", line 430
    print 'Scanning archive to generate sha1 and size info:'

お約束のPython2依存ネタな気がするので、さっそく

LH-MAIN /tmp/nacl_sdk% mkdir bin && ln -s /usr/bin/python2 bin/python && PATH=`pwd`/bin:$PATH

(↑binというディレクトリを仮設して、python2へのシンボリックリンクpythonを作り、シェル変数のPATHに仮設コマンドを入れたbinを最優先する様に放り込んでいます。)

それから、再び:

LH-MAIN /tmp/nacl_sdk% ./naclsdk list
Available bundles:
  sdk_tools
    description: Native Client SDK Tools, revision 1.16
    stability: stable
    recommended: yes
    version: 1
    revision: 16
  pepper_16
    description: Chrome 16 bundle, revision 1398
    stability: post_stable
    recommended: no
    version: 16
    revision: 1398
  pepper_17
    description: Chrome 17 bundle, revision 112997
    stability: stable
    recommended: no
    version: 17
    revision: 112997
  pepper_18
    repath: pepper_18
    description: Chrome 18 bundle, revision 124251
    stability: beta
    recommended: yes
    version: 18
    revision: 124253
  pepper_19
    repath: pepper_19
    description: Chrome 19 bundle, revision 127407
    stability: dev
    recommended: no
    version: 19
    revision: 128837

Currently installed bundles:
  sdk_tools
    description: Native Client SDK Tools, revision 1.16
    stability: stable
    recommended: yes
    version: 1
    revision: 16

よし、先へ進もう・w・b

`./nacl_sdk update` し、 シェルに変数 NACL_SDK_ROOT をセットせよ

LH-MAIN /tmp/nacl_sdk% ./naclsdk update
sdk_tools is already up-to-date.
Downloading https://commondatastorage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk/18.0.1025.46/naclsdk_linux.bz2
|================================================|
..................................................
Updating bundle pepper_18 to version 18, revision 124253
|------------------------------------------------|
..................................................

無事にSDKを更新できたらしい。

続いてドキュメントの最後にある NACL_SDK_ROOT 変数の設定を自動化する。

と、その前に私は作業を/tmpで行なっていたので、先にnacl_sdkを`~/opt/`へ移動してして措く事にする。

LH-MAIN /tmp/nacl_sdk% ..
LH-MAIN /tmp% mv nacl_sdk ~/opt

変数 NACL_SDK_ROOT は差し当たり.zshrcにでも追加しておくとしよう。

NACL_SDK_ROOT=~/opt/nacl_sdk/pepper_18

チュートリアル 3 examples でお楽しみ

LH-MAIN /tmp% cd ~/opt/nacl_sdk/pepper_18/examples

執筆時点では`pepper_18`を使っているけれど、もちろんバージョンはどんどんインクリメントされる。

LH-MAIN /home/usagi/opt/nacl_sdk/pepper_18/examples% python httpd.py 12345
INFO:root:Starting local server on port 12345
INFO:root:To shut down send http://localhost:12345?quit=1

Chromiumでこのサーバーにアクセスする。

f:id:USAGI-WRP:20120418165534p:plain

サンプルお楽しみタイムの始まり…の前にビルド。

LH-MAIN /home/usagi/opt/nacl_sdk/pepper_18/examples% make             
make -C dlopen
  File "/home/usagi/opt/nacl_sdk/pepper_18/tools/getos.py", line 29
    print 'Unknown platform.'
                            ^
SyntaxError: invalid syntax
make[1]: ディレクトリ `/home/usagi/opt/nacl_sdk/pepper_18/examples/dlopen' に入ります
/home/usagi/opt/nacl_sdk/pepper_18/toolchain/_x86_glibc/bin/i686-nacl-g++ -o dlopen_x86_32.o -c dlopen.cc -m32 -g -O0 -pthread -std=gnu++98 -Wno-long-long -Wall
make[1]: /home/usagi/opt/nacl_sdk/pepper_18/toolchain/_x86_glibc/bin/i686-nacl-g++: コマンドが見つかりませんでした
make[1]: *** [dlopen_x86_32.o] エラー 127
make[1]: ディレクトリ `/home/usagi/opt/nacl_sdk/pepper_18/examples/dlopen' から出ます
make: *** [dlopen_TARGET] エラー 2

ふむ、どうも`i686-nacl-g++`の呼び出しパスが怪しく見える。`_x86_glibc`の部分はアンダースコアの前に何か入れるのに失敗しているのでは無かろうか?

"exmaples/Makefile"を確認し、どうもそこには具体的に失敗したコマンドに関する記述は見られない様なので、そこから呼び出される"examples/dlopen/Makefile"を確認してみた。すると、:

OSNAME:=$(shell python $(NACL_SDK_ROOT)/tools/getos.py)
TC_PATH:=$(abspath $(NACL_SDK_ROOT)/toolchain/$(OSNAME)_x86_glibc)
CXX:=$(TC_PATH)/bin/i686-nacl-g++
||

とかなんとかやっている。このOSNAMEの取得`getos.py`がしくじっているに違いない。

>|sh|
LH-MAIN /home/usagi/opt/nacl_sdk/pepper_18/examples% python ../tools/getos.py 
  File "../tools/getos.py", line 29
    print 'Unknown platform.'
                            ^
SyntaxError: invalid syntax
LH-MAIN /home/usagi/opt/nacl_sdk/pepper_18/examples% python --version        
Python 3.2.2

ぁぁ、また君か・・・パイソン君…。何故互換性の無いコマンドを上書きしたのだ…この馬鹿パイソンが…。

LH-MAIN /home/usagi/opt/nacl_sdk/pepper_18/examples% python --version    
Python 2.7.2
LH-MAIN /home/usagi/opt/nacl_sdk/pepper_18/examples% python ../tools/getos.py 
linux

ふむ、どうやらそういう事らしい。ここでふとpython3/python2が同じコマンド名である事に由来するあほらしい問題に単にコマンドを実行できれば良いだけの状況でちまちまと触れるのが馬鹿らしいので、

とか作った。・・・この試みはCERRは汚くなるが、まあ上手く行くだろうと思った…。しかし`make`の途中で止まった。ふう、ダルい。

さてもう私はpython3なんてこの世に無い事にする事にした。

% su -
# rm /usr/bin/python
# ln -s /usr/bin/python2 python

もう知らん。私はpythonを自分で書く予定は無いし、書くとしても必ずや`python3 hogehoge`と呼び出される事を前提としたスクリプトとその呼び出し用のシバンを作って提供するだろう。これは本当に馬鹿馬鹿しい問題だ=w=;

さてまあ、pythonコマンドが必ずpython2を実行する様にしてしまえば`make`は綺麗に通って、NaClにより開かれた、楽しいC++によるネイティブの空をChromiumで無事に見られる様になります。

f:id:USAGI-WRP:20120418182912p:plain

いやっほー・w・b

<追記>

  • テストするChromiumは[chrome://flags/]でChromeウェブストア以外のNaClも有効化しておく
  • SDKは ./naclsdk update pepper_19 とかするとバージョンを明示して入手できる
  • シェル変数 NACL_SDK_ROOT 用に nacl_sdk/ で `ln -s pepper_19 pepper_target` とかして措いて、.zshrcとかの変数の値は固定しちゃうのがたぶんSDKの運用は楽