extconf.rbについて調べたことメモ

目的

RubyのgemのC実装を読む際に、extconf.rb周りでエラーが起きるのだが、そもそもこれが何するものかが良くわからなかったので調べた。

結論

これを読めば良い。 docs.ruby-lang.org

自分用のメモは間違えてるかもしれないので、注意してください。

自分用にメモ

Ruby の拡張ライブラリのための Makefile を作成するファイル。mkmfライブラリをrequireして、このrbスクリプトを実行して、Makefileが生成される。 ヘッダファイルの存在チェック、ライブラリの存在チェックなどextconf.rbで行う。

// gemspec にこんな感じでファイルを指定する。
spec.extensions    = ['ext/extconf.rb']

こうすると、gem install時に、make コマンドを実行して、実行環境に合わせてコンパイルしてくれる。

詳細はこのサイトに詳しく書いてあるので参考に。

gem install で C拡張をビルドする流れを追ってみた - sonots:blog

dir_config というメソッドがあるが、これを用いると、依存packageを実行する際のパスを設定することができる。

docs.ruby-lang.org

例えば、duckdbだと、gem install時に、以下のように設定することで、gem毎に参照するディレクトリを設定できる。

--with-duckdb-include=/duckdb_header_directory
--with-duckdb-lib=/duckdb_library_directory

あるいは、/duckdb_directoryの下に、includeとlibディレクトリがあって、includeの方にはheaderファイルがある、libの方には共有ライブラリがあるという状態なら以下の設定だけでいける。

--with-duckdb-dir=/duckdb_directory

homebrewだと、こんな感じで指定できるはず!

--with-duckdb-dir=$(brew --prefix duckdb)

もし、gem毎に設定する必要がなければ、CFLAGSとLDFLAGSを環境変数で設定しても参照できる。

CFLAGSとLDFLAGSについて

自信あまりないので、違ったらご指摘ください...

CFLAGS: Cのsourceファイルをbuildする時に使う(Cのコンパイラーに渡すフラグ)

コンパイラーにCのビルドしたい標準の場所以外にあるファイルの位置を教えてあげる時に使える。

LDFLAGSS: ld(リンカー)に渡すフラグ

ビルドする際は、複数の.cファイルを.soファイルにまとめている。

リンカーは複数のビルド済みのファイルを、くっつけて使えるようにする。

そのリンカーに、標準の場所以外にあるファイルの位置を教えてあげるときに、LDFLAGS -L{path} という形で使える。

Rails & mysql2 gem

Mac & homebrewを利用している環境で、Railsでmysql2のgemを利用しようとすると、毎回ld: library not found for -lsslというエラーが出る。

これは、下の記事にあるように、ライブラリが見つからないとのことなので、pathを通してあげればいい。

【Ruby】M1macでmysql2がインストールできないとき

といった感じで、個々人では解決できる。

ここで、もしexconf.rbを修正するとすると、以下のように解決できる。

Dynamically set Homebrew-installed OpenSSL flag by olivierlacan · Pull Request #1204 · brianmario/mysql2 · GitHub

// homebrewを使っていて、OSがdarwin = macの場合、LDFLAGSに値を追加している。
if RUBY_PLATFORM =~ /darwin/ && system("command -v brew")
  openssl_location = `brew --prefix openssl`.strip
  if openssl_location
    $LDFLAGS << " -L#{openssl_location}/lib" 
  end
end

例えば、LDFLAGS="-L/opt/homebrew/opt/openssl/bin" と設定すると、/opt/homebrew/opt/openssl/bin以下のライブラリを検索してくれる。

こうすることで、毎回$ bundle config --local build.mysql2 "--with-ldflags=-L/opt/homebrew/opt/openssl/lib"みたいに手動でやらなくてもエラーなくインストールができる。

現時点のmysql2最新版である0.5.3では、まだexconf.rbの修正がリリースされてないが、もう少ししたらここに悩むことは無くなりそう!