diff --git a/.gitignore b/.gitignore index 7c4f7b4..8ead203 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,8 @@ build/ +dist/ +_build/ +_generate/ +*.so +*.py[cod] +*.egg-info *.pyd \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..a90eb86 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "pybind11"] + path = pybind11 + url = https://github.com/pybind/pybind11.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 73f107f..52ea4e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,26 +15,13 @@ endif() find_package(OpenMP) - -find_package(Boost REQUIRED) -include_directories(${Boost_INCLUDE_DIRS}) - - -find_package(pybind11 REQUIRED) -include_directories(${pybind11_INCLUDE_DIRS}) - - if (OPENMP_FOUND) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") endif() -# set(WINDOWS_EXPORT_ALL_SYMBOLS 1) -# set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS 1) - - -include_directories(src) +add_subdirectory(pybind11) pybind11_add_module(marching_cubes src/python_wrapper.cpp @@ -44,23 +31,3 @@ pybind11_add_module(marching_cubes src/laplacian_smoothing.cpp) - -################################# -# INSTALL THE PYTHON MODULE -################################# - -if(NOT DEFINED PYTHON_MODULE_INSTALL_DIR OR PYTHON_MODULE_INSTALL_DIR MATCHES "^$") - execute_process(COMMAND ${PYTHON_EXECUTABLE} -c - "from distutils.sysconfig import *; print(get_python_lib(1))" - OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE) - FILE(TO_CMAKE_PATH ${PYTHON_SITE_PACKAGES} PYTHON_MODULE_INSTALL_DIR) -endif() - -SET(PYTHON_MODULE_INSTALL_DIR ${PYTHON_MODULE_INSTALL_DIR} - CACHE PATH "where to install the marching cubres Python package" FORCE) - -# this is the install path relative to CMAKE_INSTALL_PREFIX, -# use this in INSTALL() commands to get packaging right -FILE(RELATIVE_PATH PYTHON_MODULE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX} ${PYTHON_MODULE_INSTALL_DIR}) - -install(TARGETS marching_cubes DESTINATION ${PYTHON_MODULE_INSTALL_DIR}) \ No newline at end of file diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..99c01b3 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,4 @@ +include README.md LICENSE +global-include CMakeLists.txt *.cmake +recursive-include src * +recursive-include pybind11/include *.h diff --git a/conda-recipe/bld.bat b/conda-recipe/bld.bat index 5bf6ed4..c40a9bb 100644 --- a/conda-recipe/bld.bat +++ b/conda-recipe/bld.bat @@ -1,17 +1,2 @@ -mkdir build -cd build - -set CONFIGURATION=Release - -cmake .. -G "%CMAKE_GENERATOR%" ^ - -DCMAKE_PREFIX_PATH="%LIBRARY_PREFIX%" ^ - -DCMAKE_INSTALL_PREFIX="%LIBRARY_PREFIX%" ^ - -DPYTHON_EXECUTABLE="%PYTHON%" - -if errorlevel 1 exit 1 - -cmake --build . --target ALL_BUILD --config %CONFIGURATION% -if errorlevel 1 exit 1 - -cmake --build . --target INSTALL --config %CONFIGURATION% +"%PYTHON%" setup.py install if errorlevel 1 exit 1 diff --git a/conda-recipe/build.sh b/conda-recipe/build.sh index 5651d2b..fc3a9af 100644 --- a/conda-recipe/build.sh +++ b/conda-recipe/build.sh @@ -1,43 +1,3 @@ -export CXXFLAGS="" -export CFLAGS="" -export LDFLAGS="" - -PY_VER=$(python -c "import sys; print('{}.{}'.format(*sys.version_info[:2]))") -PY_ABIFLAGS=$(python -c "import sys; print('' if sys.version_info.major == 2 else sys.abiflags)") -PY_ABI=${PY_VER}${PY_ABIFLAGS} - -# Depending on our platform, shared libraries end with either .so or .dylib -if [[ $(uname) == 'Darwin' ]]; then - DYLIB_EXT=dylib - CC=clang - CXX=clang++ - CXXFLAGS="${CFLAGS} -std=c++11 -stdlib=libc++" -else - DYLIB_EXT=so - CC=gcc - CXX=g++ - CXXFLAGS="${CFLAGS} -std=c++11" - # enable compilation without CXX abi to stay compatible with gcc < 5 built packages - if [[ ${DO_NOT_BUILD_WITH_CXX11_ABI} == '1' ]]; then - CXXFLAGS="-D_GLIBCXX_USE_CXX11_ABI=0 ${CXXFLAGS}" - fi -fi - -mkdir build -cd build -cmake ..\ - -DCMAKE_C_COMPILER=${CC} \ - -DCMAKE_CXX_COMPILER=${CXX} \ - -DCMAKE_CXX_FLAGS="${CXXFLAGS}" \ - -DCMAKE_INSTALL_PREFIX=${PREFIX} \ - -DCMAKE_PREFIX_PATH=${PREFIX} \ - -DPYTHON_EXECUTABLE=${PYTHON} \ - -DPYTHON_LIBRARY=${PREFIX}/lib/libpython${PY_ABI}.${DYLIB_EXT} \ - -DPYTHON_INCLUDE_DIR=${PREFIX}/include/python${PY_ABI} \ -## - -make -j${CPU_COUNT} - -make install - -#cp ${SRC_DIR}/build/marching_cubes*.so ${PREFIX}/lib/python${PY_VER}/site-packages/ +#!/bin/bash +unset MACOSX_DEPLOYMENT_TARGET +${PYTHON} setup.py install; diff --git a/conda-recipe/conda_build_config.yaml b/conda-recipe/conda_build_config.yaml deleted file mode 100644 index 2ef911d..0000000 --- a/conda-recipe/conda_build_config.yaml +++ /dev/null @@ -1,11 +0,0 @@ -boost: - - 1.63.0 -libstdcxxng: - - 5.4.0 -python: - - 3.6 - - -pin_run_as_build: - boost: x.x - python: x.x diff --git a/conda-recipe/meta.yaml b/conda-recipe/meta.yaml index 490ee57..95d6729 100644 --- a/conda-recipe/meta.yaml +++ b/conda-recipe/meta.yaml @@ -1,43 +1,33 @@ package: - name: marching_cubes - - {% if GIT_DESCRIBE_NUMBER|int == 0 %} - version: {{GIT_DESCRIBE_TAG}} - {% else %} - # If we're using a non-tagged revision, append '.postN' to the version - version: {{GIT_DESCRIBE_TAG}}.post{{GIT_DESCRIBE_NUMBER}} - {% endif %} - -source: - path: ../ + name: cmake_example + version: {{ environ.get('GIT_DESCRIBE_TAG', 'dev') }} build: - number: 0 - string: py{{CONDA_PY}}_{{PKG_BUILDNUM}}_h{{PKG_HASH}}_g{{GIT_FULL_HASH[:7]}} + number: {{ environ.get('GIT_DESCRIBE_NUMBER', 0) }} + {% if environ.get('GIT_DESCRIBE_NUMBER', '0') == '0' %}string: py{{ environ.get('PY_VER').replace('.', '') }}_0 + {% else %}string: py{{ environ.get('PY_VER').replace('.', '') }}_{{ environ.get('GIT_BUILD_STR', 'GIT_STUB') }}{% endif %} script_env: - # Control building with CXX11 abi - - DO_NOT_BUILD_WITH_CXX11_ABI # [linux] + - CC + - CXX + +source: + git_url: ../ requirements: build: - - cmake - - python >=2.7 - - python {{ python }} - - boost {{ boost }} + - python + - setuptools - pybind11 + - cmake + run: - python - - boost - # in order to suppor older linux distros after gcc5 switch: - - libstdcxx-ng >={{ libstdcxxng }} # [linux] - - numpy + - vs2015_runtime # [win] test: imports: - - marching_cubes + - cmake_example about: - home: http://ilastik.org - license: BSD (3-clause) - liscense_file: LICENSE - summary: A fast marching cubes implementation in C++ with python bindings. + summary: An example project built with pybind11. + license_file: LICENSE diff --git a/pybind11 b/pybind11 new file mode 160000 index 0000000..e2b884c --- /dev/null +++ b/pybind11 @@ -0,0 +1 @@ +Subproject commit e2b884c33bcde70b2ea562ffa52dd7ebee276d50 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..a791ff1 --- /dev/null +++ b/setup.py @@ -0,0 +1,67 @@ +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 + + +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) + +setup( + name='marching_cubes', + version='0.0.1', + description='Standalone marching cubes implementation and Python bindings', + long_description='', + ext_modules=[CMakeExtension('marching_cubes')], + cmdclass=dict(build_ext=CMakeBuild), + zip_safe=False, +) diff --git a/src/laplacian_smoothing.cpp b/src/laplacian_smoothing.cpp index 787bf4a..dc12280 100644 --- a/src/laplacian_smoothing.cpp +++ b/src/laplacian_smoothing.cpp @@ -1,14 +1,14 @@ #include "laplacian_smoothing.h" #include -// #include +#include // #include #include -#include +// #include -typedef std::vector> Adjacency; -//typedef std::vector > Adjacency; +// typedef std::vector> Adjacency; +typedef std::vector > Adjacency; //typedef std::vector > Adjacency; /** * maps each vertex to all its neighbours