Hatena::Grouplinux2

Going My Linux Way このページをアンテナに追加 RSSフィード

2012年05月27日(日)

Ubuntu Linux に Google Go をインストールしてみる

| 14:54 | Ubuntu Linux に Google Go をインストールしてみる - Going My Linux Way を含むブックマーク はてなブックマーク - Ubuntu Linux に Google Go をインストールしてみる - Going My Linux Way Ubuntu Linux に Google Go をインストールしてみる - Going My Linux Way のブックマークコメント

Ubuntu LinuxGoogle Go をインストールしてみます。

インストール

公式ページに手順が書いてあるので、それに従います。

64bit-Linux 環境なので「go.go1.linux-amd64.tar.gz」をダウンロードしました。

$ sudo tar zxvf go.go1.linux-amd64.tar.gz -C /usr/local

以上、インストール終わり。

ユーザ環境に設定を行ないます。~/.bashrc などに以下を記述します。

export PATH=$PATH:/usr/local/go/bin

ちなみにホームなどにインストールした場合は以下のように設定します。

export GOROOT=$HOME/go
export PATH=$PATH:$GOROOT/bin

以上、(基本的な)設定終わり。(以降の作業があるので source ~/.bashrc しておきます)

チュートリアル

公式ページに参考ページがあります。

A Tour of Go は Go を Web サイト上で実行できるページがあります。

----

英語のページなので Google Chrome で翻訳しながら読んでいたら、「The Go Programming Language」が「囲碁プログラミング言語」に訳されました。

「A Tour og Go」は「囲碁のツアー」。。。。

Hello,World

Hello,World。こいつはやっとかないといけません。

難読な翻訳文を読みつつ進めます。

ワークスペースを作ります。そのパスは環境変数 GOPATH に設定します。

私は以下のようにやりました。

$ mkdir -p ~/sandbox/go
$ export GOPATH=~/sandbox/go   # 後で、~/.bashrc にも記述しました

ワークスペース直下の bin にパスを通します。

$ export PATH=$PATH:$GOPATH/bin  # 後で、~/.bashrc にも記述しました

ワークスペース直下に src を作成します。src はソースの置き場所です。

$ mkdir $GOPATH/src

作成するパッケージを置くベースのインポートパスを作成します。

ここでは example とします。*1

$ mkdir $GOPATH/src/example

hello パッケージ(のパス)を作ります。

$ mkdir $GOPATH/src/example/hello

ソースファイル hello.go を書きます。

$ vi $GOPATH/src/example/hello/hello.go

hello.go の内容(公式サイトの「A Tour of Go」に書かれているもの)

package main

import "fmt"

func main() {
    fmt.Println("Hello, 世界")
}

example/hello パッケージをビルドしてインストールします。

$ go install example/hello

$GOPAHT/bin に hello が作成されました。

$ ls $GOPATH/bin/
hello

実行してみます。

$ $GOPATH/bin/hello
Hello, 世界

実行できました。

現状では以下のような構成になってます。

$ tree $GOPATH/
/home/lnznt/sandbox/go
|--- bin
|     |--- hello
|
|--- src
      |--- example
            |--- hello
                  |--- hello.go

パッケージを作ってみる

mylib パッケージを作ってみます。

パッケージが提供するのは足し算を行なう関数 Add です。

$ mkdir $GOPATH/src/example/mylib
$ vi $GOPATH/src/example/mylib/add.go

add.go の内容

package mylib  // パッケージ名を記述する

func Add(a int, b int) int {
    return a + b
}

ビルド&インストールします。

$ go install example/mylib

パッケージができました。

$ tree $GOPATH
/home/lnznt/sandbox/go
|--- bin
|    |--- hello
|
|--- pkg
|     |--- linux_amd64
|           |--- example
|                 |--- mylib.a   # 作成されたパッケージ
|--- src
      |--- example
            |--- hello
            |     |--- hello.go
            |    
            |--- mylib
                  |--- add.go

パッケージを使ってみる

先程の hello.go で作成したパッケージの関数を使ってみます。

example/hello/hello.go を以下のように変更します。

package main

import (
    "example/mylib"  // example/mylib をインポートする
    "fmt"
)

func main() {
    fmt.Println("Hello, 世界")
    fmt.Printf("1 + 2 = %v\n", mylib.Add(1,2)) // mylib.Add() を使う
}

ビルド&インストールします。

$ go install example/hello

(更新された)hello を実行してみます。

$ $GOPATH/bin/hello
Hello, 世界
1 + 2 = 3

変更されてます。

----

mylib.Add() を最初 mylib.add() と書きました。

すると、hello のビルド時に以下のようなエラーが出ました。

$ go install example/hello
# example/hello
hello/hello.go:10: cannot refer to unexported name mylib.add

