ただです。長々とすみません。最後なんでカンベンしてください。 題記の件、諦めちゃいました。Rubyは自分には難しすぎたみたいです。 ロリポ他、MySQL4.0xを使ってるホスティング会社のユーザーの方はたくさんいらっしゃ ると思いますので、現象と原因と調査した履歴のまとめを残しておきます。 私は解決できませんでしたがスキルがある方が通りかかった時に少しでも参考になればと 思います。 【現象】 RubyからMySQLを使用するためrequire "mysql"を実行しようとするとApacheログに以下の メッセージが出力される C:/usr/local/lib/ruby/site_ruby/1.8/i386-msvcrt/mysql.so: 127: 指定されたプロシージャが見つかりません。 - C:/usr/local/lib/ruby/site_ruby/1.8/i386-msvcrt/mysql.so (LoadError) 【環境】 OS : WindowsXP Professional Apache : 2.0.54 Ruby : ruby 1.8.6 (2007-09-24 patchlevel 111) [i386-mswin32] MySQL : MySQL Ver 12.16 Distrib 4.0.9-gamma, for Win95/Win98 (i32) インタフェース:MySQL/Ruby PATH : %SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem; C:\mysql\bin;C:\j2sdk1.4.2_05\bin;C:\WINDOWS\system32; C:\usr\local\bin 【原因】 MySQLのバージョンとMySQL/Ruby(バイナリ)のバージョンが不一致。 【対策】 MySQL/Rubyのソースを入手し、Windows上でコンパイルを実施。 (MySQLのバージョンを考慮してバイナリファイルを作ってくれる) ただ、このコンパイルがうまくいかない。(私の場合) 詳細は調査履歴を参照 【調査履歴】 コンパイル前に実施すべきこと ・Ruby,MySQL,コンパイラの実行ファイルとdllのパスをPATHに設定 ・同じくライブラリパスをLIBに設定 ・extconf.rb実行時には以下のオプションを指定する --with-mysql-dir=c:/mysql --with-mysql-lib=c:/mysql/lib/opt --with-mysql-include=c:/mysql/include --with-mysqlclientlib=c:mysql/lib/opt/mysqlclient それでもうまくいかない。以下、ソースを追っかけてみた履歴です。 ## extconf.rb ======================================== require 'mkmf' #お約束らしい。 if mc = with_config('mysql-config') then #mysql-configがある場合 mc = 'mysql_config' if mc == true cflags = `#{mc} --cflags`.chomp exit 1 if $? != 0 libs = `#{mc} --libs`.chomp exit 1 if $? != 0 $CPPFLAGS += ' ' + cflags $libs = libs + " " + $libs else #mysql-configが無い場合(今回はこっち) inc, lib = dir_config('mysql', '/usr/local') libs = ['m', 'z', 'socket', 'nsl'] # # mysqlclientにmysql_queryがあるか確認。無い場合はexit 1 # どうもここでexit1しているらしい。 # while not find_library('mysqlclient', 'mysql_query', lib, "#{lib}/mysql") do exit 1 if libs.empty? have_library(libs.shift) end end ## extconf.rb ここまで ================================== mysql_configというファイルは存在するが、--with-mysql-configに指定すると 「それは実行ファイルじゃないよん」と怒られるので、多分Windowsの場合は 使えないのではないかと推測。 ちなみにmysql_configの中身はCっぽいソース。 そこでelse句を見てみると、上記のコメントのとおりfind_libraryでmysql_query が見つからず、libs.emptyに引っかかってexitしている。 というわけで、mkmfの中のfind_libraryをチェック ## find_library ======================================== def find_library(lib, func, *paths, &b) func = "main" if !func or func.empty? lib = with_config(lib+'lib', lib) paths = paths.collect {|path| path.split(File::PATH_SEPARATOR)}.flatten # # ここからよくわかんない # checking_for "#{func}() in #{LIBARG%lib}" do libpath = $LIBPATH libs = append_library($libs, lib) begin # # try_funcでmysql_queryがmysqlclientに存在するか確認しているらしい。 # ここで発見できていない様だ # until r = try_func(func, libs, &b) or paths.empty? $LIBPATH = libpath | [paths.shift] end if r $libs = libs libpath = nil end ensure $LIBPATH = libpath if libpath end r end end ## find_library ここまで ================================== ↓なにこの構文。 checking_for "#{func}() in #{LIBARG%lib}" do until r = try_func(func, libs, &b) or paths.empty? $LIBPATH = libpath | [paths.shift] end (略) end checking_forって関数じゃないの?(Rubyは関数といわない?) よくわかんないけど、 第1引数 : "#{func}() in #{LIBARG%lib}" 第2引数 : do〜endの実行結果 と推測。 until r=try_func(func, libs, &b) or paths.empty? の結果がpaths.emptyで終了している様なので、try_func()をチェック ## try_func =========================================== def try_func(func, libs, headers = nil, &b) headers = cpp_include(headers) # #↓何故か同じものをorしている # try_link(<<"SRC", libs, &b) or try_link(<<"SRC", libs, &b) #{COMMON_HEADERS} #{headers} /*top*/ int main() { return 0; } int t() { void ((*volatile p)()); p = (void ((*)()))#{func}; return 0; } SRC #{headers} /*top*/ int main() { return 0; } int t() { #{func}(); return 0; } SRC end def try_var(var, headers = nil, &b) headers = cpp_include(headers) try_compile(<<"SRC", &b) #{COMMON_HEADERS} #{headers} /*top*/ int main() { return 0; } int t() { const volatile void *volatile p; p = (void *)&#{var}; return 0; } SRC end ## try_func ここまで ==================================== わけわからん。 try_link(<<"SRC", libs, &b) or try_link(<<"SRC", libs, &b) って何だ? なぜ同じ式をorで繋ぐのだろう? そもそもtry_link(<<"SRC", libs, &b) の<<て何だろう? The Ruby way を読むと、「論理シフト」または「ヒアドキュメント」らしい。 どっちも違う気がする。 とりあえず下のほうに"SRC"があるのでこれはヒアドキュメントと仮定して #{COMMON_HEADERS}〜SRCまでを全部try_linkの第1引数に渡すものと解釈。 このtry_funcの戻り値はどこで返すんだ? よくわからないが、try_link(<<"SRC", libs, &b) or try_link(<<"SRC", libs, &b) の結果が戻り値であると推測。 というわけで try_linkをチェック ## try_link =========================================== def try_link(src, opt="", &b) try_link0(src, opt, &b) ensure rm_f "conftest*", "c0x32*" end ## try_link ここまで ==================================== そのまんま try_link0に受け流している。 というわけでtry_link0をチェック ## try_link0 =========================================== def try_link0(src, opt="", &b) try_do(src, link_command("", opt), &b) end ## try_link0 ここまで ==================================== link_command("", opt)の結果をtry_doに渡している。 一応、link_comanndをチェック... したけど、コマンドのオプション文字列を作っている だけなので、何も問題なさそう。 というわけでtry_doをチェック ## try_do =========================================== def try_do(src, command, &b) src = create_tmpsrc(src, &b) xsystem(command) ensure log_src(src) end ## try_do ここまで ==================================== さっき作ったコマンドをxsystem()に渡している。多分ここで実行しているに違いない。 ということでxsystem()をチェック ## xsystem =========================================== def xsystem command Logging::open do puts command.quote system(command) end end ## xsystem ここまで ==================================== 受け取ったコマンドをsystem関数で実行。 ここが失敗しているからmysqlclient.libにmysql_queryが無いといわれている。 というわけで、実行しているコマンドを画面に出力させてみた。 ## コマンド =========================================== (適当に改行が入っていますが、実際には1行で出力されます) cl -nologo -Feconftest -I. -IC:/usr/local/lib/ruby/1.8/i386-mswin32 -I. -IC:/usr/local/lib/ruby/1.8/i386-mswin32 -I/usr/local/include -MD -Zi -O2b2xg- -G6 conftest.c msvcrt-ruby18-static.lib c:/mysql/lib/opt/mysqlclient.lib oldnames.lib user32.lib advapi32.lib ws2_32.lib -link -libpath:"." -libpath:"C:/usr/local/lib" -libpath:"c:/mysql/lib/opt" -libpath:"/usr/local/lib" -stack:0x2000000 ## コマンド ここまで ==================================== mkmf.logに書かれているのと同じ結果が出力された。 conftest.cが何者かよくわからないが、とりあえずこのコマンドラインをこのまんまコマンド プロンプトで実行したところ、 'cl' は、内部コマンドまたは外部コマンド、操作可能なプログラムまたはバッチ ファイ ルとして認識されていません。 と出力される。 clはコマンドラインのコンパイラだったと思ったのでcl.exeを検索してPATHに追加。 すると今度はmspdb70.dllが無いといわれるのでこれも検索してPATHに追加。 3度目の正直で実行してみたところ、何とか実行に成功 キタ━( )━(゜ )━(∀゜ )━(゜∀゜)━( ゜∀)━( ゜)━( )━ で、実行結果を確認すると ## 実行結果 =========================================== C:\mr>echo %errorlevel% -1073741515 ## 実行結果 ここまで ==================================== 0以外が返って来ている。 この原因を調べれば、mysqlclient.libの中にmysql_queryが見つからない原因がわかるはず。 --