| Differences between
and this patch
- a/Tools/ChangeLog +24 lines
Lines 1-3 a/Tools/ChangeLog_sec1
1
2020-12-03  Angelos Oikonomopoulos  <angelos@igalia.com>
2
3
        [JSC] Bundle non-native libs in run-jsc-stress-tests
4
        https://bugs.webkit.org/show_bug.cgi?id=219485
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        run-jsc-stress-tests already tries to bundle library dependencies
9
        (on linux) when using the --remote functionality; this ensures
10
        that we don't need to depend on the remote environment exactly
11
        matching the build environment. However, this breaks when
12
        cross-building; run-jsc-stress-tests uses ldd, which relies on
13
        code execution to get the shared object paths.
14
15
        This patch extends generate-bundle to be able to handle the output
16
        from a cross ldd (specifically, xldd from crosstool-NG) and
17
        changes run-jsc-stress-tests to use generate-bundle for bundling
18
        the libraries for the remotes.
19
20
        * Scripts/generate-bundle:
21
        * Scripts/run-javascriptcore-tests:
22
        (runJSCStressTests):
23
        * Scripts/run-jsc-stress-tests:
24
1
2020-11-20  Frederic Wang  <fwang@igalia.com>
25
2020-11-20  Frederic Wang  <fwang@igalia.com>
2
26
3
        [GTK] Migrate WebKitTestServer to libsoup 2.48 API
27
        [GTK] Migrate WebKitTestServer to libsoup 2.48 API
- a/Tools/Scripts/generate-bundle -17 / +78 lines
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
- a/Tools/Scripts/run-javascriptcore-tests +7 lines
Lines 106-111 my $createTarball = 0; a/Tools/Scripts/run-javascriptcore-tests_sec1
106
my $remoteHost = 0;
106
my $remoteHost = 0;
107
my $model = 0;
107
my $model = 0;
108
my $archs = undef;
108
my $archs = undef;
109
my $ldd = undef;
109
my $version;
110
my $version;
110
my $versionName;
111
my $versionName;
111
my $sdk;
112
my $sdk;
Lines 234-239 my $usage = <<EOF; a/Tools/Scripts/run-javascriptcore-tests_sec2
234
Usage: $programName [options] [options to pass to build system]
235
Usage: $programName [options] [options to pass to build system]
235
  --help                        Show this help message
236
  --help                        Show this help message
236
  --architecture                Attempt to override the native architecture of a machine.
237
  --architecture                Attempt to override the native architecture of a machine.
238
  --ldd                         Use alternate ldd
237
  --root=                       Path to pre-built root containing jsc
239
  --root=                       Path to pre-built root containing jsc
238
  --[no-]ftl-jit                Turn the FTL JIT on or off
240
  --[no-]ftl-jit                Turn the FTL JIT on or off
