Debian上にOSvビルド環境を構築してみた
Debian上にOSvビルド環境を構築してみた
OSvもくもく会#1 〜OSvで遊んでみよう〜 の予習を兼ねて、Debian上にOSvビルド環境を構築してみました。
OSv
OSvはマイナビニュースで説明されているように、「クラウドオペレーティングシステム」という位置づけになっています。https://github.com/cloudius-systems/osvの説明では、Debian,Fedoraでのビルド環境構築が可能なようであり、今回はそれを参照しながら作業してみました。
- OSv
- OSvの説明(マイナビニュース)
ビルド環境構築の流れ
以下の順番でビルド環境の構築を進めます。
Debian(amd64)のインストール
- Debian 7.5.0(amd64)で仮想マシンを作成する
- ディスクサイズは10Gでギリギリ足りるようです
- amd64でインストールする点に注意する
- ftp://ftp.jaist.ac.jp/debian-cd/7.5.0/amd64/iso-cd/debian-7.5.0-amd64-netinst.iso
- 割り当てるメモリは3GB(3072MB)を設定する
- OSvで2GBのメモリを想定しているため
gcc-4.9.0のビルド・インストール
OSvのビルドにはgcc-4.8.0以上が必要ですが、Debianのパッケージはgcc-4.7が最新版であり、必要なgccバージョンを満たしていません。このため、gcc-4.9.0(2014/04/22にリリース)を自分でビルドします。
自分でビルドするものについては既存の環境と混ぜこぜにしたくないので、/opt以下にインストールする方針で作業を進めます。
Prerequisites for GCCにはgccのビルドに必要なツール、ライブラリが記載されています。gccのビルドの前に以下のライブラリをビルドします。バージョンの指定がある点に注意が必要です。
- GNU Multiple Precision Library (GMP) version 4.3.2 (or later)
- MPFR Library version 2.4.2 (or later)
- MPC Library version 0.8.1 (or later)
- ISL Library version 0.12.2
- CLooG 0.18.1
gccビルドに関連するパッケージのインストール
まずはgccのビルド作業に必要となるツールをパッケージからインストールします。
$ sudo sudo apt-get install lzip # .lz形式のgmp配布物の展開に必要 $ sudo sudo apt-get install autogen # autogenが無いとgccのビルドでエラーになる
ソースファイルの準備(ダウンロード)
インストール前に決めておくこと
- インストール先は/opt/gcc-4.9.0とする。
必要なライブラリのビルドとインストール
必要なソースアーカイブはあらかじめダウンロードしておきます。
$ ls Download/ cloog-0.18.1.tar.gz gmp-6.0.0a.tar.lz mpc-1.0.2.tar.gz gcc-4.9.0.tar.gz isl-0.12.2.tar.bz2 mpfr-3.1.2.tar.gz
ライブラリパスの設定
インストール先を/opt/gcc-4.9.0に想定しているので、作業前にライブラリパスを設定してしまいます。
後から設定しようとすると忘れてしまいがちで、make checkでテストがFAILしてからライブラリパスが未設定だったことに気づいたりします...。
$ export LD_LIBRARY_PATH=/opt/gcc-4.9.0/lib:$LD_LIBRARY_PATH $ export LD_RUN_PATH=/opt/gcc-4.9.0/lib:$LD_RUN_PATH
gmpのビルド
gmpのみソースアーカイブがlzip形式のみでの提供になっています。
$ lzip -dc Download/gmp-6.0.0a.tar.lz | tar xvf - $ cd gmp-6.0.0/ $ mkdir build ; cd build $ ../configure --enable-cxx --prefix=/opt/gcc-4.9.0 2>&1 | tee -a _configure.log $ (date ; make ; date) 2>&1 | tee -a _make.log $ (date ; make check ; date) 2>&1 | tee -a _make_check.log $ sudo make install 2>&1 | tee -a _make_install.log
mpfrのビルド
$ tar zxvf Download/mpfr-3.1.2.tar.gz $ cd mpfr-3.1.2/ $ mkdir build ; cd build $ ../configure --prefix=/opt/gcc-4.9.0 \ --with-gmp-include=/opt/gcc-4.9.0/include \ --with-gmp-lib=/opt/gcc-4.9.0/lib \ 2>&1 | tee -a _configure.log $ (date ; make ; date) 2>&1 | tee -a _make.log $ (date ; make check ; date) 2>&1 | tee -a _make_check.log $ sudo make install 2>&1 | tee -a _make_install.log
mpcのビルド
$ tar zxvf Download/mpc-1.0.2.tar.gz $ cd mpc-1.0.2/ $ mkdir build ; cd build $ ../configure --prefix=/opt/gcc-4.9.0 \ --with-gmp-include=/opt/gcc-4.9.0/include \ --with-gmp-lib=/opt/gcc-4.9.0/lib \ --with-mpfr-include=/opt/gcc-4.9.0/include \ --with-mpfr-lib=/opt/gcc-4.9.0/lib \ 2>&1 | tee -a _configure.log $ (date ; make ; date) 2>&1 | tee -a _make.log $ (date ; make check ; date) 2>&1 | tee -a _make_check.log $ sudo make install 2>&1 | tee -a _make_install.log
islのビルド
$ tar jxvf Download/isl-0.12.2.tar.bz2 $ cd isl-0.12.2 $ mkdir build ; cd build $ ../configure --prefix=/opt/gcc-4.9.0 \ --with-gmp-builddir=/opt/gcc-4.9.0/lib \ CFLAGS="-I/opt/gcc-4.9.0/include" \ LDLAGS="-I/opt/gcc-4.9.0/lib" \ 2>&1 | tee -a _configure.log $ (date ; make ; date) 2>&1 | tee -a _make.log $ (date ; make check ; date) 2>&1 | tee -a _make_check.log $ sudo make install 2>&1 | tee -a _make_install.log
cloogのビルド
$ tar zxvf Download/cloog-0.18.1.tar.gz $ cd cloog-0.18.1 $ mkdir build ; cd build $ ../configure --prefix=/opt/gcc-4.9.0 \ --with-isl=system \ --with-isl-prefix=/opt/gcc-4.9.0 \ --with-gmp=system \ --with-gmp-prefix=/opt/gcc-4.9.0 \ CFLAGS="-I/opt/gcc-4.9.0/include" \ LDLAGS="-I/opt/gcc-4.9.0/lib" \ 2>&1 | tee -a _configure.log $ (date ; make ; date) 2>&1 | tee -a _make.log $ (date ; make check ; date) 2>&1 | tee -a _make_check.log $ sudo make install 2>&1 | tee -a _make_install.log
gcc-4.9.0のビルド・インストール
今回欲しいのはC++コンパイラなので、--enable-languages=c,c++を指定して必要なコンパイラのみビルドします(C言語も不要かもしれません)。
$ tar zxvf Download/gcc-4.9.0.tar.gz $ cd gcc-4.9.0 $ mkdir build ; cd build $ ../configure --prefix=/opt/gcc-4.9.0 \ --disable-multilib \ --program-suffix=-4.9.0 \ --enable-stage1-languages=c,c++ \ --enable-languages=c,c++ \ --disable-isl-version-check \ --with-mpc-include=/opt/gcc-4.9.0/include \ --with-mpc-lib=/opt/gcc-4.9.0/lib \ --with-mpfr-include=/opt/gcc-4.9.0/include \ --with-mpfr-lib=/opt/gcc-4.9.0/lib \ --with-isl-include=/opt/gcc-4.9.0/include \ --with-isl-lib=/opt/gcc-4.9.0/include \ --with-gmp-include=/opt/gcc-4.9.0/include \ --with-gmp-lib=/opt/gcc-4.9.0/lib \ CFLAGS="-I$/opt/gcc-4.9.0/include" \ LDLAGS="-L/opt/gcc-4.9.0/lib -L/usr/lib" \ 2>&1 | tee -a _configure.log $ (date ; make ; date) 2>&1 | tee -a _make.log $ (date ; make check ; date) 2>&1 | tee -a _make_check.log $ sudo make install 2>&1 | tee -a _make_install.log
簡単な動作確認
$ export LD_LIBRARY_PATH=/opt/gcc-4.9.0/lib:$LD_LIBRARY_PATH $ export LD_RUN_PATH=/opt/gcc-4.9.0/lib:$LD_RUN_PATH $ export PATH=/opt/gcc-4.9.0/bin:$PATH $ which gcc-4.9.0 /opt/gcc-4.9.0/bin/gcc-4.9.0 $ which g++-4.9.0 /opt/gcc-4.9.0/bin/g++-4.9.0
$ gcc-4.9.0 --version gcc-4.9.0 (GCC) 4.9.0 Copyright (C) 2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ g++-4.9.0 --version g++-4.9.0 (GCC) 4.9.0 Copyright (C) 2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
qemu-2.0.0のビルド・インストール
OSvのビルド時にqemuの機能を利用しますが、Debianのqemuパッケージだとvirtio-rng-pciなデバイスが利用できないため、ビルドエラーとなります。
https://github.com/cloudius-systems/osv/issues/127を見ると、./configure --enable-virtfsしたqemuを使う方法が紹介されており、これに倣いqemuを自分でビルドします。最初Debianのqemuパッケージと同じバージョンのqemu(1.1.2)をビルドしましたが、そのバージョンではvirtio-rng-pciが提供されていないため、最新版のqemuを使います。
ビルドに必要なパッケージのインストール
$ sudo apt-get install pkg-config $ sudo apt-get install libglib2.0-dev # Development files for the GLib library $ sudo apt-get install libcap-dev $ sudo apt-get install libattr1-dev
libcap-dev,libattr1-devパッケージが無いと、configure --enable-virtfs時に以下のエラーとなります。
VirtFS is supported only on Linux and requires libcap-devel and libattr-devel
$ tar jxvf ./Download/qemu-2.0.0.tar.bz2 $ cd qemu-2.0.0 $ ./configure --prefix=/opt/qemu-2.0.0 \ --target-list=x86_64-softmmu,x86_64-linux-user \ --enable-virtfs \ 2>&1 | tee -a _configure.log $ (date ; make ; date) 2>&1 | tee -a _make.log $ sudo make install 2>&1 | tee -a _make_install.log
インストール後、virtio-rng-pciが使用可能デバイスに含まれていることを確認します。
$ qemu-system-x86_64 -device ? 2>&1 | grep virtio-rng-pci name "virtio-rng-pci", bus PCI
OSvのビルド
環境変数の設定
/opt以下にインストールしたgcc-4.9.0,qemu-2.0.0と必要なライブラリを参照するよう、.bashrc等に以下を追加します。
LD_LIBRARY_PATH=/opt/gcc-4.9.0/lib64:$LD_LIBRARY_PATH LD_LIBRARY_PATH=/opt/gcc-4.9.0/lib:$LD_LIBRARY_PATH export LD_LIBRARY_PATH LD_RUN_PATH=/opt/gcc-4.9.0/lib64:$LD_RUN_PATH LD_RUN_PATH=/opt/gcc-4.9.0/lib:$LD_RUN_PATH export LD_RUN_PATH PATH=/opt/gcc-4.9.0/bin$PATH PATH=/opt/qemu-2.0.0/bin:$PATH export PATH=/opt/gcc-4.9.0/bin:/opt/qemu-2.0.0/bin:$PATH export CXX=/opt/gcc-4.9.0/bin/g++-4.9.0
GitHubからOSvソースコードをclone
OSvのGitHubの手順にしたがいソースコードをcloneします。clone後、"git submodule update"が必要です。
$ git clone https://github.com/cloudius-systems/osv.git $ git submodule update --init --recursive
OSvのビルド
$ cd osv $ (date ; make ; date) 2>&1 | tee -a _make.log
OSv上でHello,Worldを動かす
OSvを実行する前に、kvm.koをロードします(デフォルトではkvm.koがロードされていない)。
$ sudo /sbin/modprobe kvm $ lsmod | grep kvm kvm 287749 0
Hello,world.を動かしてみます。
$ cat apps/java-example/Hello.java public class Hello { public static void main(String[] args) { System.out.println("Hello, World!"); } } $ make image=java-example $ scripts/run.py -e "java.so -cp /java-example Hello" OSv v0.08-60-g8dd67e0 eth0: 192.168.122.15 Hello, World!
ハマりどころ
何もかもが上手く進んだ場合、前述までの手順でOSvのビルドまで行えます、が、OSvのビルドではハマり所がたくさんあります(ありました...)。
何点かハマった点について、エラー内容と解消方法を以下に記載します。
Makeファイルのjar-jarsターゲットの実行でエラーが出る
jar-jarsターゲットの実行で以下のようなエラーが出る場合があります。
$ make ...中略... MVN java-jars [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project cloudius: Fatal error compiling: invalid target release: 1.7 -> [Help 1] [ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch. [ERROR] Re-run Maven using the -X switch to enable full debug logging. [ERROR] [ERROR] For more information about the errors and possible solutions, please read the following articles: [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException make[1]: *** [java-jars] Error 1 make[1]: Leaving directory `/home/fpig/work/osv_buld/osv/build/release' make: *** [all] Error 2
$ make ...中略... MVN java-jars [ERROR] BUILD ERROR make[1]: *** [java-jars] Error 1 make[1]: Leaving directory `/home/fpig/work/osv_buld/osv/build/release' make: *** [all] Error 2
私の環境では、Maven,JDKのバージョンを複数インストールしていたことが原因でした。
$ /usr/share/maven/bin/mvn --version Apache Maven 3.0.4 Maven home: /usr/share/maven Java version: 1.6.0_31, vendor: Sun Microsystems Inc. Java home: /usr/lib/jvm/java-6-openjdk-amd64/jre Default locale: en_US, platform encoding: ANSI_X3.4-1968 OS name: "linux", version: "3.2.0-4-amd64", arch: "amd64", family: "unix" $ /usr/share/maven2/bin/mvn --version Apache Maven 2.2.1 (rdebian-8) Java version: 1.6.0_31 Java home: /usr/lib/jvm/java-6-openjdk-amd64/jre Default locale: en_US, platform encoding: ANSI_X3.4-1968 OS name: "linux" version: "3.2.0-4-amd64" arch: "amd64" Family: "unix"
Maven 3.0.4が使われると思っていましたが、実際はMaven 2.2.1が使われていました。
$ mvn -version Apache Maven 2.2.1 (rdebian-8) Java version: 1.7.0_55 Java home: /usr/lib/jvm/java-7-openjdk-amd64/jre Default locale: en_US, platform encoding: ANSI_X3.4-1968 OS name: "linux" version: "3.2.0-4-amd64" arch: "amd64" Family: "unix"
さっそく切り替えます。
$ sudo update-alternatives --config mvn There are 2 choices for the alternative mvn (providing /usr/bin/mvn). Selection Path Priority Status ------------------------------------------------------------ * 0 /usr/share/maven2/bin/mvn 200 auto mode 1 /usr/share/maven/bin/mvn 150 manual mode 2 /usr/share/maven2/bin/mvn 200 manual mode Press enter to keep the current choice[*], or type selection number: 1 update-alternatives: using /usr/share/maven/bin/mvn to provide /usr/bin/mvn (mvn) in manual mode
これでOK。
$ mvn -version Apache Maven 3.0.4 Maven home: /usr/share/maven Java version: 1.7.0_55, vendor: Oracle Corporation Java home: /usr/lib/jvm/java-7-openjdk-amd64/jre Default locale: en_US, platform encoding: ANSI_X3.4-1968 OS name: "linux", version: "3.2.0-4-amd64", arch: "amd64", family: "unix"
ちなみに、mvn -eで詳細なエラー表示が行えます。Mavenまわりで上記以外のエラーが出た際はbuild.mk内のMVNに-eを追加すると原因切り分けが楽になるかもしれません。
$ man mvn ...中略... -e,--errors Produce execution error messages
JDKについても、私の環境ではこちらも予想と異なるjdkが使われていました。
(あれこれ試行錯誤する中でmaven2やopenjdk-6-jdkとかインストールしたのがマズかったようです...)
$ javac -version javac 1.6.0_31 $ sudo update-alternatives --config javac There are 2 choices for the alternative javac (providing /usr/bin/javac). Selection Path Priority Status ------------------------------------------------------------ * 0 /usr/lib/jvm/java-6-openjdk-amd64/bin/javac 1061 auto mode 1 /usr/lib/jvm/java-6-openjdk-amd64/bin/javac 1061 manual mode 2 /usr/lib/jvm/java-7-openjdk-amd64/bin/javac 1051 manual mode Press enter to keep the current choice[*], or type selection number: 2 update-alternatives: using /usr/lib/jvm/java-7-openjdk-amd64/bin/javac to provide /usr/bin/javac (javac) in manual mode
java,javac共にjava-7-openjdk-amd64を参照することを確認します。
$ java -version java version "1.7.0_55" OpenJDK Runtime Environment (IcedTea 2.4.7) (7u55-2.4.7-1~deb7u1) OpenJDK 64-Bit Server VM (build 24.51-b03, mixed mode) $ javac -version javac 1.7.0_55
"undefined reference to `__cxa_throw_bad_array_new_length'"が発生する
これはエラーメッセージの通り、__cxa_throw_bad_array_new_length()が見つけられないことが原因です。
$ make ...中略... LD loader.elf arch/x64/smp.o: In function `smp_init()': /home/fpig/work/osv_buld/osv/arch/x64/smp.cc:78: undefined reference to `__cxa_throw_bad_array_new_length' core/mempool.o: In function `memory::mark_smp_allocator_intialized::mark_smp_allocator_intialized()': /home/fpig/work/osv_buld/osv/core/mempool.cc:386: undefined reference to `__cxa_throw_bad_array_new_length' make[1]: *** [loader.elf] Error 1 ...中略...
__cxa_throw_bad_array_new_length()は/opt/gcc-4.9.0/lib64/libstdc++.soにあります(前述のgccビルド手順を実施した場合)。
$ for i in `find /opt/gcc-4.9.0/ | grep \\.so$`; do nm $i | grep __cxa_throw_bad_array_new_length if [ $? -eq 0 ]; then echo $i fi done 000000000005d3a0 T __cxa_throw_bad_array_new_length /opt/gcc-4.9.0/lib64/libstdc++.so
build.mkの中でlibstdc++.aの場所を指定しているので、/opt/gcc-4.9.0以下のライブラリを探索するようにbuild.mkを修正します。
$ diff -u build.mk.orig build.mk --- build.mk.orig 2014-05-09 02:53:53.124712117 +0900 +++ build.mk 2014-05-09 08:37:33.570625829 +0900 @@ -784,6 +784,7 @@ objects += $(addprefix fs/, $(fs)) objects += $(addprefix libc/, $(libc)) +gccbase = /opt/gcc-4.9.0 libstdc++.a = $(shell find $(gccbase)/ -name libstdc++.a) libsupc++.a = $(shell find $(gccbase)/ -name libsupc++.a) libgcc_s.a = $(shell find $(gccbase)/ -name libgcc.a | grep -v /32/)
bare.imgの作成時に"qemu-system-x86_64: -device virtio-rng-pci: Parameter 'driver' expects device type"のエラーが出る
$ make ...中略... Creating bare.img as qcow2 /home/fpig/work/osv_buld/osv/scripts/mkzfs.py -o bare.img -d bare.img.d -m /home/fpig/work/osv_buld/osv/build/release/bootfs.manifest qemu-system-x86_64: -device virtio-rng-pci: Parameter 'driver' expects device type QEMU 1.1.2 monitor - type 'help' for more information (qemu) QEMU 1.1.2 monitor - type 'help' for more information (qemu) Traceback (most recent call last): File "/home/fpig/work/osv_buld/osv/scripts/mkzfs.py", line 44, in <module> upload_manifest.upload(osv, manifest, depends) File "/home/fpig/work/osv_buld/osv/scripts/upload_manifest.py", line 62, in upload s.connect(("127.0.0.1", 10000)); File "/usr/lib/python2.7/socket.py", line 224, in meth return getattr(self._sock,name)(*args) socket.error: [Errno 111] Connection refused make[1]: *** [bare.img] Error 1 make[1]: *** Deleting file `bare.img' make[1]: Leaving directory `/home/fpig/work/osv_buld/osv/build/release' make: *** [all] Error 2
これはDebianのqemuパッケージではvirtio-rng-pciが利用できないことが原因です。前述のqemuビルドの手順を実施します。
まとめ
Debian上にOSvのビルド環境を構築し、Hello,Worldまで動かしてみました。ビルド環境構築にはいくつかハマり所があり、以下の点に気をつける必要がありました。
- Debianはamd64版を使用する(i386だとダメ)
- OSvで2GBのメモリを使用するので、ビルド環境のマシンはそれを見越したメモリ量にする
- MavenとJDKは複数バージョンの混在に注意する
- 混在していた場合は、update-alternativesで適切なバージョンを利用するよう設定する
- gccは4.8.0以上を使用する
- gccビルドではconfigure --disable-multilib,--enable-languages=c,c++を忘れずに指定する
参照ドキュメント
gcc4.9のビルド手順を調べるにあたり、以下のWebサイト・blogの内容を参考にさせていただきました。
- Prerequisites for GCC
- さくら VPS 上に gcc4.8 をインストールする方法
- Mac OS X に GCC 4.8 をインストール
- GCC 4.9.0 をビルドした
- DebianにJava7をインストールする
- GNUリンカLDの使い方
- Debian Wheezy build error: qemu-system-x86_64: -device virtio-rng-pci: Parameter 'driver' expects device type #127
- http://gcc.gnu.org/install/prerequisites.html
変更履歴
- 2014/05/17:OSvソースコードのclone手順に抜けがあったため追記しました。