libreadline.so.8: undefined symbol: UPの対処方法

GNOME Terminal

概要

Ubuntu 20.04にアップグレードした後,システムのawkを実行すると以下のエラーが出るようになってしまった。

awk --version
awk: symbol lookup error: /home/senooken/.local/lib/libreadline.so.8: undefined symbol: UP

ローカルにインストールしたlibreadline.so.8UPのシンボルがないのが理由なようだ。

実際以下の通り,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.solibtinfo.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.      

結論

気になる問題が解決できてよかった。

まともにこの問題に取り組んでいる情報がなかったので,根本的な対応方法を整理できて満足した。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です