コグノスケ


link 未来から過去へ表示(*)  link 過去から未来へ表示

link もっと前
2015年12月26日 >>> 2015年12月26日
link もっと後

2015年12月26日

GNU autotools入門 その1

その1その2

ソースコードのビルドシステムは多々あって決定打はない(個人的にはそう思う)のですが、比較的メジャーと言って良いのがGNU autotoolsです。ビルドする際にconfigureしてmakeするヤツは、大抵autotoolsが絡んでいます。

そんなGNU autotoolsを成すツール群の一つにautoconf/automakeと言うツールがあります。こいつらは簡単に言えばMakefileを作るツールです。

autoconf, automakeとMakefileの関係
configure.ac --(autoconf)--> configure

Makefile.am --(automake)--> Makefile.in --(configure)--> Makefile

最終的に生成されるのはMakefileなのに、なぜ直接書かず遠回りをするかというと、どんな環境でもそれなりに動くMakefileを直接書くのは、実は結構大変だからです。

例えば、依存関係にあるライブラリの有無をチェックしつつ、クロスコンパイルで動的ライブラリを生成するようなMakefileをパッと書けますか?私には無理そうですし、仮に書けたとしても、Makefileを作るのは手段であって目的ではないので、あまり時間を使いたくありません。

ビルドでお決まりの手順はツールで自動生成して楽して作りたい、これがGNU autotoolsや他のビルドツールを使う目的です。

automakeの非互換性

こんな便利なautomakeですが、たまに仕様が変わって、以前の書き方だと怒られることがあります。

楽するためにツールを使っていたのに、ツールの仕様変更に対応するため時間を使うのは本末転倒な感じもしますが、それでもMakefileを直接書くより断然楽でしょうね。

昔のバージョンであるautomake-1.9ではこういう書き方が出来たのですが、

automakeでSOURCESにサブディレクトリを指定

COMMON_DIR = ./common

common_SOURCES = $(COMMON_DIR)/utils.c

これがautomake-1.14だと、

サブディレクトリを指定したときのautomakeのwarning
test/Makefile.am:19: warning: source file '$(COMMON_DIR)/utils.c' is in a subdirectory,
test/Makefile.am:19: but option 'subdir-objects' is disabled
automake: warning: possible forward-incompatibility.
automake: At least a source file is in a subdirectory, but the 'subdir-objects'
automake: automake option hasn't been enabled.  For now, the corresponding output
automake: object file(s) will be placed in the top-level directory.  However,
automake: this behaviour will change in future Automake versions: they will
automake: unconditionally cause object files to be placed in the same subdirectory
automake: of the corresponding sources.
automake: You are advised to start using 'subdir-objects' option throughout your
automake: project, to avoid future incompatibilities.

こんな風に長々と説教されます。警告の通りsubdir-objectsを有効にすると、今度は $(COMMON_DIR) という名前のディレクトリが作られ、common/utils.cは無いと言われ、コンパイルエラーになります。

なんじゃそりゃ。

解決方法

この警告を解決する方法は、サブディレクトリにもMakefile.amを置くこと、のようです。

今までのMakefile.am
$ tree
.
|-- Makefile.am
|-- configure.ac
`-- test
    |-- Makefile.am
    |-- common
    |   `-- utils.c
    `-- test.c

----
configure.ac
----
AC_PREREQ(2.61)
AC_INIT([automake_test], [0.1])
AC_ARG_PROGRAM()
AC_CONFIG_SRCDIR([test/test.c])
AC_CONFIG_HEADER([config.h])
AC_CONFIG_AUX_DIR([conf])
AM_INIT_AUTOMAKE([foreign])
LT_INIT()

AC_CONFIG_FILES([Makefile
	test/Makefile])

AC_OUTPUT()

----
Makefile.am
----
SUBDIRS = test

----
test/Makefile.am
----
testdir = $(libdir)
test_LTLIBRARIES = libtest.la

libtest_la_SOURCES = test.c \
	common/utils.c

このようなプロジェクトがあったとします。このプロジェクトはautomakeに、下記のように怒られます。

automake-1.14に怒られるの図
$ autoreconf --force
test/Makefile.am:5: warning: source file 'common/utils.c' is in a subdirectory,
test/Makefile.am:5: but option 'subdir-objects' is disabled
automake: warning: possible forward-incompatibility.
automake: At least a source file is in a subdirectory, but the 'subdir-objects'
automake: automake option hasn't been enabled.  For now, the corresponding output
automake: object file(s) will be placed in the top-level directory.  However,
automake: this behaviour will change in future Automake versions: they will
automake: unconditionally cause object files to be placed in the same subdirectory
automake: of the corresponding sources.
automake: You are advised to start using 'subdir-objects' option throughout your
automake: project, to avoid future incompatibilities.
autoreconf2.50: automake failed with exit status: 1

以下のように各ディレクトリにMakefile.amを作ってあげれば、警告は出なくなります。

これからのMakefile.am
.
|-- Makefile.am
|-- configure.ac★変更★
`-- test
    |-- Makefile.am★変更★
    |-- common
    |   |-- Makefile.am★追加★
    |   `-- utils.c
    `-- test.c

