64bit Linux環境構築

64bit版 Linuxをスクラッチ構築して 32bit版 Linuxから移行する

ために 以下の手順を実行しました

  1. ターゲット環境の パーティションを設定する
  2. ターゲット環境に 64bitベース Linux環境をインストールする
  3. 32bit Linux上で動作する クロスコンパイラを構築する
  4. 32bit Linux上で 64bit版 Linuxカーネルをコンパイルする
  5. ターゲット環境に 64bitカーネルをコピーして環境を整える
  6. ターゲット環境で 64bit環境が起動することを確認
  7. インストール後のglibcの設定

2008年頃に試してみた Gentoo amd64 LiveCD版はインストーラに不具合があって
インストールが途中で停止するという苦い思い出があります

ただ 2011年となった今では 64bitディストリビューションも安定していて
わざわざ ゼロからコンパイルする必要はないかもしれません

今回は 32bitから64bit環境への本格移行が目的であるのと
スクラッチで OS環境を思い通りに構築したいという考えから
Linuxのスクラッチ構築を行い 手順をログとして残します

今回 検証した環境は次のとおり

検証環境
移行元32bit環境 移行先64bit環境
CPU Turion64 MT-37 (2GHz 1コア) PhenomII X4 905e (2.5GHz 4コア)
マザーボード K8N Neo Platinum GA-880GM-USB3
メモリ 1GB (DDR-400) 8GB (DDR3-1066)
HDD HDT722525DLAT80 (PATA 250GB) HDP725025GLA380 (SATA 250GB)
イーサネット nForce ethernet driver
(forcedeth GbE)
Realtek8111D
(R8168 GbE)
グラフィック nVidia GeForce6600GT Radeon HD 4250
オンボード
サウンド Sound Blaster Live! Audigy2
PCI
Realtek ALC892 codec (HD)
オンボード
Linuxカーネルバージョン 2.6.30.5 2.6.36.3

ターゲット環境の パーティションを設定する

ここでは ターゲットとなる 64bit構築予定のマシンで作業を行います
ハードディスクには 何も入ってない状態なので まず DVDからシステムを起動します

DVDは押入れをあさって出てきた Ubuntu-9.04 を使いました
メニューから 「端末」を立ち上げて

ubuntu@ubuntu:~$ uname -a
Linux ubuntu 2.6.28-11-generic #42-Ubuntu SMP Fri Apr 17 01:57:59 UTC 2009 i686 GNU/Linux
ubuntu@ubuntu:~$ sudo su
root@ubuntu:/home/ubuntu# fdisk /dev/sda

このディスクのシリンダ数は 484521 に設定されています。
間違いではないのですが、1024 を超えているため、以下の場合
に問題を生じうる事を確認しましょう:
1) ブート時に実行するソフトウェア (例. バージョンが古い LILO)
2) 別の OS のブートやパーティション作成ソフト
   (例. DOS FDISK, OS/2 FDISK)

コマンド (m でヘルプ): 

~
(省略)
~

コマンド (m でヘルプ): p

ディスク /dev/sda: 250.0 GB, 250059350016 バイト
ヘッド 16, セクタ 63, シリンダ 484521
Units = シリンダ数 of 1008 * 512 = 516096 バイト
Disk identifier: 0x90909090

デバイス ブート     始点        終点    ブロック   Id システム
/dev/sda1   *           1       20805    10485688+  a5  FreeBSD
/dev/sda2           20806      484521   233712864   83  Linux

コマンド (m でヘルプ): w
領域テーブルは交換されました!

ioctl() を呼び出して領域テーブルを再読込みします。
ディスクを同期させます。
root@ubuntu:/home/ubuntu#
 

250GBあるディスクのうち FreeBSD用に 10GB 割り当てました
残りの 240GBを Linux用に割り当てました

SWAPパーティションは作っていません
8GBもメモリを積んでいるので 不足することはない前提です

ちなみに FreeBSDには FreeBSD-8.1-release amd64 と grub2 をインストールしました

引き続いて 作成したばかりの /dev/sda2 を ext3 でフォーマットします

root@ubuntu:/home/ubuntu# mke2fs -j /dev/sda2
mke2fs 1.41.4 (27-Jan-2009)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
14614528 inodes, 58428216 blocks
2921410 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=0
1784 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks: 
	   32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
	   4096000, 7962624, 11239424, 20480000, 23887872

Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 22 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
root@ubuntu:/home/ubuntu#
 

ターゲット環境に 64bitベース Linux環境をインストールする

本当は インストールした FreeBSDから
Linuxパーティションに初期ファイルを転送するつもりでしたが
FreeBSDから ext3への書き込みの実績がなく
多少不安があったので このまま DVD Ubuntu上で作業を続けます

Gentoo Mirror-Site
インターネットから getntooのファイルシステムイメージを拾ってきます
Gentoo amd64 current-stage3
current-stage3 のディレクトリに 毎日のように更新されている
ファイルシステムイメージがありました

Gentoo とは Linuxディストリビュージョンの一種で有名です
初期構築手段として 上図にあるような stage3 という名前の tarボールが提供されています
中身は Linuxの最小限の環境で ls cp mv などの基本コマンドや ブートに必要な各種スクリプトが含まれます
X-Window や カーネル が含まれておらず カーネルは別途調達する必要があります

では この stage3 を先ほどフォーマットした /dev/sda2 に展開します

root@ubuntu:/home/ubuntu# mount -t ext3 /dev/sda2 /mnt
root@ubuntu:/home/ubuntu# cd /mnt
root@ubuntu:/mnt# tar -xjpf ~ubuntu/stage3-amd64-20110127.tar.bz2
root@ubuntu:/mnt# ls
bin   dev  home  lib32  lost+found  opt   root  sys  usr
boot  etc  lib   lib64  mnt         proc  sbin  tmp  var
root@ubuntu:/mnt# 
 

アーカイブを展開した状態では 起動する際にルートファイルシステムがマウントできません
/etc/fstab を編集します

#                                           

# NOTE: If your BOOT partition is ReiserFS, add the notail option to opts.
#/dev/BOOT              /boot           ext2            noauto,noatime  1 2
#/dev/ROOT              /               ext3            noatime         0 1
/dev/sda2               /               ext3            noatime         0 1
#/dev/SWAP              none            swap            sw              0 0
/dev/cdrom              /mnt/cdrom      auto            noauto,ro       0 0
#/dev/fd0               /mnt/floppy     auto            noauto          0 0

 

/dev/BOOT は別ファイルシステムをマウントする必要がないので コメントアウトします
/dev/ROOT が存在しないので代わりに 実際のファイルシステム /dev/sda2 を直接指定します
/dev/SWAP もコメントアウトします SWAPを使わない方針で進めてみます

また 初回は rootでログインする必要があるため
rootパスワードを 一旦無くします /etc/passwd を編集して

root::0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/false
daemon:x:2:2:daemon:/sbin:/bin/false
adm:x:3:4:adm:/var/adm:/bin/false
lp:x:4:7:lp:/var/spool/lpd:/bin/false
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/bin/false
news:x:9:13:news:/usr/lib/news:/bin/false
uucp:x:10:14:uucp:/var/spool/uucppublic:/bin/false
operator:x:11:0:operator:/root:/bin/bash
man:x:13:15:man:/usr/share/man:/bin/false
postmaster:x:14:12:postmaster:/var/spool/mail:/bin/false
portage:x:250:250:portage:/var/tmp/portage:/bin/false
nobody:x:65534:65534:nobody:/:/bin/false
sshd:x:22:22:added by portage for openssh:/var/empty:/sbin/nologin
 

1行目 root の隣にあった 「x」の文字を削除します これでパスワード無ログインができます

ベース環境の初期状況は 以上です
これで Linux環境としては最低限度の環境で rootアカウントでログインができるはずです

ただし 心臓となる カーネルがまだ入ってないので まだシステムは起動しません
以降の節は カーネルを構築する話となります

root@ubuntu:/mnt# cd -
root@ubuntu:/home/ubuntu# umount /mnt
root@ubuntu:/home/ubuntu# 
 

ターゲットのハードディスクをアンマウントしたら
しばらく 64bit側のシステムにはおやすみいただきます

32bit Linux上で動作する クロスコンパイラを構築する

ここからは 環境構築済の移行元 32bit Linux環境で作業をします
まず 32bit Linuxで 64bitコンパイルができる クロスコンパイル環境を構築します

コンパイル環境とは 以下の 3パッケージが適切にインストールされて利用できる状態を指します

パッケージ
binutils アセンブラである as や リンカである ld が含まれます
アセンブルソースを実行可能なマシン語バイナリに翻訳する機能です
glibc C標準ライブラリです libc.a libc.so が含まれます
C言語の標準仕様にある libm (数学ライブラリ) や
stdio.h などの標準ヘッダも含まれます
gcc コンパイラです gccコマンドが含まれます
C言語などのさまざまなソースコードをアセンブルソースに変換
binutils や glibc と連携して 実行バイナリを作ります

ここでは これら3つを 「32bit Linux上で動作し 64bit用のコードを吐く」ように構築します
現在の 32bit Linux環境でのコンパイル環境は下記のとおりです

32bit コンパイル環境
パッケージ インストールパス ビルドオプション
binutils-2.17 /usr/binutils/2.17/i686 –prefix=/usr/binutils/2.17/i686
–host=i686-linux-gnu
–target=i686-linux-gnu
–program-prefix=i686-linux-gnu-
glibc-2.5 /usr/glibc/2.5/i686 –prefix=/usr/glibc/2.5/i686
–program-prefix=i686-linux-gnu-
–build=i686-linux-gnu
–host=i686-linux-gnu
–with-headers=/usr/src/linux/include
gcc-4.1.2 /usr/gcc/4.1.2/i686 –prefix=/usr/gcc/4.1.2/i686
–program-prefix=i686-linux-gnu-
–host=i686-linux-gnu
–target=i686-linux-gnu
–build=i686-linux-gnu
–enable-threads=posix
–enable-nls
–with-libiconv-prefix=/usr/glibc/2.5/i686
–with-as=/usr/binutils/2.17/i686/bin/i686-linux-gnu-as
–with-ld=/usr/binutils/2.17/i686/bin/i686-linux-gnu-ld
–with-dwarf2
–with-arch=i686
–enable-languages=c,c++,fortran,java

一般の ディストリビューションLinuxとインストールパスが異なりますが
ネイティブコンパイラであれ クロスコンパイラであれ インストールディレクトリを別けておくと
バージョンアップや 新しいターゲット構築などに便利です

今回のクロス環境構築においても /usr/gcc/4.5.2/amd64 をインストールパスにするような方針です

最初に Linuxカーネルのソースを展開します
カーネルソースの ヘッダファイルが必要なためです

Ring Server Projectのページから 「ソフトウェアライブラリ」「各種Linuxディストリビューション」
「Linux Kernel」「kernel」「v2.6」「」
と最新のバージョンをたどって 最新のソースコードをダウンロードします

検証時点では 2.6.36.3 でした この linux-2.6.36.3.tar.bz2 をビルド用のディレクトリ展開します
検証環境では /usr/src/ 以下に展開することにしました

$ su
# chown admin /usr/src
# exit
$ cd /usr/src
$ tar -xjf ~admin/linux-2.6.36.3.tar.bz2
$ cd linux-2.6.36.3/include
$ ln -s ../arch/x86/include/asm asm
$ 
 

展開後に lnコマンドで asm というシンボリックリンクを作っています
これは ../arch/適切なアーキテクチャ/include/asm ディレクトリのシンボリックリンクとしています
これは C言語の話になりますが #include <linux/asm/〜.h> が
適切なアーキテクチャのヘッダを引っ張れるようにする準備です

以上が カーネルの準備でした 続いて早速 binutilsから構築します

$ cd
$ tar -xjf binutils-2.21.tar.bz2
$ mkdir binutils-2.21-amd64-build
$ cd binutils-2.21-amd64-build
$
$ VPATH=../binutils-2.21 ../binutils-2.21/configure --prefix=/usr/binutils/2.21/amd64 --host=i686-linux-gnu --target=amd64-linux-gnu --program-prefix=amd64-linux-gnu-
configure: WARNING: If you wanted to set the --build type, don't use --host.
    If a cross compiler is detected then cross compile mode will be used.
checking build system type... i686-pc-linux-gnu
checking host system type... i686-pc-linux-gnu
checking target system type... x86_64-pc-linux-gnu
checking for a BSD-compatible install... /bin/install -c
〜
checking whether to enable maintainer-specific portions of Makefiles... no
checking whether -fkeep-inline-functions is supported... yes
configure: creating ./config.status
config.status: creating Makefile
$
$ make
make[1]: Entering directory `/home/admin/binutils-2.21-amd64-build'
mkdir -p -- ./libiberty
Configuring in ./libiberty
configure: creating cache ./config.cache
checking whether to enable maintainer-specific portions of Makefiles... no
checking for makeinfo... makeinfo --split-size=5000000
〜
mv -f .deps/eelf_l1om.Tpo .deps/eelf_l1om.Po
/bin/sh ./libtool --tag=CC   --mode=link i686-linux-gnu-gcc -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow -Werror -g -O2   -o ld-new ldgram.o ldlex-wrapper.o lexsup.o ldlang.o mri.o ldctor.o ldmain.o ldwrite.o ldexp.o ldemul.o ldver.o ldmisc.o ldfile.o ldcref.o plugin.o eelf_x86_64.o eelf_i386.o ei386linux.o eelf_l1om.o  ../bfd/libbfd.la ../libiberty/libiberty.a  -lz -ldl
libtool: link: i686-linux-gnu-gcc -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow -Werror -g -O2 -o ld-new ldgram.o ldlex-wrapper.o lexsup.o ldlang.o mri.o ldctor.o ldmain.o ldwrite.o ldexp.o ldemul.o ldver.o ldmisc.o ldfile.o ldcref.o plugin.o eelf_x86_64.o eelf_i386.o ei386linux.o eelf_l1om.o  ../bfd/.libs/libbfd.a ../libiberty/libiberty.a -lz -ldl
make[4]: Leaving directory `/home/admin/binutils-2.21-amd64-build/ld'
make[3]: Leaving directory `/home/admin/binutils-2.21-amd64-build/ld'
make[2]: Leaving directory `/home/admin/binutils-2.21-amd64-build/ld'
make[1]: `all-target' に対して行うべき事はありません。
make[1]: Leaving directory `/home/admin/binutils-2.21-amd64-build'
$
$ su
# make install
make[1]: Entering directory `/home/admin/binutils-2.21-amd64-build'
/bin/sh ../binutils-2.21/mkinstalldirs /usr/binutils/2.21/amd64 /usr/binutils/2.21/amd64
mkdir -p -- /usr/binutils/2.21/amd64 /usr/binutils/2.21/amd64
〜
make[3]: `install' に対して行うべき事はありません。
make[3]: Leaving directory `/home/admin/binutils-2.21-amd64-build/libiberty/testsuite'
make[2]: Leaving directory `/home/admin/binutils-2.21-amd64-build/libiberty'
make[1]: `install-target' に対して行うべき事はありません。
make[1]: Leaving directory `/home/admin/binutils-2.21-amd64-build'
#
# exit
$ ls /usr/binutils/2.21/amd64/bin/
amd64-linux-gnu-addr2line  amd64-linux-gnu-ld       amd64-linux-gnu-readelf
amd64-linux-gnu-ar         amd64-linux-gnu-ld.bfd   amd64-linux-gnu-size
amd64-linux-gnu-as         amd64-linux-gnu-nm       amd64-linux-gnu-strings
amd64-linux-gnu-c++filt    amd64-linux-gnu-objcopy  amd64-linux-gnu-strip
amd64-linux-gnu-elfedit    amd64-linux-gnu-objdump
amd64-linux-gnu-gprof      amd64-linux-gnu-ranlib
$
 

特にエラーや警告なく 64bitアセンブラがインストールできました
–program-prefix に amd64-linux-gnu- を指定したのでバイナリツール名の接頭子となっています
今後このアセンブラを活用していくことになります 続けて glibc と gcc をビルドしていきます

ただし glibc と gcc は互いに依存しあっているパッケージのため
両方を交互に構築進める形となり 結果複雑な手順となります

まずは glibc から gccがまだないのでヘッダファイル(.h)のみを作ります

最近の glibcは glibc-libidn (IDN(国際化ドメイン名)ライブラリ) を必須としています
glibcの配布場所と同じところに glibc-libidnパッケージが配布されていますのでこれも持ってきます

$ tar -xjf glibc-2.9.tar.bz2
$ cd glibc-2.9
$ tar -xjf ../glibc-libidn-2.9.tar.bz2
$ mv glibc-libidn-2.9 libidn
$ cd ..
$
$ mkdir glibc-2.9-amd64-build
$ cd glibc-2.9-amd64-build
$
$ VPATH=../glibc-2.9 AR=/usr/binutils/2.21/amd64/bin/amd64-linux-gnu-ar RANLIB=/usr/binutils/2.21/amd64/bin/amd64-linux-gnu-ranlib ../glibc-2.9/configure --prefix=/usr/glibc/2.9/amd64  --host=amd64-linux-gnu --enable-add-ons=nptl,libidn --with-tls --program-prefix=amd64-linux-gnu- --enable-stackguard-randomization --with-headers=/usr/src/linux-2.6.36.3-amd64/include --with-binutils=/usr/binutils/2.21/amd64/bin --enable-shared
configure: WARNING: If you wanted to set the --build type, don't use --host.
    If a cross compiler is detected then cross compile mode will be used.
