[ Main Page ]

MinGW cross compile on Linux

MinGW + MSYSでVST Plug-inを作る方法とサンプル。

必要なもの

方法

prefix=/opt/MinGWとします。bootstrapには、MinGWのバイナリが必要になりますが、まず binutilsをsourceからbuildします。

$ tar -zxvf binutils-2.16.91-20060119-1-src.tar.gz
$ cd binutils-2.16.91-20060119-1
$ ./configure --prefix=/opt/MinGW --target=i386-mingw32 -v
$ sudo make install
    

次に、bootstrap用のバイナリとヘッダファイルとライブラリファイルを$prefix/$targetに解凍します。 この時点ではw32apiとmingw-runtimeをsourceからbuildすることはできません。

$ sudo tar -zxvf w32api-3.8.tar.gz -C /opt/MinGW/i386-mingw32/
$ sudo tar -zxvf mingw-runtime-3.11.tar.gz -C /opt/MinGW/i386-mingw32/
    

次にgccをbuildします。configureでは、languagesとprefixとtarget以外は好きに選んで下さい。 make CFLAGS="-O2 -fomit-frame-pointer" CXXFLAGS="-mthreads -fno-omit-frame-pointer -O2" LDFLAGS=-s bootstrap などもできますが、エラーが出る事があります。オプションはほどほどにしましょう。

$ tar -zxvf gcc-core-3.4.2-20040916-1-src.tar.gz
$ tar -zxvf gcc-g++-3.4.2-20040916-1-src.tar.gz
$ mkdir gcc-work;cd gcc-work
$ ../gcc-3.4.2-20040916-1/configure --enable-languages=c,c++ \
  --prefix=/opt/MinGW/ --with-gcc --with-gnu-ld --with-gnu-as \
  --target=i386-mingw32 --enable-threads --disable-nls \
  --disable-win32-registry --disable-shared \
  --enable-sjlj-exceptions --disable-libstdcxx-debug
$ make
$ sudo make install;cd ..
    

以上最低限はおわりです。正しくかかれたautotoolsでは--target=i386-mingw32とし、 /opt/MinGW/binにパスを通せば使える筈ですが、だめならCCなどをオーバーライドします。

PATH=$PATH:/opt/MinGW/bin
build=i486-slackware-linux
target=i386-mingw32
host=i386-mingw32
./configure --prefix=/opt/MinGW --build=$build --host=$host --target=$target
    

リンクの順番は大事です。gccを直接呼び出す場合、使用するライブラリ (-lkernel32など)は最後に書きますが、automakeなどを使用していると、 libtoolが勝手に並べかえるので、gccでなくlinkerに渡すコマンド(-Wl,-lkernel32) としてかき、最後に持ってくるようにします。

# Makefile.am
lib_LTLIBRARIES = Freeverb3VST.la
Freeverb3VST_la_LDFLAGS = -module -avoid-version -no-undefined \
-Wl,-lkernel32
Freeverb3VST_la_LIBADD = ...
Freeverb3VST_la_SOURCES = ...
    

リンクの順番を間違えると以下のようなエラーが出ます。

/opt/MinGW//i386-mingw32/lib/libmingwex.a(gettimeofday.o):gettimeofday.c:(.text+0x45): undefined reference to `___udivdi3'
/opt/MinGW//i386-mingw32/lib/libmingwex.a(gettimeofday.o):gettimeofday.c:(.text+0x60): undefined reference to `___umoddi3'
/opt/MinGW//i386-mingw32/lib/libmingwex.a(gettimeofday.o):gettimeofday.c:(.text+0x8a): undefined reference to `___udivdi3'
    

windresはconfigure.inで以下のようにして取得でき、Makefile.am内で$(WINDRES)として使用できます。
( Autotools Generic Program and File Checks)

AC_CHECK_TARGET_TOOL([WINDRES], [windres], [no])
if test "x$WINDRES" = "xno"; then
AC_MSG_ERROR([Cannot find windres])
fi
AC_SUBST(WINDRES)
    

参考

