make world

更新したソースをコンパイル&インストールするために、 make world を行います。 その際、必要な周辺の事項もまとめておきます。

著者は、 3.4-RELEASE から 4.4-RELEASE へのアップグレード にチャレンジしてみましたが、make buildworld をやってすぐ引っかかって うまく行きませんでした。 どうもこれは、一般的に見られる症状のようです。 こんなときは、一度 4.1(.1)-RELEASE へアップグレードしてから 4.4-RELEASE へアップグレードすればいいようです。
3.4R -> 4.1(.1)R -> 4.4R

なお、詳細は取得した最新の src/Makefile か、 ハンドブックの 19.4. make world の利用 をご覧下さい。


UPDATING を読む

何はなくとも、まずは /usr/src/UPDATING を読みましょう。 どのような変更がなされてきたか、 それに伴いどのような変更をすべきか、 また Update の方法などが書いてあります。

/etc/make.conf の確認

/etc/make.conf や /etc/defaults/make.conf を見ます。 これは、コンパイルするときのオプションなどを記したファイルです。 通常、 CFLAGS や NOPROFILE のコメントを外すとよいでしょう。
/etc/make.conf

CFLAGS= -O -pipe
NOPROFILE= true

-O は最適化オプションでコンパイラはコンパイルの スピードアップを試みます。
-pipe はコンパイル時のステージ間のデータの受渡しに テンポラルファイルではなくパイプを利用します。 ファイルを作らない分速いですがメモリを使います。

/etc/group の確認

/etc/group と /usr/src/etc/group の違いをみて、 新しいバージョンで使う予定の group 名や GID を すでに使ってないかを確認します。
% diff /etc/group /usr/src/etc/group
としてみて、自分で作ったグループ名しかなければOKです。

/usr/obj の削除

以前に make world をして /usr/obj が残っている場合は、 これを削除します。変更不可フラグが立っているものがある可能性が ありますので、以下のようにして削除します。
# cd /usr/obj
# chflags -R noschg *
# rm -rf *

/usr の空き容量の確認

次に行う make buildworld では、/usr/obj に 320 MB 程度の ファイルを書き出しますので、 /usr (を含む)パーティションに 空き容量があるかどうかを確認します。 ちなみに、/usr/src は 320 MB 程度になります。 /usr パーティションに容量がなければ、余裕のあるパーティションに 作業領域を作って、/usr/obj にシンボリックリンクしておくとよいでしょ う。

make buildworld

ソースを再構築します。 script コマンドで出力メッセージを取りながら行うとよいでしょう。
# script /var/tmp/mw.out
Script started, output file is /var/tmp/mw.out
# cd /usr/src
# make buildworld
... compile ...
# exit
Script done, ...

ここで、make に -j4 などのオプションをつけることができます。 オプション -j4 は最大4個までのプロセスを同時に実行するというもので す。 シングル CPU では -j4 が一番良いという報告があったり、 やってはいけないという報告があったり。。。 複数の CPU を持つマシンの場合、-j6 から -j10 の間で試して見て下さい。

Pentium III/550MHz, RAM/384MB, dual CPU, make -j8 では FreeBSD 4.1.1R の構築に1時間かかりました。
Pentium III/500MHz, RAM/128MB では、FreeBSD-CURRENT の構築に 3時間半かかるそうです。

最後に、
===> etc
===> etc/sendmail
rm -f freebsd.cf
(cd /usr/src/etc/sendmail &&  m4 -D_CF_DIR_=/usr/src/etc/sendmail/../../contrib/sendmail/cf/ /usr/src/etc/sendmail/../../contrib/sendmail/cf/m4/cf.m4 freebsd.mc) > freebsd.cf
chmod 444 freebsd.cf
となっていれば、make buildworld は成功です。

トラブルシューティング (4.1(.1)→4.4)

4.1R (もしくは 4.1.1R)から 4.4R へのアップグレードの際には、
eelf_i386.o: In function `gldelf_i386_open_dynamic_archive':
eelf_i386.o(.text+0xc7b): undefined reference to `basename'
*** Error code 1
1 error
*** Error code 2
1 error 

というエラーを吐いてストップしてしまいます。 他の所でもそのようなエラーが出ているようです。 解決策は、次の通りです。

# cd /usr/src
# make includes
# cd /usr/src/lib/libc
# make basename.o
# ar r /usr/lib/libc.a /usr/obj/usr/src/lib/libc/basename.o
# cd /usr/obj
# chflags -R noschg *
# rm -rf *
# cd /usr/src
# make buildworld
手動で、basename をコンパイルして libc.a に付け加えてます。
basename.o は/usr/obj/usr/src/lib/libc/basename.o ではなく、 カレントディレクトリにある こともありました(謎)。

エラーの理由は libc のバージョンが良くないためだとかで、 上のとは別に、 /usr/src/gnu/usr.bin/binutils/libiberty/Makefile に パッチ(Makefile_libiberty.patch)を当てるという方法もあるようです
# cd /usr/src/gnu/usr.bin/binutils/libiberty
# patch < Makefile_libiberty.patch
# cd /usr/obj
# chflags -R noschg *
# rm -rf *
# cd /usr/src
# make buildworld
が、うちではうまく行きませんでした。

