その3からの続き
5.34. Stripping
ここは省略しても言いようだが、ハードディスク節約のためにはやったほうがいいらしい。
デバッグシンボルを取り除く
1 2 |
$ strip --strip-debug /tools/lib/* $ strip --strip-unneeded /tools/{,s}bin/* |
ドキュメントを削除
1 |
$ rm -rf /tools/{,share}/{info,man,doc} |
5.35. Changing Ownership
ここからはrootでやる。$LFSに値が設定されているか確認すること。
1 2 3 4 5 6 |
$ 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
ある種のファイルはカーネル自身が通信するために使う。これらは実際のファイルではなくメモリ上に存在する。それらを作成する。
1 2 3 4 5 6 7 |
# 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が始まる前にこれらは存在しないとならない。
1 2 |
# 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を再マウントする。
1 2 |
# mount -v --bind /dev $LFS/dev /dev on /mnt/lfs/dev type none (rw,bind) |
1 2 3 4 5 6 7 8 9 |
# 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
1 2 3 4 5 |
# 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} |
シンボリックリンクなどを作成
1 2 3 4 5 6 |
# 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 |
1 |
# touch /etc/mtab |
パスワードファイルとグループファイルを作成
1 2 3 4 5 |
# 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はできたのでできるはず。
1 2 |
# exec /tools/bin/bash --login +h root:~# |
login, agetty, initがログをとるようにファイルを作る。ファイルがないとログをとらないらしい。
1 2 3 4 |
# 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
1 2 3 4 5 |
# 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がないとか言われたのでシンボリックリンクをつくって再トライ。
1 |
# ln -sv /bin/bash /bin/sh |
6.8. Man-pages-3.35
1 2 3 4 |
# 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ができるまでは直せないので、このテストスクリプトをいじる。
1 2 3 4 5 6 7 8 |
# 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 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 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になる。
1 2 3 |
# ../glibc-2.14.1/configure --prefix=/usr \ > --disable-profile --enable-add-ons \ > --enable-kernel=2.6.25 --libexecdir=/usr/lib/glibc |
1 |
# make |
ここでのGlibのテストは重要。
いつくかのテストが失敗しないようにコピーをとってやる。
1 2 3 |
# cp -v ../glibc-2.14.1/iconvdata/gconv-modules iconvdata # make -k check 2>&1 | tee glibc-check-log # grep Error glibc-check-log |
とくにエラーはないみたいなので先に進む。
1 2 |
# touch /etc/ld.so.conf # make install |
NISとRPC関連のヘッダをインストール
1 2 3 |
# 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になってるので全部のロカールをインストール
1 |
# make localedata/install-locales |
Glibcのために/etc/nsswitch.confをつくる。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# 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 |
タイムゾーン設定
1 |
# tzselect |
1 2 3 |
# 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
ダイナミックローダがライブラリを探すディレクトリの設定
1 2 3 4 5 |
cat > /etc/ld.so.conf << "EOF" # Begin /etc/ld.so.conf /usr/local/lib /opt/lib EOF |
もっと探せるようにする。
1 2 3 4 |
# cat >> /etc/ld.so.conf << "EOF" # Add an include directory include /etc/ld.so.conf.d/*.conf EOF |
1 |
# mkdir /etc/ld.so.conf.d |
6.10. Re-adjusting the Toolchain
Cライブラリがインストールされたので、ツールチェインの調整をする。これにより新しくコンパイルされるプログラムは、新しいライブラリを見るようになる。
前のをとっておく。
1 2 3 4 |
# 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のスペックファイルを編集して、あたらしいダイナミックリンカを指すようにする。
1 2 3 4 |
# 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 |
本当にできているか確認。
1 2 3 |
# echo 'main(){}' > dummy.c # cc dummy.c -v -Wl,--verbose &> dummy.log # readelf -l a.out | grep ': /lib' |
このように表示されるはず。
1 |
[Requesting program interpreter: /lib/ld-linux.so.2] |
このように表示されるはず。
1 2 3 4 |
# grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log /usr/lib/crt1.o succeeded /usr/lib/crti.o succeeded /usr/lib/crtn.o succeeded |
このように表示されるはず。
1 2 3 |
# grep -B1 '^ /usr/include' dummy.log #include <...> search starts here: /usr/include |
このように表示されるはず。
1 2 3 4 |
# 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"); |
このように表示されるはず。
1 2 |
# grep "/lib.*/libc.so.6 " dummy.log attempt to open /lib/libc.so.6 succeeded |
このように表示されるはず。
1 2 |
# grep found dummy.log found ld-linux.so.2 at /lib/ld-linux.so.2 |
1 |
# rm -v dummy.c a.out dummy.log |