Skip to content

Instantly share code, notes, and snippets.

@y2q-actionman
Last active August 29, 2015 14:00
Show Gist options
  • Save y2q-actionman/11133761 to your computer and use it in GitHub Desktop.
Save y2q-actionman/11133761 to your computer and use it in GitHub Desktop.
Ubuntu 12 上の SBCL で ncurses が FFI から読めない問題

Ubuntu 12 上の SBCL で ncurses が FFI から読めない問題

症状

cl-charms (CFFI + ncurses) の場合

Common Lisp から、 NCURSES を触りたくなった。早速、Quicklisp で、 cl-charms をインストールしてみよう:

 * (ql:quickload "cl-charms")
To load "cl-charms":
  Load 2 ASDF systems:
    alexandria cffi
  Install 1 Quicklisp release:
    cl-charms
; Fetching #<URL "http://beta.quicklisp.org/archive/cl-charms/2014-03-16/cl-charms-20140316-git.tgz">
; 10.48KB
==================================================
10,735 bytes in 0.00 seconds (0.00KB/sec)
; Loading "cl-charms"
[package cl-charms]........................
debugger invoked on a LOAD-FOREIGN-LIBRARY-ERROR in thread
#<THREAD "initial thread" RUNNING {1002998ED3}>:
  Unable to load foreign library (LIBCURSES).
  Error opening shared object "libncursesw.so":
  /usr/lib/x86_64-linux-gnu/libncursesw.so: ファイルが小さすぎます.

Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.

あらら、何らかのエラーが出て、インストールに失敗してしまった。何ともは や

cl-ncurses (UFFI + ncurses) の場合

もしかしたら、 CFFI がなんかやってるのだろうか?じゃあ、 UFFI を使う、 cl-ncurses を使ってみよう。

 * (ql:quickload "cl-ncurses")
To load "cl-ncurses":
  Load 1 ASDF system:
    uffi
  Install 1 Quicklisp release:
    cl-ncurses
; Fetching #<URL "http://beta.quicklisp.org/archive/cl-ncurses/2010-10-06/cl-ncurses_0.1.4.tgz">
; 23.05KB
==================================================
23,603 bytes in 0.17 seconds (134.01KB/sec)
; Loading "cl-ncurses"
[package cl-ncurses]..............................
.............
("cl-ncurses")
 * 

なにやらインストールできたようなので、ロードしてみる:

 * (require :cl-ncurses)
WARNING: Unable to load ncurses.

NIL
 * 

だめだ! 結局ライブラリのロードに失敗している。

とりあえず、既知の回避方法

Google 大先生にお問い合わせしてみると、すぐに回避方法が見つかる。 http://stackoverflow.com/questions/17416504/unable-to-load-libncurses-with-uffi

以下のようにリンクを張ることで、正常にインストールとロードができる。

sudo ln -s /lib/x86_64-linux-gnu/libncurses.so.5.9 /usr/lib/libncurses.so
sudo ln -s /lib/x86_64-linux-gnu/libncursesw.so.5.9 /usr/lib/libncursesw.so

これらを行うことで、 cl-charms も cl-ncurses も正常にインストールするこ とが出来た。

ロード失敗の原因調査

回避策はさておき、問題の原因を調べてみる。まず、エラーメッセージには、 こう書いてあった:

Error opening shared object "libncursesw.so":
/usr/lib/x86_64-linux-gnu/libncursesw.so: ファイルが小さすぎます.

これだけ見ると、 libncursesw.so が壊れているように見える。しかし、C で 適当に ncurses 使うプログラムを書き、 libncursesw をリンクしてみた所、 普通に実行することが出来た。ならば、ファイルが破損しているわけではない ようだ。

じゃあ、上記ファイルは何者なのか?

hoge:~$ file /usr/lib/x86_64-linux-gnu/libncursesw.so

/usr/lib/x86_64-linux-gnu/libncursesw.so: ASCII text

ASCII text ? 共有オブジェクトではないのか?

覗いてみよう:

hoge:~$ cat /usr/lib/x86_64-linux-gnu/libncursesw.so

INPUT(libncursesw.so.5 -ltinfo)

これは一体・・?

調べたいこと

僕の大予想は、以下のようなもの:

  1. apt-get 視点では、 libncurses は正しくインストールされている。
  2. おそらく、 Ubuntu Linux 搭載の 素敵なリンカ は、上記のASCII textを 解釈して、 いい感じにリンク してくれる。 C 言語のプログラムでは、 そのリンカを通すので、問題なかった。
  3. おそらく、 SBCL か、 Common Lisp の CFFI, UFFI のどちらかが、上記の ASCII text を解釈できない。そのため、 libncurses.so をロードする時点 で弾かれてしまう。

上記 2. と 3. は予想にすぎない。暇があったら調べてみようと思う。

調査進捗 1

謎の ASCII text とは

上で現れた謎の ASCII text は、 GNU ld の使用するリンカスクリプトである。 何らかの理由で、 ncurses はリンカスクリプトの現れる形式でインストールさ れるようだ。

当然だが、これは ELF バイナリ等ではないため、それのためのローダでは読み とれない。 dlopen(3) でも読めないようだ。

SBCL での共有オブジェクトのロードとは

共有オブジェクトのロードは、当然ながら Lisp 処理系依存である。 SBCL で は、 SB-ALIEN:LOAD-SHARED-OBJECT 関数で実装されており、これは最終的に dlopen(3) を呼んでロードしている。

上記の通り、 dlopen(3) は、リンカスクリプトを読めない。そのため、リン カスクリプトを読む必要があるライブラリのロードは失敗してしまうのである。

どうすべきなのか?

偉大なる Google 先生にお伺いをたてたところ、 Lisp じゃない処理系でのバグ レポートが見つかった:

GHC (Haskell)
https://ghc.haskell.org/trac/ghc/ticket/2615
Parrot (perl)
http://www.parrot.org/scratch/general-handling-linker-scripts-reached-dlopen

GHC のものは、なんと 自前でリンカスクリプトを読む という力技。こういう ことになるのかなあ。

調査進捗 2

GHC 7.8.1 は、 system linker を使ってリンクしてるらしい。

https://ghc.haskell.org/trac/ghc/wiki/DynamicGhcPrograms

これだな。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment