Top
Photo Drawings Software Writing Reading Memo Study Profile Bookmark 

即席GNU (autoconf & automake)

自作のプログラムをてっとりばやくGNUツールのようにパッケージ化するためのメモ

より正確、詳細かつ参考になるページ

そのほか、オーム社から「GNU Autoconf/Automake/Libtool」 という本が出ています。 その英文全文はこちら から入手できます。 でも、まとまった内容であるとはいえません。

Autoconfを一通り

バージョン

autoconf/automakeのバージョンを少し上げただけで、 それまでに作成したconfigure.inに対してautoconf/automakeを実行すると エラーや警告を生じるようになる場合が多々あります。 むやみに最新バージョンをインストールしないほうがよいようです。

以降の記述でも、autoconf/automakeのバージョンによってはエラーや警告が 発生する場合があります。

サンプルプロジェクト

instantGNU-1.0.tar.gz
dlopen使用バージョン(cygwin非対応)
instantGNU_ltdl-1.1.tar.gz
ltdl使用バージョン(cygwin対応)

参考となるように、つぎのような特徴を持たせた。

  • 階層をもつ。
  • 実行ファイルと共有ライブラリの両方を作成する。
  • インクルードファイルを別ディレクトリにまとめる。

プロジェクトの構成

dlopen使用バージョンのプロジェクト構成はつぎのようになっている。

    (root) + (↓プロジェクトごとに作成するファイル)
           |
           +- main +- main.c
           |       +- Makefile.am
           |
           +- include +- defs.h
           |          +- Makefile.am
           |
           +- libraries +- libShared.c
           |            +- Makefile.am
           |
           +- configure.in
           +- Makefile.am
           |
           | (↓コピーしてくるだけでひとまず用が足りるファイル)
           |
           +- AUTHORS
           +- COPYING
           +- ChangeLog
           +- INSTALL
           +- NEWS
           +- README

ltdl使用バージョンのプロジェクト構成はつぎのようになっている。

    (root) + (↓プロジェクトごとに作成するファイル)
           |
           +- main +- main.c
           |       +- Makefile.am
           |
           +- include +- defs.h
           |          +- Makefile.am
           |
           +- libraries +- libShared.c
           |            +- Makefile.am
           |
           +- configure.in
           +- Makefile.am
           |
           | (↓コピーしてくるだけでひとまず用が足りるファイル)
           |
           +- AUTHORS
           +- COPYING
           +- ChangeLog
           +- INSTALL
           +- NEWS
           +- README
           |
           |  (↓libtoolize --ltdlにより生成されるファイル)
           |
           +- libltdl +- config-h.in
           |          +- configure.in
           |          + ...
           |          :
           |          :  (↓libtoolのバグに対処するために作成するファイル。)
           |          :
           |          +- acconfig.h  
           |
           +- ltmain.sh

標準的なプロジェクト構成手順

1,GNUの標準規約が要求するファイル・ディレクトリを用意する。

$ touch INSTALL NEWS README COPYING AUTHORS ChangeLog
    

2,configure.inの雛形を生成する。

$ autoscan
    

3,configure.scanをconfigure.inに名前を替える。

$ mv configure.scan configure.in
    

4,configure.inを編集する。

5,Makefile.amを作成する。 各サブディレクトリにもMakefile.amをつくる。 ディレクトリツリーの中間ノードに用意するMakefile.amには、サブディレクトリ名を列挙するだけ。 葉ノードのMakefile.amに主要なコマンドを記述する。

6,acconfig.hを作成する。コピーでも可。

7,aclocal.m4を生成する。aclocalはacinclude.m4などをもとにしてaclocal.m4を生成する。

$ aclocal
    

8,config.h.inを生成する。

$ autoheader
    

9,Makefile.inを生成する。--add-missingを指定すると、 install-shやmkinstalldirsなどをautomakeが用意してくれる。

$ automake --add-missing
    

10,autoconfを実行し、configure.inからconfigureを生成する。

$ autoconf
    

shared libraryを作成する場合

libtoolというツールが、 shared libraryを含めた各種ライブラリを生成する手順の プラットホーム依存性を隠蔽してくれる。 (Windows DLLを生成したい場合は後の記述を参照。)

1,configure.inに

  AM_PROG_LIBTOOL
    
