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
14 changed files with 170 additions and 172 deletions

View File

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

View File

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

View File

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

View File

@ -3,21 +3,22 @@ config:
dependencies:
command: choco install Chocolatey.config -y
qt:
version: 6.7.2
version: 6.7
mirror: https://qt.mirror.constant.com/
install-dir: C:\Qt
modules:
- qt5compat
choco-ci:
base-dir: ./deps/qt
ci:
edit-config: Chocolatey.config
skip-packages:
- cmake
- visualstudio2022buildtools
mac:
qt-prefix-command: brew --prefix qt@6
dependencies:
command: brew bundle --file=Brewfile
qt:
version: 6.7
mirror: https://qt.mirror.constant.com/
base-dir: ./deps/qt
linux:
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 lib.env as env
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():
@ -10,14 +15,16 @@ def main():
parser.add_argument(
"--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(
"--only-python",
action="store_true",
help="Only install Python dependencies",
)
parser.add_argument(
"--ci-env",
action="store_true",
help="Set if running in CI environment",
)
args = parser.parse_args()
env.ensure_dependencies()
@ -27,7 +34,7 @@ def main():
error = False
if not args.only_python:
try:
deps = Dependencies(args.only)
deps = Dependencies(args.ci_env)
deps.install()
except Exception:
traceback.print_exc()
@ -42,12 +49,11 @@ def main():
class Dependencies:
def __init__(self, only):
def __init__(self, ci_env):
from lib.config import Config
self.config = Config()
self.only = only
self.ci_env = env.is_running_in_ci()
self.ci_env = ci_env
if self.ci_env:
print("CI environment detected")
@ -72,27 +78,18 @@ class Dependencies:
windows.relaunch_as_admin(__file__)
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 not self.ci_env or only_qt:
qt = windows.WindowsQt(*self.config.get_qt_config())
qt_install_dir = 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
if self.ci_env:
github.set_env_var(cmake_prefix_env_var, qt.get_install_dir())
else:
windows.set_env_var(cmake_prefix_env_var, qt.get_install_dir())
choco = windows.WindowsChoco()
if self.ci_env:
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)
command = self.config.get_deps_command()
@ -102,11 +99,24 @@ class Dependencies:
"""Installs dependencies on macOS."""
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")
cmd_utils.run(command, shell=True, print_cmd=True)
if not self.ci_env:
mac.set_env_vars(self.config.get_os_value("qt-prefix-command"))
if env_vars_set:
print(f"To load env vars, run: source {mac.shell_rc}")
def linux(self):
"""Installs dependencies on Linux."""

View File

@ -16,10 +16,10 @@ class ConfigKeyError(RuntimeError):
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)
if not value:
if required and not value:
key_path = f"{root_key}:{key_parent}:{key}" if key_parent else key
raise ConfigKeyError(config_file, key_path)
@ -50,8 +50,8 @@ class Config:
parent_key = f"{self.os_name}:{deps_key}"
mirror_url = _get(qt, "mirror", parent_key)
version = _get(qt, "version", parent_key)
base_dir = _get(qt, "install-dir", parent_key)
modules = _get(qt, "modules", parent_key)
base_dir = _get(qt, "base-dir", parent_key)
modules = _get(qt, "modules", parent_key, required=False)
return mirror_url, version, base_dir, modules
@ -70,8 +70,8 @@ class Config:
command = _get(deps, "command", f"{self.os_name}:{distro}:{deps_key}")
return cmd_utils.strip_continuation_sequences(command)
def get_choco_ci_config(self):
choco_ci_key = "choco-ci"
def get_windows_ci_config(self):
choco_ci_key = "ci"
choco_ci = self.get_os_deps_value(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"
def is_running_in_ci():
"""Returns True if running in a CI environment."""
return os.environ.get("CI")
def get_linux_distro():
"""Detects the Linux distro."""
os_file = "/etc/os-release"

View File

@ -1,15 +1,16 @@
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.
"""
env_file = os.getenv(github_key)
env_file = os.getenv(github_env_key)
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):
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}")
with open(env_file, "a") as env_file:
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
from lib.certificate import Certificate
path_env = "PATH"
cmake_env = "CMAKE_PREFIX_PATH"
cert_p12_env = "APPLE_P12_CERTIFICATE"
notary_user_env = "APPLE_NOTARY_USER"
shell_rc = "~/.zshrc"
@ -22,23 +20,23 @@ keychain_path = "/Library/Keychains/System.keychain"
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)
if os.path.exists(file):
with open(file, "r") as f:
if text in f.read():
return
return False
print(f"Setting environment variable: {name}={name}")
with open(file, "a") as f:
f.write(f"\n{text}\n")
print(f"Appended to {shell_rc}: {text}")
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)
return True
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"
signtool_cmd = "signtool"
certutil_cmd = "certutil"
cmake_env_var = "CMAKE_PREFIX_PATH"
runner_temp_env_var = "RUNNER_TEMP"
qt_base_dir_env_var = "QT_BASE_DIR"
dist_dir = "dist"
build_dir = "build"
wix_solution_file = f"{build_dir}/installer/Synergy.sln"
@ -188,54 +186,3 @@ class WindowsChoco:
print(f"Removed package from choco config: {remove}")
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
pyyaml
dmgbuild; sys_platform == 'darwin'
aqtinstall; sys_platform == 'win32' or sys_platform == 'darwin'

View File

@ -1,6 +1,6 @@
find_package(
Qt6
COMPONENTS Core5Compat Core Widgets Network
COMPONENTS Core Widgets Network
REQUIRED)
set(CMAKE_AUTOMOC ON)
@ -32,8 +32,7 @@ add_executable(synergy WIN32 ${GUI_SOURCE_FILES} ${GUI_UI_FILES}
include_directories(./src)
target_link_libraries(synergy shared)
target_link_libraries(synergy Qt6::Core Qt6::Widgets Qt6::Network
Qt6::Core5Compat)
target_link_libraries(synergy Qt6::Core Qt6::Widgets Qt6::Network)
target_compile_definitions(
synergy PRIVATE -DSYNERGY_VERSION_STAGE="${SYNERGY_VERSION_STAGE}")
target_compile_definitions(synergy
@ -55,12 +54,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
install(CODE "MESSAGE (\"Running: ${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")
install(TARGETS synergy DESTINATION bin)