guile-2.0がリリースされたので入れるだけ入れてみた
http://www.gnu.org/software/guile/news.html
去る2月16日に、GNUのGuile version 2.0がリリースされたのでそれのインストールメモというだけです。
http://lwn.net/Articles/428288/
近いうちに、Guile 2.0 Crashやりたいですね。近いうちっていうか本当は今月が良かったのですが今月ってあと一週間そこいらですし来週は色々イベントあるのと仕事で無理ですね。
FFIというよりもCとの双方向の色々がやり易いらしくて、そうすると色々実装どうなってるのかなーというのはかなり気になる所です。
gitから引っ張ってくる
http://www.gnu.org/software/guile/download.html#git
えっいきなり ftp://ftp.gnu.org/pub/gnu/guile/ じゃなくてgitリポジトリから取ってくるんですか?というのは、まぁ色々あったからですというか、gitリポジトリから取って来たヤツだと動いたって言うそれだけです。
普通にcloneすれば良いと思います。
autoreconf
gitから取って来たものにはconfigure入っていませんから、
autoreconf -i --verbose
などやって色々生成します。
AM_GNU_GETTEXTが無い、でもgettext-develとかは入れてるという場合は、aclocal --print-ac-dirなど見て、ちゃんとgettext.m4とか見付けられるか調べてあげてください。
configure
今回は特にくくらずに、
configure
とします。configureで失敗する場合は、C_INCLUDE_PATHとかで必要なものちゃんと見付けられているかっていういつものお話です。
それかconfigureデバッグをして切り抜けるかです。
makeすると失敗する
すくなくとも私の環境では、libguile.dylibとかそういうのを生成するタイミングで失敗します。エラー内容は多分
- rpl_putenvがundefined
- _environがundefined
とかそんな感じになると思います。
rpl_putenvについて
結論から言うと、C_INCLUDE_PATHで/usr/local/includeとか/usr/includeに通してる場合そっちを見に行ってしまうので困るよねとかそんなです多分。
まず1つ目のrpl_putenvですが、これはlib/stdlib.hを見ると740行あたりに
#if 1 # if 1 # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef putenv # define putenv rpl_putenv # endif _GL_FUNCDECL_RPL (putenv, int, (char *string) _GL_ARG_NONNULL ((1))); _GL_CXXALIAS_RPL (putenv, int, (char *string)); # else _GL_CXXALIAS_SYS (putenv, int, (char *string)); # endif _GL_CXXALIASWARN (putenv); #endif
と書いています。libguile以下ではgcc -I../libなどしているので、libguileでのstdlib includeはlib/stdlib.hを指す事になります。で、configureで何もしなかったので_cplusplusがdefinedではないですから、putenvがrpl_putenvとなってしまうわけです。
いや、でもlib/putenv.cがあってそこで多分上手く動くだろうから大丈夫なのでは?というのは実は残念なことになってしまっていて…例えば次のCプログラム
/* test.c */ #include <stdlib.h> /* stdlib.hはカレントディレクトリに存在するとする */ int main() { return 0; } %gcc -E test.c -I. | grep stdlib.h <- gcc -I$(pwd)などとしても意味ない # 1 "/usr/include/stdlib.h" 1 3 # 61 "/usr/include/stdlib.h" 3 # 62 "/usr/include/stdlib.h" 2 3 # 64 "/usr/include/stdlib.h" 2 3 # 66 "/usr/include/stdlib.h" 2 3 # 68 "/usr/include/stdlib.h" 2 3 # 81 "/usr/include/stdlib.h" 3 # 134 "/usr/include/stdlib.h" 3 # 144 "/usr/include/stdlib.h" 3 # 256 "/usr/include/stdlib.h" 2 3
これがlibディレクトリ以下で起こってしまうので、lib/putenv.c自体はシステムのstdlib.hを見に行ってしまってrpl_putenvが定義されなくなるとかそんなのです。
どう解消するのかというのはまぁ好きにしてくださいって感じだと思うのですが、putenv.cで
/* #include <stdlib.h> /* こっちをコメントアウト */ #include "stdlib.h"
とすれば「取りあえず」動くのでそれで良いと思います。
_environについて
これも結論を言うと、Darwin ldにあるundefinedオプションでdynamic_lookup付けて動的にシンボル解決するようにしろという話です。
_environはcrt1.oでdefinedだというので問題無いと思うのですが、普通このcrt1.oは明示的に渡したりしませんgccが勝手に寄越してくれるので。
まぁつまり
/* env.c */ #include <stdio.h> void punya(void) { extern char **environ; char **strs; for (strs = environ; *strs != NULL; ++strs) printf("%s\n",*strs); } /* main.c */ extern void punya(void); int main() { punya(); return 0; } % gcc -c env.c main.c % gcc -v main.o env.o ... /usr/local/libexec/gcc/x86_64-apple-darwin10/4.6.0/collect2 -dynamic -arch x86_64 -macosx_version_min 10.6.6 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/local/lib -L/opt/local/lib -L. -L/usr/local/lib/gcc/x86_64-apple-darwin10/4.6.0 -L/usr/local/lib/gcc/x86_64-apple-darwin10/4.6.0/../../.. main.o env.o -lgcc_s.10.5 -lgcc_ext.10.5 -lgcc -no_compact_unwind -lSystem ... % nm /usr/lib/crt1.10.5.o|grep environ 00000000000000a0 D _environ
ところがMacでdynamic library(つまりdylib)を作る場合は、作る「タイミング」で全シンボルの解決がされないといけないわけなのですが
% gcc -c -fPIC env.c -o env.o % gcc -v -dynamiclib env.o -o libpunya.dylib ... /usr/local/libexec/gcc/x86_64-apple-darwin10/4.6.0/collect2 -dynamic -dylib -arch x86_64 -macosx_version_min 10.6.6 -weak_reference_mismatches non-weak -o libpunya.dylib -ldylib1.10.5.o -L/usr/local/lib -L/opt/local/lib -L. -L/usr/local/lib/gcc/x86_64-apple-darwin10/4.6.0 -L/usr/local/lib/gcc/x86_64-apple-darwin10/4.6.0/../../.. env.o -lgcc_s.10.5 -lgcc_ext.10.5 -lgcc -no_compact_unwind -lSystem ... Undefined symbols: "_environ", referenced from: _punya in env.o ld: symbol(s) not found collect2: ld returned 1 exit status
とcrt1.o渡ってこずにenvironがシンボル解決出来ないので文句を言われます。どうするねんという話なのですが、Darwin ldにはundefinedオプションというものがあり
http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/ld.1.html
-undefined treatment Specifies how undefined symbols are to be treated. Options are: error, warning, suppress, or dynamic_lookup. The default is error. (http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/ld.1.html より抜粋)
従って
% gcc -dynamiclib env.o -o libpunya.dylib -Wl,-undefined,dynamic_lookup % gcc main.o libpunya.dylib
と出来ます。
で具体的にguileの場合はどこを弄れば良いのかですけど、libtoolで
# Commands used to build a shared archive. archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring \$single_module~\$DSYMUTIL \$lib || :"
という部分があるので
archive_cmds="\$CC -dynamiclib -Wl,-undefined,dynamic_lookup \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring \$single_module~\$DSYMUTIL \$lib || :"
とかすると良いと思います。
パッチ貼付けた方が良かったですけど元ファイル残してないのでまぁ御免なさいって感じですね。