目次


Intel x86 サーバー上で IBM PowerLinux アプリケーションをビルドする方法

IBM Advanced Toolchain for PowerLinux クロスコンパイラーを使用する

Comments

はじめに

x86 サーバー上で実行される Linux アプリケーションを、PowerLinux などの異なるプラットフォームに移植するには、アプリケーションをコンパイルするためのビルド環境を別途構築しなければならないと思っていますか?それが、必ずしもそうではないのです。x86 サーバー上でクロスコンパイラーを使用すれば、異なるプラットフォーム・アーキテクチャー (例えば IBM Power) をターゲットとするアプリケーション・バイナリーをビルドすることができます。クロスコンパイラーは、登場してからもう長い時間が経っています。その用途はほとんどの場合、組み込みシステム用のアプリケーションをビルドすることです。それは、組み込みシステムには、ネイティブ・コンパイラーをサポート可能なオペレーティング・システムを実行するためのリソースが限られているためです。私が初めてクロスコンパイラーを知ったのは、携帯端末向けのプロジェクトに取り組んでいたときのことです。そのときは、x86 ワークステーションでソース・コードを作成してコンパイルし、生成されたバイナリーをシリアル通信接続で端末にロードしました。最近では、開発中のロボットのサーボ・モーターを制御するための単純なアプリケーションをビルドするためにクロスコンパイラーを使用しています。私個人の経験談はこれくらいにして、早速本題に移りましょう。

この記事では、IBM Advance Toolchain for PowerLinux に組み込まれているクロスコンパイラーについて説明します。これ以降、IBM Advance Toolchain for PowerLinux を Toolchain と称することにします。Toolchain は、IBM の最新の Power ハードウェアの機能を Linux 上で利用することを可能にする、オープンソースの開発ツールとランタイム・ライブラリーの集まりです。Toolchain は、それ自身に必要なすべてのものが揃っているため、システムのツールチェーンには依存しません。Toolchain は、Linux ディストリビューションのデフォルト・ツールチェーンを上書きしないようにするために、/opt にインストールされます。この記事を執筆している時点での Toolchain の最新リリースには、以下のパッケージの最新安定版が含まれています。

  • GNU Compiler Collection (gcc、g++、および gfortran)。これに加え、サポートされている IBM POWER プロセッサー用に個別に最適化された gcc ランタイム・ライブラリーもあります。
  • GNU C ライブラリー (glibc)。サポートされている POWER プロセッサー用に個別に最適化されています。
  • GNU バイナリー・ユーティリティー (binutils)
  • 10 進浮動小数点ライブラリー (libdfp)。IBM POWER7 および IBM POWER8 プロセッサー・ベースのサーバー用のハードウェア DFP サポートによって最適化されています。
  • AUXV ライブラリー (libauxv)
  • GNU デバッガー (gdb)
  • パフォーマンス分析ツール (oprofile、valgrind、itrace)
  • マルチコアを有効利用するためのライブラリー (Intel TBB、Userspace RCU)。バージョン 5.0-3 から追加されています。
  • 各種のサポート・ライブラリー (libhugetlbfs、zlib など)

Toolchain のダウンロードについては、この記事の終わりに記載されている「参考文献」セクションを参照してください。

この記事では、主に Toolchain クロスコンパイラーに焦点をあて、Toolchain クロスコンパイラーを使用して、x86 サーバー上で PowerLinux 用のバイナリー実行ファイルをビルドする方法を説明します。さらに、以下の質問に対する答えも明らかにします。

  • x86 プラットフォーム上でクロスコンパイルされてビルドされたアプリケーションは、PowerLinux 上でネイティブにビルドされたバイナリーに匹敵するパフォーマンスを実現できるのか?
  • x86 プラットフォーム上でクロスコンパイルされたアプリケーションとライブラリーをビルドした場合、PowerLinux 上でビルドされたアプリケーションと同じアプリケーション・バイナリー機能を持つのか?
  • x86 プラットフォーム上でクロスコンパイルされてビルドされたアプリケーションは、PowerLinux 上でネイティブにデバッグできるバイナリーを生成するのか?

以上の質問に答えるために、よく使われている 2 つのオープンソース・アプリケーション、PostgreSQL と Apache httpd サーバーを使用して、PostgreSQL と Apache httpd のそれぞれのソース・ディストリビューションを、x86 サーバー上では Toolchain クロスコンパイラーを使用してビルドし、PowerLinux サーバー上ではネイティブにビルドしました。そうして作成したアプリケーションを PowerLinux サーバー上のそれぞれに異なるインストール・ディレクトリーにインストールして実行し、これらのアプリケーションに対していくつかのベンチマーク・ツールを実行して、それぞれのパフォーマンスと機能を互いに比較しました。

以降のセクションで、テストの結果を説明します。テストを再現してみたいという読者のために、環境の構成に関する情報と、どのようにしてアプリケーションをビルドしたかについて、それぞれ「環境と構成」セクション、「Toolchain を使用してアプリケーションをビルドする」セクションで説明します。

結果

アプリケーションをテストするために、一般に入手できるいくつかのベンチマーク・ツールを使用しました。PostgreSQL 用には、GitHub から入手できる pgbench-tools を使用しました。このツールでは、PostgreSQL ソース・ディストリビューションに付属の pgbench ユーティリティーが使用されます。Apache httpd 用には、Apache httpd ソース・ディストリビューションに付属の ab (apache bench) ツールを使用しました。pgbench-tools のダウンロード情報については、この記事の終わりにある「参考文献」セクションを参照してください。

PostgreSQL のテストのセットアップと結果

x86 サーバー上でクロスコンパイラーを使って PostgreSQL アプリケーションをビルドした後、バイナリー一式を PowerLinux サーバーに移しました。デフォルトの構成ファイルに対しては、以下の変更を行いました。

Postgresql.conf
max_connections = 4096
shared_buffers = 2048MB
synchronous_commit = off
checkpoint_segments = 3
checkpoint_timeout = 5min

