diff --git a/.gitignore b/.gitignore
index 1890c1da5..c8794cba3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,14 @@
*.pyc
-*.c
+zmq/*/*.c
build
dist
conf
+bundled_libzmq
*.egg-info
*.so
*.pyd
*.dll
+*.dylib
docs/source/api/generated
docs/gh-pages
setup.cfg
diff --git a/MANIFEST.in b/MANIFEST.in
index 58ec44665..f9b0747d9 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -7,12 +7,12 @@ include setup.cfg.template
include setup.py
include setupegg.py
include zmqversion.py
-include buildutils.py
graft docs
prune docs/build
prune docs/gh-pages
+graft buildutils
graft examples
graft zmq
graft perf
diff --git a/buildutils.py b/buildutils.py
deleted file mode 100644
index 868d42f80..000000000
--- a/buildutils.py
+++ /dev/null
@@ -1,261 +0,0 @@
-"""Detect zmq version"""
-#-----------------------------------------------------------------------------
-# Copyright (C) 2011 Brian Granger, Min Ragan-Kelley
-#
-# This file is part of pyzmq, copied and adapted from h5py.
-# h5py source used under the New BSD license
-#
-# h5py:
-#
-# Distributed under the terms of the New BSD License. The full license is in
-# the file COPYING.BSD, distributed as part of this software.
-#-----------------------------------------------------------------------------
-
-import shutil
-import sys
-import os
-import logging
-import pickle
-import platform
-from distutils import ccompiler
-from distutils.sysconfig import customize_compiler
-from subprocess import Popen, PIPE
-
-try:
- from configparser import ConfigParser
-except:
- from ConfigParser import ConfigParser
-
-pjoin = os.path.join
-
-#-----------------------------------------------------------------------------
-# Logging (adapted from h5py: http://h5py.googlecode.com)
-#-----------------------------------------------------------------------------
-logger = logging.getLogger()
-logger.addHandler(logging.StreamHandler(sys.stderr))
-
-def debug(what):
- pass
-
-def fatal(instring, code=1):
- logger.error("Fatal: "+instring)
- exit(code)
-
-def warn(instring):
- logger.error("Warning: "+instring)
-
-
-#-----------------------------------------------------------------------------
-# Utility functions (adapted from h5py: http://h5py.googlecode.com)
-#-----------------------------------------------------------------------------
-
-def detect_zmq(basedir, **compiler_attrs):
- """Compile, link & execute a test program, in empty directory `basedir`.
-
- The C compiler will be updated with any keywords given via setattr.
-
- Parameters
- ----------
-
- basedir : path
- The location where the test program will be compiled and run
- **compiler_attrs : dict
- Any extra compiler attributes, which will be set via ``setattr(cc)``.
-
- Returns
- -------
-
- A dict of properties for zmq compilation, with the following two keys:
-
- vers : tuple
- The ZMQ version as a tuple of ints, e.g. (2,2,0)
- options : dict
- The compiler options used to compile the test function, e.g. `include_dirs`,
- `library_dirs`, `libs`, etc.
- """
-
- cc = ccompiler.new_compiler()
- customize_compiler(cc)
- for name, val in compiler_attrs.items():
- setattr(cc, name, val)
-
- cfile = pjoin(basedir, 'vers.c')
- efile = pjoin(basedir, 'vers')
-
- f = open(cfile, 'w')
- try:
- f.write(
-r"""
-#include
-#include "zmq.h"
-
-int main(void){
- int major, minor, patch;
- zmq_version(&major, &minor, &patch);
- fprintf(stdout, "vers: %d.%d.%d\n", major, minor, patch);
- return 0;
-}
-""")
- finally:
- f.close()
-
- cpreargs = lpreargs = None
- if sys.platform == 'darwin':
- # use appropriate arch for comiler
- if platform.architecture()[0]=='32bit':
- cpreargs = ['-arch','i386']
- lpreargs = ['-arch', 'i386', '-undefined', 'dynamic_lookup']
- else:
- # allow for missing UB arch, since it will still work:
- lpreargs = ['-undefined', 'dynamic_lookup']
-
- objs = cc.compile([cfile],extra_preargs=cpreargs)
- cc.link_executable(objs, efile, extra_preargs=lpreargs)
-
- result = Popen(efile, stdout=PIPE, stderr=PIPE)
- so, se = result.communicate()
- # for py3k:
- so = so.decode()
- se = se.decode()
- if result.returncode:
- msg = "Error running version detection script:\n%s\n%s" % (so,se)
- logging.error(msg)
- raise IOError(msg)
-
- handlers = {'vers': lambda val: tuple(int(v) for v in val.split('.'))}
-
- props = {}
- for line in (x for x in so.split('\n') if x):
- key, val = line.split(':')
- props[key] = handlers[key](val)
-
- props['options'] = compiler_attrs
- return props
-
-def localpath(*args):
- plist = [os.path.dirname(__file__)]+list(args)
- return os.path.abspath(pjoin(*plist))
-
-def loadpickle(name):
- """ Load object from pickle file, or None if it can't be opened """
- name = pjoin('conf', name)
- try:
- f = open(name,'rb')
- except IOError:
- # raise
- return None
- try:
- return pickle.load(f)
- except Exception:
- # raise
- return None
- finally:
- f.close()
-
-def savepickle(name, data):
- """ Save to pickle file, exiting if it can't be written """
- if not os.path.exists('conf'):
- os.mkdir('conf')
- name = pjoin('conf', name)
- try:
- f = open(name, 'wb')
- except IOError:
- fatal("Can't open pickle file \"%s\" for writing" % name)
- try:
- pickle.dump(data, f, 0)
- finally:
- f.close()
-
-def v_str(v_tuple):
- """turn (2,0,1) into '2.0.1'."""
- return ".".join(str(x) for x in v_tuple)
-
-def get_eargs():
- """ Look for options in environment vars """
-
- settings = {}
-
- zmq = os.environ.get("ZMQ_DIR", '')
- if zmq != '':
- debug("Found environ var ZMQ_DIR=%s" % zmq)
- settings['zmq'] = zmq
-
- return settings
-
-def get_cfg_args():
- """ Look for options in setup.cfg """
-
- settings = {}
- zmq = ''
- if not os.path.exists('setup.cfg'):
- return settings
- cfg = ConfigParser()
- cfg.read('setup.cfg')
- if 'build_ext' in cfg.sections() and \
- cfg.has_option('build_ext', 'include_dirs'):
- includes = cfg.get('build_ext', 'include_dirs')
- include = includes.split(os.pathsep)[0]
- if include.endswith('include') and os.path.isdir(include):
- zmq = include[:-8]
- if zmq != '':
- debug("Found ZMQ=%s in setup.cfg" % zmq)
- settings['zmq'] = zmq
-
- return settings
-
-def get_cargs():
- """ Look for global options in the command line """
- settings = loadpickle('buildconf.pickle')
- if settings is None: settings = {}
- for arg in sys.argv[:]:
- if arg.find('--zmq=') == 0:
- zmq = arg.split('=')[-1]
- if zmq.lower() == 'default':
- settings.pop('zmq', None)
- else:
- settings['zmq'] = zmq
- sys.argv.remove(arg)
- savepickle('buildconf.pickle', settings)
- return settings
-
-def discover_settings():
- """ Discover custom settings for ZMQ path"""
- settings = get_cfg_args() # lowest priority
- settings.update(get_eargs())
- settings.update(get_cargs()) # highest priority
- return settings.get('zmq')
-
-def copy_and_patch_libzmq(ZMQ, libzmq):
- """copy libzmq into source dir, and patch it if necessary.
-
- This command is necessary prior to running a bdist on Linux or OS X.
- """
- if sys.platform.startswith('win'):
- return
- # copy libzmq into zmq for bdist
- local = localpath('zmq',libzmq)
- if ZMQ is None and not os.path.exists(local):
- fatal("Please specify zmq prefix via `setup.py configure --zmq=/path/to/zmq` "
- "or copy libzmq into zmq/ manually prior to running bdist.")
- try:
- # resolve real file through symlinks
- lib = os.path.realpath(pjoin(ZMQ, 'lib', libzmq))
- print ("copying %s -> %s"%(lib, local))
- shutil.copy(lib, local)
- except Exception:
- if not os.path.exists(local):
- fatal("Could not copy libzmq into zmq/, which is necessary for bdist. "
- "Please specify zmq prefix via `setup.py configure --zmq=/path/to/zmq` "
- "or copy libzmq into zmq/ manually.")
-
- if sys.platform == 'darwin':
- # patch install_name on darwin, instead of using rpath
- cmd = ['install_name_tool', '-id', '@loader_path/../%s'%libzmq, local]
- try:
- p = Popen(cmd, stdout=PIPE,stderr=PIPE)
- except OSError:
- fatal("install_name_tool not found, cannot patch libzmq for bundling.")
- out,err = p.communicate()
- if p.returncode:
- fatal("Could not patch bundled libzmq install_name: %s"%err, p.returncode)
-
diff --git a/buildutils/__init__.py b/buildutils/__init__.py
new file mode 100644
index 000000000..df449d23e
--- /dev/null
+++ b/buildutils/__init__.py
@@ -0,0 +1,9 @@
+"""utilities for building pyzmq.
+
+Largely adapted from h5py
+"""
+
+from .msg import *
+from .config import *
+from .detect import *
+from .bundle import *
diff --git a/buildutils/bundle.py b/buildutils/bundle.py
new file mode 100644
index 000000000..eb1fb02ae
--- /dev/null
+++ b/buildutils/bundle.py
@@ -0,0 +1,207 @@
+"""utilities for fetching build dependencies."""
+#-----------------------------------------------------------------------------
+# Copyright (c) 2012 Min Ragan-Kelley
+#
+# This file is part of pyzmq
+#
+# Distributed under the terms of the New BSD License. The full license is in
+# the file COPYING.BSD, distributed as part of this software.
+#
+# This bundling code is largely adapted from pyzmq-static's get.sh by
+# Brandon Craig-Rhodes, which is itself BSD licensed.
+#-----------------------------------------------------------------------------
+
+#-----------------------------------------------------------------------------
+# Imports
+#-----------------------------------------------------------------------------
+
+import os
+import shutil
+import sys
+import tarfile
+from subprocess import Popen, PIPE
+
+try:
+ # py2
+ from urllib2 import urlopen
+except ImportError:
+ # py3
+ from urllib.request import urlopen
+
+from .msg import fatal, debug, info, warn
+
+pjoin = os.path.join
+
+#-----------------------------------------------------------------------------
+# Constants
+#-----------------------------------------------------------------------------
+
+bundled_version = (2,2,0)
+libzmq = "zeromq-%i.%i.%i.tar.gz" % (bundled_version)
+libzmq_url = "http://download.zeromq.org/" + libzmq
+util = "util-linux-2.21.tar.gz"
+util_url = "http://www.kernel.org/pub/linux/utils/util-linux/v2.21/" + util
+
+HERE = os.path.dirname(__file__)
+ROOT = os.path.dirname(HERE)
+
+#-----------------------------------------------------------------------------
+# functions
+#-----------------------------------------------------------------------------
+
+
+def untgz(archive):
+ return archive.replace('.tar.gz', '')
+
+def localpath(*args):
+ """construct an absolute path from a list relative to the root pyzmq directory"""
+ plist = [ROOT] + list(args)
+ return os.path.abspath(pjoin(*plist))
+
+def fetch_archive(savedir, url, fname, force=False):
+ """download an archive to a specific location"""
+ dest = pjoin(savedir, fname)
+ if os.path.exists(dest) and not force:
+ info("already have %s" % fname)
+ return dest
+ info("fetching %s into %s" % (url, savedir))
+ if not os.path.exists(savedir):
+ os.makedirs(savedir)
+ req = urlopen(url)
+ with open(dest, 'wb') as f:
+ f.write(req.read())
+ return dest
+
+def fetch_libzmq(savedir):
+ """download and extract libzmq"""
+ dest = pjoin(savedir, 'zeromq')
+ if os.path.exists(dest):
+ info("already have %s" % dest)
+ return
+ fname = fetch_archive(savedir, libzmq_url, libzmq)
+ tf = tarfile.open(fname)
+ with_version = pjoin(savedir, tf.firstmember.path)
+ tf.extractall(savedir)
+ tf.close()
+ # remove version suffix:
+ shutil.move(with_version, dest)
+
+def stage_platform_hpp(zmqroot):
+ """stage platform.hpp into libzmq sources
+
+ Tries ./configure first (except on Windows),
+ then falls back on included platform.hpp previously generated.
+ """
+
+ platform_hpp = pjoin(zmqroot, 'src', 'platform.hpp')
+ if os.path.exists(platform_hpp):
+ info("already have platform.hpp")
+ return
+ if os.name == 'nt':
+ # stage msvc platform header
+ platform_dir = pjoin(zmqroot, 'builds', 'msvc')
+ else:
+ info("attempting ./configure to generate platform.hpp")
+
+ p = Popen('./configure', cwd=zmqroot, shell=True,
+ stdout=PIPE, stderr=PIPE,
+ )
+ o,e = p.communicate()
+ if p.returncode:
+ warn("failed to configure libzmq:\n%s" % e)
+ if sys.platform == 'darwin':
+ platform_dir = pjoin(HERE, 'include_darwin')
+ elif sys.platform.startswith('freebsd'):
+ platform_dir = pjoin(HERE, 'include_freebsd')
+ else:
+ platform_dir = pjoin(HERE, 'include_linux')
+ else:
+ return
+
+ info("staging platform.hpp from: %s" % platform_dir)
+ shutil.copy(pjoin(platform_dir, 'platform.hpp'), platform_hpp)
+
+
+def fetch_uuid(savedir):
+ """download, extract, and patch libuuid sources"""
+ dest = pjoin(savedir, 'uuid')
+ if os.path.exists(dest):
+ info("already have %s" % dest)
+ return
+
+ fname = fetch_archive(savedir, util_url, util)
+ tf = tarfile.open(fname)
+ util_name = untgz(util)
+ uuid_path = util_name+'/libuuid/src'
+ uuid = filter(
+ lambda m: m.name.startswith(uuid_path) and not m.name.endswith("nt.c"),
+ tf.getmembers()
+ )
+ # uuid_members = map(tf.getmember, uuid_names)
+ tf.extractall(savedir, uuid)
+ if os.path.exists(dest):
+ shutil.rmtree(dest)
+ shutil.move(pjoin(savedir, util_name, 'libuuid', 'src'), dest)
+ shutil.rmtree(pjoin(savedir, util_name))
+
+ patch_uuid(dest)
+
+
+def patch_uuid(uuid_dir):
+ """patch uuid.h with a few defines
+
+ from pyzmq-static
+ """
+ info("patching gen_uuid.c")
+ gen_uuid = pjoin(uuid_dir, "gen_uuid.c")
+ with open(gen_uuid) as f:
+ lines = f.readlines()
+
+ if 'pyzmq-patch' in lines[0]:
+ info("already patched")
+ return
+ else:
+ lines.insert(0, "// end pyzmq-patch\n")
+ for h in ('UNISTD', 'STDLIB', 'SYS_FILE'):
+ lines.insert(0, "#define HAVE_%s_H\n" % h)
+ lines.insert(0, "// begin pyzmq-patch\n")
+
+ with open(gen_uuid, 'w') as f:
+ f.writelines(lines)
+
+
+
+def copy_and_patch_libzmq(ZMQ, libzmq):
+ """copy libzmq into source dir, and patch it if necessary.
+
+ This command is necessary prior to running a bdist on Linux or OS X.
+ """
+ if sys.platform.startswith('win'):
+ return
+ # copy libzmq into zmq for bdist
+ local = localpath('zmq',libzmq)
+ if ZMQ is None and not os.path.exists(local):
+ fatal("Please specify zmq prefix via `setup.py configure --zmq=/path/to/zmq` "
+ "or copy libzmq into zmq/ manually prior to running bdist.")
+ try:
+ # resolve real file through symlinks
+ lib = os.path.realpath(pjoin(ZMQ, 'lib', libzmq))
+ print ("copying %s -> %s"%(lib, local))
+ shutil.copy(lib, local)
+ except Exception:
+ if not os.path.exists(local):
+ fatal("Could not copy libzmq into zmq/, which is necessary for bdist. "
+ "Please specify zmq prefix via `setup.py configure --zmq=/path/to/zmq` "
+ "or copy libzmq into zmq/ manually.")
+
+ if sys.platform == 'darwin':
+ # patch install_name on darwin, instead of using rpath
+ cmd = ['install_name_tool', '-id', '@loader_path/../%s'%libzmq, local]
+ try:
+ p = Popen(cmd, stdout=PIPE,stderr=PIPE)
+ except OSError:
+ fatal("install_name_tool not found, cannot patch libzmq for bundling.")
+ out,err = p.communicate()
+ if p.returncode:
+ fatal("Could not patch bundled libzmq install_name: %s"%err, p.returncode)
+
diff --git a/buildutils/config.py b/buildutils/config.py
new file mode 100644
index 000000000..ec1e62d25
--- /dev/null
+++ b/buildutils/config.py
@@ -0,0 +1,111 @@
+"""Config functions"""
+#-----------------------------------------------------------------------------
+# Copyright (C) 2011 Brian Granger, Min Ragan-Kelley
+#
+# This file is part of pyzmq, copied and adapted from h5py.
+# h5py source used under the New BSD license
+#
+# h5py:
+#
+# Distributed under the terms of the New BSD License. The full license is in
+# the file COPYING.BSD, distributed as part of this software.
+#-----------------------------------------------------------------------------
+
+import sys
+import os
+import json
+
+try:
+ from configparser import ConfigParser
+except:
+ from ConfigParser import ConfigParser
+
+pjoin = os.path.join
+from .msg import debug, fatal, warn
+
+#-----------------------------------------------------------------------------
+# Utility functions (adapted from h5py: http://h5py.googlecode.com)
+#-----------------------------------------------------------------------------
+
+
+def load_config(name):
+ """Load config dict from JSON"""
+ fname = pjoin('conf', name+'.json')
+ if not os.path.exists(fname):
+ return None
+ try:
+ with open(fname) as f:
+ cfg = json.load(f)
+ except Exception as e:
+ warn("Couldn't load %s: %s" % (fname, e))
+ cfg = None
+ return cfg
+
+
+def save_config(name, data):
+ """Save config dict to JSON"""
+ if not os.path.exists('conf'):
+ os.mkdir('conf')
+ fname = pjoin('conf', name+'.json')
+ with open(fname, 'w') as f:
+ json.dump(data, f, indent=2)
+
+
+def v_str(v_tuple):
+ """turn (2,0,1) into '2.0.1'."""
+ return ".".join(str(x) for x in v_tuple)
+
+def get_eargs():
+ """ Look for options in environment vars """
+
+ settings = {}
+
+ zmq = os.environ.get("ZMQ_DIR", '')
+ if zmq != '':
+ debug("Found environ var ZMQ_DIR=%s" % zmq)
+ settings['zmq'] = zmq
+
+ return settings
+
+def get_cfg_args():
+ """ Look for options in setup.cfg """
+
+ settings = {}
+ zmq = ''
+ if not os.path.exists('setup.cfg'):
+ return settings
+ cfg = ConfigParser()
+ cfg.read('setup.cfg')
+ if 'build_ext' in cfg.sections() and \
+ cfg.has_option('build_ext', 'include_dirs'):
+ includes = cfg.get('build_ext', 'include_dirs')
+ include = includes.split(os.pathsep)[0]
+ if include.endswith('include') and os.path.isdir(include):
+ zmq = include[:-8]
+ if zmq != '':
+ debug("Found ZMQ=%s in setup.cfg" % zmq)
+ settings['zmq'] = zmq
+
+ return settings
+
+def get_cargs():
+ """ Look for global options in the command line """
+ settings = load_config('buildconf')
+ if settings is None: settings = {}
+ for arg in sys.argv[:]:
+ if arg.find('--zmq=') == 0:
+ zmq = arg.split('=')[-1]
+ if zmq.lower() in ('default', 'auto', ''):
+ settings.pop('zmq', None)
+ else:
+ settings['zmq'] = zmq
+ sys.argv.remove(arg)
+ save_config('buildconf', settings)
+ return settings
+
+def discover_settings():
+ """ Discover custom settings for ZMQ path"""
+ settings = get_cfg_args() # lowest priority
+ settings.update(get_eargs())
+ settings.update(get_cargs()) # highest priority
+ return settings.get('zmq')
diff --git a/buildutils/detect.py b/buildutils/detect.py
new file mode 100644
index 000000000..ed95d041c
--- /dev/null
+++ b/buildutils/detect.py
@@ -0,0 +1,96 @@
+"""Detect zmq version"""
+#-----------------------------------------------------------------------------
+# Copyright (C) 2011 Brian Granger, Min Ragan-Kelley
+#
+# This file is part of pyzmq, copied and adapted from h5py.
+# h5py source used under the New BSD license
+#
+# h5py:
+#
+# Distributed under the terms of the New BSD License. The full license is in
+# the file COPYING.BSD, distributed as part of this software.
+#-----------------------------------------------------------------------------
+
+import shutil
+import sys
+import os
+import logging
+import platform
+from distutils import ccompiler
+from distutils.sysconfig import customize_compiler
+from subprocess import Popen, PIPE
+
+pjoin = os.path.join
+
+#-----------------------------------------------------------------------------
+# Utility functions (adapted from h5py: http://h5py.googlecode.com)
+#-----------------------------------------------------------------------------
+
+def detect_zmq(basedir, **compiler_attrs):
+ """Compile, link & execute a test program, in empty directory `basedir`.
+
+ The C compiler will be updated with any keywords given via setattr.
+
+ Parameters
+ ----------
+
+ basedir : path
+ The location where the test program will be compiled and run
+ **compiler_attrs : dict
+ Any extra compiler attributes, which will be set via ``setattr(cc)``.
+
+ Returns
+ -------
+
+ A dict of properties for zmq compilation, with the following two keys:
+
+ vers : tuple
+ The ZMQ version as a tuple of ints, e.g. (2,2,0)
+ settings : dict
+ The compiler options used to compile the test function, e.g. `include_dirs`,
+ `library_dirs`, `libs`, etc.
+ """
+
+ cc = ccompiler.new_compiler()
+ customize_compiler(cc)
+ for name, val in compiler_attrs.items():
+ setattr(cc, name, val)
+
+ cfile = pjoin(basedir, 'vers.c')
+ efile = pjoin(basedir, 'vers')
+
+ shutil.copy(pjoin(os.path.dirname(__file__), 'vers.c'), cfile)
+
+ cpreargs = lpreargs = None
+ if sys.platform == 'darwin':
+ # use appropriate arch for compiler
+ if platform.architecture()[0]=='32bit':
+ cpreargs = ['-arch','i386']
+ lpreargs = ['-arch', 'i386', '-undefined', 'dynamic_lookup']
+ else:
+ # allow for missing UB arch, since it will still work:
+ lpreargs = ['-undefined', 'dynamic_lookup']
+
+ objs = cc.compile([cfile],extra_preargs=cpreargs)
+ cc.link_executable(objs, efile, extra_preargs=lpreargs)
+
+ result = Popen(efile, stdout=PIPE, stderr=PIPE)
+ so, se = result.communicate()
+ # for py3k:
+ so = so.decode()
+ se = se.decode()
+ if result.returncode:
+ msg = "Error running version detection script:\n%s\n%s" % (so,se)
+ logging.error(msg)
+ raise IOError(msg)
+
+ handlers = {'vers': lambda val: tuple(int(v) for v in val.split('.'))}
+
+ props = {}
+ for line in (x for x in so.split('\n') if x):
+ key, val = line.split(':')
+ props[key] = handlers[key](val)
+
+ props['settings'] = compiler_attrs
+ return props
+
diff --git a/buildutils/include_darwin/platform.hpp b/buildutils/include_darwin/platform.hpp
new file mode 100644
index 000000000..212cfabee
--- /dev/null
+++ b/buildutils/include_darwin/platform.hpp
@@ -0,0 +1,229 @@
+/* src/platform.hpp. Generated from platform.hpp.in by configure. */
+/* src/platform.hpp.in. Generated from configure.in by autoheader. */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the `freeifaddrs' function. */
+#define HAVE_FREEIFADDRS 1
+
+/* Define to 1 if you have the `getifaddrs' function. */
+#define HAVE_GETIFADDRS 1
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_IFADDRS_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `crypto' library (-lcrypto). */
+/* #undef HAVE_LIBCRYPTO */
+
+/* Define to 1 if you have the `iphlpapi' library (-liphlpapi). */
+/* #undef HAVE_LIBIPHLPAPI */
+
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+/* #undef HAVE_LIBNSL */
+
+/* Define to 1 if you have the `pthread' library (-lpthread). */
+#define HAVE_LIBPTHREAD 1
+
+/* Define to 1 if you have the `rpcrt4' library (-lrpcrt4). */
+/* #undef HAVE_LIBRPCRT4 */
+
+/* Define to 1 if you have the `rt' library (-lrt). */
+/* #undef HAVE_LIBRT */
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
+
+/* Define to 1 if you have the `uuid' library (-luuid). */
+/* #undef HAVE_LIBUUID */
+
+/* Define to 1 if you have the `ws2_32' library (-lws2_32). */
+/* #undef HAVE_LIBWS2_32 */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define to 1 if you have the `perror' function. */
+#define HAVE_PERROR 1
+
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* Define to 1 if the system has the type `_Bool'. */
+/* #undef HAVE__BOOL */
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Name of package */
+#define PACKAGE "zeromq"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "zeromq-dev@lists.zeromq.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "zeromq"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "zeromq 2.1.11"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "zeromq"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "2.1.11"
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both and . */
+#define TIME_WITH_SYS_TIME 1
+
+/* Version number of package */
+#define VERSION "2.1.11"
+
+/* Force to use mutexes */
+/* #undef ZMQ_FORCE_MUTEXES */
+
+/* Have AIX OS */
+/* #undef ZMQ_HAVE_AIX */
+
+/* Have Cygwin */
+/* #undef ZMQ_HAVE_CYGWIN */
+
+/* Have FreeBSD OS */
+/* #undef ZMQ_HAVE_FREEBSD */
+
+/* Have HPUX OS */
+/* #undef ZMQ_HAVE_HPUX */
+
+/* Have ifaddrs.h header. */
+#define ZMQ_HAVE_IFADDRS 1
+
+/* Have Linux OS */
+/* #undef ZMQ_HAVE_LINUX */
+
+/* Have MinGW32 */
+/* #undef ZMQ_HAVE_MINGW32 */
+
+/* Have NetBSD OS */
+/* #undef ZMQ_HAVE_NETBSD */
+
+/* Have OpenBSD OS */
+/* #undef ZMQ_HAVE_OPENBSD */
+
+/* Have OpenPGM extension */
+/* #undef ZMQ_HAVE_OPENPGM */
+
+/* Have DarwinOSX OS */
+#define ZMQ_HAVE_OSX 1
+
+/* Have QNX Neutrino OS */
+/* #undef ZMQ_HAVE_QNXNTO */
+
+/* Have Solaris OS */
+/* #undef ZMQ_HAVE_SOLARIS */
+
+/* Have Windows OS */
+/* #undef ZMQ_HAVE_WINDOWS */
+
+/* Define for Solaris 2.5.1 so the uint32_t typedef from ,
+ , or is not used. If the typedef were allowed, the
+ #define below would cause a syntax error. */
+/* #undef _UINT32_T */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to `unsigned int' if does not define. */
+/* #undef size_t */
+
+/* Define to `int' if does not define. */
+/* #undef ssize_t */
+
+/* Define to the type of an unsigned integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef uint32_t */
+
+/* Define to empty if the keyword `volatile' does not work. Warning: valid
+ code using `volatile' can become incorrect without. Disable with care. */
+/* #undef volatile */
diff --git a/buildutils/include_freebsd/platform.hpp b/buildutils/include_freebsd/platform.hpp
new file mode 100644
index 000000000..7b88ff107
--- /dev/null
+++ b/buildutils/include_freebsd/platform.hpp
@@ -0,0 +1,226 @@
+/* src/platform.hpp. Generated from platform.hpp.in by configure. */
+/* src/platform.hpp.in. Generated from configure.in by autoheader. */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the `freeifaddrs' function. */
+#define HAVE_FREEIFADDRS 1
+
+/* Define to 1 if you have the `getifaddrs' function. */
+#define HAVE_GETIFADDRS 1
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_IFADDRS_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `crypto' library (-lcrypto). */
+/* #undef HAVE_LIBCRYPTO */
+
+/* Define to 1 if you have the `iphlpapi' library (-liphlpapi). */
+/* #undef HAVE_LIBIPHLPAPI */
+
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+/* #undef HAVE_LIBNSL */
+
+/* Define to 1 if you have the `pthread' library (-lpthread). */
+#define HAVE_LIBPTHREAD 1
+
+/* Define to 1 if you have the `rpcrt4' library (-lrpcrt4). */
+/* #undef HAVE_LIBRPCRT4 */
+
+/* Define to 1 if you have the `rt' library (-lrt). */
+/* #undef HAVE_LIBRT */
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
+
+/* Define to 1 if you have the `uuid' library (-luuid). */
+/* #undef HAVE_LIBUUID */
+
+/* Define to 1 if you have the `ws2_32' library (-lws2_32). */
+/* #undef HAVE_LIBWS2_32 */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define to 1 if you have the `perror' function. */
+#define HAVE_PERROR 1
+
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if stdbool.h conforms to C99. */
+/* #undef HAVE_STDBOOL_H */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* Define to 1 if the system has the type `_Bool'. */
+/* #undef HAVE__BOOL */
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Name of package */
+#define PACKAGE "zeromq"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "zeromq-dev@lists.zeromq.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "zeromq"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "zeromq 2.1.11"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "zeromq"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "2.1.11"
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both and . */
+#define TIME_WITH_SYS_TIME 1
+
+/* Version number of package */
+#define VERSION "2.1.11"
+
+/* Force to use mutexes */
+/* #undef ZMQ_FORCE_MUTEXES */
+
+/* Have AIX OS */
+/* #undef ZMQ_HAVE_AIX */
+
+/* Have Cygwin */
+/* #undef ZMQ_HAVE_CYGWIN */
+
+/* Have FreeBSD OS */
+#define ZMQ_HAVE_FREEBSD 1
+
+/* Have HPUX OS */
+/* #undef ZMQ_HAVE_HPUX */
+
+/* Have ifaddrs.h header. */
+#define ZMQ_HAVE_IFADDRS 1
+
+/* Have Linux OS */
+/* #undef ZMQ_HAVE_LINUX */
+
+/* Have MinGW32 */
+/* #undef ZMQ_HAVE_MINGW32 */
+
+/* Have NetBSD OS */
+/* #undef ZMQ_HAVE_NETBSD */
+
+/* Have OpenBSD OS */
+/* #undef ZMQ_HAVE_OPENBSD */
+
+/* Have OpenPGM extension */
+/* #undef ZMQ_HAVE_OPENPGM */
+
+/* Have DarwinOSX OS */
+/* #undef ZMQ_HAVE_OSX */
+
+/* Have QNX Neutrino OS */
+/* #undef ZMQ_HAVE_QNXNTO */
+
+/* Have Solaris OS */
+/* #undef ZMQ_HAVE_SOLARIS */
+
+/* Have Windows OS */
+/* #undef ZMQ_HAVE_WINDOWS */
+
+/* Define for Solaris 2.5.1 so the uint32_t typedef from ,
+ , or is not used. If the typedef were allowed, the
+ #define below would cause a syntax error. */
+/* #undef _UINT32_T */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to `unsigned int' if does not define. */
+/* #undef size_t */
+
+/* Define to `int' if does not define. */
+/* #undef ssize_t */
+
+/* Define to the type of an unsigned integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef uint32_t */
+
+/* Define to empty if the keyword `volatile' does not work. Warning: valid
+ code using `volatile' can become incorrect without. Disable with care. */
+/* #undef volatile */
diff --git a/buildutils/include_linux/platform.hpp b/buildutils/include_linux/platform.hpp
new file mode 100644
index 000000000..89632e6ad
--- /dev/null
+++ b/buildutils/include_linux/platform.hpp
@@ -0,0 +1,229 @@
+/* src/platform.hpp. Generated from platform.hpp.in by configure. */
+/* src/platform.hpp.in. Generated from configure.in by autoheader. */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the `freeifaddrs' function. */
+#define HAVE_FREEIFADDRS 1
+
+/* Define to 1 if you have the `getifaddrs' function. */
+#define HAVE_GETIFADDRS 1
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_IFADDRS_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `crypto' library (-lcrypto). */
+/* #undef HAVE_LIBCRYPTO */
+
+/* Define to 1 if you have the `iphlpapi' library (-liphlpapi). */
+/* #undef HAVE_LIBIPHLPAPI */
+
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+/* #undef HAVE_LIBNSL */
+
+/* Define to 1 if you have the `pthread' library (-lpthread). */
+#define HAVE_LIBPTHREAD 1
+
+/* Define to 1 if you have the `rpcrt4' library (-lrpcrt4). */
+/* #undef HAVE_LIBRPCRT4 */
+
+/* Define to 1 if you have the `rt' library (-lrt). */
+#define HAVE_LIBRT 1
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
+
+/* Define to 1 if you have the `uuid' library (-luuid). */
+#define HAVE_LIBUUID 1
+
+/* Define to 1 if you have the `ws2_32' library (-lws2_32). */
+/* #undef HAVE_LIBWS2_32 */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define to 1 if you have the `perror' function. */
+#define HAVE_PERROR 1
+
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* Define to 1 if the system has the type `_Bool'. */
+/* #undef HAVE__BOOL */
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Name of package */
+#define PACKAGE "zeromq"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "zeromq-dev@lists.zeromq.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "zeromq"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "zeromq 2.1.11"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "zeromq"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "2.1.11"
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both and . */
+#define TIME_WITH_SYS_TIME 1
+
+/* Version number of package */
+#define VERSION "2.1.11"
+
+/* Force to use mutexes */
+/* #undef ZMQ_FORCE_MUTEXES */
+
+/* Have AIX OS */
+/* #undef ZMQ_HAVE_AIX */
+
+/* Have Cygwin */
+/* #undef ZMQ_HAVE_CYGWIN */
+
+/* Have FreeBSD OS */
+/* #undef ZMQ_HAVE_FREEBSD */
+
+/* Have HPUX OS */
+/* #undef ZMQ_HAVE_HPUX */
+
+/* Have ifaddrs.h header. */
+#define ZMQ_HAVE_IFADDRS 1
+
+/* Have Linux OS */
+#define ZMQ_HAVE_LINUX 1
+
+/* Have MinGW32 */
+/* #undef ZMQ_HAVE_MINGW32 */
+
+/* Have NetBSD OS */
+/* #undef ZMQ_HAVE_NETBSD */
+
+/* Have OpenBSD OS */
+/* #undef ZMQ_HAVE_OPENBSD */
+
+/* Have OpenPGM extension */
+/* #undef ZMQ_HAVE_OPENPGM */
+
+/* Have DarwinOSX OS */
+/* #undef ZMQ_HAVE_OSX */
+
+/* Have QNX Neutrino OS */
+/* #undef ZMQ_HAVE_QNXNTO */
+
+/* Have Solaris OS */
+/* #undef ZMQ_HAVE_SOLARIS */
+
+/* Have Windows OS */
+/* #undef ZMQ_HAVE_WINDOWS */
+
+/* Define for Solaris 2.5.1 so the uint32_t typedef from ,
+ , or is not used. If the typedef were allowed, the
+ #define below would cause a syntax error. */
+/* #undef _UINT32_T */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to `unsigned int' if does not define. */
+/* #undef size_t */
+
+/* Define to `int' if does not define. */
+/* #undef ssize_t */
+
+/* Define to the type of an unsigned integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef uint32_t */
+
+/* Define to empty if the keyword `volatile' does not work. Warning: valid
+ code using `volatile' can become incorrect without. Disable with care. */
+/* #undef volatile */
diff --git a/buildutils/initlibzmq.c b/buildutils/initlibzmq.c
new file mode 100644
index 000000000..ec299f0a9
--- /dev/null
+++ b/buildutils/initlibzmq.c
@@ -0,0 +1,45 @@
+/*
+This file is from pyzmq-static by Brandon Craig-Rhodes,
+and used under the BSD license
+
+py3compat from http://wiki.python.org/moin/PortingExtensionModulesToPy3k
+
+Provide the init function that Python expects
+when we compile libzmq by pretending it is a Python extension.
+*/
+#include "Python.h"
+
+static PyMethodDef Methods[] = {
+ {NULL, NULL, 0, NULL}
+};
+
+#if PY_MAJOR_VERSION >= 3
+
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "libzmq",
+ NULL,
+ -1,
+ Methods,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+PyMODINIT_FUNC
+PyInit_libzmq(void)
+{
+ PyObject *module = PyModule_Create(&moduledef);
+ return module;
+}
+
+#else // py2
+
+PyMODINIT_FUNC
+initlibzmq(void)
+{
+ (void) Py_InitModule("libzmq", Methods);
+}
+
+#endif
diff --git a/buildutils/msg.py b/buildutils/msg.py
new file mode 100644
index 000000000..704e1924e
--- /dev/null
+++ b/buildutils/msg.py
@@ -0,0 +1,43 @@
+"""logging"""
+#-----------------------------------------------------------------------------
+# Copyright (C) 2011 Brian Granger, Min Ragan-Kelley
+#
+# This file is part of pyzmq, copied and adapted from h5py.
+# h5py source used under the New BSD license
+#
+# h5py:
+#
+# Distributed under the terms of the New BSD License. The full license is in
+# the file COPYING.BSD, distributed as part of this software.
+#-----------------------------------------------------------------------------
+
+from __future__ import division
+
+import sys
+import logging
+
+#-----------------------------------------------------------------------------
+# Logging (adapted from h5py: http://h5py.googlecode.com)
+#-----------------------------------------------------------------------------
+
+
+logger = logging.getLogger()
+logger.setLevel(logging.INFO)
+logger.addHandler(logging.StreamHandler(sys.stderr))
+
+def debug(msg):
+ logger.debug(msg)
+
+def info(msg):
+ logger.info(msg)
+
+def fatal(msg, code=1):
+ logger.error("Fatal: " + msg)
+ exit(code)
+
+def warn(msg):
+ logger.error("Warning: " + msg)
+
+def line(c='*', width=48):
+ print(c * (width // len(c)))
+
diff --git a/buildutils/vers.c b/buildutils/vers.c
new file mode 100644
index 000000000..362564f38
--- /dev/null
+++ b/buildutils/vers.c
@@ -0,0 +1,11 @@
+// check libzmq version
+
+#include
+#include "zmq.h"
+
+int main(int argc, char **argv){
+ int major, minor, patch;
+ zmq_version(&major, &minor, &patch);
+ fprintf(stdout, "vers: %d.%d.%d\n", major, minor, patch);
+ return 0;
+}
diff --git a/setup.py b/setup.py
index 48c4b36ca..4806233f0 100755
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,4 @@
#!/usr/bin/env python
-
-
#-----------------------------------------------------------------------------
# Copyright (c) 2012 Brian Granger, Min Ragan-Kelley
#
@@ -13,6 +11,11 @@
# h5py source used under the New BSD license
#
# h5py:
+#
+# The code to bundle libzmq as an Extension is from pyzmq-static
+# pyzmq-static source used under the New BSD license
+#
+# pyzmq-static:
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
@@ -25,8 +28,17 @@
import re
import shutil
import sys
+import time
from traceback import print_exc
+if sys.version_info < (2,6):
+ print("ERROR: PyZMQ >= 2.2.0 requires Python 2.6 or later. \n" +
+ " PyZMQ 2.1.11 was the last release to support Python 2.5."
+ )
+ sys.exit(1)
+
+
+import distutils
from distutils.core import setup, Command
from distutils.ccompiler import get_default_compiler
from distutils.extension import Extension
@@ -53,12 +65,17 @@
nose = None
# local script imports:
-from buildutils import (discover_settings, v_str, localpath, savepickle, loadpickle, detect_zmq,
- warn, fatal, copy_and_patch_libzmq)
+from buildutils import (
+ discover_settings, v_str, save_config, load_config, detect_zmq,
+ warn, fatal, debug, line, copy_and_patch_libzmq, localpath,
+ fetch_uuid, fetch_libzmq, stage_platform_hpp,
+ bundled_version,
+ )
#-----------------------------------------------------------------------------
# Flags
#-----------------------------------------------------------------------------
+
# ignore unused-function and strict-aliasing warnings, of which there
# will be many from the Cython generated code:
# note that this is only for gcc-style compilers
@@ -88,37 +105,57 @@
ZMQ = discover_settings()
-if ZMQ is not None and not os.path.exists(ZMQ):
+if ZMQ is not None and ZMQ != "bundled" and not os.path.exists(ZMQ):
warn("ZMQ directory \"%s\" does not appear to exist" % ZMQ)
-# bundle_libzmq flag for whether libzmq will be included in pyzmq:
+# bundle_libzmq_dylib flag for whether external libzmq library will be included in pyzmq:
if sys.platform.startswith('win'):
- bundle_libzmq = True
-elif ZMQ is not None:
- bundle_libzmq = doing_bdist
+ bundle_libzmq_dylib = True
+elif ZMQ is not None and ZMQ != "bundled":
+ bundle_libzmq_dylib = doing_bdist
else:
- bundle_libzmq = False
+ bundle_libzmq_dylib = False
# --- compiler settings -------------------------------------------------
+def bundled_settings():
+ settings = {
+ 'libraries' : [],
+ 'include_dirs' : ["bundled/zeromq/include"],
+ 'library_dirs' : [],
+ 'define_macros' : [],
+ }
+ # add pthread on freebsd
+ # is this necessary?
+ if sys.platform.startswith('freebsd'):
+ settings['libraries'].append('pthread')
+ elif sys.platform.startswith('win'):
+ # link against libzmq in build dir:
+ plat = distutils.util.get_platform()
+ temp = 'temp.%s-%s' % (plat, sys.version[0:3])
+ settings['libraries'].append('libzmq')
+ settings['library_dirs'].append(pjoin('build', temp, 'Release', 'buildutils'))
+
+ return settings
+
+
def settings_from_prefix(zmq=None):
"""load appropriate library/include settings from ZMQ prefix"""
+
+ settings = {
+ 'libraries' : [],
+ 'include_dirs' : [],
+ 'library_dirs' : [],
+ 'define_macros' : [],
+ }
if sys.platform.startswith('win'):
- settings = {
- 'libraries' : ['libzmq'],
- 'include_dirs' : [],
- 'library_dirs' : [],
- }
+ settings['libraries'].append('libzmq')
+
if zmq is not None:
settings['include_dirs'] += [pjoin(zmq, 'include')]
settings['library_dirs'] += [pjoin(zmq, 'lib')]
else:
- settings = {
- 'libraries' : ['zmq'],
- 'include_dirs' : [],
- 'library_dirs' : [],
- 'define_macros' : [('PYZMQ_POSIX', 1)],
- }
+ settings['libraries'].append('zmq')
# add pthread on freebsd
if sys.platform.startswith('freebsd'):
@@ -132,7 +169,7 @@ def settings_from_prefix(zmq=None):
settings['include_dirs'] += ['/opt/local/include']
settings['library_dirs'] += ['/opt/local/lib']
- if bundle_libzmq:
+ if bundle_libzmq_dylib:
# bdist should link against bundled libzmq
settings['library_dirs'] = ['zmq']
if sys.platform == 'darwin':
@@ -144,13 +181,24 @@ def settings_from_prefix(zmq=None):
elif sys.platform != 'darwin':
settings['runtime_library_dirs'] = [os.path.abspath(x) for x in settings['library_dirs']]
- # suppress common warnings
+ return settings
+def init_settings(zmq=None):
+ if zmq == 'bundled':
+ settings = bundled_settings()
+ else:
+ settings = settings_from_prefix(zmq)
+
+ if not sys.platform.startswith('win'):
+ settings['define_macros'].append(('PYZMQ_POSIX', 1))
+
+ # suppress common warnings
+
extra_flags = []
if ignore_common_warnings:
for warning in ('unused-function', 'strict-aliasing'):
extra_flags.append('-Wno-'+warning)
-
+
settings['extra_compile_args'] = extra_flags
# include internal directories
@@ -158,7 +206,8 @@ def settings_from_prefix(zmq=None):
return settings
-COMPILER_SETTINGS = settings_from_prefix(ZMQ)
+
+COMPILER_SETTINGS = init_settings(ZMQ)
#-----------------------------------------------------------------------------
@@ -207,20 +256,24 @@ def erase_tempdir(self):
pass
def getcached(self):
- return loadpickle('configure.pickle')
+ return load_config('configure')
def check_zmq_version(self):
zmq = self.zmq
- if zmq is not None and not os.path.isdir(zmq):
+ if zmq is not None and zmq is not "bundled" and not os.path.isdir(zmq):
fatal("Custom zmq directory \"%s\" does not exist" % zmq)
config = self.getcached()
- if config is None or config['options'] != self.settings:
+ if not config or config.get('settings') != self.settings:
self.run()
config = self.config
else:
self.config = config
+ line()
+ if self.zmq == "bundled":
+ return
+
vers = config['vers']
vs = v_str(vers)
if vers < min_zmq:
@@ -233,10 +286,10 @@ def check_zmq_version(self):
warn("Detected ZMQ version: %s, but pyzmq targets zmq %s."%(
vs, pyzmq_version))
warn("libzmq features and fixes introduced after %s will be unavailable."%vs)
- print('*'*42)
+ line()
elif vs >= '3.0':
warn("Detected ZMQ version: %s. pyzmq's support for libzmq-dev is experimental."%vs)
- print('*'*42)
+ line()
if sys.platform.startswith('win'):
# fetch libzmq.dll into local dir
@@ -251,10 +304,125 @@ def check_zmq_version(self):
"Please specify zmq prefix via configure --zmq=/path/to/zmq or copy "
"libzmq into zmq/ manually.")
- def run(self):
+
+ def bundle_libzmq_extension(self):
+ bundledir = "bundled"
+ if self.distribution.ext_modules[0].name == 'zmq.libzmq':
+ # I've already been run
+ return
+
+ line()
+ print ("Using bundled libzmq")
+
+ # fetch sources for libzmq extension:
+ if not os.path.exists(bundledir):
+ os.makedirs(bundledir)
+ if not sys.platform.startswith(('darwin', 'freebsd', 'win')):
+ fetch_uuid(bundledir)
+
+ fetch_libzmq(bundledir)
+
+ stage_platform_hpp(pjoin(bundledir, 'zeromq'))
+
+ # construct the Extension:
+
+ ext = Extension(
+ 'zmq.libzmq',
+ sources = [pjoin('buildutils', 'initlibzmq.c')] +
+ glob(pjoin(bundledir, 'zeromq', 'src', '*.cpp')),
+ include_dirs = [
+ pjoin(bundledir, 'zeromq', 'include'),
+ ],
+ )
+
+ if sys.platform.startswith('win'):
+ # include defines from zeromq msvc project:
+ ext.define_macros.append(('FD_SETSIZE', 1024))
+
+ # When compiling the C++ code inside of libzmq itself, we want to
+ # avoid "warning C4530: C++ exception handler used, but unwind
+ # semantics are not enabled. Specify /EHsc".
+
+ ext.extra_compile_args.append('/EHsc')
+
+ # And things like sockets come from libraries that must be named.
+
+ ext.libraries.append('rpcrt4')
+ ext.libraries.append('ws2_32')
+ elif not sys.platform.startswith(('darwin', 'freebsd')):
+ # add uuid as both `uuid/uuid.h` and `uuid.h`:
+ ext.include_dirs.append(pjoin(bundledir, 'uuid'))
+ ext.include_dirs.append(bundledir)
+ ext.sources.extend(glob(pjoin(bundledir, 'uuid', '*.c')))
+
+ # insert the extension:
+ self.distribution.ext_modules.insert(0, ext)
+
+ # update other extensions, with bundled settings
+ settings = init_settings("bundled")
+
+ for ext in self.distribution.ext_modules[1:]:
+ for attr, value in settings.items():
+ setattr(ext, attr, value)
+
+ save_config("buildconf", dict(zmq="bundled"))
+
+ return dict(vers=bundled_version, settings=settings)
+
+
+ def fallback_on_bundled(self):
+ """Couldn't build, fallback after waiting a while"""
+
+ line()
+
+ print ('\n'.join([
+ "Failed to build or run libzmq detection test.",
+ "",
+ "If you expected pyzmq to link against an installed libzmq, please check to make sure:",
+ "",
+ " * You have a C compiler installed",
+ " * A development version of Python is installed (including headers)",
+ " * A development version of ZMQ >= %s is installed (including headers)" % v_str(min_zmq),
+ " * If ZMQ is not in a default location, supply the argument --zmq=",
+ " * If you did recently install ZMQ to a default location,",
+ " try rebuilding the ld cache with `sudo ldconfig`",
+ " or specify zmq's location with `--zmq=/usr/local`",
+ "",
+ ]))
+
+ # ultra-lazy pip detection:
+ if 'pip' in ' '.join(sys.argv) or True:
+ print ('\n'.join([
+ "If you expected to get a binary install (egg), we have those for",
+ "current Pythons on OSX and Windows. These can be installed with",
+ "easy_install, but PIP DOES NOT SUPPORT EGGS.",
+ "",
+ ]))
+
+ print ('\n'.join([
+ "You can skip all this detection/waiting nonsense if you know",
+ "you want pyzmq to bundle libzmq as an extension by passing:",
+ "",
+ " `--zmq=bundled`",
+ "",
+ "I will now fetch the libzmq sources and build libzmq as a Python extension",
+ "unless you interrupt me (^C) in the next 10 seconds...",
+ "",
+ ]))
+
+ for i in range(10,0,-1):
+ sys.stdout.write('\r%2i...' % i)
+ sys.stdout.flush()
+ time.sleep(1)
+
+ print ("")
+
+ return self.bundle_libzmq_extension()
+
+
+ def test_build(self, zmq, settings):
self.create_tempdir()
- settings = self.settings
- if bundle_libzmq and not sys.platform.startswith('win'):
+ if bundle_libzmq_dylib and not sys.platform.startswith('win'):
# rpath slightly differently here, because libzmq not in .. but ../zmq:
settings['library_dirs'] = ['zmq']
if sys.platform == 'darwin':
@@ -263,60 +431,102 @@ def run(self):
# settings['extra_link_args'] = ['-Wl,-rpath','-Wl,$ORIGIN/../zmq']
else:
settings['runtime_library_dirs'] = ['$ORIGIN/../zmq']
+
+ line()
+ print ("Configure: Autodetecting ZMQ settings...")
+ print (" Custom ZMQ dir: %s" % zmq)
try:
- print ("*"*42)
- print ("Configure: Autodetecting ZMQ settings...")
- print (" Custom ZMQ dir: %s" % (self.zmq,))
config = detect_zmq(self.tempdir, **settings)
- except Exception:
- # if zmq unspecified on *ix, try again with explicit /usr/local
- if self.zmq is None and not sys.platform.startswith('win'):
- self.erase_tempdir()
- print ("Failed with default libzmq, trying again with /usr/local")
- self.zmq = '/usr/local'
- self.settings = settings_from_prefix(self.zmq)
-
- self.run()
+ finally:
+ self.erase_tempdir()
+
+ print (" ZMQ version detected: %s" % v_str(config['vers']))
+
+ return config
+
+ def run(self):
+ if self.zmq == "bundled":
+ self.config = self.bundle_libzmq_extension()
+ line()
+ return
+
+ config = None
+
+ # There is no available default on Windows, so start with fallback unless
+ # zmq was given explicitly.
+ if self.zmq is None and sys.platform.startswith("win"):
+ config = self.fallback_on_bundled()
+ self.zmq = "bundled"
+
+ if config is None:
+ # first try with given config or defaults
+ try:
+ config = self.test_build(self.zmq, self.settings)
+ except Exception:
+ etype, evalue, tb = sys.exc_info()
+ # print the error as distutils would if we let it raise:
+ print ("\nerror: %s\n" % evalue)
+
+ # try fallback on /usr/local on *ix
+ if config is None and self.zmq is None and not sys.platform.startswith('win'):
+ print ("Failed with default libzmq, trying again with /usr/local")
+ time.sleep(1)
+ zmq = '/usr/local'
+ settings = settings_from_prefix(zmq)
+ try:
+ config = self.test_build(zmq, settings)
+ except Exception:
+ etype, evalue, tb = sys.exc_info()
+ # print the error as distutils would if we let it raise:
+ print ("\nerror: %s\n" % evalue)
+ else:
# if we get here the second run succeeded, so we need to update compiler
# settings for the extensions with /usr/local prefix
+ self.zmq = zmq
for ext in self.distribution.ext_modules:
- for key,value in self.settings.iteritems():
- setattr(ext, key, value)
- return
-
- etype, evalue, tb = sys.exc_info()
- # print the error as distutils would if we let it raise:
- print ("error: %s" % evalue)
- if etype is CompileError:
- action = 'compile'
- elif etype is LinkError:
- action = 'link'
- else:
- action = 'build or run'
-
- fatal("""
- Failed to %s ZMQ test program. Please check to make sure:
-
- * You have a C compiler installed
- * A development version of Python is installed (including header files)
- * A development version of ZMQ >= %s is installed (including header files)
- * If ZMQ is not in a default location, supply the argument --zmq=
- * If you did recently install ZMQ to a default location,
- try rebuilding the ld cache with `sudo ldconfig`
- or specify zmq's location with `--zmq=/usr/local`
- """%(action, v_str(min_zmq)))
-
- else:
- savepickle('configure.pickle', config)
- print (" ZMQ version detected: %s" % v_str(config['vers']))
- finally:
- print ("*"*42)
- self.erase_tempdir()
+ for attr,value in settings.items():
+ setattr(ext, attr, value)
+
+ # finally, fallback on bundled
+ if config is None and self.zmq is None:
+ config = self.fallback_on_bundled()
+ self.zmq = "bundled"
+
+ save_config('configure', config)
self.config = config
+ line()
+
+
+class FetchCommand(Command):
+ """Fetch libzmq and uuid sources, that's it."""
+
+ description = "Fetch libuuid and libzmq sources into bundled"
+
+ user_options = [ ]
+
+ def initialize_options(self):
+ pass
+
+ def finalize_options(self):
+ pass
+
+ def run(self):
+ # fetch sources for libzmq extension:
+ bundledir = "bundled"
+ if not os.path.exists(bundledir):
+ os.makedirs(bundledir)
+ fetch_uuid(bundledir)
+ fetch_libzmq(bundledir)
+ for tarball in glob(pjoin(bundledir, '*.tar.gz')):
+ os.remove(tarball)
+
+
class TestCommand(Command):
"""Custom distutils command to run the test suite."""
+ description = "Test PyZMQ (must have been built inplace: `setup.py build_ext --inplace`)"
+
user_options = [ ]
def initialize_options(self):
@@ -355,7 +565,7 @@ def run(self):
sys.exit(1)
if nose is None:
- print ("nose unavailable, falling back on unittest. Skipped tests will appear as ERRORs.")
+ warn("nose unavailable, falling back on unittest. Skipped tests will appear as ERRORs.")
return self.run_unittest()
else:
return self.run_nose()
@@ -363,6 +573,8 @@ def run(self):
class GitRevisionCommand(Command):
"""find the current git revision and add it to zmq.core.verion.__revision__"""
+ description = "Store current git revision in version.py"
+
user_options = [ ]
def initialize_options(self):
@@ -467,7 +679,7 @@ class CopyingBuild(build):
"""subclass of build that copies libzmq if doing bdist."""
def run(self):
- if bundle_libzmq and not sys.platform.startswith('win'):
+ if bundle_libzmq_dylib and not sys.platform.startswith('win'):
# always rebuild before bdist, because linking may be wrong:
self.run_command('clean')
copy_and_patch_libzmq(ZMQ, 'libzmq'+lib_ext)
@@ -490,6 +702,7 @@ def build_extensions(self):
self.check_extensions_list(self.extensions)
for ext in self.extensions:
+
self.build_extension(ext)
def run(self):
@@ -497,14 +710,15 @@ def run(self):
configure = self.distribution.get_command_obj('configure')
configure.check_zmq_version()
build_ext.run(self)
-
+
#-----------------------------------------------------------------------------
# Extensions
#-----------------------------------------------------------------------------
cmdclass = {'test':TestCommand, 'clean':CleanCommand, 'revision':GitRevisionCommand,
- 'configure': Configure, 'build': CopyingBuild}
+ 'configure': Configure, 'build': CopyingBuild, 'fetchbundle': FetchCommand,
+ }
def pxd(subdir, name):
return os.path.abspath(pjoin('zmq', subdir, name+'.pxd'))
@@ -546,7 +760,7 @@ def dotc(subdir, name):
)
try:
- from Cython.Distutils import build_ext
+ from Cython.Distutils import build_ext as build_ext_c
cython=True
except ImportError:
cython=False
@@ -556,14 +770,17 @@ def dotc(subdir, name):
suffix = '.pyx'
- class CythonCommand(build_ext):
+ class CythonCommand(build_ext_c):
"""Custom distutils command subclassed from Cython.Distutils.build_ext
to compile pyx->c, and stop there. All this does is override the
C-compile method build_extension() with a no-op."""
+
+ description = "Compile Cython sources to C"
+
def build_extension(self, ext):
pass
- class zbuild_ext(build_ext):
+ class zbuild_ext(build_ext_c):
def run(self):
configure = self.distribution.get_command_obj('configure')
configure.check_zmq_version()
@@ -586,14 +803,14 @@ def run(self):
)
extensions.append(ext)
-#
+
package_data = {'zmq':['*.pxd'],
'zmq.core':['*.pxd'],
'zmq.devices':['*.pxd'],
'zmq.utils':['*.pxd', '*.h'],
}
-if bundle_libzmq:
+if bundle_libzmq_dylib:
package_data['zmq'].append('libzmq'+lib_ext)
def extract_version():
diff --git a/zmq/__init__.py b/zmq/__init__.py
index c78df1be3..969e34d1e 100644
--- a/zmq/__init__.py
+++ b/zmq/__init__.py
@@ -13,15 +13,27 @@
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
+
+import os
import sys
+import glob
+
+here = os.path.dirname(__file__)
+
+bundled = []
+for ext in ('pyd', 'so', 'dll', 'dylib'):
+ bundled.extend(glob.glob(os.path.join(here, 'libzmq*.%s*' % ext)))
+
+if bundled:
+ import ctypes
+ if bundled[0].endswith('.pyd'):
+ # a Windows Extension
+ _libzmq = ctypes.cdll.LoadLibrary(bundled[0])
+ else:
+ _libzmq = ctypes.CDLL(bundled[0], mode=ctypes.RTLD_GLOBAL)
+ del ctypes
-if sys.platform.startswith('win'):
- import os, ctypes
- here = os.path.dirname(__file__)
- libzmq = os.path.join(here, 'libzmq.dll')
- if os.path.exists(libzmq):
- ctypes.cdll.LoadLibrary(libzmq)
- del here, libzmq, ctypes, os
+del os, sys, glob, here, bundled, ext
from zmq.utils import initthreads # initialize threads
initthreads.init_threads()