From a8f48df4f93afe9be623da0ff67453bc6f2f27be Mon Sep 17 00:00:00 2001
From: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
Date: Tue, 11 Apr 2023 12:30:28 -0400
Subject: [PATCH] misc: use qt path instead of version as parameter in build
 scripts

This homogenizes the script calling convention with other platforms, and will allow for a cleaner approach when searching for Qt tools (qmlformat).

Gitlab: #1059
Change-Id: I540ff61bd92186bb5a2998670665631e352852b9
---
 INSTALL.md                      | 19 +++------
 build.py                        |  2 +-
 extras/scripts/build-windows.py | 71 +++++++++++++++++++--------------
 3 files changed, 47 insertions(+), 45 deletions(-)

diff --git a/INSTALL.md b/INSTALL.md
index 3a298778a..31cb6098b 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -197,24 +197,19 @@ Only 64-bit MSVC build can be compiled.
 - Using a new **Non-Elevated Command Prompt**
 
 ```bash
-    python build.py --install
+    python build.py --install --qt <path-to-qt-bin-folder> (e.g. C:/Qt/6.2.3/msvc2019_64)
 ```
 
 > **SDK** Note:
 > Jami can be build with more recent Windows SDK than the one specified in the table above. However, if your have another version than SDK 10.0.18362.0 installed, you need to identify it according to the example below. And you still need to have the required version in addition to the one you chose.
 
 ```bash
-    python build.py --install --sdk <your-sdk-version>
+    python build.py --install --qt <path-to-qt-bin-folder> --sdk <your-sdk-version>
 ```
 
-> **Qt** Note: If you have another version than qt 6.2.3 installed this step will build daemon correctly but will fail for the client.
-> When that happens you need to compile the client separately:
+> **Qt** Note: If you omit the `--qt` option, the build script will try to find Qt in the default installation folder, and will take the latest version found. If you have appropriate Qt and SDK versions installed, you won't need to specify any additional options.
 
-```bash
-    python build.py --install
-```
-
-- Then you should be able to use the Visual Studio Solution file in client-qt folder **(Configuration = Release, Platform = x64)**
+Once the build has finished, you should then be able to use the Visual Studio Solution file in client-qt **build** folder **(Configuration = Release, Platform = x64)**
 
 ### Build Module Individually
 
@@ -245,11 +240,9 @@ Only 64-bit MSVC build can be compiled.
 
 ```
     python extras\scripts\build-windows.py --init
-    python extras\scripts\build-windows.py --qtver <your qt version>
+    python extras\scripts\build-windows.py --qt <path-to-qt-bin-folder> (e.g. C:/Qt/6.2.3/msvc2019_64)
 ```
 
-Note: if your qt version is different than 6.2.3, you need to use `python extras\scripts\build-windows.py --qtver <your qt version>`.
-
 ## Building On MacOS
 
 **Set up**
@@ -296,7 +289,7 @@ Built client could be find in `build/Jami`
 - We currently use [GoogleTest](https://github.com/google/googletest) and [Qt Quick Test](https://doc.qt.io/qt-5/qtquicktest-index.html#introduction) in our product. To build and run tests, you could use the following command.
 
 ```
-    python extras\scripts\build-windows.py --tests
+    python extras\scripts\build-windows.py --tests --qt <path-to-qt-bin-folder>
 ```
 
 - Note that, for tests, the path of local storage files for jami will be changed based on following environment variables.
diff --git a/build.py b/build.py
index fb487d5c4..dfda20921 100755
--- a/build.py
+++ b/build.py
@@ -349,7 +349,7 @@ def run_install(args):
                  f'-s {args.sdk} -b daemon'])
         build_windows = 'extras/scripts/build-windows.py'
         execute_script([f'python {build_windows} --init'])
-        execute_script([f'python {build_windows}'])
+        execute_script([f'python {build_windows} --qt={args.qt}'])
         return True
 
     # Unix-like platforms
diff --git a/extras/scripts/build-windows.py b/extras/scripts/build-windows.py
index a7c53a4ac..b259ed817 100644
--- a/extras/scripts/build-windows.py
+++ b/extras/scripts/build-windows.py
@@ -5,9 +5,10 @@ Build, test, and package the project.
 This script provides methods to build the project, build and run qml tests,
 and package the project for Windows.
 
-usage: build.py [-h] [-a ARCH] [-c CONFIG] [-t] [-i] [-v] {pack} ...
+usage: build.py [-q] [-h] [-a ARCH] [-c CONFIG] [-t] [-i] [-v] {pack} ...
 
 optional arguments:
+  -q, --qt PATH         Sets the Qt installation path
   -a ARCH, --arch ARCH  Sets the build architecture
   -c CONFIG, --config CONFIG
                         Sets the build configuration type
@@ -23,15 +24,14 @@ usage: build.py pack [-h] [-s] (-m | -z)
 
 mutually exclusive required arguments:
   -m, --msi         Build MSI installer
-  -z, --zip         Build ZIP archive
+  -z, --zip         Build portable archive
 
 examples:
