使用pip构建CMake扩展

2024-05-16 01:14:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在从事一个具有以下结构的C++/Python项目:

foo
├── CMakeLists.txt
├── include
├── source
└── python
    ├── foo
    │   ├── _foo_py.py
    │   └── __init__.py
    ├── setup.py
    └── source
        ├── CMakeLists.txt
        └── _foo_cpp.cpp

^ {CD1>}和^ {< CD2>}包含C++源文件,^ {< CD3>}包含此C++代码的PybDun11包装代码。运行^ {< CD4}}应该构建C++代码(通过运行CGUID),以共享对象的形式创建一个^ {< CD5> } Python模块,并将其与python代码集成在{{CD6}}中。也就是说,我希望能够简单地从foo/python调用python setup.py install,将foo模块安装到我的系统中。我目前正在setup.py中使用CMake扩展类来实现这一点:

class CMakeExtension(Extension):
    def __init__(self, name, sourcedir):
        Extension.__init__(self, name, sources=[])
        self.sourcedir = os.path.abspath(sourcedir)


class CMakeBuild(build_ext):
    def run(self):
        try:
            subprocess.check_output(['cmake', '--version'])
        except OSError:
            raise RuntimeError("cmake command must be available")

        for ext in self.extensions:
            self.build_extension(ext)

    def build_extension(self, ext):
        if not os.path.exists(self.build_temp):
            os.makedirs(self.build_temp)

        self._setup(ext)
        self._build(ext)

    def _setup(self, ext):
        cmake_cmd = [
            'cmake',
            ext.sourcedir,
        ]

        subprocess.check_call(cmake_cmd, cwd=self.build_temp)

    def _build(self, ext):
        cmake_build_cmd = [
            'cmake',
            '--build', '.',
        ]

        subprocess.check_call(cmake_build_cmd, cwd=self.build_temp)

当我试图在foo/python中直接调用pip时,问题就出现了,例如:

pip wheel -w wheelhouse --no-deps .

似乎在setup.py中运行代码之前,pip会将工作目录的内容复制到临时目录中。这显然不包括C++代码和顶级^ {CD15}}。这反过来又会导致CMakeBuild._setup失败,因为在pipfoo根目录复制到另一个位置后,似乎无法从setup.py内部获取该目录的路径

我能做些什么使这个设置同时适用于pythonpip吗?我已经看到一些方法,首先运行cmakesetup.py.in生成setup.py,以注入包版本、根目录路径等。但是我希望避免这种情况,并使用setup.py调用cmake,而不是相反的方法


Tags: pip代码pybuildselfcmakecmdfoo