From ed6cf7696871e01685c1c96d6d13deb6439ae490 Mon Sep 17 00:00:00 2001 From: Dave Dalcino Date: Sun, 24 Jul 2022 00:30:16 -0700 Subject: [PATCH] Add CLI option to install desktop qt automatically This change also causes aqt to emit a warning when the option is not turned on and the expected desktop Qt is not found. --- aqt/installer.py | 45 +++++++++++++++++++++++++++++++++++++++++++ tests/test_install.py | 10 ++++++++++ 2 files changed, 55 insertions(+) diff --git a/aqt/installer.py b/aqt/installer.py index 0ecc94d..42aa5c2 100644 --- a/aqt/installer.py +++ b/aqt/installer.py @@ -299,6 +299,7 @@ class Cli: if modules is not None and archives is not None: archives.append(modules) nopatch = args.noarchives or (archives is not None and "qtbase" not in archives) # type: bool + warn_on_missing_desktop_qt: bool = not args.autodesktop if not self._check_qt_arg_versions(qt_version): self.logger.warning("Specified Qt version is unknown: {}.".format(qt_version)) if not self._check_qt_arg_combination(qt_version, os_name, target, arch): @@ -328,6 +329,7 @@ class Cli: with TemporaryDirectory() as temp_dir: _archive_dest = Cli.choose_archive_dest(archive_dest, keep, temp_dir) run_installer(qt_archives.get_packages(), base_dir, sevenzip, keep, _archive_dest) + self._handle_missing_desktop_qt(os_name, target, Version(qt_version), Path(base_dir), warn_on_missing_desktop_qt) if not nopatch: Updater.update(target_config, base_dir) self.logger.info("Finished installation") @@ -603,6 +605,12 @@ class Cli: action="store_true", help="No base packages; allow mod amendment with --modules option.", ) + install_qt_parser.add_argument( + "--autodesktop", + action="store_true", + help="For android/ios installations, a desktop Qt installation is required. " + "When enabled, this option installs the required desktop version automatically.", + ) def _set_install_tool_parser(self, install_tool_parser, *, is_legacy: bool): install_tool_parser.set_defaults(func=self.run_install_tool, is_legacy=is_legacy) @@ -640,6 +648,43 @@ class Cli: f"In the future, please omit this parameter." ) + @staticmethod + def _get_missing_desktop_arch(host: str, target: str, version: Version, base_dir: Path) -> Optional[str]: + """ + For mobile Qt installations, the desktop version of Qt is a dependency. + If the desktop version is not installed, this function returns the architecture that should be installed. + If no desktop Qt is required, or it is already installed, this function returns None. + """ + if target not in ["ios", "android"]: + return None + if host != "windows": + arch = aqt.updater.default_desktop_arch_dir(host, version) + expected_qmake = base_dir / format(version) / arch / "bin/qmake" + return arch if not expected_qmake.is_file() else None + else: + existing_desktop_qt = QtRepoProperty.find_installed_qt_mingw_dir(base_dir / format(version)) + if existing_desktop_qt: + return None + return MetadataFactory(ArchiveId("qt", host, "desktop")).fetch_default_desktop_arch(version) + + def _handle_missing_desktop_qt(self, host: str, target: str, version: Version, base_dir: Path, should_warn: bool): + missing_desktop_arch = Cli._get_missing_desktop_arch(host, target, version, base_dir) + if not missing_desktop_arch: + return + + msg_prefix = ( + f"You are installing the {target} version of Qt, which requires that the desktop version of Qt " + f"is also installed." + ) + if should_warn: + self.logger.warning( + f"{msg_prefix} You can install it with the following command:\n" + f" `aqt install-qt {host} desktop {version} {missing_desktop_arch}`" + ) + else: + self.logger.info(f"{msg_prefix} Now installing Qt: desktop {version} {missing_desktop_arch}") + self.run(["install-qt", host, "desktop", format(version), missing_desktop_arch]) + def _make_all_parsers(self, subparsers: argparse._SubParsersAction): deprecated_msg = "This command is deprecated and marked for removal in a future version of aqt." diff --git a/tests/test_install.py b/tests/test_install.py index 1aeb47a..e57cba2 100644 --- a/tests/test_install.py +++ b/tests/test_install.py @@ -576,6 +576,9 @@ def tool_archive(host: str, tool_name: str, variant: str, date: datetime = datet r"^INFO : aqtinstall\(aqt\) v.* on Python 3.*\n" r"INFO : Downloading qtbase...\n" r"Finished installation of qtbase-windows-android_armv7.7z in .*\n" + r"WARNING : You are installing the android version of Qt, which requires that the desktop version of " + r"Qt is also installed. You can install it with the following command:\n" + r" `aqt install-qt windows desktop 6.1.0 MINGW_MOCK_DEFAULT`\n" r"INFO : Patching .*6\.1\.0[/\\]android_armv7[/\\]bin[/\\]qmake.bat\n" r"INFO : Finished installation\n" r"INFO : Time elapsed: .* second" @@ -631,6 +634,9 @@ def tool_archive(host: str, tool_name: str, variant: str, date: datetime = datet r"^INFO : aqtinstall\(aqt\) v.* on Python 3.*\n" r"INFO : Downloading qtbase...\n" r"Finished installation of qtbase-linux-android_arm64_v8a.7z in .*\n" + r"WARNING : You are installing the android version of Qt, which requires that the desktop version of " + r"Qt is also installed. You can install it with the following command:\n" + r" `aqt install-qt linux desktop 6\.3\.0 gcc_64`\n" r"INFO : Patching .*6\.3\.0[/\\]android_arm64_v8a[/\\]bin[/\\]qmake\n" r"INFO : Finished installation\n" r"INFO : Time elapsed: .* second" @@ -686,6 +692,9 @@ def tool_archive(host: str, tool_name: str, variant: str, date: datetime = datet r"^INFO : aqtinstall\(aqt\) v.* on Python 3.*\n" r"INFO : Downloading qtbase...\n" r"Finished installation of qtbase-mac-ios.7z in .*\n" + r"WARNING : You are installing the ios version of Qt, which requires that the desktop version of Qt is " + r"also installed. You can install it with the following command:\n" + r" `aqt install-qt mac desktop 6\.1\.2 macos`\n" r"INFO : Patching .*6\.1\.2[/\\]ios[/\\]bin[/\\]qmake\n" r"INFO : Finished installation\n" r"INFO : Time elapsed: .* second" @@ -716,6 +725,7 @@ def test_install( monkeypatch.setattr("aqt.archives.getUrl", mock_get_url) monkeypatch.setattr("aqt.helper.getUrl", mock_get_url) monkeypatch.setattr("aqt.installer.downloadBinaryFile", mock_download_archive) + monkeypatch.setattr("aqt.metadata.MetadataFactory.fetch_default_desktop_arch", lambda *args: "MINGW_MOCK_DEFAULT") with TemporaryDirectory() as output_dir: cli = Cli()