PowerLinux システム設定の kernel.sem の値を変更します。

sysctl.conf
kernel.sem = 250     32000   32   12288

pgbench-tools の構成ファイルを変更します。

MAX_WORKERS="32".

pgbench-tools の Web サイトで説明されている以下のステップに従って、PostgreSQL テストを実行しました。

  1. pgbench データベースと results データベースを作成します。
  2. results データベースを初期化します。
  3. 説明付きのテスト・セットを作成します。
  4. runset スクリプトを使用してテストを実行します。
  5. テスト結果をまとめて POST 送信します。

上記のステップを実行するために使用したコマンドに関する具体的な情報は、pgbench-tools の README を参照してください。

PostgreSQL の結果 (クロスコンパイルされたバージョン)

以下に、Power サーバー上で、クロスコンパイルされたバイナリーに対して pgbench-tools を実行した結果を示します。

図 1. クロスコンパイルされた PostgreSQL バイナリーでスケーリング・ファクターを変化させたときのグラフ
図 1. クロスコンパイルされた PostgreSQL バイナリーでスケーリング・ファクターを変化させたときのグラフ
図 1. クロスコンパイルされた PostgreSQL バイナリーでスケーリング・ファクターを変化させたときのグラフ

このスケーリング・ファクターを変化させたときのグラフには、データベースのサイズが大きくなったときの 1 秒あたりのトランザション数の変化のプロットが示されています。緑の線は、データベースのサイズ (MB 単位) を表し、赤の線は、1 秒あたりのトランザクション数 (TPS) を表します。このグラフが示していることは、データベースのサイズが大きくなるにつれ、1 秒あたりのトランザクション数が減少することです。

図 2. クロスコンパイルされた PostgreSQL バイナリーのスケーラビリティーのグラフ
図 2. クロスコンパイルされた PostgreSQL バイナリーのスケーラビリティーのグラフ
図 2. クロスコンパイルされた PostgreSQL バイナリーのスケーラビリティーのグラフ

図 2 に、スケーラビリティーのグラフを示します。ここには、クライアント数が増えるにつれて、1 秒あたりのトランザクション数も増えることが示されています。

PostgreSQL の結果 (ネイティブにコンパイルされたバージョン)

ネイティブにコンパイルされたバイナリーをテストするときには、クロスコンパイルされた PostgreSQL とまったく同じ構成設定とデータベース・ロケーション (/tmp/usr/local/pgsql/data) を使用しました。データベースに不要なデータが入っていないことを確実にするために、テストを開始する前に、以下のように results データベースと pgbench データベースの両方をドロップしました。

postgresql# drop database results;
DROP DATABASE

postgresql# drop database pgbench;
DROP DATABASE

スケーリング・ファクターを変化させたときのグラフとスケーラビリティーのグラフをそれぞれ図 3図 4 に示します。前述のように、スケーリング・ファクターを変化させたときのグラフには、データベースのサイズが大きくなったときの 1 秒あたりのトランザション数の変化のプロットが示されています。緑の線は、データベースのサイズ (MB 単位) を表し、赤の線は、1 秒あたりのトランザクション数 (TPS) を表します。

図 3. ネイティブにビルドされた PostgreSQL バイナリーのスケーリング・ファクターを変化させたときのグラフ
図 3. ネイティブにビルドされた PostgreSQL バイナリーのスケーリング・ファクターを変化させたときのグラフ
図 3. ネイティブにビルドされた PostgreSQL バイナリーのスケーリング・ファクターを変化させたときのグラフ

図 4 のスケーラビリティーのグラフには、クライアントの数が増えるにつれ、1 秒あたりのトランザション数が増加することが示されています。

図 4. ネイティブにビルドされた PostgreSQL バイナリーのスケーラビリティーのグラフ
図 4. ネイティブにビルドされた PostgreSQL バイナリーのスケーラビリティーのグラフ
図 4. ネイティブにビルドされた PostgreSQL バイナリーのスケーラビリティーのグラフ

ご覧のように、クロスコンパイルされたバイナリーのグラフは、ネイティブにコンパイルされたバイナリーのグラフとまったく同じです。この単純なテストが示していることは、x86 サーバー上でクロスコンパイルすると、ネイティブにコードをコンパイルしたときと同じパフォーマンス特性を持つバイナリーを生成することができるということです。

Apache httpd のテストのセットアップと結果

Apache httpd をテストするために使用したのは、Apache httpd ソース・ディストリビューションに付属の ab というベンチマーク・ツールです。PostgreSQL と同じように、Toolchain クロスコンパイラーを使用して Apache httpd をビルドし、そのバイナリーを PowerLinux サーバーに移しました。デフォルトの httpd.conf ファイルに変更を加えて、htdocs ディレクトリーがローカルの documents ディレクトリーを指すようにしました。これ以外は変更せずに、デフォルト値のままにしました。

ab ツールを実行するために使用したコマンドラインと引数は以下のとおりです。

# ./ab -n 500000 -c 100 -g out1.data http://9.3.4.241/

上記のコマンドを 3 回実行し、それぞれの出力を out1.data、out2.data、out3.data に書き込みました。その後、以下のように gnuplot ユーティリティーで benchmark.tpl ファイル内のパラメーターを指定して、これらのファイルをグラフに描画しました。

# gnuplot benchmark.tpl
benchmark.tpl # output as png image set terminal png
# save file to "benchmark.png" set output "benchmark.png"
# graph title set title "Benchmark for 9.3.4.241"
# aspect ratio for image size set size 1,1
# enable grid on y-axis set grid y
# x-axis label set xlabel "Request"
# y-axis label set ylabel "Response Time (ms)"
# plot data using column 10 with smooth sbezier lines plot "out1.data" using 10 smooth sbezier with lines title "Benchmark 1:", \ "out2.data" using 10 smooth sbezier with lines title "Benchmark 2:", \ "out3.data" using 10 smooth sbezier with lines title "Benchmark 3:"

