From 69a2547c2cc153e91d8303641c6f2edd27b63e8f Mon Sep 17 00:00:00 2001 From: Marcel Steinbeck Date: Fri, 12 May 2017 23:51:18 +0200 Subject: [PATCH] Get rid of PYTHON_LIBRARY and PYTHON_INCLUDE_DIR. --- README.md | 57 +++++++++++---------------------- library/CMakeLists.txt | 51 +++++++++++++++++++----------- setup.py | 72 ++++++++++++++++++++---------------------- 3 files changed, 86 insertions(+), 94 deletions(-) diff --git a/README.md b/README.md index 003042741..a9c8437cd 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,10 @@ TinySpline is to be very small by design with a minimum set of dependencies. Non the interface has been developed to be convenient for non-experts without lacking enhanced features. -###License +### License MIT License - see the LICENSE file in the source distribution. -###Some Features of This Library +### Some Features of This Library - Use a single struct for NURBS, B-Splines, Bézier curves, lines, and points. - Support for opened and clamped splines. - Create splines of any degree and dimension. @@ -26,7 +26,7 @@ MIT License - see the LICENSE file in the source distribution. Feel free to ask for special features or to contribute to TinySpline :). -###Project Structure +### Project Structure The source distribution of TinySpline consists of two sub projects. The first one is the library itself that is located in the `library` directory. It contains all files that are required to build TinySpline. The second sub project provides some basic examples and @@ -47,7 +47,7 @@ properties for Python). Using CMake to create the bindings is recommended. Note: Use the file `debugging.h` to add some debugging features to the C interface. -###Getting Started +### Getting Started The following listing uses the C++ wrapper to give a short example of TinySpline: ```c @@ -84,9 +84,9 @@ result = beziers(0.3f).result(); // you can use '()' instead of 'evaluate' std::cout << "x = " << result[0] << ", y = " << result[1] << std::endl; ``` -###Installation +### Installation -####Compiling From Source +#### Compiling From Source TinySpline uses the CMake build system to compile and package the interfaces. The C library has been implemented in C89 and, thus, should be compilable with nearly every compiler. All other features of TinySpline are optional and will be disabled if CMake does @@ -143,7 +143,7 @@ cmake --build . You will find the resulting libraries, jars, etc. in `tinyspline/build/lib`. -####Cross Compiling +#### Cross Compiling In order to cross compile the C and C++ library, use one of the provided toolchain files. Currently, toolchain files for MinGW, ARM, and AVR are available at the root directory of the source distribution (e.g. `Toolchain-arm.cmake`). Use the following command within @@ -153,30 +153,25 @@ your build directory to cross compile TinySpline to the desired platform: cmake -DCMAKE_TOOLCHAIN_FILE=/Toolchain-*.cmake .. ``` -####Python 2 vs. Python 3 +#### Python 2 vs. Python 3 Swig needs to distinguish between Python 2 and Python 3 in order to generate source code that is compatible with the used environment. That is, Swig requires the parameter `-py` to generate Python 2 compatible code and `-py3` to generate Python 3 compatible code. Thus, the CMake file used to compile and package the libraries, configures Swig according to the version of the Python instance that was found during initialization. On systems with multiple versions of Python installed, CMake aims to use the most recent one. If you, -on the other hand, want to use a specific version of Python, the environment variables -`PYTHON_LIBRARY` and `PYTHON_INCLUDE_DIR` need to be defined. Use `PYTHON_LIBRARY` to set -the location of the shared library of the desired Python version and `PYTHON_INCLUDE_DIR` -to set the location of the appropriate header files. CMake requires both environment -variables to be defined to properly detect the right Python instance. Thus, the default -behaviour is used if one of them is undefined. +on the other hand, want to use a specific version of Python, set the environment variable +'TINYSPLINE_PYTHON_VERSION' to '2' or '3'. The following example shows how to force CMake to use Python 2 rather than Python 3 on Ubuntu: ```bash -export PYTHON_LIBRARY=/usr/lib/python2.7/config-x86_64-linux-gnu/libpython2.7.so -export PYTHON_INCLUDE_DIR=/usr/include/python2.7 +export TINYSPLINE_PYTHON_VERSION=2 cmake .. ``` -####Install the C and C++ Libraries +#### Install the C and C++ Libraries The following command installs TinySpline: ``` @@ -189,10 +184,10 @@ Python, for instance, uses Distutils/Setuptools to copy the resulting files to P specific installation directories CMake is not aware of. Thus, TinySpline ships further, language related distribution tools that will be explained in the following sections. -####Install the Python Binding -The root directory of TinySpline contains the Python script `setup.py` which uses -Setuptools to wrap the CMake build process. Additionally, it copies the resulting files to -the appropriate Python installation directory. Use the following command to build and +#### Install the Python Binding +The root directory of TinySpline contains the Python script `setup.py` using Setuptools +to wrap the CMake build process. Additionally, it copies the resulting files to the +appropriate Python installation directory. Use the following command to build and install the Python binding of TinySpline: ```bash @@ -202,21 +197,7 @@ python setup.py install Note that you may need root privileges to copy the files to the desired installation directory. -Unfortunately, the script is not able to determine the location of the Python library and -header files of the Python instance that was used to run the script. Thus, you may have to -use the approach explained above in case your system provides Python 2 and Python 3 -simultaneously. Otherwise, CMake may generate a binding for Python 3 which gets installed -to a Python 2 directory. The following examples shows how to define the environment -variables `PYTHON_LIBRARY` and `PYTHON_INCLUDE_DIR` to make sure CMake generates a Python -2 binding on Ubuntu: - -```bash -export PYTHON_LIBRARY=/usr/lib/python2.7/config-x86_64-linux-gnu/libpython2.7.so -export PYTHON_INCLUDE_DIR=/usr/include/python2.7 -python setup.py install -``` - -####Install the Java Binding +#### Install the Java Binding There are several tools to manage the build process of software implemented in Java. TinySpline uses Maven to create and install the Java binding as Maven is used in many other projects and is well supported by various integrated development environments. You @@ -253,12 +234,12 @@ TinySpline with your new generator configuration: maven clean install ``` -####Install the C# and Ruby Bindings +#### Install the C# and Ruby Bindings Currently, TinySpline does not provide tools to install the bindings for C# and Ruby. However, adding such tools is planned for the future. If you have experience with, for instance, Ruby gems and Rake, feel free to create a pull request :). -###Theoretical Backgrounds +### Theoretical Backgrounds [[1]](http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/B-spline/bspline-curve.html)    is a very good starting point for B-Splines. [[2]](http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/B-spline/de-Boor.html) diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index ef5ef01e3..2645f171b 100755 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -5,13 +5,19 @@ # Use double instead of single (float) precision. # # TINYSPLINE_DISABLE_CXX11_FEATURES - default: OFF -# Disable C++11 specific features in C++ interface. +# Disable C++11 specific features in the C++ interface. +# +# TINYSPLINE_PYTHON_VERSION - default: ANY +# Force Python version. ############################################################################### # TINYSPLINE_DOUBLE_PRECISION -option(TINYSPLINE_DOUBLE_PRECISION "Build TinySpline with double precision" OFF) +option(TINYSPLINE_DOUBLE_PRECISION "Build TinySpline with double precision." OFF) # TINYSPLINE_DISABLE_CXX11_FEATURES -option(TINYSPLINE_DISABLE_CXX11_FEATURES "Build TinySpline without C++11 features" OFF) +option(TINYSPLINE_DISABLE_CXX11_FEATURES "Build TinySpline without C++11 features." OFF) + +# TINYSPLINE_PYTHON_VERSION +set(TINYSPLINE_PYTHON_VERSION "ANY" CACHE STRING "Force Python version. Supported values are: '2', '3', and 'ANY' (fallback for unknown values).") @@ -26,15 +32,14 @@ option(TINYSPLINE_DISABLE_CXX11_FEATURES "Build TinySpline without C++11 feature # TINYSPLINE_DISABLE_CXX11_FEATURES # See corresponding option above. # +# TINYSPLINE_PYTHON_VERSION +# See corresponding option above. +# # CMAKE_TOOLCHAIN_FILE # The CMake tool chain file for cross-compiling. # # SWIG_EXECUTABLE # The SWIG executable. -# -# PYTHON_LIBRARY and PYTHON_INCLUDE_DIR -# The Python environment. Both variables must be available in order to set a -# custom environment. ############################################################################### # TINYSPLINE_DOUBLE_PRECISION if(NOT TINYSPLINE_DOUBLE_PRECISION AND DEFINED ENV{TINYSPLINE_DOUBLE_PRECISION}) @@ -48,6 +53,12 @@ if(NOT TINYSPLINE_DISABLE_CXX11_FEATURES AND DEFINED ENV{TINYSPLINE_DISABLE_CXX1 set(TINYSPLINE_DISABLE_CXX11_FEATURES $ENV{TINYSPLINE_DISABLE_CXX11_FEATURES}) endif() +# TINYSPLINE_PYTHON_VERSION +if(${TINYSPLINE_PYTHON_VERSION} STREQUAL "ANY" AND DEFINED ENV{TINYSPLINE_PYTHON_VERSION}) + message(STATUS "Using environment variable 'TINYSPLINE_PYTHON_VERSION'") + set(TINYSPLINE_PYTHON_VERSION $ENV{TINYSPLINE_PYTHON_VERSION}) +endif() + # CMAKE_TOOLCHAIN_FILE if(DEFINED ENV{CMAKE_TOOLCHAIN_FILE}) message(STATUS "Using environment variable 'CMAKE_TOOLCHAIN_FILE'") @@ -60,13 +71,6 @@ if(DEFINED ENV{SWIG_EXECUTABLE}) set(SWIG_EXECUTABLE $ENV{SWIG_EXECUTABLE}) endif() -# PYTHON_LIBRARY and PYTHON_INCLUDE_DIR -if(DEFINED ENV{PYTHON_LIBRARY} AND DEFINED ENV{PYTHON_INCLUDE_DIR}) - message(STATUS "Using environment variables 'PYTHON_LIBRARY' and 'PYTHON_INCLUDE_DIR'") - set(PYTHON_LIBRARY $ENV{PYTHON_LIBRARY}) - set(PYTHON_INCLUDE_DIR $ENV{PYTHON_INCLUDE_DIR}) -endif() - ############################################################################### @@ -508,14 +512,23 @@ if(TINYSPLINE_CXX_AVAILABLE AND TARGET_SUPPORTS_SHARED_LIBS) endif() # Python + if(${TINYSPLINE_PYTHON_VERSION} STREQUAL "2") + set(Python_ADDITIONAL_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0) + elseif(${TINYSPLINE_PYTHON_VERSION} STREQUAL "3") + set(Python_ADDITIONAL_VERSIONS 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) + endif() find_package(PythonLibs) + if(${TINYSPLINE_PYTHON_VERSION} STREQUAL "2" AND NOT ${PYTHONLIBS_VERSION_STRING} MATCHES "^2." + OR ${TINYSPLINE_PYTHON_VERSION} STREQUAL "3" AND NOT ${PYTHONLIBS_VERSION_STRING} MATCHES "^3.") + message(FATAL_ERROR "Unable to find requested Python version") + endif() if(PYTHONLIBS_FOUND) include_directories(${PYTHON_INCLUDE_DIRS}) set_source_files_properties(tinysplinepython.i PROPERTIES CPLUSPLUS ON) - if (${PYTHONLIBS_VERSION_STRING} MATCHES "^3.") - set(TINYSPLINE_PYTHON_DEFINE "-py3") + if(${PYTHONLIBS_VERSION_STRING} MATCHES "^3.") + set(TINYSPLINE_PYTHON_DEFINES "-py3") endif() - set(CMAKE_SWIG_FLAGS ${TINYSPLINE_PYTHON_DEFINE} -O ${TINYSPLINE_ADDITIONAL_SWIG_DEFINES}) + set(CMAKE_SWIG_FLAGS ${TINYSPLINE_PYTHON_DEFINES} -O ${TINYSPLINE_ADDITIONAL_SWIG_DEFINES}) set(CMAKE_SWIG_OUTDIR ${TINYSPLINE_PYTHON_DIR}) swig_add_module(tinysplinepython python tinysplinepython.i ${TINYSPLINE_CXX_SOURCE_FILES}) swig_link_libraries(tinysplinepython ${PYTHON_LIBRARIES}) @@ -728,8 +741,8 @@ Available Interfaces: Python: ${PYTHONLIBS_FOUND} Version: ${PYTHONLIBS_VERSION_STRING} - Include: ${PYTHON_INCLUDE_DIR} - Library: ${PYTHON_LIBRARY} + Include: ${PYTHON_INCLUDE_DIRS} + Library: ${PYTHON_LIBRARIES} Ruby: ${RUBY_FOUND} Version: ${RUBY_VERSION} diff --git a/setup.py b/setup.py index 7a8b471fa..0aaea9f30 100644 --- a/setup.py +++ b/setup.py @@ -5,6 +5,7 @@ from os import path, chdir from glob import glob import subprocess +import sys cmake_bin = "cmake" cmake_build_config = "Release" @@ -18,52 +19,49 @@ def run(self): build_dir = path.join(script_dir, self.build_lib, "build") bin_dir = path.join(script_dir, self.build_lib, "tinyspline") - try: - if not path.exists(build_dir): - print("creating cmake build directory") - self.mkpath(build_dir) + if not path.exists(build_dir): + print("creating cmake build directory") + self.mkpath(build_dir) - if not path.exists(bin_dir): - print("creating binary directory") - self.mkpath(bin_dir) + if not path.exists(bin_dir): + print("creating binary directory") + self.mkpath(bin_dir) - # generate make files (or any kind of project) - print("generating cmake tree") - chdir(build_dir) - cmake_cmd = [cmake_bin, src_dir, - "-DCMAKE_BUILD_TYPE=" + cmake_build_config] - if subprocess.call(cmake_cmd) != 0: - raise EnvironmentError("error calling cmake") - chdir(script_dir) + # generate make files (or any kind of project) + print("generating cmake tree") + chdir(build_dir) + cmake_cmd = [cmake_bin, src_dir, + "-DCMAKE_BUILD_TYPE=" + cmake_build_config, + "-DTINYSPLINE_PYTHON_VERSION=" + str(sys.version_info[0]), + "-Wno-dev"] + if subprocess.call(cmake_cmd) != 0: + raise EnvironmentError("error calling cmake") + chdir(script_dir) - # build the python binding - print("generating python binding") - cmake_cmd = [cmake_bin, "--build", build_dir, - "--config", cmake_build_config, - "--target", cmake_build_target] - if subprocess.call(cmake_cmd) != 0: - raise EnvironmentError("error building project") + # build the python binding + print("generating python binding") + cmake_cmd = [cmake_bin, "--build", build_dir, + "--config", cmake_build_config, + "--target", cmake_build_target] + if subprocess.call(cmake_cmd) != 0: + raise EnvironmentError("error building project") - # copy resulting files into bin_dir - for bin_file in glob(path.join(build_dir, "lib", "*tinyspline*")): - copy2(bin_file, bin_dir) + # copy resulting files into bin_dir + for bin_file in glob(path.join(build_dir, "lib", "*tinyspline*")): + copy2(bin_file, bin_dir) - # create __init__.py in bin_dir - print("creating file: __init__.py") - init_file = open(path.join(bin_dir, "__init__.py"), "w+") - init_file.writelines("from .tinyspline import *\n") - init_file.close() + # create __init__.py in bin_dir + print("creating file: __init__.py") + init_file = open(path.join(bin_dir, "__init__.py"), "w+") + init_file.writelines("from .tinyspline import *\n") + init_file.close() - # distutils uses old-style classes, so no super() - _build_py.run(self) - finally: - if path.exists(build_dir): - print("removing cmake build directory") - rmtree(build_dir) + # distutils uses old-style classes, so no super() + _build_py.run(self) setup(name="tinyspline", - version="0.1.2", + version="0.1.3", description="Python binding for TinySpline", long_description=""" TinySpline is a C library for NURBS, B-Splines and Bezier curves