【基本/応用技術者試験】クロスコンパイラとは?

サムネイル画像 基本/応用情報技術者試験

クロスコンパイラは簡単に言うと、「今使っているパソコンとは違う種類の機械で動くアプリを作るためのコンパイラ」です。

「クロスコンパイラって何?」「どんな時に使うの?」と疑問に思ったことはありませんか?

例えば、Windows PCでAndroid向けのアプリをビルドしたり、MacでiPhone向けのアプリを作ったりするときに使われています。

この記事を読み終えると、あなたはクロスコンパイラの仕組みや使いどころ、そして試験でよく出るポイントをマスターできると思いますので、ぜひ最後まで読んでいただけると嬉しいです。

クロスコンパイラとは?

クロスコンパイラは、次の2つが異なるときに使うコンパイラです。

  • プログラムを作るPC(ホスト環境/ビルド環境)
  • そのプログラムを動かす機械(ターゲット環境)

通常のコンパイラ(ネイティブコンパイラ)は、同じPC上で動くプログラムを作りますが、クロスコンパイラは別の環境で動くプログラムを作ります。

スマホの例で考えると

  • Windows PC → Android向けアプリのビルド
  • Mac → iPhone(iOS)向けアプリのビルド

このように別の環境で動くバイナリを作るコンパイラがクロスコンパイラです。

【試験ポイント】基本情報技術者試験では、「ホスト環境」と「ターゲット環境」という用語が頻出します。

なぜクロスコンパイラが必要なの?

理由1:CPUが違うと理解できる命令が違う

スマホとPCでは、搭載されているCPUが異なります。

  • PC:Intel / AMD(x86系、x64系)
  • Android:Snapdragon、Mediatek(ARM系)
  • iPhone:Aシリーズ(ARM系)

CPUが違うと、機械語の形式(命令セット)も変わるため、PC用にビルドしたものをスマホでは動かせません。

例えば、以下のような違いがあります。

x86系CPU:
MOV EAX, 5   ← このような命令を理解する

ARM系CPU:
MOV R0, #5   ← こちらの形式を理解する

同じ「値を5にする」処理でも、CPUによって命令の書き方が全く異なるのです。

理由2:OSが違うから

OSごとに利用できる機能の呼び出し方も違います。

  • Windows
  • Android(Linux系)
  • iOS

例えば、ファイルを開く処理でも、OSによって使うAPIが異なります。

Windows:
CreateFile() ← Windows API

Android/iOS:
open() ← POSIX系のシステムコール

そのため、動作させたいOSに合わせたバイナリを作る必要があります。

これらを一括で解決してくれるのがクロスコンパイラです。

過去問例(基本情報技術者試験)

基本情報技術者試験では、次のような問題が出題されています。

問題:
あるコンピュータ上で,異なる命令形式をもつ別のコンピュータで
実行できる目的プログラムを生成する言語処理プログラムはどれか。

(基本情報技術者平成17年秋期 午前問36)

この問題の答えが、まさにクロスコンパイラです。

キーワードは「別の機械用のプログラムをPCで作る」。これが出てきたらクロスコンパイラの合図です。

クロスコンパイラの動作イメージ

実際のクロスコンパイルのコマンド例を見てみましょう。

android-gcc main.cpp -o app_for_android

この例なら、次のような処理が行われます。

  • 手元のPCはWindows
  • 生成されるのはAndroid が理解できるバイナリ

実行結果の例

$ android-gcc main.cpp -o app_for_android
Compiling for ARM architecture...
Linking Android libraries...
Build successful: app_for_android (ARM binary)

$ file app_for_android
app_for_android: ELF 32-bit LSB executable, ARM, version 1 (SYSV)

このように、Windows上で作業しているにもかかわらず、ARM用のバイナリが生成されます。

例えるなら、「日本で英語の文章を作って、海外の人に渡す」ようなイメージです。

私が実際にクロスコンパイルで困った体験談

実は、私がチーム開発で組み込み機器向けのゲームを作っていた時、クロスコンパイルで大きな問題に遭遇しました。

具体的には、Windows PC上で開発していたゲームをARM系のLinuxボードに移植する際、以下のようなエラーが発生しました。

エラーメッセージ:
arm-linux-gnueabihf-g++: error: cannot find -lSDL2
/usr/lib/x86_64-linux-gnu/libSDL2.so: file not recognized: file format not recognized
collect2: error: ld returned 1 exit status

このエラーは、PC用のSDL2ライブラリをARM向けビルドでリンクしようとしたために発生しました。

原因と解決策

調査した結果、以下の問題点が明らかになりました。

  • PC用のライブラリ(x86_64用)を指定していた
  • ARM向けにクロスコンパイルされたライブラリが必要だった
  • ライブラリパスの設定が間違っていた

最終的に、以下の対応をしました。

  • ARM用のSDL2ライブラリをクロスコンパイルして用意
  • ライブラリパスをARM用のディレクトリに変更
  • Makefileにターゲット環境専用の設定を追加
