diff options
author | Florian Bruhin <me@the-compiler.org> | 2020-11-25 09:05:27 +0100 |
---|---|---|
committer | Florian Bruhin <me@the-compiler.org> | 2020-11-25 09:25:23 +0100 |
commit | ba152cbe4ab3c97110a21df02ee858dcc8c8f14b (patch) | |
tree | d49c267d51210a273767e751460a713e06f4aa66 /scripts/mkvenv.py | |
parent | b3feb9ece2ede28ee9a5e2af4226c5893e0b11ab (diff) | |
download | qutebrowser-ba152cbe4ab3c97110a21df02ee858dcc8c8f14b.tar.gz qutebrowser-ba152cbe4ab3c97110a21df02ee858dcc8c8f14b.zip |
scripts: Add libxcb-util workaround to mkvenv.py
Closes #5905
Diffstat (limited to 'scripts/mkvenv.py')
-rw-r--r-- | scripts/mkvenv.py | 90 |
1 files changed, 86 insertions, 4 deletions
diff --git a/scripts/mkvenv.py b/scripts/mkvenv.py index f582e23b0..19a20b00b 100644 --- a/scripts/mkvenv.py +++ b/scripts/mkvenv.py @@ -29,7 +29,7 @@ import os.path import shutil import venv import subprocess -from typing import List, Optional, Tuple +from typing import List, Optional, Tuple, Dict sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir)) from scripts import utils, link_pyqt @@ -93,13 +93,22 @@ def pyqt_versions() -> List[str]: return versions + ['auto'] -def run_venv(venv_dir: pathlib.Path, executable, *args: str) -> None: +def run_venv( + venv_dir: pathlib.Path, + executable, + *args: str, + capture_output=False, +) -> subprocess.CompletedProcess: """Run the given command inside the virtualenv.""" subdir = 'Scripts' if os.name == 'nt' else 'bin' try: - subprocess.run([str(venv_dir / subdir / executable)] + - [str(arg) for arg in args], check=True) + return subprocess.run( + [str(venv_dir / subdir / executable)] + [str(arg) for arg in args], + check=True, + universal_newlines=capture_output, + stdout=subprocess.PIPE if capture_output else None, + ) except subprocess.CalledProcessError as e: utils.print_error("Subprocess failed, exiting") sys.exit(e.returncode) @@ -202,6 +211,77 @@ def install_pyqt_wheels(venv_dir: pathlib.Path, pip_install(venv_dir, *wheels) +def apply_xcb_util_workaround( + venv_dir: pathlib.Path, + pyqt_type: str, + pyqt_version: str, +) -> None: + """If needed (Debian Stable), symlink libxcb-util.so.0 -> .1. + + WORKAROUND for https://bugreports.qt.io/browse/QTBUG-88688 + """ + utils.print_title("Running xcb-util workaround") + + if not sys.platform.startswith('linux'): + print("Workaround not needed: Not on Linux.") + return + if pyqt_type != 'binary': + print("Workaround not needed: Not installing from PyQt binaries.") + return + if pyqt_version not in ['auto', '5.15']: + print("Workaround not needed: Not installing Qt 5.15.") + return + + libs = _find_libs() + if 'libxcb-util.so.1' in libs: + print("Workaround not needed: libxcb-util.so.1 found.") + return + + try: + libxcb_util_path = pathlib.Path(libs['libxcb-util.so.0']) + except KeyError: + utils.print_col('Workaround failed: libxcb-util.so.0 not found.', 'red') + return + + code = [ + 'from PyQt5.QtCore import QLibraryInfo', + 'print(QLibraryInfo.location(QLibraryInfo.LibrariesPath))', + ] + proc = run_venv(venv_dir, 'python', '-c', '; '.join(code), capture_output=True) + venv_lib_path = pathlib.Path(proc.stdout.strip()) + + link_path = venv_lib_path / libxcb_util_path.with_suffix('.1').name + + # This gives us a nicer path to print, and also conveniently makes sure we + # didn't accidentally end up with a path outside the venv. + rel_link_path = venv_dir / link_path.relative_to(venv_dir.resolve()) + utils.print_col(f'$ ln -s {libxcb_util_path} {rel_link_path}', 'blue') + + link_path.symlink_to(libxcb_util_path) + + +def _find_libs() -> Dict[str, str]: + """Find all system-wide .so libraries.""" + all_libs: Dict[str, str] = {} + ldconfig_proc = subprocess.run( + ['ldconfig', '-p'], + check=True, + stdout=subprocess.PIPE, + encoding=sys.getfilesystemencoding(), + ) + for line in ldconfig_proc.stdout.splitlines(): + if ' => ' not in line: + continue + line = line.strip() + name, path = line.split(' => ') + name = name.split(' (')[0] + if name in all_libs: + raise ValueError(f'Found duplicate {name} ({all_libs[name]}; {path})') + all_libs[name] = path + + return all_libs + + def install_requirements(venv_dir: pathlib.Path) -> None: """Install qutebrowser's requirement.txt.""" utils.print_title("Installing other qutebrowser dependencies") @@ -275,6 +355,8 @@ def main() -> None: else: raise AssertionError + apply_xcb_util_workaround(venv_dir, args.pyqt_type, args.pyqt_version) + install_requirements(venv_dir) install_qutebrowser(venv_dir) if args.dev: |