このままでいいか

アニメとか,プログラミングとか,研究とか,思ったことをだらだらと書く感じで

MacOSXでcl-mysqlを実行しようとするとlibmysqlclient_r.dylibがないと言われるのを回避する

最近,cl-mysqlを利用したライブラリを使おうとしたときに,以下のようなエラーを食らって困ったので備忘録

Unable to load foreign library (LIBMYSQLCLIENT).
  Error opening shared library libmysqlclient_r.dylib : dlopen(libmysqlclient_r.dylib, 10): image not found.
   [Condition of type CFFI:LOAD-FOREIGN-LIBRARY-ERROR]

Restarts:
 0: [RETRY] Try loading the foreign library again.
 1: [USE-VALUE] Use another library instead.
 2: [LOAD-SOURCE] Load "home:.emacs.d;bin;quicklisp;dists;quicklisp;software;cl-mysql-20150302-git;system.lisp" instead of "/Users/tomoki/.cache/common-lisp/ccl-1.10-f96-macosx-x64/Users/tomoki/.emacs.d/bin/quicklisp/dists/quicklisp/software/cl-mysql-20150302-git/system.dx64fsl"
 3: [RECOMPILE] Compile "home:.emacs.d;bin;quicklisp;dists;quicklisp;software;cl-mysql-20150302-git;system.lisp" into "/Users/tomoki/.cache/common-lisp/ccl-1.10-f96-macosx-x64/Users/tomoki/.emacs.d/bin/quicklisp/dists/quicklisp/software/cl-mysql-20150302-git/system.dx64fsl" then load "/Users/tomoki/.cache/common-lisp/ccl-1.10-f96-macosx-x64/Users/tomoki/.emacs.d/bin/quicklisp/dists/quicklisp/software/cl-mysql-20150302-git/system.dx64fsl" again
 4: [RETRY-LOAD] Retry loading #P"/Users/tomoki/.cache/common-lisp/ccl-1.10-f96-macosx-x64/Users/tomoki/.emacs.d/bin/quicklisp/dists/quicklisp/software/cl-mysql-20150302-git/system.dx64fsl"
 5: [SKIP-LOAD] Skip loading #P"/Users/tomoki/.cache/common-lisp/ccl-1.10-f96-macosx-x64/Users/tomoki/.emacs.d/bin/quicklisp/dists/quicklisp/software/cl-mysql-20150302-git/system.dx64fsl"
 --more--

