コグノスケ


2015年12月5日

Device Treeを試したらハマった

ARM Linuxのブート方法は3種類あって、一番古い方式はもう使われていません。自作エミュレータの内蔵ブートローダで使っているのは2番目に新しい、ATAGSと呼ばれる方式です。

最新の流行はDevice Treeを使う方式らしいので、内蔵ブートローダを改造して試してみました。が、なぜかカーネルが異常なアドレスにアクセスして死にます。アドレスを調べても、仕様書にないレジスタです。

発動条件を調べるとDevice Treeを有効(CONFIG_MACH_VERSATILE_DTを有効にする)にして、Device Treeを使ってブートするとハマるようです。

Linuxカーネルのコードを見てもATAGSで起動したときと、Device Treeで起動したときに実行されるコードがなぜか違うし、どういう意味なんだこれ…。

怪しいレジスタアドレス

Linuxカーネルのコードに出てくるレジスタ名で調べていたら、どうもmach-integratorにあるコードと同じレジスタアドレスを使っているように見えます。

下記がIntegratorのレジスタアドレス定義です。

arch/arm/mach-integrator/hardware.h

#‎define IRQ_STATUS 0
#define IRQ_RAW_STATUS 0x04
#define IRQ_ENABLE 0x08
#define IRQ_ENABLE_SET 0x08
#define IRQ_ENABLE_CLEAR 0x0C

#define INT_SOFT_SET 0x10
#define INT_SOFT_CLEAR 0x14

#define FIQ_STATUS 0x20
#define FIQ_RAW_STATUS 0x24
#define FIQ_ENABLE 0x28
#define FIQ_ENABLE_SET 0x28
#define FIQ_ENABLE_CLEAR 0x2C

で、下記がDevice Treeで起動したときのVersatile PB/ABのレジスタアドレス定義です。コピペだと思えるくらいに似ています。

drivers/irqchip/irq-versatile-fpga.c

#define IRQ_STATUS 0x00
#define IRQ_RAW_STATUS 0x04
#define IRQ_ENABLE_SET 0x08
#define IRQ_ENABLE_CLEAR 0x0c
#define INT_SOFT_SET 0x10
#define INT_SOFT_CLEAR 0x14
#define FIQ_STATUS 0x20
#define FIQ_RAW_STATUS 0x24
#define FIQ_ENABLE 0x28
#define FIQ_ENABLE_SET 0x28
#define FIQ_ENABLE_CLEAR 0x2C

#define PIC_ENABLES 0x20 /* set interrupt pass through bits */

こちらが正しいレジスタアドレス定義です。ATAGSで起動した場合はこちらのアドレスが使われます。

arch/arm/mach-versatile/include/mach/platform.h

#define SIC_IRQ_STATUS                  0
#define SIC_IRQ_RAW_STATUS              0x04
#define SIC_IRQ_ENABLE                  0x08
#define SIC_IRQ_ENABLE_SET              0x08
#define SIC_IRQ_ENABLE_CLEAR            0x0C
#define SIC_INT_SOFT_SET                0x10
#define SIC_INT_SOFT_CLEAR              0x14
#define SIC_INT_PIC_ENABLE              0x20    /* read status of pass through mask */
#define SIC_INT_PIC_ENABLES             0x20    /* set interrupt pass through bits */
#define SIC_INT_PIC_ENABLEC             0x24    /* Clear interrupt pass through bits */

私もそんなに詳しいわけではありませんが、Versatile AB/PB (DUI0225D) とIntegrator CP (DUI0159B) は全く別のボードだと思うので、恐らくDevice Treeに対応した人が間違えたのでしょうね…。

バグってるっぽい

気になったのでqemuで試してみましたが、やはりエラーが出ます。もしかして動作確認してないのかなあ??

しかしqemuさんは強い子でして、明らかに未定義領域にwriteされたのに警告を出すのみで、とにかく先に突き進んでくれます。それで結果的に動くからスゴイですよね…。

QEMUでversatile dt (device tree) を試してみた
$ qemu-system-arm -kernel linux-4.1.13/arch/arm/boot/zImage \
 -dtb linux-4.1.13/arch/arm/boot/dts/versatile-pb.dtb \
 -M versatilepb \
 -append 'console=ttyAMA0' \
 -nographic -serial mon:stdio

