Linux環境の作り方入門 vol.1 | 16.78MHz

Linux環境の作り方入門 vol.1

# 2010/11/12 追記: 一連の作業はrootで行う必要がある。そうしないとインストールされるソフトウェアに適切な所有者とパーミッションが設定されない恐れがある

ディストリビューションを使わずにソースパッケージから自力でLinux環境を構築するのは実はそれほど難しくない。面倒くさいけど。うちでは2004年頃からそうやって用途に応じてLinux環境を作ってるけど、今回PCルータのシステム刷新の為に構築する環境の構築手順を公開してみようと思う。
新しいLinux環境は構築に使うLinux環境のディレクトリツリーの一部にぶら下げる形で作るので、とりあえずまずディレクトリを作る
$ export SYSTEM_BUILD_DIR=/mnt/neo
$ mkdir -p ${SYSTEM_BUILD_DIR}

ソースパッケージによっては通常システムに必ず存在するディレクトリが存在しないとインストールに失敗するものが結構あるので、標準的なPOSIXディレクトリツリーを作っておく。
$ cd ${SYSTEM_BUILD_DIR}
$ mkdir -p ./{bin,boot/grub,dev,etc,home,lib/modules,mnt/{floppy,cdrom},opt,proc,root,sbin,sys,tmp,usr/{bin,include,lib,local,sbin,share/{man/man{1,2,3,4,5,6,7,8},info,doc},src},var/{lock,log,mail,run,spool,tmp,opt,cache,lib/misc,local}}

/usr/manと/usr/share/manで宗教戦争が始まらないようにシンボリックリンクを張っておく
$ cd ${SYSTEM_BUILD_DIR}/usr
$ ln -s share/man
$ ln -s share/info
$ ln -s share/doc

passwdとgroupを作っておく。uid/gidはお好みで
ユーザは最低限uid0のrootとなぜかPOSIXで要求されているbinがあれば良い。
$ cat <${SYSTEM_BUILD_DIR}/etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin::/bin/false
EOF
$ cat <${SYSTEM_BUILD_DIR}/etc/group
root:x:0:
bin:x:1:

boot:x:2:
mnt:x:3:
proc:x:4:
sbin:x:5:
sys:x:6:
share:x:7:
include:x:8:
local:x:9:
etc:x:10:
man:x:11:
doc:x:12:
info:x:13:
daemon:x:14:
staff:x:15:
log:x:16:
jre:x:17:
ssl:x:19:
kmem:x:40:
tty:x:41:
floppy:x:42:
cdrom:x:43:
tape:x:44:
disk:x:45:
lp:x:46:
dialout:x:47:
lan:x:48:
fbdev:x:49:
audio:x:50:
stunnel:x:51:
pppusers:x:52:
midi:x:53:
input:x:54:

nobody:x:65535:
EOF

続いて/dev以下のスペシャルファイルを作るが、手作業で作るのは面倒なのでLFSのMAKEDEVを使う
$ cd ${SYSTEM_BUILD_DIR}/dev/
$ wget http://www.linuxfromscratch.org/~manuel/MAKEDEV-1.7.bz2
$ bzip2 -d MAKEDEV-1.7.bz2
$ chmod 700 MAKEDEV-1.7
$ ./MAKEDEV-1.7

続いてカーネルヘッダをインストールする。
ついでだからここでカーネルコンフィグも済ませておく
カーネルの設定を後回しにしたい場合でも、.configが無いとカーネルヘッダのインストールは失敗するので、テキトーな設定をしておく。
$ cd ${SYSTEM_BUILD_DIR}/usr/src
$ wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.36.tar.bz2
$ tar xf linux-2.6.36.tar.bz2
$ ln -s linux-2.6.36 linux
$ cd linux
$ make menuconfig
$ INSTALL_HDR_PATH=${SYSTEM_BUILD_DIR}/usr make headers_install

