【问题标题】:Distutils: Compiling an Objective-C++ source file as part of a C++ extensionDistutils:将 Objective-C++ 源文件编译为 C++ 扩展的一部分
【发布时间】:2016-04-07 12:21:50
【问题描述】:

我正在用 C++ 编写 Python 扩展。我通过在 setup.py 文件中定义组成源文件的列表来编译它,如下所示:

extensions = {
    'im': [
        "im/src/buffer.cpp",
        "im/src/detail.cpp",
        "im/src/gil.cpp",
        "im/src/halideimage.cpp",
        "im/src/hybrid.cpp",
        "im/src/hybridimage.cpp",
        "im/src/options.cpp",
        "im/src/pybuffer.cpp",
        "im/src/pycapsule.cpp",
        "im/src/structcode.cpp",
        "im/src/typecode.cpp",
        "im/src/module.cpp"
    ],
}

...这些用于定义setuptools.Extension 的实例,最终传递给setup() 函数。这在整个项目中都运行良好,直到现在,当我尝试添加一个特定于平台的位时:

preview_source = (sys.platform == 'darwin') and 'im/src/plat/preview_mac.mm' or \
                  (sys.platform == 'linux') and 'im/src/plat/preview_linux.cpp' or \
                  (sys.platform == 'win32') and 'im/src/plat/preview_windows.cpp' or \
                                                'im/src/plat/preview.cpp'

extensions = {
    'im': [
        "im/src/buffer.cpp",
        "im/src/detail.cpp",
        "im/src/gil.cpp",
        "im/src/halideimage.cpp",
        "im/src/hybrid.cpp",
        "im/src/hybridimage.cpp",
        "im/src/options.cpp",
        preview_source,
        "im/src/pybuffer.cpp",
        "im/src/pycapsule.cpp",
        "im/src/structcode.cpp",
        "im/src/typecode.cpp",
        "im/src/module.cpp"
    ],
}

... 添加这个新位会选择正确的文件进行编译——但它在 Mac OS X 上根本无法编译。显然distutils/setuptools 无法将“.mm”扩展名识别为源文件:

错误:未知文件类型“.mm”

对于distutilssetuptools 特定于平台的配置,我不是专家——有什么简单的方法可以有条件地将这个源文件添加到 Mac 上的源文件列表中?

【问题讨论】:

    标签: python setuptools objective-c++ distutils python-c-api


    【解决方案1】:

    我遇到了同样的问题,你有没有找到解决办法?

    我的 distutils 版本似乎不支持“.mm”,但“.m”支持。所以我将 .mm 文件的 C++ 部分分离成一个 .cpp 文件,并创建一个小的 C 头文件以从该 .cpp 访问 .m 文件。

    【讨论】:

    • 我最终做的事情是将所有 .mm 文件重命名为 .m 文件,然后将 -x objective-c++ 添加到编译器 args - 一个既不便携的解决方案(我认为 -x是只有叮当声的东西)也不适合(考虑到文件现在基本上是错误命名的)。你的解决方案听起来更干净,但从长远来看同样不受欢迎……我仍在寻找真正的解决方案。
    • 感谢您回复我。使用 .m 文件有什么问题,它似乎工作得很好。 distutils 不处理 .mm 似乎是一个长期突出的错误。我发现了一些 2001 年(16 年前!!!)的错误报告 + 补丁:mail.python.org/pipermail/distutils-sig/2001-December/…
    • 必须使用.m 的一个问题是,如果实现是在臀部加入了Objective-C++ - 因此不能轻易分解成翻译单元就语言而言,正如你所能做的那样——你最终会得到一个不适合使用的文件。 Xcode 或 cmake 等。实际上,正如您所指出的那样,世界末日并不是世界末日——不过,这种问题确实激起了我的程序员的强迫症;虽然文件后缀只是一个数据,但它仍然是您拥有的文件最可靠的元数据,依此类推。但仍然:16 年的错误,什么?
    【解决方案2】:

    我正在开展一个遇到此问题的项目。这是我放在一起的东西。它有点老套,但它确实有效。

    from distutils.unixccompiler import UnixCCompiler
    from setuptools import setup
    from setuptools.command.build_ext import build_ext
    
    class DarwinInteropBuildExt(build_ext):
        def initialize_options(self):
    
            # add support for ".mm" files
            UnixCCompiler.src_extensions.append(".mm")
            UnixCCompiler.language_map[".mm"] = "objc"
    
            # then intercept and patch the compile and link methods to add needed flags
            unpatched_compile = UnixCCompiler._compile
            unpatched_link = UnixCCompiler.link
    
            def patched_compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
                # define language specific compile flags here
                if ext == ".cpp":
                    patched_postargs = extra_postargs + ["-std=c++17"]
                elif ext == ".mm":
                    patched_postargs = extra_postargs + [
                        "-ObjC++",
                        "-fobjc-weak",
                        "-fobjc-arc",
                    ]
                else:
                    patched_postargs = extra_postargs
                unpatched_compile(self, obj, src, ext, cc_args, patched_postargs, pp_opts)
    
            def patched_link(
                    self,
                    target_desc,
                    objects,
                    output_filename,
                    output_dir=None,
                    libraries=None,
                    library_dirs=None,
                    runtime_library_dirs=None,
                    export_symbols=None,
                    debug=0,
                    extra_preargs=None,
                    extra_postargs=None,
                    build_temp=None,
                    target_lang=None,
            ):
                # define additional linking arguments here if needed
                existing_postargs = extra_postargs or []
                framework_postargs = [
                    "-framework", "Cocoa",
                    "-framework", "Metal",
                    "-framework", "QuartzCore",
                ]
                unpatched_link(
                    self,
                    target_desc,
                    objects,
                    output_filename,
                    output_dir,
                    libraries,
                    library_dirs,
                    runtime_library_dirs,
                    export_symbols,
                    debug,
                    extra_preargs,
                    existing_postargs + framework_postargs,
                    build_temp,
                    target_lang,
                )
            UnixCCompiler._compile = patched_compile
            UnixCCompiler.link = patched_link
            super().initialize_options()
    
    # ...
    
    
    setup(
        # use the custom cmd class here
        cmdclass={"build_ext": DarwinInteropBuildExt},
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-13
      • 1970-01-01
      相关资源
      最近更新 更多