Apache ベンチマーク・ツールの詳細については、この記事の終わりにある「参考文献」セクションを参照してください。

Apache httpd の結果 (ネイティブにコンパイルされたバージョンと、クロスコンパイルされたバージョン)

gnuplot ユーティリティーは、それぞれのテストごとに benchmark.png という名前のファイルを生成します。これらの画像は、任意の画像ビューアーで表示することができます。ネイティブにコンパイルされたバージョンの結果の画像と、クロスコンパイルされたバージョンの結果の画像を、それぞれ図 5図 6 に示します。

図 5 は、ネイティブにコンパイルされた httpd のグラフです。

図 5. ネイティブにコンパイルされた httpd の応答時間のグラフ
図 5. ネイティブにコンパイルされた httpd の応答時間のグラフ
図 5. ネイティブにコンパイルされた httpd の応答時間のグラフ

図 6 は、クロスコンパイルされた httpd のグラフです。

図 6. クロスコンパイルされた httpd の応答時間のグラフ
図 6. クロスコンパイルされた httpd の応答時間のグラフ
図 6. クロスコンパイルされた httpd の応答時間のグラフ

両方のグラフに示されているパフォーマンス特性は非常によく似ています。ぜひ、さまざまな Web 文書とデータを使って、さらにテストしてみてください。

機能およびデバッグについての調査結果

開発者は Toolchain クロスコンパイラーの使用に関して、パフォーマンスの他にも質問があることでしょう。このセクションでは、機能に関する質問と、クロスコンパイルされたバイナリーをデバッグできるかどうかという質問に答えます。これらの質問は、具体的には以下のとおりです。

  • クロスコンパイラーでビルドされたライブラリーは、ネイティブにビルドされた実行ファイルと機能的に互換するのか?
  • クロスコンパイルされたバイナリーを PowerLinux サーバー上でデバッグすることはできるのか?

クロスコンパイラーを使用した以下の 2 つの単純なケースが、これらの質問に答える上で役に立ちます。

  • 使用ケース 1: ネイティブにビルドされた httpd の 1 つ以上の共有ライブラリーを、Toolchain クロスコンパイラーを使用してビルドした共有ライブラリーに置き換えます。その上で、ネイティブにビルドされた httpd が引き続き正常に機能するかどうかを調べます。
  • 使用ケース 2: PowerLinux サーバー上で、実行中のプロセスにデバッガーをアタッチします。このプロセスは、x86 サーバー上でクロスコンパイルされてビルドされたバイナリー実行ファイルです。ブレークポイントを設定し、ソース・ディレクトリーを設定した後、ある関数のソース・リストを表示します。

使用ケース 1: 機能テスト

使用ケース 1 では、以下の手順に従いました。

  1. ネイティブにビルドされた httpd を /home/usr/local にインストールします。
  2. /home/use/local/bin/httpd バイナリーに対して ldd ユーティリティーを実行し、このバイナリーの共有ライブラリーへの依存関係を表示します。libaprutil-1.so.0 と libapr-1.so.0 は、home/usr/local/lib に格納されていることに注意してください。ネイティブにコンパイルされたライブラリーのうち、この 2 つが httpd に必要なライブラリーです。
[root@localhost lib]# ldd ../../bin/httpd
    linux-vdso64.so.1 => (0x00000fffa1140000)
    libaprutil-1.so.0 => /home/usr/local/apr/lib/libaprutil-1.so.0 (0x00000fffa10c0000)
    libapr-1.so.0 => /home/usr/local/apr/lib/libapr-1.so.0 (0x00000fffa1060000)
    librt.so.1 => /opt/at7.0-5-rc1/lib64/power7/librt.so.1 (0x00000fffa1040000)
    libcrypt.so.1 => /opt/at7.0-5-rc1/lib64/power7/libcrypt.so.1 (0x00000fffa0ff0000)
    libpthread.so.0 => /opt/at7.0-5-rc1/lib64/power7/libpthread.so.0 (0x00000fffa0fb0000)
    libdl.so.2 => /opt/at7.0-5-rc1/lib64/power7/libdl.so.2 (0x00000fffa0f90000)
    libc.so.6 => /opt/at7.0-5-rc1/lib64/power7/libc.so.6 (0x00000fffa0da0000)
    /opt/at7.0-5-rc1/lib64/ld64.so.1 => /lib64/ld64.so.1 (0x00000000267a0000)
  1. 共有ライブラリー libaprutil-1.so.0 および libapr-1.so.0 を削除します。
  2. クロスコンパイルされたライブラリー libaprutil-1.so.0 と libapr-1.so.0 を /tmp/usr/local/lib にコピーします。
  3. /tmp/usr/local/lib を LD_LIBRARY_PATH に含めます。
# cd /home/usr/local/apr/lib 
# rm libaprutil-1.so.0 
# rm libapr-1.so.0 
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/tmp/usr/local/lib
  1. ldd ユーティリティーを再度実行して、今は httpd が /tmp/usr/local/lib 内のライブラリーを使用するようになっていることを確認します。
[root@localhost lib]# ldd ../../bin/httpd
    linux-vdso64.so.1 => (0x00000fff951a0000)
    libaprutil-1.so.0 => /tmp/usr/local/apr/lib/libaprutil-1.so.0 (0x00000fff95150000)
    libapr-1.so.0 => /tmp/usr/local/apr/lib/libapr-1.so.0 (0x00000fff950f0000)
    librt.so.1 => /opt/at7.0-5-rc1/lib64/power7/librt.so.1 (0x00000fff950d0000)
    libcrypt.so.1 => /opt/at7.0-5-rc1/lib64/power7/libcrypt.so.1 (0x00000fff95080000)
    libpthread.so.0 =>/opt/at7.0-5-rc1/lib64/power7/libpthread.so.0 (0x00000fff95040000)
    libdl.so.2 => /opt/at7.0-5-rc1/lib64/power7/libdl.so.2 (0x00000fff95020000)
    libc.so.6 => /opt/at7.0-5-rc1/lib64/power7/libc.so.6 (0x00000fff94e30000)
    libexpat.so.0 => /tmp/usr/local/apr/lib/libexpat.so.0 (0x00000fff94df0000)
    /opt/at7.0-5-rc1/lib64/ld64.so.1 => /lib64/ld64.so.1 (0x0000000022730000)
  1. アプリケーションを起動して、正常なアプリケーションとして実行されて機能するかどうか確認します。
