Windows環境でPythonのC拡張をビルドする

Posted on 2013-03-17

Windows NativeのPythonでC拡張をビルドする方法を説明します。みなさん普通は WindowsではPythonなんて使わないのか、あんまり情報が無いんですよね……

Windows SDKをインストールする

C拡張なのでCコンパイラが必要なので、コンパイラをインストールします。MicrosoftはVistual Studioを売っているのでそれを買えばコンパイラがついてきます。また、無償版のExpress Editionをインストールしてもコンパイラがついてきます。

C拡張をうまいことビルドするために、distutilsはVS2008のコンパイラに対応するように書かれています。UNIXだと適当にPATHからコンパイラを探してくれば良いのに、なぜ WindowsだとdistutilsがVS2008のための特別な処理を入れているかというと、コンパイラの場所がWindowsだとPATHに入っていなかったりして、レジストリから推測しなければならないからです。残念OSですね……

レジストリからコンパイラの場所を推測する関係で、より新しいバージョンのVSには対応できていません(レジストリエントリの場所が違うので)。そして、最近対応している VS2008の(一部のVC++ 2008の)Express Editionのダウンロードができなくなったようです。([Python-Dev] VC++ 2008 Express Edition now locked away?)コンパイラが入手できないのではdistutilsが対応するまでWindows上ではC拡張をビルドすることができません。

案ずることはありません。まだ道はあります。我々が欲しいのはコンパイラのみです。 MicrosoftはIDEがついてこないコンパイラ単体も配布しています。それがWindows SDKです。ちょっと前までPlatform SDKという名前だった気がします。VS2008のバージョンと互換性があるのはMicrosoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1というWindows SDKでこちらはまだダウンロード可能です。こちらをインストールしましょう。

vcvarsall.batをつくる

この状態でpython setup.py buildをやるとvcvarsall.batがないという趣旨のことを言われてビルドできません。このvcvarsall.batはVS2010と互換性のあるバージョンの Windows SDKだとついてきているのですが、2008と互換性のあるバージョンのSDKだとついてこないようです。中身は単純で現在のシステムが64bitか32bitかによって(これは引数でも指定できるようです)使うコンパイラを選択するという単純なバッチファイルです。コンパイラの選択もほかのバッチファイルを呼んでいるだけですので、自作しましょう。

C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat を作成します。32bit版Pythonを利用している場合は、

@call "%~dp0bin\vcvars32.bat"

という行を、64bit版の場合は、

@call "%~dp0bin\vcvars64.bat"

という行を一行書いて保存します。64bit版Windowsではない場合は適宜Program Filesを読み替えてください。

これでC拡張をコンパイルできるようになります。

より新しいバージョンを利用する方法

より新しいバージョンのコンパイラを利用する方法もあります。残念ながらdistutilsは(Python本体がコンパイルされたバージョンである)MSVC2008のコンパイラしか認識してくれないので、その部分をスキップしてPATHから探すようにします。

環境変数に MSSdkDISTUTILS_USE_SDK という変数を追加して下さい。値はなんでも構いません。これによりdistutilsはパスが通っているところからcl.exeや link.exeを探します。

この方法の注意点は、Cygwin上でWindowsネイティブのPythonを利用してC拡張のコンパイルをしようとすると、CygwinのGCCのlink.exeが利用されてしまうことと、Python本体と依存するライブラリが変わることです。後者によりpy2exeなどでexeにして配布するときに、実行環境で再頒布可能パッケージがなくて実行できない可能性があります。(再頒布可能パッケージをインストールすれば実行可能です)

Disclaimer: The opinions stated here are my own, not necessarily those of my company.