【问题标题】:Set default compiler when using Cython and setuptools to compile multiple extensions使用 Cython 和 setuptools 编译多个扩展时设置默认编译器
【发布时间】:2018-05-25 23:36:48
【问题描述】:

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

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)

另外,我设置了

os.environ["CC"] = "clang"
os.environ["CXX"] = "clang"

setup.py 中,当我调用python setup.py build_ext --inplace 时,第一个Cython 扩展是使用clang 构建的,而第二个是使用gcc 构建的。如果我调用,此行为不会改变

export CC=clang; python setup.py build_ext --inplace

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

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

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

【问题讨论】:

  • 我在 Cython repo 上开了一个 issue 讨论这个问题。

标签: python compilation cython setuptools


【解决方案1】:

我终于发现,有必要强制覆盖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
    )

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

【讨论】:

    猜你喜欢
    • 2015-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-26
    • 2018-04-25
    • 2011-10-28
    • 2020-07-27
    • 1970-01-01
    相关资源
    最近更新 更多