# cd /home/usr/local/bin 
# ./apachectl start 
# ps 窶兎f | grep http
root 11022 1 0 15:41 ? 00:00:00 /home/usr/local/bin/httpd -k start
daemon 11023 11022 0 15:41 ? 00:00:00 /home/usr/local/bin/httpd -k start
daemon 11024 11022 0 15:41 ? 00:00:00 /home/usr/local/bin/httpd -k start
daemon 11025 11022 0 15:41 ? 00:00:00 /home/usr/local/bin/httpd -k start
daemon 11111 11022 0 15:41 ? 00:00:00 /home/usr/local/bin/httpd -k start
  1. ブラウザーで httpd プロセスを実行中の PowerLinux サーバーにアクセスし、以下のメッセージがブラウザーに表示されることを確認します。

「It works!」

このシナリオでは、ネイティブにコンパイルされたバイナリーに、クロスコンパイルされたライブラリーを混在させました。クロスコンパイルされたライブラリーは、ppc64 アーキテクチャー・オプションを指定してビルドされています。この使用ケースから、クロスコンパイルされたライブラリーとネイティブにコンパイルされた実行ファイルを PowerLinux サーバー上で混在させて使用できることが証明されました。

使用ケース 2: デバッグ

2 番目の使用ケースでは、クロスコンパイルされた実行ファイルを PowerLinux サーバー上でデバッグできることを証明したいと思います。使用ケース 2 で従った手順は以下のとおりです。

  1. gdb を使用して、httpd プロセスにアタッチします。使用する httpd のバージョンが、Toolchain クロスコンパイラーによって生成され、x86 プラットフォーム上でビルドされたものであることを確認してください。
[root@localhost ~]# gdb attach 25412 
GNU gdb (GDB) 7.6.50.20130722-cvs
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "powerpc64-linux". 
…
(gdb)
  1. ソース・パスのディレクトリーを、ソース・ディストリビューションが格納されているディレクトリーに設定します。
(gdb) set directories /home/ProjectToolchainPLCompile/apr-1.5.1
(gdb) where #0 0x00000fff7cb676f8 in ___newselect_nocancel () at ../sysdeps/unix/syscall-template.S:81 #1 0x00000fff7cd38274 in apr_sleep (t=<optimized out>) at time/unix/time.c:246 #2 0x0000000010034220 in ap_wait_or_timeout (status=0xfffeaa1e704, exitcode=0xfffeaa1e700, ret=0xfffeaa1e6e0, p=0x1003d0c6138, s=<optimized out>) at mpm_common.c:195 #3 0x0000000010079238 in server_main_loop (remaining_children_to_start=<optimized out>) at worker.c:1654 #4 worker_run (_pconf=<optimized out>, plog=<optimized out>, s=<optimized out>) at worker.c:1823 #5 0x0000000010033430 in ap_run_mpm (pconf=0x1003d0c6138, plog=0x1003d0f3378, s=0x1003d0ef4c0) at mpm_common.c:96 #6 0x000000001002a5d8 in main (argc=3, argv=0xfffeaa1ee28) at main.c:777
  1. 現在プログラムが停止している場所の表示を、1 つ上のレベルの関数に上げて apr_sleep が表示されるようにします。
(gdb) up 
#1 0x00000fff7cd38274 in apr_sleep (t=<optimized out>) at time/unix/time.c:246
246        select(0, NULL, NULL, NULL, &tv);
  1. apr_sleep のソース・コードをリスト表示します。
(gdb) list
241       delay(t/1000); 
242    #else 
243       struct timeval tv; 
244       tv.tv_usec = t % APR_USEC_PER_SEC; 
245       tv.tv_sec = t / APR_USEC_PER_SEC; 
246       select(0, NULL, NULL, NULL, &tv); 
247    #endif 
248    } 
249 
250    #ifdef OS2
  1. httpd プロセスからデタッチします。
(gdb) detach 
Detaching from program: /tmp/usr/local/bin/httpd, process 25412
(gdb) quit

リモートからのデバッグ

Toolchain には gdbserver プログラムも含まれています。このプログラムにより、開発者はリモート gdb セッションからアプリケーションに接続することができます。PowerLinux サーバー上で gdbserver プログラムを呼び出す際には、必ず Toolchain に含まれる gdbserver プログラムを使用するようにしてください。私の環境で、このプログラムがパスに含まれていることを確認するには、以下のようにします。

# type gdbserver
gdbserver is hashed (/opt/at7.0-5-rc1/bin/gdbserver)

以下は、PowerLinux サーバー上で gdbserver プログラムを使用する方法の一例です。この方法で、実行中の httpd プロセスに接続します。

[root@stgisv241 bin]# gdbserver --attach 9.3.4.240:2345 22589 
Attached; pid = 22589
Listening on port 2345

x86 サーバー上で、ローカル・サーバーに置かれている httpd バイナリーに対して powerpc64-linux-gdb プログラムを呼び出します。Toolchain に含まれるバージョンの gdb は、powerpc64-linux-gdb という名前になっていることに注目してください。使用する httpd バイナリーは、PowerLinux サーバー上で実行されるバージョンのクロスコンパイルされたバイナリーと同じものです。