Cross Compiling With GCC - Dealing with Autoconf
In building a cross compiler or cross compiling a program, the configure script flags must be set properly. Below is a brief explaination of the three main switches that control cross compiling:
SwitchExplaination
--build The architecture of the host OS (usually autodetected)
gccやbinutilsなどをコンパイル(ビルド)する環境。
--host The architecture of the OS that the resulting program will run on
ビルドされたプログラムが実行される環境。
--target The architecture of the OS that this program is intended to work with
コンパイルされたプログラムが走るCPUとアーキテクチャ。
Note the subtle difference between the --host and --target flags. When building a cross compiler, both bintuils and gcc are configured with the --target set to the target operating system, but since they are cross compilers, they will run on the local host OS. Thus we don't specify anything for the --host option. For building libraries and binaries with our cross compiler, we would specify both the --target and --host flags to be the target operating system because the libraries or binaries are intended to actually run on that platform.
The architecture designations used by autoconf configure scripts usually are in the following format:
architecture-vendor-os
Sometimes the vender tag is left out. The following are several examples of common architecture tags used:
i386-redhat-linux
ppc-yellowdog-linux
ppc-apple-darwin
i686-pc-cygwin
i386-mingw32
i386-pc-mingw32
i686-pc-cygwin
i386-linux
i686-linux
sparc-linux
sparc64-linux
arm-linux
      
When configuring, if you don't know the full vender tag, you can often just use the platform-os name.

Debian/i386でのクロスコンパイル

export set PATH=/usr/i586-mingw32msvc/bin:$PATH
export set build=i486-linux-gnu
export set host=i586-mingw32msvc
export set target=i586-mingw32msvc
    

その他の情報

.Plo:1: *** multiple target patterns. Stop.

cygwin,MinGW/make 3.81でときどき発生するようです。クロスコンパイル時のパスの扱いに問題があり、 パッチの情報があります。 別のバージョンを使う手もあります。UNIXなのに、PloにC:\MinGW\...などと 設定されているのが原因です。どうしてもうまくいかないときは、*.Ploや.cacheなどすべての 生成されたファイルを消去して初めからautotoolsをやり直すのもよいかもしれません。

EHとThreadとmthreadsとmingwm10.dllと

シングルスレッドですむ場合には特に気をつける必要がないのですが、マルチスレッドプログラムを ビルドする場合、TLS(Thread Local Storage)やEH(Exception Handling)の機構を利用するので、 いろいろと気をつける必要があります。 よくある問題が、-mthreads利用時のmingwm10.dllへの依存です。 -D_MT -mthreadsによって、多くのビルトイン関数(putとか)がthread-safe ライブラリを利用するようになりますが、 その時、マルチスレッドでtry-catchなどEHを利用する場合にMinGWライブラリの不整合から 少なくとも24bytesずつメモリリークするのを防ぐために、 DllMain()トラップを利用してリソースの開放を行うためのちょっとしたハックです。EHを使わないなら -fno-exceptionsで明示すればよいですが、ふつうはEHを使っているのでリークの原因となります。 ちなみに、SEHは、Windowsでデバッグ情報などの例外を管理するための機構で、C++のEHとは違いますが、SEHをC++のEHで とらえるようにできます(/EHa)。

