# setup.rb を使ったパッケージを作る

## シングルパッケージアーカイブを作る

「シングルパッケージアーカイブ」とは、以下のファイルが 一組だけ入ったプログラムパッケージのことです。

- コマンド
- Ruby ライブラリ
- Ruby 拡張ライブラリ
- その他のデータ

つまり普通のプログラムパッケージのことです。

シングルパッケージアーカイブを作るには、アーカイブを 以下のルールに従ってレイアウトしてください。

    アーカイブのトップ/
      setup.rb
      bin/
          コマンド類
      lib/
          Ruby ライブラリ
      ext/
          拡張モジュール
      data/
          その他のデータ
      conf/
          設定ファイル
      man/
          man ページ
      test/
          テスト

bin/, lib/, ext/, data/, conf/, man/ の下には各々インストールされるイメージを そのままにファイルを配置します。例えば lib/tmail/header.rb というファイルを 置くと RUBYLIB/tmail/header.rb としてインストールされます。なお、これらの ディレクトリは中身が空のときには省略できます。

ext/ は配置ルールが少し特殊です。複数のファイルからひとつの共有ライブラリ anyname.so ができるので、.so ができるべき場所にディレクトリを作り、その中に 必要なファイルを入れます。例えば RUBYLIB/ARCH/tmail/parser.so が必要ならば、 ディレクトリ ext/tmail/parser/ を作ってその中に parser.c や extconf.rb, depend, MANIFEST などを置きます。

[注意] setup.rb は extconf.rb または MANIFEST があるディレクトリだけを コンパイル対象にします。

最後に、test/ にはテストコードを置きます。setup.rb は test/unit で 書かれたテストしか実行できません。なお test/unit は Ruby 1.8 以降に 標準添付されています。

## マルチパッケージアーカイブを作る

setup.rb は複数のパッケージを一つのアーカイブにまとめて、それを 同時に扱うことができます。例えば依存関係のあるパッケージを全部 まとめて配布したりするのに使えます。

マルチパッケージアーカイブを作るには、まずトップに setup.rb と ディレクトリ packages/ を作り、その下にパッケージ名のディレクトリ を作ります。そしてその中にシングルパッケージアーカイブと同じ ディレクトリツリーを配置します。つまり全体像は以下のようになります。

    アーカイブのトップ/
        setup.rb
        packages/
            tmail/      # tmail パッケージ
                bin/
                lib/
                ext/
                data/
                conf/
                man/
                test/
            raccrt/     # raccrt パッケージ
                bin/
                lib/
                ext/
                data/
                conf/
                man/
                test/
            strscan/    # strscan パッケージ
                bin/
                lib/
                ext/
                data/
                conf/
                man/
                test/
            amstd/      # amstd パッケージ
                bin/
                lib/
                ext/
                data/
                conf/
                man/
                test/

packages/ の下にあるディレクトリ名がパッケージ名です。 このパッケージ名は setup.rb のヘルプメッセージに表示され、 インストールするパッケージを --with や --without でユーザが 選択するときに使われます。

またデフォルトだとパッケージはソート順にインストールされます。 順番を変更したいときは metaconfig API の declare_packages を 使ってください。

## setup.rb の働き

ファイルを上記のとおり配置しておけばあとは setup.rb が自動的に それなりの動作をしてくれます。具体的には、setup のときに以下の ことを実行します。

- bin/ 以下にあるファイルが #! で始まっていてかつ 文字列 ruby を含む場合は #! 行を --ruby-path に置き換える
- ext/ 以下の拡張モジュールをコンパイルする

install では以下のことを実行します。

- bin/ 以下のファイルを --bindir にインストール
- lib/ 以下の *.rb を --rbdir にインストール
- ext/ 以下の *.so を --sodir にインストール
- data/ 以下のファイルを --datadir にインストール
- conf/ 以下のファイルを --localstatedir にインストール
- man/ 以下のファイルを --mandir にインストール

## フックファイル

デフォルトの動作でもたいていの場合には通用します。しかし場合によっては インストール時になにか特別な作業をしたいこともあるでしょう。その 場合は特別なファイルを置くことで動作を追加することができます。

