いものやま。

雑多な知識の寄せ集め

MacでQEMUのビルドをしてみた。

最近、『30日でできる! OS自作入門』を読んでる。

この本自体はだいぶ昔に買っていたんだけど、分厚いので完全に積読になってた。
ただ、毎度おなじみのhontoで検索してみたら、電子書籍版が出てて、これなら手軽に読めるなとポチり。
ちょうどキャンペーンをやっていたので、かなりお得だったし。

で、この本ではPC/AT互換機で動くOSを実際に作っていくんだけど、使っているのはMacだし、フロッピーディスクからの起動を想定しているので、実機を用意するのはちょっと面倒。
ということで、仮想環境で試してみようかなと。

Macで使える仮想環境としては、QEMUの他にも、無料のVirtualBoxや、有料のParallels DesktopVMware Fusionなどもある。
ただ、仕事で今後QEMUと関わってくる機会が増えそうなので、せっかくだからQEMUをインストールしてみることにした。

大まかな流れ

QEMUの公式ページを見てみると、Macの場合はHomebrewを使えば簡単にインストール出来るみたい。
ただ、せっかくなので、ソースからビルドしてみようかなと。
ページを見る限り、普通に./configureしてmakeすればいいだけのようだったから。

ただ、当然というか、実際にはこんな簡単にはいかなくて。

具体的には、以下のような手順が必要だった:

  1. autotoolsのビルド
    1. autoconfのビルド
    2. automakeのビルド
    3. libtoolsのビルド
  2. pkg-configのビルド
  3. glibのビルド
    1. libffiのビルド
    2. gettextのビルド
    3. libpcreのビルド
    4. glibのビルド
  4. QEMUのビルド

すごく大変だった・・・

autotoolsのビルド

まずはautotoolsのビルドから。

UNIX系だと、ビルドするときにtarボールをダウンロードしてきて解凍し、./configureしてmakeするのが定番だけど、この仕組みを支えているのがautotools。
具体的には、このconfigureスクリプトを設定ファイルから生成してくれたりする。

もちろん、普通は生成済みのconfigureスクリプトがtarボールには入っているので、このautotoolsを普通のユーザが使うことは基本的にはない。
けど、QEMUのGitリポジトリの場合、その下に他のGitリポジトリをサブモジュールとして取り込んでいるようなので、そのサブのリポジトリでのconfigureスクリプトを生成するのに必要っぽい。

ちなみに、autotoolsにもGitリポジトリはあるんだけど、configureスクリプトは入ってない。
じゃあ、どうやってビルドするのかといえば、autotoolsを使ってconfigureスクリプトを作るw
卵が先か、鶏が先かw

まぁ、こういう開発ツールの根幹になるツールには、よくあること。
Cコンパイラとかもそうだし。

ということで、素直にtarボールをダウンロードしてきて、ビルドする。

autoconf

まずはautoconfから。

Autoconf - GNU Project - Free Software Foundation

FTPからtarボールをダウンロードしてきて、普通にビルド。

$ tar zxvf autoconf-2.69.tar.gz
$ cd autoconf-2.69
$ ./configure
$ make
$ sudo make install

automake

続いて、automake。

Automake - GNU Project - Free Software Foundation

これも同じ。

$ tar zxvf automake-1.15.tar.gz
$ cd automake-1.15
$ ./configure
$ make
$ sudo make install

libtools

最後にlibtools

GNU Libtool - GNU Project - Free Software Foundation

$ tar zxvf libtool-2.4.6.tar.gz
$ cd libtool-2.4.6
$ ./configure
$ make
$ sudo make install

簡単w

pkg-configのビルド

autotoolsのビルドが出来たら、次はpkg-configのビルド。

pkg-config

このツールは、configureスクリプトを走らせときに、ライブラリの情報を得るのに使われるツール。

ただ、実はここでも循環した依存関係が存在していて、pkg-configを動かすには後述のglibが必要なんだけど、glibのビルドにはpkg-configが必要というw

