Correct Qt macOS target and drop Core5Compat lib (#7389)

* Remove Core5Compat

* Remove hack

* Update ChangeLog

* Revert "Remove hack"

This reverts commit dda3ad05818d346fdfcbb41944b9e731a4b547c0.

* Set `add_compile_definitions` for Qt

* Revert "Set `add_compile_definitions` for Qt"

This reverts commit 0258d2d226a76081068f4e565855f37993953be5.

* Use arm64_monterey bottle

* Revert "Use arm64_monterey bottle"

This reverts commit a46d743dc6883c925e2328b9628231189cb34367.

* Use aqt to install Qt on Mac

* Append env var instead of overwrite

* Fixed filename

* Use GITHUB_PATH

* Restore original GITHUB_ENV logic

* Use newer cache action

* Update ChangeLog
This commit is contained in:
Nick Bolton 2024-07-15 12:57:39 +01:00 committed by GitHub
parent 4fa863c3ea
commit 4d3f0c820e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 170 additions and 172 deletions

View file

@ -39,9 +39,6 @@ jobs:
container: ${{ matrix.target.container }} container: ${{ matrix.target.container }}
timeout-minutes: 20 timeout-minutes: 20
env:
QT_BASE_DIR: ${{ github.workspace }}\deps\Qt
strategy: strategy:
matrix: matrix:
target: target:
@ -55,32 +52,24 @@ jobs:
submodules: "recursive" submodules: "recursive"
- name: Cache Chocolatey packages - name: Cache Chocolatey packages
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: ${{ runner.temp }}/choco path: ${{ runner.temp }}/choco
key: choco-${{ hashFiles('Chocolatey.config') }} key: choco-${{ hashFiles('Chocolatey.config') }}
- name: Install dependencies - name: Cache deps dir
run: python ./scripts/install_deps.py
- name: Set QT_VERSION env var
run: python ./scripts/github_env.py --set-qt-version
- name: Cache Qt
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
path: ${{ env.QT_BASE_DIR }} path: ./deps
key: ${{ runner.os }}-Qt_${{ env.QT_VERSION }} key: ${{ runner.os }}-deps-${{ hashFiles('config.yaml') }}
- name: Install Qt - name: Install dependencies
run: python ./scripts/install_deps.py --only qt run: python ./scripts/install_deps.py --ci-env
- name: Setup VC++ environment - name: Setup VC++ environment
uses: ilammy/msvc-dev-cmd@v1 uses: ilammy/msvc-dev-cmd@v1
- name: Configure - name: Configure
env:
CMAKE_PREFIX_PATH: "${{ env.QT_BASE_DIR }}\\${{ env.QT_VERSION }}\\msvc2019_64\\"
run: cmake -B build --preset=windows-release run: cmake -B build --preset=windows-release
- name: Build - name: Build
@ -138,11 +127,17 @@ jobs:
with: with:
submodules: "recursive" submodules: "recursive"
- name: Cache deps dir
uses: actions/cache@v4
with:
path: ./deps
key: ${{ runner.os }}-deps-${{ hashFiles('config.yaml') }}
- name: Install dependencies - name: Install dependencies
run: ./scripts/install_deps.py run: ./scripts/install_deps.py --ci-env
- name: Configure - name: Configure
run: cmake -B build --preset=macos-release -DCMAKE_PREFIX_PATH=$(brew --prefix qt@6) run: cmake -B build --preset=macos-release
- name: Build - name: Build
run: cmake --build build -j8 run: cmake --build build -j8
@ -240,7 +235,7 @@ jobs:
run: git config --global --add safe.directory $GITHUB_WORKSPACE run: git config --global --add safe.directory $GITHUB_WORKSPACE
- name: Install dependencies - name: Install dependencies
run: ./scripts/install_deps.py run: ./scripts/install_deps.py --ci-env
- name: Configure - name: Configure
run: cmake -B build --preset=linux-release run: cmake -B build --preset=linux-release

View file

@ -1,4 +1,3 @@
brew 'make' brew 'make'
brew 'cmake' brew 'cmake'
brew 'openssl' brew 'openssl'
brew 'qt@6'

View file

@ -51,6 +51,7 @@ Enhancements:
- #7381 Set macOS min version to macOS 12.0 - #7381 Set macOS min version to macOS 12.0
- #7382 Re-run `macdeployqt6` to copy missing Qt 6 dependencies - #7382 Re-run `macdeployqt6` to copy missing Qt 6 dependencies
- #7384 Run `install_deps.py` script when building containers weekly - #7384 Run `install_deps.py` script when building containers weekly
- #7389 Correct Qt macOS target and drop `Core5Compat` lib
# 1.14.6 # 1.14.6

View file

@ -3,21 +3,22 @@ config:
dependencies: dependencies:
command: choco install Chocolatey.config -y command: choco install Chocolatey.config -y
qt: qt:
version: 6.7.2 version: 6.7
mirror: https://qt.mirror.constant.com/ mirror: https://qt.mirror.constant.com/
install-dir: C:\Qt base-dir: ./deps/qt
modules: ci:
- qt5compat
choco-ci:
edit-config: Chocolatey.config edit-config: Chocolatey.config
skip-packages: skip-packages:
- cmake - cmake
- visualstudio2022buildtools - visualstudio2022buildtools
mac: mac:
qt-prefix-command: brew --prefix qt@6
dependencies: dependencies:
command: brew bundle --file=Brewfile command: brew bundle --file=Brewfile
qt:
version: 6.7
mirror: https://qt.mirror.constant.com/
base-dir: ./deps/qt
linux: linux:
debian: &debian debian: &debian

View file

@ -1,33 +0,0 @@
#!/usr/bin/env python3
import argparse
import lib.env as env
import lib.github as github
qt_version_key = "QT_VERSION"
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
"--set-qt-version",
action="store_true",
help=f"Set {qt_version_key} env var",
)
args = parser.parse_args()
# important: load venv before loading modules that install deps.
env.ensure_in_venv(__file__)
from lib.config import Config
if args.set_qt_version:
config = Config()
_, qt_version, _, _ = config.get_qt_config()
github.set_env(qt_version_key, qt_version)
else:
raise RuntimeError("No option selected")
if __name__ == "__main__":
main()

