Skip to content

Commit a554438

Browse files
committed
Added deployment to PyPI for python 3.5 and 3.6 to gitlab CI.
- added setup.py - moved versioning from CMakeLists.txt to Version.txt - updated pybind11 and glm bindings
1 parent 98bbb5e commit a554438

File tree

8 files changed

+206
-15
lines changed

8 files changed

+206
-15
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
!.gitignore
33
!.gitlab-ci.yml
44
build/
5+
dist/
56
demo
67
*.o
8+
*.egg-info
79
thirdparty/qhull
810
docs/html
911
docs/latex

.gitlab-ci.yml

+57
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
before_script:
2+
# Specify account details for PyPI
3+
- echo "[distutils]" > ~/.pypirc
4+
- echo "index-servers =" >> ~/.pypirc
5+
- echo " testpypi" >> ~/.pypirc
6+
- echo " pypi" >> ~/.pypirc
7+
- echo "[pypi]" >> ~/.pypirc
8+
- echo "repository=https://upload.pypi.org/legacy/" >> ~/.pypirc
9+
- echo "username=$PYPIUSER" >> ~/.pypirc
10+
- echo "password=$PYPIPASSWORD" >> ~/.pypirc
11+
- echo "[testpypi]" >> ~/.pypirc
12+
- echo "repository=https://test.pypi.org/legacy/" >> ~/.pypirc
13+
- echo "username=$PYPIUSER" >> ~/.pypirc
14+
- echo "password=$PYPIPASSWORD" >> ~/.pypirc
15+
116
Build (Ubuntu 16.04 / make / clang):
217
image: ubuntu:16.04
318
script:
@@ -105,3 +120,45 @@ Build (Debian 8 / make / gcc):
105120
script:
106121
- apt-get update -qq && apt-get install -y -qq git make gcc g++
107122
- CC=gcc CXX=g++ make
123+
124+
Build (Deploy from Ubuntu 16.04 / CMake / gcc / python-3.5):
125+
image: ubuntu:16.04
126+
script:
127+
# Install build tools
128+
- apt-get update -qq && apt-get install -y -qq git cmake gcc g++ python3 python3-pip ca-certificates
129+
- pip3 install setuptools twine
130+
# Pull submodules
131+
- git submodule update --init
132+
133+
# If on non-master branch, we add a dev-version tag
134+
- if [ "$CI_COMMIT_REF_NAME" != "master" ]; then export VFRENDERING_ADD_VERSION_EXTENSION=true; fi
135+
136+
# Build the package
137+
- python3 setup.py sdist bdist_wheel
138+
139+
# Upload to testpypi using twine
140+
# TODO: if [ "$MERGE_REQUEST" == "false" ]; then ...; fi
141+
- twine upload -r testpypi --skip-existing dist/*
142+
# If on master branch upload to pypi as well
143+
- if [ "$CI_COMMIT_REF_NAME" == "master" ]; then twine upload -r pypi --skip-existing dist/*; fi
144+
145+
Build (Deploy from Ubuntu 17.10 / CMake / gcc / python-3.6):
146+
image: ubuntu:17.10
147+
script:
148+
# Install build tools
149+
- apt-get update -qq && apt-get install -y -qq git cmake gcc g++ python3 python3-pip ca-certificates
150+
- pip3 install setuptools twine
151+
# Pull submodules
152+
- git submodule update --init
153+
154+
# If on non-master branch, we add a dev-version tag
155+
- if [ "$CI_COMMIT_REF_NAME" != "master" ]; then export VFRENDERING_ADD_VERSION_EXTENSION=true; fi
156+
157+
# Build the package
158+
- python3 setup.py sdist bdist_wheel
159+
160+
# Upload to testpypi using twine
161+
# TODO: if [ "$MERGE_REQUEST" == "false" ]; then ...; fi
162+
- twine upload -r testpypi --skip-existing dist/*
163+
# If on master branch upload to pypi as well
164+
- if [ "$CI_COMMIT_REF_NAME" == "master" ]; then twine upload -r pypi --skip-existing dist/*; fi

CMakeLists.txt

+12-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
22

3-
project(VFRendering VERSION 0.8.0)
3+
file(STRINGS "Version.txt" VFRENDERING_VERSION)
4+
project(VFRendering VERSION ${VFRENDERING_VERSION})
45

56
option(BUILD_DEMO "Whether or not a demo executable should be built" OFF)
67
option(BUILD_PYTHON_BINDINGS "Whether or not a binary python module should be built" OFF)
@@ -128,14 +129,17 @@ endif()
128129

129130
# Build Python bindings
130131
if (BUILD_PYTHON_BINDINGS)
132+
set(MODULE_NAME py${PROJECT_NAME})
131133
add_subdirectory(thirdparty/pybind11)
132-
pybind11_add_module(py${PROJECT_NAME} python/vfrendering_bindings.cpp)
134+
pybind11_add_module(${MODULE_NAME} python/vfrendering_bindings.cpp)
133135

134-
target_include_directories(py${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include)
135-
target_include_directories(py${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/thirdparty/pybind11/include)
136-
target_include_directories(py${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/thirdparty/glm/include)
137-
target_include_directories(py${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/thirdparty/glad/include)
138-
target_include_directories(py${PROJECT_NAME} PRIVATE ${qhull_INCLUDE_DIRS})
136+
target_compile_definitions(${MODULE_NAME} PUBLIC "-D${PROJECT_NAME}_VERSION=\"${${PROJECT_NAME}_VERSION}${MODULE_DEV_TAG}\"")
139137

140-
target_link_libraries(py${PROJECT_NAME} PRIVATE ${PROJECT_NAME})
138+
target_include_directories(${MODULE_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include)
139+
target_include_directories(${MODULE_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/thirdparty/pybind11/include)
140+
target_include_directories(${MODULE_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/thirdparty/glm/include)
141+
target_include_directories(${MODULE_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/thirdparty/glad/include)
142+
target_include_directories(${MODULE_NAME} PRIVATE ${qhull_INCLUDE_DIRS})
143+
144+
target_link_libraries(${MODULE_NAME} PRIVATE ${PROJECT_NAME})
141145
endif()

Version.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0.8.0

python/pybind11_glm.hpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ struct type_caster<glm::tvec2<T, P>>
7070
}
7171

7272
// Specifies the doc-string for the type in Python:
73-
PYBIND11_TYPE_CASTER(vector_type, _("numpy.ndarray[") + npy_format_descriptor<Scalar>::name() +
73+
PYBIND11_TYPE_CASTER(vector_type, _("numpy.ndarray[") + npy_format_descriptor<Scalar>::name +
7474
_("[") + _<num_elements>() + _("]]"));
7575
};
7676

@@ -114,7 +114,7 @@ struct type_caster<glm::tvec3<T, P>>
114114
}
115115

116116
// Specifies the doc-string for the type in Python:
117-
PYBIND11_TYPE_CASTER(vector_type, _("numpy.ndarray[") + npy_format_descriptor<Scalar>::name() +
117+
PYBIND11_TYPE_CASTER(vector_type, _("numpy.ndarray[") + npy_format_descriptor<Scalar>::name +
118118
_("[") + _<num_elements>() + _("]]"));
119119
};
120120

@@ -158,7 +158,7 @@ struct type_caster<glm::tvec4<T, P>>
158158
}
159159

160160
// Specifies the doc-string for the type in Python:
161-
PYBIND11_TYPE_CASTER(vector_type, _("numpy.ndarray[") + npy_format_descriptor<Scalar>::name() +
161+
PYBIND11_TYPE_CASTER(vector_type, _("numpy.ndarray[") + npy_format_descriptor<Scalar>::name +
162162
_("[") + _<num_elements>() + _("]]"));
163163
};
164164

@@ -206,7 +206,7 @@ struct type_caster<glm::tmat3x3<T, P>>
206206
}
207207

208208
// Specifies the doc-string for the type in Python:
209-
PYBIND11_TYPE_CASTER(matrix_type, _("numpy.ndarray[") + npy_format_descriptor<Scalar>::name() +
209+
PYBIND11_TYPE_CASTER(matrix_type, _("numpy.ndarray[") + npy_format_descriptor<Scalar>::name +
210210
_("[") + _<num_rows>() + _(", ") + _<num_cols>() + _("]]"));
211211
};
212212

@@ -254,7 +254,7 @@ struct type_caster<glm::tmat4x3<T, P>>
254254
}
255255

256256
// Specifies the doc-string for the type in Python:
257-
PYBIND11_TYPE_CASTER(matrix_type, _("numpy.ndarray[") + npy_format_descriptor<Scalar>::name() +
257+
PYBIND11_TYPE_CASTER(matrix_type, _("numpy.ndarray[") + npy_format_descriptor<Scalar>::name +
258258
_("[") + _<num_rows>() + _(", ") + _<num_cols>() + _("]]"));
259259
};
260260

@@ -302,7 +302,7 @@ struct type_caster<glm::tmat4x4<T, P>>
302302
}
303303

304304
// Specifies the doc-string for the type in Python:
305-
PYBIND11_TYPE_CASTER(matrix_type, _("numpy.ndarray[") + npy_format_descriptor<Scalar>::name() +
305+
PYBIND11_TYPE_CASTER(matrix_type, _("numpy.ndarray[") + npy_format_descriptor<Scalar>::name +
306306
_("[") + _<num_rows>() + _(", ") + _<num_cols>() + _("]]"));
307307
};
308308

python/vfrendering_bindings.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ typedef unsigned int index_type;
2424

2525
PYBIND11_MODULE(pyVFRendering, m)
2626
{
27+
#ifdef VFRendering_VERSION
28+
m.attr("__version__") = VFRendering_VERSION;
29+
#else
30+
m.attr("__version__") = "dev";
31+
#endif
32+
33+
2734
// Module docstring
2835
m.doc() = "VFRendering is a C++ library for rendering vectorfields using OpenGL,"
2936
"wrapped for Python using pybind11.";

setup.py

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import os
2+
import re
3+
import sys
4+
import platform
5+
import subprocess
6+
import datetime
7+
8+
from setuptools import setup, Extension
9+
from setuptools.command.build_ext import build_ext
10+
from wheel.bdist_wheel import bdist_wheel as bdist_wheel_
11+
from distutils.util import get_platform
12+
from distutils.version import LooseVersion
13+
14+
15+
def get_git_commit_datetime():
16+
try:
17+
commit_hash = subprocess.check_output("git rev-parse HEAD", shell=True, stderr=subprocess.STDOUT).decode("utf-8").strip()
18+
commit_datetime = subprocess.check_output("git show -s --format=%ci "+commit_hash, shell=True, stderr=subprocess.STDOUT).decode("utf-8").strip()
19+
print(commit_datetime)
20+
datetime_object = datetime.datetime.strptime(commit_datetime, '%Y-%m-%d %H:%M:%S +%f')
21+
print("{:%Y%m%d%H%M%S}".format(datetime_object))
22+
return "{:%Y%m%d%H%M%S}".format(datetime_object)
23+
except subprocess.CalledProcessError as cpe:
24+
print(cpe.output)
25+
return "00000000000000"
26+
27+
28+
class CMakeExtension(Extension):
29+
def __init__(self, name, sourcedir=''):
30+
Extension.__init__(self, name, sources=[])
31+
self.sourcedir = os.path.abspath(sourcedir)
32+
33+
34+
class CMakeBuild(build_ext):
35+
def run(self):
36+
try:
37+
out = subprocess.check_output(['cmake', '--version'])
38+
except OSError:
39+
raise RuntimeError("CMake must be installed to build the following extensions: " +
40+
", ".join(e.name for e in self.extensions))
41+
42+
if platform.system() == "Windows":
43+
cmake_version = LooseVersion(re.search(r'version\s*([\d.]+)', out.decode()).group(1))
44+
if cmake_version < '3.1.0':
45+
raise RuntimeError("CMake >= 3.1.0 is required on Windows")
46+
47+
for ext in self.extensions:
48+
self.build_extension(ext)
49+
50+
def build_extension(self, ext):
51+
extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name)))
52+
cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir,
53+
'-DPYTHON_EXECUTABLE=' + sys.executable,
54+
'-DBUILD_DEMO=OFF',
55+
'-DBUILD_PYTHON_BINDINGS=ON',
56+
'-DMODULE_DEV_TAG='+version_extension]
57+
58+
cfg = 'Debug' if self.debug else 'Release'
59+
build_args = ['--config', cfg]
60+
61+
if platform.system() == "Windows":
62+
cmake_args += ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir)]
63+
if sys.maxsize > 2**32:
64+
cmake_args += ['-A', 'x64']
65+
build_args += ['--', '/m']
66+
else:
67+
cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg]
68+
build_args += ['--', '-j2']
69+
70+
env = os.environ.copy()
71+
env['CXXFLAGS'] = '{} -DVERSION_INFO=\\"{}\\"'.format(env.get('CXXFLAGS', ''),
72+
self.distribution.get_version())
73+
if not os.path.exists(self.build_temp):
74+
os.makedirs(self.build_temp)
75+
76+
subprocess.check_call(['cmake', ext.sourcedir] + cmake_args, cwd=self.build_temp, env=env)
77+
subprocess.check_call(['cmake', '--build', '.'] + build_args, cwd=self.build_temp)
78+
79+
80+
class bdist_wheel(bdist_wheel_):
81+
def finalize_options(self):
82+
from sys import platform as _platform
83+
platform_name = get_platform()
84+
if _platform == "linux" or _platform == "linux2":
85+
# Linux
86+
platform_name = 'manylinux1_x86_64'
87+
88+
bdist_wheel_.finalize_options(self)
89+
self.universal = True
90+
self.plat_name_supplied = True
91+
self.plat_name = platform_name
92+
93+
94+
# Read version from file
95+
vfrendering_version = open('Version.txt').read()
96+
97+
98+
# Set extra version tag for dev builds if corresponding env variable is set
99+
version_extension = ""
100+
add_version_extension = os.environ.get("VFRENDERING_ADD_VERSION_EXTENSION", "")
101+
if add_version_extension.lower() in ("yes", "true", "t", "1"):
102+
timepoint_string = get_git_commit_datetime()
103+
if timepoint_string == "00000000000000":
104+
timepoint_string = "{:%Y%m%d%H%M}".format(datetime.datetime.now())
105+
version_extension = ".dev" + timepoint_string
106+
print("setup.py: package version suffix = ", version_extension)
107+
108+
109+
# Setup configuration
110+
setup(
111+
name='pyVFRendering',
112+
version=vfrendering_version + version_extension,
113+
author='Florian Rhiem',
114+
author_email='f.rhiem@fz-juelich.de',
115+
url='https://github.com/FlorianRhiem/VFRendering',
116+
description='VFRendering python bindings',
117+
long_description='',
118+
ext_modules=[CMakeExtension('pyVFRendering')],
119+
cmdclass = {'build_ext': CMakeBuild, 'bdist_wheel': bdist_wheel},
120+
)

thirdparty/pybind11

0 commit comments

Comments
 (0)