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

Python distutils, how to get a compiler that is going to be used?

例如,我可以使用python setup.py build --compiler=msvcpython setup.py build --compiler=mingw32或仅使用python setup.py build,在这种情况下,将使用默认编译器(例如bcpp)。 如何在setup.py中获取编译器名称(例如,分别为msvcmingw32bcpp)?

UPD 。:我不需要默认的编译器,我需要实际使用的编译器,而不一定是默认的编译器。 到目前为止,我还没有找到一种更好的方法来解析sys.argv来查看那里是否存在--compiler...字符串。


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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 } )


您可以子类化distutils.command.build_ext.build_ext命令。

调用build_ext.finalize_options()方法后,编译器类型将作为字符串存储在self.compiler.compiler_type中(与传递给build_ext--compiler选项的字符串相同),例如'mingw32','gcc'等...)。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#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() + '"'

1
2
3
4
5
6
7
8
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


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

导入distutils.ccompiler

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