checking build system type... i686-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
〜
configure: creating ./config.status
config.status: creating config.make
config.status: creating Makefile
config.status: creating config.h
config.status: executing default commands
$
 

configure時 –enable-shared を指定していますが これは不要かもしれません

make install-headers とコマンドを打ちます
また ヘッダファイルのインストールまで行ってくれるので root権限で実施します

$ su
# make install-headers
make -r PARALLELMFLAGS="" CVSOPTS="" -C ../glibc-2.9 objdir=`pwd` install-headers
make[1]: Entering directory `/home/admin/glibc-2.9'
〜
nptl/sysdeps/x86_64/tls.h:69:3: error: #error "TLS support is required."
make[1]: *** [/home/admin/glibc-2.9-amd64-build/Versions.v.i] エラー 1
make[1]: Leaving directory `/home/admin/glibc-2.9'
make: *** [install-headers] エラー 2
#
 

ついに というかやっぱりエラーが出てきました
「gccに TLSの機能が必須だよ」という意味だろうと思います

TLS(Thread Local Storage)は Wikipedia あたりが詳しいですが 「ふーん」という感じで読み飛ばして
今回のクロスコンパイラの機能とあまり関係なさそうなことが分かったので

# vi ../glibc-2.9/config.h.in
 

コンパイル環境を 下記のように書き換えて回避しました

126 /* Define if _rtld_local structure should be forced into .sdata section.  */
127 #undef  HAVE_SDATA_SECTION
128
129 /* Define if binutils support TLS handling.  */
130 #undef  HAVE_TLS_SUPPORT
          ------> ここを修正
    #define  HAVE_TLS_SUPPORT
131
132 /* Define if the compiler's exception support is based on libunwind.  */
133 #undef  HAVE_CC_WITH_LIBUNWIND
 

少し強引な方法ですが HAVE_TLS_SUPPORT 定数を有効化しました
(後でより大きなトラブルにならないことを祈って) さらにビルドを続けます

# make install-headers
make -r PARALLELMFLAGS="" CVSOPTS="" -C ../glibc-2.9 objdir=`pwd` install-headers
make[1]: Entering directory `/home/admin/glibc-2.9'
〜
/bin/install -c -m 644 link.h /usr/glibc/2.9/amd64/include/link.h
/bin/install -c -m 644 ../sysdeps/x86_64/bits/link.h /usr/glibc/2.9/amd64/include/bits/link.h
make[2]: Leaving directory `/home/admin/glibc-2.9/elf'
make[1]: Leaving directory `/home/admin/glibc-2.9'
#
# ls -R /usr/glibc/2.9/amd64/
/usr/glibc/2.9/amd64/:
include

/usr/glibc/2.9/amd64/include:
_G_config.h  errno.h         langinfo.h  netipx      sched.h      termio.h
a.out.h      error.h         lastlog.h   netiucv     scsi         termios.h
aio.h        execinfo.h      libgen.h    netpacket   search.h     tgmath.h
aliases.h    fcntl.h         libintl.h   netrom      semaphore.h  thread_db.h
alloca.h     features.h      libio.h     netrose     setjmp.h     time.h
ar.h         fenv.h          limits.h    nfs         sgtty.h      ttyent.h
argp.h       fmtmsg.h        link.h      nl_types.h  shadow.h     ucontext.h
argz.h       fnmatch.h       locale.h    nss.h       signal.h     ulimit.h
arpa         fpu_control.h   malloc.h    obstack.h   spawn.h      unistd.h
assert.h     fstab.h         math.h      paths.h     stab.h       ustat.h
bits         fts.h           mcheck.h    poll.h      stdint.h     utime.h
byteswap.h   ftw.h           memory.h    printf.h    stdio.h      utmp.h
complex.h    gconv.h         mntent.h    protocols   stdio_ext.h  utmpx.h
cpio.h       getopt.h        monetary.h  pthread.h   stdlib.h     values.h
crypt.h      glob.h          mqueue.h    pty.h       string.h     wait.h
ctype.h      gnu             net         pwd.h       strings.h    wchar.h
dirent.h     gnu-versions.h  netash      re_comp.h   stropts.h    wctype.h
dlfcn.h      grp.h           netatalk    regex.h     sys          wordexp.h
elf.h        iconv.h         netax25     regexp.h    syscall.h    xlocale.h
endian.h     ieee754.h       netdb.h     resolv.h    sysexits.h
envz.h       ifaddrs.h       neteconet   rpc         syslog.h
err.h        inttypes.h      netinet     rpcsvc      tar.h

/usr/glibc/2.9/amd64/include/arpa:
ftp.h  inet.h  nameser.h  nameser_compat.h  telnet.h  tftp.h

/usr/glibc/2.9/amd64/include/bits:
a.out.h         initspin.h       poll.h          sockaddr.h     syslog.h
byteswap.h      ioctl-types.h    posix1_lim.h    socket.h       termios.h
cmathcalls.h    ioctls.h         posix2_lim.h    socket2.h      time.h
confname.h      ipc.h            posix_opt.h     stab.def       types.h
dirent.h        ipctypes.h       printf-ldbl.h   stat.h         typesizes.h
dlfcn.h         libc-lock.h      pthreadtypes.h  statfs.h       uio.h
elfclass.h      libio-ldbl.h     resource.h      statvfs.h      unistd.h
endian.h        link.h           sched.h         stdio-ldbl.h   ustat.h
environments.h  local_lim.h      select.h        stdio-lock.h   utmp.h
errno.h         locale.h         sem.h           stdio.h        utmpx.h
error.h         mathcalls.h      semaphore.h     stdio2.h       utsname.h
fcntl.h         mathdef.h        setjmp.h        stdlib-ldbl.h  waitflags.h
fcntl2.h        mathinline.h     shm.h           stdlib.h       waitstatus.h
fenv.h          mman.h           sigaction.h     string.h       wchar-ldbl.h
fenvinline.h    monetary-ldbl.h  sigcontext.h    string2.h      wchar.h
huge_val.h      mqueue.h         siginfo.h       string3.h      wchar2.h
huge_valf.h     mqueue2.h        signum.h        stropts.h      wordsize.h
huge_vall.h     msq.h            sigset.h        sys_errlist.h  xopen_lim.h
in.h            nan.h            sigstack.h      syslog-ldbl.h  xtitypes.h
inf.h           netdb.h          sigthread.h     syslog-path.h

/usr/glibc/2.9/amd64/include/gnu:
lib-names.h  libc-version.h

/usr/glibc/2.9/amd64/include/net:
ethernet.h  if_arp.h     if_ppp.h     if_slip.h   ppp_defs.h
if.h        if_packet.h  if_shaper.h  ppp-comp.h  route.h

/usr/glibc/2.9/amd64/include/netash:
ash.h

/usr/glibc/2.9/amd64/include/netatalk:
at.h

/usr/glibc/2.9/amd64/include/netax25:
ax25.h

/usr/glibc/2.9/amd64/include/neteconet:
ec.h

/usr/glibc/2.9/amd64/include/netinet:
ether.h  if_ether.h  if_tr.h  in.h        ip.h   ip_icmp.h  udp.h
icmp6.h  if_fddi.h   igmp.h   in_systm.h  ip6.h  tcp.h

/usr/glibc/2.9/amd64/include/netipx:
ipx.h

/usr/glibc/2.9/amd64/include/netiucv:
iucv.h

/usr/glibc/2.9/amd64/include/netpacket:
packet.h

/usr/glibc/2.9/amd64/include/netrom:
netrom.h

/usr/glibc/2.9/amd64/include/netrose:
rose.h

/usr/glibc/2.9/amd64/include/nfs:
nfs.h

/usr/glibc/2.9/amd64/include/protocols:
routed.h  rwhod.h  talkd.h  timed.h

/usr/glibc/2.9/amd64/include/rpc:
auth.h       clnt.h       netdb.h      pmap_rmt.h  rpc_msg.h   types.h
auth_des.h   des_crypt.h  pmap_clnt.h  rpc.h       svc.h       xdr.h
auth_unix.h  key_prot.h   pmap_prot.h  rpc_des.h   svc_auth.h

/usr/glibc/2.9/amd64/include/rpcsvc:
bootparam.h       nfs_prot.x      nis_object.x  rquota.x    yp.h        ypupd.h
bootparam_prot.x  nis.h           nis_tags.h    rstat.x     yp.x
key_prot.x        nis.x           nislib.h      rusers.x    yp_prot.h
klm_prot.x        nis_callback.h  nlm_prot.x    sm_inter.x  ypclnt.h
mount.x           nis_callback.x  rex.x         spray.x     yppasswd.x

/usr/glibc/2.9/amd64/include/scsi:
scsi.h  scsi_ioctl.h  sg.h

/usr/glibc/2.9/amd64/include/sys:
acct.h      io.h           poll.h      shm.h        syslog.h       un.h
bitypes.h   ioctl.h        prctl.h     signal.h     sysmacros.h    unistd.h
cdefs.h     ipc.h          procfs.h    signalfd.h   termios.h      user.h
debugreg.h  kd.h           profil.h    socket.h     time.h         ustat.h
dir.h       kdaemon.h      ptrace.h    socketvar.h  timeb.h        utsname.h
epoll.h     klog.h         queue.h     soundcard.h  timerfd.h      vfs.h
errno.h     mman.h         quota.h     stat.h       times.h        vlimit.h
eventfd.h   mount.h        raw.h       statfs.h     timex.h        vt.h
fcntl.h     msg.h          reboot.h    statvfs.h    ttychars.h     vtimes.h
file.h      mtio.h         reg.h       stropts.h    ttydefaults.h  wait.h
fsuid.h     param.h        resource.h  swap.h       types.h        xattr.h
gmon.h      pci.h          select.h    syscall.h    ucontext.h
gmon_out.h  perm.h         sem.h       sysctl.h     uio.h
inotify.h   personality.h  sendfile.h  sysinfo.h    ultrasound.h
#
 

実際にファイルを眺めてみても 〜.h のヘッダファイルのみがインストールされた状態です

ヘッダファイルに不足があるので さらに下記の作業を行います

# cp bits/stdio_lim.h /usr/glibc/2.9/amd64/include/bits/
# touch /usr/glibc/2.9/amd64/include/gnu/stubs.h
# touch /usr/glibc/2.9/amd64/include/gnu/stubs-64.h
# exit
$ cd ..
$
 

上記を実施しないと後続作業の #include <〜> でエラーが出て失敗します

ここまでで一応ヘッダファイルまでは出来たので ようやく gccの足がかりとなります
ただし glibcのメインである libc や 標準ライブラリがまだ存在しないので
現段階では gccも完全に構築できません

ところで 最近の gccは 数学ライブラリである gmp や mpfr に依存しています
gcc-4.5.2 が必要とするバージョンの gmp と mpfr を導入しておきます

$ tar -xjf gmp-5.0.1.tar.bz2
$ cd gmp-5.0.1
$ ./configure --prefix=/usr/local
checking build system type... athlon64-pc-linux-gnu
checking host system type... athlon64-pc-linux-gnu
checking for a BSD-compatible install... /bin/install -c
〜
config.status: linking mpn/generic/zero.c to mpn/zero.c
config.status: linking mpn/x86/umul.asm to mpn/umul.asm
config.status: linking mpn/x86/udiv.asm to mpn/udiv.asm
config.status: linking mpn/x86/invert_limb.asm to mpn/invert_limb.asm
config.status: linking mpn/x86/k7/gmp-mparam.h to gmp-mparam.h
config.status: executing libtool commands
$
$ make
gcc -std=gnu99 `test -f 'gen-fac_ui.c' || echo './'`gen-fac_ui.c -o gen-fac_ui
./gen-fac_ui 32 0 >mpz/fac_ui.h || (rm -f mpz/fac_ui.h; exit 1)
gcc -std=gnu99 `test -f 'gen-fib.c' || echo './'`gen-fib.c -o gen-fib
./gen-fib header 32 0 >fib_table.h || (rm -f fib_table.h; exit 1)
./gen-fib table 32 0 >mpn/fib_table.c || (rm -f mpn/fib_table.c; exit 1)
gcc -std=gnu99 `test -f 'gen-bases.c' || echo './'`gen-bases.c -o gen-bases -lm
./gen-bases header 32 0 >mp_bases.h || (rm -f mp_bases.h; exit 1)
〜
libtool: link: ranlib .libs/libgmp.a
libtool: link: rm -fr .libs/libgmp.lax
libtool: link: ( cd ".libs" && rm -f "libgmp.la" && ln -s "../libgmp.la" "libgmp.la" )
make[2]: Leaving directory `/home/admin/gmp-5.0.1'
make[1]: Leaving directory `/home/admin/gmp-5.0.1'
$
$ make check
make  check-recursive
make[1]: Entering directory `/home/admin/gmp-5.0.1'
Making check in tests
make[2]: Entering directory `/home/admin/gmp-5.0.1/tests'
Making check in .
make[3]: Entering directory `/home/admin/gmp-5.0.1/tests'
make  libtests.la t-bswap t-constants t-count_zeros t-gmpmax t-hightomask t-modlinv t-popc t-parity t-sub
make[4]: Entering directory `/home/admin/gmp-5.0.1/tests'
〜
make[2]: Entering directory `/home/admin/gmp-5.0.1/tune'
make[2]: `check' に対して行うべき事はありません。
make[2]: Leaving directory `/home/admin/gmp-5.0.1/tune'
Making check in doc
make[2]: Entering directory `/home/admin/gmp-5.0.1/doc'
make[2]: `check' に対して行うべき事はありません。
make[2]: Leaving directory `/home/admin/gmp-5.0.1/doc'
make[2]: Entering directory `/home/admin/gmp-5.0.1'
make[2]: `check-am' に対して行うべき事はありません。
make[2]: Leaving directory `/home/admin/gmp-5.0.1'
make[1]: Leaving directory `/home/admin/gmp-5.0.1'
$
$ su
# make install
make  install-recursive
make[1]: Entering directory `/home/admin/gmp-5.0.1'
Making install in tests
make[2]: Entering directory `/home/admin/gmp-5.0.1/tests'
Making install in .
make[3]: Entering directory `/home/admin/gmp-5.0.1/tests'
make[4]: Entering directory `/home/admin/gmp-5.0.1/tests'
〜
make[4]: Entering directory `/home/admin/gmp-5.0.1'

+-------------------------------------------------------------+
| CAUTION:                                                    |
|                                                             |
| If you have not already run "make check", then we strongly  |
| recommend you do so.                                        |
|                                                             |
| GMP has been carefully tested by its authors, but compilers |
| are all too often released with serious bugs.  GMP tends to |
| explore interesting corners in compilers and has hit bugs   |
| on quite a few occasions.                                   |
|                                                             |
+-------------------------------------------------------------+

make[4]: Leaving directory `/home/admin/gmp-5.0.1'
make[3]: Leaving directory `/home/admin/gmp-5.0.1'
make[2]: Leaving directory `/home/admin/gmp-5.0.1'
make[1]: Leaving directory `/home/admin/gmp-5.0.1'
#
 

移行元環境の i686版のインストールでかまいません 続いて mpfr を

