Skip to content

Commit

Permalink
Get rid of PYTHON_LIBRARY and PYTHON_INCLUDE_DIR.
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcel Steinbeck committed May 12, 2017
1 parent f4e50f6 commit 69a2547
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 94 deletions.
57 changes: 19 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -153,30 +153,25 @@ your build directory to cross compile TinySpline to the desired platform:
cmake -DCMAKE_TOOLCHAIN_FILE=<path to root dir of tinypsline>/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:

```
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)
&nbsp;&nbsp; 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)
Expand Down
51 changes: 32 additions & 19 deletions library/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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).")



Expand All @@ -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})
Expand All @@ -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'")
Expand All @@ -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()



###############################################################################
Expand Down Expand Up @@ -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})
Expand Down Expand Up @@ -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}
Expand Down
72 changes: 35 additions & 37 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from os import path, chdir
from glob import glob
import subprocess
import sys

cmake_bin = "cmake"
cmake_build_config = "Release"
Expand All @@ -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
Expand Down

0 comments on commit 69a2547

Please sign in to comment.