LoginSignup
23
24

More than 5 years have passed since last update.

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

Last updated at Posted at 2014-10-07

コマンドの確認

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.gemspecspec.summaryにこのGemの概要を書く。必須。spec.descriptionはとりあえずコメントアウト。

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をがりがり書く

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を完璧に仕上げる

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を公開する

23
24
0

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
23
24