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を実行する際のパスを設定することができる。
例えば、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を修正するとすると、以下のように解決できる。
// 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の修正がリリースされてないが、もう少ししたらここに悩むことは無くなりそう!