修正後のMakefile:
CC = arm-linux-gnueabihf-g++
CFLAGS = -I/opt/arm-toolchain/include
LDFLAGS = -L/opt/arm-toolchain/lib -lSDL2

app: main.cpp
    $(CC) $(CFLAGS) main.cpp -o app $(LDFLAGS)

実行結果

$ make
arm-linux-gnueabihf-g++ -I/opt/arm-toolchain/include main.cpp -o app -L/opt/arm-toolchain/lib -lSDL2
Build successful!

$ file app
app: ELF 32-bit LSB executable, ARM

この経験から、クロスコンパイルでは「すべての依存ライブラリもターゲット環境用に用意する」ことの重要性を学びました。

よくある失敗例と対処法

初心者がハマりやすいクロスコンパイルのポイントを3つ紹介します。

失敗例1:PC用ライブラリをそのまま使おうとする

症状:「file not recognized」「wrong ELF class」などのリンクエラーが出る

原因:ホスト環境(PC)用のライブラリを、ターゲット環境(スマホや組み込み機器)用のビルドで使おうとしている

解決策:

  • ターゲット環境用にクロスコンパイルされたライブラリを用意する
  • ライブラリパスを正しく設定する
  • fileコマンドでバイナリのアーキテクチャを確認する
確認方法:
$ file libSDL2.so
libSDL2.so: ELF 32-bit LSB shared object, ARM ← OK(ARM用)
libSDL2.so: ELF 64-bit LSB shared object, x86-64 ← NG(PC用)

失敗例2:実機でテストせずに開発を進める

症状:PCのエミュレータでは動くが、実機では動かない、または動作が遅い

原因:エミュレータと実機では性能やOSの細かい挙動が異なる

解決策:

  • 早い段階から実機でテストする
  • 実機の性能制約(CPU、メモリ)を考慮したコードを書く
  • デバッグ環境(リモートデバッグ)を整える

失敗例3:エンディアンの違いを考慮していない

症状:数値データが正しく読み込めない、画像が壊れる

原因:PCとターゲット機器でエンディアン(バイトオーダー)が異なる

  • PC(x86):リトルエンディアン
  • 一部の組み込み機器:ビッグエンディアン

解決策:

  • バイナリデータを扱う際はエンディアン変換関数を使う
  • htonl()ntohl()などの標準関数を活用
  • プラットフォーム独立なデータフォーマット(JSON、XMLなど)を使う

つまずきやすいポイント

PC用ライブラリはスマホでは動かない

Windowsで使えるライブラリは、Androidではそのまま動きません。Android向けにビルドされたものが必要です。

これは、CPUのアーキテクチャだけでなく、OSのシステムコールの違いも関係しています。

実機での動作確認が必要

PCでビルドしても、最終的にスマホや組み込み機器でどう動くかは実機テストが必要になります。

特に、次のような点は実機でないと確認できません。

  • 実際の性能(FPS、処理速度)
  • メモリ使用量
  • バッテリー消費
  • タッチ操作やセンサーの反応

基本情報技術者試験での出題ポイント

クロスコンパイラは基本情報・応用情報の両方で頻出です。特に、以下のポイントがよく問われます。

出題ポイント①:ホスト環境とターゲット環境

  • ホスト(Host):コンパイルする側(開発用PC)
  • ターゲット(Target):実際にプログラムを動かす側(スマホ、組み込み機器)

クロスコンパイラは「ホストとターゲットが異なる」状況で用います。

試験ではこの関係性を問う問題が非常に多いです。

出題ポイント②:バイナリ形式の違い

CPUの命令セットが違えばバイナリが異なります。

  • x86/x64 → PC用
  • ARM → スマホ・組み込み機器用
  • MIPS → 一部の組み込み機器用

これを理解しておくとアーキテクチャ問題にも強くなるので、基礎知識として覚えておきたい部分です。

出題ポイント③:ネイティブコンパイラとの違い

  • ネイティブコンパイラ:ホスト=ターゲット(同じ環境で動く)
  • クロスコンパイラ:ホスト ≠ ターゲット(別の環境で動く)

この対比は試験で頻出です。

【試験頻出問題例】
問:Windows PC上でLinux組み込み機器向けのプログラムを作成する場合、
使用するコンパイラはどれか?

答:クロスコンパイラ

まとめ

クロスコンパイラについてまとめます。

  • クロスコンパイラは「別の環境で動くプログラムを作るコンパイラ」
  • PCとスマホ(Android/iPhone)など、CPUやOSが違うと必要になる
  • 基本情報では「ホストとターゲットの違い」が頻出
  • すべての依存ライブラリもターゲット環境用に用意する必要がある
  • エミュレータだけでなく、実機でのテストが必須
  • エンディアンの違いにも注意
  • ネイティブコンパイラとの違いを明確に理解する

これでクロスコンパイラの基本はバッチリですね!

スマホを例にするとイメージが掴みやすいので、苦手意識がある人はこの理解から入るのがおすすめです。

ここまで読んでくださり、ありがとうございました。

この記事が皆様の学習に役立てば幸いです。