----
configure.ac
----
AC_PREREQ(2.61)
AC_INIT([automake_test], [0.1])
AC_ARG_PROGRAM()
AC_CONFIG_SRCDIR([test/test.c])
AC_CONFIG_HEADER([config.h])
AC_CONFIG_AUX_DIR([conf])
AM_INIT_AUTOMAKE([foreign])
LT_INIT()

AC_CONFIG_FILES([Makefile
	test/Makefile test/common/Makefile])
                      ^^^^^^^^^^^^^^^^^^^^ 追加

AC_OUTPUT()


----
test/Makefile.am
----
SUBDIRS = common

test_newdir = $(libdir)
test_new_LTLIBRARIES = libtest_new.la

libtest_new_la_SOURCES = test.c

libtest_new_la_LIBADD = common/libcommon.la


----
test/common/Makefile.am
----
noinst_LTLIBRARIES = libcommon.la

libcommon_la_SOURCES = utils.c

最初は面倒くさいですが、やってみるとtestとtest/commonが分離されて見通しが良くなります。

利点と欠点

従来の方法(親ディレクトリにMakefile.amを置く方法)と、新しい方法(各ディレクトリにMakefile.amを置く方法)の利点と欠点を考えてみます。

利点は、再利用性が高くなることです。

先の例で出てきたcommonディレクトリが「何らかの便利な機能を提供しているパッケージ」だとして、他のプロジェクトにcommonのコードを流用する場合を考えてみましょう。

従来のtest/Makefile.amに全て書く方法だと、commonディレクトリのソースコードは使いまわせますが、ビルド設定であるMakefile.amが親ディレクトリのtest側にあって、単純に使いまわせません。なぜならtest/Makefile.amではtestのビルド設定とcommonのビルド設定が混ざって書かれているため、commonのビルド設定だけを抽出するのが難しいためです。

これが新しいtest/Makefile.amとtest/common/Makefile.amに分ける方法だと、文字通りcommonディレクトリをコピーするだけでMakefile.amつまりビルドの設定も使いまわすことができます。

欠点は面倒くさいことです。

無意味にディレクトリを分割したがる輩には、ディレクトリごとにMakefile.amを作らなければならない面倒くささが、ある意味の抑止力になるので、欠点だとも言い切れませんが、やはり面倒くさいものは面倒くさいです…。

ちなみに従来の方法で書くと警告が出ますが、今のところ使えない訳でもない(※)ので、ちょっと試してみるだけとか、一時的なツールに使うだけであれば、従来の方法を選べば良いと思います。

(※)今は警告だけですが、そのうち廃止されるかもしれません。

編集者:すずき(2018/05/20 03:59)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
2015年12月26日 >>> 2015年12月26日
link もっと後

管理用メニュー

link 記事を新規作成

<2015>
<<<12>>>
--12345
6789101112
13141516171819
20212223242526
2728293031--

最近のコメント5件

  • link 20年6月19日
    すずきさん (04/06 22:54)
    「ディレクトリを予め作成しておけば良いです...」
  • link 20年6月19日
    斎藤さん (04/06 16:25)
    「「Preferencesというメニューか...」
  • link 21年3月13日
    すずきさん (03/05 15:13)
    「あー、このプログラムがまずいんですね。ご...」
  • link 21年3月13日
    emkさん (03/05 12:44)
    「キャストでvolatileを外してアクセ...」
  • link 24年1月24日
    すずきさん (02/19 18:37)
    「簡単にできる方法はPowerShellの...」

最近の記事3件

  • link 24年4月17日
    すずき (04/18 22:44)
    「[VSCodeとMarkdownとPlantUMLのローカルサーバー] 目次: LinuxVSCodeのPlantUML Ex...」
  • link 23年4月10日
    すずき (04/18 22:30)
    「[Linux - まとめリンク] 目次: Linuxカーネル、ドライバ関連。Linuxのstruct pageって何?Linu...」
  • link 20年2月22日
    すずき (04/17 02:22)
    「[Zephyr - まとめリンク] 目次: Zephyr導入、ブート周りHello! Zephyr OS!!Hello! Ze...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 04/18 22:44