前回まででRuby 1.9.3-p327で単純なサンプルコードを実行するところまでできました。
Symbolにオープンクラスでパッチを当てて対応したわけですが、できればGecode/Rのソースコードを修正して1.9.3対応していきたいのでソースコードリポジトリを見つけようと思います。
公式サイトのProject Detailsを見ると、サイト内にSubversionリポジトリが存在することが分かりました。
でも今更Subversionって気もしますしGithubに展開されていないのかな〜と思って検索してみるとgautamc/gecoder-reduxというのを発見。READMEによると、
I wanted to run gecoder with ruby 1.9 and with the latest version of gecode.
とのことで私が求めてるのこれじゃん!しかし最終更新が1年前とこちらも動いているとは言い難い様子(・ω・)
Commit履歴を眺めたところ元のコードをbundler対応にしてspecを追加したものっぽい。
さっそくForkしてcloneしてみる。
$ cd /path/to/work
$ git clone git://github.com/iwazer/gecoder-redux.git
$ cd gecoder-redux
$ git co -b dev-for-osx
$ rvm use ruby-1.9.3-p327
$ rvm gemset create gecoder-redux
$ rvm use ruby-1.9.3-p327@gecoder-redux
$ echo 'rvm ruby-1.9.3-p327@gecoder-redux' > .rvmrc
$ git add -A
$ git commit -m 'change to rvm develop environment setting'
$ gem install bundler
$ bundle install
rvmで専用のgemsetを作って試そうとしています。
bundlerの指定バージョンが古くて失敗するのでGemfileのbundlerのバージョン指定を"~> 1.2.3"にしてみます。またrcovもRuby 1.9ではsimplecovを使うらしいので修正しました。
$ gem install bundler
$ bundle install
$ bundle exec rake -T
WARNING: 'require 'rake/rdoctask'' is deprecated. Please use 'require 'rdoc/task' (in RDoc 2.4.2+)' instead.
at /Users/iwazawa/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-0.9.2.2/lib/rake/rdoctask.rb
rake build # Build gem into pkg/
rake clobber_rcov # Remove rcov products for rcov
rake clobber_rdoc # Remove rdoc products
rake console[script] # Start IRB with all runtime dependencies loaded
rake gemcutter:release # Release gem to Gemcutter
rake gemspec # Generate and validate gemspec
rake gemspec:debug # Display the gemspec for debugging purposes, as jeweler knows it (not from the filesystem)
rake gemspec:generate # Regenerate the gemspec on the filesystem
rake gemspec:release # Regenerate and validate gemspec, and then commits and pushes to git
rake gemspec:validate # Validates the gemspec on the filesystem
rake git:release # Tag and push release to git.
rake install # Build and install gem using `gem install`
rake rcov # Analyze code coverage with tests
rake rdoc # Build the rdoc HTML Files
rake release # Release gem
rake rerdoc # Force a rebuild of the RDOC files
rake test # Run tests
rake version # Displays the current version
rake version:bump:major # Bump the major version by 1
rake version:bump:minor # Bump the a minor version by 1
rake version:bump:patch # Bump the patch version by 1
rake version:write # Writes out an explicit version.
rakeタスクの警告が出たが、rakeは動いた。試しにtestタスクを動かしてみませう。
$ bundle exec rake test
WARNING: 'require 'rake/rdoctask'' is deprecated. Please use 'require 'rdoc/task' (in RDoc 2.4.2+)' instead.
at /Users/iwazawa/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-0.9.2.2/lib/rake/rdoctask.rb
/Users/iwazawa/.rvm/rubies/ruby-1.9.3-p327/bin/ruby -I"lib:lib:test" -I"/Users/iwazawa/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-0.9.2.2/lib" "/Users/iwazawa/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-0.9.2.2/lib/rake/rake_test_loader.rb" "test/**/test_*.rb"
/Users/iwazawa/Dropbox/develop/github/gecoder-redux/lib/gecoder/bindings.rb:60:in `require': cannot load such file -- gecode (LoadError)
from /Users/iwazawa/Dropbox/develop/github/gecoder-redux/lib/gecoder/bindings.rb:60:in `load_bindings_lib'
:
gecodr-with-gecode gemのようにgecodeライブラリが内包されているわけではないためライブラリが見つからないと言われる。
そりゃそうだとREADMEを見ると
I need to manually install gecode-2.2.0 and then make sure ldconfig knows abt its libs. Hoping to update this gem to work with gecode-3.7.1.
最新版のgecodeはHopingということでgecode-2.2.0を公式サイトからダウンロードしてビルドします。
$ cd /path/to/build
$ wget http://www.gecode.org/download/gecode-2.2.0.tar.gz
$ tar zxvf gecode-2.2.0.tar.gz
$ cd gecode-2.2.0
$ ./configure prefix=/path/to/gecoder-redux/lib
$ make
$ make install
configureのprefixにgecoder-redux/libへのパスを指定している理由は、モジュールがライブラリを見つけられるようにビルドするためmkmfするextconf.rbがgecoder-redux/extにあって、その中で
:
ROOT = Pathname.new(File.dirname(__FILE__) + '/..').realpath
:
GECODE_LIB_DIR = "#{ROOT}/lib/lib"
GECODE_INCLUDE_DIR = "#{ROOT}/lib/include"
:
と書かれているので。
Gecodeのビルドは結構時間がかかりますが問題なく終了。続いてモジュールのビルドへ移ります。
$ cd /path/to/gecoder-redux/ext
$ ruby extconf.rb
$ make
compiling gecode.cc
cc1plus: warning: command line option "-Wdeclaration-after-statement" is valid for C/ObjC but not for C++
cc1plus: warning: command line option "-Wimplicit-function-declaration" is valid for C/ObjC but not for C++
In file included from /Users/iwazawa/Dropbox/develop/github/gecoder-redux/lib/include/gecode/int/linear.hh:1596,
from /Users/iwazawa/Dropbox/develop/github/gecoder-redux/lib/include/gecode/minimodel.hh:47,
from gecode.hh:12,
from gecode.cc:4:
/Users/iwazawa/Dropbox/develop/github/gecoder-redux/lib/include/gecode/int/linear/bool-scale.icc: In member function 'void Gecode::Int::Linear::ScaleBoolArray::update(Gecode::Space*, bool, Gecode::Int::Linear::ScaleBoolArray&)':
/Users/iwazawa/Dropbox/develop/github/gecoder-redux/lib/include/gecode/int/linear/bool-scale.icc:67: warning: implicit conversion shortens 64-bit value into a 32-bit value
:
う〜む、implicit conversion shortens 64-bit value into a 32-bit valueという、あまりよろしくなさそうな警告が大量に出ますね(汗)制約プログラミングの性格上、集合をビット演算で表現してたりしそうなので、ちゃんと動くかしら...
しかしmakeは最後まで流れるので、ひとまず警告には目をつぶってgecode.bundleというファイルが作成されている事を確認します。
OSXの場合これを、gecoder-redux/libの下にコピーすると実行できるはず。
$ cp -p gecode.bundle ../lib
$ cd ..
$ bundle exec rake test
WARNING: 'require 'rake/rdoctask'' is deprecated. Please use 'require 'rdoc/task' (in RDoc 2.4.2+)' instead.
at /Users/iwazawa/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-0.9.2.2/lib/rake/rdoctask.rb
/Users/iwazawa/.rvm/rubies/ruby-1.9.3-p327/bin/ruby -I"lib:lib:test" -I"/Users/iwazawa/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-0.9.2.2/lib" "/Users/iwazawa/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-0.9.2.2/lib/rake/rake_test_loader.rb" "test/**/test_*.rb"
/Users/iwazawa/Dropbox/develop/github/gecoder-redux/lib/gecoder/bindings.rb:60:in `require': dlopen(/Users/iwazawa/Dropbox/develop/github/gecoder-redux/lib/gecode.bundle, 9): Symbol not found: __ZTIN6Gecode6MSpaceE (LoadError)
Referenced from: /Users/iwazawa/Dropbox/develop/github/gecoder-redux/lib/gecode.bundle
Expected in: flat namespace
in /Users/iwazawa/Dropbox/develop/github/gecoder-redux/lib/gecode.bundle - /Users/iwazawa/Dropbox/develop/github/gecoder-redux/lib/gecode.bundle
あれ?まだリンクがうまくいってなさげ(´・ω・`)
nativeモジュールの作成経験が無く、さすがに自力で解決するのがキツいので、gecoder-with-gecodeのextと比べてみるとextconf.rbは同じなのにMakefileのRUBYLIBDIRとRUBYARCHDIRの値が直接パッチが当てられたかのような値に変更されている(・ω・)
< RUBYLIBDIR = /Users/iwazawa/.rvm/gems/ruby-1.9.3-p327/gems/gecoder-with-gecode-1.1.0/lib$(target_prefix)
< RUBYARCHDIR = /Users/iwazawa/.rvm/gems/ruby-1.9.3-p327/gems/gecoder-with-gecode-1.1.0/lib$(target_prefix)
---
> RUBYLIBDIR = $(sitelibdir)$(target_prefix)
> RUBYARCHDIR = $(sitearchdir)$(target_prefix)
この$(sitelibdir)と$(sitearchdir)の箇所を試しに/path/to/gecoder-redux/libと直接パスを与えてビルドし直してみると
$ bundle exec rake test
WARNING: 'require 'rake/rdoctask'' is deprecated. Please use 'require 'rdoc/task' (in RDoc 2.4.2+)' instead.
at /Users/iwazawa/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-0.9.2.2/lib/rake/rdoctask.rb
/Users/iwazawa/.rvm/rubies/ruby-1.9.3-p327/bin/ruby -I"lib:lib:test" -I"/Users/iwazawa/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-0.9.2.2/lib" "/Users/iwazawa/.rvm/gems/ruby-1.9.3-p327@global/gems/rake-0.9.2.2/lib/rake/rake_test_loader.rb" "test/**/test_*.rb"
Run options:
# Running tests:
F
Finished tests in 0.001256s, 796.1783 tests/s, 796.1783 assertions/s.
1) Failure:
test: GecoderRedux should probably rename this file and start testing for real. (TestGecoderRedux) [/Users/iwazawa/Dropbox/develop/github/gecoder-redux/test/test_gecoder-redux.rb:5]:
hey buddy, you should probably rename this file and start testing for real
1 tests, 1 assertions, 1 failures, 0 errors, 0 skips
流れた。テストが失敗するのはデフォルトのテストファイルが失敗のものしかないからですね。
というかspecsディレクトリの方にspecファイル群があるけどどうやって実行するんだ?
Rakeタスクにdeprecatedの警告が出てますので、ひとまずそれを取ります。警告からRakefileの45行目をrequire 'rdoc/task'に変えれば良い。
ここまでの作業をgitにコミットしておきます。
extの下はMakefileには個人環境のパスが含まれるしgecode.{cc|hh}は自動生成されるのでgitの管理から外します。
$ cd ext
$ make distclean
$ cd ..
$ git rm ext/Makefile ext/gecode.* ext/mkmf.log ext/*.o
$ rm Gemfile.lock
$ vi .gitignore
## 追加
# for gecode lib
ext/Makefile
ext/gecode.*
ext/*.o
ext/mkmf.log
lib/bin
lib/gecode.bundle
lib/include
lib/lib
Gmefile.lock
$ git ad .gitignore
$ git commit -m 'ignore generated files'
$ git add Rakefile
$ git commit -m 'fix deprecated'
$ git add Gemfile
$ git commit -m 'use new version gem'
まだビルド環境を整えているだけですがGitHubに経過をあげておきます。
https://github.com/iwazer/gecoder-redux
今回はここまで。