使用distutils为Python扩展构建RPM时的相对包含路径

1 投票
2 回答
848 浏览
提问于 2025-04-17 20:14

我正在使用 Python 2.6,想要为一个 Python 的 C 扩展模块构建一个 RPM 包。

我用的 setup.py 文件大概是这样的:

from distutils.core import setup, Extension

foo_ext = Extension('foo',
                    sources=['foo.c', '../src/common.c'],
                    include_dirs=['../includes'])

setup(... , ext_modules=[foo_ext])

比如说,如果我在 /devel/foo 目录下运行 python setup.py build,它会顺利编译和构建,没有任何错误,而且 gcc 也会用正确的路径调用,也就是:

gcc ... -I/devel/includes ...

但是当我用 python setup.py bdist_rpm 的时候,上面用的相对路径会变成相对于 RPM 构建目录的绝对路径,这样就导致 gcc 尝试用以下路径来编译:

gcc ... -I/devel/foo/build/bdist.linux-x86_64/rpm/BUILD/includes ...

结果编译失败,因为找不到一个必需的 .h 文件在包含路径中。

有没有什么建议或者解决办法呢?

2 个回答

0

我之前遇到过类似的问题,解决办法是给 distutils 提供一个合适的 MANIFEST.in 文件,这个文件列出了我想要包含的所有头文件。在我的情况下,它是这样的:

include src/_rvlm_fdtd/include/rvlm/fdtd/* –or–
recursive-include src/_rvlm_fdtd *.h

不过我觉得这个方法可能不适用于你的 ../ 路径。相反,我建议你把所有的源代码放在一个包的基础目录里。

RPM 构建阶段找不到你的头文件的原因是,它首先会构建一个源代码分发包(使用 setup.py sdist),然后把生成的压缩包解压到一个临时的构建目录里。所以你的源代码分发包里根本没有包含构建所需的所有文件。

2

通过在脚本第一次运行时设置一个环境变量,解决了这个问题。然后在构建RPM时再次读取这个变量:

import os
from distutils.core import setup, Extension

src_path = os.path.abspath('../src/common.c')
inc_path = os.path.abspath('../includes')

if 'SRC_PATH' not in os.environ:
    os.environ['SRC_PATH'] = src_path
    os.environ['INC_PATH'] = inc_path
else:
    src_path = os.environ['SRC_PATH']
    inc_path = os.environ['INC_PATH']

foo_ext = Extension('foo',
                sources=['foo.c', src_path],
                include_dirs=[inc_path])

setup(... , ext_modules=[foo_ext])

撰写回答