Module::Install::XSUtilでXSモジュール用のMakefile.PLを書くB!

前置き

こんにちは,gfxです。好きなソースはタルタルソースとsv.cです。JPerl Advent Calendar 2009 Hacker Trackも8日目ですね。そろそろTipsを読むだけでは飽き足らず,モジュールを書きたくなってきたんじゃないでしょうか。そんなわけで,今日はModule::Install::XSUtilを紹介します。

本題

皆さんの中にはよくXSを書く方もいらっしゃると思いますが,XSモジュールを含むディストリビューションはビルド環境の設定が結構大変ですよね。build_requiresにExtUtils::ParseXSやXSLoaderを指定したり,make_maker_argsにOBJECT => '$(O_FILES)'を指定したりする必要がありますし,Cコンパイラは使えるか,Cコンパイラの警告を有効にしたい,ppport.hは十分に新しいか,などなど考えなければいけないことが多々あります。ディストリビューションの中にXSモジュールが複数あると,また一層大変です。

これらの面倒なことはプログラムにやらせましょう!

まず基本コマンドです。Makefile.PLの冒頭は以下のようになります。

use strict;
use warnings;
use inc::Module::Install;
use Module::Install::XSUtil; # for co-developpers

all_from 'lib/Foo/XS.pm';

cc_warnings;
use_ppport 3.19;

cc_warningsはコンパイラの警告を有効にするコマンドですが,モジュールでXSを使うことを宣言する意味もあります。設定される警告はコンパイラによって異なりますが,たとえばgcc4だと -Wall -Wextra -Wdeclaration-after-statement となります。

use_ppportはppport.hを生成します。従来の慣習では,ppport.hをディストリビューションに同梱していました。しかし,そのやり方では,ppport.hが提供するルーチンにバグがあった際の対処が面倒です。ユーザーがディストリビューションをビルドする前に,ユーザー自身が同梱されているppport.hを破棄し,新しいppport.hを生成しなければならないからです。use_pportはまさにこの作業を自動化するものです。

XSUtilの基本コマンドはこれだけですが,他にもいくつか便利なコマンドがあります。

cc_src_paths @xs_src_dirs;

XSモジュールが複数のソースからなるケースでは,Makefile.PLの設定は煩雑になりがちです。しかし,cc_src_pathsでディレクトリを指定するのなら一行で済みます。

ところで,これはXSUtilとは直接関係はないのですが,XSファイルが複数あるときには,メインのXSファイルから他のXSファイルのbootルーチンを呼ぶ必要があります。以下はMouseのソースからの抜粋ですが,このような方法で処理するといいでしょう。

/* mouse.h */
#define MOUSE_CALL_BOOT(name) STMT_START {      \
        EXTERN_C XS(CAT2(boot_, name));         \
        PUSHMARK(SP);                           \
        CALL_FPTR(CAT2(boot_, name))(aTHX_ cv); \
    } STMT_END

/* Mouse.xs */
MODULE = Mouse  PACKAGE = Mouse
BOOT:
    /* ... */
    MOUSE_CALL_BOOT(Mouse__Util);
    MOUSE_CALL_BOOT(Mouse__Util__TypeConstraints);
    MOUSE_CALL_BOOT(Mouse__Meta__Method__Accessor__XS);
    MOUSE_CALL_BOOT(Mouse__Meta__Attribute);

また,インクルードパスを指定したいときは,cc_include_pathsを使います。

cc_include_paths @inc_dirs;

Cプリプロセッサマクロを指定することもできます。

cc_define qw(-DFEATURE_FOO);
cc_define qw(-UFEATURE_BAR);

なお,cc_src_pathsやcc_defineなどは既存のオプションに追加してゆくため,一つのMakefile.PLの中で複数回使用することができます。

また,XSとPure Perl二つの実装を持つモジュールの場合は,cc_availableを使用して以下のように設定します。

if(cc_available){
    cc_warnings;
    ...;
}

cc_availableはコンパイラが使用可能かどうかをチェックするコマンドですが,XSUtil バージョン0.19からはMakefile.PLへの引数を調べて,--ppが指定されていると強制的に偽を,--xsが指定されていると強制的に真を返すようになりました。

Perlのバージョンが特定以上の場合のみXSを使用したいというケースでは,以下のようになるでしょう。

if($] >= 5.010 && cc_available){
    cc_warnings;
    ...;
}

通常のXSモジュールで使用する機能はこのくらいでしょう。XSUtilによって煩雑なMakefile.PLの設定が少しでも楽になれば幸いです。Enjoy XS!

まとめ

今回は Module::Install::XSUtil について解説しました。

このモジュールは,同様の処理を何度も書いたり見かけたりしているうちに,「もうめんどくさいからモジュールにしちゃおう」とおもって作りました。普段から「定型的なコードがないだろうか」と気をつけていることが重要ですね。

というわけで今回はここまで。明日は id:TAKESAKO さんです。