Python distutils,如何获取将要使用的编译器?

36
例如,我可能会使用python setup.py build --compiler=msvcpython setup.py build --compiler=mingw32或只有python setup.py build,在这种情况下,默认编译器(假设为bcpp)将被使用。如何在我的setup.py中获取编译器名称(例如msvcmingw32bcpp)?
更新:我不需要默认编译器,我需要实际使用的编译器,这不一定是默认编译器。到目前为止,我还没有找到比解析sys.argv来查看是否存在--compiler...字符串更好的方法。

我有同样的问题。我想为 MSVC 包含额外的 stdint.h 头文件,但不用于其他编译器。 - Colonel Panic
6个回答

36

这是Luper Rouch的答案的扩展版本,它适用于我在Windows上使用mingw和msvc编译openmp扩展。在子类化build_ext之后,您需要将其传递给setup.py中的cmdclass参数。通过子类化build_extensions而不是finalize_options,您将拥有实际的编译器对象以进行查找,因此可以获取更详细的版本信息。最终,您可以根据每个编译器、每个扩展设置编译器标志:

from distutils.core import setup, Extension
from distutils.command.build_ext import build_ext
copt =  {'msvc': ['/openmp', '/Ox', '/fp:fast','/favor:INTEL64','/Og']  ,
     'mingw32' : ['-fopenmp','-O3','-ffast-math','-march=native']       }
lopt =  {'mingw32' : ['-fopenmp'] }

class build_ext_subclass( build_ext ):
    def build_extensions(self):
        c = self.compiler.compiler_type
        if copt.has_key(c):
           for e in self.extensions:
               e.extra_compile_args = copt[ c ]
        if lopt.has_key(c):
            for e in self.extensions:
                e.extra_link_args = lopt[ c ]
        build_ext.build_extensions(self)

mod = Extension('_wripaca',
            sources=['../wripaca_wrap.c', 
                     '../../src/wripaca.c'],
            include_dirs=['../../include']
            )

setup (name = 'wripaca',
   ext_modules = [mod],
   py_modules = ["wripaca"],
   cmdclass = {'build_ext': build_ext_subclass } )

需要注意的是,在Linux/POSIX下使用GCC/Clang编译器时,lopt的关键字必须为“unix”。 - marscher
谢谢。这些信息应该比现在更易于获取。我们应该向distutils报告一个bug。 - Colonel Panic

9
您可以创建distutils.command.build_ext.build_ext命令的子类。
一旦调用了build_ext.finalize_options()方法,编译器类型将以字符串形式存储在self.compiler.compiler_type中(与传递给build_ext--compiler选项相同,例如'mingw32'、'gcc'等)。

编译器对象是 self.compiler,类型在 self.compiler.compiler_type 中。 - Fred Schoen
compiler_typedistutilsbuild_ext.run 方法中进行设置。因此,如果您有一个 build_ext 子类并覆盖了 run 方法,则可能永远不会设置 compiler_type - John

2
#This should work pretty good
def compilerName():
  import re
  import distutils.ccompiler
  comp = distutils.ccompiler.get_default_compiler()
  getnext = False

  for a in sys.argv[2:]:
    if getnext:
      comp = a
      getnext = False
      continue
    #separated by space
    if a == '--compiler'  or  re.search('^-[a-z]*c$', a):
      getnext = True
      continue
    #without space
    m = re.search('^--compiler=(.+)', a)
    if m == None:
      m = re.search('^-[a-z]*c(.+)', a)
    if m:
      comp = m.group(1)

  return comp


print "Using compiler " + '"' + compilerName() + '"'

这里不需要正则表达式,并且当它们被多次使用时应该进行编译。 - EvgenKo423

0
class BuildWithDLLs(build):

    # On Windows, we install the git2.dll too.
    def _get_dlls(self):
        # return a list of of (FQ-in-name, relative-out-name) tuples.
        ret = []
        bld_ext = self.distribution.get_command_obj('build_ext')
        compiler_type = bld_ext.compiler.compiler_type

你可以使用 self.distribution.get_command_obj('build_ext') 来获取 build_ext 实例,然后获取 compiler_type。

0
import sys
sys.argv.extend(['--compiler', 'msvc'])

-1

导入distutils.ccompiler

编译器名称 = distutils.ccompiler.get_default_compiler()


5
这并不一定是distutils将要使用的编译器! - Jon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接