LoginSignup
20
23

More than 5 years have passed since last update.

Automakeでライブラリを作ることにチャレンジ1年生

Last updated at Posted at 2017-11-05

要点

  • Autotoolは基本的にautoconfautomakelibtools。ただし、libtoolsはそんなに使われない?
  • autoconfはコンパイルするとき、環境依存になりやすい関数の差分を吸収する設定などを行う
  • automakeはmakefileを簡単に作ってくれるツール
  • libtoolsはライブラリを作るときに使用するツール。ライブラリはOSによって作られる拡張子などが変わるのでこのツールが使われる

ショートカット

  1. 何をコンパイルするかというautomake用の入力ファイルMakefile.amを作る
    1. 最初に何を生成するかを示すprefix_PRIMARY = (生成ファイル名)を書く
      • prefix: インストール先(bindir, sbindir, libexecdir, pkglibexecdir, noinstなどprefixとの相対パスで決まる。詳しくはコチラ)
      • PRIMARY: 何を生成するか(PROGRAMS:普通のプログラム、LIBRARIES: ライブラリ, LTLIBRARIES: Libtools用の設定ファイル、HEADERS: 公開ヘッダ、DATA: データ、MANS, TEXINFOS: ドキュメントなど)
    2. 生成するファイルは何からできているかを生成ファイル名_SOURCES = ソース一覧を書く
      • ただし、ここで._で置き換える。例えば、libtest.soならlibtest_so_SOURCESのように書く
      • 同様にコンパイル時のオプションは生成ファイル名_CFLAGS = オプション生成ファイル_LDFLAGS = オプションのように書く
  2. autoreconf --installを実行する
    1. 色々指示が出るのでconfigure.acを直す
    2. 例えば、libtoolsを作る場合は
      • LT_INITを書く
      • AM_PROG_ARを書く
      • AC_CONFIG_MACRO_DIRS([m4])を書く
      • 他にMakefile.amにACLOCAL_AMFLAGSに-l m4を書く
    3. さらに動的ライブラリを作りたい場合Makefile.amの生成ファイル_LDFLAGS次を追加する
      • -module
      • -export-dynamic
      • -shared
      • -rpath $(libdir)
  3. automakeを実行する

あとはconfigure; makeすれば完成ですが、ライブラリファイル(.a, .soなど)は.libディレクトリ配下に作成されます

動機

以前の記事でAutotoolsから目を逸らしたのですが、なんとなくやっておかねばならない気がしてきたので、チャレンジしてみます。

AutotoolsはGNU Build Systemとも言って、ソースをいろんな環境でコンパイルできるようにするツールのセットのようです。Wikipedia

ツール自体はつぎの3つから成り立っており、これらを組み合わせてconfigureやmakefileを作成するようです。

  • autoconf
  • automake
  • libtools

しかし、日本語Wikipediaを見る限り、スゲェ難しそうです。
確かに環境依存しないコンパイルは大変ですが、どうして3つもツールが必要なのかとか色々考えてしまいます。

結局プログラマである自分は何を書けばいいのか、なぜ書かねばならないのか、その点を中心的に見ていこうと思います。

Step by Step

パッと見た感じ、

まずは次のステップをするようです。

  1. autoscanを実行し、configure.acを作る
  2. 1.を基にaclocalを実行し、aclocal.m4を作る
  3. 1.を基にautoheaderを実行し、config.h.inを作る

・・・と進めて行くようです。が、チュートリアルを見てみるとautoreconfなるコマンドがあり、

‘autoreconf’ Run all tools in the right order.

Autotools Tutorial

と書かれているのでとりあえず、コレをしてみます。


$ autoreconf --install
autoreconf: 'configure.ac' or 'configure.in' is required

チッ・・・

autoscanで環境をスキャンする

とりあえず、autoscanをしてみましょう。
マニュアルによると

 Examine  source  files  in  the directory tree rooted at SRCDIR, or the
 current directory if none is given.  Search the source files for common
 portability  problems,  check for incompleteness of `configure.ac', and
 create a file `configure.scan' which is  a  preliminary  `configure.ac'
 for that package.

from http://manpages.ubuntu.com/manpages/yakkety/man1/autoscan.1.html

とりあえず実行すればいいのかな?

configure.scanが作られました。

mv configure.scan configure.ac だけして再度autoreconf --installを実行。

  • autom4te.cache
  • autoscan.log
  • config.h.in
  • configure
  • configure.ac

が作られました。あとは、makefile.amを作るのが必要みたいですね。これだけは勉強しないと・・・

makefile.amを作る

チュートリアルとこのサイトに従って

Makefile.am
SUBDIRS = src
Makefile.am
noinst_LTLIBRARIES = libcheap_csv_reader.la
libcheap_csv_reader_la_SOURCES = record_read.c

で、再度autoreconf --install実行。特に何も言われなかったのでautomakeを実行。