GCC 28263 [win32] Memory Leak In Cleaning Exception Handling Contexts
There is a leak of 24 bytes of exception handling context per Java thread on MinGW due to a hack that fools the MinGW runtime into thinking that multi-threaded exception handling is in effect but avoids linking to the correct __mingwthr_key_dtor() from mingwm10.dll and instead links to a dummy version from libmingw32.a.
See also:
http://gcc.gnu.org/ml/java/2003-04/msg00046.html
http://gcc.gnu.org/ml/java/2006-07/msg00014.html
http://gcc.gnu.org/ml/java/2006-07/msg00017.html
A workaround for avoiding this leak is to explicitly use -mthreads while linking Java programmes with GCJ.
------- Comment #1 From Kai Tietz 2009-09-03 09:24 [reply] -------
This issue is solved for mingw-w64 runtime. It uses no more the mingwm10.dll mechanism. Instead it uses TLS callbacks to implement it. By this reason the Cleaning of Exception Contexts is always present for this runtime. Maybe mingw.org's runtime will support TLS callbacks sometimes, too. This bug remains for Windows OSes without TLS callback support, and for those the -mthreads build-option can solve the issue.
Re: memory leaks and java ...
> But in this case you are supposed to use "-mthreads" while linking in your program.
Right -- we're tricking the EH code into *thinking* that mingwm10 is linked in, when in fact it is not. This convinces the EH that it should allocate a different setjmp() buffer for each thread, believing that mingwm10.dll will deallocate it.
Since mingwm10.dll is NOT present (we're not using -mthreads), we leak about 24 bytes of memory per thread created. Somehow that doesn't bother me, especially since a conservative garbage collector is likely to leak more than that.
Recap:
-mthreads causes two things to happen:
We want (1) without (2), which is why I include the hack yet do NOT put -mthreads in libgcj.spec.
Porting POSIX Threads to Windows
Note: You will probably always want to include -mthreads in your CFLAGS for any code that relies on thread-safe exception handling. From the manpage:
* -mthreads - Support thread-safe exception handling on Mingw32. Code that relies on thread-safe exception handling must compile and link all code with the -mthreads option. When compiling, -mthreads defines:
o -D_MT; when linking, it links in a special thread helper library
o -lmingwthrd which cleans up per thread exception handling data.

C++/EHにさらにつっこんで

Can I statically link with mingwm.dll?
> How to statically link with mingwm.dll ?
> mingwm.dllを静的にリンクしたいんですが。
You can't, as its design requires that it be a DLL so that it can act on DLL_THREAD_DETACH notifications in its DllMain().
DllMainのDLL_THREAD_DETACH機構を利用しているので、静的リンクできません。
There was a proposed patch earlier this summer on the gcc list that switched the cleanup mechanism to registering a PE static TLS callback instead, which would have eliminated the need for the DLL and would generally be a much cleaner way to handle the problem.
スレッド内でEHを使用した場合にメモリリークする問題を解決する、DLLのいらないきれいな方法として、 PE(Portable Executable)の静的TLSコールバックの登録を利用してリソースを解放するパッチが、 今年の夏ごろにgccのメーリングリストで提案されました。
However this would make it essentially impossible for gcc to support threaded apps on Windows 95/98/ME without memory leaks because the non-NT versions of Windows don't have static TLS. I'm not sure what Aaron has planned for the patch, such as adding some sort of compatibility toggle or whatnot.
しかし、Windows 95/98/MEの、非NT系列のOSでは静的TLSがサポートされていないために、 その方法が使えないんです。
(以下古いOSをサポートするかの話題で井戸端会議なので略)

古いOSのサポートは面倒ですね。

-mthreads関連のundefined reference to `__mingwthr_key_dtor' / `__mingwthr_remove_key_dtor'

Makefile.amでLDFLAGS += -Wl,-lmingw32 -Wl,-lmingwex -Wl,-lmingwthrdとかするとよい。 まあ、見つからない関数をlibディレクトリでかたっぱしからgrepすればリンクすべきライブラリは みつかるんだけど。あと、リンクする順序には気をつけましょう。

multiple definition of `_main'

rateconv.o:rateconv.cpp:(.text+0xa40): multiple definition of `_main'
libmingw32.a(main.o):(.text+0x0): first defined here
libmingw32.a(main.o):(.text+0x85): undefined reference to `_WinMain@16'
    

dllを作るときには-lmingw32をつけてもいいですが、単体exeを作る時に-lmingw32を入れるとエラーになります。

libtool関連

configure;make;make installでインストールしないで*.aだけをコピーしたりすると以下のような エラーを吐いてdllが生成されないことがあります。

*** Warning: linker path does not have real file for library -lfftw3f-sse.
*** I have the capability to make that library automatically link in when
*** you link to this library.  But I can only do this if you have a
*** shared version of the library, which you do not appear to have
*** because I did check the linker path looking for a file starting
*** with libfftw3f-sse and none of the candidates passed a file format test
*** using a file magic. Last file checked: /mnt/CVS/freeverb3_vst/lib/libfftw3f-sse.a
    

静的ライブラリだと、基本的には、*.laと.libs/*.aでペアになるのがlibtoolの作法なので、“どうしても”手動で コピーしたい場合は、*.laと.libs/*.aをセットになるようにしましょう(.libsは自分で掘る)。ふつうはmake installが すべてやってくれるんですが。上は、libfftw3f-sse.aのみをコピーしたためにエラーとなりました。 *.laはテキストファイルなので、ほかから*.laを持ってきてold_libraryの部分「のみ」を書き換えて対処できます。 ちなみに、コメント部分を消すとうまくいきません。 (なお、libtoolが.laファイルの2行目の「libtoolのバージョン」を参照するため、.laファイルの先頭2行のコメントは削除してはならない。) -lfooとしても、そこにlibfoo.aがあるのかlibfoo.laがあるのか、 はたまたlibfoo.soがあるのか、libfoo.dll.aがあるのか、libtoolにすべて任せるほうが簡単でしょう。

MinGW w64 libgcc libstdc++ static link 関連

MinGW w64で普通にビルドすると、いくつかのDLL依存になることがあります。 libgcc_s_sjlj-1.dll や libstdc++-6.dllはstatic linkにすることもできます。-static-libgccや-static-libstdc++は gccやg++へのオプションなので、libtoolを利用している場合には、LDFLAGSから削られてしまうことがあります。 どうしても依存をなくしたい場合は、x86_64-w64-mingw32/lib64/libstdc++.dll.aをlibstdc++.aへのリンクに、 libgcc_s.aをlib/gcc/x86_64-w64-mingw32/4.5.0/libgcc.aへのリンクにすると強制的にstatic linkとなります。 libgcc_eh.aはlibgcc.aに含まれないいくつかのexception handlingのコードを含んでいますが、 libgcc_s.soというshared libraryはすべてを含んでいます。

multiple definition of `std::bad_alloc::~bad_alloc()' 関連

上で述べたように、dll依存のライブラリと静的リンクのライブラリが共存しているので、 動的・静的ライブラリ両方を指定するなど、リンクの仕方を間違えると出ます。やっていることが わかっていれば、--allow-multiple-definitionを使って強制的にリンクできますが、MinGWやcygwinでは 時々起る問題で、DLL間でexceptionを投げられるようになるなど動的ライブラリが望ましいんですが、 バイナリ配布のときにはDLLをインストールさせるのが面倒だったりするので一概には決められないのが難点です。

Creating library file: .libs/Freeverb3VST_Impulser2.dll.a /opt/MinGW-w64/bin/../lib/gcc/x86_64-w64-mingw32/4.5.0/../../../../x86_64-w64-mingw32/lib/../lib64/libstdc++.a(new_handler.o): In function `~bad_alloc': /extra/mingw64/m64bs/linux-x86-x86_64/build/build/gcc/obj/x86_64-w64-mingw32/libstdc++-v3/libsupc++/../../../../../../build/gcc/gcc/libstdc++-v3/libsupc++/new_handler.cc:43: multiple definition of `std::bad_alloc::~bad_alloc()' /opt/MinGW-w64/bin/../lib/gcc/x86_64-w64-mingw32/4.5.0/../../../../x86_64-w64-mingw32/lib/../lib64/libstdc++.dll.a(d002564.o):(.text+0x0): first defined here collect2: ld returned 1 exit status make: *** [Freeverb3VST_Impulser2.la] Error 1

リンク

⇒そのほかMinGW + VST Tips

MPlayer cross-platform UNIX movie player, Cygwin port

Benchmarking SSE instructions - Stack Overflow

Old Nabble - MinGW - User - MinGW with SIMD (SSE, etc)

整列したメモリを静的に確保する attribute ((aligned(n)) - PS3 Linux Information Site / Cell/B.E.のパワーを体験しよう

株式会社エス・スリー・フォー ≫ Blog Archive ≫ sizeofの不思議

G Plus Plus Minus One

The Road to Hell Is Paved with Good Intentions

Yet another Unix nightmare: statically linking libstdc++ | 2005-05-31 | christopher baus.net

Among the generalists, the conventional wisdom is that the worse-is-better
approach is more adaptive. Personally, I get a little tired of the argument:
My worse-is-better is better than your worse-is-better because I'm better at
being worser! Is it really true that the worse-is-better approach always wins?
With Perl 6 we're trying to sneak one better-is-better cycle in there and hope
to come out ahead before reverting to the tried and true worse-is-better
approach. Whether that works, only time will tell.

Larry Wall in "State of the Onion 11"
http://www.perl.com/pub/a/2007/12/06/soto-11.html?page=3

    -- Larry Wall
    -- State of the Onion 11 ( http://www.perl.com/pub/a/2007/12/06/soto-11.html?page=3 )

Suspicion always haunts the guilty mind.
		-- Wm. Shakespeare


Powered by UNIX fortune(6)
[ Main Page ]