この循環依存を断ち切る一つの方法としては、あらかじめビルドされたglibをインストールしておいて、それでpkg-configをビルドするという方法が考えられる。
ただ、それでは面倒なので、pkg-configのtarボールの中には、最近の安定版のglibのコピー(のおそらく一部だけ)が入っていて、configureで指定すれば、このglibを使ってビルドが出来るようになっている。

tarボールをダウンロードしてきたら、以下のようにすればいい:

$ tar zxvf pkg-config-0.29.2.tar.gz
$ cd pkg-config-0.29.2
$ ./configure --with-internal-glib
$ make
$ sudo make install

これでOK。

ちなみに、QEMUのビルドではこうやってビルドしたpkg-configで十分なんだけど、もし後からインストールしたglibを使うようにしたいなら、--with-internal-glibの指定を外して、もう一回ビルドし直した方がいいのかもしれない。
GCCのビルドで、まず最小限のGCCを作った後、そのGCCでCライブラリを作った後、フルのGCCを作るというのに似てるかも)
(動的リンクなら大丈夫?)

glibのビルド

次はglibのビルド。

正直、これが一番大変だった・・・
というのも、依存しているライブラリが多いから。

glibはGTK+ツールキットの根っことなる機能を提供しているライブラリで、CocoaでいうFoundationフレームワークのようなもの。(のはず)
そんな根っことなるライブラリが、他のいろいろなライブラリに依存してるのもどうなんだと思うんだけど・・・

libffiのビルド

まずはlibffiのビルドから。

libffi

libffiは、ある言語から他の言語で書かれたライブラリを呼び出したりするのに使われるライブラリ。

ビルドは普通。

$ tar zxvf libffi-3.2.1.tar.gz
$ cd libffi-3.2.1
$ ./configure
$ make
$ sudo make install

gettextのビルド

続いて、gettextのビルド。

gettext - GNU Project - Free Software Foundation (FSF)

gettextは多言語化に使われるライブラリ。

これもビルドは普通。

$ tar zxvf gettext-0.19.8.1.tar.gz
$ cd gettext-0.19.8.1
$ ./configure
$ make
$ sudo make install

libpcreのビルド

次はlibpcreのビルド。

これはPerl正規表現と同じ文法の正規表現を提供するライブラリ。
なんでこんなのが必要なんだろう・・・

このビルドは以下のとおり:

$ tar zxvf pcre-8.40.tar.gz
$ cd pcre-8.40
$ ./configure --enable-unicode-properties
$ make
$ sudo make install

気をつけないといけないのが、configureスクリプト--enable-unicode-propertiesというオプションを指定していること。

最初、configureスクリプトのヘルプを見て、--enable-utfというオプションはつけてビルドしたんだけど(これがないとUTF8/16/32のサポートも有効にならない)、それだけだと不足で、glibのビルドに失敗した。
--enable-unicode-propertiesというオプションをつけておけば、--enable-utfも有効になり、glibのビルドも問題なくなる。

glibのビルド

ここまでやって、やっとglibのビルド。

まず、glibのtarボールを落とすのが大変w
もちろん、Gitリポジトリをcloneしてビルドしてもいいんだけど、configureスクリプトが入ってないので、ちょっと面倒。

自分は以下のFTPから落としてきた:

https://ftp.gnome.org/pub/gnome/sources/glib/2.52/

ビルドは以下のとおり:

$ tar Jxvf glib-2.52.1.tar.xz
$ cd glib-2.52.1
$ CFLAGS="-I/usr/local/include -L/usr/local/lib" ./configure
$ make
$ sudo make install

ちなみに、configureの前でCFLAGSを指定しているのは、こうしないとgettextの提供するヘッダファイルとライブラリをなぜか見つけられなかったから。

長かったけど、これでやっとglibのビルドが完了。

QEMUのビルド

残すはQEMUのビルドのみ。

まずは、QEMUのGitリポジトリをローカルにcloneしてくる:

$ git clone git://git.qemu-project.org/qemu.git
$ cd qemu
$ git submodule init
$ git submodule update --recursive

前述したとおり、QEMUのGitリポジトリは、その下に他のGitリポジトリをサブモジュールとして取り込んでいるので、その初期化とアップデートも行なっている。

これであとは./configureしてmakeすれば終わり・・・ならよかったんだけど、そうは問屋が卸さず。

Macの場合、pixmanというサブモジュールに問題があるらしく、makeすると以下のエラーが出てしまった:

pixman-mmx.c:100:20: error: constraint 'K' expects an integer constant expression

調べて見ると、以下のスレッドで議論がされていて、よく分からないけど、なんとなく新しいバージョンにすれば直ってそう。

The Pixman October 2015 Archive by thread

ということで、pixmanを0.33.6のブランチに切り替えてみた。

$ git checkout topic/local_bugfix   # 適当な名前でバグフィクス用のブランチを用意
$ cd pixman
$ git checkout pixman-0.33.6
$ cd ..
$ git add pixman
$ git commit
$ git submodule update

そのあと、./configuremake

これで先ほどのエラーは出なくなったんだけど、これでも以下のエラーが出た:

Undefined symbols for architecture x86_64:
  "_prng_state", referenced from:
      _main in region-test.o
  "_prng_state_data", referenced from:
      _main in region-test.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

ただ、これは調べてみるとテストコードの問題らしく、とりあえず実害はないっぽい。
なので、エラーが起きた後にtouchコマンドで仮のファイルを作ってやれば、ビルドがスキップされて大丈夫とのこと。
(なぜかエラーが起きる前にtouchコマンドを使うとファイルが削除されてしまったので、エラーが起きた後にやった方が確実かもしれない)

$ touch pixman/test/region-test
$ touch pixman/test/scaling-helpers-test

(参考: Qemu 2.3.0 released! - Fun with virtualizationFun with virtualization

これでQEMUのビルドも完了!

ちなみに、デフォルトの設定でビルドすると、全部のアーキテクチャがビルドされる。
なので、特定のアーキテクチャだけビルドしたい場合には、configureスクリプト--target-list=LISTオプションを指定してやるといい。
(LISTをビルドしたいアーキテクチャにする)

利用可能なアーキテクチャは、./configure --helpをやれば見ることが出来る:

$ ./configure --help

Usage: configure [options]

(省略)

  --target-list=LIST       set target list (default: build everything)
                           Available targets: aarch64-softmmu alpha-softmmu 
                           arm-softmmu cris-softmmu i386-softmmu lm32-softmmu 
                           m68k-softmmu microblaze-softmmu microblazeel-softmmu 
                           mips-softmmu mips64-softmmu mips64el-softmmu 
                           mipsel-softmmu moxie-softmmu nios2-softmmu 
                           or1k-softmmu ppc-softmmu ppc64-softmmu 
                           ppcemb-softmmu s390x-softmmu sh4-softmmu 
                           sh4eb-softmmu sparc-softmmu sparc64-softmmu 
                           tricore-softmmu unicore32-softmmu x86_64-softmmu 
                           xtensa-softmmu xtensaeb-softmmu

(以下略)

動作確認

これでやっとQEMUのビルドも終わったので、動作確認をしたいところ。

以下のページでテスト用のイメージがいくつか用意されていた:

Testing/System Images - QEMU

なので、それを使って動作確認してみた:

とりあえずlinux-0.2.img.bz2というイメージをダウンロードしてきて解凍し、以下のようにして動作確認:

$ qemu-system-i386 linux-0.2.img

すると、次のような画面が現れる:

f:id:yamaimo0625:20170417000323p:plain

これで問題なく動作してることが確認できた。

ちなみに、ウィンドウ内をクリックするとマウスの制御がゲスト側に取られてしまうけど、Ctrl+Alt(Macの場合、Ctrl+Option)を押すことで、マウスの制御はホスト側に戻ってきてくれる。
終わらせるときは、メニューから終了を選べばOK。

今日はここまで!