$ tar -xjf mpfr-3.0.0.tar.bz2
$ cd mpfr-3.0.0
$
$ ./configure --prefix=/usr/local
checking for a BSD-compatible install... /bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether to disable maintainer-specific portions of Makefiles... yes
〜
configure: creating ./config.status
config.status: creating Makefile
config.status: creating tests/Makefile
config.status: creating mparam.h
config.status: executing depfiles commands
config.status: executing libtool commands
$ make
Making all in tests
make[1]: Entering directory `/home/admin/mpfr-3.0.0/tests'
make[1]: `all' に対して行うべき事はありません。
make[1]: Leaving directory `/home/admin/mpfr-3.0.0/tests'
make[1]: Entering directory `/home/admin/mpfr-3.0.0'
/bin/sh ./libtool --tag=CC   --mode=compile gcc -std=gnu99 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_LOCALE_H=1 -DHAVE_WCHAR_H=1 -DHAVE_STDARG=1 -DHAVE_SYS_TIME_H=1 -DHAVE_STDINT_H=1 -DHAVE_VA_COPY=1 -DHAVE_SETLOCALE=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_LONG_LONG=1 -DHAVE_INTMAX_T=1 -DMPFR_HAVE_INTMAX_MAX=1 -DMPFR_HAVE_FESETROUND=1 -DHAVE_DENORMS=1 -DHAVE_ROUND=1 -DHAVE_TRUNC=1 -DHAVE_FLOOR=1 -DHAVE_CEIL=1 -DHAVE_NEARBYINT=1 -DHAVE_LDOUBLE_IEEE_EXT_LITTLE=1 -DLT_OBJDIR=\".libs/\" -DHAVE_ATTRIBUTE_MODE=1 -I.     -Wall -Wmissing-prototypes -Wpointer-arith -m32 -O2 -pedantic -fomit-frame-pointer -mtune=k8 -march=k8 -ffloat-store -MT exceptions.lo -MD -MP -MF .deps/exceptions.Tpo -c -o exceptions.lo exceptions.c
〜
libtool: link: ar cru .libs/libmpfr.a  exceptions.o extract.o uceil_exp2.o uceil_log2.o ufloor_log2.o add.o add1.o add_ui.o agm.o clear.o cmp.o cmp_abs.o cmp_si.o cmp_ui.o comparisons.o div_2exp.o div_2si.o div_2ui.o div.o div_ui.o dump.o eq.o exp10.o exp2.o exp3.o exp.o frac.o get_d.o get_exp.o get_str.o init.o inp_str.o isinteger.o isinf.o isnan.o isnum.o const_log2.o log.o modf.o mul_2exp.o mul_2si.o mul_2ui.o mul.o mul_ui.o neg.o next.o out_str.o printf.o vasprintf.o const_pi.o pow.o pow_si.o pow_ui.o print_raw.o print_rnd_mode.o reldiff.o round_prec.o set.o setmax.o setmin.o set_d.o set_dfl_prec.o set_exp.o set_rnd.o set_f.o set_prc_raw.o set_prec.o set_q.o set_si.o set_str.o set_str_raw.o set_ui.o set_z.o sqrt.o sqrt_ui.o sub.o sub1.o sub_ui.o rint.o ui_div.o ui_sub.o urandom.o urandomb.o get_z_exp.o swap.o factorial.o cosh.o sinh.o tanh.o sinh_cosh.o acosh.o asinh.o atanh.o atan.o cmp2.o exp_2.o asin.o const_euler.o cos.o sin.o tan.o fma.o fms.o hypot.o log1p.o expm1.o log2.o log10.o ui_pow.o ui_pow_ui.o minmax.o dim.o signbit.o copysign.o setsign.o gmp_op.o init2.o acos.o sin_cos.o set_nan.o set_inf.o set_zero.o powerof2.o gamma.o set_ld.o get_ld.o cbrt.o volatile.o fits_sshort.o fits_sint.o fits_slong.o fits_ushort.o fits_uint.o fits_ulong.o fits_uintmax.o fits_intmax.o get_si.o get_ui.o zeta.o cmp_d.o erf.o inits.o inits2.o clears.o sgn.o check.o sub1sp.o version.o mpn_exp.o mpfr-gmp.o mp_clz_tab.o sum.o add1sp.o free_cache.o si_op.o cmp_ld.o set_ui_2exp.o set_si_2exp.o set_uj.o set_sj.o get_sj.o get_uj.o get_z.o iszero.o cache.o sqr.o int_ceil_log2.o isqrt.o strtofr.o pow_z.o logging.o mulders.o get_f.o round_p.o erfc.o atan2.o subnormal.o const_catalan.o root.o sec.o csc.o cot.o eint.o sech.o csch.o coth.o round_near_x.o constant.o abort_prec_max.o stack_interface.o lngamma.o zeta_ui.o set_d64.o get_d64.o jn.o yn.o rem1.o get_patches.o add_d.o sub_d.o d_sub.o mul_d.o div_d.o d_div.o li2.o rec_sqrt.o min_prec.o buildopt.o digamma.o bernoulli.o isregular.o set_flt.o get_flt.o scale2.o set_z_exp.o ai.o gammaonethird.o
libtool: link: ranlib .libs/libmpfr.a
libtool: link: ( cd ".libs" && rm -f "libmpfr.la" && ln -s "../libmpfr.la" "libmpfr.la" )
make[1]: Leaving directory `/home/admin/mpfr-3.0.0'
$
$ su
# make install
Making install in tests
make[1]: Entering directory `/home/admin/mpfr-3.0.0/tests'
make[2]: Entering directory `/home/admin/mpfr-3.0.0/tests'
make[2]: `install-exec-am' に対して行うべき事はありません。
make[2]: `install-data-am' に対して行うべき事はありません。
〜
test -z "/usr/local/share/doc/mpfr" || /bin/mkdir -p "/usr/local/share/doc/mpfr"
/bin/mkdir -p '/usr/local/share/doc/mpfr/examples'
 /bin/install -c -m 644  examples/ReadMe examples/divworst.c examples/rndo-add.c examples/sample.c examples/version.c '/usr/local/share/doc/mpfr/examples'
 /bin/install -c -m 644  AUTHORS BUGS COPYING COPYING.LESSER FAQ.html NEWS TODO '/usr/local/share/doc/mpfr/.'
make[2]: Leaving directory `/home/admin/mpfr-3.0.0'
make[1]: Leaving directory `/home/admin/mpfr-3.0.0'
#
 

準備ができたのでようやく 64bitターゲットの gcc をビルドします
簡易版の gcc となります makeコマンドも make all-gcc と制限することになります

$ tar -xjf gcc-4.5.2.tar.bz2
$ mkdir  gcc-4.5.2-amd64-build
$ cd gcc-4.5.2-amd64-build
$
$ VPATH=../gcc-4.5.2 ../gcc-4.5.2/configure --prefix=/usr/gcc/4.5.2/amd64 --target=amd64-linux-gnu --enable-languages=c --disable-shared --with-gmp --with-mpfr --with-mpc --disable-threads --disable-libssp --with-as=/usr/binutils/2.21/amd64/bin/amd64-linux-gnu-as --with-ld=/usr/binutils/2.21/amd64/bin/amd64-linux-gnu-ld
checking build system type... i686-pc-linux-gnu
checking host system type... i686-pc-linux-gnu
checking target system type... x86_64-pc-linux-gnu
checking for a BSD-compatible install... /bin/install -c
〜
checking where to find the target windmc... pre-installed
checking whether to enable maintainer-specific portions of Makefiles... no
checking whether -fkeep-inline-functions is supported... yes
configure: creating ./config.status
config.status: creating Makefile
$
$ make all-gcc
〜
echo timestamp > gpl.pod
perl ../../gcc-4.5.2/gcc/../contrib/texi2pod.pl ../../gcc-4.5.2/gcc/doc/include/gpl_v3.texi > gpl.pod
echo timestamp > doc/gpl.7
(pod2man --center="GNU" --release="gcc-4.5.2" --section=7 gpl.pod > doc/gpl.7.T$$ && \
        mv -f doc/gpl.7.T$$ doc/gpl.7) || \
        (rm -f doc/gpl.7.T$$ && exit 1)
rm gcc.pod
make[1]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build/gcc'
$
 

configureでは ほとんどのオプションを disable指定しています
また –enable-languages も c のみとして c++ や java なども指定せず 最小限の構築とします

$ su
# make install
make[1]: Entering directory `/home/admin/gcc-4.5.2-amd64-build'
/bin/sh ../gcc-4.5.2/mkinstalldirs /usr/gcc/4.5.2/amd64 /usr/gcc/4.5.2/amd64
mkdir -p -- /usr/gcc/4.5.2/amd64 /usr/gcc/4.5.2/amd64
make[2]: Entering directory `/home/admin/gcc-4.5.2-amd64-build/fixincludes'
rm -rf /usr/gcc/4.5.2/amd64/libexec/gcc/amd64-linux-gnu/4.5.2/install-tools
〜
fi
make[3]: Entering directory `/home/admin/gcc-4.5.2-amd64-build/libiberty/testsuite'
make[3]: `install' に対して行うべき事はありません。
make[3]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build/libiberty/testsuite'
make[2]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build/libiberty'
/bin/sh: line 0: cd: amd64-linux-gnu/libmudflap: そのようなファイルやディレクトリはありません
make[1]: *** [install-target-libmudflap] エラー 1
make[1]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build'
make: *** [install] エラー 2
#
 

環境によっては 下記エラーが出ることがありますがとりあえず無視します

 /bin/sh: line 0: cd: amd64-linux-gnu/libstdc++-v3: そのようなファイルやディレクトリはありません
や
 /bin/sh: line 0: cd: amd64-linux-gnu/libmudflap: そのようなファイルやディレクトリはありません
 

インストールが不完全のために途中で止まったように見えますが
後続のサブディレクトリは libiberty/testsuite ぐらいなのでとりあえず問題ないと思います

もうひとつ specs ファイルをインストールしておきます
specsとは gcc の挙動を制御するためのの設定ファイルで
gccに与えられたオプションを解釈して 別のオプションを与えるといった動作をします

gccの挙動に重要な役割をもっていながらほとんど 隠しファイル的な扱いです
現在の(32bitの)環境で gcc -v を実行すると specsの在処が分かります

$ gcc -v
/usr/gcc/4.1.2/i686/lib/gcc/i686-linux-gnu/4.1.2/specs から spec を読み込み中
Target: i686-linux-gnu
コンフィグオプション: ../gcc-4.1.2/configure --prefix=/usr/gcc/4.1.2/i686 --program-prefix=i686-linux-gnu- --host=i686-linux-gnu --target=i686-linux-gnu --build=i686-linux-gnu --enable-threads=posix --enable-nls --with-libiconv-prefix=/usr/glibc/2.5/i686 --enable-languages=c,c++,fortran,java --with-as=/usr/binutils/2.17/i686/bin/i686-linux-gnu-as --with-ld=/usr/binutils/2.17/i686/bin/i686-linux-gnu-ld --with-dwarf2 : (reconfigured) ../gcc-4.1.2/configure --prefix=/usr/gcc/4.1.2/i686 --program-prefix=i686-linux-gnu- --host=i686-linux-gnu --target=i686-linux-gnu --build=i686-linux-gnu --enable-threads=posix --enable-nls --with-libiconv-prefix=/usr/glibc/2.5/i686 --with-as=/usr/binutils/2.17/i686/bin/i686-linux-gnu-as --with-ld=/usr/binutils/2.17/i686/bin/i686-linux-gnu-ld --with-dwarf2 --enable-languages=c,c++,fortran,java --with-arch=i686
スレッドモデル: posix
gcc バージョン 4.1.2
$
 

specsの場所は かなりディレクトリの奥深い部分にあります
ちなみに 上記のコマンドを実行したときに 「build-in specs」と表示されたら
適切な場所に specsが配置されていません(デフォルトの specsの挙動となる?)

今回の amd64 クロスコンパイラも同様の場所に specsを配置します
まずは make install 直後の状態から続けて

# vi gcc/specs 
 

今回 64bit環境の specsを作る上でポイントとなる部分があります
まず *link: の部分を確認してください

 %{!m32:-m elf_x86_64} %{m32:-m elf_i386}
 

これは -m32 が与えられていれば -m elf_i386 と解釈し そうでなければ -m elf_x86_64 と解釈します
つまり gcc に -m32 と与えれば 32bit用のコード そうでなければ 64bit用のコード を生成する動作となるのです

今回 specs の設定の主なポイントは -m32 とそうでない場合の振舞いの違いをどう記述するかになります
また specs に対して主にカスタマイズする部分は 3つです

  • インクルードパス (今回 標準的な /usr/include/ にインストールしないので)
  • glibc gcc の crt(C RunTime)ディレクトリ
  • glibc のライブラリパス (libgcc.a や libgcc_eh.a など)

ここではひとまず インクルードパスを設定しておきます

77 *version:
78 4.5.2
79 
80 *multiinclude:
81 %{!D__KERNEL__:%{!m32:-isystem /usr/glibc/2.9/amd64/include -isystem /usr/gcc/4.5.2/amd64/include -isystem /usr/src/linux-2.6.36.3/include} %{m32:-m32 -isystem /usr/binutils/2.17/i686/include -isystem /usr/glibc/2.5/i686/include -isystem /usr/gcc/4.1.2/i686/include -isystem /usr/src/linux-2.6.30.5/include}}
82 
83 *multilib:
84 . !m64 !m32;64:../lib64 m64 !m32;32:../lib !m64 m32;
85 
86 *multilib_defaults:
87 m64
88 
 

上記のように *multiinclude: という項目を追加しました (名称は適当です)

-m32 の場合とそれ以外とで場合分けを行い
それぞれ 32bit用 64bit用 のディレクトリを指定しているのがポイントです

また -isystemの記述がやたら多いですが
glibc gcc カーネル のヘッダファイルディレクトリを検索パスに追加しているのです

最後に全体を %{!D__KERNEL__:} で括っています
これを省略すると 後でカーネルをビルドしたときに
下記のようなエラーメッセージが表示され カーネルのビルドがうまくいかなかったためです

  CHK     include/generated/compile.h
  UPD     include/generated/compile.h
  CC      init/version.o
  LD      init/built-in.o
  LD      .tmp_vmlinux1
arch/x86/kernel/head64.o: In function `x86_64_start_reservations':
head64.c:(.init.text+0x15): relocation truncated to fit: R_X86_64_32 against symbol `boot_params' defined in .init.data section in arch/x86/built-in.o
head64.c:(.init.text+0x26): relocation truncated to fit: R_X86_64_32 against symbol `boot_command_line' defined in .init.data section in init/built-in.o
head64.c:(.init.text+0x39): relocation truncated to fit: R_X86_64_32 against symbol `__bss_stop' defined in .bss section in .tmp_vmlinux1
head64.c:(.init.text+0x43): relocation truncated to fit: R_X86_64_32 against symbol `_text' defined in .text section in .tmp_vmlinux1
head64.c:(.init.text+0x50): relocation truncated to fit: R_X86_64_32 against `.rodata.str1.1'
head64.c:(.init.text+0x7b): relocation truncated to fit: R_X86_64_32 against `.rodata.str1.1'
arch/x86/kernel/head64.o: In function `x86_64_start_kernel':
head64.c:(.init.text+0xa1): relocation truncated to fit: R_X86_64_32 against symbol `__bss_stop' defined in .bss section in .tmp_vmlinux1
head64.c:(.init.text+0xb8): relocation truncated to fit: R_X86_64_32 against symbol `__bss_start' defined in .bss section in .tmp_vmlinux1
head64.c:(.init.text+0x10d): relocation truncated to fit: R_X86_64_32 against symbol `idt_table' defined in .bss section in arch/x86/kernel/head_64.o
head64.c:(.init.text+0x169): relocation truncated to fit: R_X86_64_32 against symbol `idt_descr' defined in .data section in arch/x86/built-in.o
head64.c:(.init.text+0x17e): additional relocation overflows omitted from the output
make: *** [.tmp_vmlinux1] エラー 1
 

カーネルのビルド時 -D__KERNEL__ が使われるため
このオプションを認識して -isystem を適用しないようにしました

美しい記述とは言えませんが これで コンパイル環境と カーネルのビルドまで確認できました

では 作成した *multiinclude: を C C++ の標準オプションに追加します
*cpp_options: *cc1_options: 部分に追記します

17 *cpp:
18 %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}
19 
20 *cpp_options:
21 %(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w} %{f*} %{g*:%{!g0:%{g*} %{!fno-working-directory:-fworking-directory}}} %{O*} %{undef} %{save-temps*:-fpch-preprocess} %(multiinclude)
22 
23 *cpp_debug_options:
24 %{d*}

32 *cc1:
33 %(cc1_cpu) %{profile:-p}
34 
35 *cc1_options:
36 %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}} %1 %{!Q:-quiet} %{!dumpbase:-dumpbase %B} %{d*} %{m*} %{a*} %{fcompare-debug-second:%:compare-debug-auxbase-opt(%b)}  %{!fcompare-debug-second:%{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}}%{!c:%{!S:-auxbase %b}}  %{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs} %{v:-version} %{pg:-p} %{p} %{f*} %{undef} %{Qn:-fno-ident} %{--help:--help} %{--target-help:--target-help} %{--help=*:--help=%(VALUE)} %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}} %{fsyntax-only:-o %j} %{-param*} %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants} %{coverage:-fprofile-arcs -ftest-coverage} %(multiinclude)
37 
38 *cc1plus:
39 
 

それぞれ最後尾に %(multiinclude) を追記しています
これにより C C++ のコンパイル時に -isystem の設定が利用されます

上記の編集でも推測できると思いますが specsは gccにとって重要な役割を持っていて
標準ライブラリパス 標準インクルードヘッダパス さらには -lc などの標準的なオプションが定義されていることが分かります

作成した specs をインストールしておきます

# cp gcc/specs /usr/gcc/4.5.2/amd64/lib/gcc/amd64-linux-gnu/4.5.2/
 

glibcを本格的に構築するのに必要な libgcc.a を構築しておきます
実は libgcc_eh.a も必要なのですが glibcが構築できていないため現段階では作れません

現在の gccのビルド状況は中途半端なままですが 進めるところまで構築を進めましょう
続けて makeコマンドを実施します

# exit
$ make
〜
checking for amd64-linux-gnu-gcc... /home/admin/gcc-4.5.2-amd64-build/./gcc/xgcc -B/home/admin/gcc-4.5.2-amd64-build/./gcc/ -B/usr/gcc/4.5.2/amd64/amd64-linux-gnu/bin/ -B/usr/gcc/4.5.2/amd64/amd64-linux-gnu/lib/ -isystem /usr/gcc/4.5.2/amd64/amd64-linux-gnu/include -isystem /usr/gcc/4.5.2/amd64/amd64-linux-gnu/sys-include
checking for C compiler default output file name...
configure: error: in `/home/admin/gcc-4.5.2-amd64-build/amd64-linux-gnu/libmudflap':
configure: error: C compiler cannot create executables
See `config.log' for more details.
make[1]: *** [configure-target-libmudflap] エラー 1
make[1]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build'
make: *** [all] エラー 2
$
 

エラーが出て途中でビルドが停止しています
config.log によると原因は libc や crti.o crt1.o が見付からないためで
つまり ここから先に構築を進めるには glibcが必要となっています

ここでの目的である libgcc.a が出来ていればOKです

$ find . -name '*libgcc*'
./amd64-linux-gnu/32/libgcc
./amd64-linux-gnu/32/libgcc/libgcc.a
./amd64-linux-gnu/libgcc
./amd64-linux-gnu/libgcc/libgcc.a
./gcc/32/libgcc.a
./gcc/libgcc.mvars
./gcc/libgcc.a
$
 

amd64-linux-gnu/ に入っている libgcc.a と gcc/ に入っている libgcc.a は同じようです
(バイナリレベルでは 別ものみたいですが詳細は分かりませんでした)
さらに 32bit版と 64bit版があることが分かります (32というディレクトリが 32bit版)
こういうところでも 32bit版と 64bit版の構築環境の違いが感じられます

共有ライブラリ用?の libgcc_eh.a も最終的に必要となりますが
glibcの crti.o や crtn.o を先に作る必要があるため 今の段階では作成できません
また configureにも –enable-shared が必要なため 結局 gcc を後で作り直すことになります

できあがった gcc/ を一旦ビルドディレクトリ外に退避します
(今の gcc のビルドディレクトリを 後で 一旦削除するためです)
また 退避した gcc/ ディレクトリを参照できるように specsにも設定をいれます

$ cp -r gcc ../
$ su
# vi /usr/gcc/4.5.2/amd64/lib/gcc/amd64-linux-gnu/4.5.2/specs
 

今回 specsには crtのあるディレクトリを設定します
specsには 既に *md_startfile_prefix: *md_startfile_prefix_1: という項目があり
未使用状態なのでこれを使わせてもらいます
((注) *md_startfile_prefix: *md_startfile_prefix_1: を使うのは間違った方法かも)

119 *md_exec_prefix:
120 
121 
122 *md_startfile_prefix:
123 %{!m32:/usr/glibc/2.9/amd64/lib/}%{m32:/usr/glibc/2.5/i686/lib/}
124 
125 *md_startfile_prefix_1:
126 %{!m32:/home/admin/gcc/}%{m32:/home/admin/gcc/32/}
127 
 

やはり -m32 かそうでないかで場合分けをしているところがポイントです

今回 specsに設定を入れるのは crtを設定している *startfile: *endfile: です
ここにある 〜.o 各ファイルのパスを設定します指定します

まず *endfile: から

46 
47 *endfile:
48 %{ffast-math|funsafe-math-optimizations:%(md_startfile_prefix_1)crtfastmath.o%s}    %{mpc32:%(md_startfile_prefix_1)crtprec32.o%s}    %{mpc64:%(md_startfile_prefix_1)crtprec64.o%s}    %{mpc80:%(md_startfile_prefix_1)crtprec80.o%s}    %{shared|pie:%(md_startfile_prefix_1)crtendS.o%s;:%(md_startfile_prefix_1)crtend.o%s}  %(md_startfile_prefix)crtn.o%s
49 
 

crtfastmath.o crtprec32.o crtprec64.o crtprec80.o crtendS.o crtend.o は gccの crtなので md_startfile_prefix_1 を指定します
crtn.o は glibcの crtです md_startfile_prefix を設定しておきます

*startfile: も同様です

67 
68 *startfile:
69 %{!shared: %{pg|p|profile:%(md_startfile_prefix)gcrt1.o%s;pie:%(md_startfile_prefix)Scrt1.o%s;:%(md_startfile_prefix)crt1.o%s %(md_startfile_prefix)crti.o%s %{static:%(md_startfile_prefix_1)crtbeginT.o%s;shared|pie:%(md_startfile_prefix_1)crtbeginS.o%s;:%(md_startfile_prefix_1)crtbegin.o%s}
70 
 

crtbeginT.o crtbeginS.o crtbegin.o は gccの crtなので md_startfile_prefix_1 を指定
gcrt1.o Scrt1.o crt1.o crti.o は glibcのファイルです これも今回設定しておきます

紛らわしい作業となるのでご注意ください
glibcのパスとして本命のディレクトリを指定していますが 現段階では crtファイルはありません

これで ようやく簡易版 gcc が動くようになりました いよいよ glibcを構築していきます
念のため glibcの既存ビルドディレクトリを削除した上で再構築します

# cd
# rm -rf glibc-2.9-amd64-build
# exit
$ mkdir glibc-2.9-amd64-build
$ cd glibc-2.9-amd64-build
$ VPATH=../glibc-2.9 AR=/usr/binutils/2.21/amd64/bin/amd64-linux-gnu-ar CC=/usr/gcc/4.5.2/amd64/bin/amd64-linux-gnu-gcc RANLIB=/usr/binutils/2.21/amd64/bin/amd64-linux-gnu-ranlib ../glibc-2.9/configure --prefix=/usr/glibc/2.9/amd64  --host=amd64-linux-gnu --enable-add-ons=nptl,libidn --with-tls --program-prefix=amd64-linux-gnu- --enable-stackguard-randomization
configure: WARNING: If you wanted to set the --build type, don't use --host.
    If a cross compiler is detected then cross compile mode will be used.
checking build system type... i686-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
〜
checking for autoconf... autoconf
checking whether autoconf works... yes
configure: error:
*** These critical programs are missing or too old: as ld
*** Check the INSTALL file for required versions.
$
 

いきなり エラーが出て止まってしまいました
これは binutilsのバージョンが新し過ぎるために 許容バージョンとしてチェックされなかったものです

configure スクリプトを編集して回避することにします

$ vi ../glibc-2.9/configure
 

下記の部分に追加行を作って回避するようにします

4532   case $ac_prog_version in
4533     '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
4534     2.1[3-9]*)
4535        ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
4536     2.2[0-9]*)
4537        ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
4538     *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
〜
4597   case $ac_prog_version in
4598     '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
4599     2.1[3-9]*)
4600        ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
4601     2.2[0-9]*)
4602        ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
4603     *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
 

追加行は 4535〜4536行目 4601〜4602行目 です
これで binutils-2.21 が許容範囲になります (強引ですね)

$ VPATH=../glibc-2.9 AR=/usr/binutils/2.21/amd64/bin/amd6-linux-gnu-ar CC=/usr/gcc/4.5.2/amd64/bin/amd64-linux-gnu-gcc RANLIB=/usr/binutls/2.21/amd64/bin/amd64-linux-gnu-ranlib ../glibc-2.9/configure --prefix=/usr/gibc/2.9/amd64  --host=amd64-linux-gnu --enable-add-ons=nptl,libidn --with-tls -program-prefix=amd64-linux-gnu- --enable-stackguard-randomization
〜
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking for long double... yes
checking size of long double... configure: error: cannot compute sizeof (long double)
See `config.log' for more details.
$
 

