Read about our upcoming Code of Conduct on this issue

Commit 444e0913 authored by Matti Picus's avatar Matti Picus
Browse files

add a --make-portable option to package.py

parent 8f3a6314492e
#!/usr/bin/env python
bundle = ['sqlite3', 'ssl', 'crypto', 'ffi', 'expat', 'tcl', 'tk', 'gdbm', 'lzma', 'ncursesw', 'panelw', 'tinfow']
from os import chdir, mkdir, symlink
from os.path import dirname, relpath, join, exists, basename, realpath
from shutil import copy2
import sys
from glob import glob
from subprocess import check_output, check_call
def get_deps(binary):
deps = {}
output = check_output(['ldd', binary])
for line in output.splitlines():
if '=>' not in line:
continue
line = line.strip()
needed, path = line.split(' => ')
if path == 'not found':
print('Broken dependency in ' + binary)
path = path.split(' ')[0]
path = realpath(path)
if not path:
continue
if needed[3:].split('.', 1)[0] not in bundle:
continue
deps[needed] = path
deps.update(get_deps(path))
return deps
def gather_deps(binaries):
deps = {}
for binary in binaries:
deps.update(get_deps(binary))
return deps
def copy_deps(deps):
copied = {}
for needed, path in deps.items():
bname = basename(path)
copy2(path, 'lib/' + bname)
copied[path] = 'lib/' + bname
if not exists('lib/' + needed):
symlink(bname, 'lib/' + needed)
return copied
def rpath_binaries(binaries):
rpaths = {}
for binary in binaries:
rpath = join('$ORIGIN', relpath('lib', dirname(binary)))
check_call(['patchelf', '--set-rpath', rpath, binary])
rpaths[binary] = rpath
return rpaths
def make_portable():
binaries = glob('bin/libpypy*.so')
if not binaries:
raise ValueError('Could not find bin/libpypy*.so')
binaries.extend(glob('lib_pypy/*_cffi.pypy*.so'))
binaries.extend(glob('lib_pypy/_pypy_openssl*.so'))
binaries.extend(glob('lib_pypy/_tkinter/*_cffi.pypy*.so'))
deps = gather_deps(binaries)
copied = copy_deps(deps)
for path, item in copied.items():
print('Copied {0} to {1}'.format(path, item))
binaries.extend(copied.values())
rpaths = rpath_binaries(binaries)
for binary, rpath in rpaths.items():
print('Set RPATH of {0} to {1}'.format(binary, rpath))
return deps
if __name__ == '__main__':
try:
chdir(sys.argv[1])
except:
print('Call as %s <path/to/pypy/topdir' % sys.argv[0])
exit(-1)
try:
mkdir('lib')
except OSError:
pass
make_portable()
......@@ -235,7 +235,11 @@ def create_package(basedir, options, _fake=False):
else:
archive = bindir.join(target)
smartstrip(archive, keep_debug=options.keep_debug)
#
# make the package portable by adding rpath=$ORIGIN/..lib,
# bundling dependencies
if options.make_portable:
make_portable()
if USE_ZIPFILE_MODULE:
import zipfile
archive = str(builddir.join(name + '.zip'))
......@@ -319,6 +323,12 @@ def package(*args, **kwds):
default=(sys.platform == 'darwin'),
help='whether to embed dependencies in CFFI modules '
'(default on OS X)')
parser.add_argument('--make-portable', '--no-make-portable',
dest='make_portable',
action=NegateAction,
default=(platform.linux_distribution() in ('CentOS',)),
help='whether to make the package portable by shipping '
'dependent shared objects and mangling RPATH')
options = parser.parse_args(args)
if os.environ.has_key("PYPY_PACKAGE_NOKEEPDEBUG"):
......@@ -329,6 +339,10 @@ def package(*args, **kwds):
options.embed_dependencies = True
elif os.environ.has_key("PYPY_NO_EMBED_DEPENDENCIES"):
options.embed_dependencies = False
if os.environ.has_key("PYPY_MAKE_PORTABLE"):
options.embed_dependencies = True
elif os.environ.has_key("PYPY_NO_MAKE_PORTABLE"):
options.embed_dependencies = False
if not options.builddir:
# The import actually creates the udir directory
from rpython.tool.udir import udir
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment