BundlerでCのソースを含んだGemは簡単に作れる


#コマンドの確認
`bundler help gem`を確認

```
➜  jewelrybox  bundler help gem
Usage:
  bundler gem GEM [OPTIONS]

Options:
  -b, [--bin=Generate a binary for your library.]
  -t, [--test=Generate a test directory for your library: 'rspec' is the default, but 'minitest' is also supported.]
  -e, [--edit=/path/to/your/editor]                                                                                   # Open generated gemspec in the specified editor (defaults to $EDITOR or $BUNDLER_EDITOR)
      [--ext=Generate the boilerplate for C extension code]
      [--no-color=Disable colorization in output]
  -V, [--verbose=Enable verbose output mode]
  -r, [--retry=Specify the number of times you wish to attempt network commands]

Creates a skeleton for creating a rubygem
```

`--ext`でC拡張用のボイラープレートが出来るとある。ついでに`-t minitest`でテスト生成。

#ひな形の生成
`bundle gem --ext -t minitest diamond`


```
➜  jewelrybox  bundle gem --ext -t minitest diamond
      create  diamond/Gemfile
      create  diamond/Rakefile
      create  diamond/LICENSE.txt
      create  diamond/README.md
      create  diamond/.gitignore
      create  diamond/diamond.gemspec
      create  diamond/lib/diamond.rb
      create  diamond/lib/diamond/version.rb
      create  diamond/test/minitest_helper.rb
      create  diamond/test/test_diamond.rb
      create  diamond/.travis.yml
      create  diamond/ext/diamond/extconf.rb
      create  diamond/ext/diamond/diamond.h
      create  diamond/ext/diamond/diamond.c
Initializing git repo in /Users/ymmtmdk/mygem/jewelrybox/diamond
```

#.gemspecの編集
`diamond.gemspec`の`spec.summary`にこのGemの概要を書く。必須。`spec.description`はとりあえずコメントアウト。

```ruby:diamond.gemspec
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'diamond/version'

Gem::Specification.new do |spec|
  spec.name          = "diamond"
  spec.version       = Diamond::VERSION
  spec.authors       = ["ymmtmdk"]
  spec.email         = ["ymmtmdk@gmail.com"]
  spec.extensions    = ["ext/diamond/extconf.rb"]
  spec.summary       = "the perfectest Gem in the world"
#  spec.description   = %q{TODO: Write a longer description. Optional.}
  spec.homepage      = ""
  spec.license       = "MIT"

  spec.files         = `git ls-files -z`.split("\x0")
  spec.executables   = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
  spec.test_files    = spec.files.grep(%r{^(test|spec|features)/})
  spec.require_paths = ["lib"]

  spec.add_development_dependency "bundler", "~> 1.7"
  spec.add_development_dependency "rake", "~> 10.0"
  spec.add_development_dependency "rake-compiler"
  spec.add_development_dependency "minitest"
end

```

#Cコードの編集
`diamond/ext/diamond/diamond.c`をがりがり書く

```c:diamond.c
#include "diamond.h"

static VALUE
piece_price(VALUE self)
{
  return INT2NUM(10000000);
}

void
Init_diamond(void)
{
  VALUE rb_mDiamond = rb_define_module("Diamond");
  VALUE rb_mPiece = rb_define_class_under(rb_mDiamond, "Piece", rb_cObject);
  rb_define_method(rb_mPiece, "price", piece_price, 0);
}

```

#コンパイルしてみる
`rake compile`でエラーが出ないか確認

```
➜  diamond git:(master) ✗ rake compile
mkdir -p tmp/x86_64-darwin13/diamond/2.2.0
cd tmp/x86_64-darwin13/diamond/2.2.0
/Users/ymmtmdk/.rvm/rubies/ruby-head/bin/ruby -I. ../../../../ext/diamond/extconf.rb
creating Makefile
cd -
cd tmp/x86_64-darwin13/diamond/2.2.0
make
compiling ../../../../ext/diamond/diamond.c
linking shared-object diamond/diamond.bundle
cd -
mkdir -p tmp/x86_64-darwin13/stage/lib/diamond
install -c tmp/x86_64-darwin13/diamond/2.2.0/diamond.bundle lib/diamond/diamond.bundle
cp tmp/x86_64-darwin13/diamond/2.2.0/diamond.bundle tmp/x86_64-darwin13/stage/lib/diamond/diamond.bundle
```

#テストを書く
`diamond/test/test_diamond.rb`を完璧に仕上げる

```ruby:test_diamond.rb
require 'minitest_helper'

class TestDiamond < MiniTest::Unit::TestCase
  def test_that_it_has_a_version_number
    refute_nil ::Diamond::VERSION
  end

  def test_i_cant_buy_the_price_of_the_gem
    assert Diamond::Piece.new.price > 30
  end
end
```
#テスト実行

`rake test`

```
➜  diamond git:(master) ✗ rake test
MiniTest::Unit::TestCase is now Minitest::Test. From /Users/ymmtmdk/mygem/jewelrybox/diamond/test/test_diamond.rb:3:in `<top (required)>'
Run options: --seed 53137

# Running:

..

Finished in 0.002090s, 956.9378 runs/s, 956.9378 assertions/s.

2 runs, 2 assertions, 0 failures, 0 errors, 0 skips
➜  diamond git:(master) ✗
```

#.gemの生成

`rake build`

```
➜  diamond git:(master) ✗ rake build
diamond 0.0.1 built to pkg/diamond-0.0.1.gem.
```

成功すれば`pkg/diamond-0.0.1.gem`が出来る。
あら簡単。

参考: [BundlerでC拡張を含んだgemを公開する](http://qiita.com/gam0022/items/2ee82e84e5c9f608eb85)