壊れたメガネ

ホッチキスの達人の意識の高いブログ。

mathtex のソースコードを Autotools でパッケージングしてみた。

mathtex ホームページ
今回パッケージングした mathtex の GitHub リポジトリ
f:id:oasynnoum:20120914034016g:plain

TEX 使ってみたいのと、 Autotools そろそろ手をつけてみたいという事でやってみた。
mathtex は使う分にはとても簡単。 zip アーカイブをダウンロード展開して、ソースをコンパイルしてバイナリを cgi が動くディレクトリに置くだけ。

$ wget http://www.forkosh.com/mathtex.zip
$ mkdir mathtex
$ unzip -d mathtex mathtex.zip
$ cd mathtex
$ cc mathtex.c   \DLATEX=\"$(which latex)\"   \DDVIPNG=\"$(which dvipng)\"   \
      –o mathtex.cgi 

このコマンドから見て取れるように、 mathtex は latex と dvipng に依存している。
基本的にこれだけ。
だけど実際には mathtex.cgi を置いたディレクトリ(多分 cgi-bin)は HTTP サーバー(CGI 実行ユーザー。例えば apache, www-data など)が書き込み可能でなければならない。このことは実際に画像をリクエストし、エラーが起きた際にメッセージを画像で示してくれる。
f:id:oasynnoum:20120914025900g:plain

つまり、大体次のようにする必要がある。もちろん /path/to のあたりは環境によるので適当に読み替える。

$ APACHE_USER=`cat /path/to/httpd.conf | perl -e "while (<>) { s/^User\s+([^\s]+)$/\1/ && print $_; }"`
$ chown root:$APACHE_USER /path/to/cgi-bin
$ chmod 0775 /path/to/cgi-bin

個人的に思ったことは、 CGI 実行ユーザーに対し mathtex.cgi を置くディレクトリを書き込み可能にさせる事が危なっかしいということ。
この設定を変えるにはソースコードを修正する必要がある。まだソースコードを読んではいないが、設定ファイルというものが無いのでハードコーディングされているはず。

上で展開してできたソースコードに対し、 Autotools を使ってパッケージングを行う。
この作業は新しめの Autotools (Autoconf&Automake) を使ってみよう Autoconfを参考に行った。
まずは基本ステップのとおり進める。

$ cd mathtex
$ autoscan
$ mv configure.scan configure.in
$ cat configure.in
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.65])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([mathtex.c])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.
AC_PROG_CC

# Checks for libraries.

# Checks for header files.
AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h])

# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_PID_T

# Checks for library functions.
AC_FUNC_FORK
AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK
AC_FUNC_STRTOD
AC_CHECK_FUNCS([alarm memmove memset mkdir strchr strcspn strncasecmp strspn strstr])

AC_OUTPUT

AC_INIT の引数をそれなりに変更する。とりあえず AC_INIT([mathtex], [1.05], [BUG-REPORT-ADDRESS]) というように変更した。 BUG-REPORT-ADDRES は放置。
AC_INIT の下に AM_INIT_AUTOMAKE を挿入。
さらに、 AC_CONFIG_HEADERS([config.h]) の下の行に AC_CONFIG_FILES([Makefile]) を挿入。

automake 用に Makefile.am を作る。

$ cat Makefile.am
bin_PROGRAMS = mathtex.cgi
mathtex_cgi_SOURCES = mathtex.c

mathtex_cgi_SOURCES という名前は bin_PROGRAMS の値 mathtex.cgi を参照している。 . (ドット) は _ (アンダースコア) に置き換えなければならない。

必要なファイルを作り、 autoconf する。このあたりのコマンドは全然調べていない。

$ touch NEWS README AUHTORS ChangeLog
$ aclocal
$ autoheader
$ automake -a -c
$ autoconf

ここまでやると configure スクリプトや config.h などができているのが確認できる。
mathtex.c の include ブロックの冒頭に次の行を挿入する。

#include "config.h"

あとは、

$ ./configure && make

とすれば、 mathtex.cgi が作成される。
というのが Autotools によるパッケージングの大まかな流れらしい。


冒頭でも示したとおり、 mathtexlatex と、 dvipng に依存している。
この依存関係を configure 中に確かめ、当該プログラムが見つからなければ失敗とし、それらプログラムのインストールを促すメッセージを表示し、スクリプトを停止させたい。
このことは次のマクロを用いて行える。

4.1.2 Generic Program and File Checks

AC_CHECK_PROG (variable, prog-to-check-for, value-if-found [, value-if-not-found [, path, [ reject ]]])
プログラムprog-to-check-forがPATH中にあるかどうかを調べます。もし発見された場合variableを value-if-foundに設定します。発見されなかった場合 (value-if-not-foundが指定されていた場合は) value-if-not-foundに設定します。このマクロは、reject (絶対パスのファイル名)をサーチパス上で発見してもそれは無視します。この場合、variableはパス上でみつかった prog-to-check-forで、rejectではないファイルの絶対パス名になります。 variableが既に設定されていた場合、なにもしません。 variableのために、AC_SUBSTを呼び出します。

