その3 からの続き
5.34. Stripping
ここは省略しても言いようだが、ハードディスク節約のためにはやったほうがいいらしい。
デバッグシンボルを取り除く
$ strip -- strip - debug / tools / lib / *
$ strip -- strip - unneeded / tools / { , s } bin / *
ドキュメントを削除
$ rm - rf / tools / { , share } / { info , man , doc }
5.35. Changing Ownership
ここからはrootでやる。$LFSに値が設定されているか確認すること。
$ exit
$ sudo su -
# echo $LFS
# export LFS=/mnt/lfs
# echo $LFS
# chown -R root:root $LFS/tools
ここでバックアップを取っておくといいらしい。一応VMWareのハードディスクごとコピーしておいた。バックアップを取るならtarしたソースやmakeしたオブジェクトは要らないと思うが、それは作業ディレクトリにあるという想定なのだろうか、いずれにしてもvmwareなので小さくするのは面倒なのでスルー。
Part III. Building the LFS System
ここから本格的なLFSシステムの構築が始まる。chrootでミニリナックスに入り、パッケージのインストールを行う。
6.2. Preparing Virtual Kernel File Systems
ある種のファイルはカーネル自身が通信するために使う。これらは実際のファイルではなくメモリ上に存在する。それらを作成する。
# echo $LFS
# export LFS=/mnt/lfs
# echo $LFS
# mkdir -v $LFS/{dev,proc,sys}
mkdir : created directory ` / mnt / lfs / dev '
mkdir : created directory ` / mnt / lfs / proc '
mkdir : created directory ` / mnt / lfs / sys '
6.2.1. Creating Initial Device Nodes
カーネルがブートするときいくつかのデバイスノードを必要とする。consoleやnullデバイス。udevdが始まる前にこれらは存在しないとならない。
# mknod -m 600 $LFS/dev/console c 5 1
# mknod -m 666 $LFS/dev/null c 1 3
c はキャラクターデバイスをあらわす。キャラクターデバイスとはシークできないもの。キーボードや乱数がある。その後の番号はそのデバイスの種類を決めたものでカーネル作成者が決めている。詳しくは/usr/src/linux/Documentation/devices.txtにある。
–bindを使ってホストの/devを再マウントする。
# mount -v --bind /dev $LFS/dev
/ dev on / mnt / lfs / dev type none ( rw , bind )
# mount -vt devpts devpts $LFS/dev/pts
devpts on / mnt / lfs / dev / pts type devpts ( rw )
# mount -vt tmpfs shm $LFS/dev/shm
shm on / run / shm type tmpfs ( rw )
# mount -vt proc proc $LFS/proc
proc on / mnt / lfs / proc type proc ( rw )
# mount -vt sysfs sysfs $LFS/sys
sysfs on / mnt / lfs / sys type sysfs ( rw )
#
6.4. Entering the Chroot Environment
# chroot "$LFS" /tools/bin/env -i \
> HOME = / root TERM = "$TERM" PS1 = '\u:\w\$ ' \
> PATH = / bin : / usr / bin : / sbin : / usr / sbin : / tools / bin \
> / tools / bin / bash -- login + h
I have no name ! : / #
これで$LFSがルートディレクトリになった。これからは$LFSは必要ない。
I have no name!と表示されるのは/etc/passwdがないからだそうだ。
ここから先はすべてここでの環境になる。ホストをリブートしたりしたときはまた、/devなどを作り直さないとならない。
標準的なディレクトリをつくる。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# mkdir -pv /{bin,boot,etc/{opt,sysconfig},home,lib,mnt,opt,run}
# mkdir -pv /{media/{floppy,cdrom},sbin,srv,var}
# install -dv -m 0750 /root
# install -dv -m 1777 /tmp /var/tmp
# mkdir -pv /usr/{,local/}{bin,include,lib,sbin,src}
# mkdir -pv /usr/{,local/}share/{doc,info,locale,man}
# mkdir -v /usr/{,local/}share/{misc,terminfo,zoneinfo}
# mkdir -pv /usr/{,local/}share/man/man{1..8}
# for dir in /usr /usr/local; do
# ln -sv share/{man,doc,info} $dir
# done
# case $(uname -m) in
# x86_64) ln -sv lib /lib64 && ln -sv lib /usr/lib64 ;;
# esac
# mkdir -v /var/{log,mail,spool}
# ln -sv /run /var/run
# ln -sv /run/lock /var/lock
# mkdir -pv /var/{opt,cache,lib/{misc,locate},local}
シンボリックリンクなどを作成
# ln -sv /tools/bin/{bash,cat,echo,pwd,stty} /bin
# ln -sv /tools/bin/perl /usr/bin
# ln -sv /tools/lib/libgcc_s.so{,.1} /usr/lib
# ln -sv /tools/lib/libstdc++.so{,.6} /usr/lib
# sed 's/tools/usr/' /tools/lib/libstdc++.la > /usr/lib/libstdc++.la
# ln -sv bash /bin/sh
パスワードファイルとグループファイルを作成
# cat > /etc/passwd << "EOF"
root : x : 0 : 0 : root : / root : / bin / bash
bin : x : 1 : 1 : bin : / dev / null : / bin / false
nobody : x : 99 : 99 : Unprivileged User : / dev / null : / bin / false
EOF
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# cat > /etc/group << "EOF"
root : x : 0 :
bin : x : 1 :
sys : x : 2 :
kmem : x : 3 :
tty : x : 4 :
tape : x : 5 :
daemon : x : 6 :
floppy : x : 7 :
disk : x : 8 :
lp : x : 9 :
dialout : x : 10 :
audio : x : 11 :
video : x : 12 :
utmp : x : 13 :
usb : x : 14 :
cdrom : x : 15 :
mail : x : 34 :
nogroup : x : 99 :
EOF
udevなどのためにいろいろなグループがあるらしい。
“I have no name!”を変える。Glibcはインストールされ、/etc/passwd, /etc/groupはできたのでできるはず。
# exec /tools/bin/bash --login +h
root : ~ #
login, agetty, initがログをとるようにファイルを作る。ファイルがないとログをとらないらしい。
# touch /var/run/utmp /var/log/{btmp,lastlog,wtmp}
# chgrp -v utmp /var/run/utmp /var/log/lastlog
# chmod -v 664 /var/run/utmp /var/log/lastlog
# chmod -v 600 /var/log/btmp
/var/run/utmpは現在ログインしているユーザの記録。/var/log/wtmpはすべてのログインログアウトの記録。/var/log/lastlogはユーザごとの最後のログインの記録。/var/log/btmpはbad loginの記録。
6.7. Linux-3.2.6 API Headers
# cd /sources/linux-3.2.6
# make mrproper
# make headers_check
# find dest/include \ ( - name . install - o - name .. install . cmd \ ) -delete
# cp -rv dest/include/* /usr/include
なんか/bin/shがないとか言われたのでシンボリックリンクをつくって再トライ。
# ln -sv /bin/bash /bin/sh
6.8. Man-pages-3.35
# cd /sources/
# tar xfvz man-pages-3.35.tar.gz
# cd man-pages-3.35
# make install
6.9. Glibc-2.14.1
現在のコンパイラのスペックは/toolsを指していて、これだとtestスクリプトが失敗する。コンパイラのスペックはGlibcができるまでは直せないので、このテストスクリプトをいじる。
# cd /sources/
# mv glibc-2.14.1 glibc-2.14.1.pass1
# tar xfvj glibc-2.14.1.tar.bz2
# cd glibc-2.14.1
# DL=$(readelf -l /bin/sh | sed -n 's@.*interpret.*/tools\ ( . * \ ) ]$@\1@p')
# echo $DL
# sed -i "s|libs -o|libs -L/usr/lib -Wl,-dynamic-linker=$DL -o|" scripts/test-installation.pl
# unset DL
# sed -i -e 's/"db1"/& \&\& $name ne "nss_test1"/' scripts/test-installation.pl
# sed -i 's|@BASH@|/bin/bash|' elf/ldd.bash.in
# patch -Np1 -i ../glibc-2.14.1-fixes-1.patch
# patch -Np1 -i ../glibc-2.14.1-sort-1.patch
# patch -Np1 -i ../glibc-2.14.1-gcc_fix-1.patch
# sed -i '195,213 s/PRIVATE_FUTEX/FUTEX_CLOCK_REALTIME/' \
nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_rwlock_timed { rd , wr } lock .S
# mv ../glibc-build/ ../glibc-build.pass1
# mkdir -v ../glibc-build
mkdir : created directory ` . . / glibc - build '
# cd ../glibc-build
# case `uname -m` in
i ? 86 ) echo "CFLAGS += -march=i486 -mtune=native -O3 -pipe" > configparms ; ;
esac
コンフィグする。こんどは/usrになる。
# ../glibc-2.14.1/configure --prefix=/usr \
> -- disable - profile -- enable - add - ons \
> -- enable - kernel = 2.6.25 -- libexecdir = / usr / lib / glibc
ここでのGlibのテストは重要。
いつくかのテストが失敗しないようにコピーをとってやる。
# cp -v ../glibc-2.14.1/iconvdata/gconv-modules iconvdata
# make -k check 2>&1 | tee glibc-check-log
# grep Error glibc-check-log
とくにエラーはないみたいなので先に進む。
# touch /etc/ld.so.conf
# make install
NISとRPC関連のヘッダをインストール
# cp -v ../glibc-2.14.1/sunrpc/rpc/*.h /usr/include/rpc
# cp -v ../glibc-2.14.1/sunrpc/rpcsvc/*.h /usr/include/rpcsvc
# cp -v ../glibc-2.14.1/nis/rpcsvc/*.h /usr/include/rpcsvc
最小限のロカールをインストール。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# mkdir -pv /usr/lib/locale
# localedef -i cs_CZ -f UTF-8 cs_CZ.UTF-8
# localedef -i de_DE -f ISO-8859-1 de_DE
# localedef -i de_DE@euro -f ISO-8859-15 de_DE@euro
# localedef -i de_DE -f UTF-8 de_DE.UTF-8
# localedef -i en_HK -f ISO-8859-1 en_HK
# localedef -i en_PH -f ISO-8859-1 en_PH
# localedef -i en_US -f ISO-8859-1 en_US
# localedef -i en_US -f UTF-8 en_US.UTF-8
# localedef -i es_MX -f ISO-8859-1 es_MX
# localedef -i fa_IR -f UTF-8 fa_IR
# localedef -i fr_FR -f ISO-8859-1 fr_FR
# localedef -i fr_FR@euro -f ISO-8859-15 fr_FR@euro
# localedef -i fr_FR -f UTF-8 fr_FR.UTF-8
# localedef -i it_IT -f ISO-8859-1 it_IT
# localedef -i ja_JP -f EUC-JP ja_JP
# localedef -i tr_TR -f UTF-8 tr_TR.UTF-8
# localedef -i zh_CN -f GB18030 zh_CN.GB18030
EUCJPになってるので全部のロカールをインストール
# make localedata/install-locales
Glibcのために/etc/nsswitch.confをつくる。
# cat > /etc/nsswitch.conf << "EOF"
# Begin /etc/nsswitch.conf
passwd : files
group : files
shadow : files
hosts : files dns
networks : files
protocols : files
services : files
ethers : files
rpc : files
# End
EOF
タイムゾーン設定
# cp -v --remove-destination /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
removed ` / etc / localtime '
` / usr / share / zoneinfo / Asia / Tokyo ' -> `/etc/localtime'
–remove-destinationをつけるのはシンボリックリンクだった場合に削除するため。
このファイルはシングルユーザモードのためにコピーしておくらしい
6.9.3. Configuring the Dynamic Loader
ダイナミックローダがライブラリを探すディレクトリの設定
cat > / etc / ld .so .conf << "EOF"
# Begin /etc/ld.so.conf
/ usr / local / lib
/ opt / lib
EOF
もっと探せるようにする。
# cat >> /etc/ld.so.conf << "EOF"
# Add an include directory
include / etc / ld .so .conf .d / * .conf
EOF
# mkdir /etc/ld.so.conf.d
6.10. Re-adjusting the Toolchain
Cライブラリがインストールされたので、ツールチェインの調整をする。これにより新しくコンパイルされるプログラムは、新しいライブラリを見るようになる。
前のをとっておく。
# mv -v /tools/bin/{ld,ld-old}
# mv -v /tools/$(gcc -dumpmachine)/bin/{ld,ld-old}
# mv -v /tools/bin/{ld-new,ld}
# ln -sv /tools/bin/ld /tools/$(gcc -dumpmachine)/bin/ld
gccのスペックファイルを編集して、あたらしいダイナミックリンカを指すようにする。
# gcc -dumpspecs | sed -e 's@/tools@@g' \
- e '/\*startfile_prefix_spec:/{n;s@.*@/usr/lib/ @}' \
- e '/\*cpp:/{n;s@$@ -isystem /usr/include@}' > \
` dirname $ ( gcc -- print - libgcc - file - name ) ` / specs
本当にできているか確認。
# echo 'main(){}' > dummy.c
# cc dummy.c -v -Wl,--verbose &> dummy.log
# readelf -l a.out | grep ': /lib'
このように表示されるはず。
[ Requesting program interpreter : / lib / ld - linux .so . 2 ]
このように表示されるはず。
# grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log
/ usr / lib / crt1 .o succeeded
/ usr / lib / crti .o succeeded
/ usr / lib / crtn .o succeeded
このように表示されるはず。
# grep -B1 '^ /usr/include' dummy.log
#include <...> search starts here:
/ usr / include
このように表示されるはず。
# grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
SEARCH_DIR ( "/tools/i686-pc-linux-gnu/lib" )
SEARCH_DIR ( "/usr/lib" )
SEARCH_DIR ( "/lib" ) ;
このように表示されるはず。
# grep "/lib.*/libc.so.6 " dummy.log
attempt to open / lib / libc .so . 6 succeeded
このように表示されるはず。
# grep found dummy.log
found ld - linux .so . 2 at / lib / ld - linux .so . 2
# rm -v dummy.c a.out dummy.log
続く