ふるつき

記事と内容がないです

初心者のあこがれ。クロスコンパイルをやる

この記事は初心者 C++er Advent Calendar 2015の六日目の記事です

五日目はReputelessさんのVec2 クラスを作る(モダンな C++ クラスデザインのためのチュートリアル)でした。

qiita.com

C++クロスプラットフォームな言語です

 よく言われますよね。ネイティブなオブジェクトコードを吐く上にクロスプラットフォームなので開発しやすいよって。しかし、実際にC++を触ってみてもクロスコンパイルをする機会はあまり多くない気がしています。わざわざ他のプラットフォームのバイナリ吐く必要ってないですよね。

 ということでやったことがなかったのでやります。

なにが必要か。

 コンパイラが必要です。普段使っているであろうコンパイラではなく、ターゲットの環境に合わせた(そのプラットフォームのバイナリをはける)コンパイラです。コンパイラって言ってますけどリンカとかそのたもろもろ(把握してない)ひっくるめていってます。

 自分の対象にしているプラットフォームのコンパイラを探すにはここをおすすめします。

今回は

たまたまvirtualbox内にあったKaliLinuxから、Windows向けのバイナリを作ってみたいと思います。

 環境についてちゃんと書くと、kaliは

# uname -r
4.0.0-kali1-686-pae

windowswindows8.1 Pro 64bit with MinGW64です。

 というわけでまずはそのためのコンパイラを入手します。aptでgcc windowsで検索してやるといろいろ出るので、そのうちのg++-mingw-w64-x86-64に目をつけます。apt-get installしました。依存は次の用な感じです(apt-cache showでみれます)。

Depends: gcc-mingw-w64-x86-64 (= 4.9.1-19+14.3), gcc-mingw-w64-base, libc6 (>= 2.11), libcloog-isl4 (>= 0.17), libgmp10, libisl10 (>= 0.10), libmpc3, libmpfr4 (>= 3.1.2), zlib1g (>= 1:1.1.4)

思ったより少ないですが、依存の依存があるためです。gcc-mingw-w64-x86-64 の依存関係も見てみると

Depends: binutils-mingw-w64-x86-64, mingw-w64-x86-64-dev, gcc-mingw-w64-base (= 4.9.1-19+14.3), libc6 (>= 2.11), libcloog-isl4 (>= 0.17), libgmp10, libisl10 (>= 0.10), libmpc3, libmpfr4 (>= 3.1.2), zlib1g (>= 1:1.1.4)

binutilsやdev、にも依存していました。

ロスコンパイル

とても簡単にHello Worldにしておきます。

#include <iostream>

int main() {
  std::cout << "Hello\n";
  return 0;
}

これをクロスコンパイルします。先ほど入手したコンパイラを使って、

# x86_64-w64-mingw32-g++ hello.cpp

 これだけです。これで、a.exeというファイルができているはずです。fileコマンドで確認してみます。

# file a.exe 
a.exe: PE32+ executable (console) x86-64, for MS Windows

これがx86_64用のPEファイルができているようです。それではWindows環境に持って行って動かしてみましょう。

うごかす

 先ほどのa.exeを適当な場所に配置して動かしてみます。但し、mingw/binへのパスが通っていることを確認しておいて下さい。でなければ、

コンピューターに libstdc++-6.dll がないため、プログラムを開始できまんん。この問題を解決するには、プログラムを再インストールしてみてください。

と、このように言われると思います。

 それはそれとして、動かしてみましょう。

f:id:Furutsuki:20151206213957p:plain

 このように実行が確認できました。

ほんのすこしだけ余談

 上記のエラーメッセージですが、動的にリンクするためのファイルが存在しないので起こるエラーですから、静的にリンクして実行ファイルに埋め込んでしまえば、mingwは必要ありません。静的なリンクは次のコマンドで行えます。

# x86_64-w64-mingw32-g++ hello.cpp -static-libgcc -static-libstdc++

-static-libに続けてライブラリ名が入ります。今回使っているのはlibgccとlibstdc++なのでこのようになります。

明日はcocodripsさん(pythonのアイドル!)で、「参照とポインタのおはなし!」です

おわり

私がC++を知ってすぐは、クロスコンパイルにとても憧れていました。ネイティブなバイナリを吐けるなんてとても格好良いじゃあありませんか。しかしぐぐってもそんなに情報が出なかったか何かでとても難しく感じてできなかったんですよね。成長。

C++の記事じゃなくてほとんどCの記事だったかもしれない。