を追加する。(またはAC_PROG_LIBTOOL

2,aclocalを実行する。 これによりaclocal.m4が生成される。

3,libtoolizeを実行する。 これにより、 config.guess,config.sub,ltconfig,ltmain.sh,ltcf-c.shが生成される。

4,libtoolizeがaclocalを実行しろというので、ふたたびaclocalを実行する。

WindowsのDLLを生成する場合

Cygwin環境上で、DLLを生成するよう指示することもできる。 Unix上で動的ライブラリを生成する場合とほぼ同様で、configure.inに AM_PROG_LIBTOOLの前にAC_LIBTOOL_WIN32_DLLを追加する。 これで、Unix上では動的ライブラリ、Windows上ではDLLを生成するこ とができる。

動的ライブラリ読み込み処理を含む場合

Unixでのdlopenや、WindowsでのLoadLibraryなど、 動的ライブラリ読み込みのプラットホーム依存性を隠蔽するために、libtoolは ltdlというライブラリを用意している。 dlopenやLoadLibraryなどの代わりに、ltdl提供のlt_dlopen,lt_dlsym...などの 関数を使用すれば、動的ライブラリロードに関してソースコードの可搬性を 保つことができる。 ltdlについてはinfo libtool参照。

プロジェクト構成手順

以下に説明する手順は、cygwin上でのlibtoolのバグに対処するために 若干手間を費やしている。

1, libtoolizeを実行する。 その際に--ltdl --copyオプションを指定する。

$ libtoolize --ltdl --copy
するとlibltdlというサブディレクトリが作成される。

以下の2から5までの手順は、cygwin上でのバグ対処のために必要。

2, libltdlに移動する。

$ cd libltdl
    

3, つぎの一行のみを含むlibltdl/acconfig.h を作成し、

#undef __WINDOWS__
        
autoheaderを実行する。
$ autoheader
        
これにより、libltdl/config-h.in にこの行が追加される。

4, libltdl/configure.in(またはconfigure.ac) につぎのコードを追加する。 AC_OUTPUTよりも前の位置に挿入しなければならないことに注意。

case $host_os in
cygwin* | mingw* | pw32*)
  AC_DEFINE(__WINDOWS__)
  ;;
esac
        
そして、autoconfを実行する。
$ autoconf
       
libltdl/configureが更新される。 これによって、以降でconfigureした際にconfig.h中で __WINDOWS__がdefineされる。

5, トップディレクトリに戻る。

$ cd ..
   

6,configure.inに以下の内容を追加する。

AC_LIBTOOL_WIN32_DLL
AC_LIBLTDL_CONVENIENCE
dnl AC_LIBLTDL_INSTALLABLE
AC_LIBTOOL_DLOPEN
AC_PROG_LIBTOOL
AC_CONFIG_SUBDIRS(libltdl)
AC_LIB_LTDL
AC_SUBST(INCLTDL)
AC_SUBST(LIBLTDL)
    
これには、動的ライブラリ作成のためのマクロも含んでいる。 動的ライブラリ読み込みだけをおこなうならば、いくつかのマクロは不要かも。

あとは通常のようにautomake,autoconfなどをおこなえばよい。

ソースコードでは、lt_dlinit,lt_dlopen(ext),lt_dlsymなどを使うようにする。

実例については、ltdl使用サンプルパッケージを参照。

サンプルプログラムのビルド・実行手順

サンプルプログラムは、つぎの二種類のバイナリファイルを生成する。
autoconfsample
実行ファイル。 第一引数に動的ライブラリ名、第二引数にライブラリ中の関数名を指定して 起動すると、ライブラリをロードして、その中の関数を呼び出す。
libShared.{a,la,(so),(dll.a)},(cygShared.dll)
ライブラリ。funcという関数のみを実装する。

dlopen使用バージョン

$ tar zxf instantGNU-1.0.tar.gz
$ cd instantGNU-1.0
$ ./configure --prefix=/tmp
$ make
$ make install
$ cd /tmp
$ ./bin/autoconfsample ./lib/libShared.so func
configured in Tue Nov 19 00:29:25 JST 2002
hi!

ltdl使用バージョン

$ tar zxf instantGNU_ltdl-1.1.tar.gz
$ cd instantGNU_ltdl-1.1
$ ./configure --prefix=/tmp
$ make
$ make install
$ cd /tmp
$ ./bin/autoconfsample ./lib/libShared func
configured in Tue Nov 19 00:29:25 JST 2002
hi!

サンプルプログラム(autoconfsample)を実行する際に、 第一引数のライブラリ名には拡張子を含まないか、 もしくはlibShared.laと指定することに注意。 Unix上ではlibShared.soと指定しても動くが、 cygwin上では、libShared.dllもしくはlibShared.dll.a、cygShared.dll を指定するとライブラリをロードできない。 これはlibltdlのバグによる。

各設定ファイルの書き方

Makefile.am中の変数

Makefile.am中には、ほかの値に置き換えられる名前(=変数)が いくつかの方法で記述できる。

