distutilsメモ

vcでpythonエクステンションをビルドするときにスタティックCランタイムを選択(cl.exeのオプション/MT)してマニフェスト無用の方法を模索したがそんなオプションは無いみたいだ。


distutilsは内部ではsetupのコール以降だいたい以下のように呼び出される

distutils.core
	def setup
distutils.dist
	class Distribution:
		def run_command
distutils.command.build
	class build:
		def run:
	sub-commands
		build_py      - pure Python modules
		build_clib    - standalone C libraries
		build_ext     - Python extensions
		build_scripts - (Python) scripts

ビルドのサブコマンドbuild_clibとbuild_extの中で
from distutils.ccompiler import new_compile
から
distutils.msvc9compiler
インスタンス生成がある。
msvc9compilerが/MDオプションの指定とマニフェスト埋め込みをしているのだが
cl.exeの/MDを/MTに変更したり、mt.exeの呼び出しを回避するオプションは無かった。


とりあえず動きゃいいという方法を編み出した。
setup.py

# coding: utf-8

from distutils.core import setup, Extension
import os

option={
        'swig_opts': ['-c++'],
        'include_dirs': [
            '../include'
            ],
        'libraries': [
            'meshio',
            ],
        'library_dirs': [
            '../release',
            ],
        }

if os.name=='nt':
    # cl.exeの追加オプション指定
    option['extra_compile_args']=[
            '/EHsc', # 警告回避
            '/MT', # /MDオプション上書き
            ]

ext_modules=[
        Extension("_mqo", ["mqo.i"], **option),
        ]

# スタティックruntime(/MT)とリンクするのでマニフェストが不要だが
# mt.exeの呼び出しを止めることができないので、エラーが無くなるまでsetupを呼ぶ。
# mt.exeの失敗以外でエラーになる場合に無限ループするのでCモジュールの個数+1回
for i in range(len(ext_modules)+1):
    try:
        setup(name="meshio",
                packages=['meshio'],
                package_dir={'meshio': '.'},
                ext_package='meshio',
                ext_modules=ext_modules
                )
        break
    except:
        continue

よりましな方法

2010/10/04

最後のfor文以降を下記のようにする

import distutils.msvc9compiler
org=distutils.msvc9compiler.MSVCCompiler.link
def custom(self, *args):
    try:
        org(self, *args)
    except distutils.msvc9compiler.LinkError as e:
        print(e)
distutils.msvc9compiler.MSVCCompiler.link=custom

setup(name="meshio",
        packages=['meshio'],
        package_dir={'meshio': '.'},
        ext_package='meshio',
        ext_modules=ext_modules
        )

MSVCCompilerのlinkメソッド内のmt.exe呼び出しで起こるエラーを捕捉して処理を続行
するようにMSVCCompilerクラスを改造している。
linkメソッドを置き換えてでmt.exeの呼び出しを削除する方がきれいだが、
そのためだけに長いlinkメソッドのほとんどをコピーするのもなんなので、このような形に。