本当に細かすぎて伝わらない上に困っているのが世界で @k0kubun くんと僕くらいというバグなのだが、ruby/erb
のリポジトリの直下で bundle exec irb
で irb を起動すると
$ bundle exec irb
Ignoring erb-4.0.2 because its extensions are not built. Try: gem pristine erb --version 4.0.2
>>
というような warning が出て、実際には rake-compiler
によってビルドされているのに、RubyGems 的には erb
の C extension がビルドされていないという状態になる不具合を直した。
最初は RubyGems の missing_extension?
の判定処理がおかしいので、その判定処理を直すことにしたのだが、このメソッドはあらゆる gem を require する時に呼ばれるメソッドで、その度に full_require_paths
, すなわち gemspec で指定されている、ロード対象となるパスすべてを操作するのはコストが高い、ということで最終的には bundler の方に処理を移動して、bundle exec して、直下に gemspec がある時だけ判定を行うということにした。
この判定というのがものすごく微妙な状態になっていて、普通に gem install
をした時は rubygems は gem.build_complete
というファイルを extension_dir
に作成し、そのファイルがある時はビルドされているという判定をしているのだけど、ruby/erb
などリポジトリの下で rake-compiler を使ってビルドする、irb を起動する、テストするというようなときは gem.build_complete
ファイルがないので C extension がビルド済みなのかを判定できない。
なので、ヒューリスティックに、lib
ディレクトリの下に gem と同名のバイナリ、または namespace の下に何かしらのバイナリがあるかなどで判定している。これ、rake-compiler の方と共同で同じようなビルド済みを判定するファイルを置くようにするのがいいんだろうけど、rake-compiler は tmp ディレクトリを使うなどしているので、上手なアーキテクチャが思いつかず一旦はこんな感じで直すことにした。