diff options
Diffstat (limited to 'scripts/dev/build_release.py')
-rwxr-xr-x | scripts/dev/build_release.py | 157 |
1 files changed, 101 insertions, 56 deletions
diff --git a/scripts/dev/build_release.py b/scripts/dev/build_release.py index 18658f920..3ac48ad55 100755 --- a/scripts/dev/build_release.py +++ b/scripts/dev/build_release.py @@ -48,6 +48,10 @@ from scripts import utils from scripts.dev import update_3rdparty, misc_checks +IS_MACOS = sys.platform == 'darwin' +IS_WINDOWS = os.name == 'nt' + + @dataclasses.dataclass class Artifact: @@ -134,43 +138,65 @@ def _smoke_test_run( return subprocess.run(argv, check=True, capture_output=True) -def smoke_test(executable: pathlib.Path, debug: bool) -> None: +def smoke_test(executable: pathlib.Path, debug: bool, qt6: bool) -> None: """Try starting the given qutebrowser executable.""" stdout_whitelist = [] stderr_whitelist = [ # PyInstaller debug output r'\[.*\] PyInstaller Bootloader .*', r'\[.*\] LOADER: .*', - - # https://github.com/qutebrowser/qutebrowser/issues/4919 - (r'objc\[.*\]: .* One of the two will be used\. ' - r'Which one is undefined\.'), - (r'QCoreApplication::applicationDirPath: Please instantiate the ' - r'QApplication object first'), - (r'\[.*:ERROR:mach_port_broker.mm\(48\)\] bootstrap_look_up ' - r'org\.chromium\.Chromium\.rohitfork\.1: Permission denied \(1100\)'), - (r'\[.*:ERROR:mach_port_broker.mm\(43\)\] bootstrap_look_up: ' - r'Unknown service name \(1102\)'), - - (r'[0-9:]* WARNING: The available OpenGL surface format was either not ' - r'version 3\.2 or higher or not a Core Profile\.'), - r'Chromium on macOS will fall back to software rendering in this case\.', - r'Hardware acceleration and features such as WebGL will not be available\.', - r'Unable to create basic Accelerated OpenGL renderer\.', - r'Core Image is now using the software OpenGL renderer\. This will be slow\.', - - # Windows N: - # https://github.com/microsoft/playwright/issues/2901 - (r'\[.*:ERROR:dxva_video_decode_accelerator_win.cc\(\d+\)\] ' - r'DXVAVDA fatal error: could not LoadLibrary: .*: The specified ' - r'module could not be found. \(0x7E\)'), - - # https://github.com/qutebrowser/qutebrowser/issues/3719 - '[0-9:]* ERROR: Load error: ERR_FILE_NOT_FOUND', - - # macOS 11 - (r'[0-9:]* WARNING: Failed to load libssl/libcrypto\.'), ] + if IS_MACOS: + stderr_whitelist.extend([ + # macOS on Qt 5.15 + # https://github.com/qutebrowser/qutebrowser/issues/4919 + (r'objc\[.*\]: .* One of the two will be used\. ' + r'Which one is undefined\.'), + (r'QCoreApplication::applicationDirPath: Please instantiate the ' + r'QApplication object first'), + (r'\[.*:ERROR:mach_port_broker.mm\(48\)\] bootstrap_look_up ' + r'org\.chromium\.Chromium\.rohitfork\.1: Permission denied \(1100\)'), + (r'\[.*:ERROR:mach_port_broker.mm\(43\)\] bootstrap_look_up: ' + r'Unknown service name \(1102\)'), + + # macOS on Qt 5.15 + (r'[0-9:]* WARNING: The available OpenGL surface format was either not ' + r'version 3\.2 or higher or not a Core Profile\.'), + r'Chromium on macOS will fall back to software rendering in this case\.', + r'Hardware acceleration and features such as WebGL will not be available\.', + r'Unable to create basic Accelerated OpenGL renderer\.', + r'Core Image is now using the software OpenGL renderer\. This will be slow\.', + + # https://github.com/qutebrowser/qutebrowser/issues/3719 + '[0-9:]* ERROR: Load error: ERR_FILE_NOT_FOUND', + + # macOS 11 + (r'[0-9:]* WARNING: Failed to load libssl/libcrypto\.'), + ]) + if qt6: + stderr_whitelist.extend([ + # FIXME:qt6 Qt 6.3 on macOS + r'[0-9:]* WARNING: Incompatible version of OpenSSL', + r'[0-9:]* WARNING: Qt WebEngine resources not found at .*', + (r'[0-9:]* WARNING: Installed Qt WebEngine locales directory not found at ' + r'location /qtwebengine_locales\. Trying application directory\.\.\.'), + + # https://github.com/pyinstaller/pyinstaller/pull/6903 + r"[0-9:]* INFO: Sandboxing disabled by user\.", + + # macOS? + (r'\[.*:ERROR:command_buffer_proxy_impl.cc\([0-9]*\)\] ' + r'ContextResult::kTransientFailure: Failed to send ' + r'GpuControl\.CreateCommandBuffer\.'), + ]) + elif IS_WINDOWS: + stderr_whitelist.extend([ + # Windows N: + # https://github.com/microsoft/playwright/issues/2901 + (r'\[.*:ERROR:dxva_video_decode_accelerator_win.cc\(\d+\)\] ' + r'DXVAVDA fatal error: could not LoadLibrary: .*: The specified ' + r'module could not be found. \(0x7E\)'), + ]) proc = _smoke_test_run(executable) if debug: @@ -233,23 +259,19 @@ def verify_windows_exe(exe_path: pathlib.Path) -> None: assert pe.verify_checksum() -def patch_mac_app() -> None: +def patch_mac_app(qt6: bool) -> None: """Patch .app to save some space and make it signable.""" dist_path = pathlib.Path('dist') + ver = '6' if qt6 else '5' app_path = dist_path / 'qutebrowser.app' contents_path = app_path / 'Contents' macos_path = contents_path / 'MacOS' resources_path = contents_path / 'Resources' - pyqt_path = macos_path / 'PyQt5' + pyqt_path = macos_path / f'PyQt{ver}' # Replace some duplicate files by symlinks - framework_path = pyqt_path / 'Qt5' / 'lib' / 'QtWebEngineCore.framework' - - core_lib = framework_path / 'Versions' / '5' / 'QtWebEngineCore' - core_lib.unlink() - core_target = pathlib.Path(*[os.pardir] * 7, 'MacOS', 'QtWebEngineCore') - core_lib.symlink_to(core_target) + framework_path = pyqt_path / f'Qt{ver}' / 'lib' / 'QtWebEngineCore.framework' framework_resource_path = framework_path / 'Resources' for file_path in framework_resource_path.iterdir(): @@ -260,6 +282,16 @@ def patch_mac_app() -> None: file_path.unlink() file_path.symlink_to(target) + if qt6: + # Symlinking QtWebEngineCore.framework does not seem to work with Qt 6. + # Also, the symlinking/moving before signing doesn't seem to be required. + return + + core_lib = framework_path / 'Versions' / '5' / 'QtWebEngineCore' + core_lib.unlink() + core_target = pathlib.Path(*[os.pardir] * 7, 'MacOS', 'QtWebEngineCore') + core_lib.symlink_to(core_target) + # Move stuff around to make things signable on macOS # See https://github.com/pyinstaller/pyinstaller/issues/6612 pyqt_path_dest = resources_path / pyqt_path.name @@ -303,6 +335,7 @@ def _mac_bin_path(base: pathlib.Path) -> pathlib.Path: def build_mac( *, gh_token: Optional[str], + qt6: bool, skip_packaging: bool, debug: bool, ) -> List[Artifact]: @@ -317,21 +350,20 @@ def build_mac( shutil.rmtree(d, ignore_errors=True) utils.print_title("Updating 3rdparty content") - # FIXME:qt6 Use modern PDF.js version here - update_3rdparty.run(ace=False, pdfjs=True, legacy_pdfjs=True, fancy_dmg=False, + update_3rdparty.run(ace=False, pdfjs=True, legacy_pdfjs=not qt6, fancy_dmg=False, gh_token=gh_token) utils.print_title("Building .app via pyinstaller") - call_tox('pyinstaller-64bit', '-r', debug=debug) + call_tox(f'pyinstaller-64bit{"-qt6" if qt6 else ""}', '-r', debug=debug) utils.print_title("Patching .app") - patch_mac_app() + patch_mac_app(qt6=qt6) utils.print_title("Re-signing .app") sign_mac_app() dist_path = pathlib.Path("dist") utils.print_title("Running pre-dmg smoke test") - smoke_test(_mac_bin_path(dist_path), debug=debug) + smoke_test(_mac_bin_path(dist_path), debug=debug, qt6=qt6) if skip_packaging: return [] @@ -341,6 +373,7 @@ def build_mac( subprocess.run(['make', '-f', dmg_makefile_path], check=True) suffix = "-debug" if debug else "" + suffix += "-qt6" if qt6 else "" dmg_path = dist_path / f'qutebrowser-{qutebrowser.__version__}{suffix}.dmg' pathlib.Path('qutebrowser.dmg').rename(dmg_path) @@ -352,7 +385,7 @@ def build_mac( subprocess.run(['hdiutil', 'attach', dmg_path, '-mountpoint', tmp_path], check=True) try: - smoke_test(_mac_bin_path(tmp_path), debug=debug) + smoke_test(_mac_bin_path(tmp_path), debug=debug, qt6=qt6) finally: print("Waiting 10s for dmg to be detachable...") time.sleep(10) @@ -391,6 +424,7 @@ def _get_windows_python_path(x64: bool) -> pathlib.Path: def _build_windows_single( *, x64: bool, + qt6: bool, skip_packaging: bool, debug: bool, ) -> List[Artifact]: @@ -404,12 +438,11 @@ def _build_windows_single( _maybe_remove(out_path) python = _get_windows_python_path(x64=x64) - call_tox( - f'pyinstaller-{"64bit" if x64 else "32bit"}', - '-r', - python=python, - debug=debug, - ) + suffix = "64bit" if x64 else "32bit" + if qt6: + # FIXME:qt6 does this regress 391623d5ec983ecfc4512c7305c4b7a293ac3872? + suffix += "-qt6" + call_tox(f'pyinstaller-{suffix}', '-r', python=python, debug=debug) out_pyinstaller = dist_path / "qutebrowser" shutil.move(out_pyinstaller, out_path) @@ -419,7 +452,7 @@ def _build_windows_single( verify_windows_exe(exe_path) utils.print_title(f"Running {human_arch} smoke test") - smoke_test(exe_path, debug=debug) + smoke_test(exe_path, debug=debug, qt6=qt6) if skip_packaging: return [] @@ -432,6 +465,7 @@ def _build_windows_single( desc_arch=human_arch, desc_suffix='' if x64 else ' (only for 32-bit Windows!)', debug=debug, + qt6=qt6, ) @@ -440,12 +474,12 @@ def build_windows( skip_packaging: bool, only_32bit: bool, only_64bit: bool, + qt6: bool, debug: bool, ) -> List[Artifact]: """Build windows executables/setups.""" utils.print_title("Updating 3rdparty content") - # FIXME:qt6 Use modern PDF.js version here - update_3rdparty.run(nsis=True, ace=False, pdfjs=True, legacy_pdfjs=True, + update_3rdparty.run(nsis=True, ace=False, pdfjs=True, legacy_pdfjs=not qt6, fancy_dmg=False, gh_token=gh_token) utils.print_title("Building Windows binaries") @@ -461,12 +495,14 @@ def build_windows( x64=True, skip_packaging=skip_packaging, debug=debug, + qt6=qt6, ) - if not only_64bit: + if not only_64bit and not qt6: artifacts += _build_windows_single( x64=False, skip_packaging=skip_packaging, debug=debug, + qt6=qt6, ) return artifacts @@ -480,6 +516,7 @@ def _package_windows_single( desc_suffix: str, filename_arch: str, debug: bool, + qt6: bool, ) -> List[Artifact]: """Build the given installer/zip for windows.""" artifacts = [] @@ -497,6 +534,8 @@ def _package_windows_single( ] if debug: name_parts.append('debug') + if qt6: + name_parts.append('qt6') name = '-'.join(name_parts) + '.exe' artifacts.append(Artifact( @@ -515,6 +554,8 @@ def _package_windows_single( ] if debug: zip_name_parts.append('debug') + if qt6: + zip_name_parts.append('qt6') zip_name = '-'.join(zip_name_parts) + '.zip' zip_path = dist_path / zip_name @@ -699,6 +740,8 @@ def main() -> None: help="Skip Windows 32 bit build.", dest='only_64bit') parser.add_argument('--debug', action='store_true', required=False, help="Build a debug build.") + parser.add_argument('--qt6', action='store_true', required=False, + help="Build against PyQt6") args = parser.parse_args() utils.change_cwd() @@ -721,18 +764,20 @@ def main() -> None: else: run_asciidoc2html() - if os.name == 'nt': + if IS_WINDOWS: artifacts = build_windows( gh_token=gh_token, skip_packaging=args.skip_packaging, only_32bit=args.only_32bit, only_64bit=args.only_64bit, + qt6=args.qt6, debug=args.debug, ) - elif sys.platform == 'darwin': + elif IS_MACOS: artifacts = build_mac( gh_token=gh_token, skip_packaging=args.skip_packaging, + qt6=args.qt6, debug=args.debug, ) else: |