-1.  build.py --init pack --msi      # Build the application from scratch and
-                                      an MSI installer
-2.  build.py --init --tests         # Build the application from scratch and
-                                      build and run tests
-    build.py pack --zip             # Generate a ZIP archive of the application
-                                      without building
+1.  build.py --qt=C:/Qt/6.2.3/msvc2019_64  # Build the app using a specific Qt
+2.  build.py --init pack --msi             # Build the app and an MSI installer
+3.  build.py --init --tests                # Build the app and run tests
+    build.py pack --zip --skip-build       # Generate a 7z archive of the app
+                                             without building
 
 """
 
@@ -43,16 +43,6 @@ import argparse
 import multiprocessing
 
 
-# Qt information
-QT_VERSION = "6.2.3"
-if sys.platform == "win32":
-    QT_PATH = os.path.join("c:", os.sep, "Qt")
-    QT_KIT_PATH = "msvc2019_64"
-else:
-    QT_PATH = ""
-    QT_KIT_PATH = "clang_64"
-qt_root_path = os.getenv("QT_ROOT_DIRECTORY", QT_PATH)
-
 # Visual Studio helpers
 VS_WHERE_PATH = ""
 if sys.platform == "win32":
@@ -73,6 +63,22 @@ repo_root_dir = os.path.abspath(os.path.join(this_dir, os.pardir, os.pardir))
 build_dir = os.path.join(repo_root_dir, "build")
 
 
+def find_latest_qt_path():
+    """Find the latest Qt installation path."""
+    # Start with the default install path.
+    qt_base_path = os.path.join("c:", os.sep, "Qt")
+    # There should be folders named with SEMVER numbers under it.
+    # Find the highest version number with an alphabetical sort dirname.
+    qt_version_dirs = sorted(os.listdir(qt_base_path), reverse=True)
+    # Filter out any non-numeric version numbers.
+    qt_version_dirs = [d for d in qt_version_dirs if d[0].isnumeric()]
+    # If there are no version numbers, return None.
+    if len(qt_version_dirs) == 0:
+        return None
+    # The latest version should be the last item in the list.
+    return os.path.join(qt_base_path, qt_version_dirs[0], 'msvc2019_64')
+
+
 def execute_cmd(cmd, with_shell=False, env_vars=None, cmd_dir=repo_root_dir):
     """Execute a command with subprocess."""
     proc = subprocess.Popen(
@@ -263,16 +269,13 @@ def cmake_build(config_str, env_vars, cmake_build_dir):
     return True
 
 
-def build(config_str, qtver, tests):
+def build(config_str, qt_dir, tests):
     """Use cmake to build the project."""
-    print("Building with Qt " + qtver)
+    print("Building with Qt at " + qt_dir)
 
     vs_env_vars = {}
     vs_env_vars.update(get_vs_env())
 
-    # Get the Qt bin directory.
-    qt_dir = os.path.join(qt_root_path, qtver, QT_KIT_PATH)
-
     # Get the daemon bin/include directories.
     daemon_dir = os.path.join(repo_root_dir, "daemon")
     daemon_bin_dir = os.path.join(
@@ -304,11 +307,10 @@ def build(config_str, qtver, tests):
         sys.exit(1)
 
 
-def run_tests(config_str):
+def run_tests(config_str, qt_dir):
     """Run tests."""
     print("Running client tests")
 
-    qt_dir = os.path.join(qt_root_path, QT_VERSION, QT_KIT_PATH)
     os.environ["PATH"] += os.pathsep + os.path.join(qt_dir, 'bin')
     os.environ["QT_QPA_PLATFORM"] = "offscreen"
     os.environ["QT_QUICK_BACKEND"] = "software"
@@ -385,6 +387,10 @@ def parse_args():
     parser = argparse.ArgumentParser(description="Client build tool")
     subparsers = parser.add_subparsers(dest="subcommand")
 
+    # The Qt install path is not required and will be searched for if not
+    # specified. In that case, the latest version of Qt will be used.
+    parser.add_argument('-q', '--qt', default=None,
+                        help='Sets the Qt root path')
     parser.add_argument(
         "-a", "--arch", default="x64", help="Sets the build architecture")
     parser.add_argument(
@@ -395,9 +401,6 @@ def parse_args():
     parser.add_argument(
         '-b', '--beta', action='store_true',
         help='Build Qt Client in Beta Config')
-    parser.add_argument(
-        '-q', '--qtver', default=QT_VERSION,
-        help='Sets the version of Qmake')
     parser.add_argument(
         "-i", "--init", action="store_true", help="Initialize submodules")
     parser.add_argument(
@@ -435,6 +438,12 @@ def main():
 
     parsed_args = parse_args()
 
+    if not parsed_args.qt:
+        parsed_args.qt = find_latest_qt_path()
+        if not parsed_args.qt:
+            print("Qt not found. Please specify the path to Qt.")
+            sys.exit(1)
+
     if parsed_args.version:
         print(get_version())
         sys.exit(0)
@@ -449,17 +458,17 @@ def main():
 
     if parsed_args.subcommand == "pack":
         if not skip_build:
-            build(config_str, parsed_args.qtver, False)
+            build(config_str, parsed_args.qt, False)
         elif parsed_args.msi:
             generate_msi(get_version())
         elif parsed_args.zip:
             generate_zip(get_version())
     else:
         if not skip_build:
-            build(config_str, parsed_args.qtver,
+            build(config_str, parsed_args.qt,
                   parsed_args.tests)
         if parsed_args.tests:
-            run_tests(config_str)
+            run_tests(config_str, parsed_args.qt)
 
     print("Done")
 
-- 
GitLab