たとえば setup のタイミングに lib/tmail/ でなにかをしたいとしたら、 lib/tmail/pre-setup.rb を作ってその中にやりたいことを書きます。

    # pre-setup.rb

    # racc の文法ファイルをその場でコンパイル (普通、やらない)
    system "racc #{srcdir_root + '/src/mp.y'} -o mailp.rb"

    # require 'tmail' で tmail/ の中身を全部 require できるようにする
    list = Dir.glob(curr_srcdir + '/*.rb').collect {|n| File.basename(n) }
    File.open( '_loadlib.rb', 'w' ) {|f|
      f.puts list.collect {|n| "require 'tmail/" + n + "'" }
    }
    File.open( '../tmail.rb', 'w' ) {|f|
      f.puts "require 'tmail/_loadlib'"
    }

一般には、ディレクトリに入った直後に pre-TASK.rb を、 ディレクトリを出る直前に post-TASK.rb を実行します。 TASK の部分に使えるもの（フック可能なタスク）は config, setup, install, test, clean, distclean の六つです。

またフックスクリプトの実行中に例外が起きた場合はインストーラ 全体が即座に失敗します。逆に言うと、処理失敗の時は例外を投げれば よいということです。exit はしないでください。

またフックファイルの例で srcdir_root や curr_srcdir という メソッドを使っていることに注意してください。setup.rb には、 作ったファイルだけを別のディレクトリに置く仕組みがある （srcdir と objdir が区別されている）ので、カレントディレクトリから 読めばよいとは限りません。フックファイル中では以下のルールに従って ください。

- 読みこみは常に現在の srcdir (curr_srcdir) から行う。
- 書きこみは常にカレントディレクトリに対して行う。

srcdir/objdir の仕組み

    archive_top/                  srcdir は変更しないで
        ext/tmail/scanmail/
            MANIFEST
            depend
            extconf.rb
            scanmail.c

    OBJ/                          対応する objdir に作ったものを置く
        ext/tmail/scanmail/
            Makefile
            scanmail.o
            scanmail.so

この場合 archive_top/ を「srcdir のルート」、 OBJ/ を「objdir のルート」と言います。 また archive_top/ext/tmail/scanmail/ を「カレント srcdir」、 OBJ/ext/tmail/scanmail/ を「カレント objdir」と呼びます。

こうしておくと、srcdir に対しては読み出ししか行われないので、 clean などしなくても常に srcdir を最小限のファイルのきれいな 状態に保てます。またマニアックなところでは複数のクロスコンパイルを 同時に行ったりもできるようになります。そこまでいかなくとも、 コンパイルオプションだけを変えていくつものバージョンを作ったりする ことはあるでしょう。この仕組みはそのような場合に便利なのです。

srcdir/objdir 対応は絶対必要というわけではありませんが、対応して おいて損はありません。

また curr_srcdir や srcdir_root など フックファイル中で使える API については別ページの <a href="hookapi.html">フック API リファレンス</a> を参照してください。

## メタコンフィグ

setup.rb では、config のタスクオプションを増やすことができます。 このために使うのが metaconfig ファイルです。

例えば、libc のパスを指定するための config オプション --libc と、 win32 サポートのオンオフを指定するためのオプション --win32 を 追加してみましょう。setup.rb を置くのと同じディレクトリに metaconfig というファイルを作り、この中に以下のような Ruby スクリプトを書きます。

    add_path_config 'libc', '/lib/libc.so', 'path to the C standard library'
    add_bool_config 'win32', false, 'compile with Win32 support'

これで、パスを指定するオプション --libc と、真偽値を取る オプション--win32 が追加されました。以下のように config のときに使うことができます。

    ruby setup.rb config --libc=/lib/libc-devel.so --win32

また setup.rb のヘルプメッセージにも自動的に表示されます。

metaconfig で使える API については <a href="metaconfapi.html">metaconfig API リファレンスマニュアル</a> を参照してください。

## 以前のバージョンとの互換性

インストーラというものの特殊性を考え、 互換性はまったく保っていません。2.0 以前とは別物と思ってください。 前バージョンの動作が必要ならばそのバージョンを使いましょう。 以前のバージョンとは以下の点で非互換です。

- ディレクトリ構造が完全に違う
- PATHCONV がない
- share/ → data/
- フックの形式が違う
- dryrun コマンドがない → --prefix 使ってインストールしてください。

## ライセンスについて

setup.rb 自体は GNU LGPL (Lesser General Public License) version 2.1 に従って配布します。詳細はファイル COPYING を見てください。また、 setup.rb を使ってインストールするプログラムが LGPL である必要は ありません。

## インストールマニュアル

このアーカイブに含まれている Usage_*.txt は自由にコピー・編集 して自分のパッケージに使ってください。Copyright 表示が入って いますが、これは単に自動化が楽だから入っているだけなので消しても 構いません。