Uncompressing Linux... done, booting the kernel.
vpb_sic_write: Bad register offset 0x2c★★★エラー出てる★★★
Booting Linux on physical CPU 0x0
Linux version 4.1.13 (katsuhiro@vbox) (gcc version 4.9.2 (GCC) ) #4 Sun Dec 6 01:46:36 JST 2015
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00093177
CPU: VIVT data cache, VIVT instruction cache
Machine model: ARM Versatile PB

★を付けたところ(vpb_sic_write〜 と出ている部分)がqemuの警告です。

編集者:すずき(2015/12/06 03:11)

コメント一覧

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



2015年12月9日

Flash ROMのエミュレーション

自作エミュレータ(リンク)にFlash ROMのエミュレーションを実装しました。

未実装だらけですが、mkfsしてmountするくらいなら、とりあえず動いています。今はリセットすると中身が消えますが、ファイルに読み書きするように変更したら、ストレージとして使えそうです。

バースト書き込みモードがあって高速と思われるIntelのNOR Flashをエミュレーションしていますが、速度的には残念な感じです。

flashへの書き込み速度
$ dd if=/dev/zero of=/dev/mtdblock0 bs=262144 count=10
10+0 records in
10+0 records out
2621440 bytes (2.5MB) copied, 17.980000 seconds, 142.4KB/s

ただ、これはエミュレータ自体が遅いのも原因ではあります。

ramfsへの書き込み速度
$ dd if=/dev/zero of=/tmp/aaa bs=262144 count=10
10+0 records in
10+0 records out
2621440 bytes (2.5MB) copied, 0.830000 seconds, 3MB/s

最速でもこれくらいにしかならないはずです。

作ってみて感じたこと

Flash ROMをエミュレーションしていて思ったのは、単純なだけに書き込みに関してはかなり非効率的なデバイスだということです。

Flash ROMは独立したコマンド線を持ちません。CPUはコマンドもデータも混ぜてバスにWriteします。WriteされたデータはFlash ROM側の状態によってコマンドと解釈されたり、データと解釈されたりする仕組みです。

書き込みの際は、出来る限りデータだけ送る方が効率が良いですが、Flashの場合は仕様上コマンドWriteやステータスReadを必ず挟まなければならないため、効率が悪いです。

Flashの宿命として部分的な書き換えが出来ませんので、書き換えの際は必ずErase -> Writeが行われます。Eraseは256KBなどの大きな単位なのに、書き込みは最大でも128バイトしか書けません。これも効率が悪い原因でしょう。

将来への展望

次に何か足すとしたら、eMMCにチャレンジしてみようと思います。ストレージ専用のI/Fならば断然効率が違う…はずです。たぶん。

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

編集者:すずき(2015/12/10 01:44)

コメント一覧

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



2015年12月10日

光で測る

レーザー距離計(メーカーのサイトへのリンク)を買ってみました。BOSCHのGLM 50Cです。Amazonで1万5000円でした。もっと安い機種もありますが、どうせならスマホとつながった方が面白いだろうと思いBluetooth対応機種を選びました。

メタルの巻き尺と比べると、

  • 断然早い、1秒で計測
  • 自分から見えるところならどこでも測れる
  • 天井などの手が届かない高さも測れる
  • 角度計、水平器の代用もできる
  • 測定値を書き写す必要がない

測定値は本体に記録され、Bluetoothでスマホに飛ばして写真上に値を書き写すこともできます(要、専用アプリ)。

引っ越しや、新たに家具を買う時に非常に便利そうです。活躍の機会は遠いと思いますけどね…。

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

編集者:すずき(2015/12/12 01:01)

コメント一覧

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



2015年12月11日

Androidは巨大な壁

自作エミュレータ、ARM9とはいえ、一応ARMをエミュレーションしているわけだし、いつかAndroidも動かせるだろうか?と思って、試しにAOSPをビルドしてみました。

生成されたイメージファイルを見てみると、アプリも何も入れていないのにsystem.imgが1.6GBもあります。

ちなみにVersatile PBのNANDは最大でも64MBですので、全くお話になりませんでした。eMMCに期待ですかね…。

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

編集者:すずき(2015/12/12 01:23)

コメント一覧

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