configure.ac: error: no proper invocation of AM_INIT_AUTOMAKE was found.
configure.ac: You should verify that configure.ac invokes AM_INIT_AUTOMAKE,
configure.ac: that aclocal.m4 is present in the top-level directory,
configure.ac: and that aclocal.m4 was recently regenerated (using aclocal)
automake: error: no 'Makefile.am' found for any configure output
automake: Did you forget AC_CONFIG_FILES([Makefile]) in configure.ac?

ダメ?とりあえずAC_CONFIG_FILES[(Makefile src/Makefile)]と。チュートリアルにあったAM_INIT_AUTOMAKE([foreign -Wall -Werror])を追加して再度実行。


configure.ac:11: installing './compile'
configure.ac:6: installing './install-sh'
configure.ac:6: installing './missing'
src/Makefile.am:1: error: Libtool library used but 'LIBTOOL' is undefined
src/Makefile.am:1:   The usual way to define 'LIBTOOL' is to add 'LT_INIT'
src/Makefile.am:1:   to 'configure.ac' and run 'aclocal' and 'autoconf' again.
src/Makefile.am:1:   If 'LT_INIT' is in 'configure.ac', make sure
src/Makefile.am:1:   its definition is in aclocal's search path.
automake: warnings are treated as errors
/usr/local/Cellar/automake/1.15.1/share/automake-1.15/am/ltlibrary.am: warning: 'libcheap_csv_reader.la': linking libtool libraries using a non-POSIX
/usr/local/Cellar/automake/1.15.1/share/automake-1.15/am/ltlibrary.am: archiver requires 'AM_PROG_AR' in 'configure.ac'
src/Makefile.am:1:   while processing Libtool library 'libcheap_csv_reader.la'
src/Makefile.am: installing './depcomp'
autoreconf: automake failed with exit status: 1

おお、いっぱい出てきた。
とりあえず、1つ1つ潰していきましょう。

libtoolsの設定を修正する

configure.acにLT_INITを追加します。また、AM_PROG_ARも必要らしいので追記します。

再度autoreconf --install実行。


glibtoolize: putting auxiliary files in '.'.
glibtoolize: copying file './ltmain.sh'
glibtoolize: Consider adding 'AC_CONFIG_MACRO_DIRS([m4])' to configure.ac,
glibtoolize: and rerunning glibtoolize and aclocal.
glibtoolize: Consider adding '-I m4' to ACLOCAL_AMFLAGS in Makefile.am.
configure.ac:9: installing './ar-lib'
configure.ac:10: installing './config.guess'
configure.ac:10: installing './config.sub'

AC_CONFIG_MACRO_DIRS([m4])を追加してみるのを考えて見てと言われたので、追加します。
また、Makefile.amにACLOCAL_AMFLAGSに-l m4を追加してみてと言われたので追加です。


$ autoreconf --install
aclocal: warning: couldn't open directory 'm4': No such file or directory
glibtoolize: putting macros in AC_CONFIG_MACRO_DIRS, 'm4'.
glibtoolize: copying file 'm4/libtool.m4'
glibtoolize: copying file 'm4/ltoptions.m4'
glibtoolize: copying file 'm4/ltsugar.m4'
glibtoolize: copying file 'm4/ltversion.m4'
glibtoolize: copying file 'm4/lt~obsolete.m4'

m4がないと怒られましたが、glibtoolizeが勝手に追加してくれたみたいです。

で、automakeを実行しても何も起きませんでした。
この時点で大量にファイルが作られておりますが、とりあえず、動くか試して見ましょう。

configureで動くか確認


$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... ./install-sh -c -d
(以下略)

おお、いつものアレが出てきました・・・

で、makeをするとsrcの下にlibcheap_csv_reader.laができています。lib_cheap_csv_reader.loもできています。
・・・ただ、どちらも単なるテキストファイルなんですよね・・・
.aファイルはないのか・・・とfindをかけてみるとsrc配下の.libという隠しフォルダに隠されていました。これをリンクすればいいわけですね。

動的ライブラリを作るには?

さて、ここで、動的ライブラリが作りたいなと思ってしまいました。

libtoolのマニュアルを見てみると次のオプションが役に立ちそうです

-module ダイナミックロードできるライブラリを作成する。 モジュール名は lib' で始まる必要はないが、 名前の衝突を避けるためlibname' と `name' はパッケージの中で 同時に使用すべきではない。

-export-dynamic OUTPUT-FILE のシンボルを dlsym(3) を使って解決できるようにする。

-static OUTPUT-FILE がプログラムの場合、 アンインストールされた共有 libtool ライブラリはリンクしない。 OUTPUT-FILE がライブラリの場合、 静的ライブラリを作成するのみである。
```

これで、実行・・・あれ?作られない。

色々試行錯誤しているうちに次のオプションが必要なことが判明。

-shared
-rpath $(libdir)

sharedはccのオプションですね。rpathは・・・動的ライブラリに必要なオプションらしいでのすが、動的のクセに自分のパスを知らないといけないのか・・・

ちなみに、-moduleオプションを外すとdylibファイルが作成されました。

参考

20
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
23