なんとな~くしあわせ?の日記

「そしてそれゆえ、知識そのものが力である」 (Nam et ipsa scientia potestas est.) 〜 フランシス・ベーコン

UNIX向けソフトウェアをMinGWに移植する際のテクニック

UNIX向けソフトウェアをMinGWに移植する

最近MinGWのクロスコンパイラを使ってcurlppとspidermonkeyのビルドができるようになった。これはつまり、もともとLinux/Mac/MSVC向けでしか動かなかったものをMinGWでビルドできるようにしたということである。その時使用した小手先テクニックを述べる。

MSVC向けルートは壊さない

MinGWPOSIX互換ではない。Cygwinにはあるのに、MinGWには無いヘッダファイルが結構ある。既存のコードにMSVCでビルドするルートができている場合、コンパイル時はそこをMinGWに走らせる形が望ましい。

具体的な方法としては、下のようなconfigure.acを書いてMinGWコンパイラが使う定数値をMSVCが使っているものに誘導する。

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.67])
AC_INIT([hoge], [1.0.0], [hogehoge@fuga-mail.com])
AC_CANONICAL_TARGET ← ここ重要

(省略)

# Checks for HostOS ← ここでホストのOSを判断して分岐させる
case "$host" in
        *-*-mingw*) ← ここで使いたい定数値を決めてしまう
		;;
	*-*-cygwin*)
                ;;
        *-*-linux*)
                ;;
        *-*-darwin*)
                ;;
	*-*-solaris*)
		;;
	*-*-freebsd*)
		;;
        *)
		AC_MSG_WARN([*** Please add $host to configure.ac checks!])
		;;
esac
リンク時はUNIX形式に従う

前のエントリで述べたように、MinGWでdllを作成する場合はdllimportやdllexportなどのVC++独自の仕様が邪魔になる(Importing inline functions in MinGW - なんとな~くしあわせ?の日記)。だからリンク時はコンパイラが、UNIX向けルートを見るように誘導する。

MinGW32とMinGW64はそれぞれコンパイラプリプロセッサとして以下を定義している

 # MinGW32
__MINGW32__

# MinGW64は __MINGW32__と__MINGW64__のどちらも定義する
__MINGW32__ __MINGW64__

参考:MinGW - Dev - Macros __MINGW32__ AND __MINGW64__

それを使って、Windowsのリンク時の設定でdllexportやdllimportの設定を行うルートに誘導しようとするところを改変する。

// もともとのコード
#ifdef WIN32
   // MSVCのdllexport, dllimportの設定
#else
   // UNIX向け
#endif

// 改変後のコード
#if defined(WIN32) && !defined(__MINGW32__) && !defined(__MINGW64__)
   // MSVCはこっちに入る
#else
   // MinGW32, 64はこっちに入る
#endif

まあそんな感じです