2015年12月12日

意外と知らない日本語の一面

電車で隣に座った親子がしりとりをずっとやっていました。幼稚園くらいのお子さんは言葉が枯渇気味になったようで、お父さんに「あ」で始まるなら思いつく…とリクエストをしていました。

そのときお父さんは「た」だったので「た」で始まり「あ」で終わる単語が思いつかず、ずっと悩んでいたそうです。

…という話を、電車を降りたときに奥さんがするもんだから、「よっしゃ、俺らも考えるべし」と挑戦したものの、

  • タスマニア
  • タンザニア

くらいしか思いつかず何だかイマイチ…。くやしいので家帰ってから辞書引いたら、

  • ターヘルアナトミア
  • ターミナルケア
  • タウンウェア

などがありましたが、外来語しかありません。

そんなバカなと思って「あ」で後方一致かけても、「あ」で終わる単語のほぼ全てが外来語です。

「あ」で終わる日本語って無いんですね。意外でした。

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

編集者:すずき(2015/12/15 23:46)

コメント一覧

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



2015年12月13日

高槻ドライブ

車を放置しすぎてバッテリーが上がり、今まで自宅に3回ほどJAFを呼んでいます。4回だったかもしれないが…。

あまりにも車が可哀想なので、1か月に1度はドライブに行くことにしました。今回は高槻市の北側を体験するコースです。

  • 枚方亀岡線(府道6号線)を北へ
  • The山道(府道733号線)を西へ
  • 茨木亀岡線(府道46号線)を南へ

距離は30km程度、約1時間ほどです。ここまで書いておいてなんですが、あまりオススメしません。

46号線から一瞬だけ見える高槻市、茨木市の夜景は綺麗ですが、他は森ばかりで何も見えません。733号線は対向可能なのに車1台分しか幅がなく、横は崖で、二度と行きたくない道です。

もっとマシな道はねーのかよ?と思うのですが、高槻市は道路状況があまり良くないのです。

北は山道、南は淀川で通れず、東西は大阪〜京都を移動する車で渋滞だらけです。

その点言うと、つくば市は、土地が平らで、道が綺麗で、空いてて、広くて、とても良かったんですがねえ…。

編集者:すずき(2015/12/18 01:58)

コメント一覧

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



2015年12月20日

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)

コメント一覧

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



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 この記事にコメントする



2015年12月27日

GNU autotools入門 その2

その1その2

GNU autotoolsは簡単なんですが、使い始めるまではかなり難儀した記憶があります。例えば、下記のようにlibtest_new.soという名前の「動的ライブラリ」を作成するプロジェクトを作ったとします。

GNU autotoolsで動的ライブラリをビルドするプロジェクト
.
|-- 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

基本的にGNU autotoolsを使う時はautoreconfというコマンドを実行すれば、勝手に全ての関連ファイルが更新されます。

ただ残念なことに、初回だけはそうもいきません。

初回のautoreconfの結果
$ autoreconf
configure.ac:16: error: required file 'conf/compile' not found
configure.ac:16:   'automake --add-missing' can install 'compile'
configure.ac:16: error: required file 'conf/config.guess' not found
configure.ac:16:   'automake --add-missing' can install 'config.guess'
configure.ac:16: error: required file 'conf/config.sub' not found
configure.ac:16:   'automake --add-missing' can install 'config.sub'
configure.ac:15: error: required file 'conf/install-sh' not found
configure.ac:15:   'automake --add-missing' can install 'install-sh'
configure.ac:16: error: required file 'conf/ltmain.sh' not found
configure.ac:15: error: required file 'conf/missing' not found
configure.ac:15:   'automake --add-missing' can install 'missing'
test/Makefile.am: error: required file 'conf/depcomp' not found
test/Makefile.am:   'automake --add-missing' can install 'depcomp'
autoreconf2.50: automake failed with exit status: 1

このようにたくさん怒られます。何を怒っているのかというと、AC_CONFIG_AUX_DIR([conf]) で指定したディレクトリ(詳細は automakeのマニュアル参照)に、補助ツールが入ってないじゃないか!と怒っているのです。

エラーメッセージの最後に「'automake --add-missing' can install 'depcomp'」とあるように、優しいautotoolsさんは解決策も用意してくれています。これもやってみましょう。