# pwd 
/tmp/usr/local/bin 
[root@stgisv240 bin]# powerpc64-linux-gdb ./httpd 
GNU gdb (GDB) 7.6.50.20130722-cvs 
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it. 
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details. 
This GDB was configured as "--host=i686-linux --target=powerpc64-linux".
Type "show configuration" for configuration details. 
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
.. 
Reading symbols from /tmp/usr/local/bin/httpd...done. 
(gdb)

引き続き同じ x86 gdb セッションで、gdb 内で target コマンドを呼び出します。以下に例を示します。

(gdb) target remote 9.3.4.241:2345
Remote debugging using 9.3.4.241:2345
warning: Could not load shared library symbols for 7 libraries,
    e.g. /opt/at7.0-5-rc1/lib64/power7/librt.so.1. 
Use the "info sharedlibrary" command to see the complete listing.
Do you need "set solib-search-path" or "set sysroot"?
Reading symbols from /tmp/usr/local/apr/lib/libaprutil-1.so.0...done.
Loaded symbols for /tmp/usr/local/apr/lib/libaprutil-1.so.0
Reading symbols from /tmp/usr/local/apr/lib/libexpat.so.0...done.
Loaded symbols for /tmp/usr/local/apr/lib/libexpat.so.0
Reading symbols from /tmp/usr/local/apr/lib/libapr-1.so.0...done.
Loaded symbols for /tmp/usr/local/apr/lib/libapr-1.so.0 
….
Reading symbols from /tmp/usr/local/modules/mod_alias.so...done. 
Loaded symbols for /tmp/usr/local/modules/mod_alias.so
warning: Unable to find dynamic linker breakpoint function. 
GDB will be unable to debug shared library initializers 
and track explicitly loaded dynamic code.
0x00000fffa8fe76f8 in ?? ()
(gdb)

gdb がライブラリーのシンボルを見つけることができないことに関連する警告メッセージがいくつか表示されることに注意してください。gdb コマンド info sharedlibrary を実行すると、gdb がシンボルを読み取れなかったライブラリーを表示することができます。以下に示す出力例に、gdb がシンボルを読み取れなかったライブラリーが示されています。これらのライブラリーはシステムの一部であるため、シンボルをオンにしてライブラリーがコンパイルされているのでなければ、シンボルを読み取れなかったライブラリーについて気にする必要はありません。

(gdb) info sharedlibrary 
From               To                 Syms Read Shared Object Library 
                                      No        linux-vdso64.so.1 
0x00000fffa924ce80 0x00000fffa927e8a8 Yes       /tmp/usr/local/apr/lib/libaprutil-1.s
0x00000fffa91f7940 0x00000fffa922aa18 Yes       /tmp/usr/local/apr/lib/libexpat.so.0
0x00000fffa9192e60 0x00000fffa91ca0b8 Yes       /tmp/usr/local/apr/lib/libapr-1.so.0 
                                      No        /opt/at7.0-5-rc1/lib64/power7/librt.s
                                      No        /opt/at7.0-5-rc1/lib64/power7/libcrypt
                                      No        /opt/at7.0-5-rc1/lib64/power7/libdl.s
                                      No        /opt/at7.0-5-rc1/lib64/power7/libpthre 
                                      No        /opt/at7.0-5-rc1/lib64/power7/libc.so
                                      No        /opt/at7.0-5-rc1/lib64/ld64.so.1
                                      No        /opt/at7.0-5-rc1/lib64/power7/libnss_f
0x00000fffa8ea0c00 0x00000fffa8ea1878 Yes       /tmp/usr/local/modules/mod_authn_file
0x00000fffa8e810a0 0x00000fffa8e82108 Yes       /tmp/usr/local/modules/mod_authn_core.
0x00000fffa8e60da0 0x00000fffa8e61bb0 Yes       /tmp/usr/local/modules/mod_authz_host. 
0x00000fffa8e40f40 0x00000fffa8e41ed0 Yes       /tmp/usr/local/modules/mod_authz_group
0x00000fffa8e208e0 0x00000fffa8e20f18 Yes       /tmp/usr/local/modules/mod_authz_user.
0x00000fffa8e019e0 0x00000fffa8e046d8 Yes       /tmp/usr/local/modules/mod_authz_core.
...

使用ケース 2 から明らかなように、クロスコンパイルされた実行ファイルのデバッグは、ネイティブにコンパイルされた実行ファイルをデバッグする場合と同じように、PowerLinux サーバー上のローカルで行うこともリモートで行うこともできます。また、デバッグ情報を生成するために、-g オプションを指定してバイナリーをコンパイルしたことにも注意してください。

環境と構成

このテスト環境は、IBM Flex System と複数の IBM Flex System x240 コンピュート・ノードおよび IBM POWER7 プロセッサー・ベースの 2 つのノード (1 つは Flex System p260、もう 1 つは Flex System p460) で構成されています。このプロジェクトでは、Flex System x240 コンピュート・ノードのうちの 1 つを使用して Apache httpd と PostgreSQL をクロスコンパイルしています。バイナリーをビルドした後、それらのバイナリーを Flex System p460 コンピュート・ノードに移動しました。図 7 に、IBM Flex System テスト環境の概要図を示します。

図 7. IBM Flex System テスト環境
図 7. IBM Flex System テスト環境
図 7. IBM Flex System テスト環境

以下に、システム構成、オペレーティング・システムのレベル、システムのセットアップに関するその他の情報を記載します。

Flex System x240 コンピュート・ノード

バイナリーのクロスコンパイルに使用する Intel ノードには、Power バイナリーをビルドできるだけの処理能力とメモリーがあれば十分です。Flex System x240 コンピュート・ノードの構成は以下のとおりです。

  • KVM (Kernel-based Virtual Machine) ハイパーバイザー Red Hat 6.5
    • 32 基のプロセッサー
    • 64 GB のメモリー
    • SAN (Storage Area Network) に接続されたディスク: IBM Storwize V7000
  • KVM ゲスト
    • Red Hat Enterprise Linux 6.5
    • 4 基のプロセッサー
    • 16 GB のメモリー
    • 1 台の virtio ディスク: 100 GB
    • br0 として構成された 1 個のネットワーク・インターフェース・カード (NIC)

