适用于 OS X 的带有 openmp 的 Python C 扩展

标签 python c gcc clang

我已经为 C 程序创建了 python 扩展。在 Linux 中,使用 gcc,一切正常,并且可以安装扩展,输入:

sudo python setup.py install

但是当我尝试在 OS X 中使用它时:

GCC 4.7:

我已经使用 macports 安装了 gcc 4.9,并且在我的 setup.py 文件中添加了这一行

import os
os.environ["CC"]="gcc-mp-4.9"

当我输入sudo python setup.py install

我收到此错误:

unrecognized command line option '-Wshorten-64-to-32'

我一直在寻找解决方案,每个人都说“使用 clang 而不是 gcc”来解决该问题。

Clang 3.8:

我还安装了 clang 3.8(3.5 安装在 os X 中,但它没有 openmp)并且我修改了文件 setup.py:

import os
os.environ["CC"]="clang-mp-3.8"

我收到此错误:

unknown argument: '-mno-fused-madd'

在一些论坛中,我找到了解决此问题的可能解决方案,为 CFLAGS 设置空值:

sudo CFLAGS=""python setup.py install

但是我收到一个新错误:

library not found for -lgomp

我使用 -fopenmp 但我不知道为什么调用 -fgomp 。在一些论坛上,人们说我必须使用 gcc 而不是 clang,所以我又回到了起点。

我想找到一个解决方案来轻松地在 OS X 中安装此扩展,因为我想创建一个任何人都可以轻松安装的扩展。

最佳答案

我也遇到了类似的问题。 Python 是用 clang 构建的,并使用 clang 特定的 CFLAGS:

>>> import sysconfig
>>> sysconfig.get_config_var("CFLAGS")
'-fno-strict-aliasing -fno-common -dynamic -arch x86_64
-arch i386 -g -Os -pipe -fno-common -fno-strict-aliasing
-fwrapv -DENABLE_DTRACE -DMACOSX -DNDEBUG -Wall
-Wstrict-prototypes -Wshorten-64-to-32 -DNDEBUG -g
-fwrapv -Os -Wall -Wstrict-prototypes -DENABLE_DTRACE'

Distutils 将此信息复制到“UnixCCCompiler”实例,用于进行扩展。但是,正如您所发现的,-Wshorten-64-to-32 是 clang 特定的。

我的解决方案是修改 distutils 构建扩展的方式。以下内容从命令行参数列表中删除该选项,以在调用真正的编译代码之前传递给编译器。 (你的代码可能不需要那么复杂。我支持多种编译器和配置。)

def _is_gcc(compiler):
    return "gcc" in compiler or "g++" in compiler

class build_ext_subclass( build_ext ):
    def build_extensions(self):
        c = self.compiler.compiler_type
        if c == "unix":
            compiler_args = self.compiler.compiler
            c = compiler_args[0]  # get the compiler name (argv0)
            if _is_gcc(c):
                names = [c, "gcc"]
                # Fix up a problem on older Mac machines where Python
                # was compiled with clang-specific options:
                #  error: unrecognized command line option '-Wshorten-64-to-32'
                compiler_so_args = self.compiler.compiler_so
                for args in (compiler_args, compiler_so_args):
                    if "-Wshorten-64-to-32" in args:
                        del args[args.index("-Wshorten-64-to-32")]

        build_ext.build_extensions(self)

然后告诉 setup() 使用这个新的子类来构建扩展:

setup(name = ...
      cmdclass = {"build_ext": build_ext_subclass},
     )

关于适用于 OS X 的带有 openmp 的 Python C 扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40234807/

相关文章:

Python 类型提示 : typing. Mapping vs. typing.Dict

c - 在 C : "undefined reference to ` sqrtf'"中使用 sqrtf()

c - 指向多个源文件之间共享的数组的指针

c++ - 'g++' 不是内部或外部命令,也不是可运行的程序或批处理文件。

c++ - 为什么C++优化器在删除同一个指针时使用不同的delete

python - 如何循环遍历每个源文件并将特定列复制到新工作簿中,并将每个新的 "paste"转移到相邻列?

python - 我如何解决 future 的警告 -> % (min_groups, self.n_splits)), Warning) in python?

python - 从带有和不带有 **kwargs 的类继承

c - 推荐学习C

arrays - C 结构体可以包含指向其他结构体数组的指针(具有不同的长度)