以下の条件で失敗したので、対応過程を残す。
条件
- Arch Linux
- 2.0系、2.1系で失敗
- 1.9系は成功
- pacmanによるRuby 2.1のインストールには成功
- rbenvはanyenvで導入
結論
以下のコマンドを実行したら上手くいった。
rbenv install --patch 2.1.1 < <(curl -sSL 'https://projects.archlinux.org/svntogit/packages.git/plain/ruby/trunk/0001-Fix-undeclared-identifier-error-by-using-the-actual-.patch?id=d54cc2645013754f6a303075eb22df1eecb7676a')
ここでFile to patch:
と聞かれるので、ext/readline/readline.c
を入力する。
過程
誤った対応(後述)をして記事を公開したところ、コメント欄にてありがたいご指摘を頂き、現在の形に至った。
Rubyのコードにpatchを当てる必要があるとのことだった。
対象のpatchはこちら。
https://projects.archlinux.org/svntogit/packages.git/tree/ruby/trunk/0001-Fix-undeclared-identifier-error-by-using-the-actual-.patch?id=d54cc2645013754f6a303075eb22df1eecb7676a
plainのリンクで生のpatchファイルが取得できる。
次に、rbenvでpatchを当ててインストールする方法を調査した。
ruby-buildのREADMEにpatchの当て方が書いてある
https://github.com/sstephenson/ruby-build
「Applying patches to Ruby before compiling」のセクションを参照。
以前の誤った対応記録
履歴を見れば分かるには分かるのだが、どんな勘違いをしていたか明確に残しておく。
結論(偽物)
以下のコマンドで上手く行ったと勘違い。
とりあえずインストールはできて動作もするが、readlineが使えない。
RUBY_CONFIGURE_OPTS=--with-readline-dir="/usr/lib/libreadline.so" rbenv install 2.1.1
ruby-build、readlineという組み合わせでググると、readlineマターで失敗しするというのはArch Linuxに限らずちょいちょい見かける。
過程(迷走の記録)
まずは純朴にインストールしようとした。
$ rbenv install 2.1.1
すると以下のエラーが出て失敗した。
Inspect or clean up the working tree at /tmp/ruby-build.20140303235140.25701
Results logged to /tmp/ruby-build.20140303235140.25701.log
Last 10 log lines:
linking shared-object openssl.so
make[2]: Leaving directory '/tmp/ruby-build.20140303235140.25701/ruby-2.1.1/ext/openssl'
linking shared-object dl/callback.so
make[2]: Leaving directory '/tmp/ruby-build.20140303235140.25701/ruby-2.1.1/ext/dl/callback'
linking shared-object ripper.so
make[2]: Leaving directory '/tmp/ruby-build.20140303235140.25701/ruby-2.1.1/ext/ripper'
make[1]: Leaving directory '/tmp/ruby-build.20140303235140.25701/ruby-2.1.1'
uncommon.mk:180: recipe for target 'build-ext' failed
make: *** [build-ext] Error 2
ここで、エラーメッセージでググってみた。他にも同じ問題に悩んだ人もいるだろう。
まずは
uncommon.mk:180: recipe for target 'build-ext' failed
で調べてみたが、こちらはまともな情報がヒットせず。
そこで広げて「build-ext error」でググってみたところ、openssl
、readline
をオプションで指定すれば良いという話をよく見かけた。
Mac OS Xでの話ばかり。Archの話は見かけない。
加えて、エラーメッセージに出ている大本のログファイルである、 /tmp/ruby-build.20140303235140.25701.log を確認してみた。
エラーメッセージではError 2
とあったので、その上をたどるとError 1
を発見した。
readline.c: 関数 ‘Init_readline’ 内:
readline.c:1977:26: エラー: ‘Function’ が宣言されていません (この関数内での最初の使用)
rl_pre_input_hook = (Function *)readline_pre_input_hook;
^
readline.c:1977:26: 備考: 未宣言の識別子は出現した各関数内で一回のみ報告されます
readline.c:1977:36: エラー: expected expression before ‘)’ token
rl_pre_input_hook = (Function *)readline_pre_input_hook;
^
readline.c: トップレベル:
readline.c:634:1: 警告: ‘readline_pre_input_hook’ が定義されましたが使用されません [-Wunused-function]
readline_pre_input_hook(void)
^
make[2]: Leaving directory '/tmp/ruby-build.20140305230735.2209/ruby-2.1.1/ext/psych'
make[2]: Leaving directory '/tmp/ruby-build.20140305230735.2209/ruby-2.1.1/ext/rbconfig/sizeof'
Makefile:228: recipe for target 'readline.o' failed
make[2]: *** [readline.o] Error 1
LANG
がja_JP.UTF-8
なので日本語だ。英語でかつ同じ問題で悩んでいる方、ぐぐラビリティが低くて恐縮。
つまるところ、opensslの前にreadlineの辺りでコケている。
というわけで、まずはオプションでreadlineのパスを指定してみることにした。
パスの調べ方だが、find
してもいいが、pacman
を使えばパッケージの関連ファイルのパスが分かる。
$ pacman -Ql readline
アタリがつけばfind
でもいいが、そうでなければこちらの方が時間が短いかと思う。
ここから.so
ファイルの場所を特定し、RUBY_CONFIGURE_OPTS
で指定してみたら上手くいった。
以上をもって、無事に解決。
と思ったら、そんなことは全くなかった。