mkmf.rb

Ruby の拡張ライブラリのための Makefile を作成するライブラリです。通常 extconf.rb という名の ruby スクリプトの中で require され、このスクリプ トを実行することで Makefile を作成するのが慣習となっています。

拡張ライブラリの作り方(extconf.rbの書き方)に関しては ruby のアーカイブ に含まれる [ruby-src:README.EXT] (日本語版は [ruby-src:README.EXT.ja])も参照してください。

使い方

架空の拡張ライブラリ foo.so を作成することを考えます。この拡張ライブラ リを作成するためには、ヘッダファイル bar.h とライブラリ libbar.a の関 数 baz() が必要だとします。このための extconf.rb は以下のように書きま す。

require 'mkmf.rb'

dir_config('bar')
if have_header('bar.h') and have_library('bar', 'baz')
  create_makefile('foo')
end

そして、拡張ライブラリを作成、インストールするには以下のようにします。

$ ruby extconf.rb
$ make
$ make site-install

dir_config('bar') により、ヘッダファイルのパス、ライブラリのパス を以下のように指定できます。

$ ruby extconf.rb --with-bar-include=/usr/local/include \
                  --with-bar-lib=/usr/local/lib

あるいは

$ ruby extconf.rb --with-bar-dir=/usr/local

詳細は dir_config を参照してください。

configure オプション

ここでの configure オプションとは ruby インタプリタ作成時に指定された configure スクリプトのオプション、または extconf.rb 実行時のオプショ ンのことです。extconf.rb の作成者は任意のオプションを定義できます。 (arg_config を参照)。

また、以下のオプションがデフォルトで利用可能です。

--with-opt-include=directory

ヘッダファイルを探索するディレクトリ directory を追加します。

--with-opt-lib=directory

ライブラリファイルを探索するディレクトリ directory を追加します。

--with-opt-dir=directory

ヘッダファイル、ライブラリファイルを探索するディレクトリ directory/include、directory/lib をそれぞれ追加します。

--with-target-include=directory

extconf.rb の中で dir_config(target) を実行していればこ のオプションを指定できます。

ヘッダファイルを探索するディレクトリ directory を追加します。

--with-target-lib=directory

extconf.rb の中で dir_config(target) を実行していればこ のオプションを指定できます。

ライブラリを探索するディレクトリ directory を追加します。

--with-target-dir=directory

extconf.rb の中で dir_config(target) を実行していればこ のオプションを指定できます。

ヘッダファイル、ライブラリファイルを探索するディレクトリ directory/include、directory/lib をそれぞれ追加します。

depend ファイル

カレントディレクトリに depend という名前のファイルがあればこの内容は生 成される Makefile の最後に追加されます。

このファイルは、ソースファイルの依存関係を記述するために使用します。例 えば、拡張ライブラリのソース foo.c が foo.h をインクルードしていれば foo.h が更新されたときにも foo.c を再コンパイルしたくなります。

このような依存関係を記述するには depend ファイルに以下を書きます。

foo.o: foo.c foo.h

これは、foo.o が foo.c と foo.h に依存し、これらが更新されれば foo.o は再作成されることを示します。

C コンパイラによっては、このような出力を自動生成することができます。こ のためのオプションは -M として知られています。

cc -M *.c > depend

は、上記の出力を得ます。

