首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Python2.7带有CMake和SetupTools的C++扩展?

Python2.7带有CMake和SetupTools的C++扩展?
EN

Stack Overflow用户
提问于 2018-07-21 06:26:54
回答 1查看 1K关注 0票数 1

概述

我有一个提供Python2.7包装器的C++项目。我正在使用CMake构建该项目,我希望有一个setup.py文件,这样我就可以轻松地将该项目pip install git+https://mygitrepo/my_project到一个虚拟环境中。我已经成功地让pip构建了我的项目,但是我不知道如何在我的setup.py文件或我的CMakeLists.txt中指定应该在哪里安装我的二进制文件。

详细信息

当我使用CMake (例如mkdir /path/to/my_project/build && cd /path/to/my_project/build && cmake .. && make)构建我的项目时,一切都被正确地构建,最后我得到了一个libmy_project.so和一个pymy_project.so文件,我可以在Python中成功地导入和使用它们。

当我在virtualenv (例如pip install /path/to/my_project -v)中使用pip构建项目时,我可以看到CMake和我的编译器按预期进行编译。然而,它们被构建在一个临时目录中,并立即被丢弃。如何告诉我的setup.py要保留哪些文件,以及将它们放在哪里?

相关文件

我的CMakeLists.txt如下所示:

代码语言:javascript
复制
cmake_minimum_required (VERSION 3.0.0)
project (my_project)

# Find SomePackage
find_package(SomePackage REQUIRED COMPONENTS cool_unit great_unit)
include_directories(${SomePackage_INCLUDE_DIR})

# Find Python
find_package(PythonLibs 2.7 REQUIRED)
include_directories(${PYTHON_INCLUDE_DIR})

# Build libmy_project
add_library(my_project SHARED src/MyProject.cpp)
target_link_libraries(my_project ${SomePackage_LIBRARIES} ${PYTHON_LIBRARIES})

# Build py_my_project
add_library(py_my_project SHARED src/python/pyMyProject.cpp)
set_target_properties(py_my_project PROPERTIES PREFIX "")
target_link_libraries(py_my_project ${SomePackage_LIBRARIES} 
                      ${PYTHON_LIBRARIES} my_project)

file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/__init__.py "__all__ = ['py_my_project']")

我的setup.py文件看起来像这样:

代码语言:javascript
复制
import os
import subprocess

from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext

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):
        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)
        subprocess.check_call(['cmake', ext.sourcedir], cwd=self.build_temp)
        subprocess.check_call(['cmake', '--build', '.'], cwd=self.build_temp)

setup(
    name='my_project',
    version='0.0.1',
    author='Me',
    author_email='rcv@stackoverflow.com',
    description='A really cool and easy to install library',
    long_description='',
    ext_modules=[CMakeExtension('.')],
    cmdclass=dict(build_ext=CMakeBuild),
    zip_safe=False,
)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-07-22 06:21:44

答案是“我如何告诉我的setup.py要保留哪些文件,以及它将把它们放在哪里?”似乎是self.get_ext_fullpath(ext.name),正如abarnerthoefling指出的在this solution中发现的那样。此方法返回一个临时根目录,您可以将构建输出放入其中。然后,Pip会扫描该目录,并在构建完成后将所有内容复制到您的实际环境中。

不幸的是,Linux动态链接器无法找到我的扩展的依赖项(libmy_project.so),因为virtualenv没有设置LD_LIBRARY_PATH或其他任何东西,所以我最终只是将所有编译单元滚动到我的扩展中。完整的解决方案如下:

setup.py

代码语言:javascript
复制
import os
import subprocess

from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext

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):
        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)

        extdir = self.get_ext_fullpath(ext.name)
        if not os.path.exists(extdir):
            os.makedirs(extdir)

        # This is the temp directory where your build output should go
        install_prefix = os.path.abspath(os.path.dirname(extdir))
        cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={}'.format(install_prefix)]

        subprocess.check_call(['cmake', ext.sourcedir, cmake_args], cwd=self.build_temp)
        subprocess.check_call(['cmake', '--build', '.'], cwd=self.build_temp)

setup(
    name='my_project',
    version='0.0.1',
    author='Me',
    author_email='rcv@stackoverflow.com',
    description='A really cool and easy to install library',
    long_description='',
    ext_modules=[CMakeExtension('.')],
    cmdclass=dict(build_ext=CMakeBuild),
    zip_safe=False,
    install_requires=[
        'cmake',
    ]
)

CMakeLists.txt

代码语言:javascript
复制
cmake_minimum_required (VERSION 3.0.0)
project (my_project)

# Find SomePackage
find_package(SomePackage REQUIRED COMPONENTS cool_unit great_unit)
include_directories(${SomePackage_INCLUDE_DIR})

# Find Python
find_package(PythonLibs 2.7 REQUIRED)
include_directories(${PYTHON_INCLUDE_DIR})

# Build py_my_project
add_library(py_my_project SHARED src/python/pyMyProject.cpp src/MyProject.cpp)
set_target_properties(py_my_project PROPERTIES PREFIX "")
target_link_libraries(py_my_project ${SomePackage_LIBRARIES} 
                      ${PYTHON_LIBRARIES})

file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/__init__.py "__all__ = ['py_my_project']")
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51451124

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档