Edited at

Windows用バイナリGemをMacでクロスコンパイルする

More than 3 years have passed since last update.


昨今、Unix環境ではそれぞれのマシンでRubyをビルドし、native gemをビルドするのが一般的になっています。一方、Windowsでは未だにCコンパイラを導入している環境は少数派ですので、バイナリgemの配布が望まれています。しかし、Windows用バイナリgemを2.0.0/2.1/2.2と32bit/64bitで6バージョンビルドするのは誰にとっても負担です。


rake-compiler-dock is awesome

そんな状況を解決するスーパーライフチェンジングなgemがrake-compiler-dockです。詳しくはREADMEの通りですが、Docker Toolboxをインストールした環境でrake-compiler-dockをサポートしたgemをbundle exec rake build:windowsとすると、dockerでビルド用のLinux環境が立ち上がり、しばらく待つとローカルにpkg/-x86-mingw32.gemと-x64-mingw32.gemができあがります。便利!

以下のような変更を行えば導入できますので、是非皆さん導入しましょう。

diff --git a/Rakefile b/Rakefile

index 84443f9..dbfb045 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,4 +1,5 @@
-require "bundler/gem_tasks"
+require "bundler"
+Bundler::GemHelper.install_tasks
require "rspec/core/rake_task"

RSpec::Core::RakeTask.new(:spec)
@@ -9,6 +10,19 @@ require "rake/extensiontask"
task :build => :compile
task :spec => :compile

-Rake::ExtensionTask.new("strptime") do |ext|
- ext.lib_dir = "lib/strptime"
+spec = eval File.read("strptime.gemspec")
+Rake::ExtensionTask.new("strptime", spec) do |ext|
+ ext.ext_dir = 'ext/strptime'
+ ext.cross_compile = true
+ ext.lib_dir = File.join(*['lib', 'strptime', ENV['FAT_DIR']].compact)
+ # cross_platform names are of MRI's platform name
+ ext.cross_platform = ['x86-mingw32', 'x64-mingw32']
+end
+
+namespace :build do
+ desc 'Build gems for Windows per rake-compiler-dock'
+ task :windows do
+ require 'rake_compiler_dock'
+ RakeCompilerDock.sh 'bundle && rake cross native gem RUBY_CC_VERSION=2.0.0:2.1.6:2.2.2'
+ end
end
diff --git a/lib/strptime.rb b/lib/strptime.rb
index 049d0c1..c18c7e2 100644
--- a/lib/strptime.rb
+++ b/lib/strptime.rb
@@ -1,5 +1,9 @@
require "strptime/version"
-require "strptime/strptime"
+begin
+ require "strptime/#{RUBY_VERSION[/\d+\.\d+/]}/strptime"
+rescue LoadError
+ require "strptime/strptime"
+end

class Strptime
# Your code goes here...
diff --git a/strptime.gemspec b/strptime.gemspec
index df30440..7b0a8e4 100644
--- a/strptime.gemspec
+++ b/strptime.gemspec
@@ -23,6 +23,6 @@ Gem::Specification.new do |spec|

spec.add_development_dependency "bundler"
spec.add_development_dependency "rake"
spec.add_development_dependency "rake-compiler"
+ spec.add_development_dependency 'rake-compiler-dock'
spec.add_development_dependency "rspec"
diff --git a/README.md b/README.md
index 29185fa..c5b8da5 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
# Strptime

[![Build Status](https://travis-ci.org/nurse/strptime.png)](https://travis-ci.org/nurse/strptime)
+[![Build status](https://ci.appveyor.com/api/projects/status/9wr116l8uy1bdcxf/branch/master?svg=true)](https://ci.appveyor.com/project/nurse/strptime/branch/master)
+

Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/strptime`. To experiment with that code, run `bin/console` for an interactive prompt.

diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..d848da2
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,16 @@
+---
+install:
+ - SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
+ - ruby --version
+ - gem --version
+ - bundle install
+build_script:
+ - bundle exec rake -rdevkit
+environment:
+ matrix:
+ - ruby_version: "200"
+ - ruby_version: "200-x64"
+ - ruby_version: "21"
+ - ruby_version: "21-x64"
+ - ruby_version: "22"
+ - ruby_version: "22-x64"

なお、ついでにAppVeyorの設定もの設定も載せているのでご活用ください。