From 7ea8e23b85ccc6bc59788dc3605adec58db2bc2e Mon Sep 17 00:00:00 2001 From: "Benjamin R. Jack" Date: Sun, 25 Feb 2018 19:26:46 -0600 Subject: [PATCH] Revert "setup: simplify build system using scikit-build" --- CMakeLists.txt | 5 +-- setup.py | 104 +++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 93 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cb0d86f..2e9477f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,4 @@ cmake_minimum_required(VERSION 2.8.12) - project(python_cpp_example) SET(SOURCE_DIR "src/python_cpp_example") @@ -15,9 +14,7 @@ SET(TESTS ${SOURCES} # Generate a test executable include_directories(lib/catch/include) add_executable("${PROJECT_NAME}_test" ${TESTS}) -set_target_properties("${PROJECT_NAME}_test" PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests/bin) # Generate python module add_subdirectory(lib/pybind11) -pybind11_add_module(python_cpp_example ${SOURCES} "${SOURCE_DIR}/bindings.cpp") -install(TARGETS python_cpp_example DESTINATION src/python_cpp_example) +pybind11_add_module(python_cpp_example ${SOURCES} "${SOURCE_DIR}/bindings.cpp") \ No newline at end of file diff --git a/setup.py b/setup.py index 868602c..54753b8 100755 --- a/setup.py +++ b/setup.py @@ -1,28 +1,108 @@ #! /usr/bin/env python3 -from __future__ import print_function -from os import sys, path +import os +import re +import sys +import sysconfig +import platform +import subprocess -try: - from skbuild import setup -except ImportError: - print('scikit-build is required to build from source.', file=sys.stderr) - print('Please run:', file=sys.stderr) - print('', file=sys.stderr) - print(' python -m pip install scikit-build') - sys.exit(1) +from distutils.version import LooseVersion +from setuptools import setup, Extension, find_packages +from setuptools.command.build_ext import build_ext +from setuptools.command.test import test as TestCommand +from shutil import copyfile, copymode -from setuptools import find_packages + +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))) + cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir, + '-DPYTHON_EXECUTABLE=' + sys.executable] + + 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'] + + 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) + # Copy *_test file to tests directory + test_bin = os.path.join(self.build_temp, 'python_cpp_example_test') + self.copy_test_file(test_bin) + print() # Add an empty line for cleaner output + + def copy_test_file(self, src_file): + ''' + Copy ``src_file`` to ``dest_file`` ensuring parent directory exists. + By default, message like `creating directory /path/to/package` and + `copying directory /src/path/to/package -> path/to/package` are displayed on standard output. Adapted from scikit-build. + ''' + # Create directory if needed + dest_dir = os.path.join(os.path.dirname( + os.path.abspath(__file__)), 'tests', 'bin') + if dest_dir != "" and not os.path.exists(dest_dir): + print("creating directory {}".format(dest_dir)) + os.makedirs(dest_dir) + + # Copy file + dest_file = os.path.join(dest_dir, os.path.basename(src_file)) + print("copying {} -> {}".format(src_file, dest_file)) + copyfile(src_file, dest_file) + copymode(src_file, dest_file) setup( name='python_cpp_example', - version='0.3', + version='0.2', author='Benjamin Jack', author_email='benjamin.r.jack@gmail.com', description='A hybrid Python/C++ test project', long_description='', packages=find_packages('src'), package_dir={'':'src'}, + ext_modules=[CMakeExtension('python_cpp_example/python_cpp_example')], + cmdclass=dict(build_ext=CMakeBuild), test_suite='tests', zip_safe=False, )