また エラーが出ました
原因は configure の中で検証されるテストプログラムがコンパイルに失敗したためです

glibcの構築に実害はないはずなので
configure スクリプトに ac_cv_sizeof_long_double=yes を渡すことで回避します

$ VPATH=../glibc-2.9 AR=/usr/binutils/2.21/amd64/bin/amd6-linux-gnu-ar CC=/usr/gcc/4.5.2/amd64/bin/amd64-linux-gnu-gcc RANLIB=/usr/binutls/2.21/amd64/bin/amd64-linux-gnu-ranlib ../glibc-2.9/configure --prefix=/usr/gibc/2.9/amd64  --host=amd64-linux-gnu --enable-add-ons=nptl,libidn --with-tls -program-prefix=amd64-linux-gnu- --enable-stackguard-randomization ac_cv_sizeof_ong_double=yes
〜
checking size of long double... (cached) yes
running configure fragment for sysdeps/x86_64/elf
checking for x86-64 TLS support... yes
running configure fragment for nptl/sysdeps/pthread
checking for forced unwind support... no
configure: error: forced unwind support is required
$
 

次は unwind関連ですか libc_cv_forced_unwind=yes を渡して回避するようにします

$ VPATH=../glibc-2.9 AR=/usr/binutils/2.21/amd64/bin/amd6-linux-gnu-ar CC=/usr/gcc/4.5.2/amd64/bin/amd64-linux-gnu-gcc RANLIB=/usr/binutls/2.21/amd64/bin/amd64-linux-gnu-ranlib ../glibc-2.9/configure --prefix=/usr/gibc/2.9/amd64  --host=amd64-linux-gnu --enable-add-ons=nptl,libidn --with-tls -program-prefix=amd64-linux-gnu- --enable-stackguard-randomization ac_cv_sizeof_ong_double=yes libc_cv_forced_unwind=yes
〜
checking size of long double... (cached) yes
running configure fragment for sysdeps/x86_64/elf
checking for x86-64 TLS support... yes
running configure fragment for nptl/sysdeps/pthread
checking for forced unwind support... (cached) yes
checking for C cleanup handling... no
configure: error: the compiler must support C cleanup handling
$
 

続けざまに引っかかっています
これも テストプログラムのコンパイルテストに失敗しただけで 特に何か不足しているとかないはずです
このテスト項目も libc_cv_c_cleanup=yes を渡して回避します

$ VPATH=../glibc-2.9 AR=/usr/binutils/2.21/amd64/bin/amd6-linux-gnu-ar CC=/usr/gcc/4.5.2/amd64/bin/amd64-linux-gnu-gcc RANLIB=/usr/binutls/2.21/amd64/bin/amd64-linux-gnu-ranlib ../glibc-2.9/configure --prefix=/usr/gibc/2.9/amd64  --host=amd64-linux-gnu --enable-add-ons=nptl,libidn --with-tls -program-prefix=amd64-linux-gnu- --enable-stackguard-randomization ac_cv_sizeof_ong_double=yes libc_cv_forced_unwind=yes libc_cv_c_cleanup=yes
〜
checking if -g produces usable source locations for assembler-with-cpp... yes
checking for old glibc 2.0.x headers... no
checking whether -fPIC is default... no
configure: creating ./config.status
config.status: creating config.make
config.status: creating Makefile
config.status: creating config.h
config.status: executing default commands
$
 

configureはとりあえず パスさせました

ちなみに 次のエラーメッセージが出た場合
checking for .preinit_array/.init_array/.fini_array support… no
configure: error: Need linker with .init_array/.fini_array support.
glibcの 標準スタートアップライブラリが認識されていないのが原因と思います
configure上で このチェックを迂回するには libc_cv_initfini_array=yes を指定します

いよいよ glibcのビルドです

$ make
〜
/bin/sh scripts/move-if-change /home/admin/glibc-2.9-amd64-build/gnu/lib-names.T /home/admin/glibc-2.9-amd64-build/gnu/lib-names.h
touch /home/admin/glibc-2.9-amd64-build/gnu/lib-names.stmp
/bin/install -c -m 644 include/limits.h /usr/glibc/2.9/amd64/include/limits.h
/bin/install: cannot remove `/usr/glibc/2.9/amd64/include/limits.h': 許可がありません
make[1]: *** [/usr/glibc/2.9/amd64/include/limits.h] エラー 1
make[1]: Leaving directory `/home/admin/glibc-2.9'
make: *** [all] エラー 2
$
 

エラーが出ました やはり強引な configure が問題だったかな
と思ったら原因は違っていました

最初に構築した make install-headers によるヘッダファイルを置き換えようとしていたようです
root権限がないためファイルの上書きができずエラーになったようです

古いファイルは make install時に消せばよくて 今消す必要はありません
configureに –disable-force-install オプションを追加して make 時の余計なインストール動作を抑制します

$ VPATH=../glibc-2.9 AR=/usr/binutils/2.21/amd64/bin/amd6-linux-gnu-ar CC=/usr/gcc/4.5.2/amd64/bin/amd64-linux-gnu-gcc RANLIB=/usr/binutls/2.21/amd64/bin/amd64-linux-gnu-ranlib ../glibc-2.9/configure --prefix=/usr/gibc/2.9/amd64  --host=amd64-linux-gnu --enable-add-ons=nptl,libidn --with-tls -program-prefix=amd64-linux-gnu- --enable-stackguard-randomization ac_cv_sizeof_ong_double=yes libc_cv_forced_unwind=yes libc_cv_c_cleanup=yes --disable-force-nstall
〜
checking whether -fPIC is default... no
configure: creating ./config.status
config.status: creating config.make
config.status: creating Makefile
config.status: creating config.h
config.status: config.h is unchanged
config.status: executing default commands
$ make
〜
a - elf/dl-profstub.os
a - elf/dl-libc.os
a - elf/dl-sym.os
a - elf/dl-tsd.os
a - elf/dl-vdso.os
/usr/binutils/2.21/amd64/bin/amd64-linux-gnu-ranlib /home/admin/glibc-2.9-amd64-build/libc_pic.a
/usr/gcc/4.5.2/amd64/bin/amd64-linux-gnu-gcc   -nostdlib -nostartfiles -r -o /home/admin/glibc-2.9-amd64-build/elf/librtld.map.o '-Wl,-(' /home/admin/glibc-2.9-amd64-build/elf/dl-allobjs.os /home/admin/glibc-2.9-amd64-build/libc_pic.a -lgcc '-Wl,-)' -Wl,-Map,/home/admin/glibc-2.9-amd64-build/elf/librtld.mapT
/usr/binutils/2.21/amd64/bin/amd64-linux-gnu-ld: cannot find -lgcc
collect2: ld はステータス 1 で終了しました
make[2]: *** [/home/admin/glibc-2.9-amd64-build/elf/librtld.map] エラー 1
make[2]: Leaving directory `/home/admin/glibc-2.9/elf'
make[1]: *** [elf/subdir_lib] エラー 2
make[1]: Leaving directory `/home/admin/glibc-2.9'
make: *** [all] エラー 2
$
 

今度はかなり いいところまで進行しました けどエラーが出ました

-lgcc で libgcc.a が見付からず失敗しています
先ほど構築した libgcc.a は暫定のディレクトリにあるので これを glibcに伝える必要があります

ここは仕方ないので glibcの ソース Makefile内で強引にライブラリパスを指定して対応します

$ vi ../glibc-2.9/elf/Makefile
 
263 $(objpfx)librtld.map: $(objpfx)dl-allobjs.os $(common-objpfx)libc_pic.a
264         @-rm -f $@T
265         $(reloc-link) -o $@.o '-Wl,-(' $^ -lgcc -L/home/admin/gcc '-Wl,-)' -Wl,-Map,$@T
266         rm -f $@.o
267         mv -f $@T $@

292
293 $(objpfx)librtld.os: $(objpfx)dl-allobjs.os $(objpfx)rtld-libc.a
294         $(LINK.o) -nostdlib -nostartfiles -r -o $@ '-Wl,-(' $^ -lgcc -L/home/admin/gcc '-Wl,-)' \
295                   -Wl,-Map,$@.map
296
 

2箇所 -lgcc の直後に暫定 -L/home/admin/gcc を指定します

make を続行しますが もし次のようなエラーが出た場合

../sysdeps/unix/sysv/linux/accept.S:5:20: fatal error: socket.S: そのようなファ>イルやディレクトリはありません
コンパイルが中断されました。
 

glibc-2.9/sysdeps/unix/sysv/linux/x86_64/ には socket.S が提供されていないのが原因です
この場合 空の socket.S を用意してごまかしましょう

$ touch ../glibc-2.9/sysdeps/unix/sysv/linux/x86_64/socket.S
 

上記のエラーは環境によって出ないかもしれません
ともかく make を続行します

$ make
〜
/home/admin/glibc-2.9-amd64-build/elf/librtld.os: In function `_dl_start_final':
/home/admin/glibc-2.9/elf/rtld.c:294: undefined reference to `_begin'
/usr/binutils/2.21/amd64/bin/amd64-linux-gnu-ld: /home/admin/glibc-2.9-amd64-build/elf/librtld.os: relocation R_X86_64_PC32 against undefined hidden symbol `_begin' can not be used when making a shared object
/usr/binutils/2.21/amd64/bin/amd64-linux-gnu-ld: final link failed: Bad value
collect2: ld はステータス 1 で終了しました
make[2]: *** [/home/admin/glibc-2.9-amd64-build/elf/ld.so] エラー 1
make[2]: Leaving directory `/home/admin/glibc-2.9/elf'
make[1]: *** [elf/subdir_lib] エラー 2
make[1]: Leaving directory `/home/admin/glibc-2.9'
make: *** [all] エラー 2
 

やはり ここまで来ると いろいろ不都合が積もってきているのでしょうか…
謎なセリフを吐いてビルドが停止する現象が多発します

原因は ソースの不具合なのか結局分かりませんでしたが 解決策を発見しました

$ vi ../glibc-2.9/elf/Makefile
 

307行目を変更します

(変更前) -e 's/\. = 0 + SIZEOF_HEADERS;/& _begin = . - SIZEOF_H    EADERS;/' \
(変更後) -e 's/\. = .* + SIZEOF_HEADERS;/& _begin = . - SIZEOF_H    EADERS;/' \
 

気をとりなおしてビルドを続けます

$ make
/usr/gcc/4.5.2/amd64/bin/amd64-linux-gnu-gcc   -shared -static-libgcc -Wl,-O1  -Wl,-z,defs -Wl,-dynamic-linker=/usr/glibc/2.9/amd64/lib/ld-linux-x86-64.so.2  -B/home/admin/glibc-2.9-amd64-build/csu/  -Wl,--version-script=/home/admin/glibc-2.9-amd64-build/libc.map -Wl,-soname=libc.so.6 -Wl,-z,combreloc -Wl,-z,relro -Wl,--hash-style=both -nostdlib -nostartfiles -e __libc_main -L/home/admin/glibc-2.9-amd64-build -L/home/admin/glibc-2.9-amd64-build/math -L/home/admin/glibc-2.9-amd64-build/elf -L/home/admin/glibc-2.9-amd64-build/dlfcn -L/home/admin/glibc-2.9-amd64-build/nss -L/home/admin/glibc-2.9-amd64-build/nis -L/home/admin/glibc-2.9-amd64-build/rt -L/home/admin/glibc-2.9-amd64-build/resolv -L/home/admin/glibc-2.9-amd64-build/crypt -L/home/admin/glibc-2.9-amd64-build/nptl -Wl,-rpath-link=/home/admin/glibc-2.9-amd64-build:/home/admin/glibc-2.9-amd64-build/math:/home/admin/glibc-2.9-amd64-build/elf:/home/admin/glibc-2.9-amd64-build/dlfcn:/home/admin/glibc-2.9-amd64-build/nss:/home/admin/glibc-2.9-amd64-build/nis:/home/admin/glibc-2.9-amd64-build/rt:/home/admin/glibc-2.9-amd64-build/resolv:/home/admin/glibc-2.9-amd64-build/crypt:/home/admin/glibc-2.9-amd64-build/nptl -o /home/admin/glibc-2.9-amd64-build/libc.so -T /home/admin/glibc-2.9-amd64-build/shlib.lds /home/admin/glibc-2.9-amd64-build/csu/abi-note.o /home/admin/glibc-2.9-amd64-build/elf/soinit.os /home/admin/glibc-2.9-amd64-build/libc_pic.os /home/admin/glibc-2.9-amd64-build/elf/sofini.os /home/admin/glibc-2.9-amd64-build/elf/interp.os /home/admin/glibc-2.9-amd64-build/elf/ld.so -lgcc
/usr/binutils/2.21/amd64/bin/amd64-linux-gnu-ld: cannot find -lgcc
collect2: ld はステータス 1 で終了しました
make[1]: *** [/home/admin/glibc-2.9-amd64-build/libc.so] エラー 1
make[1]: Leaving directory `/home/admin/glibc-2.9'
make: *** [all] エラー 2
$
 