gcc では、さらに -MM というオプションがあります。これは(通常更新するこ とのないstdio.hなど)システムのヘッダファイルを依存ファイルとみなしませ ん。(#include <...> の形式で参照されるヘッダファイルをシステムのヘッダ ファイルとみなすようです)

gcc -MM *.c > depend

のように使います。

depend ファイルを他の用途で使用しては行けません。mkmf.rb はこの内容を Makefile に出力する際に多少の加工を行う場合があります。

make ターゲット

extconf.rb が生成した Makefile には以下のターゲットが定義されています。

all

拡張ライブラリを作成します。

clean

作成した拡張ライブラリ、オブジェクトファイルなどを削除します。

distclean
realclean

clean に加えて Makefile extconf.h(create_header参照) core ruby などを削除します。

install
site-install

作成した拡張ライブラリを $archdir にインストールします。カレン トディレクトリにディレクトリ lib があればその配下の ruby スクリプト (.rb ファイル)をディレクトリ階層ごと $libdir にインストールし ます。

独立したライブラリとしてコンパイルされた場合、拡張ライブラリは $sitearchdir に、 ruby スクリプトは $sitelibdir にインストールされます。

関数

以下は、extconf.rb を記述するのに有用な関数です。ヘッダファイルの存在 チェック、ライブラリの存在チェックなど、システム間の差異を調べシステム に適した Makefile を生成するためにこれらの関数が必要となります。

try_link(src[, opt])

C ソース src をコンパイル、リンクします。リンクの結果が正常 かどうかを true または false で返します。

optが指定されていればリンク時のコマンド引数として渡されます。 このメソッドは、$CFLAGS$LDFLAGS の値もコンパイラ、リ ンカに渡します。

src には直接 C ソースを文字列で書きます。

try_cpp(src[, opt])

C ソース src をプリプロセスし、その結果が正常かどうかを true または false で返します。

$CFLAGS opt をプリプロセッサの引数に渡します。

src には直接 C ソースを文字列で書きます。

このメソッドはヘッダファイルの存在チェックなどに使用します。

egrep_cpp(pat, src[, opt])

C ソース src をプリプロセスし、その結果が正規表現 pat にマッチするかどうかを判定します。pat には、egrepの正 規表現を文字列で指定します。

CPP $CFLAGS opt | egrep pat

を実行し、その結果が正常かどうかを true または false で返します。

src には直接 C ソースを文字列で書きます。

このメソッドはヘッダファイルに関数などの宣言があるかどうかを検 査するのに使用します。

try_run(src[, opt])

C ソース src をコンパイルし、生成された実行ファイルを実行し た結果が正常かどうかを true または false で返します。

src には直接 C ソースを文字列で書きます。

install_rb(mfile, dest[, srcdir])

このメソッドは、create_makefile が使用します

ディレクトリ srcdir/lib 配下の ruby スクリプト (.rbファイル)をdest にインストールするための Makefile 規則を mfile に出力します。mfileIO クラスの インスタンスです。

srcdir/lib のディレクトリ構造はそのまま dest 配 下に反映されます。

引数 srcdir のデフォルトは "." です。

append_library(libs, lib)

ライブラリ lib をライブラリのリスト libs の先頭に追加 した結果を返します。

引数 libs とこのメソッドの戻り値はリンカに渡す引数形式の文字 列です。これは UNIX では、

"-lfoo -lbar"

であり、MS-Windows などでは

"foo.lib bar.lib"

です。引数 lib は、この例での "foo""bar" に あたります。

have_library(lib[, func])

ライブラリ lib がシステムに存在し、関数 func が定義され ているかどうかを検査します。検査に成功すれば $libslib を追加し true を返します。そうでなければ false を返しま す。

func の指定を省略した場合、関数の存在は検査しません。

func が nil または空文字列("") であれば特に何も検査をせずに、 無条件で lib を追加します。

find_library(lib, func[, path1[, path2[, ...]]])

関数 func が定義されたライブラリ lib を探します。最初 にパス指定なしで検査し、次にpath1を指定、ダメならpath2 を指定・・・といったように順にリンク可能なライブラリを探索します。

検査に成功すれば lib$libs に追加し、見つかったパス を $LDFLAGS に追加して true を返します。指定されたすべての パスを検査してもライブラリ lib が見つからなければ false を返 します。

path の指定がなければhave_libraryと同じです。

have_func(func[, header])

関数 func が存在するかどうかを検査します。

func が存在すれば $defs-DHAVE_func (func は大文字に変換されます)を追加して true を返します。そ うでなければ false を返します。

header には、関数funcを使用するのに必要なヘッダファイ ル名を指定します。これは引数の型チェックのためではなく(そのような 検査はこのメソッドでは行われません)関数が実際にはマクロで定義され ている場合などのために使用します。

have_header(header)

ヘッダファイル header が存在するかどうかを検査します。

header が存在すれば $defs に、 -DHAVE_header (header は実際には大文字に変換され 文字 "-", "." が、"_" に置き換えられます)を追加して true を返しま す。そうでなければ false を返します。

arg_config(config[, default])

configure オプション --config の値を返します。値が設定 されていなければ default を返します。

extconf.rb の場合、

ruby extconf.rb --foo --bar=baz

と実行すれば arg_config("foo") の値は true、arg_config("bar") の値は "baz" です。

with_config(config[, default])

arg_config と同じですが、--with-config オプショ ンの値だけを参照します。

enable_config(config[, default])

arg_config と同じですが、--enable-config オプショ ン、または--disable-config オプションの値だけを参照しま す。

create_header()

have_funcなどの検査結果を元に

#define HAVE_FUNC 1
#define HAVE_HEADER_H 1

などを定義した extconf.h ファイルを生成します。

dir_config(target[, default])
dir_config(target[, idefault, ldefault])

システムに標準では存在しないヘッダファイルやライブラリがあるディレ クトリを extconf.rb の利用者が指定できるようにします。

最初の形式では、configure オプション --with-target-dir=path が指定されていれば、 $CFLAGS に "-Ipath/include" を $LDFLAGS に "-Lpath/lib" を追加します。

--with-target-dir の代わりに configure オプション --with-target-include--with-target-lib が指定されていれば、これらの値を $CFLAGS$LDFLAGS に それぞれ追加します。

configure オプションがいずれも指定されていなければ、省略可能な引数 deafultidefaultldefault が使用されます。最初 の形式では、"-Idefault/include""-Ldefault/lib" をそれぞれ追加し、二番目の形式では "-Iidefault""-Lldefault" をそれぞれ追加 します。

create_makefile(target[, srcdir])

have_libraryなどの各種検査の結果を元に 拡張ライブラリ target.so を作成する Makefile を生成します。

srcdir は make 変数 srcdir の値になり、これにはソー スがあるディレクトリ名を指定します。省略した場合は、 extconf.rb があるディレクトリです。

extconf.rb は普通このメソッドの呼び出しで終ります。

定数

CONFIG

Config::MAKEFILE_CONFIG と同じです。

CFLAGS

この値は、Makefileにも反映されます。

LINK

リンクを検査するときのコマンドラインのフォーマットです。 try_linkなどが使用します。

CPP

プリプロセスを検査するときのコマンドラインのフォーマットです。 try_cppなどが使用します。

グローバル変数

$srcdir

ruby インタプリタを make したときのソースディレクトリです。

$libdir

ruby のライブラリを置くディレクトリです。 通常 /usr/local/lib/ruby/version です。

$archdir

マシン固有のライブラリを置くディレクトリです。 通常 /usr/local/lib/ruby/version/arch です。

$sitelibdir

サイト固有のライブラリを置くディレクトリです。 通常 /usr/local/lib/ruby/site_ruby/version です。

$sitearchdir

サイト固有でかつマシン固有のライブラリを置くディレクトリです。 通常 /usr/local/lib/ruby/site_ruby/version/arch です。

$hdrdir

ruby のヘッダファイル ruby.h が存在するディレクトリです。 通常 /usr/local/lib/ruby/version/arch です。

$topdir

拡張ライブラリを make するためのヘッダファイル、ライブラリ等が存在 するディレクトリです。

通常 /usr/local/lib/ruby/version/arch です。

$defs

拡張ライブラリをコンパイルするときのマクロ定義を指定する配列です。

have_funchave_header の検査結果はこの配列の要素になり

["-DHAVE_FUNC", "-DHAVE_HEADER_H"]

といった値になります。

create_header は、この変数の値を参照してヘッダファイルを生成 します。

$libs

拡張ライブラリをリンクするときに一緒にリンクされるライブラリを指定 する文字列です。

have_libraryfind_library の検査結果はこの文字列に

"-lfoo -lbar"

のように間に空白を置いて連結されます。

$CFLAGS

拡張ライブラリをコンパイルするときの C コンパイラのオプション、ヘッ ダファイルのディレクトリを指定する文字列です。

dir_config はこの変数に値 "-Idir" を追加します。

$LDFLAGS

拡張ライブラリをリンクするときのリンカのオプション、ライブラリファ イルのディレクトリを指定する文字列です。

find_librarydir_config はこの変数に値 "-Ldir" を追加 します。



rubyist ML