LoginSignup
40

More than 5 years have passed since last update.

go1.3でNative Client(NaCl)アプリをビルドする #golang

Last updated at Posted at 2014-06-19

今朝、golang 1.3がリリースされました。
このバージョンからPlan9などの新しい環境に対応しましたが、特にNative Client(NaCl)が気になりましたので、バージョンアップのついでに試してみました。

Native Client

Native Client、通称NaClはブラウザ上でx86ネイティブコードが実行出来る仕組みであって、JavaScriptの諸問題の一部を解消できると期待されています。バイナリはNaClのサンドボックスに閉じ込めて実行されるため、周りに影響を与えないという特徴もあります。
類似の技術にMozillaのasm.jsがありますが、asm.jsがJavaScriptを単純にしたサブセットで実行速度を改善しているのに対し、Native Clientはコンパイル済みのマジで本気なバイナリがゴリゴリ動くので、大変に萌え度が高いです。

とは言ったものの、go1.3ではNativeClientをブラウザで動かすためのPepperPluginAPIに対応していないため、普通にサンドボックス内でバイナリを動かすことしかできません。(Go1.4かそれ以降でPPAPIにも対応する予定)
また、go1.3で対応したのはx86/x64のバイトコードを用いたNaClのみで、LLVM版のPNaCl(Portable Native Client)には対応していません。こちらは対応に向けての確固たる計画もないそうです。まぁ、成り立ちを考えれば難しいでしょうしね。

go1.3で環境を作る

NaCl SDKをダウンロードする

go1.3だけでなく、NaCl SDKが必要になるので、ダウンロードします。
このページ(Download the Native Client SDK)中の「Download and install the SDK」から「nacl_sdk.zip」を落としてきて、適当にunzipして、「/opt」にmvします。
最後に、中に居る「naclsdk」のスクリプトを蹴ります。

 $ unzip nacl_sdk.zip
 $ mv nack_sdk /opt
 $ cd /opt/nacl_sdk
 $ ./nacksdk install

つぎに、必要なスクリプトをパスの通ったディレクトリへ移します。("pepper_35"の数字部分は、インストールしたnaclsdkのバージョンで変わるので要確認)

 $ ln -nfs /opt/nacl_sdk/pepper_35/tools/sel_ldr_x86_32 $GOPATH/bin/sel_ldr_x86_32
 $ ln -nfs /opt/nacl_sdk/pepper_35/tools/sel_ldr_x86_64 $GOPATH/bin/sel_ldr_x86_64

サポートスクリプトを準備する

go/misc/nacl以下にサポートスクリプト達が居ますので、これらをパスの通ったディレクトリへ移します。

 $ ln -nfs $GOROOT/misc/nacl/go_nacl_amd64p32_exec $GOPATH/bin/go_nacl_amd64p32_exec
 $ ln -nfs $GOROOT/misc/nacl/go_nacl_386_exec $GOPATH/bin/go_nacl_386_exec

環境をビルド&テスト

仕上げに、例えばx86のnaclなら386をサポートしたサポートスクリプトを叩いてから、nacl用go環境をビルド&テストします。

 $ go_nacl_386_exec
 $ cd $GOROOT/src
 $ env GOARCH=amd64p32 ./nacltest.bash

NaClアプリをビルドしてみる

環境はできたので、NaClアプリをビルドします。
先に書いたとおり、go1.3の時点ではブラウザで動かすことはできませんので、Native ClientのSDKについているサンドボックスを使ってなんとなく動かしてみます。

test.go
package main

import (
        "fmt"
)

func main() {
        fmt.Println("hello")
}
 $ env GOOS=nacl GOARCH=amd64p32 go build test.go
 $ sel_ldr_x86_64 test
[28083,2572449600:13:50:19.491746] Native Client module will be loaded at base address 0x00004a0c00000000
runtime: nacl_exception_stack: error 38
runtime: nacl_exception_handler: error 38
runtime: nacl_exception_stack: error 38
runtime: nacl_exception_handler: error 38
runtime: nacl_exception_stack: error 38
runtime: nacl_exception_handler: error 38
runtime: nacl_exception_stack: error 38
runtime: nacl_exception_handler: error 38
hello
[28083,2572236544:13:50:20.140744] NaClRuntimeHostInterfaceReportExitStatus(0x7f9a9a0a9f50, 0x0)

nacl_exception_stackってのがたくさん出ていていますが、ふわっと検索した感じ、そういうものらしい。ウザければ「2>/dev/null」でも付けてエラー出力を無視するといい感じになります。

一応、サンドボックス内で動いていることを確認しておきましょう。

test2.go
package main

import (
        "fmt"
        "os"
)

func main() {
        f, err := os.Open("test2.go")
        if err != nil {
                fmt.Println(err)
        }

        fmt.Println(f)
        return
}
 $ env GOOS=nacl GOARCH=amd64p32 go build test2.go
 $ sel_ldr_x86_64 test2
open /home/umisama/main.go: No such file or directory
<nil>

予定通り、ファイルを開くことが出来ませんでした。
とりあえず満足したので、ここまで。

実用例

go playgroundでユーザが書いたコードは、NaCl用にビルドされてサンドボックス内で動作しているらしい。
こんな感じの用途になら、現状でもなんとなく使えます。(やっぱまだ用途が微妙だな〜)

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40