その他すべての KVM ゲストは、環境の妨害になる可能性を排除するためにオフにしました。

Flex System p440 コンピュート・ノード

Flex System p440 コンピュート・ノードは複数の論理パーティション (LPAR) からなり、そのうちの 1 つがテスト・サーバーとして構成されています。PowerLinux サーバーの構成は以下のとおりです。

  • IBM PowerVM ゲスト
    • Red Hat Enterprise Linux 6.5
    • 8 基のプロセッサー (専用)
    • 32 GB のメモリー
    • SAN に接続されたディスク: Storwize V7000 (50 GB)
    • 仮想 I/O サーバー (VIOS) を介して共有されるイーサネット・アダプター
  • LPAR 構成
    • 処理モード: 専用
      • 最小プロセッサー数: 8
      • 推奨プロセッサー数: 8
      • 最大プロセッサー数: 32
    • 専用メモリー
      • 最小メモリー容量: 256 MB
      • 推奨メモリー容量: 32 GB
      • 最大メモリー容量: 64 GB
  • 仮想イーサネット・アダプター (VIOS 経由)
    • アダプター ID: 2
    • VLAN ID: 1
    • 仮想サーバーのアクティベーションに必須のアダプターとして選択

以下のさまざまなコマンドも実行しました。

# ppc64_cpu --frequency 
min:    3.56 GHz (cpu 28) 
max:    3.56 GHz (cpu 4) 
avg:    3.56 GHz 
# ppc64_cpu --cores-present Number of cores present = 8
# sysctl.conf kernel.sem = 250     32000   32    12288

Toolchain を使用してアプリケーションをビルドする

通常、オープンソース・ディストリビューションをビルドするプロセスは、反復型のプロセスです。運が良ければ、そのまま何も手を加えずにビルドできる可能性もありますが、残念なことに、ほとんどのオープンソース・ディストリビューションは x86 サーバー上でビルドされているため、IBM Power アーキテクチャーなどの異なるアーキテクチャーを対象にビルドしようとすると問題が発生することがあります。

オープンソース・パッケージを Power 上でビルドして問題が発生した場合に行うべきことは、インターネットで同じような事象を検索し、報告されている問題と発生した問題との間に密接な関わりがあるかどうかを調べることのみです。発生した問題との関連性があれば、ほとんどの場合は、問題の解決方法に関するアドバイスが見つかるはずです。

私の場合は、postgresql のビルドについては、構成スクリプトに適切なパラメーターを指定しただけで問題なく完了しましたが、Apache httpd の場合はそうは行きませんでした。次のセクションで、httpd を Power アーキテクチャー用にビルドするために必要となった修正内容を説明します。

クロスコンパイラーのエクスペリエンス

この記事を執筆しているときに私が使用していたクロスコンパイラーのバージョンは、テスト中に発生したエラーを修正することを目的にビルドされた IBM 社内専用のリリースです。読者の皆さんには、バージョン AT 7.0-5 をダウンロードすることをお勧めします。このバージョンは (この記事の原文公開時点での) 最新のクロスコンパイラーであり、以下に説明するエラーのフィックスが適用されています。

私は apr-1.5.1 ソース・ディストリビューションをクロスコンパイルしようとして、以下のコンパイラー・メッセージを受け取りました。

"sorry - this program has been built without plugin support"

先ほどの私のアドバイスに基づいて、インターネットで参考になるかもしれないヘルプとソリューションを検索すると、コンパイラーは「プラグインを有効」にしてビルドする必要があると述べている関連ページがいくつか見つかりました。このことを Toolchain サポート・グループに報告すると、Toolchain の保守担当者がすぐに対応して、プラグインを有効にしてビルドした修正バージョンを提供してくれました。Toolchain のクロスコンパイラー・バージョンとネイティブ・コンパイラー・バージョンは、どちらもプラグインを有効にしてビルドしなければならないことに注意してください。このように修正されたバージョンの Toolchain を入手した後は、作業を先に進めることができました。

これが、PowerLinux Toolchain での私の最初のエクスペリエンスです。

httpd 2.4.3 のクロスコンパイル

Apache httpd をクロスコンパイルするには、他に 3 つのパッケージが必要でした。それは、apr、apr-util、pcre です。最新のパッケージをダウンロードできる場所を見つけた上で、Toolchain クロスコンパイラーを使用して x86 サーバー上でそれらのパッケージのビルドに取り掛かってください。

apr-1.5.1 をビルドする際に直面した問題は、gen_test_char.o モジュールのビルドにあります。詳細については、「ASF Bugzilla – Bug 51257」を参照してください。私は以下のように Makefile.in ファイルを変更してから、buildconf スクリプトを実行して構成スクリプトの変更を取り込みました。

Makefile.in で行った変更を以下に示します。

[root@stgisv240 apr-1.5.1]# diff -u Makefile.in ../../apr-1.5.1/Makefile.in
--- Makefile.in 2014-03-17 10:10:26.000000000 -0500
+++ ../../apr-1.5.1/Makefile.in 2014-07-03 13:36:11.125013781 -0500
@@ -46,7 +46,6 @@ 
CLEAN_TARGETS = apr-config.out apr.exp exports.c export_vars.c .make.dirs \ build/apr_rules.out tools/gen_test_char@EXEEXT@ \ - tools/gen_test_char.o tools/gen_test_char.lo \ include/private/apr_escape_test_char.h DISTCLEAN_TARGETS = config.cache config.log config.status \ include/apr.h include/arch/unix/apr_private.h \ @@ -132,10 +131,9 @@ make_tools_dir: $(APR_MKDIR) tools
-OBJECTS_gen_test_char = tools/gen_test_char.lo $(LOCAL_LIBS) -tools/gen_test_char.lo: make_tools_dir -tools/gen_test_char@EXEEXT@: $(OBJECTS_gen_test_char) - $(LINK_PROG) $(OBJECTS_gen_test_char) $(ALL_LIBS) +tools/gen_test_char@EXEEXT@: make_tools_dir +tools/gen_test_char@EXEEXT@: tools/gen_test_char.c + $(BUILD_CC) $(CFLAGS_FOR_BUILD) $< -o $@ include/private/apr_escape_test_char.h: tools/gen_test_char@EXEEXT@ $(APR_MKDIR) include/private

