なぜ?
僕には、Linux、OSをもっとよく知りたいという漠然とした欲求があります
いや、じゃあカーネルのコード読めよって話ですがまずは身近な所から始めようと思った所存でございます。
bashとかzshとかは、ソースコードがあまりにも大きすぎるので、小さめのdashでshellがどういう風に作られているかを見ていきたいと思います。
はじめに
前提のスキル(というか僕の経験)
- Linuxの基礎スキル
- OpenStack構築やWEBサービス開発で基礎的なLinuxスキルはきっとあるのでしょう
- 何かしらのプログラミング言語経験
- WEBサービスをスクラッチで書いた経験(4年以上前ですが。。)
- PythonのOSSへのバグパッチ提供
ただ上記を見ていただいて分かるように、C言語を使ってバリバリ商用コードを書いていたわけではないので、文法などは適宜調べながら読んでいきます。完走できるか分かりませんが、きっと大丈夫でしょう
バージョン and ソースコード
バージョンは、0.5.9.1を読むことにします。
ソースコードは、適当にここから取ってきました
$curl -O http://gondor.apana.org.au/~herbert/dash/files/dash-0.5.9.1.tar.gz
$tar xzvf dash-0.5.9.1.tar.gz
というわけで、ソースコードが手に入ったので読み進めていきます
ディレクトリー構造
ukinau$ ls dash-0.5.9.1
COPYING Makefile.am aclocal.m4 configure depcomp missing
ChangeLog Makefile.in config.h.in configure.ac install-sh src
ChangeLogやCOPYINGは、明確なので説明を省きますがその他のMakefile.amやaclocal.m4について、目的を調べます。普段pythonやrubyなどで開発をしてる人には、これらはあまり馴染みのないものだと思います。
file | what for |
---|---|
Makefile.am | Makefileの雛型のMakefile.inを生成するためのファイル |
configure.ac | configureの雛形 |
src | dashのソースコード |
Makefile.in | automakeによって生成される、Makefile.amからMakefile.inを生成。 |
depcomp | automake --add-missing が用意してくれることのあるスクリプト。ファイルの依存関係を自動的に調べてくれる |
missing | automake --add-missing が用意してくれるスクリプト。忘れ物を教えてくれる。 |
install-sh | automake --add-missing が用意してくれるスクリプト。make installのときに使われることがある。 |
config.h.in | autoheaderによって生成される |
aclocal.m4 | aclocalによって生成される |
configure | configure.acを元にautoconfが生成する |
調べてみると、boldした文字以外のファイルは、autotoolsによって生成される中間ファイルであることがわかります。ですので、1度全部削除して1からビルドして見ましょう。(なんで、中間ファイルがそのままtarballに入っていたんだろう。。。)
dashをソースからインストールしてみる
ディレクトリ構造
ここからダウンロードしたdashディレクトリから、色々中間ファイルを削除して
http://gondor.apana.org.au/~herbert/dash/files/dash-0.5.9.1.tar.gz
下記のようなファイルだけにする
ukinau$ rm -fr aclocal.m4 configure depcomp missing Makefile.in config.h.in install-sh
ukinau$ ls
COPYING ChangeLog Makefile.am configure.ac src
1. aclocal
ukinau$ aclocal
ukianu$ ls
COPYING ChangeLog Makefile.am aclocal.m4 autom4te.cache configure.ac src
aclocal.m4とautom4te.cacheが生成された。
aclocalとは
ここで少し脱線、「aclocalとはなんだろうか」調べて見た
https://stackoverflow.com/questions/1970926/whats-the-point-of-aclocal
https://cpplover.blogspot.jp/2013/07/gnuautotools.html
https://www.lrde.epita.fr/~adl/dl/autotools.pdf (まだ読んでない...)
どうやら上記サイトに詳しい説明が載っている
Autoconfには、Macroという概念があり複雑な処理を1つの定義にまとめている。
ただ、Autoconfが読み込めるMacroの定義ファイルは1つと決まっているので、
Macroが定義されているファイルをかき集めて、aclocal.m4という1つのファイルにしている。
でaclocalがそのファイルをconfigure.acを元に生成してくれる
2. autoconf
ukinau$ autoconf
ukinau$ ls
COPYING ChangeLog Makefile.am aclocal.m4 autom4te.cache configure configure.ac src
configureというファイルが生成された
autoconfとは
configure.acを元にconfigureを生成するソフトウェア
configure.acは、autoscanでsrc配下のCプログラムから自動生成することもできますが、今回のdashのケースでは、すでに定義済みのconfigure.acが用意されてますのでそれを元にしています。
3. autoheader
ukinau$ autoheader
ukinau$ ls
COPYING Makefile.am config.h.in configure.ac src
ChangeLog autom4te.cache configure
config.h.inというファイルが生成された
autoheaderとは
http://markuskimius.wikidot.com/programming:tut:autotools:3
https://www.gnu.org/software/autoconf/manual/autoconf-2.66/html_node/autoheader-Invocation.html
autoheaderは、configure.acを元にconfig.h.inというファイルを生成する
config.h.inは、config.hの元になるファイルである。
環境情報を元に定数の値を操作するような定義ファイルがconfig.h.inであり、configureによってconfig.hになる。
config.hが必要なモチベーションは、ここのサイトが非常にわかりやすい
4. automake
ukinau$ automake --add-missing
configure.ac:8: installing './compile'
configure.ac:2: installing './install-sh'
configure.ac:2: installing './missing'
src/Makefile.am:21: warning: source file 'bltin/printf.c' is in a subdirectory,
src/Makefile.am:21: 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.
src/Makefile.am:21: warning: source file 'bltin/test.c' is in a subdirectory,
src/Makefile.am:21: but option 'subdir-objects' is disabled
src/Makefile.am:21: warning: source file 'bltin/times.c' is in a subdirectory,
src/Makefile.am:21: but option 'subdir-objects' is disabled
src/Makefile.am: installing './depcomp'
ukinau$ ls
COPYING Makefile.am aclocal.m4 compile configure depcomp missing
ChangeLog Makefile.in autom4te.cache config.h.in configure.ac install-sh src
compile, depcomp, missing, install-sh, Makefile.inが生成された
しかし、compile, depcomp, missing, install-shはautomakeパッケージに含まれるシェルスクリプトのシンボリックリンクである。これらは --add-missing をつけることで生成される
ukinau$ ls -l | grep -e depcomp -e install-sh -e missing -e compile
lrwxr-xr-x 1 ukinau staff 61 3 Dec 20:42 compile -> /usr/local/Cellar/automake/1.15.1/share/automake-1.15/compile
lrwxr-xr-x 1 ukinau staff 61 3 Dec 20:42 depcomp -> /usr/local/Cellar/automake/1.15.1/share/automake-1.15/depcomp
lrwxr-xr-x 1 ukinau staff 64 3 Dec 20:42 install-sh -> /usr/local/Cellar/automake/1.15.1/share/automake-1.15/install-sh
lrwxr-xr-x 1 ukinau staff 61 3 Dec 20:42 missing -> /usr/local/Cellar/automake/1.15.1/share/automake-1.15/missing
Makefile.inはMakefileの元になるファイルである
5. configure
configureは、「config.h.in, Makefile.in」を 「config.h, Makefile」に変換してくれる
ukinau$ ./configure
ukinau$ ls
COPYING Makefile.am autom4te.cache config.h.in configure install-sh stamp-h1
ChangeLog Makefile.in compile config.log configure.ac missing
Makefile aclocal.m4 config.h config.status depcomp src
内部では、config.statusを生成後、config.statusを実行することで「config.h, Makefile」を生成している
6. make
ukinau$ make
ukinau$ ls -l src | grep -e '^...x'
drwxr-xr-x 6 ukinau staff 204 23 Sep 2016 bltin
-rwxr-xr-x 1 ukinau staff 141588 3 Dec 21:05 dash
-rwxr-xr-x 1 ukinau staff 15864 3 Dec 21:05 mkinit
drwxr-xr-x 3 ukinau staff 102 3 Dec 21:05 mkinit.dSYM
-rwxr-xr-x 1 ukinau staff 14192 3 Dec 21:05 mknodes
drwxr-xr-x 3 ukinau staff 102 3 Dec 21:05 mknodes.dSYM
-rwxr-xr-x 1 ukinau staff 9444 3 Dec 21:05 mksignames
drwxr-xr-x 3 ukinau staff 102 3 Dec 21:05 mksignames.dSYM
-rwxr-xr-x 1 ukinau staff 13680 3 Dec 21:05 mksyntax
drwxr-xr-x 3 ukinau staff 102 3 Dec 21:05 mksyntax.dSYM
実行可能ファイルがいくつかsrcディレクトリ配下に作成されていることがわかります。
buildしたdashをloginシェルにしてみる
ログインshellに指定するために、/etc/shells にdash実行ファイルを追加
ukinau$ echo /Users/ukinau/dash-0.5.9.1/src/dash >> /etc/shells
これをしないとnon-standard shellと言われて変更できません
ukinau$ sudo chsh -s /Users/ukinau/dash-0.5.9.1/src/dash ukinau
ukinau$ su ukinau
$
とビルドしたdashがログインシェルに設定できるとこまで確認しました
ここまでできたので、もし拡張したりしたらビルドし直すことによって自分だけのshellが作れそうです。
まぁそんなことはしないのですが。遊びでもできることが大事です。
考察
なんだか薄っぺらい情報しか載せていませんが、なんとなくどういうプロセスでインストールされるのかわかった気がするので、ちょっと整理します。
configure.acとMakefile.amが大元になっており、ゴールは、Makefileを作ること。
configure.acには、どのような条件でどのような定数を指定するかみたいな定義が羅列されておりマクロが大量に使われている。
マクロは、automakeパッケージに含まれているものも使われている。しかし、前述のようにデフォルトで使えないマクロもあるので、aclocalを使って、それらのマクロ定義ファイルのマクロをaclocal.m4にコピーすることで、autoconfで使えるようになる。
上述で作ったaclocal.m4のマクロを利用して、autoconfでconfigureスクリプトを生成する。
configureスクリプトは、.inのファイルからというファイルを生成する。環境(XXがインストールされているかなど)に応じた変数の置換がベースである。
autoheaderは、config.hの元になるconfig.inを生成するconfig.hは、プリプロセッサに処理されるの定数の定義ファイルである(モチベーションについてはここをみると良い)。
もちろん環境に応じて、それらの定数の値を変更したいので、configureを利用してconfig.hを生成したい。config.h.inは、configure.acでAC_DEFINE.*マクロで定義されている置換ルールが抜粋されて作られている。で最後に、automakeを利用してMakefile.inを生成する。
ここで、configure.inとMakefile.inが揃ったので、configureスクリプトで変数置換を実施して、Makefileを作る。
こうすることで、私の環境に適応したMakefileとconfig.hができて、プログラムのビルドができるようになった。
あまり深く追いすぎてもアレなので、autotoolsはどんな目的でざっくりどんなプロセスを踏むのかを見ていきました。次の投稿から実際にソースコードを読み進めたいと思います。
参考にしたサイト
記事中に基本的には書いてありますが特に参考になるなーと思ったものを下記に記しておきます。(もちろん全部参考になりました、ありがとうございます)
- GNU開発ツール
- config.hのモチベーションChapter 3: Let's make "Hello, world!" portable
- Autotoolsの全体像Autotoolsについてのメモ
- Configure.acの文法についてautoconfで「configure」をつくろう
- Autotoolsの詳細についてautotools.pdf
- Autotoolsの簡単な使い方