Help us understand the problem. What is going on with this article?

ノリでシェル(dash)のソースコードを読んでみた(1日目)〜sourceからインストール〜

More than 1 year has passed since last update.

なぜ?

僕には、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はどんな目的でざっくりどんなプロセスを踏むのかを見ていきました。次の投稿から実際にソースコードを読み進めたいと思います。

参考にしたサイト

記事中に基本的には書いてありますが特に参考になるなーと思ったものを下記に記しておきます。(もちろん全部参考になりました、ありがとうございます)

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした