|
Lines 29-37
import hashlib
a/Tools/Scripts/generate-bundle_sec1
|
| 29 |
import json |
29 |
import json |
| 30 |
import logging |
30 |
import logging |
| 31 |
import os |
31 |
import os |
|
|
32 |
from pathlib import PurePath |
| 32 |
import shutil |
33 |
import shutil |
| 33 |
import subprocess |
34 |
import subprocess |
| 34 |
import sys |
35 |
import sys |
|
|
36 |
import tarfile |
| 35 |
import tempfile |
37 |
import tempfile |
| 36 |
import zipfile |
38 |
import zipfile |
| 37 |
|
39 |
|
|
Lines 86-94
fi
a/Tools/Scripts/generate-bundle_sec2
|
| 86 |
_log = logging.getLogger(__name__) |
88 |
_log = logging.getLogger(__name__) |
| 87 |
LOG_MESSAGE = 25 |
89 |
LOG_MESSAGE = 25 |
| 88 |
|
90 |
|
|
|
91 |
class Archiver(object): |
| 92 |
|
| 93 |
def __enter__(self): |
| 94 |
return self |
| 95 |
|
| 96 |
def __exit__(self, type, v, tb): |
| 97 |
return self._archive.close() |
| 98 |
|
| 99 |
class TarArchiver(Archiver): |
| 100 |
|
| 101 |
def __init__(self, path): |
| 102 |
self._archive = tarfile.open(path, 'w:xz') |
| 103 |
|
| 104 |
def add_file(self, system_path, zip_path): |
| 105 |
return self._archive.add(system_path, zip_path) |
| 106 |
|
| 107 |
class ZipArchiver(Archiver): |
| 108 |
|
| 109 |
def __init__(self, path): |
| 110 |
self._archive = zipfile.ZipFile(path, 'w', compression=zipfile.ZIP_DEFLATED) |
| 111 |
|
| 112 |
def add_file(self, system_path, zip_path): |
| 113 |
if os.path.islink(system_path): |
| 114 |
symlink_zip_info = zipfile.ZipInfo(zip_path) |
| 115 |
symlink_zip_info.create_system = 3 # Unix (for symlink support) |
| 116 |
symlink_zip_info.external_attr = 0xA1ED0000 # Zip softlink magic number |
| 117 |
return self._archive.writestr(symlink_zip_info, os.readlink(system_path)) |
| 118 |
return self._archive.write(system_path, zip_path) |
| 119 |
|
| 89 |
class BundleCreator(object): |
120 |
class BundleCreator(object): |
| 90 |
|
121 |
|
| 91 |
def __init__(self, configuration, platform, bundle_type, syslibs, should_strip_objects, compression_type, destination = None, revision = None, builder_name = None): |
122 |
def __init__(self, configuration, platform, bundle_type, syslibs, ldd, should_strip_objects, compression_type, destination = None, revision = None, builder_name = None): |
| 92 |
self._configuration = configuration |
123 |
self._configuration = configuration |
| 93 |
self._platform = platform.lower() |
124 |
self._platform = platform.lower() |
| 94 |
self._revision = revision |
125 |
self._revision = revision |
|
Lines 96-101
class BundleCreator(object):
a/Tools/Scripts/generate-bundle_sec3
|
| 96 |
self._bundle_type = bundle_type |
127 |
self._bundle_type = bundle_type |
| 97 |
self._buildername = builder_name |
128 |
self._buildername = builder_name |
| 98 |
self._syslibs = syslibs |
129 |
self._syslibs = syslibs |
|
|
130 |
self._ldd = ldd |
| 99 |
self._should_strip_objects = should_strip_objects |
131 |
self._should_strip_objects = should_strip_objects |
| 100 |
self._compression_type = compression_type |
132 |
self._compression_type = compression_type |
| 101 |
self._tmpdir = None |
133 |
self._tmpdir = None |
|
Lines 125-135
class BundleCreator(object):
a/Tools/Scripts/generate-bundle_sec4
|
| 125 |
return command_process.returncode, stdout, stderr |
157 |
return command_process.returncode, stdout, stderr |
| 126 |
|
158 |
|
| 127 |
|
159 |
|
| 128 |
def _ldd_get_libs_and_interpreter(self, object): |
160 |
def _get_interpreter_objname(self, object): |
|
|
161 |
# Note: we use patchelf to get the object name (not the path!) |
| 162 |
# of the interpreter because this works regardless of the |
| 163 |
# architecture of the ELF file. |
| 164 |
retcode, stdout, stderr = self._run_cmd_and_get_output(['patchelf', '--print-interpreter', object]) |
| 165 |
if retcode != 0: |
| 166 |
_log.debug("patchelf stdout:\n%s\nPatchelf stderr:\n%s" % (stdout, stderr)) |
| 167 |
if 'cannot find section' in stdout: |
| 168 |
# This is fine; we only expect an interpreter in the main binary. |
| 169 |
return None |
| 170 |
raise RuntimeError('The patchelf command returned non-zero status for object %s' % object) |
| 171 |
interpreter_path = PurePath(stdout.strip()) |
| 172 |
return interpreter_path.name |
| 173 |
|
| 174 |
def _get_libs_and_interpreter(self, object): |
| 129 |
interpreter = None |
175 |
interpreter = None |
| 130 |
retcode, stdout, stderr = self._run_cmd_and_get_output(['ldd', object]) |
176 |
retcode, stdout, stderr = self._run_cmd_and_get_output([self._ldd, object]) |
|
|
177 |
_log.debug("ldd stdout:\n%s" % stdout) |
| 131 |
if retcode != 0: |
178 |
if retcode != 0: |
| 132 |
raise RuntimeError('The ldd command returned non-zero status for object %s' % object) |
179 |
raise RuntimeError('The %s command returned non-zero status for object %s' % (self._ldd, object)) |
| 133 |
libs = [] |
180 |
libs = [] |
| 134 |
for line in stdout.splitlines(): |
181 |
for line in stdout.splitlines(): |
| 135 |
line = line.strip() |
182 |
line = line.strip() |
|
Lines 144-154
class BundleCreator(object):
a/Tools/Scripts/generate-bundle_sec5
|
| 144 |
line = line.split(' ')[0].strip() |
191 |
line = line.split(' ')[0].strip() |
| 145 |
if os.path.isfile(line): |
192 |
if os.path.isfile(line): |
| 146 |
interpreter = line |
193 |
interpreter = line |
|
|
194 |
if interpreter is None: |
| 195 |
# This is the case for non-native binaries. For those, we |
| 196 |
# can use a cross-ldd (xldd), but then the interpreter |
| 197 |
# looks like any other shared object in the output of |
| 198 |
# ldd. Try to identify it by looking at the object name |
| 199 |
# from the interpreter string. |
| 200 |
interpreter_objname = self._get_interpreter_objname(object) |
| 201 |
for lib in libs: |
| 202 |
if PurePath(lib).name == interpreter_objname: |
| 203 |
interpreter = lib |
| 204 |
break |
| 205 |
# If we found an interpreter, remove it from the libs. |
| 206 |
libs = [lib for lib in libs if lib != interpreter] |
| 147 |
return libs, interpreter |
207 |
return libs, interpreter |
| 148 |
|
208 |
|
| 149 |
|
209 |
|
| 150 |
def _ldd_recursive_get_libs_and_interpreter(self, object, already_checked_libs = []): |
210 |
def _ldd_recursive_get_libs_and_interpreter(self, object, already_checked_libs = []): |
| 151 |
libs, interpreter = self._ldd_get_libs_and_interpreter(object) |
211 |
libs, interpreter = self._get_libs_and_interpreter(object) |
| 152 |
if libs: |
212 |
if libs: |
| 153 |
for lib in libs: |
213 |
for lib in libs: |
| 154 |
if lib in already_checked_libs: |
214 |
if lib in already_checked_libs: |
|
Lines 296-305
class BundleCreator(object):
a/Tools/Scripts/generate-bundle_sec6
|
| 296 |
for bundle_binary in self._bundle_binaries: |
356 |
for bundle_binary in self._bundle_binaries: |
| 297 |
self._create_bundle(bundle_binary) |
357 |
self._create_bundle(bundle_binary) |
| 298 |
self._generate_readme() |
358 |
self._generate_readme() |
|
|
359 |
|
| 299 |
if self._compression_type == 'zip': |
360 |
if self._compression_type == 'zip': |
| 300 |
self._create_zip() |
361 |
archiver = ZipArchiver(self._bundle_file_path) |
|
|
362 |
elif self._compression_type == 'tar.xz': |
| 363 |
archiver = TarArchiver(self._bundle_file_path) |
| 301 |
else: |
364 |
else: |
| 302 |
raise NotImplementedError('Support for compression type %s not implemented' % self._compression_type) |
365 |
raise NotImplementedError('Support for compression type %s not implemented' % self._compression_type) |
|
|
366 |
self._create_archive(archiver) |
| 303 |
self._remove_tempdir() |
367 |
self._remove_tempdir() |
| 304 |
if not os.path.isfile(self._bundle_file_path): |
368 |
if not os.path.isfile(self._bundle_file_path): |
| 305 |
raise RuntimeError('Unable to create the file %s' % self._bundle_file_path) |
369 |
raise RuntimeError('Unable to create the file %s' % self._bundle_file_path) |
|
Lines 332-351
class BundleCreator(object):
a/Tools/Scripts/generate-bundle_sec7
|
| 332 |
return bundle_lib |
396 |
return bundle_lib |
| 333 |
|
397 |
|
| 334 |
|
398 |
|
| 335 |
def _create_zip(self): |
399 |
def _create_archive(self, archiver): |
| 336 |
_log.info('Create ZIP file') |
400 |
_log.info('Create archive') |
| 337 |
with zipfile.ZipFile(self._bundle_file_path, 'w', compression=zipfile.ZIP_DEFLATED) as zipHandle: |
401 |
with archiver: |
| 338 |
for dirname, subdirs, files in os.walk(self._tmpdir): |
402 |
for dirname, subdirs, files in os.walk(self._tmpdir): |
| 339 |
for filename in files: |
403 |
for filename in files: |
| 340 |
system_file_path = os.path.join(dirname, filename) |
404 |
system_file_path = os.path.join(dirname, filename) |
| 341 |
zip_file_path = system_file_path.replace(self._tmpdir, '', 1).lstrip('/') |
405 |
zip_file_path = system_file_path.replace(self._tmpdir, '', 1).lstrip('/') |
| 342 |
if os.path.islink(system_file_path): |
406 |
archiver.add_file(system_file_path, zip_file_path) |
| 343 |
symlink_zip_info = zipfile.ZipInfo(zip_file_path) |
|
|
| 344 |
symlink_zip_info.create_system = 3 # Unix (for symlink support) |
| 345 |
symlink_zip_info.external_attr = 0xA1ED0000 # Zip softlink magic number |
| 346 |
zipHandle.writestr(symlink_zip_info, os.readlink(system_file_path)) |
| 347 |
else: |
| 348 |
zipHandle.write(system_file_path, zip_file_path) |
| 349 |
|
407 |
|
| 350 |
|
408 |
|
| 351 |
def _get_system_package_name(self, object): |
409 |
def _get_system_package_name(self, object): |
|
Lines 456-461
class BundleCreator(object):
a/Tools/Scripts/generate-bundle_sec8
|
| 456 |
# and everything will be examined and bundled as we don't account for system packages in that case. |
514 |
# and everything will be examined and bundled as we don't account for system packages in that case. |
| 457 |
if not system_package: |
515 |
if not system_package: |
| 458 |
libraries, interpreter = self._ldd_recursive_get_libs_and_interpreter(object) |
516 |
libraries, interpreter = self._ldd_recursive_get_libs_and_interpreter(object) |
|
|
517 |
if interpreter is None: |
| 518 |
raise RuntimeError("Could not determine interpreter for binary %s" % object) |
| 459 |
if copied_interpreter is None: |
519 |
if copied_interpreter is None: |
| 460 |
if self._syslibs == 'bundle-all': |
520 |
if self._syslibs == 'bundle-all': |
| 461 |
self._copy_and_remove_rpath(interpreter, type='interpreter') |
521 |
self._copy_and_remove_rpath(interpreter, type='interpreter') |
|
Lines 616-621
def main():
a/Tools/Scripts/generate-bundle_sec9
|
| 616 |
parser.add_argument('--syslibs', dest='syslibs', choices=['bundle-all', 'generate-install-script'], default='generate-install-script', |
676 |
parser.add_argument('--syslibs', dest='syslibs', choices=['bundle-all', 'generate-install-script'], default='generate-install-script', |
| 617 |
help='If value is "bundle-all", the bundle will include _all_ the system libraries instead of a install-dependencies script.\n' |
677 |
help='If value is "bundle-all", the bundle will include _all_ the system libraries instead of a install-dependencies script.\n' |
| 618 |
'If value is "generate-install-script", the system libraries will not be bundled and a install-dependencies script will be generated for this distribution.') |
678 |
'If value is "generate-install-script", the system libraries will not be bundled and a install-dependencies script will be generated for this distribution.') |
|
|
679 |
parser.add_argument('--ldd', dest='ldd', default='ldd', help='Use alternative ldd (useful for non-native binaries') |
| 619 |
parser.add_argument('--compression', dest='compression', choices=['zip', 'tar.xz'], default='zip') |
680 |
parser.add_argument('--compression', dest='compression', choices=['zip', 'tar.xz'], default='zip') |
| 620 |
parser.add_argument('--destination', action='store', dest='destination', |
681 |
parser.add_argument('--destination', action='store', dest='destination', |
| 621 |
help='Optional path were to store the bundle') |
682 |
help='Optional path were to store the bundle') |
|
Lines 633-639
def main():
a/Tools/Scripts/generate-bundle_sec10
|
| 633 |
jhbuildutils.enter_jhbuild_environment_if_available(options.platform) |
694 |
jhbuildutils.enter_jhbuild_environment_if_available(options.platform) |
| 634 |
|
695 |
|
| 635 |
configure_logging(options.log_level) |
696 |
configure_logging(options.log_level) |
| 636 |
bundle_creator = BundleCreator(options.configuration, options.platform, options.bundle_binary, options.syslibs, |
697 |
bundle_creator = BundleCreator(options.configuration, options.platform, options.bundle_binary, options.syslibs, options.ldd, |
| 637 |
not options.no_strip, options.compression, options.destination, options.webkit_version, options.builder_name) |
698 |
not options.no_strip, options.compression, options.destination, options.webkit_version, options.builder_name) |
| 638 |
bundle_file_path = bundle_creator.create() |
699 |
bundle_file_path = bundle_creator.create() |
| 639 |
|
700 |
|