add-missingを実行した結果
$ automake --add-missing
configure.ac:16: installing 'conf/compile'
configure.ac:16: installing 'conf/config.guess'
configure.ac:16: installing 'conf/config.sub'
configure.ac:15: installing 'conf/install-sh'
configure.ac:16: error: required file 'conf/ltmain.sh' not found
configure.ac:15: installing 'conf/missing'
test/Makefile.am: installing 'conf/depcomp'

まだ何か怒っています。ltmain.shが無いそうです。これはlibtoolというツールの一部です。

最初に述べたようにこのプロジェクトは「動的ライブラリ」を作るプロジェクトです。GNU autotoolsは動的ライブラリをビルドする際にlibtoolという別のツールを使っています。プロジェクトのconfigure.acにLT_INIT() と書いていましたよね。この行はlibtoolを使うことをautotoolsに伝えるため(詳細は libtoolのマニュアル参照)にあります。

逆に言えば、LT_INIT() が無いと動的ライブラリはビルドできません。そんなの知るかって?正直言って私もそう思いました、けど、今のところそういう作りなので我慢するしかありません…。

さてltmain.shが何者かもわかったところで、肝心のどこから持って来るか?ですが、こんなときってfindが便利ですよね?

ltmain.shを無理やり持ってくる
$ find /usr -name ltmain.sh
/usr/share/libtool/config/ltmain.sh

$ cp /usr/share/libtool/config/ltmain.sh conf/ltmain.sh

$ automake --add-missing

$ tree
.
|-- Makefile.am
|-- Makefile.in
|-- aclocal.m4
|-- conf
|   |-- compile -> /usr/share/automake-1.14/compile
|   |-- config.guess -> /usr/share/automake-1.14/config.guess
|   |-- config.sub -> /usr/share/automake-1.14/config.sub
|   |-- depcomp -> /usr/share/automake-1.14/depcomp
|   |-- install-sh -> /usr/share/automake-1.14/install-sh
|   |-- ltmain.sh
|   `-- missing -> /usr/share/automake-1.14/missing
|-- config.h.in
|-- configure
|-- configure.ac
`-- test
    |-- Makefile.am
    |-- Makefile.in
    |-- common
    |   |-- Makefile.am
    |   |-- Makefile.in
    |   `-- utils.c
    `-- test.c

以上のようにltmain.shを無理やり持って来たら、エラーも警告も出なくなりました。めでたしめでたし、です。

もし他の環境に持っていく場合、conf/missingなどのシンボリックリンクはリンク先に何もない可能性がある(※)ので、実体に置き換えておくと良いでしょう。

(※)autotoolsをインストールしていない環境もあれば、インストールされていたとしても違うディレクトリに置かれている可能性があります。

全てを台無しにする

既にautotoolsをお使いの方はもちろんのこと、autoreconfという見慣れぬコマンドに対して、すぐにヘルプを見た方はお気づきかと思いますが、今までの手順を一撃でやってくれるコマンドがあります。

その名もautoreconf --installです。早速やってみましょう。