カーネルの構築&インストール

make installworld をする前に、カーネルの構築&インストールをします。 これは、make installworld をしてしまった後で 「カーネルが構築できない!」という事態を避けるためです。 また、通常のカーネル再構築の手順ではなく、make {buildkernel ,installkernel} を使わないといけないようです。

ここでは、まず GENERIC カーネルを作って、 動くのを確認してから改めてコンフィギュレーションする方法 を取ります。

3.x → 4.1 へのアップグレードの場合:
# cd /usr/src
# make buildkernel
# make installkernel
(この時点で、/GENERIC というカーネルができます)
# chflags noschg /kernel
# chflags noschg /GENERIC
# mv /kernel /kernel.old
# mv /GENERIC /kernel
# chflags schg /kernel
なお、4.1.1 へのアップグレードの場合は、make installkernel の段階で、 新しいカーネルが /kernel としてインストールされます。

4.x → 4.4 へのアップグレードの場合:
# cd /usr/src
# make buildkernel
# make installkernel
(この時点で、/kernel が新しいカーネルになってます)
/usr/src/sys/i386/conf の GENERIC ファイルを編集して HOGEHOGE という名前のファイルにしたとすると、これをコンパイル&インストールす るには、
# cd /usr/src
# make buildkernel KERNCONF=HOGEHOGE
# make installkernel KERNCONF=HOGEHOGE
とします。

いくつかのもののインストール(3.x→4.1のみ)

# cd /usr/src/sbin/mknod
# make install

/usr/src/UPDATING には
# cd /usr/src/sys/modules
# make install
もしろ、と書いてあったのですが、/modules の中身の日付けを見ると すでに入っているようなので、気にしないことにします。

/dev を作り直す(3.x→4.1のみ)

# cp /usr/src/etc/MAKEDEV /dev
# cd /dev
# ls -l | awk '{print $1,$2,$3,$4,$5,$6,$NF}' > /var/tmp/dev.out
# sh MAKEDEV all
# ls -l | awk '{print $1,$2,$3,$4,$5,$6,$NF}' > /var/tmp/dev2.out
3行目と5行目は、/dev のエントリーのリストを取っています。 変更の前後でリストが違わないか、チェックするのに使います。
# diff /var/tmp/dev.out /var/tmp/dev2.out

/etc/fstab を修正する

4.x では IDE ハードディスクのデバイス名が wd* から ad* に変更になり ました。これに伴い、/etc/fstab の wd を ad に変更します。 ただし、ウチでは 3.4 -> 4.1.1 のアップグレード時には問題 ありませんでしたが、 4.1.1 -> 4.4 のアップグレード時には 「root file system が見つからない」というエラーがでて ブートできませんでした。(下の項目の問題?)

ブートブロックとブートローダをアップグレード する(未試用)

# cd /sys/boot
# make install

シングルユーザモードに移る

# reboot
# fsck -p
# mount -u /
# mount -a
# cd /usr/src
# adjkerntz -i # if COMS is wall time
このあと、ブートするときにシングルユーザモードで起動するか、 マルチユーザモードで起動してしまった後
# shutdown now
....
Enter full pathname of shell or RETURN for [/bin/sh] : (リターン)
#
でシングルユーザモードに移行します。

トラブルシューティング

マルチユーザモードから shutdown now でいきなり シングルユーザモードに移行するとよろしくありません。 とりあえず一度新しいカーネルで起ち上げなくてはならないようです。

いくつかのもののインストール II(3.x→4.1のみ)

# cd /usr/src
# cd gnu/usr.bin/texinfo/install-info
# make install

make installworld

いよいよ、make buildworld で作ったバイナリをインストールします。
# cd /usr/src
# make installworld

トラブルシューティング(3.4→4.1)

CVSup でソースを新しくして、 3.4R から 4.1R へのアップグレードの際には、 この make installworld がうまく行きませんでした。 しょうがないので、ここまでの作業をした上で、 もう一度 make world したら、うまくいきました。
# cd /usr/src
# script /var/tmp/mw.out
# make world
... compile & install ...
# exit

トラブルシューティング(4.1→4.4)

4.1R から 4.4R へのアップグレードの際にも、 この make installworld がうまく行きませんでした。 こちらの方は、もう一度 make world したら良くなる、 というほどお気楽ではなくて、/usr/obj を削除してから make world すると、
# cd /usr/src
# make world
... compile ...
/usr/lib/crtbegin.o: In function `_init':
/usr/lib/crtbegin.o(.init+0x0): multiple definition of `_init'
/usr/lib/crti.o(.init+0x0): first defined here
/usr/lib/crtbegin.o: In function `_fini':
/usr/lib/crtbegin.o(.fini+0x0): multiple definition of `_fini'
/usr/lib/crti.o(.fini+0x0): first defined here
*** Error code 1
などというエラーを吐いてしまいました。 これは次のようにすれば解決しました。

