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

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

日々

link permalink

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年 5月 20日 03:59]
link 編集する

コメント一覧

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



link permalink

C++ の変数初期化

会社で大幅にソフトを置き換えるチャンスがあったので、思い切って C から C++11(gcc-4.6 で使える範囲だけ)に切り替えました。

まだまだ使いこなせてませんが C++98 より見やすいです。それでも C++ は魔界だなーと思うこともありますけど…。

Effective Modern C++ にも出てますが、C++11 で導入された uniform initialization(波括弧 { a, b, c, } での初期化)は、丸括弧や等号を置き換えることができます。大抵の場合は、ですが。

コンテナ系など std::initializer_list を引数に取れる場合は、丸括弧と置き換えると動きが変わってしまいます。

std::initializer_list を引数に取るコンストラクタがある例

int i1(5);
-> 5
int i2{5};
-> 5

std::vector<int> b1(5);
-> size:5: 0, 0, 0, 0, 0,
std::vector<int> b2{5};
-> size:1: 5,

丸括弧は丸括弧で、引数が 0個になるといきなり関数宣言扱いされる、クラスメンバ変数に使えないなど、一貫性がなくて使いづらいのです。

関数宣言扱いされる例

std::vector<int> a1();
-> a1 type is std::vector<int, std::allocator<int> > ()
std::vector<int> a2{};
-> size:0:

結局、コンストラクタが std::initializer_list を取れるかどうかを意識して、丸括弧と波括弧を使い分ける必要がありまして、だいぶ難しいですね…。

メモ: 技術系の話は Facebook から転記しておくことにした。

[編集者: すずき]
[更新: 2015年 12月 23日 23:26]
link 編集する

コメント一覧

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



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

管理用メニュー

link 記事を新規作成

合計:  counter total
本日:  counter today

link About www2.katsuster.net
RDF ファイル RSS 1.0
QR コード QR コード

最終更新: 9/20 11:22

カレンダー

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

最近のコメント 5件

  • link 18年09月07日
    すずき 「ありがとう!\nこちらこそ、楽しみにして...」
    (更新:09/11 19:30)
  • link 18年09月07日
    よしだあ 「おつかれさまでした!\nまた仕事できるの...」
    (更新:09/11 19:17)
  • link 18年08月15日
    すずき 「うーん、なんか暴走したり、動かなかったり...」
    (更新:08/15 10:52)
  • link 18年08月15日
    すずき 「実行できた。あと実行ファイルパスについて...」
    (更新:08/15 10:42)
  • link 18年08月15日
    すずき 「さすがに x86_64 と arm のク...」
    (更新:08/15 10:35)

最近の記事 3件

link もっとみる
  • link 18年09月15日
    すずき 「[TigerVNC のエラーメッセージ] TigerVNC Jav...」
    (更新:09/20 11:22)
  • link 18年09月16日
    すずき 「[音が出なくなったよ Windows 10] 昨日まで元気に動作し...」
    (更新:09/20 11:10)
  • link 18年09月13日
    すずき 「[府民から都民へ] 家が決まりました。今月末から東京都民です。さよ...」
    (更新:09/17 20:03)

こんてんつ

open/close wiki
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 過去日記について

その他の情報

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