使用 Cython 和 setuptools 编译多个扩展时设置默认编译器

Lab*_*llo 7 python compilation setuptools cython

我目前有一个项目,我们大量使用 Cython 来加速我们所有的子模块/类,我希望用clang而不是gcc在 Linux 系统上编译它们。为此,我目前有一个函数可以通过以下方式收集所有扩展:

def extensions():
    try:
        from Cython.Build import cythonize
    except ImportError:
        def cythonize(*args, **kwargs):
            print("Hint: Wrapping import of cythonize in extensions()")
            from Cython.Build import cythonize
            return cythonize(*args, **kwargs)

    try:
        import numpy
        lstIncludes = [numpy.get_include()]
    except ImportError:
        lstIncludes = []

    extensionArguments = {
        'include_dirs':
        lstIncludes + ['package/core', 'package/inspect', 'util'],
        'extra_compile_args': compilerArguments,
        'extra_link_args': linkerArguments,
        'define_macros': defineMacros
    }

    return cythonize(
        [Extension("*", ["package/*.pyx"], **extensionArguments),
         Extension("*", ["package/algs/*.pyx"], **extensionArguments),
         Extension("*", ["package/core/*.pyx"], **extensionArguments)],
        compiler_directives=cythonDirectives)
Run Code Online (Sandbox Code Playgroud)

此外,我设置

os.environ["CC"] = "clang"
os.environ["CXX"] = "clang"
Run Code Online (Sandbox Code Playgroud)

setup.py当我打电话python setup.py build_ext --inplace时,先用Cython扩展使用内置clang,但第二个是建立与gcc。这种行为不会改变,如果我调用

export CC=clang; python setup.py build_ext --inplace
Run Code Online (Sandbox Code Playgroud)

再说一次,第一个未编译的 cythonized 扩展是使用构建的,clang但第二个和所有后续扩展都gcc再次使用构建。

如何在编译期间为所有 Cython 模块设置和修复编译器?

编辑:经过几周的考虑,我仍然没有解决上述问题,而且它也发生在多台机器上,所以这不是我特定设置的结果。

Lab*_*llo 8

我终于发现,有必要强制覆盖disutils从我们的系统配置中提取的内容。为此,必须通过修改上述代码来分别为每个扩展设置某些选项,如下所示

from distutils import sysconfig

def extensions():
    '''
    Handle generation of extensions (a.k.a "managing cython compilery").
    '''
    try:
        from Cython.Build import cythonize
    except ImportError:
        def cythonize(*args, **kwargs):
            print("Hint: Wrapping import of cythonize in extensions()")
            from Cython.Build import cythonize
            return cythonize(*args, **kwargs)

    try:
        import numpy
        lstIncludes = [numpy.get_include()]
    except ImportError:
        lstIncludes = []

    extensionArguments = {
        'include_dirs':
        lstIncludes + ['package/core', 'package/inspect', 'util'],
        'extra_compile_args': compilerArguments,
        'extra_link_args': linkerArguments,
        'define_macros': defineMacros
    }

    # me make damn sure, that disutils does not mess with our
    # build process

    sysconfig.get_config_vars()['CFLAGS'] = ''
    sysconfig.get_config_vars()['OPT'] = ''
    sysconfig.get_config_vars()['PY_CFLAGS'] = ''
    sysconfig.get_config_vars()['PY_CORE_CFLAGS'] = ''
    sysconfig.get_config_vars()['CC'] = 'gcc'
    sysconfig.get_config_vars()['CXX'] = 'g++'
    sysconfig.get_config_vars()['BASECFLAGS'] = ''
    sysconfig.get_config_vars()['CCSHARED'] = '-fPIC'
    sysconfig.get_config_vars()['LDSHARED'] = 'gcc -shared'
    sysconfig.get_config_vars()['CPP'] = ''
    sysconfig.get_config_vars()['CPPFLAGS'] = ''
    sysconfig.get_config_vars()['BLDSHARED'] = ''
    sysconfig.get_config_vars()['CONFIGURE_LDFLAGS'] = ''
    sysconfig.get_config_vars()['LDFLAGS'] = ''
    sysconfig.get_config_vars()['PY_LDFLAGS'] = ''

    return cythonize(
        [Extension("*", ["package/*.pyx"], **extensionArguments),
         Extension("*", ["package/algs/*.pyx"], **extensionArguments),
         Extension("*", ["package/core/*.pyx"], **extensionArguments)],
        compiler_directives=cythonDirectives,
        nthreads=4
    )
Run Code Online (Sandbox Code Playgroud)

这样,人们就可以完全控制构建扩展时发生的任何事情。