Makefile.in ファイルに変更を加えた後、buildconf を実行して新しい構成スクリプトを作成しました。次のパラグラフで、この構成スクリプトに使用した引数と変数について説明します。ちなみに、私が選択した構成スクリプトへの引数は、Apache httpd とそのコンポーネントを ARM などの別のプラットフォームでクロスコンパイルしようと取り組んでいた他の開発者が提案してくれたものです。

x86 サーバー上で apr-1.5.1 コンポーネント用の構成スクリプトを実行したときに使用した引数と環境変数は、以下のとおりです。

# Config script using Power Linux toolchain on x86 
BUILD_CC=gcc
CC_FOR_BUILD=gcc
CC=powerpc64-linux-gcc
CPP=powerpc64-linux-cpp
AS=powerpc64-linux-as
AR=powerpc64-linux-ar 
RANLIB=powerpc64-linux-gcc-ranlib
CXX=powerpc64-linux-c++
LD=powerpc64-linux-ld
STRIP=powerpc64-linux-strip 
export CC CPP AS ASCPP AR RANLIB CXXCPP CXX LD STRIP CFLAGS LDFLAGS CC_FOR_BUILD
./configure --prefix=/tmp/usr/local/apr --host=powerpc64-linux ac_cv_file__dev_zero=no ac_cv_func_setpgrp_void=no apr_cv_tcp_nodelay_with_cork=no ac_cv_sizeof_struct_iovec=1
BUILD_CC=gcc make install

同じディストリビューションに Power サーバー上での修正を加えて使用しました。注意する点として、Power サーバー用の PowerLinux Toolchain は、ネイティブの cpp パッケージと binutils パッケージからインストールされた実行ファイルと同じような名前 (cpp、ld など) の実行ファイルを使用します。そこで、スクリプトの CPP 変数と LD 変数を以下のように変更します。必ず、PATH 環境変数で Power Toolchain のパスが最初に来るようにしてください。

Power サーバー上で apr-1.5.1 コンポーネント用の構成スクリプトを実行したときに使用した引数と環境変数は、以下のとおりです。

# Config script using PowerLinux toolchain on Power 
BUILD_CC=gcc
CC_FOR_BUILD=gcc 
CC=powerpc64-linux-gcc 
CPP=cpp                                   # Note the difference
AS=powerpc64-linux-as
AR=powerpc64-linux-ar 
RANLIB=powerpc64-linux-gcc-ranlib 
CXX=powerpc64-linux-c++ 
LD=ld                                     # Note the difference 
STRIP=powerpc64-linux-strip 
#CFLAGS="-mcpu=440fp -mtune=440fp --sysroot $SYSROOT"
#LDFLAGS=-L$SYSROOT/lib
export CC CPP AS ASCPP AR RANLIB CXXCPP CXX LD STRIP CFLAGS LDFLAGS CC_FOR_BUILD
./configure --prefix=/home/usr/local/apr ac_cv_file__dev_zero=no ac_cv_func_setpgrp_void=no apr_cv_tcp_nodelay_with_cork=no ac_cv_sizeof_struct_iovec=1 ac_cv_struct_rlimit=yes BUILD_CC=gcc make install

x86 サーバー上で apr-util-1.5.3 コンポーネント用の構成スクリプトを実行したときに使用した引数と環境変数は、以下のとおりです。

# Configure script for apr-util-1.5.3 on x86 
BUILD_CC=gcc 
CC_FOR_BUILD=gcc
CC=powerpc64-linux-gcc 
CPP=powerpc64-linux-cpp 
AS=powerpc64-linux-as 
AR=powerpc64-linux-ar
RANLIB=powerpc64-linux-gcc-ranlib
CXX=powerpc64-linux-c++ 
LD=powerpc64-linux-ld
STRIP=powerpc64-linux-strip 
export CC CPP AS ASCPP AR RANLIB CXXCPP CXX LD STRIP CFLAGS LDFLAGS CC_FOR_BUILD
./configure --prefix=/tmp/usr/local/apr --host=powerpc64-linux --with- apr=/tmp/usr/local/apr ac_cv_file__dev_zero=no ac_cv_func_setpgrp_void=no apr_cv_tcp_nodelay_with_cork=no ac_cv_sizeof_struct_iovec=1

Power サーバー上で apr-util-1.5.3 コンポーネント用の構成スクリプトを実行したときに使用した引数と環境変数は、以下のとおりです。

# Configure script for apr-util-1.5.3 on Power
BUILD_CC=gcc 
CC_FOR_BUILD=gcc
CC=powerpc64-linux-gcc 
CPP=cpp 
AS=powerpc64-linux-as
AR=powerpc64-linux-ar
RANLIB=powerpc64-linux-gcc-ranlib
CXX=powerpc64-linux-c++
LD=ld 
STRIP=powerpc64-linux-strip 
export CC CPP AS ASCPP AR RANLIB CXXCPP CXX LD STRIP CFLAGS LDFLAGS CC_FOR_BUILD
./configure --prefix=/home/usr/local/apr --host=powerpc64-linux --with- apr=/tmp/usr/local/apr ac_cv_file__dev_zero=no ac_cv_func_setpgrp_void=no apr_cv_tcp_nodelay_with_cork=no ac_cv_sizeof_struct_iovec=1