View file

@ -3,6 +3,11 @@
import os, sys, argparse, traceback import os, sys, argparse, traceback
import lib.env as env import lib.env as env
import lib.cmd_utils as cmd_utils import lib.cmd_utils as cmd_utils
import lib.qt_utils as qt_utils
import lib.github as github
path_env_var = "PATH"
cmake_prefix_env_var = "CMAKE_PREFIX_PATH"
def main(): def main():
@ -10,14 +15,16 @@ def main():
parser.add_argument( parser.add_argument(
"--pause-on-exit", action="store_true", help="Useful on Windows" "--pause-on-exit", action="store_true", help="Useful on Windows"
) )
parser.add_argument(
"--only", type=str, help="Only install the specified dependency"
)
parser.add_argument( parser.add_argument(
"--only-python", "--only-python",
action="store_true", action="store_true",
help="Only install Python dependencies", help="Only install Python dependencies",
) )
parser.add_argument(
"--ci-env",
action="store_true",
help="Set if running in CI environment",
)
args = parser.parse_args() args = parser.parse_args()
env.ensure_dependencies() env.ensure_dependencies()
@ -27,7 +34,7 @@ def main():
error = False error = False
if not args.only_python: if not args.only_python:
try: try:
deps = Dependencies(args.only) deps = Dependencies(args.ci_env)
deps.install() deps.install()
except Exception: except Exception:
traceback.print_exc() traceback.print_exc()
@ -42,12 +49,11 @@ def main():
class Dependencies: class Dependencies:
def __init__(self, only): def __init__(self, ci_env):
from lib.config import Config from lib.config import Config
self.config = Config() self.config = Config()
self.only = only self.ci_env = ci_env
self.ci_env = env.is_running_in_ci()
if self.ci_env: if self.ci_env:
print("CI environment detected") print("CI environment detected")
@ -72,27 +78,18 @@ class Dependencies:
windows.relaunch_as_admin(__file__) windows.relaunch_as_admin(__file__)
sys.exit() sys.exit()
only_qt = self.only == "qt" qt = qt_utils.WindowsQt(*self.config.get_qt_config())
qt.install()
# for ci, skip qt; we install qt separately so we can cache it. if self.ci_env:
if not self.ci_env or only_qt: github.set_env_var(cmake_prefix_env_var, qt.get_install_dir())
qt = windows.WindowsQt(*self.config.get_qt_config()) else:
qt_install_dir = qt.get_install_dir() windows.set_env_var(cmake_prefix_env_var, qt.get_install_dir())
if qt_install_dir:
print(f"Skipping Qt, already installed at: {qt_install_dir}")
else:
qt.install()
if not self.ci_env:
qt.set_env_vars()
if only_qt:
return
choco = windows.WindowsChoco() choco = windows.WindowsChoco()
if self.ci_env: if self.ci_env:
choco.config_ci_cache() choco.config_ci_cache()
edit_config, skip_packages = self.config.get_choco_ci_config() edit_config, skip_packages = self.config.get_windows_ci_config()
choco.remove_from_config(edit_config, skip_packages) choco.remove_from_config(edit_config, skip_packages)
command = self.config.get_deps_command() command = self.config.get_deps_command()
@ -102,11 +99,24 @@ class Dependencies:
"""Installs dependencies on macOS.""" """Installs dependencies on macOS."""
import lib.mac as mac import lib.mac as mac
qt = qt_utils.MacQt(*self.config.get_qt_config())
qt.install()
qt_dir = qt.get_install_dir()
qt_bin_dir = os.path.join(qt_dir, "bin")
env_vars_set = 0
if self.ci_env:
github.set_env_var(cmake_prefix_env_var, qt_dir)
github.add_to_path(qt_bin_dir)
else:
env_vars_set += mac.set_env_var(cmake_prefix_env_var, qt_dir)
env_vars_set += mac.set_env_var(path_env_var, qt_bin_dir)
command = self.config.get_os_deps_value("command") command = self.config.get_os_deps_value("command")
cmd_utils.run(command, shell=True, print_cmd=True) cmd_utils.run(command, shell=True, print_cmd=True)
if not self.ci_env: if env_vars_set:
mac.set_env_vars(self.config.get_os_value("qt-prefix-command")) print(f"To load env vars, run: source {mac.shell_rc}")
def linux(self): def linux(self):
"""Installs dependencies on Linux.""" """Installs dependencies on Linux."""

