flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics --exclude benchmark Excluding the benchmark directory (due to protobuf generated files) Also removing some Python2 specific code
177 lines
5.5 KiB
Python
177 lines
5.5 KiB
Python
"""utilities for fetching build dependencies."""
|
|
|
|
#
|
|
# Copyright (C) PyZMQ Developers
|
|
# Distributed under the terms of the Modified BSD License.
|
|
#
|
|
# This bundling code is largely adapted from pyzmq-static's get.sh by
|
|
# Brandon Craig-Rhodes, which is itself BSD licensed.
|
|
#
|
|
# Adapted for use in pycapnp from pyzmq. See https://github.com/zeromq/pyzmq
|
|
# for original project.
|
|
|
|
|
|
import os
|
|
import shutil
|
|
import stat
|
|
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, info, warn
|
|
|
|
pjoin = os.path.join
|
|
|
|
#
|
|
# Constants
|
|
#
|
|
|
|
bundled_version = (0, 7, 4)
|
|
libcapnp_name = "capnproto-c++-%i.%i.%i.tar.gz" % (bundled_version)
|
|
libcapnp_url = "https://capnproto.org/" + libcapnp_name
|
|
|
|
HERE = os.path.dirname(__file__)
|
|
ROOT = os.path.dirname(HERE)
|
|
|
|
#
|
|
# Utilities
|
|
#
|
|
|
|
|
|
def untgz(archive):
|
|
"""Remove .tar.gz"""
|
|
return archive.replace('.tar.gz', '')
|
|
|
|
def localpath(*args):
|
|
"""construct an absolute path from a list relative to the root pycapnp 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
|
|
|
|
#
|
|
# libcapnp
|
|
#
|
|
|
|
def fetch_libcapnp(savedir, url=None):
|
|
"""download and extract libcapnp"""
|
|
is_preconfigured = False
|
|
if url is None:
|
|
url = libcapnp_url
|
|
is_preconfigured = True
|
|
dest = pjoin(savedir, 'capnproto-c++')
|
|
if os.path.exists(dest):
|
|
info("already have %s" % dest)
|
|
return
|
|
fname = fetch_archive(savedir, url, libcapnp_name)
|
|
tf = tarfile.open(fname)
|
|
with_version = pjoin(savedir, tf.firstmember.path)
|
|
tf.extractall(savedir)
|
|
tf.close()
|
|
# remove version suffix:
|
|
if is_preconfigured:
|
|
shutil.move(with_version, dest)
|
|
else:
|
|
cpp_dir = os.path.join(with_version, 'c++')
|
|
conf = Popen(['autoreconf', '-i'], cwd=cpp_dir)
|
|
returncode = conf.wait()
|
|
if returncode != 0:
|
|
raise RuntimeError('Autoreconf failed. Make sure autotools are installed on your system.')
|
|
shutil.move(cpp_dir, dest)
|
|
|
|
|
|
def stage_platform_hpp(capnproot):
|
|
"""stage platform.hpp into libcapnp sources
|
|
|
|
Tries ./configure first (except on Windows),
|
|
then falls back on included platform.hpp previously generated.
|
|
"""
|
|
|
|
platform_hpp = pjoin(capnproot, '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(capnproot, 'builds', 'msvc')
|
|
else:
|
|
info("attempting ./configure to generate platform.hpp")
|
|
|
|
p = Popen('./configure', cwd=capnproot, shell=True,
|
|
stdout=PIPE, stderr=PIPE,
|
|
)
|
|
_, e = p.communicate()
|
|
if p.returncode:
|
|
warn("failed to configure libcapnp:\n%s" % e)
|
|
if sys.platform == 'darwin':
|
|
platform_dir = pjoin(HERE, 'include_darwin')
|
|
elif sys.platform.startswith('freebsd'):
|
|
platform_dir = pjoin(HERE, 'include_freebsd')
|
|
elif sys.platform.startswith('linux-armv'):
|
|
platform_dir = pjoin(HERE, 'include_linux-armv')
|
|
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 copy_and_patch_libcapnp(capnp, libcapnp):
|
|
"""copy libcapnp 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 libcapnp into capnp for bdist
|
|
local = localpath('capnp', libcapnp)
|
|
if not capnp and not os.path.exists(local):
|
|
fatal("Please specify capnp prefix via `setup.py configure --capnp=/path/to/capnp` "
|
|
"or copy libcapnp into capnp/ manually prior to running bdist.")
|
|
try:
|
|
# resolve real file through symlinks
|
|
lib = os.path.realpath(pjoin(capnp, 'lib', libcapnp))
|
|
print ("copying %s -> %s" % (lib, local))
|
|
shutil.copy(lib, local)
|
|
except Exception:
|
|
if not os.path.exists(local):
|
|
fatal("Could not copy libcapnp into capnp/, which is necessary for bdist. "
|
|
"Please specify capnp prefix via `setup.py configure --capnp=/path/to/capnp` "
|
|
"or copy libcapnp into capnp/ manually.")
|
|
|
|
if sys.platform == 'darwin':
|
|
# chmod u+w on the lib,
|
|
# which can be user-read-only for some reason
|
|
mode = os.stat(local).st_mode
|
|
os.chmod(local, mode | stat.S_IWUSR)
|
|
# patch install_name on darwin, instead of using rpath
|
|
cmd = ['install_name_tool', '-id', '@loader_path/../%s' % libcapnp, local]
|
|
try:
|
|
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
|
|
except OSError:
|
|
fatal("install_name_tool not found, cannot patch libcapnp for bundling.")
|
|
_, err = p.communicate()
|
|
if p.returncode:
|
|
fatal("Could not patch bundled libcapnp install_name: %s" % err, p.returncode)
|