x86 サーバー上で httpd コンポーネント用の構成スクリプトを実行したときに使用した引数と環境変数は、以下のとおりです。

# Configure script for httpd 2.4.3 on x86 
CC_FOR_BUILD=gcc
CC=powerpc64-linux-gcc 
CPP=powerpc64-linux-cpp 
AS=powerpc64-linux-as 
AR=powerpc64-linux-ar
RANLIB=powerpc64-linux-gcc-ranlib 
CXX=powerpc64-linux-c++ 
LD=powerpc64-linux-ld
STRIP=powerpc64-linux-strip 
export CC CPP AS ASCPP AR RANLIB CXXCPP CXX LD STRIP CFLAGS LDFLAGS CC_FOR_BUILD
./configure --prefix=/tmp/usr/local --host=ppc64 ap_cv_void_ptr_lt_long=no --with- pcre=/tmp/usr/local/bin/pcre-config --with-apr=/tmp/usr/local/apr --with-mpm=worker-- with-apr-util=/tmp/usr/local/apr/bin/apu-1-config

Power サーバー上で httpd コンポーネント用の構成スクリプトを実行したときに使用した引数と環境変数は、以下のとおりです。

# Configure script for httpd 2.4.3 on Power
CC_FOR_BUILD=gcc
CC=powerpc64-linux-gcc
CPP=cpp 
AS=powerpc64-linux-as 
#ASCPP=powerpc-apm-linux-gnu-as
AR=powerpc64-linux-ar 
RANLIB=powerpc64-linux-gcc-ranlib
#CXXCPP=powerpc-apm-linux-gnu-cpp
CXX=powerpc64-linux-c++ 
LD=/opt/at7.0-5-rc1/bin/ld
STRIP=powerpc64-linux-strip
#CFLAGS="-mcpu=440fp -mtune=440fp --sysroot $SYSROOT" 
#LDFLAGS=-L$SYSROOT/lib
export CC CPP AS ASCPP AR RANLIB CXXCPP CXX LD STRIP CFLAGS LDFLAGS CC_FOR_BUILD
./configure --prefix=/home/usr/local --host=ppc64 ap_cv_void_ptr_lt_long=no--with- pcre=/home/usr/local/bin/pcre-config --with-apr=/home/usr/local/apr --with-mpm=worker-- with-apr-util=/home/usr/local/apr/bin/apu-1-config

PostgreSQL 9.4.3 のクロスコンパイル

Apache httpd をビルドするために必要になった先ほどのソース・ディストリビューションとは異なり、PostgreSQL 9.4.3 のクロスコンパイルには何の問題もありませんでした。PostgreSQL は、以下の構成スクリプトでそのままビルドされます。

x86 サーバーで PostgresSQL 用の構成スクリプトを実行したときに使用した引数と環境変数は、以下のとおりです。

# Configure script for postgresql-9.3.4 on x86 
CC=powerpc64-linux-gcc
CPP=powerpc64-linux-cpp 
AS=powerpc64-linux-as
AR=powerpc64-linux-ar
RANLIB=powerpc64-linux-gcc-ranlib
CXX=powerpc64-linux-c++ 
D=powerpc64-linux-ld
STRIP=powerpc64-linux-strip 
export CC CPP AS ASCPP AR RANLIB CXXCPP CXX LD STRIP CFLAGS LDFLAGS CC_FOR_BUILD
./configure --prefix=/tmp/usr/local --host=powerpc64-linux --without-readline --without-zlib

Apache 構成スクリプトと同じように、Power サーバー用の PowerLinux Toolchain は、ネイティブの cpp パッケージと binutils パッケージからインストールされた実行ファイルと同じような名前 (cpp、ld など) の実行ファイルを使用します。スクリプトの CPP 変数と LD 変数を以下のように変更してください。必ず、PATH 環境変数で Toolchain のパスが最初に来るようにしてください。

Power サーバー上で PostgresSQL 用の構成スクリプトを実行したときに使用した引数と環境変数は、以下のとおりです。

# Configure script for postgresql-9.3.4 on Power
CC=powerpc64-linux-gcc
CPP=cpp 
AS=powerpc64-linux-as 
AR=powerpc64-linux-ar
RANLIB=powerpc64-linux-gcc-ranlib
CXX=powerpc64-linux-c++
LD=powerpc64-linux-ld 
STRIP=powerpc64-linux-strip 
export CC CPP AS ASCPP AR RANLIB CXXCPP CXX LD STRIP CFLAGS LDFLAGS CC_FOR_BUILD
./configure --prefix=/home/usr/local --host=powerpc64-linux --without-readline --without-zlib

まとめ

Toolchain クロスコンパイラーの真の価値は、開発者が使い慣れた開発プラットフォーム (ほとんどの場合、x86) で Power Architecture 用のアプリケーションをコンパイルしてビルドできることにあります。この記事で説明した使用ケースから明らかなように、Toolchain が生成するバイナリー実行ファイルとライブラリーは、ネイティブにコンパイルされたアプリケーションに匹敵するパフォーマンスを発揮することができます。さらに、クロスコンパイルされたライブラリーは、ネイティブにコンパイルされたアプリケーションと互換します。最後になりましたが同じく重要な点として、クロスコンパイルされたアプリケーションは、ネイティブに、そしてリモートからでも gdb デバッガーを使用してデバッグすることができます。

要するに、PowerLinux Toolchain は、x86 プラットフォーム上でネイティブツール Linux Toolchain を使用するのと同じことです。この記事を読んで、PowerLinux Toolchain の機能と能力を十分に理解していただけたことを願っています。

参考文献

謝辞

この記事を作成するに当たって支援してくれた IBM の Tulio Filho 氏、Steve Munroe 氏、Steve Pratt 氏に感謝いたします。


ダウンロード可能なリソース


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux
ArticleID=993636
ArticleTitle=Intel x86 サーバー上で IBM PowerLinux アプリケーションをビルドする方法
publish-date=12252014