概述
我有一个提供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如下所示:
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文件看起来像这样:
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,
)
发布于 2018-07-22 06:21:44
答案是“我如何告诉我的setup.py要保留哪些文件,以及它将把它们放在哪里?”似乎是self.get_ext_fullpath(ext.name)
,正如abarnert和hoefling指出的在this solution中发现的那样。此方法返回一个临时根目录,您可以将构建输出放入其中。然后,Pip会扫描该目录,并在构建完成后将所有内容复制到您的实际环境中。
不幸的是,Linux动态链接器无法找到我的扩展的依赖项(libmy_project.so
),因为virtualenv没有设置LD_LIBRARY_PATH
或其他任何东西,所以我最终只是将所有编译单元滚动到我的扩展中。完整的解决方案如下:
setup.py
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
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']")
https://stackoverflow.com/questions/51451124
复制相似问题