拡張ライブラリの gem をつくる

よくわかってませんが、メモがてら

bundler

gem ファイルを作るのに便利なツールが色々あるようですが、 bundler を使ってみます。

まずは雛形を作成します。ここでは testlib という名前にしました。

$ bundle gem testlib
      create  testlib/Gemfile
      create  testlib/Rakefile
      create  testlib/LICENSE.txt
      create  testlib/README.md
      create  testlib/.gitignore
      create  testlib/testlib.gemspec
      create  testlib/lib/testlib.rb
      create  testlib/lib/testlib/version.rb
Initializating git repo in /home/foo/testlib
$ cd testlib

自動的に各ファイルや git リポジトリが生成されます。このとき作成された testlib.gemspec に色々書きこむのですが、それは一旦置いときます。

ext

$ mkdir ext
$ mkdir ext/testlib
$ vim ext/testlib/extconf.rb
$ vim ext/testlib/testlib_core.c
$ git add ext

ext ディレクトリを作成し、 extconf.rb と拡張ライブラリのコードを記述します。ここでは拡張ライブラリを testlib_core という名前にしています。

書き方については「LoveRubyNet Wiki: RubyExtensionProgrammingGuide」や Rubyソースコード付属の README.EXT.ja などに載っています。

ここで、必ず git add をしておきます。後述の gemspec ファイル内で git ls-files を利用してファイルの一覧を取得しているからです。

lib

自動的に生成された lib/testlib.rb を編集します。

require "testlib/version"

module Testlib
  # Your code goes here...
end

次の行を1行目に追加して、拡張ライブラリとしてコンパイルされる testlib_core を読み込むようにします。

require 'testlib_core'

gemspec

で、次は testlib.gemspec について編集します。

# -*- encoding: utf-8 -*-
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'testlib/version'

Gem::Specification.new do |gem|
  gem.name          = "testlib"
  gem.version       = Testlib::VERSION
  gem.authors       = ["Author"]
  gem.email         = ["Author@email.com"]
  gem.description   = %q{TODO: Write a gem description}
  gem.summary       = %q{TODO: Write a gem summary}
  gem.homepage      = ""

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

authors と email は ~/.gitconfig を見て自動で設定されるようです。 description や summary は適切な説明に変更する必要があります("TODO" が含まれたままだとエラーになる)。拡張ライブラリを扱うために以下のように追加・変更します。

Gem::Specification.new do |gem|
  gem.extensions   << "ext/testlib/extconf.rb"

  # gem.require_paths = ["lib"] を
  gem.require_paths = ["ext", "lib"]
end

ビルド

$ rake build
testlib 0.0.1 built to pkg/testlib-0.0.1.gem

rake build で gem ファイルが作成されます。

デバッグ

$ gem install pkg/testlib-0.0.1.gem

gem ファイルからインストールを行い、ちゃんと動くか確認。デバッグなどを行います。

その他

git でソースを管理したり、 Rubygems に登録(rake release)したりします。この段階になれば、ググればいろいろ出てきます。

注釈

今回は bundle gem の雛形を基本そのまま用いたので(バージョン情報の管理のため) lib/testlib.rb や lib/testlib/version.rb を使うことが前提でした。そのため、 C で記述する拡張ライブラリ自体の名前は ext/testlib/testlib_core.so にして、 lib/testlib.rb から呼び出す形にしてあります。

もちろん testlib.gemspec を適切に修正すれば *.rb ファイルを経由させず、 testlib.so という名前の拡張ライブラリにすることもできます。