def check_pkgconfig(): """ pull compile / link flags from pkg-config if present. """ pcfg = None zmq_config = None try: check_call(['pkg-config', '--exists', 'libzmq']) # this would arguably be better with --variable=libdir / # --variable=includedir, but would require multiple calls pcfg = Popen(['pkg-config', '--libs', '--cflags', 'libzmq'], stdout=subprocess.PIPE) except OSError as osexception: if osexception.errno == errno.ENOENT: info('pkg-config not found') else: warn("Running pkg-config failed - %s." % osexception) except CalledProcessError: info("Did not find libzmq via pkg-config.") if pcfg is not None: output, _ = pcfg.communicate() output = output.decode('utf8', 'replace') bits = output.strip().split() zmq_config = {'library_dirs':[], 'include_dirs':[], 'libraries':[]} for tok in bits: if tok.startswith("-L"): zmq_config['library_dirs'].append(tok[2:]) if tok.startswith("-I"): zmq_config['include_dirs'].append(tok[2:]) if tok.startswith("-l"): zmq_config['libraries'].append(tok[2:]) info("Settings obtained from pkg-config: %r" % zmq_config) return zmq_config
def run(self): """Run the test suite, with nose, or unittest if nose is unavailable""" # crude check for inplace build: try: import zmq except ImportError: print_exc() fatal( "\n ".join( [ "Could not import zmq!", "You must build pyzmq with 'python setup.py build_ext --inplace' for 'python setup.py test' to work.", "If you did build pyzmq in-place, then this is a real error.", ] ) ) sys.exit(1) info("Testing pyzmq-%s with libzmq-%s" % (zmq.pyzmq_version(), zmq.zmq_version())) if nose is None: warn("nose unavailable, falling back on unittest. Skipped tests will appear as ERRORs.") return self.run_unittest() else: return self.run_nose()
def init_settings(cfg): if 'PyPy' in sys.version: return {} settings = cfg['build_ext'] if cfg['libzmq_extension']: settings = bundled_settings() else: settings = settings_from_prefix(CONFIG['zmq_prefix']) if 'have_sys_un_h' not in cfg: try: compile_and_run(pjoin("build", "sock_un"), pjoin('buildutils', 'check_sys_un.c'), **settings ) except Exception as e: warn("No sys/un.h, IPC_PATH_MAX_LEN will be undefined: %s" % e) cfg['have_sys_un_h'] = False else: cfg['have_sys_un_h'] = True save_config('buildconf', cfg) if cfg['have_sys_un_h']: settings['define_macros'] = [('HAVE_SYS_UN_H', 1)] settings.setdefault('define_macros', []) # include internal directories settings.setdefault('include_dirs', []) settings['include_dirs'] += [pjoin('zmq', sub) for sub in ('utils','core','devices')] return settings
def fallback_on_bundled(self): """Couldn't build, fallback after waiting a while""" line() warn( "\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=<path>", " * 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): info( "\n".join( [ "If you expected to get a binary install (egg), we have those for", "current Pythons on OS X and Windows. These can be installed with", "easy_install, but PIP DOES NOT SUPPORT EGGS.", "", ] ) ) info( "\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 try to 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) info("") return self.bundle_libzmq_extension()
def run(self): try: import Cython except ImportError: warn("Cython is missing") else: if V(Cython.__version__) < V('0.16'): warn("Cython >= 0.16 required for compiling Cython sources, but we have %s" % Cython.__version__)
def run(self): try: import Cython except ImportError: warn("Cython is missing") else: cv = getattr(Cython, "__version__", None) if cv is None or V(cv) < V("0.16"): warn("Cython >= 0.16 is required for compiling Cython sources, " "found: %s" % (cv or "super old"))
def check_zmq_version(self): """check the zmq version""" cfg = self.config # build test program zmq_prefix = cfg["zmq_prefix"] detected = self.test_build(zmq_prefix, self.compiler_settings) # now check the libzmq version vers = tuple(detected["vers"]) vs = v_str(vers) if cfg["allow_legacy_libzmq"]: min_zmq = min_legacy_zmq else: min_zmq = min_good_zmq if vers < min_zmq: msg = ["Detected ZMQ version: %s, but require ZMQ >= %s" % (vs, v_str(min_zmq))] if zmq_prefix: msg.append(" ZMQ_PREFIX=%s" % zmq_prefix) if vers >= min_legacy_zmq: msg.append(" Explicitly allow legacy zmq by specifying `--zmq=/zmq/prefix`") raise LibZMQVersionError("\n".join(msg)) if vers < min_good_zmq: msg = [ "Detected legacy ZMQ version: %s. It is STRONGLY recommended to use ZMQ >= %s" % (vs, v_str(min_good_zmq)) ] if zmq_prefix: msg.append(" ZMQ_PREFIX=%s" % zmq_prefix) warn("\n".join(msg)) elif vers < target_zmq: warn("Detected ZMQ version: %s, but pyzmq targets ZMQ %s." % (vs, v_str(target_zmq))) warn("libzmq features and fixes introduced after %s will be unavailable." % vs) line() elif vers >= dev_zmq: warn("Detected ZMQ version: %s. Some new features in libzmq may not be exposed by pyzmq." % vs) line() if sys.platform.startswith("win"): # fetch libzmq.dll into local dir local_dll = localpath("zmq", "libzmq.dll") if not zmq_prefix and not os.path.exists(local_dll): fatal( "ZMQ directory must be specified on Windows via setup.cfg or 'python setup.py configure --zmq=/path/to/zeromq2'" ) try: shutil.copy(pjoin(zmq_prefix, "lib", "libzmq.dll"), local_dll) except Exception: if not os.path.exists(local_dll): warn( "Could not copy libzmq into zmq/, which is usually necessary on Windows." "Please specify zmq prefix via configure --zmq=/path/to/zmq or copy " "libzmq into zmq/ manually." )
def run(self): try: import Cython except ImportError: warn("Cython is missing") else: cv = getattr(Cython, "__version__", None) if cv is None or V(cv) < V(min_cython_version): warn( "Cython >= %s is required for compiling Cython sources, " "found: %s" % (min_cython_version, cv or Cython) )
def init_settings_from_config(self): """set up compiler settings, based on config""" cfg = self.config if cfg['libzmq_extension']: settings = bundled_settings(self.debug) else: settings = settings_from_prefix(cfg['zmq_prefix'], self.bundle_libzmq_dylib) if 'have_sys_un_h' not in cfg: # don't link against anything when checking for sys/un.h minus_zmq = copy.deepcopy(settings) try: minus_zmq['libraries'] = [] except Exception: pass try: compile_and_run(self.tempdir, pjoin('buildutils', 'check_sys_un.c'), **minus_zmq ) except Exception as e: warn("No sys/un.h, IPC_PATH_MAX_LEN will be undefined: %s" % e) cfg['have_sys_un_h'] = False else: cfg['have_sys_un_h'] = True self.save_config('config', cfg) if cfg['have_sys_un_h']: settings['define_macros'] = [('HAVE_SYS_UN_H', 1)] settings.setdefault('define_macros', []) # include internal directories settings.setdefault('include_dirs', []) settings['include_dirs'] += [pjoin('zmq', sub) for sub in ( 'utils', pjoin('backend', 'cython'), 'devices', )] if sys.platform.startswith('win') and sys.version_info < (3, 3): settings['include_dirs'].insert(0, pjoin('buildutils', 'include_win32')) for ext in self.distribution.ext_modules: if ext.name.startswith('zmq.lib'): continue for attr, value in settings.items(): setattr(ext, attr, value) self.compiler_settings = settings self.save_config('compiler', settings)
def create_tempdir(self): self.erase_tempdir() os.mkdir(self.tempdir) if sys.platform.startswith('win'): # fetch libzmq.dll into local dir local_dll = pjoin(self.tempdir, 'libzmq.dll') if ZMQ is None and not os.path.exists(local_dll): fatal("ZMQ directory must be specified on Windows via setup.cfg or 'python setup.py configure --zmq=/path/to/zeromq2'") try: shutil.copy(pjoin(ZMQ, 'lib', 'libzmq.dll'), local_dll) except Exception: if not os.path.exists(local_dll): warn("Could not copy libzmq into zmq/, which is usually necessary on Windows." "Please specify zmq prefix via configure --zmq=/path/to/zmq or copy " "libzmq into zmq/ manually.")
def fallback_on_bundled(self): """Couldn't build, fallback after waiting a while""" line() warn( "\n".join( [ "Couldn't find an acceptable libzmq on the system.", "", "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_good_zmq), " * If ZMQ is not in a default location, supply the argument --zmq=<path>", " * 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`", "", ] ) ) info( "\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 try to 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) info("") return self.bundle_libzmq_extension()
def build_extensions(self): self.extensions.remove(dummy_ext) bld_ext.build_extensions(self) # build ffi extension after bundled libzmq, # because it may depend on linking it here = os.getcwd() sys.path.insert(0, self.build_lib) try: from zmq.backend.cffi import ffi except ImportError as e: warn("Couldn't get CFFI extension: %s" % e) else: ext = ffi.verifier.get_extension() self.extensions.append(ext) self.build_extension(ext) finally: sys.path.pop(0)
def init_settings_from_config(self): """set up compiler settings, based on config""" if "PyPy" in sys.version: self.compiler_settings = {} cfg = self.config if cfg["libzmq_extension"]: settings = bundled_settings() else: settings = settings_from_prefix(cfg["zmq_prefix"], self.bundle_libzmq_dylib) if "have_sys_un_h" not in cfg: # don't link against anything when checking for sys/un.h minus_zmq = copy.deepcopy(settings) try: minus_zmq["libraries"] = [] except Exception: pass try: compile_and_run(self.tempdir, pjoin("buildutils", "check_sys_un.c"), **minus_zmq) except Exception as e: warn("No sys/un.h, IPC_PATH_MAX_LEN will be undefined: %s" % e) cfg["have_sys_un_h"] = False else: cfg["have_sys_un_h"] = True self.save_config("config", cfg) if cfg["have_sys_un_h"]: settings["define_macros"] = [("HAVE_SYS_UN_H", 1)] settings.setdefault("define_macros", []) # include internal directories settings.setdefault("include_dirs", []) settings["include_dirs"] += [pjoin("zmq", sub) for sub in ("utils", pjoin("backend", "cython"), "devices")] for ext in self.distribution.ext_modules: if ext.name == "zmq.libzmq": continue for attr, value in settings.items(): setattr(ext, attr, value) self.compiler_settings = settings self.save_config("compiler", settings)
def init_settings_from_config(self): """set up compiler settings, based on config""" if 'PyPy' in sys.version: self.compiler_settings = {} cfg = self.config if cfg['libzmq_extension']: settings = bundled_settings() else: settings = settings_from_prefix(cfg['zmq_prefix'], self.bundle_libzmq_dylib) if 'have_sys_un_h' not in cfg: try: compile_and_run(self.tempdir, pjoin('buildutils', 'check_sys_un.c'), **settings ) except Exception as e: warn("No sys/un.h, IPC_PATH_MAX_LEN will be undefined: %s" % e) cfg['have_sys_un_h'] = False else: cfg['have_sys_un_h'] = True self.save_config('config', cfg) if cfg['have_sys_un_h']: settings['define_macros'] = [('HAVE_SYS_UN_H', 1)] settings.setdefault('define_macros', []) # include internal directories settings.setdefault('include_dirs', []) settings['include_dirs'] += [pjoin('zmq', sub) for sub in ('utils','core','devices')] for ext in self.distribution.ext_modules: if ext.name == 'zmq.libzmq': continue for attr, value in settings.items(): setattr(ext, attr, value) self.compiler_settings = settings self.save_config('compiler', settings)
def check_zmq_version(self): zmq = CONFIG['zmq_prefix'] if zmq and not os.path.exists(zmq) and \ not CONFIG['libzmq_extension']: fatal("Custom zmq directory \"%s\" does not exist" % zmq) config = self.getcached() if not config or config.get('settings') != self.settings: self.run() config = self.config else: if CONFIG['libzmq_extension']: config = self.bundle_libzmq_extension() self.config = config line() if CONFIG['libzmq_extension'] or CONFIG['skip_check_zmq'] or CROSSCOMPILE: return # now check the libzmq version vers = tuple(config['vers']) vs = v_str(vers) if vers < min_zmq: fatal("Detected ZMQ version: %s, but depend on zmq >= %s"%( vs, v_str(min_zmq)) +'\n Using ZMQ=%s'%(zmq or 'unspecified')) if vers < target_zmq: warn("Detected ZMQ version: %s, but pyzmq targets ZMQ %s." % ( vs, v_str(target_zmq)) ) warn("libzmq features and fixes introduced after %s will be unavailable." % vs) line() elif vers >= dev_zmq: warn("Detected ZMQ version: %s. pyzmq's support for libzmq-dev is experimental." % vs) line() if sys.platform.startswith('win'): # fetch libzmq.dll into local dir local_dll = localpath('zmq','libzmq.dll') if not zmq and not os.path.exists(local_dll): fatal("ZMQ directory must be specified on Windows via setup.cfg or 'python setup.py configure --zmq=/path/to/zeromq2'") try: shutil.copy(pjoin(zmq, 'lib', 'libzmq.dll'), local_dll) except Exception: if not os.path.exists(local_dll): warn("Could not copy libzmq into zmq/, which is usually necessary on Windows." "Please specify zmq prefix via configure --zmq=/path/to/zmq or copy " "libzmq into zmq/ manually.")
def build_extensions(self): self.extensions.remove(dummy_ext) bld_ext.build_extensions(self) # build ffi extension after bundled libzmq, # because it may depend on linking it if self.inplace: sys.path.insert(0, '') else: sys.path.insert(0, self.build_lib) try: from zmq.backend.cffi import ffi except ImportError as e: warn("Couldn't get CFFI extension: %s" % e) else: ext = ffi.verifier.get_extension() if not ext.name.startswith('zmq.'): ext.name = 'zmq.backend.cffi.' + ext.name self.extensions.append(ext) self.build_extension(ext) finally: sys.path.pop(0)
def create_tempdir(self): self.erase_tempdir() os.makedirs(self.tempdir) if sys.platform.startswith('win'): # fetch libzmq.dll into local dir local_dll = pjoin(self.tempdir, 'libzmq.dll') if not self.config['zmq_prefix'] and not os.path.exists(local_dll): fatal( "ZMQ directory must be specified on Windows via setup.cfg" " or 'python setup.py configure --zmq=/path/to/zeromq2'") try: shutil.copy( pjoin(self.config['zmq_prefix'], 'lib', 'libzmq.dll'), local_dll) except Exception: if not os.path.exists(local_dll): warn( "Could not copy libzmq into zmq/, which is usually necessary on Windows." "Please specify zmq prefix via configure --zmq=/path/to/zmq or copy " "libzmq into zmq/ manually.")
def run(self): try: p = Popen('git log -1'.split(), stdin=PIPE, stdout=PIPE, stderr=PIPE) except IOError: warn("No git found, skipping git revision") return if p.wait(): warn("checking git branch failed") info(p.stderr.read()) return line = p.stdout.readline().decode().strip() if not line.startswith('commit'): warn("bad commit line: %r" % line) return rev = line.split()[-1] # now that we have the git revision, we can apply it to version.py with open(self.version_py) as f: lines = f.readlines() for i,line in enumerate(lines): if line.startswith('__revision__'): lines[i] = "__revision__ = '%s'\n"%rev break with open(self.version_py, 'w') as f: f.writelines(lines)
def fallback_on_bundled(self): """Couldn't build, fallback after waiting a while""" line() warn('\n'.join([ "Couldn't find an acceptable libzmq on the system.", "", "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_good_zmq), " * If ZMQ is not in a default location, supply the argument --zmq=<path>", " * 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`", "", ])) info('\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 try to 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) info("") return self.bundle_libzmq_extension()
def run(self): try: p = Popen('git log -1'.split(), stdin=PIPE, stdout=PIPE, stderr=PIPE) except IOError: warn("No git found, skipping git revision") return if p.wait(): warn("checking git branch failed") info(p.stderr.read()) return line = p.stdout.readline().decode().strip() if not line.startswith('commit'): warn("bad commit line: %r" % line) return rev = line.split()[-1] # now that we have the git revision, we can apply it to version.py with open(self.version_py) as f: lines = f.readlines() for i, line in enumerate(lines): if line.startswith('__revision__'): lines[i] = "__revision__ = '%s'\n" % rev break with open(self.version_py, 'w') as f: f.writelines(lines)
def check_zmq_version(self): zmq = ZMQ if zmq is not None 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'] != COMPILER_SETTINGS: self.run() config = self.config else: self.config = config vers = config['vers'] vs = v_str(vers) if vers < min_zmq: fatal("Detected ZMQ version: %s, but depend on zmq >= %s" % (vs, v_str(min_zmq)) + '\n Using ZMQ=%s' % (zmq or 'unspecified')) pyzmq_version = extract_version().strip('abcdefghijklmnopqrstuvwxyz') if vs < pyzmq_version: 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) elif vs >= '3.0': warn( "Detected ZMQ version: %s. pyzmq's support for libzmq-dev is experimental." % vs) print('*' * 42) if sys.platform.startswith('win'): # fetch libzmq.dll into local dir local_dll = localpath('zmq', 'libzmq.dll') if zmq is None and not os.path.exists(local_dll): fatal( "ZMQ directory must be specified on Windows via setup.cfg or 'python setup.py configure --zmq=/path/to/zeromq2'" ) try: shutil.copy(pjoin(zmq, 'lib', 'libzmq.dll'), local_dll) except Exception: if not os.path.exists(local_dll): warn( "Could not copy libzmq into zmq/, which is usually necessary on Windows." "Please specify zmq prefix via configure --zmq=/path/to/zmq or copy " "libzmq into zmq/ manually.")
def run(self): """Run the test suite, with nose, or unittest if nose is unavailable""" # crude check for inplace build: try: import zmq except ImportError: print_exc() fatal('\n '.join([ "Could not import zmq!", "You must build pyzmq with 'python setup.py build_ext --inplace' for 'python setup.py test' to work.", "If you did build pyzmq in-place, then this is a real error." ])) sys.exit(1) info("Testing pyzmq-%s with libzmq-%s" % (zmq.pyzmq_version(), zmq.zmq_version())) if nose is None: warn( "nose unavailable, falling back on unittest. Skipped tests will appear as ERRORs." ) return self.run_unittest() else: return self.run_nose()
def check_zmq_version(self): zmq = self.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 not config or config.get('settings') != self.settings: self.run() config = self.config else: self.config = config line() if self.zmq == "bundled": return vers = tuple(config['vers']) vs = v_str(vers) if vers < min_zmq: fatal("Detected ZMQ version: %s, but depend on zmq >= %s"%( vs, v_str(min_zmq)) +'\n Using ZMQ=%s'%(zmq or 'unspecified')) pyzmq_vs = extract_version() pyzmq_version = tuple(int(d) for d in re.findall(r'\d+', pyzmq_vs)) if vers < pyzmq_version[:len(vers)]: 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) line() elif vers >= (3,0,0): warn("Detected ZMQ version: %s. pyzmq's support for libzmq-dev is experimental."%vs) line() if sys.platform.startswith('win'): # fetch libzmq.dll into local dir local_dll = localpath('zmq','libzmq.dll') if zmq is None and not os.path.exists(local_dll): fatal("ZMQ directory must be specified on Windows via setup.cfg or 'python setup.py configure --zmq=/path/to/zeromq2'") try: shutil.copy(pjoin(zmq, 'lib', 'libzmq.dll'), local_dll) except Exception: if not os.path.exists(local_dll): warn("Could not copy libzmq into zmq/, which is usually necessary on Windows." "Please specify zmq prefix via configure --zmq=/path/to/zmq or copy " "libzmq into zmq/ manually.")
def check_zmq_version(self): zmq = ZMQ if zmq is not None 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"] != COMPILER_SETTINGS: self.run() config = self.config else: self.config = config vers = config["vers"] vs = v_str(vers) if vers < min_zmq: fatal( "Detected ZMQ version: %s, but depend on zmq >= %s" % (vs, v_str(min_zmq)) + "\n Using ZMQ=%s" % (zmq or "unspecified") ) pyzmq_version = extract_version().strip("abcdefghijklmnopqrstuvwxyz") if vs < pyzmq_version: 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) elif vs > "3.0": warn("Detected ZMQ version: %s. pyzmq's 3.0 support is experimental." % vs) print("*" * 42) if sys.platform.startswith("win"): # fetch libzmq.dll into local dir local_dll = localpath("zmq", "libzmq.dll") if zmq is None and not os.path.exists(local_dll): fatal( "ZMQ directory must be specified on Windows via setup.cfg or 'python setup.py configure --zmq=/path/to/zeromq2'" ) try: shutil.copy(pjoin(zmq, "lib", "libzmq.dll"), local_dll) except Exception: if not os.path.exists(local_dll): warn( "Could not copy libzmq into zmq/, which is usually necessary on Windows." "Please specify zmq prefix via configure --zmq=/path/to/zmq or copy " "libzmq into zmq/ manually." )
def check_zmq_version(self): """check the zmq version""" cfg = self.config # build test program zmq_prefix = self.config['zmq_prefix'] detected = self.test_build(zmq_prefix, self.compiler_settings) # now check the libzmq version vers = tuple(detected['vers']) vs = v_str(vers) if vers < min_zmq: fatal("Detected ZMQ version: %s, but depend on zmq >= %s" % (vs, v_str(min_zmq)) + '\n Using ZMQ=%s' % (zmq_prefix or 'unspecified')) if vers < target_zmq: warn("Detected ZMQ version: %s, but pyzmq targets ZMQ %s." % (vs, v_str(target_zmq))) warn( "libzmq features and fixes introduced after %s will be unavailable." % vs) line() elif vers >= dev_zmq: warn( "Detected ZMQ version: %s. pyzmq's support for libzmq-dev is experimental." % vs) line() if sys.platform.startswith('win'): # fetch libzmq.dll into local dir local_dll = localpath('zmq', 'libzmq.dll') if not zmq_prefix and not os.path.exists(local_dll): fatal( "ZMQ directory must be specified on Windows via setup.cfg or 'python setup.py configure --zmq=/path/to/zeromq2'" ) try: shutil.copy(pjoin(zmq_prefix, 'lib', 'libzmq.dll'), local_dll) except Exception: if not os.path.exists(local_dll): warn( "Could not copy libzmq into zmq/, which is usually necessary on Windows." "Please specify zmq prefix via configure --zmq=/path/to/zmq or copy " "libzmq into zmq/ manually.")
def check_zmq_version(self): """check the zmq version""" cfg = self.config # build test program zmq_prefix = self.config["zmq_prefix"] detected = self.test_build(zmq_prefix, self.compiler_settings) # now check the libzmq version vers = tuple(detected["vers"]) vs = v_str(vers) if vers < min_zmq: fatal( "Detected ZMQ version: %s, but depend on zmq >= %s" % (vs, v_str(min_zmq)) + "\n Using ZMQ=%s" % (zmq_prefix or "unspecified") ) if vers < target_zmq: warn("Detected ZMQ version: %s, but pyzmq targets ZMQ %s." % (vs, v_str(target_zmq))) warn("libzmq features and fixes introduced after %s will be unavailable." % vs) line() elif vers >= dev_zmq: warn("Detected ZMQ version: %s. pyzmq's support for libzmq-dev is experimental." % vs) line() if sys.platform.startswith("win"): # fetch libzmq.dll into local dir local_dll = localpath("zmq", "libzmq.dll") if not zmq_prefix and not os.path.exists(local_dll): fatal( "ZMQ directory must be specified on Windows via setup.cfg or 'python setup.py configure --zmq=/path/to/zeromq2'" ) try: shutil.copy(pjoin(zmq_prefix, "lib", "libzmq.dll"), local_dll) except Exception: if not os.path.exists(local_dll): warn( "Could not copy libzmq into zmq/, which is usually necessary on Windows." "Please specify zmq prefix via configure --zmq=/path/to/zmq or copy " "libzmq into zmq/ manually." )
def check_zmq_version(self): zmq = self.zmq if zmq is not None 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: self.run() config = self.config else: self.config = config vers = config['vers'] vs = v_str(vers) if vers < min_zmq: fatal("Detected ZMQ version: %s, but depend on zmq >= %s"%( vs, v_str(min_zmq)) +'\n Using ZMQ=%s'%(zmq or 'unspecified')) pyzmq_version = extract_version().strip('abcdefghijklmnopqrstuvwxyz') if vs < pyzmq_version: 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) elif vs >= '3.0': warn("Detected ZMQ version: %s. pyzmq's support for libzmq-dev is experimental."%vs) print('*'*42) if sys.platform.startswith('win'): # fetch libzmq.dll into local dir local_dll = localpath('zmq','libzmq.dll') if zmq is None and not os.path.exists(local_dll): fatal("ZMQ directory must be specified on Windows via setup.cfg or 'python setup.py configure --zmq=/path/to/zeromq2'") try: shutil.copy(pjoin(zmq, 'lib', 'libzmq.dll'), local_dll) except Exception: if not os.path.exists(local_dll): warn("Could not copy libzmq into zmq/, which is usually necessary on Windows." "Please specify zmq prefix via configure --zmq=/path/to/zmq or copy " "libzmq into zmq/ manually.")
def check_zmq_version(self): zmq = ZMQ if zmq is not None 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'] != COMPILER_SETTINGS: self.run() config = self.config vers = config['vers'] vs = v_str(vers) if vers < min_zmq: fatal("Detected ZMQ version: %s, but depend on zmq >= %s"%( vs, v_str(min_zmq)) +'\n Using ZMQ=%s'%(zmq or 'unspecified')) pyzmq_version = extract_version().strip('abcdefghijklmnopqrstuvwxyz') if vs < pyzmq_version: warn("Detected ZMQ version: %s, but pyzmq is based on zmq %s."%( vs, pyzmq_version)) warn("Some features may be missing or broken.") print('*'*42) if sys.platform.startswith('win'): # fetch libzmq.dll into local dir local_dll = localpath('zmq','libzmq.dll') if zmq is None and not os.path.exists(local_dll): fatal("ZMQ directory must be specified on Windows via setup.cfg or 'python setup.py configure --zmq=/path/to/zeromq2'") try: shutil.copy(pjoin(zmq, 'lib', 'libzmq.dll'), local_dll) except Exception: if not os.path.exists(local_dll): warn("Could not copy libzmq into zmq/, which is usually necessary on Windows." "Please specify zmq prefix via configure --zmq=/path/to/zmq or copy " "libzmq into zmq/ manually.")
def run(self): cfg = self.config if cfg['libzmq_extension']: self.bundle_libzmq_extension() self.finish_run() return # When cross-compiling and zmq is given explicitly, we can't testbuild # (as we can't testrun the binary), we assume things are alright. if cfg['skip_check_zmq'] or self.cross_compiling: warn("Skipping zmq version check") self.finish_run() return zmq_prefix = cfg['zmq_prefix'] # There is no available default on Windows, so start with fallback unless # zmq was given explicitly, or libzmq extension was explicitly prohibited. if (sys.platform.startswith("win") and not cfg['no_libzmq_extension'] and not zmq_prefix): self.fallback_on_bundled() self.finish_run() return if (zmq_prefix and self.bundle_libzmq_dylib and not sys.platform.startswith('win')): copy_and_patch_libzmq(zmq_prefix, libzmq_name + lib_ext) # first try with given config or defaults try: self.check_zmq_version() except LibZMQVersionError as e: info("\nBad libzmq version: %s\n" % e) except Exception as e: # print the error as distutils would if we let it raise: info("\nerror: %s\n" % e) else: self.finish_run() return # try fallback on /usr/local on *ix if no prefix is given if not zmq_prefix and not sys.platform.startswith('win'): info("Failed with default libzmq, trying again with /usr/local") time.sleep(1) zmq_prefix = cfg['zmq_prefix'] = '/usr/local' self.init_settings_from_config() try: self.check_zmq_version() except LibZMQVersionError as e: info("\nBad libzmq version: %s\n" % e) except Exception as e: # print the error as distutils would if we let it raise: info("\nerror: %s\n" % e) else: # if we get here the second run succeeded, so we need to update compiler # settings for the extensions with /usr/local prefix self.finish_run() return # finally, fallback on bundled if cfg['no_libzmq_extension']: fatal( "Falling back on bundled libzmq," " but config has explicitly prohibited building the libzmq extension." ) self.fallback_on_bundled() self.finish_run()
def bundle_libzmq_extension(self): bundledir = "bundled" ext_modules = self.distribution.ext_modules if ext_modules and any(m.name == 'zmq.libzmq' for m in ext_modules): # I've already been run return line() info("Using bundled libzmq") # fetch sources for libzmq extension: if not os.path.exists(bundledir): os.makedirs(bundledir) fetch_libzmq(bundledir) stage_platform_hpp(pjoin(bundledir, 'zeromq')) sources = [pjoin('buildutils', 'initlibzmq.cpp')] sources.extend([ src for src in glob(pjoin(bundledir, 'zeromq', 'src', '*.cpp')) # exclude draft ws transport files if not os.path.basename(src).startswith(("ws_", "wss_")) ]) includes = [pjoin(bundledir, 'zeromq', 'include')] if bundled_version < (4, 2, 0): tweetnacl = pjoin(bundledir, 'zeromq', 'tweetnacl') tweetnacl_sources = glob(pjoin(tweetnacl, 'src', '*.c')) randombytes = pjoin(tweetnacl, 'contrib', 'randombytes') if sys.platform.startswith('win'): tweetnacl_sources.append(pjoin(randombytes, 'winrandom.c')) else: tweetnacl_sources.append(pjoin(randombytes, 'devurandom.c')) sources += tweetnacl_sources includes.append(pjoin(tweetnacl, 'src')) includes.append(randombytes) else: # >= 4.2 sources += glob(pjoin(bundledir, 'zeromq', 'src', 'tweetnacl.c')) # construct the Extensions: libzmq = Extension( 'zmq.libzmq', sources=sources, include_dirs=includes, ) # register the extension: # doing this here means we must be run # before finalize_options in build_ext self.distribution.ext_modules.insert(0, libzmq) # use tweetnacl to provide CURVE support libzmq.define_macros.append(('ZMQ_HAVE_CURVE', 1)) libzmq.define_macros.append(('ZMQ_USE_TWEETNACL', 1)) # select polling subsystem based on platform if sys.platform == "darwin" or "bsd" in sys.platform: libzmq.define_macros.append(('ZMQ_USE_KQUEUE', 1)) libzmq.define_macros.append(('ZMQ_IOTHREADS_USE_KQUEUE', 1)) libzmq.define_macros.append(('ZMQ_POLL_BASED_ON_POLL', 1)) elif 'linux' in sys.platform: libzmq.define_macros.append(('ZMQ_USE_EPOLL', 1)) libzmq.define_macros.append(('ZMQ_IOTHREADS_USE_EPOLL', 1)) libzmq.define_macros.append(('ZMQ_POLL_BASED_ON_POLL', 1)) elif sys.platform.startswith('win'): libzmq.define_macros.append(('ZMQ_USE_SELECT', 1)) libzmq.define_macros.append(('ZMQ_IOTHREADS_USE_SELECT', 1)) libzmq.define_macros.append(('ZMQ_POLL_BASED_ON_SELECT', 1)) else: # this may not be sufficiently precise libzmq.define_macros.append(('ZMQ_USE_POLL', 1)) libzmq.define_macros.append(('ZMQ_IOTHREADS_USE_POLL', 1)) libzmq.define_macros.append(('ZMQ_POLL_BASED_ON_POLL', 1)) if sys.platform.startswith('win'): # include defines from zeromq msvc project: libzmq.define_macros.append(('FD_SETSIZE', 16384)) libzmq.define_macros.append(('DLL_EXPORT', 1)) libzmq.define_macros.append(('_CRT_SECURE_NO_WARNINGS', 1)) # 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". if self.compiler_type == 'msvc': libzmq.extra_compile_args.append('/EHsc') elif self.compiler_type == 'mingw32': libzmq.define_macros.append(('ZMQ_HAVE_MINGW32', 1)) # And things like sockets come from libraries that must be named. libzmq.libraries.extend( ['rpcrt4', 'ws2_32', 'advapi32', 'iphlpapi']) # bundle MSCVP redist if self.config['bundle_msvcp']: from setuptools import msvc from setuptools._distutils.util import get_platform vcvars = msvc.msvc14_get_vc_env(get_platform()) try: vcruntime = vcvars["py_vcruntime_redist"] except KeyError: warn(f"platform={get_platform()}, vcvars=") pprint(vcvars, stream=sys.stderr) # fatal error if env set, warn otherwise msg = fatal if os.environ.get("PYZMQ_BUNDLE_CRT") else warn msg("Failed to get py_vcruntime_redist via vcvars, not bundling MSVCP" ) redist_dir, dll = os.path.split(vcruntime) to_bundle = [ pjoin(redist_dir, dll.replace('vcruntime', name)) for name in ('msvcp', 'concrt') ] for src in to_bundle: dest = localpath('zmq', basename(src)) info("Copying %s -> %s" % (src, dest)) # copyfile to avoid permission issues shutil.copyfile(src, dest) else: libzmq.include_dirs.append(bundledir) # check if we need to link against Realtime Extensions library cc = new_compiler(compiler=self.compiler_type) customize_compiler(cc) cc.output_dir = self.build_temp if not sys.platform.startswith(('darwin', 'freebsd')): line() info("checking for timer_create") if not cc.has_function('timer_create'): info("no timer_create, linking librt") libzmq.libraries.append('rt') else: info("ok") # copy the header files to the source tree. bundledincludedir = pjoin('zmq', 'include') if not os.path.exists(bundledincludedir): os.makedirs(bundledincludedir) if not os.path.exists(pjoin(self.build_lib, bundledincludedir)): os.makedirs(pjoin(self.build_lib, bundledincludedir)) for header in glob(pjoin(bundledir, 'zeromq', 'include', '*.h')): shutil.copyfile(header, pjoin(bundledincludedir, basename(header))) shutil.copyfile( header, pjoin(self.build_lib, bundledincludedir, basename(header))) # update other extensions, with bundled settings self.config['libzmq_extension'] = True self.init_settings_from_config() self.save_config('config', self.config)
def check_zmq_version(self): """check the zmq version""" cfg = self.config # build test program zmq_prefix = cfg['zmq_prefix'] detected = self.test_build(zmq_prefix, self.compiler_settings) # now check the libzmq version vers = tuple(detected['vers']) vs = v_str(vers) if cfg['allow_legacy_libzmq']: min_zmq = min_legacy_zmq else: min_zmq = min_good_zmq if vers < min_zmq: msg = [ "Detected ZMQ version: %s, but require ZMQ >= %s" % (vs, v_str(min_zmq)), ] if zmq_prefix: msg.append(" ZMQ_PREFIX=%s" % zmq_prefix) if vers >= min_legacy_zmq: msg.append( " Explicitly allow legacy zmq by specifying `--zmq=/zmq/prefix`" ) raise LibZMQVersionError('\n'.join(msg)) if vers < min_good_zmq: msg = [ "Detected legacy ZMQ version: %s. It is STRONGLY recommended to use ZMQ >= %s" % (vs, v_str(min_good_zmq)), ] if zmq_prefix: msg.append(" ZMQ_PREFIX=%s" % zmq_prefix) warn('\n'.join(msg)) elif vers < target_zmq: warn("Detected ZMQ version: %s, but pyzmq targets ZMQ %s." % (vs, v_str(target_zmq))) warn( "libzmq features and fixes introduced after %s will be unavailable." % vs) line() elif vers >= dev_zmq: warn( "Detected ZMQ version: %s. Some new features in libzmq may not be exposed by pyzmq." % vs) line() if sys.platform.startswith('win'): # fetch libzmq.dll into local dir local_dll = localpath('zmq', libzmq_name + '.dll') if not zmq_prefix and not os.path.exists(local_dll): fatal( "ZMQ directory must be specified on Windows via setup.cfg or 'python setup.py configure --zmq=/path/to/zeromq2'" ) try: shutil.copy(pjoin(zmq_prefix, 'lib', libzmq_name + '.dll'), local_dll) except Exception: if not os.path.exists(local_dll): warn( "Could not copy " + libzmq_name + " into zmq/, which is usually necessary on Windows." "Please specify zmq prefix via configure --zmq=/path/to/zmq or copy " + libzmq_name + " into zmq/ manually.")
def init_settings_from_config(self): """set up compiler settings, based on config""" cfg = self.config if sys.platform == 'win32' and cfg.get('bundle_msvcp') is None: # default bundle_msvcp=True on: # Windows Python 3.5 bdist *without* DISTUTILS_USE_SDK if os.environ.get("PYZMQ_BUNDLE_CRT") or ( doing_bdist and self.compiler_type == "msvc" and not os.environ.get("DISTUTILS_USE_SDK")): cfg['bundle_msvcp'] = True if cfg['libzmq_extension']: settings = bundled_settings(self.debug) else: settings = settings_from_prefix(cfg['zmq_prefix'], self.bundle_libzmq_dylib) if 'have_sys_un_h' not in cfg: # don't link against anything when checking for sys/un.h minus_zmq = copy.deepcopy(settings) try: minus_zmq['libraries'] = [] except Exception: pass try: compile_and_forget(self.tempdir, pjoin('buildutils', 'check_sys_un.c'), **minus_zmq) except Exception as e: warn("No sys/un.h, IPC_PATH_MAX_LEN will be undefined: %s" % e) cfg['have_sys_un_h'] = False else: cfg['have_sys_un_h'] = True self.save_config('config', cfg) settings.setdefault('define_macros', []) if cfg['have_sys_un_h']: settings['define_macros'].append(('HAVE_SYS_UN_H', 1)) if cfg.get('zmq_draft_api'): settings['define_macros'].append(('ZMQ_BUILD_DRAFT_API', 1)) use_static_zmq = cfg.get('use_static_zmq', 'False').upper() if use_static_zmq in ('TRUE', '1'): settings['define_macros'].append(('ZMQ_STATIC', '1')) if os.environ.get("PYZMQ_CYTHON_COVERAGE"): settings['define_macros'].append(('CYTHON_TRACE', '1')) # include internal directories settings.setdefault('include_dirs', []) settings['include_dirs'] += [pjoin('zmq', sub) for sub in ('utils', )] settings.setdefault('libraries', []) # Explicitly link dependencies, not necessary if zmq is dynamic if sys.platform.startswith('win'): settings['libraries'].extend(('ws2_32', 'iphlpapi', 'advapi32')) for ext in self.distribution.ext_modules: if ext.name.startswith('zmq.lib'): continue for attr, value in settings.items(): setattr(ext, attr, value) self.compiler_settings = settings self.save_config('compiler', settings)
import subprocess import sys import time import errno import platform from traceback import print_exc # whether any kind of bdist is happening # do this before importing anything from distutils doing_bdist = any(arg.startswith('bdist') for arg in sys.argv[1:]) if doing_bdist: try: import setuptools except Exception: warn("doing a bdist, but setuptools is unavailable") import distutils from distutils.core import setup, Command from distutils.ccompiler import get_default_compiler from distutils.ccompiler import new_compiler from distutils.extension import Extension from distutils.command.build_ext import build_ext from distutils.command.sdist import sdist from distutils.version import LooseVersion as V from unittest import TextTestRunner, TestLoader from glob import glob from os.path import splitext, basename, join as pjoin from subprocess import Popen, PIPE
sources=sources, include_dirs=[ pjoin('zmq', sub) for sub in ('utils', pjoin('backend', 'cython'), 'devices') ], ) if suffix == '.pyx' and ext.sources[0].endswith('.c'): # undo setuptools stupidly clobbering cython sources: ext.sources = sources extensions.append(ext) if 'PyPy' in sys.version: try: from zmq.backend.cffi import ffi except ImportError: warn("Couldn't get CFFI extension") extensions = [] else: extensions = [ffi.verifier.get_extension()] package_data = { 'zmq': ['*.pxd'], 'zmq.backend.cython': ['*.pxd'], 'zmq.devices': ['*.pxd'], 'zmq.utils': ['*.pxd', '*.h'], } package_data['zmq'].append('libzmq' + lib_ext) def extract_version():
def run(self): cfg = self.config if 'PyPy' in sys.version: info("PyPy: Nothing to configure") return if cfg['libzmq_extension']: self.bundle_libzmq_extension() self.finish_run() return # When cross-compiling and zmq is given explicitly, we can't testbuild # (as we can't testrun the binary), we assume things are alright. if cfg['skip_check_zmq'] or self.cross_compiling: warn("Skipping zmq version check") self.finish_run() return zmq_prefix = cfg['zmq_prefix'] # There is no available default on Windows, so start with fallback unless # zmq was given explicitly, or libzmq extension was explicitly prohibited. if sys.platform.startswith("win") and \ not cfg['no_libzmq_extension'] and \ not zmq_prefix: self.fallback_on_bundled() self.finish_run() return if zmq_prefix and self.bundle_libzmq_dylib and not sys.platform.startswith('win'): copy_and_patch_libzmq(zmq_prefix, 'libzmq'+lib_ext) # first try with given config or defaults try: self.check_zmq_version() except Exception: etype, evalue, tb = sys.exc_info() # print the error as distutils would if we let it raise: info("\nerror: %s\n" % evalue) else: self.finish_run() return # try fallback on /usr/local on *ix if no prefix is given if not zmq_prefix and not sys.platform.startswith('win'): info("Failed with default libzmq, trying again with /usr/local") time.sleep(1) zmq_prefix = cfg['zmq_prefix'] = '/usr/local' self.init_settings_from_config() try: self.check_zmq_version() except Exception: etype, evalue, tb = sys.exc_info() # print the error as distutils would if we let it raise: info("\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.finish_run() return # finally, fallback on bundled if cfg['no_libzmq_extension']: fatal("Falling back on bundled libzmq," " but setup.cfg has explicitly prohibited building the libzmq extension." ) self.fallback_on_bundled() self.finish_run()
def settings_from_prefix(prefix=None, bundle_libzmq_dylib=False): """load appropriate library/include settings from ZMQ prefix""" settings = {} settings['libraries'] = [] settings['include_dirs'] = [] settings['library_dirs'] = [] settings['runtime_library_dirs'] = [] settings['extra_link_args'] = [] if sys.platform.startswith('win'): settings['libraries'].append('libzmq') if prefix: settings['include_dirs'] += [pjoin(prefix, 'include')] settings['library_dirs'] += [pjoin(prefix, 'lib')] else: # If prefix is not explicitly set, pull it from pkg-config by default. if not prefix: try: p = Popen('pkg-config --variable=prefix --print-errors libzmq'.split(), stdout=PIPE, stderr=PIPE) except OSError as e: if e.errno == errno.ENOENT: info("pkg-config not found") else: warn("Running pkg-config failed - %s." % e) p = None if p is not None: if p.wait(): info("Did not find libzmq via pkg-config:") info(p.stderr.read().decode()) else: prefix = p.stdout.readline().strip().decode() info("Using zmq-prefix %s (found via pkg-config)." % prefix) settings['libraries'].append('zmq') # add pthread on freebsd if sys.platform.startswith('freebsd'): settings['libraries'].append('pthread') if sys.platform.startswith('sunos'): if platform.architecture()[0] == '32bit': settings['extra_link_args'] += ['-m32'] else: settings['extra_link_args'] += ['-m64'] if prefix: settings['include_dirs'] += [pjoin(prefix, 'include')] if not bundle_libzmq_dylib: if sys.platform.startswith('sunos') and platform.architecture()[0] == '64bit': settings['library_dirs'] += [pjoin(prefix, 'lib/amd64')] settings['library_dirs'] += [pjoin(prefix, 'lib')] else: if sys.platform == 'darwin' and os.path.isdir('/opt/local/lib'): # allow macports default settings['include_dirs'] += ['/opt/local/include'] settings['library_dirs'] += ['/opt/local/lib'] if os.environ.get('VIRTUAL_ENV', None): # find libzmq installed in virtualenv env = os.environ['VIRTUAL_ENV'] settings['include_dirs'] += [pjoin(env, 'include')] settings['library_dirs'] += [pjoin(env, 'lib')] if bundle_libzmq_dylib: # bdist should link against bundled libzmq settings['library_dirs'].append('zmq') if sys.platform == 'darwin': pass # unused rpath args for OS X: # settings['extra_link_args'] = ['-Wl,-rpath','-Wl,$ORIGIN/..'] else: settings['runtime_library_dirs'] += ['$ORIGIN/..'] elif sys.platform != 'darwin': settings['runtime_library_dirs'] += [ os.path.abspath(x) for x in settings['library_dirs'] ] return settings
def settings_from_prefix(prefix=None): """load appropriate library/include settings from ZMQ prefix""" settings = {} settings['libraries'] = [] settings['include_dirs'] = [] settings['library_dirs'] = [] settings['runtime_library_dirs'] = [] settings['extra_link_args'] = [] if sys.platform.startswith('win'): global libzmq_name if prefix: # add prefix itself as well, for e.g. libzmq Windows releases for include_dir in [pjoin(prefix, 'include'), prefix]: if os.path.exists(pjoin(include_dir, "zmq.h")): settings['include_dirs'].append(include_dir) info(f"Found zmq.h in {include_dir}") break else: warn(f"zmq.h not found in {prefix} or {prefix}/include") for library_dir in [pjoin(prefix, 'lib'), prefix]: matches = glob(pjoin(library_dir, f"{libzmq_name}*.dll")) if matches: libzmq_path = matches[0] libzmq_lib, libzmq_dll_name = os.path.split(libzmq_path) libzmq_name, _ = os.path.splitext(libzmq_dll_name) info(f"Found {libzmq_path} in {libzmq_lib}") if libzmq_lib not in os.environ["PATH"].split(os.pathsep): info(f"Adding {libzmq_lib} to $PATH") os.environ["PATH"] += os.pathsep + libzmq_lib settings['library_dirs'].append(library_dir) break else: warn( f"{libzmq_name}.dll not found in {prefix} or {prefix}/lib") settings['libraries'].append(libzmq_name) else: # add pthread on freebsd if sys.platform.startswith('freebsd'): settings['libraries'].append('pthread') if sys.platform.startswith('sunos'): if platform.architecture()[0] == '32bit': settings['extra_link_args'] += ['-m32'] else: settings['extra_link_args'] += ['-m64'] if prefix: settings['libraries'].append('zmq') settings['include_dirs'] += [pjoin(prefix, 'include')] if (sys.platform.startswith('sunos') and platform.architecture()[0] == '64bit'): settings['library_dirs'] += [pjoin(prefix, 'lib/amd64')] settings['library_dirs'] += [pjoin(prefix, 'lib')] else: # If prefix is not explicitly set, pull it from pkg-config by default. # this is probably applicable across platforms, but i don't have # sufficient test environments to confirm pkgcfginfo = check_pkgconfig() if pkgcfginfo is not None: # we can get all the zmq-specific values from pkgconfg for key, value in pkgcfginfo.items(): settings[key].extend(value) else: settings['libraries'].append('zmq') if sys.platform == 'darwin' and os.path.isdir( '/opt/local/lib'): # allow macports default settings['include_dirs'] += ['/opt/local/include'] settings['library_dirs'] += ['/opt/local/lib'] if os.environ.get('VIRTUAL_ENV', None): # find libzmq installed in virtualenv env = os.environ['VIRTUAL_ENV'] settings['include_dirs'] += [pjoin(env, 'include')] settings['library_dirs'] += [pjoin(env, 'lib')] for path in settings['library_dirs']: _add_rpath(settings, os.path.abspath(path)) info(settings) return settings
def settings_from_prefix(prefix=None, bundle_libzmq_dylib=False): """load appropriate library/include settings from ZMQ prefix""" settings = {} settings['libraries'] = [] settings['include_dirs'] = [] settings['library_dirs'] = [] settings['runtime_library_dirs'] = [] settings['extra_link_args'] = [] if sys.platform.startswith('win'): settings['libraries'].append('libzmq') if prefix: settings['include_dirs'] += [pjoin(prefix, 'include')] settings['library_dirs'] += [pjoin(prefix, 'lib')] else: # If prefix is not explicitly set, pull it from pkg-config by default. if not prefix: try: p = Popen('pkg-config --variable=prefix --print-errors libzmq'.split(), stdout=PIPE, stderr=PIPE) except OSError as e: if e.errno == errno.ENOENT: info("pkg-config not found") else: warn("Running pkg-config failed - %s." % e) p = None if p is not None: if p.wait(): info("Did not find libzmq via pkg-config:") info(p.stderr.read().decode()) else: prefix = p.stdout.readline().strip().decode() info("Using zmq-prefix %s (found via pkg-config)." % prefix) settings['libraries'].append('zmq') # add pthread on freebsd if sys.platform.startswith('freebsd'): settings['libraries'].append('pthread') if prefix: settings['include_dirs'] += [pjoin(prefix, 'include')] if not bundle_libzmq_dylib: if sys.platform == 'sunos5': if platform.architecture()[0] == '32bit': settings['library_dirs'] += [pjoin(prefix, 'lib')] else: settings['library_dirs'] += [pjoin(prefix, 'lib/amd64')] settings['extra_link_args'] += ['-m64'] else: settings['library_dirs'] += [pjoin(prefix, 'lib')] else: if sys.platform == 'darwin' and os.path.isdir('/opt/local/lib'): # allow macports default settings['include_dirs'] += ['/opt/local/include'] settings['library_dirs'] += ['/opt/local/lib'] if os.environ.get('VIRTUAL_ENV', None): # find libzmq installed in virtualenv env = os.environ['VIRTUAL_ENV'] settings['include_dirs'] += [pjoin(env, 'include')] settings['library_dirs'] += [pjoin(env, 'lib')] if bundle_libzmq_dylib: # bdist should link against bundled libzmq settings['library_dirs'].append('zmq') if sys.platform == 'darwin': pass # unused rpath args for OS X: # settings['extra_link_args'] = ['-Wl,-rpath','-Wl,$ORIGIN/..'] else: settings['runtime_library_dirs'] += ['$ORIGIN/..'] elif sys.platform != 'darwin': settings['runtime_library_dirs'] += [ os.path.abspath(x) for x in settings['library_dirs'] ] return settings
def bundle_libzmq_extension(self): bundledir = "bundled" if "PyPy" in sys.version: fatal("Can't bundle libzmq as an Extension in PyPy (yet!)") ext_modules = self.distribution.ext_modules if ext_modules and ext_modules[0].name == 'zmq.libzmq': # I've already been run return line() info("Using bundled libzmq") # fetch sources for libzmq extension: if not os.path.exists(bundledir): os.makedirs(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)) ext.define_macros.append(('DLL_EXPORT', 1)) # 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". if self.compiler_type == 'msvc': ext.extra_compile_args.append('/EHsc') elif self.compiler_type == 'mingw32': ext.define_macros.append(('ZMQ_HAVE_MINGW32', 1)) # And things like sockets come from libraries that must be named. ext.libraries.extend(['rpcrt4', 'ws2_32', 'advapi32']) else: ext.include_dirs.append(bundledir) # check if we need to link against Realtime Extensions library cc = new_compiler(compiler=self.compiler_type) cc.output_dir = self.build_temp if not sys.platform.startswith(('darwin', 'freebsd')) \ and not cc.has_function('timer_create'): ext.libraries.append('rt') # check if we *can* link libsodium if cc.has_function('crypto_box_keypair', libraries=ext.libraries + ['sodium']): ext.libraries.append('sodium') ext.define_macros.append(("HAVE_LIBSODIUM", 1)) else: warn( "libsodium not found, zmq.CURVE security will be unavailable" ) # insert the extension: self.distribution.ext_modules.insert(0, ext) # update other extensions, with bundled settings self.config['libzmq_extension'] = True self.init_settings_from_config() self.save_config('config', self.config)
lib_ext = '.dylib' else: lib_ext = '.so' # whether any kind of bdist is happening doing_bdist = any(arg.startswith('bdist') for arg in sys.argv[1:]) #----------------------------------------------------------------------------- # Configuration (adapted from h5py: http://h5py.googlecode.com) #----------------------------------------------------------------------------- ZMQ = discover_settings() 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_dylib flag for whether external libzmq library will be included in pyzmq: if sys.platform.startswith('win'): bundle_libzmq_dylib = True elif ZMQ is not None and ZMQ != "bundled": bundle_libzmq_dylib = doing_bdist else: bundle_libzmq_dylib = False # --- compiler settings ------------------------------------------------- def bundled_settings(): settings = { 'libraries' : [], 'include_dirs' : ["bundled/zeromq/include"],
def settings_from_prefix(prefix=None, bundle_libzmq_dylib=False): """load appropriate library/include settings from ZMQ prefix""" settings = {} settings["libraries"] = [] settings["include_dirs"] = [] settings["library_dirs"] = [] settings["runtime_library_dirs"] = [] settings["extra_link_args"] = [] if sys.platform.startswith("win"): settings["libraries"].append("libzmq") if prefix: settings["include_dirs"] += [pjoin(prefix, "include")] settings["library_dirs"] += [pjoin(prefix, "lib")] else: # If prefix is not explicitly set, pull it from pkg-config by default. if not prefix: try: p = Popen("pkg-config --variable=prefix --print-errors libzmq".split(), stdout=PIPE, stderr=PIPE) except OSError as e: if e.errno == errno.ENOENT: info("pkg-config not found") else: warn("Running pkg-config failed - %s." % e) p = None if p is not None: if p.wait(): info("Did not find libzmq via pkg-config:") info(p.stderr.read().decode()) else: prefix = p.stdout.readline().strip().decode() info("Using zmq-prefix %s (found via pkg-config)." % prefix) settings["libraries"].append("zmq") # add pthread on freebsd if sys.platform.startswith("freebsd"): settings["libraries"].append("pthread") if prefix: settings["include_dirs"] += [pjoin(prefix, "include")] if not bundle_libzmq_dylib: if sys.platform == "sunos5": if platform.architecture()[0] == "32bit": settings["library_dirs"] += [pjoin(prefix, "lib")] else: settings["library_dirs"] += [pjoin(prefix, "lib/amd64")] settings["extra_link_args"] += ["-m64"] else: settings["library_dirs"] += [pjoin(prefix, "lib")] else: if sys.platform == "darwin" and os.path.isdir("/opt/local/lib"): # allow macports default settings["include_dirs"] += ["/opt/local/include"] settings["library_dirs"] += ["/opt/local/lib"] if os.environ.get("VIRTUAL_ENV", None): # find libzmq installed in virtualenv env = os.environ["VIRTUAL_ENV"] settings["include_dirs"] += [pjoin(env, "include")] settings["library_dirs"] += [pjoin(env, "lib")] if bundle_libzmq_dylib: # bdist should link against bundled libzmq settings["library_dirs"].append("zmq") if sys.platform == "darwin": pass # unused rpath args for OS X: # settings['extra_link_args'] = ['-Wl,-rpath','-Wl,$ORIGIN/..'] else: settings["runtime_library_dirs"] += ["$ORIGIN/.."] elif sys.platform != "darwin": settings["runtime_library_dirs"] += [os.path.abspath(x) for x in settings["library_dirs"]] return settings
lib_ext = '.1.dylib' else: lib_ext = '.so.1' # whether any kind of bdist is happening doing_bdist = any(arg.startswith('bdist') for arg in sys.argv[1:]) #----------------------------------------------------------------------------- # Configuration (adapted from h5py: http://h5py.googlecode.com) #----------------------------------------------------------------------------- ZMQ = discover_settings() if ZMQ is not None and not os.path.exists(ZMQ): warn("ZMQ directory \"%s\" does not appear to exist" % ZMQ) # --- compiler settings ------------------------------------------------- if sys.platform.startswith('win'): COMPILER_SETTINGS = { 'libraries' : ['libzmq'], 'include_dirs' : [], 'library_dirs' : [], } if ZMQ is not None: COMPILER_SETTINGS['include_dirs'] += [pjoin(ZMQ, 'include')] COMPILER_SETTINGS['library_dirs'] += [pjoin(ZMQ, 'lib')] else: COMPILER_SETTINGS = { 'libraries' : ['zmq'],
sources.extend(packages[pkg]) ext = Extension( 'zmq.%s.%s'%(submod, pkg), sources = sources, include_dirs=[pjoin('zmq', sub) for sub in ('utils',pjoin('backend', 'cython'),'devices')], ) if suffix == '.pyx' and ext.sources[0].endswith('.c'): # undo setuptools stupidly clobbering cython sources: ext.sources = sources extensions.append(ext) if 'PyPy' in sys.version: try: from zmq.backend.cffi import ffi except ImportError: warn("Couldn't get CFFI extension") extensions = [] else: extensions = [ffi.verifier.get_extension()] package_data = {'zmq':['*.pxd'], 'zmq.backend.cython':['*.pxd'], 'zmq.devices':['*.pxd'], 'zmq.utils':['*.pxd', '*.h'], } package_data['zmq'].append('libzmq'+lib_ext) def extract_version(): """extract pyzmq version from sugar/version.py, so it's not multiply defined""" with open(pjoin('zmq', 'sugar', 'version.py')) as f:
def bundle_libzmq_extension(self): bundledir = "bundled" if "PyPy" in sys.version: fatal("Can't bundle libzmq as an Extension in PyPy (yet!)") ext_modules = self.distribution.ext_modules if ext_modules and ext_modules[0].name == 'zmq.libzmq': # I've already been run return line() info("Using bundled libzmq") # fetch sources for libzmq extension: if not os.path.exists(bundledir): os.makedirs(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)) ext.define_macros.append(('DLL_EXPORT', 1)) # 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". if self.compiler_type == 'msvc': ext.extra_compile_args.append('/EHsc') elif self.compiler_type == 'mingw32': ext.define_macros.append(('ZMQ_HAVE_MINGW32', 1)) # And things like sockets come from libraries that must be named. ext.libraries.extend(['rpcrt4', 'ws2_32', 'advapi32']) else: ext.include_dirs.append(bundledir) # check if we need to link against Realtime Extensions library cc = new_compiler(compiler=self.compiler_type) cc.output_dir = self.build_temp if not sys.platform.startswith(('darwin', 'freebsd')) \ and not cc.has_function('timer_create'): ext.libraries.append('rt') # check if we *can* link libsodium if cc.has_function('crypto_box_keypair', libraries=ext.libraries + ['sodium']): ext.libraries.append('sodium') ext.define_macros.append(("HAVE_LIBSODIUM", 1)) else: warn("libsodium not found, zmq.CURVE security will be unavailable") # insert the extension: self.distribution.ext_modules.insert(0, ext) # update other extensions, with bundled settings self.config['libzmq_extension'] = True self.init_settings_from_config() self.save_config('config', self.config)
def init_settings_from_config(self): """set up compiler settings, based on config""" cfg = self.config if sys.platform == 'win32' and cfg.get('bundle_msvcp') is None: # default bundle_msvcp=True on: # Windows Python 3.5 bdist *without* DISTUTILS_USE_SDK if os.environ.get("PYZMQ_BUNDLE_CRT") or ( sys.version_info >= (3, 5) and self.compiler_type == 'msvc' and not os.environ.get('DISTUTILS_USE_SDK') and doing_bdist): cfg['bundle_msvcp'] = True if cfg['libzmq_extension']: settings = bundled_settings(self.debug) else: settings = settings_from_prefix(cfg['zmq_prefix'], self.bundle_libzmq_dylib) if 'have_sys_un_h' not in cfg: # don't link against anything when checking for sys/un.h minus_zmq = copy.deepcopy(settings) try: minus_zmq['libraries'] = [] except Exception: pass try: compile_and_run(self.tempdir, pjoin('buildutils', 'check_sys_un.c'), **minus_zmq) except Exception as e: warn("No sys/un.h, IPC_PATH_MAX_LEN will be undefined: %s" % e) cfg['have_sys_un_h'] = False else: cfg['have_sys_un_h'] = True self.save_config('config', cfg) if cfg['have_sys_un_h']: settings['define_macros'] = [('HAVE_SYS_UN_H', 1)] settings.setdefault('define_macros', []) # include internal directories settings.setdefault('include_dirs', []) settings['include_dirs'] += [ pjoin('zmq', sub) for sub in ( 'utils', pjoin('backend', 'cython'), 'devices', ) ] if sys.platform.startswith('win') and sys.version_info < (3, 3): settings['include_dirs'].insert( 0, pjoin('buildutils', 'include_win32')) for ext in self.distribution.ext_modules: if ext.name.startswith('zmq.lib'): continue for attr, value in settings.items(): setattr(ext, attr, value) self.compiler_settings = settings self.save_config('compiler', settings)
def init_settings_from_config(self): """set up compiler settings, based on config""" cfg = self.config if sys.platform == 'win32' and cfg.get('bundle_msvcp') is None: # default bundle_msvcp=True on: # Windows Python 3.5 bdist *without* DISTUTILS_USE_SDK if os.environ.get("PYZMQ_BUNDLE_CRT") or ( sys.version_info >= (3,5) and self.compiler_type == 'msvc' and not os.environ.get('DISTUTILS_USE_SDK') and doing_bdist ): cfg['bundle_msvcp'] = True if cfg['libzmq_extension']: settings = bundled_settings(self.debug) else: settings = settings_from_prefix(cfg['zmq_prefix'], self.bundle_libzmq_dylib) if 'have_sys_un_h' not in cfg: # don't link against anything when checking for sys/un.h minus_zmq = copy.deepcopy(settings) try: minus_zmq['libraries'] = [] except Exception: pass try: compile_and_forget(self.tempdir, pjoin('buildutils', 'check_sys_un.c'), **minus_zmq ) except Exception as e: warn("No sys/un.h, IPC_PATH_MAX_LEN will be undefined: %s" % e) cfg['have_sys_un_h'] = False else: cfg['have_sys_un_h'] = True self.save_config('config', cfg) if cfg['have_sys_un_h']: settings['define_macros'] = [('HAVE_SYS_UN_H', 1)] settings.setdefault('define_macros', []) if cfg.get('zmq_draft_api'): settings['define_macros'].append(('ZMQ_BUILD_DRAFT_API', 1)) # include internal directories settings.setdefault('include_dirs', []) settings['include_dirs'] += [pjoin('zmq', sub) for sub in ( 'utils', pjoin('backend', 'cython'), 'devices', )] if sys.platform.startswith('win') and sys.version_info < (3, 3): settings['include_dirs'].insert(0, pjoin('buildutils', 'include_win32')) for ext in self.distribution.ext_modules: if ext.name.startswith('zmq.lib'): continue for attr, value in settings.items(): setattr(ext, attr, value) self.compiler_settings = settings self.save_config('compiler', settings)