Overview
I have a C++ project that provides a Python 2.7 wrapper. I'm building that project using CMake and I would like to have a setup.py file so that I can easily pip install git+https://mygitrepo/my_project
this project into a virtualenv. I have successfully gotten to the point where I can get pip to build my project, but I have no idea how to specify in my setup.py file or my CMakeLists.txt where my binaries should be installed.
Details
When I build my project with CMake (e.g. mkdir /path/to/my_project/build && cd /path/to/my_project/build && cmake .. && make
) everything gets built correctly and I end up with a libmy_project.so
and a pymy_project.so
file that I can succesfully import and use in Python.
When I build the project with pip in a virtualenv (e.g. pip install /path/to/my_project -v
) I can watch CMake and my compiler cranking away to compile things as expected. However they're built in a temp directory and immediately thrown away. How do I tell my setup.py which files to keep, and where will it put them?
Relevant files
My CMakeLists.txt looks like the following:
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']")
and my setup.py file looks like this:
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,
)