PROTON-2102: [Python] Work on proton build and python setup to build better python packages
- Now rely on setuptools
This gives us bdist_wheel
- Slim down source pacakge add swigged files to sources
- Never try to swig at build/install time only use source package swig files
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index aacb665..6414a31 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -174,7 +174,25 @@
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PN_C_INCLUDE_DIR} "${py_dist_dir}/include")
add_custom_command(TARGET py_src_dist
- COMMAND ${CMAKE_COMMAND} -E copy_directory ${PN_C_SOURCE_DIR} "${py_dist_dir}/src")
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${PN_C_SOURCE_DIR}/core "${py_dist_dir}/src/core")
+
+add_custom_command(TARGET py_src_dist
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${PN_C_SOURCE_DIR}/compiler "${py_dist_dir}/src/compiler")
+
+add_custom_command(TARGET py_src_dist
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${PN_C_SOURCE_DIR}/platform "${py_dist_dir}/src/platform")
+
+add_custom_command(TARGET py_src_dist
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${PN_C_SOURCE_DIR}/ssl "${py_dist_dir}/src/ssl")
+
+add_custom_command(TARGET py_src_dist
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${PN_C_SOURCE_DIR}/sasl "${py_dist_dir}/src/sasl")
+
+add_custom_command(TARGET py_src_dist
+ COMMAND ${CMAKE_COMMAND} -E copy ${PN_C_SOURCE_DIR}/encodings.h "${py_dist_dir}/src")
+
+add_custom_command(TARGET py_src_dist
+ COMMAND ${CMAKE_COMMAND} -E copy ${PN_C_SOURCE_DIR}/protocol.h "${py_dist_dir}/src")
add_custom_command(TARGET py_src_dist
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/README.rst "${py_dist_dir}")
diff --git a/python/setup.py.in b/python/setup.py.in
index 16fff1b..c5e1bbb 100644
--- a/python/setup.py.in
+++ b/python/setup.py.in
@@ -45,13 +45,13 @@
import os
import shutil
+from setuptools import setup, Extension
+from setuptools.command.sdist import sdist
+from setuptools.command.build_ext import build_ext
+from setuptools.command.build_py import build_py
+
import distutils.sysconfig as ds_sys
from distutils.ccompiler import new_compiler, get_default_compiler
-from distutils.core import setup, Extension
-from distutils.command.build import build
-from distutils.command.build_ext import build_ext
-from distutils.command.sdist import sdist
-from distutils import errors
from setuputils import log
from setuputils import misc
@@ -63,22 +63,26 @@
_PROTON_VERSION_STR = "%d.%d.%d" % _PROTON_VERSION
-class CheckSDist(sdist):
-
+class Swig(build_ext):
def run(self):
- self.distribution.run_command('configure')
+ """Run swig against the sources. This will cause swig to compile the
+ cproton.i file into a .c file called cproton_wrap.c, and create
+ cproton.py.
+ """
+ ext = Extension('_cproton',
+ sources=['cproton.i'],
+ swig_opts=['-threads', '-Iinclude'])
- # Append the source that was removed during
- # the configuration step.
- _cproton = self.distribution.ext_modules[-1]
- _cproton.sources.append('cproton.i')
+ if 'SWIG' in os.environ:
+ self.swig = os.environ['SWIG']
- try:
- sdist.run(self)
- finally:
- for src in ['cproton.py', 'cproton_wrap.c']:
- if os.path.exists(src):
- os.remove(src)
+ self.swig_sources(ext.sources, ext)
+
+
+class CheckSDist(sdist):
+ def run(self):
+ self.distribution.run_command('swig')
+ sdist.run(self)
class Configure(build_ext):
@@ -94,30 +98,6 @@
else:
return compiler.compiler_type
- def prepare_swig_wrap(self):
- """Run swig against the sources. This will cause swig to compile the
- cproton.i file into a .c file called cproton_wrap.c, and create
- cproton.py.
- """
- ext = self.distribution.ext_modules[-1]
-
- if 'SWIG' in os.environ:
- self.swig = os.environ['SWIG']
-
- try:
- # This will actually call swig to generate the files
- # and list the sources.
- self.swig_sources(ext.sources, ext)
- except (errors.DistutilsExecError, errors.DistutilsPlatformError) as e:
- if not (os.path.exists('cproton_wrap.c') or
- os.path.exists('cproton.py')):
- raise e
-
- # now remove the cproton.i file from the source list so we don't run
- # swig again.
- ext.sources = ext.sources[1:]
- ext.swig_opts = []
-
def use_bundled_proton(self):
"""The proper version of libqpid-proton-core is not installed on the system,
so use the included proton-c sources to build the extension
@@ -247,10 +227,6 @@
_cproton.include_dirs.append(build_include)
_cproton.include_dirs.append(proton_include)
- # swig will need to access the proton headers:
- _cproton.swig_opts.append('-I%s' % build_include)
- _cproton.swig_opts.append('-I%s' % proton_include)
-
# lastly replace the libqpid-proton-core dependency with libraries required
# by the Proton objects:
_cproton.libraries=libraries
@@ -283,38 +259,22 @@
else:
# Proton not installed or compatible, use bundled proton-c sources
self.use_bundled_proton()
- self.prepare_swig_wrap()
-class CustomBuildOrder(build):
- # The sole purpose of this class is to re-order
- # the commands execution so that `build_ext` is executed *before*
- # build_py. We need this to make sure `cproton.py` is generated
- # before the python modules are collected. Otherwise, it won't
- # be installed.
- sub_commands = [
- ('build_ext', build.has_ext_modules),
- ('build_py', build.has_pure_modules),
- ('build_clib', build.has_c_libraries),
- ('build_scripts', build.has_scripts),
- ]
+class BuildExtFirst(build_py):
+ def run(self):
+ # Make sure swig runs first and adds file etc
+ self.distribution.run_command('build_ext')
+ build_py.run(self)
class CheckingBuildExt(build_ext):
- """Subclass build_ext to build qpid-proton using `cmake`"""
-
def run(self):
- # Discover qpid-proton in the system
+ # Discover qpid-proton and prerequisites in the system
self.distribution.run_command('configure')
build_ext.run(self)
-# Override `build_ext` and add `configure`
-cmdclass = {'configure': Configure,
- 'build': CustomBuildOrder,
- 'build_ext': CheckingBuildExt,
- 'sdist': CheckSDist}
-
setup(name='python-qpid-proton',
version=_PROTON_VERSION_STR + os.environ.get('PROTON_VERSION_SUFFIX', ''),
description='An AMQP based messaging library.',
@@ -335,7 +295,13 @@
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8"],
- cmdclass=cmdclass,
+ cmdclass = {
+ 'configure': Configure,
+ 'swig': Swig,
+ 'build_py': BuildExtFirst,
+ 'build_ext': CheckingBuildExt,
+ 'sdist': CheckSDist
+ },
extras_require={
'opentracing': ['opentracing', 'jaeger_client']
},
@@ -343,7 +309,6 @@
# installation! If you make changes below, you may need to update the
# Configure class above
ext_modules=[Extension('_cproton',
- sources=['cproton.i', 'cproton_wrap.c'],
- swig_opts=['-threads'],
+ sources=['cproton_wrap.c'],
extra_compile_args=['-pthread'],
libraries=['qpid-proton-core'])])