tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

headless.py (5039B)


      1 #!/usr/bin/env python3
      2 
      3 # This Source Code Form is subject to the terms of the Mozilla Public
      4 # License, v. 2.0. If a copy of the MPL was not distributed with this
      5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
      6 
      7 # Build and run wrench with off-screen software rendering (OSMesa/LLVMpipe)
      8 # for platform-independent results. This is good for running reference tests.
      9 #
     10 # Usage: headless.py ARGS
     11 #
     12 # Pass ARGS through to wrench, after '--headless' and '--no-scissor'.
     13 #
     14 # Environment variables:
     15 #
     16 # WRENCH_HEADLESS_TARGET: If set, don't rebuild wrench. Instead, the value should
     17 #     be the path to an already-built cargo 'target' directory. This is useful
     18 #     for running a cross-compiled wrench.
     19 #
     20 # CARGOFLAGS: Extra flags to be passed to 'cargo build'. Split on whitespace.
     21 #
     22 # OPTIMIZED: This script uses the release build by default, but if this variable
     23 #     is set to '0' or 'false', the script uses the debug build.
     24 #
     25 # DEBUGGER: If set, run wrench under a debugger. Permitted values are 'rr' (run
     26 #     under 'rr record'), or 'gdb', 'rust-gdb', or 'cgdb' (run under the given
     27 #     debugger, and arrange to supply ARGS to the wrench debuggee, not the
     28 #     debugger)
     29 
     30 from __future__ import print_function
     31 import contextlib
     32 import os
     33 import subprocess
     34 import sys
     35 from os import path
     36 from glob import glob
     37 
     38 
     39 @contextlib.contextmanager
     40 def cd(new_path):
     41    """Context manager for changing the current working directory"""
     42    previous_path = os.getcwd()
     43    try:
     44        os.chdir(new_path)
     45        yield
     46    finally:
     47        os.chdir(previous_path)
     48 
     49 
     50 def find_dep_path_newest(package, bin_path):
     51    deps_path = path.join(path.split(bin_path)[0], "build")
     52    with cd(deps_path):
     53        candidates = glob(package + '-*')
     54    candidates = (path.join(deps_path, c) for c in candidates)
     55    """ For some reason cargo can create an extra osmesa-src without libs """
     56    candidates = (c for c in candidates if path.exists(path.join(c, 'out')))
     57    candidate_times = sorted(((path.getmtime(c), c) for c in candidates), reverse=True)
     58    if len(candidate_times) > 0:
     59        return candidate_times[0][1]
     60    return None
     61 
     62 
     63 def is_windows():
     64    """ Detect windows, mingw, cygwin """
     65    return sys.platform == 'win32' or sys.platform == 'msys' or sys.platform == 'cygwin'
     66 
     67 
     68 def is_macos():
     69    return sys.platform == 'darwin'
     70 
     71 
     72 def is_linux():
     73    return sys.platform.startswith('linux')
     74 
     75 
     76 def debugger():
     77    if "DEBUGGER" in os.environ:
     78        return os.environ["DEBUGGER"]
     79    return None
     80 
     81 
     82 def use_gdb():
     83    return debugger() in ['gdb', 'cgdb', 'rust-gdb']
     84 
     85 
     86 def use_rr():
     87    return debugger() == 'rr'
     88 
     89 
     90 def optimized_build():
     91    if "OPTIMIZED" in os.environ:
     92        opt = os.environ["OPTIMIZED"]
     93        return opt not in ["0", "false"]
     94    return True
     95 
     96 
     97 def set_osmesa_env(bin_path):
     98    """Set proper LD_LIBRARY_PATH and DRIVE for software rendering on Linux and OSX"""
     99    base = find_dep_path_newest('osmesa-src', bin_path)
    100    osmesa_path = path.join(base, "out", "mesa", "src", "gallium", "targets", "osmesa")
    101    os.environ["GALLIUM_DRIVER"] = "llvmpipe"
    102    if is_linux():
    103        print(osmesa_path)
    104        os.environ["LD_LIBRARY_PATH"] = osmesa_path
    105    elif is_macos():
    106        osmesa_path = path.join(base, "out", "mesa", "src", "gallium", "targets", "osmesa")
    107        glapi_path = path.join(base, "out", "mesa", "src", "mapi", "shared-glapi")
    108        os.environ["DYLD_LIBRARY_PATH"] = osmesa_path + ":" + glapi_path
    109 
    110 
    111 extra_flags = os.getenv('CARGOFLAGS', None)
    112 extra_flags = extra_flags.split(' ') if extra_flags else []
    113 
    114 wrench_headless_target = os.getenv('WRENCH_HEADLESS_TARGET', None)
    115 
    116 if wrench_headless_target:
    117    target_folder = wrench_headless_target
    118 else:
    119    target_folder = '../target/'
    120 
    121 if optimized_build():
    122    target_folder += 'release/'
    123 else:
    124    target_folder += 'debug/'
    125 
    126 # For CI purposes, don't build if WRENCH_HEADLESS_TARGET is set.
    127 # This environment variable is used to point to the location of a cross-compiled
    128 # wrench for the CI on some platforms.
    129 if not wrench_headless_target:
    130    build_cmd = ['cargo', 'build'] + extra_flags + ['--verbose', '--features', 'headless']
    131    if optimized_build():
    132        build_cmd += ['--release']
    133    subprocess.check_call(build_cmd)
    134 
    135 dbg_cmd = []
    136 if use_rr():
    137    dbg_cmd = ['rr', 'record']
    138 elif use_gdb():
    139    dbg_cmd = [debugger(), '--args']
    140 elif debugger():
    141    print("Unknown debugger: " + debugger())
    142    sys.exit(1)
    143 
    144 set_osmesa_env(target_folder)
    145 # TODO(gw): We have an occasional accuracy issue or bug (could be WR or OSMesa)
    146 #           where the output of a previous test that uses intermediate targets can
    147 #           cause 1.0 / 255.0 pixel differences in a subsequent test. For now, we
    148 #           run tests with no-scissor mode, which ensures a complete target clear
    149 #           between test runs. But we should investigate this further...
    150 cmd = dbg_cmd + [target_folder + 'wrench', '--no-scissor', '--headless'] + sys.argv[1:]
    151 print('Running: `' + ' '.join(cmd) + '`')
    152 subprocess.check_call(cmd, stderr=subprocess.STDOUT)