Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

コマンドの確認

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

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away