2011/06/06

CoffeeScriptのインストール

Mac OS XにCoffeeScriptをインストールしたときのメモ。

環境

  • Mac OS X 10.6.7 
  • Node.js 0.4.6
  • npm 1.0.9-1
  • CoffeScript 1.1.1

Node.jsのインストール

まずNode.jsをインストール。MacPortsでインストールできます。
$ sudo port install nodejs
$ node -v
v0.4.6

npmのインストール

次にnpmのインストール。インストール自体はスクリプト一発で終わりますが、スクリプトの実行前に /opt/local/ のアクセス権限を変更しておかないと、パーミッションエラーが出るので注意が必要です。
$ sudo chmod -R g+w /opt/local/
$ curl http://npmjs.org/install.sh | sh
$ npm -v
1.0.9-1

CoffeeScriptのインストール

ようやくCoffeeScriptのインストールです。インストールには、先ほど入れたnpmを使います。
$ npm install -g coffee-script
$ coffee -v
CoffeeScript version 1.1.1

CoffeeScriptでHello World

CoffeeScriptでお約束のHello Worldしてみます。CoffeeScriptファイルの拡張子は.coffeeです。
$ cat hello_world.coffee 
console.log 'Hello, world!'
上記のCoffeeScriptファイルをcoffeeコマンドでJavaScriptファイルに変換します。
$ coffee -c hello_world.coffee
生成されたJavaScriptファイルをNode.jsで実行してみます。
$ node hello_world.js 
Hello, world!
おー、実行できましたね。パチパチ。
ちなみに、以下のようなjsファイルに変換されています。
$ cat hello_world.js
(function() {
console.log('Hello, world!');
}).call(this);
なお、JavaScriptファイルに変換せず直接実行することも可能です。
$ coffee hello_world.coffee 
Hello, world!

参考

2011/05/11

Mac OS Xにpacoをインストールしてみた

pacoをMac OS Xにインストールしたときのメモ。
pacoはソースコンパイルでインストールしたパッケージを管理できる便利なツールです。pacoを使えば、どこになんのパッケージが入っているのかわからないとか、アンインストールできないといった事態に陥らずに済むため、僕のような神経質な人間には必須といえるソフトです。
pacoはMac対応をうたっていない上に、READMEに以下のような記述がありBSD系のMac OS Xでは動かないようにも見えますが、問題なくインストールできました。

Note: Paco does not work on systems in which binaries are linked statically,
      like FreeBSD or OpenBSD.

pacoの詳しい使い方について知りたい人は、以下のサイトを参考にしてください。

"make install"したソフトウェアを管理できる超便利ツール「Paco」

環境

環境は以下のとおりです。
  • Mac OS X 10.6.6
  • paco 2.0.9

pacoのインストール

アーカイブをpacoのサイトからダウンロードしてインストールします。

$ tar zxvf paco-2.0.9.tar.gz
$ cd paco-2.0.9
$ ./configure

すると、僕の環境では以下のようなエラーが発生しました。

checking for GTKMM... configure: error: Package requirements (gtkmm-2.4 >= 2.12) were not met:

No package 'gtkmm-2.4' found

Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.

Alternatively, you may set the environment variables GTKMM_CFLAGS
and GTKMM_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.

どうやらGpaco(GUI版のpaco)をインストールするのにgtkmmが必要なようです。gtkmmはMacPortsに入っています。

$ sudo port install gtkmm

再度pacoをインストールします。

$ ./configure
$ make
$ sudo make install

今度は問題なくインストールが完了しました。
pacoのインストールが終わったら、paco自身をpacoで管理してみます。

$ sudo make logme

paco -aコマンドでインストールしたパッケージ一覧を表示できます。

$ paco -a
paco-2.0.9

ちゃんと表示されました。
というわけで、pacoはMac OSでも正常に動作するようです。

参考

2011/05/01

MacBook AirにMacPortsとGitをインストールしたときのメモ

最近MacBook Airでノマドワーキングすることが多くなったので、母艦のMacBookだけでなくMacBook AirにもMacPortsやらGitやらをインストールしておこうと思い立ちました。しかし、以前インストールしたときの手順をすっかり忘れてしまっていたので、Google先生を使ってあれこれ調べるはめに…。せっかくなので、今回インストールしたときの手順を備忘録としてメモしておきます。
環境は以下のとおりです。
  • Mac OS X 10.6.6
  • Xcode 3.2.6
  • MacPorts 1.9.2
  • Git 1.7.5