ここから、chrootしてビルドを行うために最低限必要なソフトウェアをインストールしていくが、LFSで指摘されているように今からビルドするバイナリは構築に使うLinux環境のABI等を引き継いで意図しないバイナリになってしまう恐れがあるため、真面目にやるなら一度スタティックリンクされた一時的なビルド環境を構築して、そこから新しいシステムを構築してやる必要がある。が、実際のところx86 Linux環境ではABIもバイナリフォーマットももう何年も変わっていないので(ARMみたいに最近大きく変わったアーキテクチャだと真面目にやる必要があるかもしれないが)/usr以下にインストールされたgccを使って構築する場合一時的な環境は構築しなくても上手くいく。というわけで今回は一時的な環境は作らずにいきなり本環境を作る。まずはC言語標準ライブラリがないと話にならないので、glibcをインストールする。
$ cd ${SYSTEM_BUILD_DIR}/usr/src
$ wget http://ftp.yz.yamagata-u.ac.jp/pub/GNU/glibc/glibc-2.12.1.tar.xz
$ tar xf glibc-2.12.1.tar.xz
$ cd glibc-2.12.1
$ mkdir build
$ cd build

glibcはstack protector等一部の最適化フラグをつけてビルドすると正常に動作しないことが知られているため、ひかえめに最適化フラグを設定する。うちのPCルータはAtomプロセッサなのでAtom向けに最適化。ちなみにgccの最適化は-O0から-03までの4段階だが、-O3は一部のトリッキーなコードでは意図したとおりに動かないかもしれない最適化を含んでいるため、ソースパッケージが自分で-O3を付ける(つまり-O3でのテストが行われている)ソフトウェア以外は-O2までにとどめておくのが無難。
$ export CFLAGS="-O2 -march=atom -msse3 -mfpmath=sse -fforce-addr -fomit-frame-pointer -fstrength-reduce"
$ export CXXFLAGS="-O2 -march=atom -msse3 -mfpmath=sse -fforce-addr -fomit-frame-pointer -fstrength-reduce"
$ ../configure --enable-add-ons --enable-shared --with-fp --with-elf --disable-profile \
--enable-kernel=2.6.20 --with-headers=${SYSTEM_BUILD_DIR}/usr/include
$ make

glibcのインストールはインストール先に/etc/ld.so.confが無いと失敗するため、とりあえず空のファイルでごまかしておく。
$ touch ${SYSTEM_BUILD_DIR}/etc/ld.so.conf
$ make install_root=${SYSTEM_BUILD_DIR} install
$ make install_root=${SYSTEM_BUILD_DIR} localedata/install-locales

続いてncurses。ncursesは様々なターミナルの違いを吸収し、好きな位置に文字列を配置する仕組みを提供するライブラリ。シェルはこれを利用してターミナル上に標準出力を流しているので、これも要れておかないと色々始まらない。
$ cd ${SYSTEM_BUILD_DIR}/usr/src/
$ wget http://ftp.yz.yamagata-u.ac.jp/pub/GNU/ncurses/ncurses-5.7.tar.gz
$ tar xf ncurses-5.7.tar.gz
$ cd ncurses-5.7

ここからは本気の最適化でビルドしていくのでCFLAGSとCXXFLAGSを再設定。
$ export CFLAGS="-O2 -march=atom -msse3 -mfpmath=sse -fno-math-errno -ffast-math -fforce-addr -fomit-frame-pointer -pipe -fstrength-reduce -fno-strict-aliasing -fstack-protector"
$ export CXXFLAGS="-O2 -march=atom -msse3 -mfpmath=sse -fno-math-errno -ffast-math -fforce-addr -fomit-frame-pointer -pipe -fstrength-reduce -fno-strict-aliasing -fstack-protector"

ncursesにはマルチバイト文字に対応しているかどうかとスレッドに対応しているかどうかで4種類のバージョンが存在するので、全部インストールするためには4回ビルドする必要がある。ただ、シェル自体はマルチバイト対応もスレッド対応も要求しておらず、標準のものだけインストールされていればとりあえず動くので今はそれだけ入れる。
$ mkdir build1
$ cd build1
$ ../configure --prefix=/usr --with-install-prefix=${SYSTEM_BUILD_DIR} \
--with-shared --enable-termcap --enable-safe-sprintf --enable-colorfgbg \
--with-develop --enable-symlinks --without-debug --sysconfdir=/etc \
--localstatedir=/var --mandir=/usr/share/man --infodir=/usr/share/info \
--without-ada --with-manpage-symlinks
$ make
$ make install

(つづく!)