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メソッドのほとんどをコピーするのもなんなので、このような形に。