【问题标题】:setup.py check if non-python library dependency existssetup.py 检查是否存在非python库依赖
【发布时间】:2015-05-04 19:26:49
【问题描述】:

我正在尝试为cgal-bindings 创建一个 setup.py。要安装它,用户需要至少有一个特定版本的 CGAL。此外,如果用户有一些库(如 Eigen3),CGAL 有一些可选目标应该构建。 Python中有跨平台的方法来检查这个吗?

我可以在ctypes.util 中使用find_library 来检查该库是否存在,但我没有看到任何简单的方法来获取版本

使用setup()install_requires 参数仅适用于Python 库,而CGAL 是一个C/C++ 库。

【问题讨论】:

    标签: python setuptools distutils setup.py cgal


    【解决方案1】:

    是否应该编译特定的扩展模块取决于某些库版本的可用性,可以通过在setup.py 中动态生成setup()ext_modules 参数来完成。

    对于ruamel.yaml_yaml.so模块,只有在我做的系统上安装了libyaml开发库时才应该编译:

    import os
    from textwrap import dedent
    
    def check_extensions():
        """check if the C module can be build by trying to compile a small 
        program against the libyaml development library"""
    
        import tempfile
        import shutil
    
        import distutils.sysconfig
        import distutils.ccompiler
        from distutils.errors import CompileError, LinkError
    
        libraries = ['yaml']
    
        # write a temporary .c file to compile
        c_code = dedent("""
        #include <yaml.h>
    
        int main(int argc, char* argv[])
        {
            yaml_parser_t parser;
            parser = parser;  /* prevent warning */
            return 0;
        }
        """)
        tmp_dir = tempfile.mkdtemp(prefix = 'tmp_ruamel_yaml_')
        bin_file_name = os.path.join(tmp_dir, 'test_yaml')
        file_name = bin_file_name + '.c'
        with open(file_name, 'w') as fp:
            fp.write(c_code)
    
        # and try to compile it
        compiler = distutils.ccompiler.new_compiler()
        assert isinstance(compiler, distutils.ccompiler.CCompiler)
        distutils.sysconfig.customize_compiler(compiler)
    
        try:
            compiler.link_executable(
                compiler.compile([file_name]),
                bin_file_name,
                libraries=libraries,
            )
        except CompileError:
            print('libyaml compile error')
            ret_val = None
        except LinkError:
            print('libyaml link error')
            ret_val = None
        else:
            ret_val = [
                Extension(
                    '_yaml',
                    sources=['ext/_yaml.c'],
                    libraries=libraries,
                    ),
            ]
        shutil.rmtree(tmp_dir)
        return ret_val
    

    这样,您在分发中不需要额外的文件。即使你不能在编译时根据版本号编译失败,你也应该 能够从临时目录运行生成的程序并检查退出值和/或输出。

    【讨论】:

    • Autotools 也这样做,所以我会说这是要走的路。虽然我认为如果你在 distutils 中使用 CCompiler 类,你可以让它更加跨平台。
    • @sciencectn 我更新了函数(我知道我在走捷径,但我第一次尝试使用 CCompiler 时遇到了困难)。如果标头或库不可用,这现在会失败。如果 distutils/setuptools 有一些选项来检查库(及其版本)的可用性以决定是否在 setup.py 中包含构建特定扩展,那就太好了。
    • 您 4 日的评论和回答让我再次出发。
    • 甜,我正在使用这个。在我的 setup.py 中感谢您。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-02
    • 1970-01-01
    • 2016-08-01
    • 1970-01-01
    • 2016-11-14
    • 2022-01-15
    • 2017-04-26
    相关资源
    最近更新 更多