View file

@ -16,10 +16,10 @@ class ConfigKeyError(RuntimeError):
return f"Not found in {self.config_file}: {self.key}" return f"Not found in {self.config_file}: {self.key}"
def _get(dict, key, key_parent=None): def _get(dict, key, key_parent=None, required=True):
value = dict.get(key) value = dict.get(key)
if not value: if required and not value:
key_path = f"{root_key}:{key_parent}:{key}" if key_parent else key key_path = f"{root_key}:{key_parent}:{key}" if key_parent else key
raise ConfigKeyError(config_file, key_path) raise ConfigKeyError(config_file, key_path)
@ -50,8 +50,8 @@ class Config:
parent_key = f"{self.os_name}:{deps_key}" parent_key = f"{self.os_name}:{deps_key}"
mirror_url = _get(qt, "mirror", parent_key) mirror_url = _get(qt, "mirror", parent_key)
version = _get(qt, "version", parent_key) version = _get(qt, "version", parent_key)
base_dir = _get(qt, "install-dir", parent_key) base_dir = _get(qt, "base-dir", parent_key)
modules = _get(qt, "modules", parent_key) modules = _get(qt, "modules", parent_key, required=False)
return mirror_url, version, base_dir, modules return mirror_url, version, base_dir, modules
@ -70,8 +70,8 @@ class Config:
command = _get(deps, "command", f"{self.os_name}:{distro}:{deps_key}") command = _get(deps, "command", f"{self.os_name}:{distro}:{deps_key}")
return cmd_utils.strip_continuation_sequences(command) return cmd_utils.strip_continuation_sequences(command)
def get_choco_ci_config(self): def get_windows_ci_config(self):
choco_ci_key = "choco-ci" choco_ci_key = "ci"
choco_ci = self.get_os_deps_value(choco_ci_key) choco_ci = self.get_os_deps_value(choco_ci_key)
choco_ci_path = f"{self.os_name}:{deps_key}:{choco_ci_key}" choco_ci_path = f"{self.os_name}:{deps_key}:{choco_ci_key}"

View file

@ -37,11 +37,6 @@ def is_linux():
return get_os() == "linux" return get_os() == "linux"
def is_running_in_ci():
"""Returns True if running in a CI environment."""
return os.environ.get("CI")
def get_linux_distro(): def get_linux_distro():
"""Detects the Linux distro.""" """Detects the Linux distro."""
os_file = "/etc/os-release" os_file = "/etc/os-release"

View file

