Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何判断在setuptools中为Python C扩展调用哪个编译器? 我有一个Python C++扩展,它需要在编译时使用以下的编译标志:OSX:< /P> CPPFLAGS='-std=c++11 -stdlib=libc++ -mmacosx-version-min=10.8' LDFLAGS='-lc++'_Python_Setuptools_Distutils - Fatal编程技术网

如何判断在setuptools中为Python C扩展调用哪个编译器? 我有一个Python C++扩展,它需要在编译时使用以下的编译标志:OSX:< /P> CPPFLAGS='-std=c++11 -stdlib=libc++ -mmacosx-version-min=10.8' LDFLAGS='-lc++'

如何判断在setuptools中为Python C扩展调用哪个编译器? 我有一个Python C++扩展,它需要在编译时使用以下的编译标志:OSX:< /P> CPPFLAGS='-std=c++11 -stdlib=libc++ -mmacosx-version-min=10.8' LDFLAGS='-lc++',python,setuptools,distutils,Python,Setuptools,Distutils,在my setup.py中检测OSX非常简单。我可以这样做: if sys.prefix == 'darwin': compile_args.append(['-mmacosx-version-min=10.8', '-stdlib=libc++']) link_args.append('-lc++') (请参阅完整上下文) 但是,在GCC上,此编译标志无效。因此,如果我以这种方式编写setup.py,那么如果有人试图在OSX上使用GCC,编译将失败 GCC和clang支持不同

在my setup.py中检测OSX非常简单。我可以这样做:

if sys.prefix == 'darwin':
    compile_args.append(['-mmacosx-version-min=10.8', '-stdlib=libc++'])
    link_args.append('-lc++')
(请参阅完整上下文)

但是,在GCC上,此编译标志无效。因此,如果我以这种方式编写setup.py,那么如果有人试图在OSX上使用GCC,编译将失败

GCC和clang支持不同的编译器标志。因此,我需要知道将调用哪个编译器,以便发送不同的标志。在setup.py中检测编译器的正确方法是什么

编辑1:

请注意,编译错误不会引发Python异常:

$ python setup.py build_ext --inplace
running build_ext
building 'spacy.strings' extension
gcc -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -c spacy/strings.cpp -o build/temp.linux-x86_64-2.7/spacy/strings.o -O3 -mmacosx-version-min=10.8 -stdlib=libc++
gcc: error: unrecognized command line option ‘-mmacosx-version-min=10.8’
gcc: error: unrecognized command line option ‘-stdlib=libc++’
error: command 'gcc' failed with exit status 1
$

我突然想到了你的问题,因为我需要同样的转换。此外,在我的例子中,
sys.prefix
不是很好,因为无论平台是什么,
clang
的标志都是

我不确定它是否完美,但以下是最适合我的。因此,我检查是否设置了
CC
变量;如果没有,我会检查
distutils
的查看位置

欢迎有更好的解决方案

import os
import distutils

try:
    if os.environ['CC'] == "clang":
        clang = True
except KeyError:
    clang = False

if clang or distutils.sysconfig_get_config_vars()['CC'] == 'clang':
    try:
        _ = os.environ['CFLAGS']
    except KeyError:
        os.environ['CFLAGS'] = ""
    os.environ['CFLAGS'] += " -Wno-unused-function"
    os.environ['CFLAGS'] += " -Wno-int-conversion"
    os.environ['CFLAGS'] += " -Wno-incompatible-pointer-types

给脾气暴躁的家伙们注意:我本想使用
extra\u compile\u args
选项,但它在
clang
编译命令中将标志放在错误的位置。

将以下代码添加到
setup.py
中。它显式检测编译器接受哪些标志,然后只添加那些标志

# check whether compiler supports a flag
def has_flag(compiler, flagname):
    import tempfile
    from distutils.errors import CompileError
    with tempfile.NamedTemporaryFile('w', suffix='.cpp') as f:
        f.write('int main (int argc, char **argv) { return 0; }')
        try:
            compiler.compile([f.name], extra_postargs=[flagname])
        except CompileError:
            return False
    return True


# filter flags, returns list of accepted flags
def flag_filter(compiler, *flags):
    result = []
    for flag in flags:
        if has_flag(compiler, flag):
            result.append(flag)
    return result


class BuildExt(build_ext):
    # these flags are not checked and always added
    compile_flags = {"msvc": ['/EHsc'], "unix": ["-std=c++11"]}

    def build_extensions(self):
        ct = self.compiler.compiler_type
        opts = self.compile_flags.get(ct, [])
        if ct == 'unix':
            # only add flags which pass the flag_filter
            opts += flag_filter(self.compiler,
                                '-fvisibility=hidden', '-stdlib=libc++', '-std=c++14')
        for ext in self.extensions:
            ext.extra_compile_args = opts
        build_ext.build_extensions(self)

setup(
   cmdclass=dict(build_ext=BuildExt),
   # other options...
)
has_flag
方法取自这个pybind11示例。

当您传递错误标志时(在Python脚本中)会发生什么异常?正确的方法是
try:send\u flags\u for\u clang(),例外情况除外:send\u flags\u for\u gcc()
。请参阅编辑---不会引发异常。