6.1 Defining C Preprocessor Symbols

AC_DEFINE (variable [, value [, description]])
Cプリプロセッサ変数variableを定義します。valueが与えられる場合は、variableにその値を(逐語的に)セットし、それ以外では1にセットします。valueは改行リテラルを含むべきではなく、 AC_CONFIG_HEADERを使わない場合はmakeが処理してしまうので、 `#'文字を含めるべきではありません。シェル変数(m4の引用符文字 `['や`]'を含む定義値が必要なもの)を使うために、代わりに AC_DEFINE_UNQUOTEDを使ってください。descriptionは、 AC_CONFIG_HEADERを使う場合のみ役に立ちます。この場合、 descriptionは、生成された`config.h.in'にマクロ定義前のコメントとして置かれます。マクロを`acconfig.h'に記述する必要はありません。次の例は、Cプリプロセッサ変数EQUATIONを文字定数 `"$a > $b"' と定義します。

AC_DEFINE(EQUATION, "$a > $b")

AC_DEFINE_UNQUOTED (variable [, value [, description]])
AC_DEFINEに似ていますが、3つのシェル拡張は、variableと valueで一度だけ実行されるもので、変数の拡張(`$')、コマンドの代入(``')と、バックスラッシュエスケープ(`\')です。値のシングルとダブルクオートの文字列は特別な意味を持ちません。variableや valueがシェル変数の時は、AC_DEFINEの代わりにこのマクロを使ってください。以下が例です。

AC_DEFINE_UNQUOTED(config_machfile, "${machfile}")
AC_DEFINE_UNQUOTED(GETGROUPS_T, $ac_cv_type_getgroups)
AC_DEFINE_UNQUOTED(${ac_tr_hdr})

6.4 Printing Messages

AC_MSG_ERROR (error-description)
ユーザにconfigureが中断してしまうようなエラーに関して知らせます。このマクロは標準エラー出力にエラーメッセージを出力し、 configureを終了します。exit statusは0でない値になります。 error-descriptionはたとえば`invalid value $HOME for \$HOME' などのようなテキストがいいでしょう。

これらのマクロを用いて dvipng を確認するコードを次のように書いた。 latex を確認するコードも同様。

AC_CHECK_PROG([HAVE_DVIPNG], [dvipng], [yes], [no])
if test "$HAVE_DVIPNG" = "yes"; then
    AC_DEFINE_UNQUOTED([DVIPNG], ["`which dvipng`"], [path to latex bin file])
else
    AC_MSG_ERROR([dvipng NOT found. you must install latex before installing mathtex.])
fi

if ステートメントを用いているが、ここで [ ] を用いてはいけない。マクロが展開されるときに [ ] も引用符として展開され、確実に動かない。
さらに、 AC_DEFINE または AC_DEFINE_UNQUOTED の第三引数 description を省略してはいけない。うまく動かない場合がある。(参考)

configure.in は最終的に次のようになった。

$ cat configure.in
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.65])
AC_INIT([mathtex], [1.05], [BUG-REPORT-ADDRESS])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([mathtex.c])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile])

# Checks for programs.
AC_PROG_CC

AC_CHECK_PROG([HAVE_LATEX], [latex], [yes], [no])
if test "$HAVE_LATEX" = "yes"; then
    AC_DEFINE_UNQUOTED([LATEX], ["`which latex`"], [path to latex bin file])
else
    AC_MSG_ERROR([latex NOT found. you must install latex before installing mathtex.])
fi

AC_CHECK_PROG([HAVE_DVIPNG], [dvipng], [yes], [no])
if test "$HAVE_DVIPNG" = "yes"; then
    AC_DEFINE_UNQUOTED([DVIPNG], ["`which dvipng`"], [path to latex bin file])
else
    AC_MSG_ERROR([dvipng NOT found. you must install latex before installing mathtex.])
fi

# Checks for libraries.

# Checks for header files.
AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h])

# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_PID_T

# Checks for library functions.
AC_FUNC_FORK
AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK
AC_FUNC_STRTOD
AC_CHECK_FUNCS([alarm memmove memset mkdir strchr strcspn strncasecmp strspn strstr])

AC_OUTPUT

パッケージングの流れは少しはつかめた気がする。
mathtex.cgi はディレクトリパーミッションの件や、 latex dvipng などバイナリへのパスをコンパイル時に要求する点、そもそも CGI という点が少しアレなので apache モジュールとしてラップしてみたい。