@ -1,15 +1,16 @@
import os import os
github_key = "GITHUB_ENV" github_env_key = "GITHUB_ENV"
github_path_key = "GITHUB_PATH"
def set_env(key, value): def set_env_var(key, value):
""" """
Appends the key=value pair to the GitHub environment file. Appends the key=value pair to the GitHub environment file.
""" """
env_file = os.getenv(github_key) env_file = os.getenv(github_env_key)
if not env_file: if not env_file:
raise RuntimeError(f"Env var {github_key} not set") raise RuntimeError(f"Env var {github_env_key} not set")
if not os.path.exists(env_file): if not os.path.exists(env_file):
raise RuntimeError(f"File not found: {env_file}") raise RuntimeError(f"File not found: {env_file}")
@ -17,3 +18,19 @@ def set_env(key, value):
print(f"Setting GitHub env var: {key}={value}") print(f"Setting GitHub env var: {key}={value}")
with open(env_file, "a") as env_file: with open(env_file, "a") as env_file:
env_file.write(f"{key}={value}\n") env_file.write(f"{key}={value}\n")
def add_to_path(value):
"""
Appends the value to the GitHub path.
"""
path_file = os.getenv(github_path_key)
if not path_file:
raise RuntimeError(f"Env var {github_path_key} not set")
if not os.path.exists(path_file):
raise RuntimeError(f"File not found: {path_file}")
print(f"Adding to GitHub path: {value}")
with open(path_file, "a") as path_file:
path_file.write(f"{value}\n")

View file

@ -4,8 +4,6 @@ import lib.cmd_utils as cmd_utils
import lib.env as env import lib.env as env
from lib.certificate import Certificate from lib.certificate import Certificate
path_env = "PATH"
cmake_env = "CMAKE_PREFIX_PATH"
cert_p12_env = "APPLE_P12_CERTIFICATE" cert_p12_env = "APPLE_P12_CERTIFICATE"
notary_user_env = "APPLE_NOTARY_USER" notary_user_env = "APPLE_NOTARY_USER"
shell_rc = "~/.zshrc" shell_rc = "~/.zshrc"
@ -22,23 +20,23 @@ keychain_path = "/Library/Keychains/System.keychain"
def set_env_var(name, value): def set_env_var(name, value):
text = f'export {name}="${name}:{value}"' """
Adds to an environment variable in the shell rc file.
Returns True if the variable was added, False if it already exists.
"""
text = f'export {name}="{value}:${name}"'
file = os.path.expanduser(shell_rc) file = os.path.expanduser(shell_rc)
if os.path.exists(file): if os.path.exists(file):
with open(file, "r") as f: with open(file, "r") as f:
if text in f.read(): if text in f.read():
return return False
print(f"Setting environment variable: {name}={name}") print(f"Setting environment variable: {name}={name}")
with open(file, "a") as f: with open(file, "a") as f:
f.write(f"\n{text}\n") f.write(f"\n{text}\n")
print(f"Appended to {shell_rc}: {text}") print(f"Appended to {shell_rc}: {text}")
return True
def set_env_vars(cmake_prefix_command):
cmd_sub = f"$({cmake_prefix_command})"
set_env_var(path_env, cmd_sub)
set_env_var(cmake_env, cmd_sub)
def package(filename_base): def package(filename_base):

74
scripts/lib/qt_utils.py Normal file
View file

@ -0,0 +1,74 @@
import os
import lib.cmd_utils as cmd_utils
import lib.env as env
import glob
class Qt:
def __init__(
self, mirror_url, version, base_dir, modules, os_name, compiler, tool_dir
):
self.mirror_url = mirror_url
self.version = version
self.base_dir = base_dir
self.modules = modules
self.os_name = os_name
self.compiler = compiler
self.tool_dir = tool_dir
self.dir_pattern = f"{self.base_dir}{os.sep}{self.version}*/{self.tool_dir}"
def get_install_dir(self):
match = glob.glob(self.dir_pattern)
return os.path.abspath(match[0]) if match else None
def install(self):
"""Install Qt."""
if self.get_install_dir():
print(f"Skipping Qt, already installed at: {self.dir_pattern}")
return
args = [env.get_python_executable(), "-m", "aqt", "install-qt"]
args.extend(["--outputdir", self.base_dir])
args.extend(["--base", self.mirror_url])
args.extend([self.os_name, "desktop", str(self.version), self.compiler])
if self.modules:
args.extend(["-m"] + self.modules)
print(args)
cmd_utils.run(
args,
print_cmd=True,
)
if not self.get_install_dir():
raise RuntimeError(
f"Qt was not installed, path not found: {self.dir_pattern}"
)
class WindowsQt(Qt):
def __init__(self, mirror_url, version, base_dir, modules):
super().__init__(
mirror_url,
version,
base_dir,
modules,
"windows",
"win64_msvc2019_64",
"msvc2019_64",
)
class MacQt(Qt):
def __init__(self, mirror_url, version, base_dir, modules):
super().__init__(
mirror_url,
version,
base_dir,
modules,
"mac",
"clang_64",
"macos",
)

