import os import platform import sys from setuptools import setup, find_packages # --with-librabbitmq=: path to librabbitmq package if needed BASE_PATH = os.path.dirname(__file__) LRMQDIST = lambda *x: os.path.join(BASE_PATH, 'rabbitmq-c', *x) LRMQSRC = lambda *x: LRMQDIST('librabbitmq', *x) PYCP = lambda *x: os.path.join(BASE_PATH, 'Modules', '_librabbitmq', *x) def senv(*k__v, **kwargs): sep = kwargs.get('sep', ' ') restore = {} for k, v in k__v: prev = restore[k] = os.environ.get(k) os.environ[k] = (prev + sep if prev else '') + str(v) return dict((k, v) for k, v in restore.items() if v is not None) def create_builder(): from setuptools import Extension from distutils.command.build import build as _build cmd = None pkgdirs = [] # incdirs and libdirs get these libs = [] defs = [] incdirs = [] libdirs = [] def append_env(L, e): v = os.environ.get(e) if v and os.path.exists(v): L.append(v) append_env(pkgdirs, 'LIBRABBITMQ') # Hack up sys.argv, yay unprocessed = [] for arg in sys.argv[1:]: if arg == '--gen-setup': cmd = arg[2:] elif '=' in arg: if arg.startswith('--with-librabbitmq='): pkgdirs.append(arg.split('=', 1)[1]) continue unprocessed.append(arg) sys.argv[1:] = unprocessed incdirs.append(LRMQSRC()) if find_cmake() != "": incdirs.append(LRMQDIST('build', 'librabbitmq')) PyC_files = map(PYCP, [ 'connection.c', ]) librabbit_files = map(LRMQSRC, [ 'amqp_api.c', 'amqp_connection.c', 'amqp_consumer.c', 'amqp_framing.c', 'amqp_hostcheck.c', 'amqp_mem.c', 'amqp_socket.c', 'amqp_table.c', 'amqp_tcp_socket.c', 'amqp_time.c', 'amqp_url.c', ]) incdirs.append(LRMQDIST()) # for config.h if is_linux: # Issue #42 libs.append('rt') # -lrt for clock_gettime librabbitmq_ext = Extension( '_librabbitmq', sources=list(PyC_files) + list(librabbit_files), libraries=libs, include_dirs=incdirs, library_dirs=libdirs, define_macros=defs, ) # Hidden secret: # If environment variable GEN_SETUP is set, generate Setup file. if cmd == 'gen-setup': line = ' '.join(( librabbitmq_ext.name, ' '.join('-l' + lib for lib in librabbitmq_ext.libraries), ' '.join('-I' + incdir for incdir in librabbitmq_ext.include_dirs), ' '.join('-L' + libdir for libdir in librabbitmq_ext.library_dirs), ' '.join('-D' + name + ('=' + str(value), '')[value is None] for name, value in librabbitmq_ext.define_macros))) open('Setup', 'w').write(line + '\n') sys.exit(0) class build(_build): stdcflags = [ '-DHAVE_CONFIG_H', ] if os.environ.get('PEDANTIC'): # Python.h breaks -pedantic, so can only use it while developing. stdcflags.append('-pedantic -Werror') def run(self): from distutils import sysconfig here = os.path.abspath(os.getcwd()) config = sysconfig.get_config_vars() make = find_make() cmake = find_cmake() try: vars = {'ld': config['LDFLAGS'], 'c': config['CFLAGS']} for key in list(vars): vars[key] = vars[key].replace('-lSystem', '') # Python on Maverics sets this, but not supported on clang vars[key] = vars[key].replace('-mno-fused-madd', '') vars[key] = vars[key].replace( '-isysroot /Developer/SDKs/MacOSX10.6.sdk', '') restore = senv( ('CFLAGS', vars['c']), ('LDFLAGS', vars['ld']), ) try: if not os.path.isdir(os.path.join(LRMQDIST(), '.git')): print('- pull submodule rabbitmq-c...') if os.path.isfile('Makefile'): os.system(' '.join([make, 'submodules'])) else: os.system(' '.join(['git', 'clone', '-b', 'v0.8.0', 'https://github.com/alanxz/rabbitmq-c.git', 'rabbitmq-c'])) os.chdir(LRMQDIST()) if cmake == "" and not os.path.isfile('configure'): print('- autoreconf') os.system('autoreconf -i') if cmake == "" and not os.path.isfile('config.h'): print('- configure rabbitmq-c...') if os.system('/bin/sh configure --disable-tools \ --disable-docs --disable-dependency-tracking'): return if cmake: print('- cmake rabbitmq-c...') if os.system('mkdir -p build'): return os.chdir('build') if not os.path.isfile('Makefile'): if os.system(cmake + ' ..'): return if os.system(make + ' rabbitmq rabbitmq-static'): return finally: os.environ.update(restore) finally: os.chdir(here) restore = senv( ('CFLAGS', ' '.join(self.stdcflags)), ) try: _build.run(self) finally: os.environ.update(restore) return librabbitmq_ext, build def find_make(alt=('gmake', 'gnumake', 'make', 'nmake')): for path in os.environ['PATH'].split(':'): for make in (os.path.join(path, m) for m in alt): if os.path.isfile(make): return make def find_cmake(): for path in os.environ['PATH'].split(':'): make = os.path.join(path, 'cmake') if os.path.isfile(make): return make return "" if sys.version_info[0] < 3: with open(os.path.join(BASE_PATH, 'README.rst'), 'U') as f: long_description = f.read() else: with open(os.path.join(BASE_PATH, 'README.rst')) as f: long_description = f.read() distmeta = open(PYCP('distmeta.h')).read().strip().splitlines() distmeta = [item.split('\"')[1] for item in distmeta] version = distmeta[0].strip() author = distmeta[1].strip() contact = distmeta[2].strip() homepage = distmeta[3].strip() ext_modules = [] cmdclass = {} packages = [] goahead = False is_jython = sys.platform.startswith('java') is_pypy = hasattr(sys, 'pypy_version_info') is_win = platform.system() == 'Windows' is_linux = platform.system() == 'Linux' if is_jython or is_pypy or is_win: pass elif find_make(): try: librabbitmq_ext, build = create_builder() except Exception as exc: print('Could not create builder: %r' % (exc, )) raise else: goahead = True ext_modules = [librabbitmq_ext] cmdclass = {'build': build} packages = find_packages(exclude=['ez_setup', 'tests', 'tests.*']) if not goahead: ext_modules = [] cmdclass = {} packages = [] # 'install doesn't always call build for some reason if 'install' in sys.argv and 'build' not in sys.argv: _index = sys.argv.index('install') sys.argv[:] = ( sys.argv[:_index] + ['build', 'install'] + sys.argv[_index + 1:] ) # 'bdist_wheel doesn't always call build for some reason if 'bdist_wheel' in sys.argv and 'build' not in sys.argv: _index = sys.argv.index('bdist_wheel') sys.argv[:] = ( sys.argv[:_index] + ['build', 'bdist_wheel'] + sys.argv[_index + 1:] ) # 'bdist_egg doesn't always call build for some reason if 'bdist_egg' in sys.argv and 'build' not in sys.argv: _index = sys.argv.index('bdist_egg') sys.argv[:] = ( sys.argv[:_index] + ['build', 'bdist_egg'] + sys.argv[_index + 1:] ) # 'test doesn't always call build for some reason if 'test' in sys.argv and 'build' not in sys.argv: _index = sys.argv.index('test') sys.argv[:] = ( sys.argv[:_index] + ['build', 'test'] + sys.argv[_index + 1:] ) setup( name='librabbitmq', version=version, url=homepage, author=author, author_email=contact, license='MPL', description='AMQP Client using the rabbitmq-c library.', long_description=long_description, test_suite="tests", zip_safe=False, packages=packages, cmdclass=cmdclass, install_requires=[ 'amqp>=1.4.6', 'six>=1.0.0', ], ext_modules=ext_modules, classifiers=[ 'Development Status :: 5 - Production/Stable', 'Operating System :: POSIX', 'Operating System :: Microsoft :: Windows', 'Programming Language :: C', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: Implementation :: CPython', 'Intended Audience :: Developers', 'License :: OSI Approved :: Mozilla Public License 1.0 (MPL)', 'Topic :: Communications', 'Topic :: System :: Networking', 'Topic :: Software Development :: Libraries', ], )