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 自体存在しない。つまり、これらのバージョンの切り分けも必要になる。
  • 実際にパッチで行っていることは何か?
    1. VC++ の (CRT ライブラリの) バージョンが 8.0 以上であることの確認 - コンパイラコマンドのコマンド名が "cl" であり、且つ、mt.exe コマンドが存在する (実際に mt を呼んでみて、コマンドの戻り値が 0 である) ならば、VC++ v8.0 以降である、とみなす。
    2. 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++ 2005 ExpressPlatform SDK を用いて、ActivePerl 環境向けに Perl モジュールをビルド (nmake) することが出来るようになる。
    • すなわち、これまでは不可能だった、Win32 版 ActivePerl 向けのモジュール開発・テスト環境をタダで構築するということが可能になる。

ちうわけで。。。おいらエーゴわかんないから誰か連絡してあげて~\(^O^)/

コメント

コメントをどうぞ

※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。

※投稿には管理者が設定した質問に答える必要があります。

名前:
メールアドレス:
URL:
次の質問に答えてください:
おいらがやっている会社の名前をひらがな4文字で。

コメント:

トラックバック

このエントリのトラックバックURL: http://harapeko.asablo.jp/blog/2006/12/21/1041020/tb

※なお、送られたトラックバックはブログの管理者が確認するまで公開されません。

_ Windowsのフリーウェア、フリーソフトを紹介 - KOCのブログ - 2007/07/13 00:30:27

今回の対象は、XAMPP + Perl Add-on、またはActive Perl。

Windows環境では、デフォルトでは
CPANからモジュールを入れるのが困難です。

理由は、以下の通りです。
1.MAKEコマンドが無い
2.gzip、tarコマンドが無い
3.Cのコンパイラが無い
4.フリーのCコンパイラとして、
Visual Studio 2005 Express Editions: Visual C++ 2005 Express Edition
がある。しかし、実行(テスト)時にエラーが出まくる。

1〜3は、下記のサイトに記載された対策で対応可能です。
Perlメモ/モジュールのインストール(CPAN) - Walrus, Digit.


4は、上記サイトのメモにも記載されていますが
「Microsoft Platform SDKの導入」
「Visual C++ 2005 再頒布可能パッケージのインストール」
の対応が必要です。

この後、下記のサイトを参考に
「ExtUtils::MM_Win32」を修正して下さい。
Visual C++ 2003/2005 で perl モジュールを nmake できるようにするためのパッチ: 国民宿舎はらぺこ 大浴場

下記のバージョンで、CPANからモジュールが
入れられるようになりました。感動した。
・XAMPP(1.6.2)
・Perl Add-on(5.8.8-2.2.4)
・Active Perl(5.8.8.817)