また -lgcc で失敗と出ています
対処療法的に対応していくしかありません

$ vi ../glibc-2.9/Makeconfig
 

下記の部分に修正を加えました -L/home/admin/gcc を追記しています 534行目です

532 gnulib := -lgcc $(libgcc_eh)
533 static-gnulib := -lgcc -lgcc_eh $(libunwind)
534 libc.so-gnulib := -lgcc -L/home/admin/gcc
535 endif
 

ひたすら make します

$ make
〜
/usr/gcc/4.5.2/amd64/bin/amd64-linux-gnu-gcc -nostdlib -nostartfiles -o /home/admin/glibc-2.9-amd64-build/iconv/iconvconfig  -Wl,-dynamic-linker=/usr/glibc/2.9/amd64/lib/ld-linux-x86-64.so.2   -Wl,-z,combreloc -Wl,-z,relro -Wl,--hash-style=both /home/admin/glibc-2.9-amd64-build/csu/crt1.o /home/admin/glibc-2.9-amd64-build/csu/crti.o `/usr/gcc/4.5.2/amd64/bin/amd64-linux-gnu-gcc --print-file-name=crtbegin.o` /home/admin/glibc-2.9-amd64-build/iconv/iconvconfig.o /home/admin/glibc-2.9-amd64-build/iconv/strtab.o /home/admin/glibc-2.9-amd64-build/iconv/xmalloc.o /home/admin/glibc-2.9-amd64-build/iconv/hash-string.o  -Wl,-rpath-link=/home/admin/glibc-2.9-amd64-build:/home/admin/glibc-2.9-amd64-build/math:/home/admin/glibc-2.9-amd64-build/elf:/home/admin/glibc-2.9-amd64-build/dlfcn:/home/admin/glibc-2.9-amd64-build/nss:/home/admin/glibc-2.9-amd64-build/nis:/home/admin/glibc-2.9-amd64-build/rt:/home/admin/glibc-2.9-amd64-build/resolv:/home/admin/glibc-2.9-amd64-build/crypt:/home/admin/glibc-2.9-amd64-build/nptl /home/admin/glibc-2.9-amd64-build/libc.so.6 /home/admin/glibc-2.9-amd64-build/libc_nonshared.a -lgcc -lgcc_eh  `/usr/gcc/4.5.2/amd64/bin/amd64-linux-gnu-gcc --print-file-name=crtend.o` /home/admin/glibc-2.9-amd64-build/csu/crtn.o
amd64-linux-gnu-gcc: crtbegin.o: そのようなファイルやディレクトリはありません
amd64-linux-gnu-gcc: crtend.o: そのようなファイルやディレクトリはありません
make[2]: *** [/home/admin/glibc-2.9-amd64-build/iconv/iconvconfig] エラー 1
make[2]: Leaving directory `/home/admin/glibc-2.9/iconv'
make[1]: *** [iconv/others] エラー 2
make[1]: Leaving directory `/home/admin/glibc-2.9'
make: *** [all] エラー 2
$
 

specsにわざわざ設定した crtbegin.o crtend.o のフルパス指定が無視されていますね
原因は 先ほどの Makeconfigファイルにありした

$ vi ../glibc-2.9/Makeconfig
 

crtbegin.o のパスを gcc –print-file-name=crtbegin.o コマンドで検索している箇所があります
このコマンドは crtbegin.o などのファイルが適切にインストールされてないと正しいパスを回答しません
つまり今回のエラーは オブジェクトを ~/gcc/ 内に暫定配置しているために発生したことになります

+prector と +postctor を直接修正します

(修正前)
+prector = `$(CC) --print-file-name=crtbegin.o`
+postctor = `$(CC) --print-file-name=crtend.o`
(修正後)
+prector = /home/admin/gcc/crtbegin.o
+postctor = /home/admin/gcc/crtend.o
 

さらに make を続けます

$ make
〜
/usr/binutils/2.21/amd64/bin/amd64-linux-gnu-ld: cannot find -lgcc
/usr/binutils/2.21/amd64/bin/amd64-linux-gnu-ld: cannot find -lgcc_eh
collect2: ld はステータス 1 で終了しました
make[2]: *** [/home/admin/glibc-2.9-amd64-build/iconv/iconvconfig] エラー 1
make[2]: Leaving directory `/home/admin/glibc-2.9/iconv'
make[1]: *** [iconv/others] エラー 2
make[1]: Leaving directory `/home/admin/glibc-2.9'
make: *** [all] エラー 2
$
 

ここから先は libgcc_eh.a が必要となります ただし

$ ls *.so *.a
libc.a  libc.so  libc_nonshared.a  libc_pic.a
$ find . -name '*crt*.o'
./wcsmbs/wcrtomb.o
./signal/allocrtsig.o
./csu/gcrt1.o
./csu/Mcrt1.o
./csu/crtn.o
./csu/crti.o
./csu/Scrt1.o
./csu/crt1.o
./nptl/crtn.o
./nptl/crti.o
./debug/wcrtomb_chk.o
$
 

上記のように crti.o crtn.o libc.a libc.soが作成されているので
これを使って 共有ライブラリ版 gcc の構築を進めることができます

csu/ にある オブジェクトだけ先に手動インストールしておきます

$ su
# mkdir /usr/glibc/2.9/amd64/lib
# cp *.so /usr/glibc/2.9/amd64/lib/
# cp *.a /usr/glibc/2.9/amd64/lib/
# cp csu/*crt*.o /usr/glibc/2.9/amd64/lib/
# cp elf/ld.so /usr/glibc/2.9/amd64/lib/
# ln -s ld.so /usr/glibc/2.9/amd64/lib/ld-linux-x86-64.so.2
# exit
$ cd ..
 

一旦 glibcの構築を中断して gccのビルドに移りましょう
次の gcc構築の目的は libgcc_eh です

$ rm -rf gcc-4.5.2-amd64-build
$ mkdir gcc-4.5.2-amd64-build
$ cd gcc-4.5.2-amd64-build
$ VPATH=../gcc-4.5.2 ../gcc-4.5.2/configure --prefix=/usr/gcc/4.5.2/amd64 --target=amd64-linux-gnu --enable-languages=c,c++,java --enable-shared --with-gmp --with-mpfr --with-mpc --enable-threads=posix --enable-libssp --enable-nls --with-as=/usr/binutils/2.21/amd64/bin/amd64-linux-gnu-as --with-ld=/usr/binutils/2.21/amd64/bin/amd64-linux-gnu-ld
checking build system type... i686-pc-linux-gnu
checking host system type... i686-pc-linux-gnu
checking target system type... x86_64-pc-linux-gnu
checking for a BSD-compatible install... /bin/install -c
checking whether ln works... yes
〜
checking where to find the target strip... pre-installed
checking where to find the target windres... pre-installed
checking where to find the target windmc... pre-installed
checking whether to enable maintainer-specific portions of Makefiles... no
checking whether -fkeep-inline-functions is supported... yes
configure: creating ./config.status
config.status: creating Makefile
$
 

今度は configureの指定は 本命の設定です
ほとんどのオプションを有効化し –enable-languagesも c,c++,java を指定しています

ただし fortran はビルド途中でエラーが出て回避できなかったため今回はビルドをあきらめました
(64bit環境での問題?)

$ make
〜
../../../../gcc-4.5.2/libgcc/config/libbid/bid_decimal_globals.c:47:18: fatal error: fenv.h: そのようなファイルやディレクトリはありません
コンパイルが中断されました。 
make[4]: *** [bid_decimal_globals.o] エラー 1 
make[4]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build/amd64-linux-gnu/32/libgcc'
make[3]: *** [multi-do] エラー 1 
make[3]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build/amd64-linux-gnu/libgcc'
make[2]: *** [all-multi] エラー 2 
make[2]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build/amd64-linux-gnu/libgcc'
make[1]: *** [all-target-libgcc] エラー 2 
make[1]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build'
make: *** [all] エラー 2 
$
 

上記のエラーは glibc の fenv.hが見付からないエラーです
gccのビルドディレクトリから作りなおしているので 再度 specs の設定が必要です

$ vi gcc/specs
 

先ほどと同じく
*multiinclude: を追加して
*cpp_options: *cc1_options: に %(multiinclude) を追記するのと

*md_startfile_prefix: を設定して glibc系の crtパスを設定します

19 
20 *cpp_options:
21 %(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w} %{f*} %{g*:%{!g0:%{g*} %{!fno-working-directory:-fworking-directory}}} %{O*} %{undef} %{save-temps*:-fpch-preprocess} %(multiinclude)
22 

34 
35 *cc1_options:
36 %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}} %1 %{!Q:-quiet} %{!dumpbase:-dumpbase %B} %{d*} %{m*} %{a*} %{fcompare-debug-second:%:compare-debug-auxbase-opt(%b)}  %{!fcompare-debug-second:%{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}}%{!c:%{!S:-auxbase %b}}  %{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs} %{v:-version} %{pg:-p} %{p} %{f*} %{undef} %{Qn:-fno-ident} %{--help:--help} %{--target-help:--target-help} %{--help=*:--help=%(VALUE)} %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}} %{fsyntax-only:-o %j} %{-param*} %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants} %{coverage:-fprofile-arcs -ftest-coverage} %(multiinclude)
37 

46 
47 *endfile:
48 %{ffast-math|funsafe-math-optimizations:%(md_startfile_prefix_1)crtfastmath.o%s}    %{mpc32:%(md_startfile_prefix_1)crtprec32.o%s}    %{mpc64:%(md_startfile_prefix_1)crtprec64.o%s}    %{mpc80:%(md_startfile_prefix_1)crtprec80.o%s}    %{shared|pie:%(md_startfile_prefix_1)crtendS.o%s;:%(md_startfile_prefix_1)crtend.o%s} %(md_startfile_prefix)crtn.o%s
49
50 *link:
51 %{!static:--eh-frame-hdr} %{!m32:-m elf_x86_64 -L/usr/glibc/2.9/amd64/lib} %{m32:-m elf_i386 -L/usr/glibc/2.5/i686/lib}   %{shared:-shared}   %{!shared:     %{!static:       %{rdynamic:-export-dynamic}       %{m32:%{!dynamic-linker:-dynamic-linker %{muclibc:%{mglibc:%e-mglibc and -muclibc used together}/lib/ld-uClibc.so.0;:/lib/ld-linux.so.2}}}       %{!m32:%{!dynamic-linker:-dynamic-linker %{muclibc:%{mglibc:%e-mglibc and -muclibc used together}/lib/ld64-uClibc.so.0;:/lib64/ld-linux-x86-64.so.2}}}}     %{static:-static}}
52

67 
68 *startfile:
69 %{!shared: %{pg|p|profile:%(md_startfile_prefix)gcrt1.o%s;pie:%(md_startfile_prefix)Scrt1.o%s;:%(md_startfile_prefix)crt1.o%s}}    %(md_startfile_prefix)crti.o%s %{static:%(md_startfile_prefix_1)crtbeginT.o%s;shared|pie:%(md_startfile_prefix_1)crtbeginS.o%s;:%(md_startfile_prefix_1)crtbegin.o%s}
70 

79 
80 *multiinclude:
81 %{!D__KERNEL__:%{!m32:-isystem /usr/glibc/2.9/amd64/include -isystem /usr/gcc/4.5.2/amd64/include -isystem /usr/src/linux-2.6.36.3/include} %{m32:-m32 -isystem /usr/binutils/2.17/i686/include -isystem /usr/glibc/2.5/i686/include -isystem /usr/gcc/4.1.2/i686/include -isystem /usr/src/linux-2.6.30.5/include}}
82 

121 
122 *md_startfile_prefix:
123 %{!m32:/usr/glibc/2.9/amd64/lib/}%{m32:/usr/glibc/2.5/i686/lib/}
124 
125 *md_startfile_prefix_1:
126 %{!m32:/home/admin/gcc/}%{m32:/home/admin/gcc/32/}
127 
 

新しく設定した箇所は *link: 部分で
-m32 かそうでないか で glibcのライブラリパスを設定しています
これで -lc による libc.a がちゃんと見付かるように specsに教えているのです

参考情報ですが 今回の specsは –enable-shared を指定したことにより
*libgcc: 部分が変化していました

 %{static|static-libgcc:-lgcc -lgcc_eh}%{!static:%{!static-libgcc:%{!shared-libgcc:-lgcc --as-needed -lgcc_s --no-as-needed}%{shared-libgcc:-lgcc_s%{!shared: -lgcc}}}}
 

–disable-shared の時は -lgcc のみでしたが
libgcc_eh libgcc_s を使い分けるような記述が見られます

さて 本題に戻ってビルドを続けます

$ make
〜
checking for C compiler default output file name...
configure: error: in `/home/admin/gcc-4.5.2-amd64-build/amd64-linux-gnu/libgomp':
configure: error: C compiler cannot create executables
See `config.log' for more details.
make[1]: *** [configure-target-libgomp] エラー 1
make[1]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build'
make: *** [all] エラー 2
$
 

いいところまで進みました ログ amd64-linux-gnu/libgomp/config.log を見ると
__libc_csu_fini や __libc_csu_init のシンボルが見付からないエラーとなっています

ちなみに 上記シンボルがどのオブジェクトで提供されているか確認すると

$ amd64-linux-gnu-nm /usr/glibc/2.9/amd64/lib/libc.a | grep libc_csu
0000000000000090 T __libc_csu_fini
0000000000000000 T __libc_csu_init
$ amd64-linux-gnu-nm /usr/glibc/2.9/amd64/lib/libc.so | grep libc_csu
$
 

スタティックライブラリ版 libc.a には含まれるが
共有ライブラリ版 libc には含まれていません

いずれにしても glibcを構築進める必要があります
とりあえずここまで作れた ライブラリを確認しましょう

$ find . -name '*libgcc*'
./amd64-linux-gnu/32/libgcc
./amd64-linux-gnu/32/libgcc/32/libgcc_s.so
./amd64-linux-gnu/32/libgcc/32/libgcc_s.so.1
./amd64-linux-gnu/32/libgcc/libgcc.map
./amd64-linux-gnu/32/libgcc/libgcc_eh.a
./amd64-linux-gnu/32/libgcc/libgcc.a
./amd64-linux-gnu/libgcc
./amd64-linux-gnu/libgcc/libgcc_s.so
./amd64-linux-gnu/libgcc/libgcc_s.so.1
./amd64-linux-gnu/libgcc/libgcc.map
./amd64-linux-gnu/libgcc/libgcc_eh.a
./amd64-linux-gnu/libgcc/libgcc.a
./gcc/libgcc_s.so
./gcc/libgcc_s.so.1
./gcc/32/libgcc_s.so
./gcc/32/libgcc_s.so.1
./gcc/32/libgcc_eh.a
./gcc/32/libgcc.a
./gcc/libgcc.mvars
./gcc/libgcc_eh.a
./gcc/libgcc.a
$
 

いい感じで増えてます 目的である libgcc_eh.a も作られています

これらライブラリを 暫定場所に退避しておきましょう

$ rm -rf ../gcc
$ cp -r gcc ../
$
 

specsファイルも インストールディレクトリの方に反映します

$ su
# cp gcc/specs /usr/gcc/4.5.2/amd64/lib/gcc/amd64-linux-gnu/4.5.2/
# exit
$ 
 

gccのライブラリもだいぶ揃って来ました
ここで再び glibcの構築に戻ります

先ほどエラーで glibcの構築を止めた原因の libgcc_eh.a も作成されています
glibcのビルドを継続するために libgcc_eh.a の場所を glibcに教えてあげる必要あります

$ cd ../glibc-2.9-amd64-build
$ vi ../glibc-2.9/Makeconfig
 

暫定ディレクトリを指定します 426行目 439行目 に -L/home/admin/gcc を追記します