Backtrace:
  0: (CFFI::FL-ERROR "Unable to load foreign library (~A).~%  ~A" COM.HACKINGHAT.CL-MYSQL-SYSTEM::LIBMYSQLCLIENT "Error opening shared library libmysqlclient_r.dylib : dlopen(libmysqlclient_r.dylib, 10): i..
  1: ((:INTERNAL CFFI::%DO-LOAD CFFI::%DO-LOAD-FOREIGN-LIBRARY) #<FOREIGN-LIBRARY LIBMYSQLCLIENT> COM.HACKINGHAT.CL-MYSQL-SYSTEM::LIBMYSQLCLIENT (:DEFAULT "libmysqlclient_r"))
  2: (CFFI:LOAD-FOREIGN-LIBRARY COM.HACKINGHAT.CL-MYSQL-SYSTEM::LIBMYSQLCLIENT :SEARCH-PATH NIL)
  3: (CCL::$FASL-LFUNCALL #<CCL::FASLSTATE #x26F9BBED>)
  4: (CCL::%FASLOAD "/Users/tomoki/.cache/common-lisp/ccl-1.10-f96-macosx-x64/Users/tomoki/.emacs.d/bin/quicklisp/dists/quicklisp/software/cl-mysql-20150302-git/system.dx64fsl" #(#<Compiled-function CCL::$..
  5: (CCL::%LOAD #P"/Users/tomoki/.cache/common-lisp/ccl-1.10-f96-macosx-x64/Users/tomoki/.emacs.d/bin/quicklisp/dists/quicklisp/software/cl-mysql-20150302-git/system.dx64fsl" NIL NIL :ERROR :DEFAULT NIL)
  6: (LOAD #P"/Users/tomoki/.cache/common-lisp/ccl-1.10-f96-macosx-x64/Users/tomoki/.emacs.d/bin/quicklisp/dists/quicklisp/software/cl-mysql-20150302-git/system.dx64fsl" :VERBOSE NIL :PRINT NIL :IF-DOES-NO..
  7: (UIOP/UTILITY:CALL-WITH-MUFFLED-CONDITIONS #<COMPILED-LEXICAL-CLOSURE (:INTERNAL UIOP/LISP-BUILD:LOAD*) #x30200279676F> ("Overwriting already existing readtable ~S." ..))
  8: (CCL::%%BEFORE-AND-AFTER-COMBINED-METHOD-DCODE (NIL #<STANDARD-METHOD ASDF/ACTION:PERFORM (ASDF/LISP-ACTION:LOAD-OP ASDF/LISP-ACTION:CL-SOURCE-FILE)> . 81588985))
  9: (CCL::%%STANDARD-COMBINED-METHOD-DCODE ((#<STANDARD-METHOD ASDF/ACTION:PERFORM :BEFORE (ASDF/OPERATION:OPERATION ASDF/COMPONENT:COMPONENT)>) ..))) 81588985)
 10: (NIL #<Unknown Arguments>)
 11: (CCL::%CALL-NEXT-METHOD (NIL #<STANDARD-METHOD ASDF/ACTION:PERFORM-WITH-RESTARTS (T T)> . 81589056))
 12: (#<STANDARD-METHOD ASDF/ACTION:PERFORM-WITH-RESTARTS (ASDF/LISP-ACTION:LOAD-OP ASDF/LISP-ACTION:CL-SOURCE-FILE)> #<LOAD-OP :VERBOSE NIL> #<CL-SOURCE-FILE "cl-mysql" "system">)
 13: (CCL::%CALL-NEXT-METHOD (NIL #<STANDARD-METHOD ASDF/ACTION:PERFORM-WITH-RESTARTS (T T)> . 81589056))
 14: (#<STANDARD-METHOD ASDF/ACTION:PERFORM-WITH-RESTARTS :AROUND (T T)> #<LOAD-OP :VERBOSE NIL> #<CL-SOURCE-FILE "cl-mysql" "system">)
 15: (CCL::%%STANDARD-COMBINED-METHOD-DCODE (#<STANDARD-METHOD ASDF/ACTION:PERFORM-WITH-RESTARTS :AROUND (T T)> ..)) 81589056)
 16: (NIL #<Unknown Arguments>)
 17: (#<STANDARD-METHOD ASDF/PLAN:PERFORM-PLAN (LIST)> ((#<PREPARE-OP > . #<SYSTEM "uiop">) (#<COMPILE-OP > . #<SYSTEM "uiop">) (#<LOAD-OP > . #<SYSTEM "uiop">) ..))) :FORCE NIL)
 18: (CCL::%CALL-NEXT-METHOD (NIL #<STANDARD-METHOD ASDF/PLAN:PERFORM-PLAN (LIST)> . 81589118))
 19: (CCL::CALL-WITH-COMPILATION-UNIT #<COMPILED-LEXICAL-CLOSURE (:INTERNAL CCL::WITH-COMPILATION-UNIT-BODY (ASDF/PLAN:PERFORM-PLAN :AROUND (T))) #x26F9C62F> :OVERRIDE NIL)
 --more--

結論から言えば,今回,この問題は,cl-mysql内のCFFIによるMySQL Clientライブラリの指定で問題が発生していた.

自分の場合,使用しているQuicklispのディレクトリは ~/.emacs.d/bin/quicklisp/ 以下にある.

そして,cl-mysqlのCFFI設定は以下のファイル内に記述されていた.

~/.emacs.d/bin/quicklisp/dists/quicklisp/software/cl-mysql-*********-git/system.lisp

元のファイルでは以下のような記述になっている.

(define-foreign-library libmysqlclient
  ((:not :windows) (:default "libmysqlclient_r"))
  (:windows (:default "libmysql")))

Windowsでなければlibmysqlclient_rというファイルを,Windowsならlibmysqlというファイルを使うという設定.

しかし,自分の環境(macOSX Sierra)のデフォルトMySQLのdylibファイルを調べてみると,

~ $ ls -la /usr/local/opt/mysql/lib/
total 22448
drwxr-xr-x   8 tomoki  staff      272  6 29 01:42 .
drwxr-xr-t  15 tomoki  staff      510 10 21 13:53 ..
-rw-r--r--   1 tomoki  staff  5424044 10 21 13:53 libmysqlclient.21.dylib
-r--r--r--   1 tomoki  staff  6047688  6 29 01:42 libmysqlclient.a
lrwxr-xr-x   1 tomoki  staff       23  6 29 01:42 libmysqlclient.dylib -> libmysqlclient.21.dylib
-r--r--r--   1 tomoki  staff     9624  6 29 01:42 libmysqlservices.a
drwxr-xr-t   3 tomoki  staff      102 10 21 13:53 pkgconfig
drwxr-xr-x  91 tomoki  staff     3094  6 29 01:42 plugin

となっており,libmysqlclient_rというファイルはない.

今回は対処療法的に,

(define-foreign-library libmysqlclient
  (:darwin (:or "libmysqlclient"))
  ((:not :windows) (:default "libmysqlclient_r"))
  (:windows (:default "libmysql")))

と書き換えて,正しく動作するようになった.

作者のGithubページを見に行くとすでに修正が入っているようだったので,昔インストールしたものやキャッシュを削除して入れ直せば治っていたのだろう.

github.com