Vine Linux 3.1 AMD64化

作成:

私の愛用する Vine Linux には今のところ AMD64 版が用意される気配はないようです。 しかし、せっかく Athlon64 マシンを持っているのだから、 64bitの世界を味わってみたいのが人の常。
すでに AMD64 版が用意されているメジャーディストリビューションを利用すればいいじゃないかとかそういうことはおいておいて、 Vine Linux に 64bit カーネルをインストールすることにチャレンジしてみました。
Workstation に分類するのも変な気がしますがServerに限らないということで、
あと、ここでやってること、実は半分ほどしか理解してないわけで、本当に必要な作業かどうかはっきりしないでやってたりします。 それと、一応私の環境では問題なくいくことを確認しましたが、ほかの環境でどうなるのか全くわかりません。 これみてやってみようって人は自己責任でお願いします。

謝辞

この作業に当たり「2ちゃんねる」の Linux 板の住民の皆さんのアドバイスをもらいました。 特に「AMD 64ビットCPUでLINUXしよう Part2」 の732さんが提供してくれたSlackwareの64bit化手順 ftp://ftp.cs.tohoku-gakuin.ac.jp/pub/Linux/packages/Slackware/TarBall.Linux64/How2Make.amd64 を元に作業を進めさせていただきました。

そのおかげといっては何ですが、 ここでやってること、実は半分ほどしか理解してなかったりします。 本当に必要な作業かどうかはっきりしないでやってたりします。 それと、一応私の環境では問題なく動くことを確認しましたが、 ほかの環境でどうなるのか全くわかりません。 これみてやってみようって人は自己責任でお願いします。
データ消えたぞ(#゚Д゚)ゴルァ!!なんていわれても、( ´_ゝ`)フーンとしかいいようがないので。

前提

Vine Linux 3.1 のインストールCDからフルインストールを選んでインストールした状態から始めました。
作業はシステムへのインストール作業をのぞいて一般ユーザで行います。
作業ディレクトリは ~/work/

本当は Vine Linux をベースに進めるのでrpmベースでやんなきゃいけないんだろうけど、 tar 玉から configure -> make -> make install でやってます。rpm の作り方勉強不足でわからんもんで。
当然のことながらインストールしたパッケージは rpm の管理下から離れますので、 この作業の後で rpm を使おうとしたときに問題が出てくるでしょう。 また、 32bit の環境と 64bit の環境が混在してしまったり、作成した 64bit ライブラリが 32bit ライブラリを上書きしたことによって 既存のソフトが動かなくなることもあるかもしれません。
この作業は確実に環境を壊すものとしてご覧ください。(っていうか、この方法だとすでに Vine Linux じゃなくなってるような・・・)
ところで、頭に AMD64 と書いただけあって、 Athlon64 でやってますが EM64T でもいけるんかな?(どこのソースにもほぼ互換としか書いてないよ~~) あと、この命令セットの総称は x86-64 、 x86_64 、 x64 どれが正しいんでしょうか? それともほかに何かあったっけ?

使用した各ファイル (本家サイトを示してますがringサーバとか kddilabsを使って負荷分散しましょう)

binutils-2.15.94.0.1.tar.bz2
  ftp://ftp.kernel.org/pub/linux/devel/binutils/
binutils-2.15.tar.bz2
  ftp://ftp.gnu.org/gnu/binutils/
gcc-3.4.3.tar.bz2
  ftp://ftp.gnu.org/gnu/gcc/
glibc-2.3.3.tar.bz2
  ftp://ftp.gnu.org/gnu/glibc/
glibc-linuxthreads-2.3.3.tar.bz2
  ftp://ftp.gnu.org/gnu/glibc/
linux-2.6.9.tar.bz2
  ftp://ftp.kernel.org/pub/linux/kernel/
module-init-tools-3.1.tar.bz2
  ftp://ftp.kernel.org/pub/linux/utils/kernel/module-init-tools/
ncurses-5.4.tar.gz
  ftp://ftp.gnu.org/pub/gnu/ncurses/

0. 開発環境のインストール

Vine Linux 3.1 のフルインストールしただけでは開発用パッケージがインストールされていないので、まず、それを用意 (はじめ気づかないで悩んでた、エラーに command not found とかでてるのに(笑))

# apt-get update
# apt-get build-dep binutils gcc glibc kernel

とする、フルインストール直後の状態なら(12/3 現在で) bison dejagnu expect flex gd-devel gettext libpng-devel thread zlib-devel がインストールされる。詳細は知らない。
あと、 kernel の構築で menuconfig するなら ncurses-devel が必要

# apt-get install ncurses-devel

あと、 module-init-tools をビルドするときに docbook2man を要求されるので(あんまり本質じゃないけど)、 docbook-utils をインストール

# apt-get install docbook-utils

これで、 docbook-style-dsssl docbook-utils jadetex tetex-extra がインストールされる。

1. クロスコンパイル環境の構築

1.1 クロスコンパイル用binutilsの準備

ftp://ftp.gnu.org/gnu/binutils/
から適当なのをとってくる
ついでに
ftp://ftp.kernel.org/pub/linux/devel/binutils/
にパッチの当たったさらに新しいバージョンがある。
が、私の環境では binutils-2.15.94.0.1 の x86-64 ネイティブスタティックビルドに失敗した。理由不明。

x86-64向けのバイナリを吐くようにビルドする。 インストール先は ~/work/cross

$ tar xvjf binutils-2.15.94.0.1.tar.bz2
$ mkdir binutils-cross
$ cd binutils-cross
$ ../binutils-2.15.94.0.1/configure\
	 --host=i686-pc-linux-gnu\
	 --target=x86_64-unknown-linux-gnu\
	 --prefix=$HOME/work/cross
$ make
$ make install

ここで、 --prefix ってのはインストール先ディレクトリを指す。 失敗してもできる限りシステムに影響が出ないように一般ユーザの作業領域で作業する。

1.2 クロスコンパイル用 gcc の準備

ftp://ftp.gnu.org/gnu/gcc/ から適当なのをとってくる
カーネルのビルドに必要なのはC言語のコンパイラだけなので現時点では gcc-core でも可、 実際にビルドする言語は configure オプションで設定できるのでオールインワンパッケージの gcc-<バージョン>.tar.bz2 でもいい。 tar.gz と tar.bz2 があるが圧縮方法の違いだけっぽい。
こいつのビルドに先ほど作った binutils が必要なのでパスを通しておく&インクルードディレクトリにリンクを張る。

$ export PATH=$HOME/work/cross/bin:$PATH
$ ( cd $HOME/work/cross/x86_64-unknown-linux-gnu; ln -s /usr/include )
$ tar xvjf gcc-3.4.3.tar.bz2
$ mkdir gcc-cross
$ cd gcc-cross
$ ../gcc-3.4.3/configure\
	 --enable-__cxa_atexit\
	 --enable-languages=c\
	 --disable-shared\
	 --host=i686-pc-linux-gnu\
	 --target=x86_64-unknown-linux-gnu\
	 --prefix=$HOME/work/cross
$ make
$ make install

これで、クロスビルド環境が一通りできあがり。

2. カーネル(仮)構築

ftp://ftp.kernel.org/pub/linux/kernel/ から適当なパッケージをとってくる

$ tar xvjf linux-2.6.9.tar.bz2
$ cd linux-2.6.9

Makefile を編集、 Makefile の頭に

EXTRAVERSION =

ってところがあるので、自分の好きなサブバージョン名をつける、私は -amd64-0 とした。

EXTRAVERSION = -amd64-0

クロスコンパイルの設定をする。 Makefile に

ARCH           ?= $(SUBARCH)
CROSS_COMPILE  ?=

ってところがあるので

ARCH		?= x86_64
CROSS_COMPILE	?= $(HOME)/work/cross/bin/x86_64-unknown-linux-gnu-

と書き換える。 $(HOME) は直書きしてください /home/hogehoge とか。

あとは、 make menuconfig とかして適当にコンフィグ、ただし Loadable Module support はオフにしておく、 (モジュールのロードに x84-64 ネイティブのユーティリティが必要らしい)
このカーネルは x86-64 ネイティブの環境を整備するまでの一時的なものです。 設定はほとんどそのままで問題ないと思います。あえていえば NIC のドライバぐらいは組み込んどいた方がいいかも。 あと、マルチメディア系など必要のないオプションをはずしておけばコンパイルが速い。

$ make
$ make install

lilo.conf がないとエラー出すけど放置
lilo を使うなら lilo.conf を編集して新しいカーネルが起動できるようにする。
grub なら特に必要ないが、 /boot/grub/grub.conf に追加しておくのもあり。

ではリブート

3. x86-64 環境の整備

ここまでうまくいっていればあっさりと 64bit カーネルで起動します。 ただし、カーネル以外全部がまだ 32bit バイナリなので注意。

/usr/src/linux のリンクを新しいカーネルソースへ書き換え、
ヘッダファイル群の参照先が変わる。
一部カーネルソースのリンクを書き換えただけではうまくいかない部分があるので、さらに /usr/include に入ってリンクを張る。

$ cd /usr/src
$ rm linux
$ ln -s $HOME/work/linux-2.6.9 linux
$ cd linux/include
$ cd /usr/include/
$ ln -s ../src/linux/include/asm-generic

4. x86-64 ネイティブの開発環境整備(第一段階)

4.1 glibcのスタティックビルド

ftp://ftp.gnu.org/gnu/glibc/ から適当なバージョンのをとってくる。
ついでに同じバージョンの glibc-linuxthreads ってのも取ってくる。
これはアドオンパッケージではあるが事実上必須パッケージらしい、詳しいことは知らん。
32bit 環境で作ったクロスコンパイラを使って glibc をビルドします。
PATHにクロスコンパイルツールのディレクトリを追加、 CCにクロスコンパイラを指定

$ tar xvjf glibc-2.3.3.tar.bz2
$ cd glibc-static
$ export PATH=$HOME/work/cross/bin:$PATH
$ export CC=$HOME/work/cross/bin/x86_64-unknown-linux-gnu-gcc
$ export ac_cv_type_long_double=no
$ ../glibc-2.3.3/configure\
	 --disable-shared\
	 --disable-profile\
	 --enable-add-ons=linuxthreads\
	 --prefix=/usr
$ make gnulib=-lgcc
$ make install

ac_cv_type_long_double=no ってしてるのは

$ checking size of long double... configure: error: cannot compute sizeof (long double), 77

とかっていうエラーの対策
gnulib=-lgcc ってのは

/x86_64-unknown-linux-gnu/bin/ld: cannot find -lgcc_eh

とかっていうエラーの対策
終わったら、一時的に使用した環境変数を取り消しておく

$ unset ac_cv_type_long_double

4.2 binutils のスタティックビルド

ネイティブの binutils をビルドします。 2.15.94.0.1 ではビルドに失敗し解決できなかったので、 2.15を使っています。(だれかおせーて)
先ほど作った glibc をクロスコンパイラが利用できるように /usr/lib64 へのリンクを張っておく。
glibcの続きなら必要ないが、必要なら環境変数も設定してから開始。

$ ( cd $HOME/work/cross/x86_64-unknown-linux-gnu; ln -s /usr/lib64 lib64 )
$ mkdir binutils-static
$ cd binutils-static
$ export PATH=$HOME/work/cross/bin:$PATH
$ export CC=$HOME/work/cross/bin/x86_64-unknown-linux-gnu-gcc
$ ../binutils-2.15/configure --disable-shared  --prefix=/usr
$ make
$ make install

4.3 gcc のスタティックビルド

binutils と同様に gcc もビルド

$ mkdir gcc-static
$ cd gcc-static
$ export PATH=$HOME/work/cross/bin:$PATH
$ export CC=$HOME/work/cross/bin/x86_64-unknown-linux-gnu-gcc
$ ../gcc-3.4.3/configure\
	 --enable-__cxa_atexit\
	 --enable-languages=c\
	 --disable-shared\
	 --prefix=/usr
$ make
$ make install

5. x86-64 ネイティブの開発環境整備(第二段階)

5.1 glibc のネイティブビルド

ネイティブのビルド環境が整ったところで、 glibc のビルドを行います。
ここからは先ほどビルドした binutils、gcc を利用しますので、 PATH を戻しておきます。
しかし、 gcc-3.4.x の最適化にはバグがあるらしく、 うまくいかないので CFLAGS を指定して一部の最適化を抑制します。 意味はわかってない。

$ mkdir glibc-partial
$ cd glibc-partial
$ export CFLAGS="-O2 -fno-unit-at-a-time"
$ ../glibc-2.3.3/configure\
	 --enable-add-ons=linuxthreads\
	 --prefix=/usr
$ make gnulib=-lgcc
$ make install

終わったらCFLAGSを消す

$ unset CFLAGS

5.2 binutils のネイティブビルド

binutils も同様にビルド
しかし、 これをインストールするとローダブルモジュール(名前記録忘れ)がロードできないってエラーがでるので、 make install する前に LD_LIBRARY_PATH を設定しておく。

$ mkdir binutils-native
$ cd binutils-native
$ ../binutils-2.15.94.0.1/configure\
	 --enable-shared\
	 --prefix=/usr
$ make
$ export LD_LIBRARY_PATH=/usr/lib
$ make install

5.3 gcc のネイティブビルド

gcc も同様にビルド

$ mkdir gcc-native
$ cd gcc-native
$ ../gcc-3.4.3/configure\
	 --enable-__cxa_atexit\
	 --enable-languages=c\
	 --prefix=/usr
$ make
$ make install

6. x86-64 ネイティブの開発環境整備(第三段階)

6.1 glibcのネイティブビルド

シェアドライブラリを使ったビルド環境ができあがったら、 再度 glibc をビルド、前回と同様に最適化抑制フラグを設定

$ mkdir glibc-native
$ cd glibc-native
$ export CFLAGS="-O2 -fno-unit-at-a-time"
$ ../glibc-2.3.3/configure\
	 --enable-add-ons=linuxthreads\
	 --prefix=/usr
$ make
$ make install
$ unset CFLAGS

6.2 gcc のネイティブビルド

最後に、 gcc, g++ をビルド

$ mkdir gcc-native2
$ cd gcc-native2
$ ../gcc-3.4.3/configure\
	 --enable-__cxa_atexit\
	 --enable-languages=c,c++\
	 --prefix=/usr
$ make
$ make install

7. ローダブルモジュール付きカーネルが利用できるようにする

7.1 module-init-toolsのビルド

ftp://ftp.kernel.org/pub/linux/utils/kernel/module-init-tools/ から適当なのをとってくる。
modprove とか、 insmod とかローダブルモジュールを扱うパッケージです。

$ tar xvjf module-init-tools-3.1.tar.bz2
$ mkdir module
$ cd module
$ ../module-init-tools-3.1/configure --prefix=/
$ make
$ make install

7.2 ncursesのビルド

ftp://ftp.gnu.org/pub/gnu/ncurses/ から適当なのをとってくる。
本質的ではないが、カーネルのコンフィギュレーションで make menuconfig するときに要求される。 これは32bit環境でインストールしたやつではだめみたいなので、この環境用のをビルドします。
$ tar xvzf ncurses-5.4.tar.gz
$ mkdir ncurses
$ cd ncurses
$ ../ncurses-5.4/configure --prefix=/usr
$ make
$ make install

8. カーネル(真)の構築

ここまできたらやっとこさローダブルモジュール付きのカーネルが構築できます。 クロスビルドしたときの Makefile の設定を元に戻して、

$ make menuconfig
$ make
$ make install
$ make modules_install

これで Vine Linux 3.1 for AMD64 の基礎が完成!?
後はいろいろなパッケージを 64bit で再構築・・・

終わってからやったこと

#include <stdio.h>
main(){
  printf("size of short     = %d bits\n", sizeof(short) * 8);
  printf("size of int       = %d bits\n", sizeof(int) * 8);
  printf("size of long      = %d bits\n", sizeof(long) * 8);
  printf("size of long long = %d bits\n", sizeof(long long) * 8);
  printf("size of void *    = %d bits\n", sizeof(void *) * 8);
}

ってなファイルを作ってコンパイル&実行
32bit 環境では当然

size of short     = 16 bits
size of int       = 32 bits
size of long      = 32 bits
size of long long = 64 bits
size of void *    = 32 bits

ってなるわけだが、 64bit 環境では

size of short     = 16 bits
size of int       = 32 bits
size of long      = 64 bits
size of long long = 64 bits
size of void *    = 64 bits

うぉぉぉぉぉぉ!! void * が 64bit ~~~
さらに long も 64bit !! (こっちはコンパイラ依存か?)

詰まらんことしかやってませんな。

あと、この作業を通して改めて思ったこと。
Athlon64 ってコンパイルはえぇぇ~~