424 # Command for linking programs with the C library.
425 ifndef +link
426 +link = $(CC) -nostdlib -nostartfiles -L/home/admin/gcc -o $@ \
427               $(sysdep-LDFLAGS) $(config-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)    ) \           $(combreloc-LDFLAGS) $(relro-LDFLAGS) $(hashstyle-LDFLAGS) \
429               $(addprefix $(csu-objpfx),$(start-installed-name)) \
430               $(+preinit) $(+prector) \
431               $(filter-out $(addprefix $(csu-objpfx),start.o \
432                                                      $(start-installed-name)    )\                         $(+preinit) $(link-extra-libs) \
434                            $(common-objpfx)libc% $(+postinit),$^) \
435               $(link-extra-libs) $(link-libc) $(+postctor) $(+postinit)
436 endif
437 # Command for statically linking programs with the C library.
438 ifndef +link-static
439 +link-static = $(CC) -nostdlib -nostartfiles -static -L/home/admin/gcc -o $@ \            $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F))  \
441               $(addprefix $(csu-objpfx),$(static-start-installed-name)) \
442               $(+preinit) $(+prector) \
443               $(filter-out $(addprefix $(csu-objpfx),start.o \
444                                                      $(start-installed-name)    )\                         $(+preinit) $(link-extra-libs-static) \
446                            $(common-objpfx)libc% $(+postinit),$^) \
447               $(link-extra-libs-static) $(link-libc-static) $(+postctor) $(+    postinit)
 

glibcの構築を継続します

$ make
〜
/usr/binutils/2.21/amd64/bin/amd64-linux-gnu-ld: cannot find -lgcc
/usr/binutils/2.21/amd64/bin/amd64-linux-gnu-ld: cannot find -lgcc_eh
/usr/binutils/2.21/amd64/bin/amd64-linux-gnu-ld: cannot find -lgcc
/usr/binutils/2.21/amd64/bin/amd64-linux-gnu-ld: cannot find -lgcc_eh
collect2: ld はステータス 1 で終了しました
make[2]: *** [/home/admin/glibc-2.9-amd64-build/locale/libBrokenLocale.so] エラ
ー 1
make[2]: Leaving directory `/home/admin/glibc-2.9/locale'
make[1]: *** [locale/others] エラー 2
make[1]: Leaving directory `/home/admin/glibc-2.9'
make: *** [all] エラー 2
 

またもや libgcc.a と libgcc_eh.a が見付からないエラーです
ともかくビルドを継続させるために 必要な箇所に暫定 gccライブラリパスを指定していきます

$ ../glibc-2.9/Makeconfig
 

LDFLAGSに -L/home/admin/gcc を設定します

410
411 relro-LDFLAGS = -Wl,-z,relro
412 LDFLAGS.so += $(relro-LDFLAGS) -L/home/admin/gcc
413 LDFLAGS-rtld += $(relro-LDFLAGS)
414
 

そして再び make

$ make
〜
make[2]: Leaving directory `/home/admin/glibc-2.9/elf'
make[1]: Leaving directory `/home/admin/glibc-2.9'
$
 

おお ついにー glibcのビルドが通ったぞー
喜びもひとしおです

早速インストールしますが 現在のディレクトリは一旦削除します

$ su
# rm -rf /usr/glibc/2.9/amd64
# make install
LANGUAGE=C LC_ALL=C; export LANGUAGE LC_ALL; \
make -r PARALLELMFLAGS="" CVSOPTS="" -C ../glibc-2.9 objdir=`pwd` install
make[1]: Entering directory `/home/admin/glibc-2.9'
./scripts/mkinstalldirs /usr/glibc/2.9/amd64/include
mkdir /usr/glibc/2.9/amd64
mkdir /usr/glibc/2.9/amd64/include
〜
if test -r /usr/glibc/2.9/amd64/include/gnu/stubs-64.h && cmp -s /home/admin/glibc-2.9-amd64-build/stubs.h /usr/glibc/2.9/amd64/include/gnu/stubs-64.h; \
then echo 'stubs.h unchanged'; \
else /bin/install -c -m 644 /home/admin/glibc-2.9-amd64-build/stubs.h /usr/glibc/2.9/amd64/include/gnu/stubs-64.h; fi
rm -f /home/admin/glibc-2.9-amd64-build/stubs.h
make[1]: Leaving directory `/home/admin/glibc-2.9'
#
# exit
$
 

ちなみに 32bit版と異なり 64bit用のライブラリディレクトリ /lib64/ が出来てます

$ ls -l /lib64/
-rwxr-xr-x  1 root root 783038  1月 27 01:19 ld-2.9.so
lrwxrwxrwx  1 root root      9  1月 27 01:20 ld-linux-x86-64.so.2 -> ld-2.9.so
$
 

つまり 64bit環境は 既存の 32bitライブラリと 64bitライブラリを 別ディレクトリに格納する設計です
(64bit環境では 32bitバイナリも実行できるための配慮か? おそらく)

ともかく glibcが完成したので gccもすぐに完成するでしょう
gccの構築を継続します

$ cd ../gcc-4.5.2-amd64-build
$ make
〜
true  DO=all multi-do # make
make[8]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build/amd64-linux-gnu/32/libgomp'
make[7]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build/amd64-linux-gnu/32/libgomp'
make[6]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build/amd64-linux-gnu/32/libgomp'
make[5]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build/amd64-linux-gnu/libgomp'
make[4]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build/amd64-linux-gnu/libgomp'
make[3]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build/amd64-linux-gnu/libgomp'
make[2]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build/amd64-linux-gnu/libgomp'
make[1]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build'
$
 

gccも構築できました
specsに設定している 暫定 gccパス(md_startfile_prefix_1)を削除します

$ vi gcc/specs
 

*endfile: *startfile: を修正し *md_startfile_prefix_1: の設定も空にします

46 
47 *endfile:
48 %{ffast-math|funsafe-math-optimizations:crtfastmath.o%s}    %{mpc32:crtprec32.o%s}    %{mpc64:crtprec64.o%s}    %{mpc80:crtprec80.o%s}    %{shared|pie:crtendS.o%s;:crtend.o%s} %(md_startfile_prefix)crtn.o%s
49 

67 
68 *startfile:
69 %{!shared: %{pg|p|profile:%(md_startfile_prefix)gcrt1.o%s;pie:%(md_startfile_prefix)Scrt1.o%s;:%(md_startfile_prefix)crt1.o%s}}    %(md_startfile_prefix)crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}
70 

124 
125 *md_startfile_prefix_1:
126 
127 
 

gccも 一旦現在のディレクトリを削除して正式にインストールします

$ su
# rm -rf /usr/gcc/4.5.2/amd64
# make install
〜
ldconfig: /usr/gcc/4.5.2/amd64/amd64-linux-gnu/lib/../lib64/libstdc++.so.6.0.14-gdb.py is not an ELF file - it has the wrong magic bytes at the start.

----------------------------------------------------------------------
Libraries have been installed in:
   /usr/gcc/4.5.2/amd64/amd64-linux-gnu/lib/../lib64

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `LD_LIBRARY_PATH' environment variable
     during execution
   - add LIBDIR to the `LD_RUN_PATH' environment variable
     during linking
   - use the `-Wl,-rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to `/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
test -z "/usr/gcc/4.5.2/amd64/share/info" || /bin/mkdir -p "/usr/gcc/4.5.2/amd64/share/info"
 /bin/install -c -m 644 ./libgomp.info '/usr/gcc/4.5.2/amd64/share/info'
 install-info --info-dir='/usr/gcc/4.5.2/amd64/share/info' '/usr/gcc/4.5.2/amd64/share/info/libgomp.info'
test -z "/usr/gcc/4.5.2/amd64/lib/gcc/amd64-linux-gnu/4.5.2/finclude" || /bin/mkdir -p "/usr/gcc/4.5.2/amd64/lib/gcc/amd64-linux-gnu/4.5.2/finclude"
test -z "/usr/gcc/4.5.2/amd64/lib/gcc/amd64-linux-gnu/4.5.2/include" || /bin/mkdir -p "/usr/gcc/4.5.2/amd64/lib/gcc/amd64-linux-gnu/4.5.2/include"
 /bin/install -c -m 644 omp.h '/usr/gcc/4.5.2/amd64/lib/gcc/amd64-linux-gnu/4.5.2/include'