書式 その変数を解釈するプログラム 値の設定方法
@NAME@ configure configure.in中でAC_SUBST(NAME)。 (値はAC_OUTPUTの時点で設定されている値が使用される。)
$(NAME)
${NAME}
make Makefile中でNAME = value あるいはmakeを呼び出す側やMakefile中で環境変数を設定
$$NAME sh makeを呼び出す側あるいはMakefile中でシェル変数を設定

@NAME@

@NAME@は、configureによって置換される「変数」を指す。

たとえば、configure.in 中に

hoge=foo
  :
AC_SUBST(hoge)
  :
AC_OUTPUT(bar ...)
      
と記述し、bar.in に
  :
@hoge@
  :
      
@hoge@が含まれていると、configure の結果、
  :
foo
  :
      
というように@hoge@fooに置き換えられた ファイルbarが生成される。

$(NAME),${NAME}

Makefile{,.am,.in}中の$(NAME)および${NAME}は、 Makefile内で設定されるmakeマクロを指す。 NAMEという名前のmakeマクロが設定されていなければ、 環境変数NAMEを指す。

$$NAME

makeは通常、文字'$'を変数名の開始文字として扱う。 '$'自体をMakefile中に記述したい場合、'$$'とする。

定義したい変数が次の二条件の両方に当てはまる場合、この方法を使う。

  • configure時ではなくmake実行時に値を決定する。
  • makeのマクロ変数では適切に設定できない。
たとえばMakefileのアクション部で次のようにシェル変数を定義し 参照する場合に使う。
foo: bar
    DATE=`date` \
    echo $${DATE} >> compile_foo.log
    
makeは、文字列$${DATE}${DATE}としてシェルに渡す。 シェルはこの文字列${DATE}をシェル変数DATEへの参照として 扱う。

configure.inの書き方

プリプロセッサ時にdefineしたい場合

Cプログラム中のシンボル定義

#define NAME Value
    
を、configureの結果に応じて設定する方法について説明する。

マクロAC_DEFINEまたはAC_DEFINE_UNQUOTEDを使う。

AC_DEFINE(変数名,[値,[説明]])
AC_DEFINE_UNQUOTED(変数名,[値,[説明]])
    
変数名または値にシェル変数を使用する場合は AC_DEFINE_UNQUOTEDを使用する。

たとえば、変数hoge"foo"と指定したい場合、 configure.inに次のように指定する。

AC_DEFINE(hoge, "foo")
    
この定義結果をプログラムに反映させる方法としては、 ヘッダファイルで#defineする方法と、 コンパイラ起動時に-Dオプションで指定する方法の二通りがある。

ヘッダファイルでdefineさせたい場合
  1. configure.inでAM_CONFIG_HEADER(include/config.h)と 指定しておく。
  2. include/config.h.inに以下の行を追加する。
    #undef hoge
                  
configureを実行すると、生成されるinclude/config.hに次の行が含 まれる。
#define hoge "foo"
         
プリプロセッサを起動する際のオプションでdefineさせたい場合
configure.inでAM_CONFIG_HEADER(...)を指定しない。 configureすると、Makefileにつぎのように書き込まれる。
DEFS = "..... -Dhoge=\"foo\" ...."
	

configureの結果に応じてMakefile中で使用する変数の値を設定したい場合

マクロAC_SUBSTを使う。

AC_SUBST(変数名)
    

例として、リンカに渡すオプションを切り替える方法を取り上げる。

リンカがGNU ldであった場合、リンク時に -Wl,--export-dynamicを指定し、そうで無い場合は -Wl,d,yを指定したい。

GNU ldであるかどうかは、aclocal.m4を探すと、 マクロAC_PROG_LD_GNUが、 変数ac_cv_prog_gnu_ldyesあるいはnoに 設定するようになっており、これで判別できる。 そこで、configure.inにつぎのように記述する。

AC_PROG_LD
AC_PROG_LD_GNU
if test "x$ac_cv_prog_gnu_ld" = "xyes" ;then
    EXPORTLDFLAG=-Wl,--export-dynamic
else
    EXPORTLDFLAG=-Wl,-d,y
fi
AC_SUBST(EXPORTLDFLAG)
    

ここでautomakeを実行すると、automakeはconfigure.in中の AC_SUBST(EXPORTLDFLAG)を検出し、生成するMakefile.in中に

EXPORTLDFLAG = @EXPORTLDFLAG@
という行を挿入する。

インストール先で./configureを実行すると、 Makefile.in中の@EXPORTLDFLAG@は、 AC_PROG_LD_GNUの結果に応じて-Wl,--export-dynamicと、 -Wl,-d,yのどちらかの文字列に置き換えられる。

学校のWSで実行した場合、つぎのような行を含むMakefileが生成される。

DLLTOOL = ....
EXPORTLDFLAG = -Wl,-d,y
GTK_CFLAGS = ....
    

その他