多分ですが、名前が大文字で始まらない関数エクスポートされないようです。

参考URI

参考書籍

はじめての「Go言語」 (I・O BOOKS)

はじめての「Go言語」 (I・O BOOKS)

Ubuntu 12.04 で hello.c をARMバイナリとしてコンパイルして実行してみる

| 14:52 | Ubuntu 12.04 で hello.c をARMバイナリとしてコンパイルして実行してみる - Going My Linux Way を含むブックマーク はてなブックマーク - Ubuntu 12.04 で hello.c をARMバイナリとしてコンパイルして実行してみる - Going My Linux Way Ubuntu 12.04 で hello.c をARMバイナリとしてコンパイルして実行してみる - Going My Linux Way のブックマークコメント

こちらの記事を参考に Ubuntu 12.04 の Multiarch を試してみました。

ARM 用のバイナリビルドしてネイティブ(x86-64bit)で実行しようと思います。

以下、要点メモです。

Ubuntu 12.04 ですが上記の記事とはパスなどが若干異なりました。

インストール

ツールチェーンとエミュレータインストールします。

$ suto apt-get install g++-arm-linux-gnueabihf \
                       qemu-user               \
                       qemu-user-static

g++-arm-linux-gnueabihf の依存関係によりツールがインストールされます。

C++ が不要の場合は、gcc-arm-linux-gnueabihf でもいいと思います。

インストールされる gcc のバージョンは 4.6.3 (2012/05/14現在)です。

...abihf は Embedded-ABI Hard-Float を表します。

ARM アーキテクチャでは EABI と OABI (Old ABI) の二つがあるそうです。

Hard Float (FPU命令を使用する) に対するのは Soft Float です。

qemu-user と qemu-user-static はネイティブ上で ARM (や他の CPU アーキテクチャ)のバイナリを動かすエミュレータです。エミュレートしないならインストールする必要はありません。また、用途によってどちらか片方でも構いません。

qemu-user-static のほうは、static link したバイナリを動かすのに便利なように構成されています。特筆すべきは binfmt の設定をしてくれることです。

$ update-binfmts --display qemu-arm
qemu-arm (enabled):
     package = qemu-user-static
        type = magic
      offset = 0
       magic = \x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00
        mask = \xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff
 interpreter = /usr/bin/qemu-arm-static
    detector = 
$ cat /proc/sys/fs/binfmt_misc/qemu-arm
enabled
interpreter /usr/bin/qemu-arm-static
flags: OC
offset 0
magic 7f454c4601010100000000000000000002002800
mask ffffffffffffff00fffffffffffffffffeffffff

binfmt は Linuxバイナリのロード/実行の方法(インタプリタの選択)を指定できる仕組みです。マジックナンバーで識別/特定されたバイナリは指定のインタプリタで実行されます。

これは、実行可能ファイルの先頭2バイトが '#!' の場合に先頭行に記述されたインタプリタに実行が任される、shebang の仕組みに似ています。

ちなみに、qemu-user-static が設定する binfmt は ARM 以外もいっぱいあります。

$ ls /proc/sys/fs/binfmt_misc/
jar         qemu-armeb       qemu-mipsel      qemu-sh4eb        status
python2.7   qemu-cris        qemu-ppc         qemu-sparc
python3.2   qemu-m68k        qemu-ppc64       qemu-sparc32plus
qemu-alpha  qemu-microblaze  qemu-ppc64abi32  qemu-sparc64
qemu-arm    qemu-mips        qemu-sh4         register

hello.c のコンパイル(static link)

$ hello-c >hello.c
$ CC=arm-linux-gnueabihf-gcc
$ CFLAGS=-static make hello

$ ./hello            # binfmt の設定により、そのまま実行可能
hello, world
$ qemu-arm ./hello  # エミュレータを指定して実行
hello, world
$ qemu-arm-static ./hello  # エミュレータ(static版)を指定して実行
hello, world

hello-c は hello.c を出力する bash 関数 - lnzntのプログラミング日記 - プログラマの秘密のあれこれ で書いた hello.c を出力する bash関数です。

hello.c のコンパイル(dynamic link)

$ hello-c >hello.c
$ CC=arm-linux-gnueabihf-gcc
$ make hello

$ qemu-arm -L /usr/arm-linux-gnueabihf ./hello  # 実行
hello, world

実行する場合は、通常版のエミュレータ(qemu-arm)に -L オプションとしてインタプリタのパスの prefix を指定する必要があります。

chroot、jail、あるいは仮想環境化などで ARM バイナリが動く環境などを作ってやればいいと思うんですが、とりあえず以下のような対処でそのまま実行が可能です。

# ローダと共有ライブラリのディレクトリのシンボリックリンクを /lib に作る
$ cd /lib/
$ sudo ln -s /usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3 .
$ sudo ln -s /usr/arm-linux-gnueabihf/lib arm-linux-gnueabihf

