Windows10でcurbをbundle installしたら、Can’t find libcurl or curl/curl.h

Linuxで作成したスクリプトをWindowsでexe化しようとしてハマったのでそのメモです。
環境はWindows10、Ruby 3.0です。

bundle install でGemfileに記載した「curb」をインストールしようとしたところ、エラーが発生しインストールが行えませんでした。


発生したエラー

どうやら、「Can’t find libcurl or curl/curl.h (RuntimeError)」このあたりにヒントがありそうです。

PS E:\test> bundle install
Fetching gem metadata from https://rubygems.org/......
Resolving dependencies...
Using bundler 2.2.9
Using cgi 0.2.0
Fetching childprocess 3.0.0
Installing childprocess 3.0.0
Fetching curb 0.9.11
Installing curb 0.9.11 with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

current directory:
E:/test/vendor/bundle/ruby/3.0.0/gems/curb-0.9.11/ext
E:/Ruby/Ruby30-x64/bin/ruby.exe -I E:/Ruby/Ruby30-x64/lib/ruby/3.0.0 -r      
./siteconf20210214-10672-vrsxmm.rb extconf.rb
checking for curl-config... no
checking for -lcurl... no
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary     
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
        --with-opt-dir
        --without-opt-dir
        --with-opt-include
        --without-opt-include=${opt-dir}/include
        --with-opt-lib
        --without-opt-lib=${opt-dir}/lib
        --with-make-prog
        --without-make-prog
        --srcdir=.
        --curdir
        --ruby=E:/Ruby/Ruby30-x64/bin/$(RUBY_BASE_NAME)
        --with-curl-dir
        --without-curl-dir
        --with-curl-include
        --without-curl-include=${curl-dir}/include
        --with-curl-lib
        --without-curl-lib=${curl-dir}/lib
        --with-curllib
        --without-curllib
extconf.rb:18:in `<main>':   Can't find libcurl or curl/curl.h (RuntimeError)

  Try passing --with-curl-dir or --with-curl-lib and --with-curl-include
  options to extconf.

To see why this extension failed to compile, please check the mkmf.log which can
be found here:

E:/test/vendor/bundle/ruby/3.0.0/extensions/x64-mingw32/3.0.0/curb-0.9.11/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in
E:/test/vendor/bundle/ruby/3.0.0/gems/curb-0.9.11 for inspection.
Results logged to
E:/test/vendor/bundle/ruby/3.0.0/extensions/x64-mingw32/3.0.0/curb-0.9.11/gem_make.out

An error occurred while installing curb (0.9.11), and Bundler cannot continue.
Make sure that `gem install curb -v '0.9.11' --source 'https://rubygems.org/'`
succeeds before bundling.

In Gemfile:
  curb

エラーに以下の表記があります。
Try passing –with-curl-dir or –with-curl-lib and –with-curl-include
options to extconf.
オプションを試してね。とのこと。

libcurlをダウンロードし指定

Windows環境でcurbを使うために行う手順として、libcurlをWindows10にダウンロードしてインストール時にDLLをオプションとして渡すという方法をとる必要があるとのことでした。
この手順は、GitHubにも載っているためWindows環境ではこの手順を行う必要があるようです。

Windows用のcurlは、https://curl.se/windows/から取得します。
zipを展開し、例えば「C:\curl」などとして展開します。

次に、curbのインストールですが、gemの場合以下のようにmkmfのオプションとしてヘッダーファイル、DLLのパスを渡すことで指定したDLLを使ってビルドを行ってくれます。
※Bunderを使ったインストールの場合は、後述。

gem install curb --pratform=ruby -- --with-curl-lib=C:/curl-7.75.0-win64-mingw/bin/ --with-curl-include=C:/curl-7.75.0-win64-mingw/include/

これでうまくいくという情報もあるのですが、僕の環境ではこれだけでは解決しませんでした。

もし、ここでうまくいかない場合、次を参考にしてみてください。

オプションに–with-curl-dirを追加

僕の場合、「–with-curl-lib、–with-curl-include」のオプション指定ではうまくいかず、内部のDLL構造が変わっている?もしくはパスをうまく解析できてない?などいろいろ考えながらgemのオプションについて調べていたところ、–with-curl-dirだと、ヘッダファイルとDLLを探してくれそうだったため、こちらを指定してみることにしました。
発行コマンドは以下です。

gem install curb --pratform=ruby -- --with-curl-bin=C:/curl-7.75.0-win64-mingw/

この指定を行ったところ、curbのインストールに成功しました。

require ‘curb’が失敗する

gem installがうまくいったので早速コードを実行してみると、「`require’: 126: 指定されたモジュールが見つかりません。」というエラーに遭遇しました。

 `require': 126: 指定されたモジュールが見つかりません。   - E:/test/vendor/bundle/ruby/3.0.0/gems/curb-0.9.11/lib/curb_core.so (LoadError)

エラーに出力されたファイル自体は、そのPathに存在するようです。
この場合、Rubyのbinディレクトリ内にlibcurlのDLLをコピーすることで正常に動くようになります。

Bunderでcurbをインストールする場合

bundle installコマンドでcurbをインストールしたい場合、bundle configコマンドを使用し、gemで指定したオプションを同じように設定します。
以下を参考にコマンドを発行してください。.bundle/configに「BUNDLE_BUILD__CURB」という定義ができオプションが設定されます。
※「–local」を付けた場合、プロジェクトルートに設定され、そうでない場合ユーザーディレクトリ上に作成されグローバル設定となります。

bundle config --local build.curb --with-curl-dir=C:/curl-7.75.0-win64-mingw/

オプションの設定ができたら、通常のインストールです。
僕はプロジェクト毎のgemファイル管理が好きなので、以下も発行しています。
bundle config set –local path ‘vendor/bundle’

bundle install

いかがでしょうか。普段開発しているLinuxでは遭遇したことのないエラーでWindowsならではだなぁ。なんて思いながら4時間ぐらい格闘しました。
同じ問題に直面した方のお役に立てれば幸いです。