まず、MacPorts本家(http://www.macports.org/)でSnow Leopard用のインストーラをダウンロードします。あとはインストーラを実行してインストール完了、といきたいところでしたが、以下のようなエラーが発生しました。
Xcode is not installed, or was installed with UNIX Development (10.5+) or Command Line Support (10.4) deselected.
「Xcodeがインストールされてないよ!」といわれてしまいました。えー、インストールしてるんけど…。原因はよくわかりませんが、以前移行アシスタントを使って母艦から持ってきたXcodeだから正しく認識されていないのかも(思いっきり推測)。というわけで、Xcodeもインストールし直しました。
Apple Developerのサイト(http://developer.apple.com/jp/)にログインしてXcodeをダウンロードします。アプリ開発に影響が出そうだったので、Xcode 4ではなく3.2.6をインストールすることにしました。Xcodeをインストールし直したあとでMacPortsのインストーラを起動したところ、先ほどのエラーは出なくなりました。
MacPortsのインストール完了後、念のため以下のコマンドでMacPorts自身をアップデートしておきます。
$ sudo port selfupdate
$ sudo port sync
続いてGitのインストールです。まず、以下のコマンドでインストールオプションをチェック。
$ port variants git-core
git-core has the variants:
   bash_completion: Completion support for bash
[+]doc: Install HTML and plaintext documentation
   gitweb: Install gitweb.cgi
   python26: Use Python 2.6
     * conflicts with python27
[+]python27: Use Python 2.7
     * conflicts with python26
   svn: Bi-directional subversion repository support
   universal: Build for multiple architectures

gitwebとsvnもなんとなくインストールしておきました。
$ sudo port install git-core +gitweb +svn
以上で無事インストール完了です。

参考

2011/04/29

RubyでiPhoneアプリが開発できるRhodesフレームワークについて書いてみる

iPhoneアプリ開発に興味を持ってMacを買った人は多いと思いますが、Objective-Cの敷居の高さに挫折した人もまた多いと思います。僕もその1人です(だって、メソッド名とか引数とかものすごく長いんだもん…)。そんな人におすすめなのが、今回紹介するRhodesフレームワークです。Rhodesフレームワークを使えば、Ruby、HTML、CSS、JavaScriptといった馴染みのある技術を使ってiPhoneアプリを作ることができます。

Rhodesについて

RhodesはRubyでiPhoneアプリを開発するためのフレームワークです(正確にいうとiPhoneだけでなく、Android、BlackBerry、Windows Mobileのアプリを作ることができます)。Rhodesフレームワークを使えば、難解なObjective-Cではなく、Ruby、HTML、CSS、JavaScriptといった馴染みのある技術を使ってiPhoneアプリを作ることができます。フレームワーク自体はRailsライクのMVCフレームワークで、Railsを使ったことがある人ならすんなり馴染めると思います。

インストール

Rhodesはgemでインストールすることができます。
$ sudo gem install rhodes
インストールが終わったらセットアップスクリプトを実行します。iOS SDKのパスなどを設定していきます。
$ sudo rhodes-setup
これでインストールは完了です。簡単ですね。

RhodesでHello World

RhodesでHello Worldアプリを作ってみます。Rhodesでアプリを作る際の大まかな流れは以下のとおりです。

  1. プロジェクトを作る
  2. モデル、ビュー、コントローラを作る
  3. アプリをビルドする

1. プロジェクトの作成

rhodes appコマンドでプロジェクトを作成します。Railsでいうところのrailsコマンドです。
$ rhodes app hello_world
Generating with app generator:
     [ADDED]  hello_world/rhoconfig.txt
     [ADDED]  hello_world/build.yml
     [ADDED]  hello_world/app/application.rb
     [ADDED]  hello_world/app/index.erb
     [ADDED]  hello_world/app/index.bb.erb
     [ADDED]  hello_world/app/layout.erb
     [ADDED]  hello_world/app/loading.html
     [ADDED]  hello_world/Rakefile
     [ADDED]  hello_world/app/helpers
     [ADDED]  hello_world/icon
     [ADDED]  hello_world/app/Settings
     [ADDED]  hello_world/public
     [ADDED]  hello_world/app/loading.png
この時点でプロジェクトディレクトリは次のような構成になっています。

$ tree hello_world/ -d
hello_world/
├── app
│   ├── Settings
│   └── helpers
├── icon
└── public
    ├── css
    ├── images
    │   ├── android
    │   └── iphone
    │       └── jqtouch
    ├── jqtouch
    └── js

12 directories

各ディレクトリの大まかな説明は以下のとおりです。

app
モデル、ビュー、コントローラなどを置きます
icon
ホーム画面用のアイコンを置きます
public
JavaScript、CSS、画像ファイルなどを置きます

2. モデル、ビュー、コントローラの作成

プロジェクトを作成したら、次はモデル、ビュー、コントローラを作成します。モデル、ビュー、コントローラの作成にはrhodes modelコマンドを使用すると便利です。これはRailsでいうところのscaffoldコマンドに相当します。使用方法は以下のとおりです。
$ rhodes model <モデル名> <属性>
モデルは使わずビューとコントローラだけがほしい場合でも、属性は省略することはできません。その場合は、適当な値を入れておいてください。

$ rhodes model hello_world id
Generating with model generator:
     [ADDED]  app/HelloWorld/index.erb
     [ADDED]  app/HelloWorld/edit.erb
     [ADDED]  app/HelloWorld/new.erb
     [ADDED]  app/HelloWorld/show.erb
     [ADDED]  app/HelloWorld/index.bb.erb
     [ADDED]  app/HelloWorld/edit.bb.erb
     [ADDED]  app/HelloWorld/new.bb.erb
     [ADDED]  app/HelloWorld/show.bb.erb
     [ADDED]  app/HelloWorld/hello_world_controller.rb
     [ADDED]  app/HelloWorld/hello_world.rb
     [ADDED]  app/test/hello_world_spec.rb

これでモデル、ビュー、コントローラが生成されました。生成されたファイルの大まかな説明は以下のとおりです。
app/HelloWorld/hello_world.rb
モデル
app/HelloWorld/hello_world_controller.rb
コントローラ
app/HelloWorld/*.erb、app/HelloWorld/*.bb.erb
ビュー(*.bb.erbファイルはBlackBerry用のビュー)
app/test/hello_world_spec.rb
単体テストコード

RhodesはRailsと違って、1つのディレクトリの中にモデル、ビュー、コントローラのセットを置きます。

まずビューを編集してみます。

app/HelloWorld/index.erb
<div class="pageTitle">
  <h1>HelloWorlds</h1>
</div>

<div class="toolbar">
  <div class="leftItem regularButton">
    <a href="<%= Rho::RhoConfig.start_path %>">Home</a>
  </div>
  <div class="rightItem regularButton">
    <a class="button" href="<%= url_for :action => :new %>">New</a>
  </div>
</div>

<div class="content">
  <ul>
    <% @hello_worlds.each do |hello_world| %>
   
        <li>
          <a href="<%= url_for :action => :show, :id => hello_world.object %>">
            <span class="title"><%= hello_world.id %></span><span class="disclosure_indicator"></span>
          </a>
        </li>
   
    <% end %>
  </ul>
</div>

「Hello, world!」という文字列をコントローラで設定し、それをビューで表示するようにしてみましょう。18〜22行目を以下のように書き換えます。
        <li>
          <%= @message >
        </li>
@messageにコントローラで設定した文字列を入れることにします。

次にコントローラを編集します。indexアクションを以下のように書き換えます。

app/HelloWorld/hello_world_controller.rb
#GET /HelloWorld                                                                       
  def index                                                                              
    @message = @params['message']                                                        
    render                                                                               
  end     

@paramsでGETパラメータやPOSTパラメータの値を取得できます。この場合、messageパラメータの値を@messageに入れてビューに渡しています。

最後に、HelloWorldコントローラのindexアクションに文字列「Hello, world!」を渡すリンクをアプリのトップ画面に実装します。アプリのトップ画面はデフォルトではapp/index.erbです。

app/index.erb
<div class="pageTitle">
  <h1>HelloWorld</h1>
</div>

<div class="toolbar">
  <% if SyncEngine::logged_in > 0 %>
      <div class="leftItem blueButton">
        <a href="<%= url_for :controller => :Settings, :action => :do_sync %>">Sync</a>
      </div>
      <div class="rightItem regularButton">
        <a href="<%= url_for :controller => :Settings, :action => :logout %>">Logout</a>
      </div>
  <% else %>
      <div class="rightItem regularButton">
        <a href="<%= url_for :controller => :Settings, :action => :login %>">Login</a>
      </div>
  <% end %>
</div>

<div class="content">
  <ul>
    <li>
      <a href="#"><span class="title">Add link here...</span><span class="disclosure_indicator"/></a>
    </li>
  </ul>
</div>

23行目を以下のように書き換えます。
      <a href="<%= url_for :controller => :HelloWorld, :action => :index, :query => {:message => 'Hello, world!'} %>"><span class="title">Hello Wolrd Demo</span><span class="disclosure_indicator"/></a>

url_forはURLを組み立てるRhodesのヘルパーメソッドです(Railsにもありますね)。

3. ビルドする

Rhodesで作ったアプリをビルドするには以下のコマンドを実行します。ビルドが完了すると自動的にiPhoneシミュレータが起動し、アプリが立ち上がります。
$ rake run:iphone
トップ画面に先ほど実装したリンクが表示されていますね。


タッチしてみます。


画面遷移し、「Hello, world!」と表示されました。

まとめ

Rhodesを使ってHello Worldアプリを作ってみました。Rhodesを使えばObjective-Cで書くより圧倒的に少ないコード量でアプリを作ることができます。
ただし、RhodesはiOSのすべての機能をカバーしているわけではないので、その点は注意が必要です(http://docs.rhomobile.com/rhodes/device-caps)。とはいうものの、ツイッタークライアントなど、あまり凝ったUIを使わず、APIの実行結果を表示するだけアプリであれば十分作ることが可能です。複雑なタッチ操作や加速度センサをバリバリ使うようなアプリは難しいかな。
いずれ、ツイッターやフォースクエアのAPIを利用する例や、GPSを使用する例なども紹介したいと思います。

参考
Rhodesのページ http://rhomobile.com/
Rhodesドキュメントの日本語訳 http://ackcell.blogspot.com/

2011/04/25

SWIGを使ってRubyの拡張ライブラリを作る

Rubyは高い生産性を持つ言語ですが、反面パフォーマンスがいまいちです。Rubyで開発していてパフォーマンスが出ずに困った経験はないでしょうか?僕はあります。しかし、だからといってC/C++でスクラッチ開発すると死人が出てしまいます。そんなときは、SWIGを使ってRubyの拡張ライブラリを作ってみましょう。
SWIGはC/C++で書いたプログラムをRubyから呼び出せるようにするためのツールです。SWIGを使えば、全体はRubyで書き、特にパフォーマンスが要求される部分だけをC/C++で書くといったことが可能になります。

環境

環境は以下のとおりです。
  • Mac OS X 10.6.6
  • Ruby 1.8.7 p334
  • gcc 4.2.1
  • SWIG 2.0.3

SWIGのインストール

MacならMacPortsを使って簡単にインストールできます。

$ sudo port install swig
Rubyの拡張ライブラリを作るには、いっしょにRubyバインディングもインストールする必要があります。
$ sudo port install swig-ruby

サンプルプログラム

簡単なサンプルとして、C言語で書いたフィボナッチ数列を計算するプログラムを拡張ライブラリ化してみます。ソースコートは以下のとおりです。

fib.c
int fib(int n) {
    if (n == 0) {
        return 0;
    }
    if (n == 1) {
        return 1;
    }
    return fib(n - 1) + fib(n - 2);
}

fib.h
int fib(int n);

まずSWIG用のインタフェースファイルを書きます。インタフェースファイルには、モジュール名とモジュールから呼び出す関数を宣言します。

fib.i
%module fib

extern int fib(int n);

インタフェースファイルが書けたらswigコマンドを実行します。swigコマンドを実行すると、C言語の関数をRubyから呼び出すためのラッパーファイルを生成してくれます。

$ swig -ruby fib.i

ここまででSWIGの仕事は終わりです。
最後にソースファイルとラッパーファイルを使って共有ライブラリを作ります。Makefileを自分で書くのは面倒なので、extconf.rbに生成してもらいましょう。

extconf.rb
require 'mkmf'
create_makefile("fib")

$ ruby extconf.rb
$ make

C言語の関数をRubyから呼び出してみます。共有ライブラリをrequireすれば、通常のモジュール関数のように呼び出すことができます。
irb(main):001:0> require 'fib'
=> true
irb(main):003:0> puts Fib.fib(10)
55
=> nil
おー。無事呼び出せましたね。

ベンチマーク

ベンチマークを測定し、Rubyで書いたプログラムとパフォーマンスを比較してみました。

bench_fib.rb
#!/opt/local/bin/ruby
require 'fib'
require 'benchmark'

def fib(n)
  return 0 if n == 0
  return 1 if n == 1
  fib(n - 1) + fib(n - 2)
end

n = 30
Benchmark.bm(13) do |x|
  x.report("c fib(#{n}):")    { Fib.fib(n) }
  x.report("ruby fib(#{n}):") { fib(n) }
end

結果は以下のようになりました。やっぱりC言語は速い!

user     system      total        real
c fib(30):     0.010000   0.000000   0.010000 (  0.015184)
ruby fib(30):  2.170000   0.000000   2.170000 (  2.176323)

まとめ

SWIGを使ってRubyの拡張ライブラリを作る方法を紹介しました。SWIGを上手に使えば、Rubyの生産性とC/C++のパフォーマンスを同時に手に入れることが可能になります。Rubyで開発していてパフォーマンスが出ずに悩んでいる人は試してみてはいかがでしょうか。