$ ./hello           # そのまま実行可能
hello, world
$ qemu-arm ./hello  # エミュレータを指定して実行
hello, world
$ qemu-arm-static ./hello  # エミュレータ(static版)を指定して実行
hello, world

(2013.11.30 追記)

hard float でない版の場合は、上記のシンボリックリンクを作る作業を以下のようにする。

$ cd /lib/
$ sudo ln -s /usr/arm-linux/gnueabi/lib/ld-linux.so.3 ld-linux-arm.so.3
$ sudo ln -s /usr/arm-linux/gnueabi/lib arm-linux-gnueabi

Ubuntu 12.04 で Linux KVM のネットワークのブリッジ設定

00:45 | Ubuntu 12.04 で Linux KVM のネットワークのブリッジ設定 - Going My Linux Way を含むブックマーク はてなブックマーク - Ubuntu 12.04 で Linux KVM のネットワークのブリッジ設定 - Going My Linux Way Ubuntu 12.04 で Linux KVM のネットワークのブリッジ設定 - Going My Linux Way のブックマークコメント

Linux KVMネットワークNAT で設定していましたが、ブリッジにしてみました。

現在の環境

以下、手順。

$ sudo ifconfig eth0 0.0.0.0 promisc up
$ sudo brctl addbr br0
$ sudo brctl addif br0 eth0
$ sudo ifconfig br0 192.168.1.101 netmask 255.255.255.0 up
$ sudo route add default gw 192.168.1.1

virt-manager仮想マシンの詳細を表示して、「仮想ネットワークインターフェイス」ソースデバイスで「共有デバイス名を指定」を選択してブリッジ名に「br0」を設定する。

以降は、仮想マシンを通常通り起動する。

仮想マシンNICIP が 192.168.1.0/24 のアドレスになっているはずである。

その IPアドレスでホストOSからゲストOSへ通信ができる。

/etc/network/interfaces の設定

$ cat /etc/network/interfaces 
auto lo
iface lo inet loopback

auto eth0
#iface eth0 inet dhcp
iface eth0 inet static
	address 0.0.0.0

#	address 192.168.1.101
#	netmask 255.255.255.0
#	gateway 192.168.1.1

auto br0
#iface eth0 inet dhcp
iface br0 inet static
	address 192.168.1.101
	netmask 255.255.255.0
	gateway 192.168.1.1
	bridge_ports eth0

リブート後の状態

$ a a i r
alias a='alias'
alias i='ifconfig -a'
alias r='route'

$ i
br0       Link encap:イーサネット  ハードウェアアドレス 00:25:22:5e:ec:d1  
          inetアドレス:192.168.1.101  ブロードキャスト:192.168.1.255  マスク:255.255.255.0
          inet6アドレス: 2001:c90:1028:12a7:70c6:3acf:fdcf:9152/64 範囲:グローバル
          inet6アドレス: 2001:c90:1028:12a7:225:22ff:fe5e:ecd1/64 範囲:グローバル
          inet6アドレス: fe80::225:22ff:fe5e:ecd1/64 範囲:リンク
          UP BROADCAST RUNNING MULTICAST  MTU:1500  メトリック:1
          RXパケット:14 エラー:0 損失:0 オーバラン:0 フレーム:0
          TXパケット:19 エラー:0 損失:0 オーバラン:0 キャリア:0
          衝突(Collisions):0 TXキュー長:0 
          RXバイト:1513 (1.5 KB)  TXバイト:1701 (1.7 KB)

eth0      Link encap:イーサネット  ハードウェアアドレス 00:25:22:5e:ec:d1  
          UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1500  メトリック:1
          RXパケット:17 エラー:0 損失:0 オーバラン:0 フレーム:0
          TXパケット:20 エラー:0 損失:0 オーバラン:0 キャリア:0
          衝突(Collisions):0 TXキュー長:1000 
          RXバイト:1972 (1.9 KB)  TXバイト:1707 (1.7 KB)
          割り込み:43 ベースアドレス:0x4000 

                  :
                 (略)
                  :               

$ r -n
カーネルIP経路テーブル
受信先サイト    ゲートウェイ    ネットマスク   フラグ Metric Ref 使用数 インタフェース
0.0.0.0         192.168.1.1     0.0.0.0         UG    100    0        0 br0
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 br0
192.168.122.0   0.0.0.0         255.255.255.0   U     0      0        0 virbr0

$ brctl show
bridge name	bridge id		STP enabled	interfaces
br0		8000.0025225eecd1	no		eth0
virbr0		8000.000000000000	yes		

*1チュートリアルでは、バージョン管理のリポジトリの場所を使うのが良い、と書かれてます。