239
  --[no-]build                  Check (or don't check) to see if the jsc build is up-to-date (default: $buildJSCDefault)
241
  --[no-]build                  Check (or don't check) to see if the jsc build is up-to-date (default: $buildJSCDefault)
Lines 331-336 GetOptions( a/Tools/Scripts/run-javascriptcore-tests_sec3
331
    'remote=s' => \$remoteHost,
333
    'remote=s' => \$remoteHost,
332
    'model=s' => \$model,
334
    'model=s' => \$model,
333
    'architecture=s' => \$archs,
335
    'architecture=s' => \$archs,
336
    'ldd=s' => \$ldd,
334
    'version=s' => \$version,
337
    'version=s' => \$version,
335
    'version-name=s' => \$versionName,
338
    'version-name=s' => \$versionName,
336
    'sdk=s' => \$sdk,
339
    'sdk=s' => \$sdk,
Lines 761-766 sub runJSCStressTests a/Tools/Scripts/run-javascriptcore-tests_sec4
761
        push(@jscStressDriverCmd, $archs);
764
        push(@jscStressDriverCmd, $archs);
762
    }
765
    }
763
766
767
    if (defined($ldd)) {
768
        push(@jscStressDriverCmd, "--ldd");
769
        push(@jscStressDriverCmd, $ldd);
770
    }
764
    push(@jscStressDriverCmd, @testList);
771
    push(@jscStressDriverCmd, @testList);
765
772
766
    if (isWindows() && !isCygwin()) {
773
    if (isWindows() && !isCygwin()) {
- a/Tools/Scripts/run-jsc-stress-tests -10 / +36 lines
Lines 132-137 $mode = "full" a/Tools/Scripts/run-jsc-stress-tests_sec1
132
$buildType = "release"
132
$buildType = "release"
133
$forceCollectContinuously = false
133
$forceCollectContinuously = false
134
$reportExecutionTime = false
134
$reportExecutionTime = false
135
$ldd = 'ldd'
135
136
136
def usage
137
def usage
137
    puts "run-jsc-stress-tests -j <shell path> <collections path> [<collections path> ...]"
138
    puts "run-jsc-stress-tests -j <shell path> <collections path> [<collections path> ...]"
Lines 151-156 def usage a/Tools/Scripts/run-jsc-stress-tests_sec2
151
    puts "--arch                      Specify architecture instead of determining from JavaScriptCore build."
152
    puts "--arch                      Specify architecture instead of determining from JavaScriptCore build."
152
    puts "--force-architecture        Override the architecture to run tests with."
153
    puts "--force-architecture        Override the architecture to run tests with."
153
    puts "                            e.g. x86, x86_64, arm."
154
    puts "                            e.g. x86, x86_64, arm."
155
    puts "--ldd                       Use alternate ldd"
154
    puts "--os                        Specify os instead of determining from JavaScriptCore build."
156
    puts "--os                        Specify os instead of determining from JavaScriptCore build."
155
    puts "                            e.g. darwin, linux & windows."
157
    puts "                            e.g. darwin, linux & windows."
156
    puts "--shell-runner              Uses the shell-based test runner instead of the default make-based runner."
158
    puts "--shell-runner              Uses the shell-based test runner instead of the default make-based runner."
Lines 192-197 GetoptLong.new(['--help', '-h', GetoptLong::NO_ARGUMENT], a/Tools/Scripts/run-jsc-stress-tests_sec3
192
               ['--force-vm-copy', GetoptLong::NO_ARGUMENT],
194
               ['--force-vm-copy', GetoptLong::NO_ARGUMENT],
193
               ['--arch', GetoptLong::REQUIRED_ARGUMENT],
195
               ['--arch', GetoptLong::REQUIRED_ARGUMENT],
194
               ['--force-architecture', GetoptLong::REQUIRED_ARGUMENT],
196
               ['--force-architecture', GetoptLong::REQUIRED_ARGUMENT],
197
               ['--ldd', GetoptLong::REQUIRED_ARGUMENT],
195
               ['--os', GetoptLong::REQUIRED_ARGUMENT],
198
               ['--os', GetoptLong::REQUIRED_ARGUMENT],
196
               ['--shell-runner', GetoptLong::NO_ARGUMENT],
199
               ['--shell-runner', GetoptLong::NO_ARGUMENT],
197
               ['--make-runner', GetoptLong::NO_ARGUMENT],
200
               ['--make-runner', GetoptLong::NO_ARGUMENT],
Lines 265-270 GetoptLong.new(['--help', '-h', GetoptLong::NO_ARGUMENT], a/Tools/Scripts/run-jsc-stress-tests_sec4
265
    when '--force-architecture'
268
    when '--force-architecture'
266
        $architecture = arg unless $architecture
269
        $architecture = arg unless $architecture
267
        $forceArchitecture = arg
270
        $forceArchitecture = arg
271
    when '--ldd'
272
        $ldd = arg
268
    when '--os'
273
    when '--os'
269
        $hostOS = arg
274
        $hostOS = arg
270
    when '--model'
275
    when '--model'
Lines 1858-1864 def prepareBundle a/Tools/Scripts/run-jsc-stress-tests_sec5
1858
            if $copyVM
1863
            if $copyVM
1859
                FileUtils.cp_r source, destination
1864
                FileUtils.cp_r source, destination
1860
            else
1865
            else
1861
                begin 
1866
                begin
1862
                    FileUtils.ln_s source, destination
1867
                    FileUtils.ln_s source, destination
1863
                rescue Exception
1868
                rescue Exception
1864
                    $stderr.puts "Warning: unable to create soft link, trying to copy."
1869
                    $stderr.puts "Warning: unable to create soft link, trying to copy."
Lines 1867-1881 def prepareBundle a/Tools/Scripts/run-jsc-stress-tests_sec6
1867
            end
1872
            end
1868
1873
1869
            if $remote and $hostOS == "linux"
1874
            if $remote and $hostOS == "linux"
1870
                begin
1875
                generate_bundle = (Pathname.new(THIS_SCRIPT_PATH).dirname + 'generate-bundle').realpath
1871
                    dependencies = `ldd #{source}`
1876
                Dir.mktmpdir {
1872
                    dependencies.split(/\n/).each {
1877
                    | tmpdir |
1873
                        | dependency |
1878
                    # Generate bundle in a temporary directory so that
1874
                        FileUtils.cp_r $&, $jscPath.dirname if dependency =~ /#{WEBKIT_PATH}[^ ]*/
1879
                    # we can safely pick it up regardless of its name
1875
                    }
1880
                    # (it's the only zip file there).
1876
                rescue
1881
                    cmdline = [
1877
                    $stderr.puts "Warning: unable to determine or copy library dependnecies of JSC."
1882
                        generate_bundle.to_s,
1878
                end
1883
                        "--platform=gtk",
1884
                        "--bundle=jsc",
1885
                        "--syslibs=bundle-all",
1886
                        "--ldd=#{$ldd}",
1887
                        "--no-strip",
1888
                        "--compression=tar.xz",
1889
                        ($buildType == "release") ? "--release" : "--debug",
1890
                        "--destination=#{tmpdir}"
1891
                    ]
1892
                    mysys(cmdline)
1893
                    archives = Dir.glob("#{tmpdir}/*.tar.xz")
1894
                    if archives.size != 1
1895
                        raise "Expected exactly one entry in tmpdir, not #{archives}"
1896
                    end
1897
                    # Note: we overwrite 'jsc'. This obviously conflicts with
1898
                    # !copyVM but, then gain, so does $remote.
1899
                    mysys(["tar",
1900
                           "-C",
1901
                           $jscPath.dirname.to_s,
1902
                           "-xf",
1903
                           archives[0]])
1904
                }
1879
            end
1905
            end
1880
        }
1906
        }
1881
    end
1907
    end

Return to Bug 219485