カレーミュージアムが ― 2006年12月21日 13時07分44秒
終わってしまうらしい。。。
Visual C++ 2003/2005 で perl モジュールを nmake できるようにするためのパッチ ― 2006年12月21日 17時20分57秒
こいつの続き。ていうか、すっかり忘れてたw。
ExtUtils::MakeMaker
モジュールが Windows 版 ActivePerl 向けに生成する Makefile は、Windows XP (および Windows Server 2003) + Visual C++ 2003/2005 の環境 (いや、実際、VC++ 2003 では試したことないので知らんのですが、システム DLL に Manifest の概念が導入されたのがどうやらこいつかららしいので、多分間違いないかと) で nmake → nmake install しても、use する際に R6034 エラーが発生してモジュールのロードに失敗してしまうという問題があります。
解決策として、ExtUtils::MakeMaker
モジュールを構成するサブモジュール ExtUtils::MM_Win32
のモジュールファイル ExtUtils/MM_Win32
の最新版 (v1.13) に対するパッチを書いたので、以下に公開します。
*** MM_Win32.pm.old Thu Dec 21 16:28:52 2006 --- MM_Win32.pm Thu Dec 21 16:34:28 2006 *************** *** 37,38 **** --- 37,39 ---- my $GCC = 1 if $Config{'cc'} =~ /^gcc/i; + my $VC80 = 1 if $Config{'cc'} =~ /^cl/i && system('mt >nul 2>nul') == 0; *************** *** 340,344 **** } else { # VC push(@m, ! q{ $(LD) -out:$@ $(LDDLFLAGS) }.$ldfrom.q{ $(OTHERLDFLAGS) } .q{$(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) -def:$(EXPORT_LIST)}); } --- 341,347 ---- } else { # VC + my $ld_manifest_option = ' -manifest -manifestfile:$@.intermediate.manifest' if $VC80; push(@m, ! q{ $(LD) -out:$@}.$ld_manifest_option.q{ $(LDDLFLAGS) }.$ldfrom.q{ $(OTHERLDFLAGS) } .q{$(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) -def:$(EXPORT_LIST)}); + push @m, "\n\t", q'mt -outputresource:$@;2 -manifest $@.intermediate.manifest -nologo' if $VC80; }
なお、現行の ActivePerl の最新版では、付属のExtUtils::MM_Win32
モジュールのバージョンは v1.12 となっていて若干古いので、上記のパッチを当てる場合は、まずその前に、最新の ExtUtils::MakeMaker
モジュールをインストールしてから行うようにしてください (ExtUtils::MakeMaker
モジュール自体はインストール時にコンパイラを必要とはしないので、cpan
コマンドから install ExtUtils::MakeMaker
してあげればインストールできるはずです)。
ちなみに、上記パッチでやっていることがなんなのかを一応メモしておきます。
- 何が必要か?
- 具体的にいうと、いわゆる標準 C ランタイムライブラリ DLL であるところの
msvc?XX.dll
ファイル (
には?
m
とかp
とかr
とかが入る) (XX
はバージョンを表す番号。v6.0 なら60
とか) の、リビジョンなどを厳密に管理するようになった為、それに合わせて使用するこれらの DLL のバージョンを判別するような情報 (「マニフェスト manifest」と呼ばれる) を、実行ファイル (.exe
ファイルや.dll
ファイル) に埋め込んだりする必要が出てきた。 - マニフェストを埋め込むには、リンク時に XML 形式のマニフェストファイルを生成し、それをマニフェストツール (
mt.exe
) を呼び出して埋め込む必要がある。つまり、Makefile にその辺の指示内容を含める必要がある。 - この対応が必要なのは、C ランタイムライブラリのバージョンが v8.0 以降のもの (つまり、
msvc?80.dll
以降のシリーズ) のみ。それ以前の CRT ライブラリを使用するバージョンの VC++ 環境には、そもそもリンカにマニフェストを生成する為のオプションが存在しないし、mt.exe
自体存在しない。つまり、これらのバージョンの切り分けも必要になる。
- 具体的にいうと、いわゆる標準 C ランタイムライブラリ DLL であるところの
- 実際にパッチで行っていることは何か?
- VC++ の (CRT ライブラリの) バージョンが 8.0 以上であることの確認 - コンパイラコマンドのコマンド名が "
cl
" であり、且つ、mt.exe
コマンドが存在する (実際にmt
を呼んでみて、コマンドの戻り値が 0 である) ならば、VC++ v8.0 以降である、とみなす。 - Makefile に吐き出す内容の変更 -
dynamic_lib
セクションにて、かつて以下のような内容が書き出されていたのを、$(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP) $(INST_ARCHAUTODIR)$(DFSEP).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP) $(LD) -out:$@ $(LDDLFLAGS) $(LDFROM) $(OTHERLDFLAGS) $(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) -def:$(EXPORT_LIST) $(CHMOD) $(PERM_RWX) $@
以下のような内容で書き出されるように変更した。$(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP) $(INST_ARCHAUTODIR)$(DFSEP).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP) $(LD) -out:$@ -manifest -manifestfile:$@.intermediate.manifest $(LDDLFLAGS) $(LDFROM) $(OTHERLDFLAGS) $(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) -def:$(EXPORT_LIST) mt -outputresource:$@;2 -manifest $@.intermediate.manifest -nologo $(CHMOD) $(PERM_RWX) $@
ちゃんと解説すると、よーするに、以下の変更を加えている。link
コマンドに、マニフェストを生成する為のオプション-manifest
と-manifestfile:(ファイル名)
を追加。link
コマンドを呼んだ直後に、mt
コマンドを呼ぶ。オプションの-outputresource:(ファイル名);(リソース番号)
は、ファイル名のオブジェクトにマニフェストをリソースとして埋め込む、という意味。リソース番号は DLL の場合は常に 2 となる。
- VC++ の (CRT ライブラリの) バージョンが 8.0 以上であることの確認 - コンパイラコマンドのコマンド名が "
- 何ができるようになるか?
- 無料配布されている VC++ 2005 Express と Platform SDK を用いて、ActivePerl 環境向けに Perl モジュールをビルド (
nmake
) することが出来るようになる。 - すなわち、これまでは不可能だった、Win32 版 ActivePerl 向けのモジュール開発・テスト環境をタダで構築するということが可能になる。
- 無料配布されている VC++ 2005 Express と Platform SDK を用いて、ActivePerl 環境向けに Perl モジュールをビルド (
ちうわけで。。。おいらエーゴわかんないから誰か連絡してあげて~\(^O^)/
最近のコメント