今までの苦労は何だったのか
$ tree
.
|-- Makefile.am
|-- configure.ac
`-- test
    |-- Makefile.am
    |-- common
    |   |-- Makefile.am
    |   `-- utils.c
    `-- test.c

$ autoreconf --install
libtoolize: putting auxiliary files in AC_CONFIG_AUX_DIR, `conf'.
libtoolize: copying file `conf/ltmain.sh'
libtoolize: Consider adding `AC_CONFIG_MACRO_DIR([m4])' to configure.ac and
libtoolize: rerunning libtoolize, to keep the correct libtool macros in-tree.
libtoolize: Consider adding `-I m4' to ACLOCAL_AMFLAGS in Makefile.am.
configure.ac:16: installing 'conf/compile'
configure.ac:16: installing 'conf/config.guess'
configure.ac:16: installing 'conf/config.sub'
configure.ac:15: installing 'conf/install-sh'
configure.ac:15: installing 'conf/missing'
test/Makefile.am: installing 'conf/depcomp'

$ tree
.
|-- Makefile.am
|-- Makefile.in
|-- aclocal.m4
|-- conf
|   |-- compile
|   |-- config.guess
|   |-- config.sub
|   |-- depcomp
|   |-- install-sh
|   |-- ltmain.sh
|   `-- missing
|-- config.h.in
|-- configure
|-- configure.ac
`-- test
    |-- Makefile.am
    |-- Makefile.in
    |-- common
    |   |-- Makefile.am
    |   |-- Makefile.in
    |   `-- utils.c
    `-- test.c

シンボリックリンクを実体に置き換えるところまで勝手にやってくれます。いやー、もう全部これだけで良いんじゃない?というくらい、素晴らしいです。

スクラッチビルドのススメ

GNU autotoolsを使う時は、常にautoreconf --install頼りでもそこそこ動くはずですが、いざautoreconfがエラーで止まった時は手も足も出なくなってしまいます。

私個人の悲しい経験から言って、この手の便利ツールって、中で何をやっているのかサッパリわからないので、トラブルが起きると非常に苦労します。

  • ツールを動かすのに最低限どんなファイルが必要か?
  • 無いときはどんなエラーが出るか?
  • エラーの解消には何をすれば良いか?

ツールのコードを読めとは言いません(私も読んだことありません)が、せめてこのくらいは調べた方が良いです。トラブルシュートの早さが断然違います。

これらを調べるには、マニュアルを当てずっぽうに読むより、スクラッチからプロジェクトを作ってみるのが一番効きます。既存プロジェクトのコピペでは得られなかった、新たな発見があると思いますよ。

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

コメント一覧

  • 名前さん(2018/05/11 12:40)
    助かりました。勉強になります。
  • すずきさん(2018/05/12 21:45)
    お役に立てて何よりです。
open/close この記事にコメントする



2015年12月28日

GNU autotools入門 その3

GNU autotoolsの話を書いていて思い出したのですが、autotools + libtoolで動的ライブラリをビルドしたとき、生成されたlibxxxx.soを見失ったのは、きっと俺だけじゃないはず。

正解はMakefile.amの有るディレクトリに .libsという隠しディレクトリが出来て、その中にlibxxxx.soが置かれます(※)。

おそらくMakefile.amと同じディレクトリに置くと、不都合なことがあったからだと思われますが、何がダメだったのかサッパリ想像付きません…。

(※)生成物を .libsに置くのはGNU libtoolの仕様らしいので、正確にはGNU autotoolsは関係ありません。

libtoolと .libsディレクトリ

調べてみたら、意味不明な .libsディレクトリの件、libtoolのマニュアル(マニュアルへのリンク)に、はっきりと書いてありました。

Note how libtool creates extra files in the .libs subdirectory, rather than the current directory. This feature is to make it easier to clean up the build directory, and to help ensure that other programs fail horribly if you accidentally forget to use libtool when you should.

だそうで、

  • .libsを消せばlibtoolの影響は元に戻せる
  • libtoolを使い忘れたら、他がコケるから(なんで?.libsが無いから??)確実にわかる

というお気遣いのようです。

でも今はバージョン管理システムがあるから、クリーンナップのお気遣いは不要ですし、libtoolは大抵autotoolsと組み合わせるので、libtoolのせいで失敗したかどうか容易にわかりません。

優しい気遣いのはずが、今となっては壮絶な空振りで、見ていて悲しくなります…。

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

編集者:すずき(2015/12/28 17:10)

コメント一覧

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



2015年12月29日

モノクロからカラーへ

自作ARMエミュレータememu(リンク)の仮想ターミナルが白黒で寂しいので、色が出るようにしてみました。ECMA-048のSGR (Select Graphic Rendition) の一部に対応しています。


仮想ターミナルが色付きに対応

ところで、今回作るまで存在すら知らなかった機能に、ネガ・ポジ機能(※)があります。

規格見たときは「何これ?誰が使うんだ?」って思ってたんですが、実はtopコマンドのPID PPID USER PR ... という見出し(背景が白い部分)部分で、しれっと使われています。


実はtopが使っているネガ・ポジ機能

いつも目にしている画面なのに、案外知らないものです…。

(※)普通の「ネガ」は色相反転を指しますが、ememuでは前景色と背景色の入れ替えで実現しました。他のターミナルも入れ替えで対応しているようです。

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

編集者:すずき(2015/12/29 00:41)

コメント一覧

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



こんてんつ

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 サイトの情報