View file

@ -7,9 +7,7 @@ from lib.certificate import Certificate
msbuild_cmd = "msbuild" msbuild_cmd = "msbuild"
signtool_cmd = "signtool" signtool_cmd = "signtool"
certutil_cmd = "certutil" certutil_cmd = "certutil"
cmake_env_var = "CMAKE_PREFIX_PATH"
runner_temp_env_var = "RUNNER_TEMP" runner_temp_env_var = "RUNNER_TEMP"
qt_base_dir_env_var = "QT_BASE_DIR"
dist_dir = "dist" dist_dir = "dist"
build_dir = "build" build_dir = "build"
wix_solution_file = f"{build_dir}/installer/Synergy.sln" wix_solution_file = f"{build_dir}/installer/Synergy.sln"
@ -188,54 +186,3 @@ class WindowsChoco:
print(f"Removed package from choco config: {remove}") print(f"Removed package from choco config: {remove}")
tree.write(choco_config_file) tree.write(choco_config_file)
class WindowsQt:
"""Qt for Windows."""
def __init__(self, mirror_url, version, base_dir, modules):
self.mirror_url = mirror_url
self.version = version
self.modules = modules
# allows ci to override the qt base dir path
self.base_dir = os.environ.get(qt_base_dir_env_var)
if not self.base_dir:
print(f"QT_BASE_DIR not set, using: {base_dir}")
self.base_dir = base_dir
self.install_dir = f"{self.base_dir}\\{self.version}"
def get_install_dir(self):
if os.path.isdir(self.install_dir):
return self.install_dir
def install(self):
"""Installs Qt on Windows."""
cmd_utils.run(
["pip", "install", "aqtinstall"],
shell=True,
print_cmd=True,
)
args = ["python", "-m", "aqt", "install-qt"]
args.extend(["--outputdir", self.base_dir])
args.extend(["--base", self.mirror_url])
args.extend(
["windows", "desktop", self.version, "win64_msvc2019_64", "-m"]
+ self.modules
)
cmd_utils.run(
args,
shell=True,
print_cmd=True,
)
install_dir = self.get_install_dir()
if not install_dir:
raise RuntimeError(f"Qt not installed, path not found: {install_dir}")
def set_env_vars(self):
set_env_var(cmake_env_var, f"{self.get_install_dir()}\\msvc2019_64")

View file

@ -3,3 +3,4 @@ clang-format
python-dotenv python-dotenv
pyyaml pyyaml
dmgbuild; sys_platform == 'darwin' dmgbuild; sys_platform == 'darwin'
aqtinstall; sys_platform == 'win32' or sys_platform == 'darwin'

View file

@ -1,6 +1,6 @@
find_package( find_package(
Qt6 Qt6
COMPONENTS Core5Compat Core Widgets Network COMPONENTS Core Widgets Network
REQUIRED) REQUIRED)
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
@ -32,8 +32,7 @@ add_executable(synergy WIN32 ${GUI_SOURCE_FILES} ${GUI_UI_FILES}
include_directories(./src) include_directories(./src)
target_link_libraries(synergy shared) target_link_libraries(synergy shared)
target_link_libraries(synergy Qt6::Core Qt6::Widgets Qt6::Network target_link_libraries(synergy Qt6::Core Qt6::Widgets Qt6::Network)
Qt6::Core5Compat)
target_compile_definitions( target_compile_definitions(
synergy PRIVATE -DSYNERGY_VERSION_STAGE="${SYNERGY_VERSION_STAGE}") synergy PRIVATE -DSYNERGY_VERSION_STAGE="${SYNERGY_VERSION_STAGE}")
target_compile_definitions(synergy target_compile_definitions(synergy
@ -55,12 +54,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
install(CODE "MESSAGE (\"Running: ${MACDEPLOYQT_CMD}\")") install(CODE "MESSAGE (\"Running: ${MACDEPLOYQT_CMD}\")")
install(CODE "execute_process(COMMAND ${MACDEPLOYQT_CMD})") install(CODE "execute_process(COMMAND ${MACDEPLOYQT_CMD})")
# HACK: Bundle again to fix missing deps. Since Qt 6, it seems that the first
# pass misses out many dependencies from the Framework dir (it also finishes
# quickly with a bunch of warnings), and after the 2nd pass (which takes much
# longer), all of the dependencies are copied to the bundle.
install(CODE "execute_process(COMMAND ${MACDEPLOYQT_CMD})")
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
install(TARGETS synergy DESTINATION bin) install(TARGETS synergy DESTINATION bin)