libreadline.so.8: undefined symbol: UPの対処方法
概要
Ubuntu 20.04にアップグレードした後,システムのawkを実行すると以下のエラーが出るようになってしまった。
awk --version
awk: symbol lookup error: /home/senooken/.local/lib/libreadline.so.8: undefined symbol: UP
ローカルにインストールしたlibreadline.so.8
にUP
のシンボルがないのが理由なようだ。
実際以下の通り,libreadline
にはUP
のシンボルは定義されていなかった。
nm ~/.local/lib/libreadline.so | grep UP
U UP
この件について調べていると「Re: [Bug-readline] libreadline.so.7: undefined symbol: UP」や「c – libreadline.so.7: undefined symbol: UP – Stack Overflow」が見つかった。
ここのコメントによると,Readline自体はUP
のシンボルを提供しておらず,代わりにtermcap/termlib/ncursesの変数を使っているらしい。つまり,Readlineのビルド時にこれらのライブラリーをきちんとリンクできていないのが問題のようだ。
実際に以下のコマンドで,ローカルのReadlineとシステムのReadline (ldd /usr/bin/awk
でパスを確認) にリンクされているライブラリーを比較してみる。
ldd ~/.local/lib/libreadline.so.8
linux-vdso.so.1 (0x00007ffcb6de0000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd281a23000) /lib64/ld-linux-x86-64.so.2 (0x00007fd281c9a000)
ldd /lib/x86_64-linux-gnu/libreadline.so.8.0
linux-vdso.so.1 (0x00007ffea3f69000) libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007fca10e3e000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fca10c4c000) /lib64/ld-linux-x86-64.so.2 (0x00007fca10ef0000)
システムのReadlineにはlibtinfo.so.6
がリンクされている。これがローカルのReadlineのビルドにも必要なようだ。
そこで,GNU Readlineのビルド時にlibtinfo.so
をリンクしてビルドし直す。
ビルド
まず,libtinfo.so
(TermInfo) を用意する。これはncursesに含まれているので,configure
のオプションこ--with-termlib
を指定 (参考)して,libncurses.so
に一つにまとめられていたものを分離してlibtinfo.so
を生成することで対応する。詳細なインストール手順は「インストール: ncurses | 端末操作の基本ライブラリー」を参考にする。
libtinfo.so
を用意できたので,続いて,GNU Readlineをビルドする。ビルドに当たっては,先ほど参考にした質疑応答にある通り,注意が必要となる。
そのままでは,libtinfo.so
をリンクしてくれないので,shlib/Makefile
で定義されているSHLIB_LIBS
変数に-ltinfo
を指定する。具体的には,make
の実行時に以下のように変数を上書きすればいい。
make -j $J SHLIB_LIBS=-ltinfo
これで,libreadline.so
にlibtinfo.so
がリンクされ,問題が解消される。詳細なインストール手順は「インストール: GNU Readline | コマンドライン操作の共通ライブラリー」を参考にする。
なお,GNU Readlineのconfigure
のオプションには--with-curses
というそれっぽいオプションがある。しかし,これはMakefile内のTERMCAP_LIB
の値を-ltermcap
から-lcurses
に差し替えるだけであり,別にリンク時に使っているわけでもなかったので,効果はなかった。
`--with-curses'
This tells readline that it can find the termcap library functions
(tgetent, et al.) in the curses library, rather than a separate
termcap library. Readline uses the termcap functions, but does not
link with the termcap or curses library itself, allowing applications
which link with readline the to choose an appropriate library.
This option tells readline to link the example programs with the
curses library rather than libtermcap.
結論
気になる問題が解決できてよかった。
まともにこの問題に取り組んでいる情報がなかったので,根本的な対応方法を整理できて満足した。