【问题标题】:Prevent double compilation of c files in cython防止在cython中双重编译c文件
【发布时间】:2019-08-27 11:02:32
【问题描述】:

我正在为 c 库编写一个包装器,这个库包含几乎所有函数的文件,比如说 all_funcs.c。该文件又需要编译大量其他 c 文件

我创建了all_funcs.pyx,我在其中包装了所有函数,但我还想创建一个子模块,它可以访问来自all_funcs.c 的函数。现在可行的方法是将所有 c 文件添加到 setup.py 中的两个扩展,但是每个 c 文件编译两次:第一次用于 all_funcs.pyx,第二次用于子模块扩展。

有没有办法为每个扩展提供通用的源文件?

当前 setup.py 示例:

ext_helpers = Extension(name=SRC_DIR + '.wrapper.utils.helpers',
                        sources=[SRC_DIR + '/wrapper/utils/helpers.pyx'] + source_files_paths,
                        include_dirs=[SRC_DIR + '/include/'])


ext_all_funcs = Extension(name=SRC_DIR + '.wrapper.all_funcs',
                          sources=[SRC_DIR + '/wrapper/all_funcs.pyx'] + source_files_paths,
                          include_dirs=[SRC_DIR + '/include/'])

EXTENSIONS = [
    ext_helpers,
    ext_all_funcs,
]

if __name__ == "__main__":
    setup(
        packages=PACKAGES,
        zip_safe=False,
        name='some_name',
        ext_modules=cythonize(EXTENSIONS, language_level=3)
        )

source_files_paths - 常用c源文件列表

【问题讨论】:

    标签: cython


    【解决方案1】:

    注意:此答案仅说明如何避免使用 libraries-argument of setup-function 多次编译 c/cpp 文件。然而,它并没有解释如何避免由于 ODR 违规而可能出现的问题 - 请参阅 this SO-post

    libraries-argument 添加到setup 将在构建ext_modules 之前触发build_clib(运行setup.py buildsetup.py install 命令时),生成的static 库将当扩展被链接时,也会自动传递给链接器。

    对于您的setup.py,这意味着:

    from setuptools import setup, find_packages, Extension
    ...
    #common c files compiled to a static library:
    mylib = ('mylib', {'sources': source_files_paths}) # possible further settings
    
    # no common c-files (taken care of in mylib):
    ext_helpers = Extension(name=SRC_DIR + '.wrapper.utils.helpers',
                            sources=[SRC_DIR + '/wrapper/utils/helpers.pyx'],
                            include_dirs=[SRC_DIR + '/include/'])
    
    # no common c-files (taken care of in mylib):
    ext_all_funcs = Extension(name=SRC_DIR + '.wrapper.all_funcs',
                              sources=[SRC_DIR + '/wrapper/all_funcs.pyx'],
                              include_dirs=[SRC_DIR + '/include/'])
    
    EXTENSIONS = [
        ext_helpers,
        ext_all_funcs,
    ]
    
    if __name__ == "__main__":
        setup(
            packages=find_packages(where=SRC_DIR),
            zip_safe=False,
            name='some_name',
            ext_modules=cythonize(EXTENSIONS, language_level=3),
            # will be build as static libraries and automatically passed to linker:
            libraries = [mylib] 
            )
    

    要就地构建扩展,应该调用:

    python setupy.py build_clib build_ext --inplace
    

    因为仅build_ext 是不够的:我们需要先构建静态库,然后才能在扩展中使用它们。

    【讨论】:

    • 我还在setup函数中添加了include_dirs,这也缩短了代码,谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-08
    • 2022-01-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 2018-01-13
    • 1970-01-01
    相关资源
    最近更新 更多