クロスGCC(on Linux Host for Targeting Mingw-w64 Windows)のビルド
色々試行錯誤重ねた結果、とりあえず出来上がったので記事にして残しておく。
以下のコンフィグレーション及び手順は、”本当”にとりあえずビルド通る&動くことを目標にしたやり方なので、あしからず。
1.用意するもの
・GCC-4.8.1のソースコード
・mpc-1.0.1, mpfr-3.1.2, gmp-5.1.2の各ソースコード
・isl-0.11.1 cloog-0.18.0のソースコード
・libiconv-1.14のソースコードと、libiconv-1.14-gets-undefined-in-C11パッチと有志によるja対応パッチ
・Mingw-w64-v3.0.0のソースコード
・LFS(Linux-From-Scratch)ブックを始め、各種公式サイトや参考文献などを閲覧できる環境
・何でもいいので、GCCと各種ビルド用ツールを走らせることができるLinuxが入ったx86_64マシン
・気合と根性とたっぷりの時間
2.確認
・Target:CPU=Core-i7 875K(x86_64/i686), Mem=16GB ※(OS=Linuxは今回Fedora19-amd64ーKDE-Spinを使用しました)
・Host:同上。OS=Windows 7 64bit Professional
・使用GCC=x86_64-redhat-linux 4.8.1
・これから作るクロスコンパイラ(GCC)セット=x86_64-w64-mingw32 4.8.1(出来上がったコンパイラの-m32オプションで32bitコード=i686-w64-mingw32タイプの吐き出しがおそらく可能)
3.準備する
まずはさくっとLinux環境を構築します。
KDEを選んだのでそのまま日本語を選択して各種設定しながらインストール後、KDEの日本語対応パッケージを入れる。
さらに、Linuxネイティヴのgcc,g++、それからautotools(automake,autoconf,m4)や、flex,bison,patchパッケージ等必要なものをインストールします。各種tarballに対応するために追加で必要な圧縮展開ツールを入れる可能性があるかも?
4.作業開始
ホームディレクトリに、packageディレクトリ(別にどこでもいいけど)を作成し、そこにダウンロードした各種ソースコードとパッチファイルを放り込む
~/.bashrcに以下を追記。(いやまあ、書かなくてもいいんだけど、スクリプトに書いてもいいし、そのまま端末で打ってもいいし、とにかく下記の環境変数を設定しておく。MAKEFLAGSとかCFLAGSとかは好きなようにしてください)
export CFLAGS="-O2 -pipe -march=corei7 -mtune=generic" export CXXFLAGS="${CFLAGS}" export MAKEFLAGS="-j 8" export TARGET=x86_64-w64-mingw32 export CHOST=x86_64-redhat-linux export PACKAGE=$HOME/package export BUILDS=$HOME/Builds export CROSS_SYSROOT=$HOME/cross-mingw64 export PATH=$PATH:$CROSS_SYSROOT/bin
CFLAGS: コンパイル時にGCCに指示するCソース向けフラグ
CXXFLAGS:同じくC++向けフラグ。上記のように書いて、同じフラグを用いることにする。
MAKEFLAGS:makeコマンド時に適用する、パラレル実行数(CPUコア数*2程度)
TARGET:今回の場合、作成するクロスコンパイラの名前や配置ディレクトリなどに使用する。またクロスコンパイラでビルドしたバイナリの実行環境を示すものでもある。i686-w64-mingw32でも可
CHOST=名前は何でもいいが、今回ビルドに使用するクライアントの定義 x86_64-pc-linux-gnuなど。詳しくは他のサイトでどうぞ。
CROSS_SYSROOT(ここにビルド成果物を配置)やBUILDS(ビルド作業ディレクトリ)は適当に読み替えてください。
それができたら、souce .bash_profileする。
LFS(Linux-From-Scratch)ブックに従い、専用のユーザーを作成してから作業するのもあり。その場合の手順の一部はそれに従う。
binutilsのビルド&インストール
tar xf $PACKAGE/binutils-2.23.2.tar.bz2 cd binutils-2.23.2 echo '##Texinfo-5.1 でドキュメントをビルドする際の文法の誤りを訂正します。' sed -i -e 's/@colophon/@@colophon/' \ -e 's/doc@cygnus.com/doc@@cygnus.com/' bfd/doc/bfd.texinfo mkdir -v ../binutils-build cd ../binutils-build ../binutils-2.23.2/configure \ --build=$CHOST \ --host=$CHOST \ --target=$TARGET \ --enable-targets=x86_64-w64-mingw32,i686-w64-mingw32 \ --prefix=$CROSS_SYSROOT \ --with-sysroot=$CROSS_SYSROOT \ --with-lib-path=$CROSS_SYSROOT/lib \ --target=$TARGET \ --enable-64bit-bfd \ --with-windres \ --disable-shared \ --disable-werror make && make install cd $BUILDS rm -rf build-binutils
こんな感じでどうぞ。
修正部分は、必要かわからんかったけどLFSブックを参考にしました。
-
- enable-targetsでクロスコンパイラが吐き出すバイナリが2種類対応することになる?
必要ならインストール前にmake checkしてください。
次に、mingw-w64-v3.0.0のヘッダファイルのインストール
cd $BUILDS tar xf $PACKAGE/mingw-w64-v3.0.0.tar.bz2 mkdir build-mingw-w64-headers cd build-mingw-w64-headers ../mingw-w64-v3.0.0/configure \ --host=$TARGET \ --prefix=$CROSS_SYSROOT/$TARGET \ --enable-sdk=all \ --enable-secure-api \ --without-crt \ --enable-wchar_t \ --enable-unicode make && make install
ヘッダーファイルのみのインストールです。とるあえずはGCCのコア部分をビルドするのに必要です。
SDKとセキュアAPIを有効にしてます。
wchar_tとunicodeのフラグはわかんないけど入れてみた。必要ないかも?
ついでに以下の作業をこなしておきます。
cd $CROSS_SYSROOT echo '## ※Windowsの場合は以下のところを、リンクの代わりにコピーで対応.もちろんそうでなくてもコピーで対応可能かも' ln -sv $CROSS_SYSROOT/$TARGET $CROSS_SYSROOT/mingw mkdir -pv $CROSS_SYSROOT/$TARGET/lib ln -sv $CROSS_SYSROOT/$TARGET/lib $CROSS_SYSROOT/$TARGET/lib64
上記は、成果物のディレクトリ以下のところに、リンクとディレクトリを作成しますです。(じゃないと以降の作業が失敗します)
続いて、クロスGCC-4.8.1のビルドです。
MinGW-CRTがまだできていないので、いきなりの完成は無理です。
まずはコア部分のみビルド&インストールします。
tar xf $PACKAGE/gcc-4.8.1.tar.bz2 cd gcc-4.8.1 tar xf $PACKAGE/mpfr-3.1.2.tar.bz2 mv mpfr-3.1.2 mpfr tar xf $PACKAGE/mpc-1.0.1.tar.gz mv mpc-1.0.1 mpc tar xf $PACKAGE/gmp-5.1.3.tar.bz2 mv gmp-5.1.3 gmp tar xf $PACKAGE/isl-0.12.tar.bz2 mv isl-0.12 isl tar xf $PACKAGE/cloog-0.18.0.tar.gz mv cloog-0.18.0 cloog tar xf $PACKAGE/libiconv-1.14.tar.gz mv libiconv-1.14 libiconv cd libiconv patch -p1 < $PACKAGE/libiconv-1.14-gets-undefined-in-C11.patch patch -p1 < $PACKAGE/libiconv-1.14-ja-1.patch cd .. # Fix chk isl version sed -i.orig 's/0.10/0.12/g' configure # Fix make-temp-file #patch -p1 < $PACKAGE/make-temp-file.diff # Fix libstdc++-v3-chk-sleep-func sed -i.orig 's/nono/no/g' libstdc++-v3/configure # Fix Hardcoding for file in $(find gcc/config -name linux64.h -o -name linux.h -o -name sysv4.h) do cp -uv $file{,.orig} sed -e 's@/lib\(64\)\?\(32\)\?/ld@/$CROSS_SYSROOT/$TGT&@g' \ -e 's@/usr@/$CROSS_SYSROOT/$TGT@g' $file.orig > $file echo ' #undef STANDARD_STARTFILE_PREFIX_1 #undef STANDARD_STARTFILE_PREFIX_2 #define STANDARD_STARTFILE_PREFIX_1 "/x86_64-w64-mingw32/lib/" #define STANDARD_STARTFILE_PREFIX_2 ""' >> $file touch $file.orig done echo '### GCCコアをビルド' mkdir -p $BUILDS/build-gcc cd $BUILDS/build-gcc ../gcc-4.8.1/configure \ --target=$TARGET \ --enable-targets=all \ --enable-languages=c,c++ \ --enable-__cxa_atexit \ --disable-win32-registory \ --enable-threads=win32 \ --enable-wchar_t \ --enable-unicode \ --disable-libgomp \ --disable-libatomic \ --disable-libitm \ --disable-libmudflap \ --disable-libquadmath \ --disable-libsanitizer \ --disable-libssp \ --disable-install-libiberty \ --with-sysroot=$CROSS_SYSROOT \ --prefix=$CROSS_SYSROOT \ --with-gxx-include-dir=$CROSS_SYSROOT/$TARGET/include/c++/4.8.1 \ --enable-version-specific-runtime-libs \ --enable-lto \ --with-libs=$CROSS_SYSROOT/mingw/lib \ --with-headers=$CROSS_SYSROOT/mingw/include \ --enable-libstdcxx-allocator \ --enable-libstdcxx-pch \ --enable-libstdcxx-threads \ --enable-libstdcxx-wchar_t \ --enable-libstdcxx-unicode
--enable-targets=all でi686とx86_64を両対応。
--enable-wchar_t --enable-unicode --enable-libstdcxx-unicode で--enable-libstdcxx-wchar_t ユニコードに対応したかも?
--with-sysroot=$CROSS_SYSROOT --prefix=$CROSS_SYSROOT 忘れずに指定してください。
--enable-libstdcxx-allocator --enable-libstdcxx-pch ほかサイト様似説明を任せます。
--enable-libstdcxx-threads => 私の解釈だと、libstdc++のスレッド部分を実装してビルドさせます。
その他の-disable-lib***はそうしないと今回のようなクロスコンパイラのビルドに失敗するみたいです。試しにenableに変えてみてください。
以下のコマンドで、とりあえずのGCCコア部分をインストールします。
make all-gcc && make install-gcc
順調ならば、次のステップへ。
MinGW-w64-v3.00のCRTをビルド&インストールします
cd $BUILDS mkdir -p $BUILDS/build-mingw-w64-crt cd $BUILDS/build-mingw-w64-crt ../mingw-w64-v3.0.0/mingw-w64-crt/configure \ --host=$TARGET \ --enable-lib32 \ --prefix=$CROSS_SYSROOT/x86_64-w64-mingw32 \ --with-sysroot=$CROSS_SYSROOT \ --enable-wchar_t \ --enable-unicode make && make install
最後に、残りのGCC部分をビルド&インストールして終了です。
cd $BUILDS/build-gcc make && make install ln -sv $CROSS_SYSROOT/lib/gcc/x86_64-w64-mingw32/lib/libgcc_s.a $CROSS_SYSROOT/lib/libgcc_s.a
上記のリンクを貼るのは、実際にクロスコンパイラでなにかビルドした時に、libgcc_s.aがねえよ!って怒られるからです。
貼れば、問題がなくなります。
お疲れ様でした。
最後に、$TARGET-gccや、$TARGET-g++を -v して確認したり、実際にコンパイルしてみたりして動くかどうか確認してください。
できたEXEを実行する際は「WINE」を入れておくとスムーズです。
※最後に、色々な団体、個人さまに謝辞を。
※以下サンプルのっけておきます。
#include <stdio.h> #include <locale.h> #include <tchar.h> #include <windows.h> int main(int argc, char *argv[]){ _tsetlocale(LC_ALL, _T("")); _tprintf(_T("Hello, MinGW!\n日本語で「こんにちは世界」を表示")); MessageBoxW(NULL, _T("This is a test.\n日本語でメッセージ表示!!"), _T("Test-MessageBox"), MB_OK | MB_ICONINFORMATION); return 0; }
$ x86_64-w64-mingw32-g++ Main.cpp -static -D_UNICODE $ wine a.exe Hello, MinGW! 日本語で「こんにちは世界」を表示 $ x86_64-w64-mingw32-objdump ./a.exe -h a.exe: ファイル形式 pei-x86-64 セクション: 索引名 サイズ VMA LMA File off Algn
※お使いのデスクトップ環境に応じたメッセージボックスが出ます。