diff --git a/.gitignore b/.gitignore index ce615056e..7398001cd 100644 --- a/.gitignore +++ b/.gitignore @@ -106,3 +106,4 @@ tutorial/cmake-build-debug .vscode/ .idea/ site/ +*.egg-info/ diff --git a/.travis.yml b/.travis.yml index 4e747f981..aadb59cb2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,8 @@ matrix: - liblapack-dev - xorg-dev - libglu1-mesa-dev + - python3-setuptools + - libpython3-dev env: - MATRIX_EVAL="export CONFIG=Debug && CHECK_UNDEFINED=ON && PYTHON=python3" - os: linux @@ -38,12 +40,14 @@ matrix: - liblapack-dev - xorg-dev - libglu1-mesa-dev + - python3-setuptools + - libpython3-dev env: - - MATRIX_EVAL="export CC=gcc-7 && CXX=g++-7 && CONFIG=Debug && CHECK_UNDEFINED=OFF && PYTHON=python3" + - MATRIX_EVAL="export CC=gcc-7 && CXX=g++-7 && CONFIG=Debug && CHECK_UNDEFINED=ON && PYTHON=python3" - os: osx compiler: clang env: - - MATRIX_EVAL="export CONFIG=Debug && CHECK_UNDEFINED=OFF && PYTHON=python" + - MATRIX_EVAL="export CONFIG=Debug && CHECK_UNDEFINED=ON && PYTHON=python3" install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install ccache; fi @@ -55,11 +59,8 @@ install: script: # Python bindings - cd python -- mkdir build -- cd build -- cmake -DCMAKE_BUILD_TYPE=$CONFIG -DLIBIGL_WITH_EMBREE=OFF -DLIBIGL_USE_STATIC_LIBRARY=ON -DCHECK_UNDEFINED=${CHECK_UNDEFINED} ../ -- make -j 2 -- cd ../tutorial +- ${PYTHON} setup.py develop --user -- -DCMAKE_BUILD_TYPE=${CONFIG} -DLIBIGL_WITH_EMBREE=OFF -DLIBIGL_USE_STATIC_LIBRARY=ON -DCHECK_UNDEFINED=${CHECK_UNDEFINED} +- cd tutorial - ${PYTHON} 101_FileIO.py - cd ../../ - rm -rf python/build diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 901d5837f..6e92fe144 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -10,8 +10,9 @@ project(pyigl) # set(PYTHON_INCLUDE_DIR "/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/include/python3.5m") set(Python_ADDITIONAL_VERSIONS 3.4 3.5 3.6) -find_package(PythonLibs REQUIRED) find_package(PythonInterp REQUIRED) +find_package(PythonLibs REQUIRED) + string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE) if(UNIX) diff --git a/python/setup.py b/python/setup.py new file mode 100644 index 000000000..21ef19d4c --- /dev/null +++ b/python/setup.py @@ -0,0 +1,90 @@ +import os +import re +import sys +import platform +import subprocess + +from setuptools import setup, Extension +from setuptools.command.build_ext import build_ext +from distutils.version import LooseVersion +from distutils.sysconfig import get_config_var +from distutils.sysconfig import get_python_inc + +CMAKE_ADDITIONAL_OPT = [] +if '--' in sys.argv: + i = sys.argv.index('--') + CMAKE_ADDITIONAL_OPT = sys.argv[i+1:] + sys.argv = sys.argv[:i] + +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: + out = subprocess.check_output(['cmake', '--version']) + except OSError: + raise RuntimeError("CMake must be installed to build the following extensions: " + + ", ".join(e.name for e in self.extensions)) + + if platform.system() == "Windows": + cmake_version = LooseVersion( + re.search(r'version\s*([\d.]+)', out.decode()).group(1)) + if cmake_version < '3.1.0': + raise RuntimeError("CMake >= 3.1.0 is required on Windows") + + for ext in self.extensions: + self.build_extension(ext) + + def build_extension(self, ext): + extdir = os.path.abspath(os.path.dirname( + self.get_ext_fullpath(ext.name))) + + python_library = str(get_config_var('LIBDIR')) + python_include_directory = str(get_python_inc()) + + cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir, + '-DPYTHON_EXECUTABLE=' + sys.executable, + '-DPYTHON_INCLUDE_DIR=' + python_include_directory, ] + + cfg = 'Debug' if self.debug else 'Release' + build_args = ['--config', cfg] + + if platform.system() == "Windows": + cmake_args += [ + '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir)] + if sys.maxsize > 2**32: + cmake_args += ['-A', 'x64'] + build_args += ['--', '/m'] + else: + cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg] + build_args += ['--', '-j2'] + cmake_args += CMAKE_ADDITIONAL_OPT + + env = os.environ.copy() + env['CXXFLAGS'] = '{} -DVERSION_INFO=\\"{}\\"'.format(env.get('CXXFLAGS', ''), + self.distribution.get_version()) + if not os.path.exists(self.build_temp): + os.makedirs(self.build_temp) + + subprocess.check_call(['cmake', ext.sourcedir] + + cmake_args, cwd=self.build_temp, env=env) + subprocess.check_call(['cmake', '--build', '.'] + + build_args, cwd=self.build_temp) + +setup( + name='pyigl', + version='0.0.1', + author='Geometric Computing Lab @ NYU', + author_email='info@geometriccomputing.org', + description='', + long_description='', + ext_modules=[CMakeExtension('pyigl')], + cmdclass=dict(build_ext=CMakeBuild), + zip_safe=False, +)