如何从 cython 设置文件中删除 -pthread 编译器标志

Posted

技术标签:

【中文标题】如何从 cython 设置文件中删除 -pthread 编译器标志【英文标题】:How to remove -pthread compiler flag from cython setup file 【发布时间】:2019-11-24 13:44:27 【问题描述】:

在 linux 环境中,当我运行 cython 的设置脚本时,我得到了

gcc -pthread -B /apps/.../compiler_compat -Wl,-sysroot=/ -Wsign-compare 
-DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/ap......  

就我而言,我想删除 pthread 选项。我如何通过 cython 设置文件做到这一点?我看到有添加编译器标志的选项,但没有删除。我的设置文件:

from distutils.core import setup
from Cython.Build import cythonize

from distutils.extension import Extension

extensions = [Extension("foo",sources = ["foo.pyx"])]                                 

setup(ext_modules = cythonize(extensions))

【问题讨论】:

This question 是相关的,但我认为没有帮助; this answer 的第三个选项可能会有所帮助,但丢失所有参数有点极端。 【参考方案1】:

正如@DavidW 所指出的,对于许多选项,还有一个选项可以否定/覆盖它,命令行上的最后一个选项“获胜”。因此,例如添加额外的编译选项-Os 将推翻默认设置-O2-O3,因为-Os 将在命令行上的-O2 之后出现(-fwrapv/-fno-wrapv 是此类对的另一个示例)。

然而,-pthread 没有这样的“伙伴”,唯一禁用它的机会就是完全阻止它出现在命令行上。实现它的方法有些 hacky,但这种 hacky 不是我们都使用 python 的原因吗?

distutils 使用distutils.sysconfig 找到正确的编译/链接标志。一种可能性是修改其功能,以便过滤掉-pthread

我选择get_config_vars,当然也有其他选择。计划很简单:

    包裹distutils.sysconfig.get_config_vars,这样-pthread就被过滤掉了 用包装器替换distutils.sysconfig.get_config_vars 否则,setup.py 不变

这导致以下setup.py

# manipulate get_config_vars:
# 1. step: wrap functionality and filter
from distutils.sysconfig import get_config_vars as default_get_config_vars

def remove_pthread(x):
    if type(x) is str:
        # x.replace(" -pthread ") would be probably enough...
        # but we want to make sure we make it right for every input
        if x=="-pthread":
            return ""
        if x.startswith("-pthread "):
            return remove_pthread(x[len("-pthread "):])
        if x.endswith(" -pthread"):
            return remove_pthread(x[:-len(" -pthread")])
        return x.replace(" -pthread ", " ")
    return x

def my_get_config_vars(*args):
  result = default_get_config_vars(*args)
  # sometimes result is a list and sometimes a dict:
  if type(result) is list:
     return [remove_pthread(x) for x in result]
  elif type(result) is dict:
     return k : remove_pthread(x) for k,x in result.items()
  else:
     raise Exception("cannot handle type"+type(result))

# 2.step: replace    
import distutils.sysconfig as dsc
dsc.get_config_vars = my_get_config_vars


# 3.step: normal setup.py

from distutils.core import setup
from Cython.Build import cythonize

from distutils.extension import Extension

extensions = [Extension("foo",sources = ["foo.pyx"])]                                 

setup(ext_modules = cythonize(extensions))

我不完全确定,在没有-pthread 的情况下构建并在使用-pthread 构建的python-interpreter 中加载生成的模块是一个好主意 - 不确定它不会以一些微妙的方式中断并按预期工作。

【讨论】:

像魅力一样精美。除了能够删除 pthread 之外,我还在从您的帖子中学习新的 python 技巧。非常感谢@ead

以上是关于如何从 cython 设置文件中删除 -pthread 编译器标志的主要内容,如果未能解决你的问题,请参考以下文章

如何将内置的 Cython 扩展从 PC 转移到另一台?

使用Cython将结构从C返回到Python

如何从 cython 公开静态 constexpr

通过Cython打包py文件,生成包含pyd的wheel(.whl)

使用 pyximport 时如何设置 Cython 编译器标志?

如何在 Cython 中正确管理 C++ 对象的生命周期?