/
zmqconfig.py
220 lines (194 loc) · 7.83 KB
/
zmqconfig.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# -*- coding: utf-8 -*-
import os
import sys
import distutils
import errno
import platform
from itertools import chain
import functools
from glob import glob
import subprocess
from subprocess import Popen, check_call, CalledProcessError
from os.path import exists, join as pjoin
import distutils
from distutils import log
warn = log.warn
info = log.info
HERE = os.path.dirname(__file__)
def get_zmq_config():
"""Get ZeroMQ config"""
try:
import zmq
except ImportError as e:
pass
else:
compiler_json = pjoin(os.path.dirname(zmq.__file__), 'utils', 'compiler.json')
try:
import json
with open(compiler_json, 'r') as f:
config = json.loads(f.read())
except (ValueError, IOError, OSError):
pass
return {}
def get_zmq_include_path():
"""Get the ZMQ include path in an import-safe manner."""
try:
import zmq
includes = zmq.get_includes()
except ImportError as e:
includes = []
if os.path.exists(pjoin(HERE, 'include')):
includes += [ pjoin(HERE, 'include') ]
return includes
def get_zmq_library_path():
"""Get the ZMQ include path in an import-safe manner."""
try:
import zmq
except ImportError as e:
pass
else:
ZMQDIR = os.path.dirname(zmq.__file__)
if len(glob(pjoin(ZMQDIR, 'libzmq.*'))):
return [ZMQDIR]
elif os.path.exists(pjoin(ZMQDIR,".libs")):
return [pjoin(ZMQDIR,".libs")+os.path.sep]
return []
def unix_libname(name):
if name.startswith("lib"):
return name[3:]
return name
def bundled_settings(debug, libzmq_name='libzmq'):
"""settings for linking extensions against bundled libzmq"""
settings = {}
settings['libraries'] = []
settings['library_dirs'] = get_zmq_library_path()
settings['include_dirs'] = get_zmq_include_path()
settings['runtime_library_dirs'] = get_zmq_library_path()
# add pthread on freebsd
# is this necessary?
if sys.platform.startswith('freebsd'):
settings['libraries'].append(unix_libname(libzmq_name))
settings['libraries'].append('pthread')
elif sys.platform.startswith('win'):
suffix = ''
if sys.version_info >= (3,5):
# Python 3.5 adds EXT_SUFFIX to libs
ext_suffix = distutils.sysconfig.get_config_var('EXT_SUFFIX')
suffix = os.path.splitext(ext_suffix)[0]
if debug:
suffix = '_d' + suffix
settings['libraries'].append(libzmq_name + suffix)
else:
settings['libraries'].append(unix_libname(libzmq_name))
return settings
def check_pkgconfig(libzmq_name='libzmq'):
""" 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 settings_from_prefix(prefix=None, bundle_libzmq_dylib=False, libzmq_name='libzmq'):
"""load appropriate library/include settings from ZMQ prefix"""
settings = {}
settings['libraries'] = []
settings['library_dirs'] = get_zmq_library_path()
settings['include_dirs'] = get_zmq_include_path()
settings['runtime_library_dirs'] = get_zmq_library_path()
settings['extra_link_args'] = []
if sys.platform.startswith('win'):
settings['libraries'].append(libzmq_name)
if prefix:
settings['include_dirs'] += [pjoin(prefix, 'include')]
settings['library_dirs'] += [pjoin(prefix, 'lib')]
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(unix_libname(libzmq_name))
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 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(unix_libname(libzmq_name))
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(unix_libname(libzmq_name))
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':
info("%r" % settings)
settings['runtime_library_dirs'] += [
os.path.abspath(x) for x in settings['library_dirs']
]
return settings
_libzmq_settings = {}
def libzmq_settings(debug=False, libzmq_name='libzmq', zmq_prefix=None):
"""Return libzmq settings"""
global _libzmq_settings
try:
return _libzmq_settings[(debug, libzmq_name, zmq_prefix)]
except KeyError:
settings = get_zmq_config()
if settings:
return settings
if any(chain(glob(pjoin(p, 'libzmq.*')) for p in get_zmq_library_path())):
settings = bundled_settings(debug)
else:
settings = settings_from_prefix(zmq_prefix, bundle_libzmq_dylib=False, libzmq_name=libzmq_name)
_libzmq_settings[(debug, libzmq_name, zmq_prefix)] = settings
return settings