make[4]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build/amd64-linux-gnu/libgomp'
make[3]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build/amd64-linux-gnu/libgomp'
make[2]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build/amd64-linux-gnu/libgomp'
make[1]: Leaving directory `/home/admin/gcc-4.5.2-amd64-build'
#
# cp gcc/specs /usr/gcc/4.5.2/amd64/lib/gcc/amd64-linux-gnu/4.5.2/
# exit
$ cd
$
 

かなり複雑な手順でしたが 64bitクロスコンパイル環境ができました
ここで テストとして Hello World プログラムをコンパイルしてみます

$ vi hello.c
 
#include <stdio.h>

int main ()
{
        printf ( "Hello World!\n" );
        return ( 0 );
}
 

32bit版 と 64bit版 のバイナリが作れることを確認します

$ /usr/gcc/4.5.2/amd64/bin/amd64-linux-gnu-gcc -m32 -o hello32 hello.c
$ /usr/gcc/4.5.2/amd64/bin/amd64-linux-gnu-gcc -o hello64 hello.c
$
$ ./hello32
Hello World!
$ ./hello64
bash: ./hello64: cannot execute binary file
$ file hello*
hello.c: ASCII C program text
hello32: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.0.0, dynamically linked (uses shared libs), not stripped
hello64: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.4.0, dynamically linked (uses shared libs), not stripped
$ ls -l hello*
-rw-r--r--  1 admin users   82  2月  2 12:02 hello.c
-rwxr-xr-x  1 admin users 7751  2月  2 12:03 hello32
-rwxr-xr-x  1 admin users 9884  2月  2 12:03 hello64
$
 

一応大丈夫でした 上記の確認ポイントは

  • 32bit環境で 64bitバイナリが実行できないこと
  • アーキテクチャが 32bit 64bit 正しく表示されること
  • バイナリファイルのサイズが 数Kバイトであること

特に最後の ファイルサイズですが 数Mバイト以上ある場合
スタティックリンク版のバイナリになっていて gcc もしくは glibc の構築が間違っている可能性が高いです

所々強引な手作業を入れたり かなり複雑な手順となりましたが
ようやくクロスコンパイル環境が作れました

32bit Linux上で 64bit版 Linuxカーネルをコンパイルする

ターゲット環境のマシンの電源が落ちたまま 数週間…経ってしまいました
(早く PhenomII のマシンで遊びたい…)
stage3 まで入っているので あとは カーネルと カーネルモジュールを入れればいいだけです

クロスコンパイル環境がやっと整ったので (その動作確認を兼ねて) 早速 カーネルをビルドしましょう

再度 32bit移行元のマシンで作業を続けます
カーネルのソースは先ほどの章で展開済で /usr/src/linux-2.6.36.3/ にあります

$ /usr/src/linux-2.6.36.3
$ make ARCH=x86_64 menuconfig
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/basic/docproc
  HOSTCC  scripts/basic/hash
  HOSTCC  scripts/kconfig/conf.o
  HOSTCC  scripts/kconfig/kxgettext.o
〜
 

ARCH=x86_64 の指定は必須です
結果下記のような カーネルのコンフィグが出ます
linuxカーネルコンフィグ01
もしくは Xを使っている場合は ARCH=x86_64 make xconfig で GUIのコンフィグ画面が使えます

今回 ハードウェアが PhenomII CPUと マザーボードが GA-880GM-USB3 を意識して
設定ポイントは次のとおりです
linuxカーネルコンフィグ General Setup 1
まず General Setupですが
クロスコンパイルなので Cross-compiler tool prefix を amd64-linux-gnu- と指定します
この指定により amd64-linux-gnu-gcc が利用されます

あと SWAPを使わない方針としたので Support for paging of anonymous memory のチェックを外します
linuxカーネルコンフィグ Processor 1
Processor type and features で AMD CPU系の設定を入れます
Processor family は K8 を選択しました (PhenomIIは 正確には K10ですが選択肢がない)
linuxカーネルコンフィグ Bus options
Bus options では PCI Express support を有効にします
linuxカーネルコンフィグ Executable file formats
IA32 Emulation を有効にすれば 32bitバイナリも実行できそうです
linuxカーネルコンフィグ Device Drivers / SATA and PATA
Device Drivers の中の Serial ATA and Parallel ATA drivers です
SATAを使えるように設定します
linuxカーネルコンフィグ Device Drivers / Network device support
Device Drivers の中の Network device support です
ここだけは 後で再設定します NICのドライバがまだ収録されていないのです
linuxカーネルコンフィグ Device Drivers / Graphics support
Device Drivers の中の Graphics support です
ほとんど未設定です Xクライアントを動かす予定がないためです
Radeon HD 4250 相当のため Xを動かす場合 AMDから X用のドライバを入手する必要あります
linuxカーネルコンフィグ Device Drivers / Sound card support 1
Device Drivers の中の Sound card support です
ALSAを選択して さらにデバイスを指定する必要あります
linuxカーネルコンフィグ Device Drivers / Sound card support 2
さらにその中の PCI sound devices から Intel HD Audio を選択
Realtek の項目を選択します
linuxカーネルコンフィグ Device Drivers / USB support
Device Drivers の中の USB support です
USB3を持っているため USB3.0の項目を選択しておきます
linuxカーネルコンフィグ Device Drivers / Xen driver supoort
Device Drivers の中の Xen driver support です
Xenを使って 仮想環境をそのうち構築したいなぁとか考えているので
それっぽいデバイスを選択してみました
linuxカーネルコンフィグ File systems 1
File systems です
まず ターゲットマシンを ext3 で初期化しているため Ext3 は必須です
後は 用途に応じて必要なファイルシステムを選択します
linuxカーネルコンフィグ File systems 2
File systems の中の Miscellaneous filesystems です
Freebsdのパーティションがあるので UFSを選択しておきます
linuxカーネルコンフィグ File systems 3
File systems の中の Network File Systems です
あると便利な NFSと リモートWindowsのマウントもしたいので CIFSも選択しています
linuxカーネルコンフィグ File systems 4
File systems の中の Partition Types です
UFSを選択しただけでは足りず スライスを認識するために BSD disklabel が必要です
linuxカーネルコンフィグ File systems 5
File systems の中の Native language support です
今回から UFS8 をデフォルトとし UFS8ベースのシステムを構築したいと思ってます
今まで EUC-JPで記録した日本語ファイルがことごとくファイル名が文字化けするので
ファイル名の変換も必要になると思います (大変そう)
linuxカーネルコンフィグ Virtualization
Virtualization の状況です
仮想化を構築したいと考えているため オプションを設定しています
まず Xenを使う予定なので KVMのオプションは不要かもしれません

こんな感じで 設定をすすめたら Exit を選んで保存します

#
# configuration written to .config
#


*** End of Linux kernel configuration.
*** Execute 'make' to build the kernel or try 'make help'.

$
 

カレントディレクトリに .config 隠しファイルが作成されます
これがカーネルのコンフィグ設定ファイルになります 必要に応じてバックアップをとりましょう

ところで NICのドライバが未選択です
チップは Realtek 8111D ですが R8168ドライバが使えるとのことです (Googleによると…)
ドライバは Realtek から直接ダウンロードします
Realtek NICドライバダウンロードページ
ドライバは カーネルと別ディレクトリで カーネルモジュールにコンパイルできますが
今回は カーネルディレクトリに組み込む方法をとりました

手順は以下のとおりです まずダウンロードしたアーカイブを展開します

$ cd drivers/net
$ tar -xjvf ~/r8168-8.021.00.tar.bz2 r8168-8.021.00/src/*.c r8168-8.021.00/src/*.h --strip-path=2
r8168-8.021.00/src/r8168.h
r8168-8.021.00/src/rtl_eeprom.c
r8168-8.021.00/src/r8168_asf.h
r8168-8.021.00/src/rtl_eeprom.h
r8168-8.021.00/src/r8168_asf.c
r8168-8.021.00/src/r8168_n.c
r8168-8.021.00/src/rtltool.c
r8168-8.021.00/src/rtltool.h
 

上記作業により 8つのファイルが展開されています
同じディレクトリにある Kconfigを編集して コンフィグにドライバを追加します

$ vi Kconfig
 

下記の行を追加します R8169 の手前あたりでかまいません
追加内容も R8169を参考にしています

config R8168
        tristate "Realtek 8168 (8111D) gigabit ethernet support"
        depends on PCI
        select CRC32
        select MII
        ---help---
          Say Y here if you have a Realtek 8168 PCI Gigabit Ethernet adapter.

          To compile this driver as a module, choose M here: the module
          will be called r8168.  This is recommended.

config R8168_VLAN
        bool "VLAN support"
        depends on R8168 && VLAN_8021Q
        ---help---
          Say Y here for the r8168 driver to support the functions required
          by the kernel 802.1Q code.

          If in doubt, say Y.
 

Makefileにも追加します 作成すべきターゲットオブジェクトを指定します
これも 同様に r8169.o の手前の行でかまいません

obj-$(CONFIG_R8168) += r8168.o
r8168-objs := r8168_n.o r8168_asf.o rtl_eeprom.o rtltool.o
 

これだけです もう一度 カーネルのコンフィグ画面を開き直します

$ cd -
$ make ARCH=x86_68 menuconfig
 

linuxカーネルコンフィグ Device Drivers / Network device support 2
Device drivers の中の Network device support / Ethernet (1000 Mbit) を選択すると
上記のように R8168 が選択できるようになっています

選択し終えたら Exit して保存します
R8168ドライバは カーネルモジュールの形でなくカーネル組込みとしてビルドすることにしました

カーネルのビルドに入ります

$ make ARCH=x86_68
  CHK     include/linux/version.h
  CHK     include/generated/utsrelease.h
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/basic/docproc
  HOSTCC  scripts/basic/hash
  CC      kernel/bounds.s
  GEN     include/generated/bounds.h
〜
  BUILD   arch/x86/boot/bzImage
Root device is (3, 4)
Setup is 12940 bytes (padded to 13312 bytes).
System is 3490 kB
CRC d5d86061
Kernel: arch/x86/boot/bzImage is ready  (#13)
  Building modules, stage 2.
  MODPOST 14 modules
  CC      arch/x86/kvm/kvm-amd.mod.o
  LD [M]  arch/x86/kvm/kvm-amd.ko
  CC      arch/x86/kvm/kvm.mod.o
  LD [M]  arch/x86/kvm/kvm.ko
  CC      drivers/media/video/cx2341x.mod.o
  LD [M]  drivers/media/video/cx2341x.ko
  CC      drivers/scsi/scsi_wait_scan.mod.o
  LD [M]  drivers/scsi/scsi_wait_scan.ko
  CC      drivers/virtio/virtio.mod.o
  LD [M]  drivers/virtio/virtio.ko
  CC      drivers/virtio/virtio_balloon.mod.o
  LD [M]  drivers/virtio/virtio_balloon.ko
  CC      drivers/virtio/virtio_pci.mod.o
  LD [M]  drivers/virtio/virtio_pci.ko
  CC      drivers/virtio/virtio_ring.mod.o
  LD [M]  drivers/virtio/virtio_ring.ko
  CC      drivers/xen/platform-pci.mod.o
  LD [M]  drivers/xen/platform-pci.ko
  CC      net/8021q/8021q.mod.o
  LD [M]  net/8021q/8021q.ko
  CC      net/ipv4/ip_gre.mod.o
  LD [M]  net/ipv4/ip_gre.ko
  CC      net/ipv4/ipip.mod.o
  LD [M]  net/ipv4/ipip.ko
  CC      net/l2tp/l2tp_core.mod.o
  LD [M]  net/l2tp/l2tp_core.ko
  CC      net/netfilter/xt_mark.mod.o
  LD [M]  net/netfilter/xt_mark.ko
$
 

カーネルと カーネルモジュールまでビルドできました

カーネルで必要なファイルは System.map と arch/x86_64/boot/bzImage の2ファイル
カーネルモジュールは 個々に取り出すのは面倒なため
一旦 現行の 32bitマシンにインストールしておきます

$ su
# make ARCH=x86_64 modules_install
Warning: you may need to install module-init-tools
See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt
  INSTALL arch/x86/kvm/kvm-amd.ko
  INSTALL arch/x86/kvm/kvm.ko
  INSTALL drivers/media/video/cx2341x.ko
  INSTALL drivers/scsi/scsi_wait_scan.ko
  INSTALL drivers/virtio/virtio.ko
  INSTALL drivers/virtio/virtio_balloon.ko
  INSTALL drivers/virtio/virtio_pci.ko
  INSTALL drivers/virtio/virtio_ring.ko
  INSTALL drivers/xen/platform-pci.ko
  INSTALL net/8021q/8021q.ko
  INSTALL net/ipv4/ip_gre.ko
  INSTALL net/ipv4/ipip.ko
  INSTALL net/l2tp/l2tp_core.ko
  INSTALL net/netfilter/xt_mark.ko
  DEPMOD  2.6.36.3
#
 

これでカーネルモジュールは /lib/modules/2.6.36.3/ 配下にコピーされています

カーネルができあがったので 64bit環境に必要なファイルは揃ったことになります
次は いよいよターゲットマシンを起動して 64bit Linux環境が起動するところまで確認します

ターゲット環境に 64bitカーネルをコピーして環境を整える

ターゲット環境へ いよいよインストール作業を再開します
先ほど作成した カーネル と カーネルモジュール を転送するだけです

ターゲット環境をブートするのに DVDの Linux環境を使いたかったが
面倒なところがあったので 結局 インストール済の FreeBSDから起動してしまいました

FreeBSD/amd64 (phenom) (pts/0)

login: admin
Password:
Last login: Thu Feb  3 07:53:55 from 192.168.1.3
Copyright (c) 1992-2010 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
        The Regents of the University of California. All rights reserved.

FreeBSD 8.1-RELEASE (ADMIN) #1: Mon Jan 10 23:39:00 JST 2011

Welcome to FreeBSD!

Before seeking technical support, please use the following resources:

o  Security advisories and updated errata information for all releases are
   at http://www.FreeBSD.org/releases/ - always consult the ERRATA section
   for your release first as it's updated frequently.

o  The Handbook and FAQ documents are at http://www.FreeBSD.org/ and,
   along with the mailing lists, can be searched by going to
   http://www.FreeBSD.org/search/.  If the doc distribution has
   been installed, they're also available formatted in /usr/share/doc.

If you still have a question or problem, please take the output of
`uname -a', along with any relevant error messages, and email it
as a question to the questions@FreeBSD.org mailing list.  If you are
unfamiliar with FreeBSD's directory layout, please refer to the hier(7)
manual page.  If you are not familiar with manual pages, type `man man'.

You may also use sysinstall(8) to re-enter the installation and
configuration utility.  Edit /etc/motd to change this login announcement.

> su
Password:
# mount -t ext2fs /dev/ad4s2 /mnt
#
 

stage3イメージを導入済のパーティションを ext2fs でマウントします
(FreeBSDは ext3をサポートしていないので多少の不安が残ります)

コピー元の 32bit linux環境に戻って転送準備を行います

$ su
# cd /lib/modules
# tar -czf ~/modules.tar.gz 2.6.36.3/
#
 

こんな感じで作られた modules.tar.gz と bzImage と System.map を FreeBSD側に転送して
(FTPなど使ってください)

再び FreeBSDで書き戻す作業を行います

# cd /mnt/boot
# mv ~/System.map System.map-2.6.36.3
# ln -s System.map-2.6.36.3 System.map
# mv ~/bzImage vmlinuz-2.6.36.3
# ln -s vmlinuz-2.6.36.3 vmlinuz
# cd /mnt/lib/modules
# tar -xzf modules.tar.gz
#
# ls /mnt/boot/
.keep                   System.map-2.6.36.3     vmlinuz
System.map              boot                    vmlinuz-2.6.36.3
# ls -R /mnt/lib64/modules/2.6.36.3/
build           kernel          modules.builtin modules.order   source

/mnt/lib64/modules/2.6.36.3/kernel:
arch    drivers net

/mnt/lib64/modules/2.6.36.3/kernel/arch:
x86

/mnt/lib64/modules/2.6.36.3/kernel/arch/x86:
kvm

/mnt/lib64/modules/2.6.36.3/kernel/arch/x86/kvm:
kvm-amd.ko      kvm.ko

/mnt/lib64/modules/2.6.36.3/kernel/drivers:
media   scsi    virtio  xen

/mnt/lib64/modules/2.6.36.3/kernel/drivers/media:
video

/mnt/lib64/modules/2.6.36.3/kernel/drivers/media/video:
cx2341x.ko

/mnt/lib64/modules/2.6.36.3/kernel/drivers/scsi:
scsi_wait_scan.ko

/mnt/lib64/modules/2.6.36.3/kernel/drivers/virtio:
virtio.ko               virtio_pci.ko
virtio_balloon.ko       virtio_ring.ko

/mnt/lib64/modules/2.6.36.3/kernel/drivers/xen:
platform-pci.ko

/mnt/lib64/modules/2.6.36.3/kernel/net:
8021q           ipv4            l2tp            netfilter

/mnt/lib64/modules/2.6.36.3/kernel/net/8021q:
8021q.ko

/mnt/lib64/modules/2.6.36.3/kernel/net/ipv4:
ip_gre.ko       ipip.ko

/mnt/lib64/modules/2.6.36.3/kernel/net/l2tp:
l2tp_core.ko

/mnt/lib64/modules/2.6.36.3/kernel/net/netfilter:
xt_mark.ko
#
 

うまく転送されていることを確認したら
Grub2 の設定も行います 設定ファイルは /boot/grub/grub.cfg です


insmod terminal
insmod gfxterm
insmod vbe
insmod vga
insmod tga

set gfxmode=640x480
set root=(hd0,1,a)

background_image /boot/grub/bg1.tga
set menu_color_normal=white/black
set menu_color_highlight=white/green

set default=1
set timeout=20

terminal gfxterm

menuentry "FreeBSD" {
 set root=(hd0,1,a)
 kfreebsd /boot/loader
}

menuentry "Linux-2.6.36.3" {
 set root=(hd0,2)
 linux /boot/vmlinuz-2.6.36.3 root=0802
}
 

Grubの背景画像に /boot/grub/bg1.tga を指定しました
bg1.tga は 640*480 のTGA形式の画像をあらかじめ準備しておく必要があります
(ただし 検証の環境では背景画像は写りませんでした なんで?)

FreeBSDをリブートして いよいよ Linuxのパーティションをブートします

# cd
# umount /mnt
# shutdown -r now
 

うまく ブートしてきて ログインプロンプトが表示されたら

root
 

と叩いてください パスワードなしでログインできるはずです
ログインできたら手始めに何をしましょうか

次回以降システムをブートしたとき ネットワークが適切に設定され
adminアカウントでリモートから sshログインできるところまでの環境設定を目標とします

Gentooのベースシステムのため 初期設定は Gentoo Linux x86 ハンドブック が参考になります
ます admin アカウントの作成から

# useradd -m -g wheel -G users -s /bin/bash -u 1000 admin
# id admin
uid=1000(admin) gid=10(wheel) groups=10(wheel),100(users)
#
 

ネットワークを初回は 手動で設定します 各自の LANの構成にもよりますが
192.168.1.254 を割り当て デフォルトルートは 192.168.1.1 とします

# ifconfig eth0 192.168.1.254 netmask 255.255.255.0 up
# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 〜  
          inet addr:192.168.1.254  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: 〜/64 Scope:Global
          inet6 addr: fe80::〜/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:809 errors:0 dropped:0 overruns:0 frame:0
          TX packets:627 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:86770 (84.7 KiB)  TX bytes:72918 (71.2 KiB)
          Interrupt:41 Base address:0x6000 
# route add default gw 192.168.1.1
# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.1.0     *               255.255.255.0   U     0      0        0 eth0
loopback        *               255.0.0.0       U     0      0        0 lo
default         192.168.1.1     0.0.0.0         UG    0      0        0 eth0
#
 

NICのドライバもうまく動作しているようです
OCNのプロバイダを使っていて IPv6 のグローバルが割り当てられているのもポイントです
上記の設定がリブート後も有効になるように 各設定ファイルをカスタマイズします

# nano /etc/hosts
 

一番最後の行に 自前のホスト名を設定しておきます

192.168.1.254     phenom phenom.mydomain
 

ホスト名も設定します

# nano /etc/conf.d/hostname
 
# /etc/conf.d/hostname

# Set to the hostname of this machine
HOSTNAME="phenom"
 

NICの設定も設定ファイルに落とし込みます

# nano /etc/conf.d/net
 
# This blank configuration will automatically use DHCP for any net.*
# scripts in /etc/init.d.  To create a more complete configuration,
# please review /etc/conf.d/net.example and save your configuration
# in /etc/conf.d/net (this file:]!).
dns_domain_lo="mydomain"
config_eth0=( "192.168.1.254 netmask 255.255.255.0 brd 192.168.1.255")
routes_eth0=( "default via 192.168.1.1" )
 

最後に遠隔からログインできるように 設定します
Gentooベースのシステムでは SSHが標準で提供されています

# rc-update add sshd default
#
 

これで次回起動から sshdが有効になります
ただし sshdの設定も必要です

# nano /etc/ssh/sshd_config
 

設定を変えた部分のみ抜粋します

Protocol 2,1
RSAAuthentication yes
PubkeyAuthentication no
AuthorizedKeysFile .ssh/authorized_keys
ChallengeResponseAuthentication no
 

RSA鍵認証によるログインをベースとしました
ここから sshdを起動して RSA鍵を作成します

# /etc/init.d/sshd start
 * Caching service dependencies ...                 [ ok ]
 * Generating RSA1-Hostkey...
〜
 * Starting sshd ...                                [ ok ]
#
 

初回稼働のため 自動的に鍵ペアが生成されたようです
それとは関係なく RSA鍵ペアを手動で作成しておきます

# su - admin
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/admin/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/admin/.ssh/id_rsa.
Your public key has been saved in /home/admin/.ssh/id_rsa.pub.
The key fingerprint is:
〜
$
 

これで ~/.ssh/ に id_rsa (秘密鍵) と id_rsa.pub (公開鍵) が作成されました
パスフレーズを空白とすればパスワードなしログインできます
公開鍵は サーバである phenom側に登録します

# cat .ssh/id_rsa.pub >> .ssh/authorized_keys
# chmod 600 .ssh/authorized_keys
#
 

秘密鍵は 何らかの手段で ログイン元である クライアント端末へ運んだ後
他人に中身が見られないように 属性を変えて保存します
(検証環境では FTPを使ってしまいましたが)

$ mv id_rsa .ssh/id_rsa.phenom
$ chmod 600 .ssh/id_rsa.phenom
$
 

64bitサーバ側へログインするときに その秘密鍵を使うように設定します

$ vi .ssh/config
 

下記の行を追加します


Host phenom
 Hostname 192.168.1.254
 Port 22
 User admin
 Identityfile ~/.ssh/id_rsa.phenom
 RSAAuthentication yes
 RhostsAuthentication no
 HostbasedAuthentication no
 PasswordAuthentication no
 Protocol 2,1

 

早速 リモートクライアントから サーバ側へログインしてみましょう

$ ssh phenom
The authenticity of host '192.168.1.254 (192.168.1.254)' can't be established.
RSA key fingerprint is 〜.
Are you sure you want to continue connecting (yes/no)? yes
$
$ uname -a
Linux localhost 2.6.36.3 #13 SMP Fri Feb 18 07:38:05 JST 2011 x86_64 AMD Phenom(tm) II X4 905e Processor AuthenticAMD GNU/Linux
$
 

初回ログインなので fingerprintの確認を求められています 確認できたら yes をタイプします
うまくログインできるようになったら 先ほど作成した鍵ペアは不要なので削除します

$ rm .ssh/id_rsa .ssh/id_rsa.pub
$ su
#
# passwd
New password: 
Retype new password: 
passwd: password updated successfully
#
 

念のために rootにスイッチできるところまで確認し
rootのパスワードを設定します

ターゲットマシンをリブートして ネットワークが再設定され SSHでログインできれば OKです
以上で 64bit Linuxマシンを初期設定して 最小限の設定まで完了しました

ここでは触れませんが 今後ネイティブの 64bitコンパイル環境を整え
自分の好みのソフトウェアでシステムの構築を進めてもよいですし

また Gentooにどっぷり浸かりたいなら Gentoo Linux x86 ハンドブックを読み進めて
ebuildが管理する 無数のパッケージを試すことも自由です

インストール後のglibcの設定

ここでは glibcインストール後に必要になる設定を行います
ロケールとタイムゾーンです これらは glibcに含まれている機能のため再設定が必要となります

まずロケールから 必要なロケールデータは既に glibcに含まれているので必要なデータを展開します

# cd /usr/glibc/2.9/amd64/share/i18n/charmaps/
# ls
ANSI_X3.110-1983.gz    IBM1129.gz        ISO-IR-90.gz
ANSI_X3.4-1968.gz      IBM1132.gz        ISO_10367-BOX.gz
ARMSCII-8.gz           IBM1133.gz        ISO_10646.gz
ASMO_449.gz            IBM1160.gz        ISO_11548-1.gz
BIG5-HKSCS.gz          IBM1161.gz        ISO_2033-1983.gz
BIG5.gz                IBM1162.gz        ISO_5427-EXT.gz
BRF.gz                 IBM1163.gz        ISO_5427.gz
BS_4730.gz             IBM1164.gz        ISO_5428.gz
BS_VIEWDATA.gz         IBM256.gz         ISO_646.BASIC.gz
CP10007.gz             IBM273.gz         ISO_646.IRV.gz
CP1125.gz              IBM274.gz         ISO_6937-2-25.gz
CP1250.gz              IBM275.gz         ISO_6937-2-ADD.gz
CP1251.gz              IBM277.gz         ISO_6937.gz
CP1252.gz              IBM278.gz         ISO_8859-1,GL.gz
CP1253.gz              IBM280.gz         ISO_8859-SUPP.gz
CP1254.gz              IBM281.gz         IT.gz
CP1255.gz              IBM284.gz         JIS_C6220-1969-JP.gz
〜
HP-ROMAN9.gz           ISO-8859-4.gz     T.61-8BIT.gz
HP-THAI8.gz            ISO-8859-5.gz     TCVN5712-1.gz
HP-TURKISH8.gz         ISO-8859-6.gz     TIS-620.gz
IBM037.gz              ISO-8859-7.gz     TSCII.gz
IBM038.gz              ISO-8859-8.gz     UTF-8.gz
IBM1004.gz             ISO-8859-9.gz     VIDEOTEX-SUPPL.gz
IBM1026.gz             ISO-8859-9E.gz    VISCII.gz
IBM1047.gz             ISO-IR-197.gz     WINDOWS-31J.gz
IBM1124.gz             ISO-IR-209.gz
#
 

ここに各国語のロケールデータが収まっています 必要な分だけ解凍しましょう

# gunzip ISO-8859-1
# gunzip UTF-8.gz
 

ロケールをコンパイルする localedef コマンドを使いますが その前にヘルプを確認します

# localedef --help
Usage: localedef [OPTION...] NAME
  or:  localedef [OPTION...] [--add-to-archive|--delete-from-archive] FILE...
  or:  localedef [OPTION...] --list-archive [FILE]
Compile locale specification

 Input Files:
  -f, --charmap=FILE         Symbolic character names defined in FILE
  -i, --inputfile=FILE       Source definitions are found in FILE
  -u, --repertoire-map=FILE  FILE contains mapping from symbolic names to UCS4
                             values

〜

System's directory for character maps :
/usr/glibc/2.9/amd64/share/i18n/charmaps
                       repertoire maps: /usr/glibc/2.9/amd64/share/i18n/repertoiremaps
                       locale path    :
/usr/glibc/2.9/amd64/lib/locale:/usr/glibc/2.9/amd64/share/i18n
For bug reporting instructions, please see:
.
#
 

locale path の欄にロケールデータ格納ディレクトリ /usr/glibc/2.9/amd64/lib/locale
が表示されていますが このディレクトリが存在しないため localedef はエラーを返します
ディレクトリを作成してから 実行しましょう

# mkdir /usr/glibc/2.9/amd64/lib/locale
# localedef -i en_US -f ISO-8859-1 en_US
# localedef -i ja_JP -f UTF-8 ja_JP.UTF-8
# ls -l /usr/glibc/2.9/amd64/lib/locale/
total 1228
-rw-r--r-- 1 root root 1322672 Apr 24 14:47 locale-archive
#
 

locale-archive という単一ファイルに格納される仕組みのようです

では 作成した ja_JP.UTF-8 に切り替えてみましょう
locale -a で ja_JP.UTF-8 の存在を確認した上で
LANG環境変数を設定して localeコマンドで反映させます

# locale -a
C
POSIX
en_US
en_US.iso88591
ja_JP.utf8
# export LANG=ja_JP.utf8
# locale
LANG=ja_JP.utf8
LC_CTYPE="ja_JP.utf8"
LC_NUMERIC="ja_JP.utf8"
LC_TIME="ja_JP.utf8"
LC_COLLATE="ja_JP.utf8"
LC_MONETARY="ja_JP.utf8"
LC_MESSAGES="ja_JP.utf8"
LC_PAPER="ja_JP.utf8"
LC_NAME="ja_JP.utf8"
LC_ADDRESS="ja_JP.utf8"
LC_TELEPHONE="ja_JP.utf8"
LC_MEASUREMENT="ja_JP.utf8"
LC_IDENTIFICATION="ja_JP.utf8"
LC_ALL=
# ls -l /usr/glibc/2.9/amd64/lib/locale/
合計 1228
-rw-r--r-- 1 root root 1322672  4月 24 14:47 locale-archive
#
 

ls の表示も日本語に切り替わっています
後は LANG環境変数が ログイン時に自動設定されるようにしておけばよいだけです

次に タイムゾーンを設定します
タイムゾーン情報は elsie.nci.nih.gov で配布されています
ここの tzdata ファイルをダウンロードしましょう
timezone : elsie.nci.nih.gov
この中から必要なファイルだけ展開します ここでは asia と leapseconds が必要です

$ tar -tzf tzdata2011f.tar.gz
africa
antarctica
asia
australasia
europe
northamerica
southamerica
pacificnew
etcetera
backward
systemv
factory
solar87
solar88
solar89
iso3166.tab
zone.tab
leapseconds
yearistype.sh
$ tar -xzf tzdata2011f.tar.gz asia leapseconds
$
 

leapsecondsは うるう秒を補正する情報です うるう秒が発生する毎に更新されます
zicコマンドでこれらのファイルをコンパイルします

$ su
# zic -d /usr/glibc/2.9/amd64/share/zoneinfo -L leapseconds asia
# ls /usr/glibc/2.9/amd64/share/zoneinfo/
Asia  Europe  Indian  iso3166.tab  zone.tab
#
 

Asia や Indian といったディレクトリが作られています Asia/Tokyo があれば OKです

タイムゾーンの切り替え方ですが 2通りあります
まず TZ環境変数を設定する方法です

# date
2011年  4月 24日 日曜日 16:55:45 UTC
# export TZ=Asia/Tokyo
# date
2011年  4月 25日 月曜日 01:55:34 JST
#
 

9時間ほど進んで 東京のタイムゾーンに切り替わりました

もうひとつの方法は localtime ファイルを作成する方法で
システムデフォルトのタイムゾーンが設定されます

# ln -s /usr/glibc/2.9/amd64/share/zoneinfo/Asia/Tokyo /etc/localtime
#
 

localtime は タイムゾーンファイルへのシンボリックリンクとして作成するのが一般的です

サーバ管理者の仕事としては うるう秒がアナウンスされたときに
あらかじめそれが適用された leapseconds を入手して zicコマンドで反映するだけです

 

FreeBSD8.1 amd64 + grub2 のパッチ

FreeBSD8.1-amd64-release で grub2のインストールに失敗する

バグだそうです

検証環境
CPU PhenomII x4 905e (2.5GHz 4-core)
メモリ DDR3-1066 4GB x 2
HDD SATA 250GB
グラフィック GA-880GM-USB3 (Gigabyte) オンボード
サウンド GA-880GM-USB3 (Gigabyte) オンボード
ネットワーク GA-880GM-USB3 (Gigabyte) オンボード GbE
OS FreeBSD8.1-amd64-release

先日 上記の構成でパソコンを購入して 64bit IPv6 環境を構築しようか という矢先に

# grub-install /dev/ad4
/usr/local/sbin/grub-probe: error: cannot find a device for /boot/grub (is /dev mounted?).
No path or device is specified.
Try `/usr/local/sbin/grub-probe --help' for more information.
Auto-detection of a filesystem module failed.
Please specify the module with the option `--modules' explicitly.
 

のような 謎のエラーでインストールできない
–modulesを指定しても やっぱりエラー

ネットで検索したところ 結局バグだったということで対処方法も記載されていたので備忘録です

バイナリパッケージは 結局バグってるので一旦アンインストールします

# pkg_delete grub2-1.98
 

portsからソースファイルを拾ってきます

# cd /usr/ports/sysutils/grub2
# make fetch
〜
# make extract
〜
#
 

ここで portsで提供されている patch-util-getroot.c パッチを削除 (これが間違ってるらしい)

# rm files/patch-util-getroot.c
 

代わりに files/patch-include-grub-gpt_partition.h を下記の内容で作成
(vi などのエディッタで作成)

--- include/grub/gpt_partition.h.orig   2010-03-06 12:51:37.000000000 -0800
+++ include/grub/gpt_partition.h        2010-10-10 02:57:26.000000000 -0700
@@ -40,6 +40,17 @@
     { 0x74, 0x4e, 0x65, 0x65, 0x64, 0x45, 0x46, 0x49 } \
   }

+#define GRUB_GPT_PARTITION_TYPE_FREEBSD_BOOT \
+  { grub_cpu_to_le32 (0x83BD6B9D), grub_cpu_to_le16 (0x7F41), grub_cpu_to_le16 (0x11DC), \
+    { 0xBE, 0x0B, 0x00, 0x15, 0x60, 0xB8, 0x4F, 0x0F } \
+  }
+
+#define GRUB_GPT_PARTITION_TYPE_SOLARIS_BOOT \
+  { grub_cpu_to_le32 (0x6A82CB45), grub_cpu_to_le16 (0x1DD2), grub_cpu_to_le16 (0x11B2), \
+    { 0x99, 0xA6, 0x08, 0x00, 0x20, 0x73, 0x66, 0x31 } \
+  }
+
+
 struct grub_gpt_header
 {
   grub_uint8_t magic[8];
 

もうひとつ files/patch-util-i386-pc-grub-setup.c を下記の内容で作成

--- util/i386/pc/grub-setup.c.orig      2010-03-06 12:51:37.000000000 -0800
+++ util/i386/pc/grub-setup.c   2010-10-10 02:56:55.000000000 -0700
@@ -38,7 +38,8 @@
 #include <grub/util/getroot.h>

 static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT;
-
+static const grub_gpt_part_type_t grub_gpt_partition_type_freebsd_boot = GRUB_GPT_PARTITION_TYPE_FREEBSD_BOOT;
+static const grub_gpt_part_type_t grub_gpt_partition_type_solaris_boot = GRUB_GPT_PARTITION_TYPE_SOLARIS_BOOT;
 #include <grub_setup_init.h>

 #include <stdio.h>
@@ -138,7 +139,9 @@
       struct grub_gpt_partentry *gptdata = p->data;

       /* If there's an embed region, it is in a dedicated partition.  */
-      if (! memcmp (&gptdata->type, &grub_gpt_partition_type_bios_boot, 16))
+      if (! memcmp (&gptdata->type, &grub_gpt_partition_type_bios_boot, 16) ||
+             ! memcmp (&gptdata->type, &grub_gpt_partition_type_freebsd_boot, 16) ||
+                 ! memcmp (&gptdata->type, &grub_gpt_partition_type_solaris_boot, 16))
        {
          embed_region.start = p->start;
          embed_region.end = p->start + p->len;
 

ビルド インストールします

# make build
〜
# make install

途中で 依存性のある portsのインストールについても聞かれるかもしれません
(とりあえず ハイと答えておく)
一応これで grub2のツール一式はインストールされます

いよいよ grubのセットアップをします

# mkdir /boot/grub
#
 

/boot/grub/grub.cfg を下記の感じで作成します
背景画像の /boot/grub/bg1.tga は必要あれば各自で準備します 640×480 32bit tga画像です

set default=0
set timeout=20

set root=(hd0,1,a)
set gfxmode=640x480
set menu_color_normal=white/black
set menu_color_highlight=white/green

insmod terminal
insmod gfxterm
insmod vbe
insmod tga

terminal gfxterm
background_image (hd0,1,a)/boot/grub/bg1.tga

menuentry "FreeBSD" {
 set root=(hd0,1,a)
 kfreebsd /boot/loader
}
 

/boot/grub/device.map を作成します 次のコマンドで自動生成してくれます

# grub-mkdevicemap
#
 

最後に ハードディスクの MBR(マスターブートレコード)を書き換えます
慎重に!!
ハードディスクの MBRにインストールするのか PBRにインストールするのかは各環境に応じてください

# grub-install /dev/ad4
Installation finished. No error reported.
 

エラーメッセージは出ず 正常に動作したように見えます
(バグの原因はルートデバイス情報を うまく取得できないことによる不具合だったらしい…)
後はシステムをリブートして確認するだけです

ちなみに 検証環境ではうまく GRUBが動作したが
背景画像が表示されず真っ暗でしたー

 

FAT32(VFAT) で 大容量HDDを扱えるか

先日購入した SATA 500GB HDD + SATA+USB変換コネクタ を
FreeBSDノートマシンに使ってましたが FreeBSDが不調になったため HDDを再フォーマットする羽目になりそうです
元の構成
HDD Hitachi Deskstar HDP725050GLA360 (500GB)
SATA〜USB変換 S-ATA⇒USB2.0変換コネクター
商品コード:CDSU2
JANコード:4936014586123
ノートパソコン FMV6266NU3/X(富士通) Pentium2PE 266MHz
OS FreeBSD 5.3-RELEASE
Linuxパソコン 省すペースPC Celeron450MHz
OS Slackware10.0 カーネルだけ 2.6.24 に入れ替え
HDDを UFSフォーマットしたため 今の FreeBSDを Linuxにリプレースできません
(Linuxで UFSを読み込むことはできるが 書き込みについては危険扱いされている)

このように データ保存用のHDDですが OSが変わることで使えなくなるようでは困ります
そこで OSが変わっても HDDを使いつづけられる方法を考えたところ
「FAT32でフォーマットすればよいのでは」 と思い当たりました
FAT32ならば Windows FreeBSD Linux で共通に使えそうです
ただし 500GBのような大容量パーティションを FAT32で扱えるのか検証も含めて確認が必要です

FreeBSDで FAT32フォーマット

  % newfs_msdos /dev/da1s1
 

ところが

  % mount_msdosfs -L ja_JP.eucJP -D CP932 /dev/da1s1 /mnt
  mount_msdosfs: /dev/da1s1: Invalid argument
 

謎のエラーが出ます iconv() ルーチンに渡す -L -D パラメータの不正かと思い

  % mount_msdosfs /dev/da1s1 /mnt
  mount_msdosfs: /dev/da1s1: Invalid argument
 

と 同様な症状です

原因を ググってみたところ 解決策として 2つ紹介されてました

mount_msdosfs モジュールのオプションを書き換える

カーネルのソースコードを一部修正します /usr/src/sys/fs/msdosfs/msdosfs_vfsops.c 380行目付近

 /*
  * Read the boot sector of the filesystem, and then check the
  * boot signature.  If not a dos boot sector then error out.
  *
  * NOTE: 2048 is a maximum sector size in current...
  */
 error = bread(devvp, 0, 2048, NOCRED, &bp);
 

コメントを見ると ファイルシステムの先頭指定セクタ分を読み出して FATかどうかを
判定しているようです ここを 4096 などに書き換えるとうまくいったと報告がありました
ただし 実際 4096 に書き換えてカーネル再構築しても症状は改善されませんでした
(FATの管理テーブルサイズが肥大化してしまっているせいでしょうか)
また 131072のような巨大なサイズを指定すると
mount_msdosfs したときにシステムがハングアップしました

カーネルオプションに options MSDOSFS_LARGE を付与

後から見つけた方法なので まだ試してません 128GB以上の容量を扱えそうな紹介がされてました

FreeBSDでフォーマットされた領域を Linuxでマウントしてみる

USB〜SATA 変換ケーブルを Linuxにそのまま接続 dmesgの応答は以下のとおり

# dmesg
〜
usb 1-2: new full speed USB device using uhci_hcd and address 2
usb 1-2: configuration #1 chosen from 1 choice
 uba: uba1
#
 

fdisk でパーティションテーブル確認

# fdisk /dev/uba
Command (m for help): p

Disk /dev/uba: 500.1 GB, 500107862016 bytes
255 heads, 63 sectors/track, 60801 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/uba1   *           1       60801   488384001    c  W95 FAT32 (LBA)

 

FAT32 500GB はパーティションテーブルでは認識されてます
実際にこのパーティションをマウントしてみたところ

# mount -t vfat -o iocharset=euc-jp,codepage=932 /dev/uba1 /mnt
# df -k | grep uba1
/dev/uba1            487431968        16 487431952   1% /mnt
 

とうまくマウントされているようです ただしファイルを実際に書き込んでないので
現状「未確認」状態とさせていただきます

のように 500GB FAT32 の検証結果をまとめると
FreeBSD Linux-2.6.24 Windows98SE
フォーマット 可能 可能 不可能(128GBまで)
マウント 未確認 可能 未確認
読み書き 未確認 未確認 未確認

なぜ FAT32ではパーティション容量に制限がでるのか

いくつかパーティションの容量を制約する要因があります

OSによる制限

  • Windows9x系 では スキャンディスクの実装上の制限から実質 128GB までが限界
  • Windows2000 WindowsXP では FAT32では 32GB までしかフォーマットできない

クラスタ管理による制限

FATのテーブルサイズに制限がある(かも)しれません
Windowsでフォーマット時 設定される値
FAT32 260MB〜8G 4096 バイト/クラスタ
FAT32 8G〜16G 8192 バイト/クラスタ
FAT32 16G〜32G 16384 バイト/クラスタ
FAT32 32G〜 32768 バイト/クラスタ
となっており 上記の表から推測するに 32768バイト/クラスタ のフォーマットを行っても
64GB位までしか扱えないのではないかと予想されます
実際 FreeBSDで newfs_msdos したときは 500GBを 4096バイト/クラスタ でフォーマットしました
(FATテーブルが肥大化しているような気がする)
また 別HDDですが Windows98SE で 110GBをフォーマットしたときは 32768バイト/クラスタでした

実際に FAT32でのフォーマットは可能でしたが
FreeBSDでのマウントや Windowsでの利用に支障が出ます
128GBを越える FAT32 を FreeBSD Linux Windows で使いまわすのは現実的ではなさそうです

Ext2フォーマットなら 最大 2TBまで扱えるので FreeBSD Linux での利用が可能です
(Windowsはあきらめる) Ext2を利用することにします

便利補助ツール complete (tcsh)

tcshのプログラマブル補完
tcsh の complete コマンドでシェルの補完機能をカスタマイズできるので概要を紹介します通常シェル(bashやtcshなど)では 「第1引数は コマンドを補完」「第2引数以降は ファイルパスを補完」するのが一般的です。 tcshでは complete コマンドによりこの補完動作をカスタマイズできます。
completeコマンドの一般的な書式は以下のとおりです

complete コマンド 補完方式/パターン指定/補完リスト[:補完リストの絞り条件]/[後置文字/]

補完方式 補完を実施するための条件を指定します p(引数の位置) や n(直前の引数のパターン) などが指定可能です
パターン指定 補完方式に対する目的語です pに対しては番号や*で指定します や nに対しては文字列で指定します
補完リスト 実際に補完される候補リストを指定します (文字列 文字列 …) のように直接文字列を指定したり f(ファイルパス) d(ディレクトリパス) u(UNIXアカウント) などの指定が可能です
補完リストの絞り条件 補完リストに対して絞り条件を指定できます 例えば テキストファイルだけを候補にしたいなら *.txtといった書き方です
後置文字 補完が完了した場合に直後に置く文字列です デフォルトは 半角空白 です
complete file 'p/1/f/'
fileコマンドの第1引数にファイルパスが補完されます
complete cd 'p/1/d/'
cdコマンドの第1引数にディレクトリパスが補完されます
complete basecolor 'p/1/(red blue green)/'
basecolorと入力した次のワードが red か blue か green かの候補が補完されるようになります (basecolorというコマンドは存在しません)
complete echo 'p/1/s/'
echoコマンドの第1引数にシェル変数名が補完されます

tcshの場合 補完候補を表示するには Ctrl+D です
completeの設定を解除するには uncomplete コマンド です