# cd /usr/src/gnu/lib/csu
# ls
Makefile
# make
# make install
# cd /usr/obj
# chflags -R noschg *
# rm -rf *
# cd /usr/src
# make world

CVSup でソースを新しくしたのがダメらしいのですが、 詳しくはわかりません。

トラブルシューティング(4.1.1→4.4)

こんなエラーもありました。
... install ...
install -c -s -o root -g wheel -m 555 sh /bin
Could not execute shell
*** Error code 1
1 error
これは make -j4 installworld とやったのがいけなかったらしく、 make installworld とやればうまくいきました。

/etc の更新

ここまでの作業では /etc は更新されていません。 /usr/src/etc の下に、新しいバージョンの /etc の デフォルトファイル群が入っています。 これを /etc にマージするには、mergemaster というコマンドを使うのが 便利です。その前に、/etc のバックアップを取っておきましょう。
# cp -Rp /etc /etc.old
# mergemaster

mergemaster は、シェルスクリプトです。 起動すると、新しいファイルに変更点を見つけた場合や、 新しいファイルに対応するインストールされているファイルが ない場合には、それを処理するための4つの選択しを示します。

  1. 新しいファイルをそのままインストールする
  2. 新しいファイルは消す
  3. 新旧のファイルを sdiff を使って適切にマージする
  4. 後で手でマージするためにファイルを仮のルート環境に残しておく
デフォルトでは、仮のルートは /var/tmp/temproot になります。 始めて mergemaster を使うならば、-v オプションをつけるのがよいでしょ う。

mergemaster を終了したら、/var/tmp/temproot にいっぱいある 空ディレクトリを消しておきましょう。
# cd /var/tmp/temproot
# find -d . -type d | xargs rmdir 2 > /dev/null
# rm sys

トラブルシューティング

3.x では tcsh は /usr/local/bin/tcsh にありましたが、 4.x では /bin/tcsh に移りました。 /etc/passwd に SHELL が /usr/local/bin/tcsh となっている ユーザのログインシェルを、/bin/tcsh に変えておきましょう。
# cd /etc
# vipw

/stand の更新(オプション)

# cd /usr/src/release/sysinstall
# make all install

トラブルシューティング

4.4 にアップグレードしてから、/stand を更新しようと思ったら 何やらエラーがでてうまく行きませんでした。 あとで、od-driver を入れる時にパッチを当てたあとで /stand を更新したらうまく行きました。

CVSup でソースを新しくしたのがダメらしいのですが、 詳しくはわかりません。

qmail に関する処置

MTA に qmail を使っている場合、/usr/sbin/sendmail は qmail が用意する /var/qmail/bin/sendmail へのシンボリックリンク になっています(デフォルトでは)。 しかし、make world すると、/usr/sbin/sendmail は 本物の sendmail になってしまいますので、 再起動する前にシンボリックリンクを張り直します。
# chmod 0 /usr/sbin/sendmail
# mv /usr/sbin/sendmail /usr/sbin/sendmail.bak
# ln -s /var/qmail/bin/sendmail /usr/sbin/sendmail

再起動

# fastboot

カーネルコンフィギュレーション

必要ならば、カーネルのコンフィギュレーションを行います。 od-driver を使う場合には、もう一度インストール&カーネルコンフィギュ レーションをし直さなければならなくなるでしょう。

なお、以下のトラブルシューティングは、ソースファイルを CVSup で持って来たときに起こったことです。 正式 RELEASE 版のソースファイルを FTP で持って来た時には、 問題なくちゃんとカーネルの再構築ができました。

トラブルシューティング

make world したあとで、カーネルを通常の手続きで コンフィギュレーションしようと思ったら、 make depend ができませんでした。 HOGE をコンフィグレーションしたカーネルの名前とします。

3.4→4.1 では、make kernel でできました。
# cd /usr/obj
# chflags -R noschg *
# rm -rf *
# cd /usr/src
# make buildkernel KERNEL=HOGE
# make installkernel KERNEL=HOGE

4.1→4.4 では od-driver のパッチを当ててから make depend したので すが、
/usr/src/sys/cam/scsi/scsi_od.c:1782: sys/dkbad.h: No such file or directory
/usr/src/sys/cam/scsi/scsi_od.c:1791: machine/cons.h: No such file or directory
/usr/src/sys/cam/scsi/scsi_od.c:1795: vm/vm_prot.h: No such file or directory
mkdep: compile failed
*** Error code 1
というエラーが出て make depend できませんでした。 これは、/usr/src で make kernel しても同じ結果でした。

しょうがないので、/usr/src を一度全部消去して、 もう一度最新のソースに入れ換えたらできるようになりました。 その際、/usr/src/sys/i386/conf にある、 自前のカーネルコンフィギュレーションファイルを バックアップしておくとよいでしょう。

トラブルシューティング

NFS サーバを make world すると、 クライアント側で NFS に失敗していることがあります。 こんなときは慌てず騒がす、一度 umount してから 再度 nfs mount します。

参考ページ


FreeBSD の部屋


Dec. 3, 2001