1
0
mirror of https://gitlab.com/kelteseth/ScreenPlay.git synced 2024-11-22 10:42:29 +01:00

Fix compilation and signing

Move TrayIcon back to ScreenPlay:
- This fixes the missing labs plugins when running the macdeployqt script
- We don't need it here only in the SP main folder anyway

Move building and sign of the osx version for x64 and arm64 into the
actual build script.

Remove the qml plugin path workaround from the addImportPath
This commit is contained in:
Elias Steurer 2023-02-11 11:57:09 +01:00
parent 03c8d275d0
commit 6e2cecddb3
11 changed files with 104 additions and 70 deletions

View File

@ -44,6 +44,11 @@ option(OSX_BUNDLE "Enable distribution macOS bundle" OFF)
# This subdirectoy is needed for OSX and Linux to fix linker errors because we would have ScreenPlayApp executable and folder for the qml # This subdirectoy is needed for OSX and Linux to fix linker errors because we would have ScreenPlayApp executable and folder for the qml
# files in the same directory. # files in the same directory.
set(SCREENPLAY_QML_MODULES_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/qml") set(SCREENPLAY_QML_MODULES_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/qml")
if(APPLE)
set(SCREENPLAY_QML_MODULES_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ScreenPlay.app/Contents/MacOS/qml")
endif()
# Adds the qml import path so QtCreator can find them # Adds the qml import path so QtCreator can find them
list(APPEND QML_DIRS "${SCREENPLAY_QML_MODULES_PATH}") list(APPEND QML_DIRS "${SCREENPLAY_QML_MODULES_PATH}")
set(QML_IMPORT_PATH set(QML_IMPORT_PATH

View File

@ -97,7 +97,8 @@ set(QML
qml/Settings/SettingsHeader.qml qml/Settings/SettingsHeader.qml
qml/Settings/SettingsHorizontalSeperator.qml qml/Settings/SettingsHorizontalSeperator.qml
qml/Settings/SettingsPage.qml qml/Settings/SettingsPage.qml
qml/Workshop/Workshop.qml) qml/Workshop/Workshop.qml
qml/TrayIcon.qml)
set(TS_FILES set(TS_FILES
# cmake-format: sort # cmake-format: sort

View File

@ -14,6 +14,7 @@ import "qml/Monitors" as Monitors
import "qml/Installed" as Installed import "qml/Installed" as Installed
import "qml/Navigation" as Navigation import "qml/Navigation" as Navigation
import "qml/Community" as Community import "qml/Community" as Community
import "qml"
ApplicationWindow { ApplicationWindow {
id: root id: root
@ -123,7 +124,7 @@ ApplicationWindow {
id: monitors id: monitors
modalSource: content modalSource: content
} }
Util.TrayIcon { TrayIcon {
window: root window: root
} }
} }

View File

@ -200,14 +200,6 @@ void App::init()
qmlRegisterSingletonInstance("ScreenPlay", 1, 0, "App", this); qmlRegisterSingletonInstance("ScreenPlay", 1, 0, "App", this);
m_mainWindowEngine->addImportPath(guiAppInst->applicationDirPath() + "/qml"); m_mainWindowEngine->addImportPath(guiAppInst->applicationDirPath() + "/qml");
#if defined(Q_OS_OSX)
QDir workingDir(guiAppInst->applicationDirPath());
workingDir.cdUp();
workingDir.cdUp();
workingDir.cdUp();
// OSX Development workaround:
m_mainWindowEngine->addImportPath(workingDir.path() + "/qml");
#endif
guiAppInst->addLibraryPath(guiAppInst->applicationDirPath() + "/qml"); guiAppInst->addLibraryPath(guiAppInst->applicationDirPath() + "/qml");
if (m_settings->desktopEnvironment() == Settings::DesktopEnvironment::KDE) { if (m_settings->desktopEnvironment() == Settings::DesktopEnvironment::KDE) {

View File

@ -36,8 +36,7 @@ set(QML
qml/Slider.qml qml/Slider.qml
qml/Tag.qml qml/Tag.qml
qml/TagSelector.qml qml/TagSelector.qml
qml/TextField.qml qml/TextField.qml)
qml/TrayIcon.qml)
set(SOURCES set(SOURCES
# cmake-format: sort # cmake-format: sort

View File

@ -17,14 +17,10 @@ ScreenPlay::WallpaperExitCode MacWindow::start()
connect(m_sdk.get(), &ScreenPlaySDK::sdkDisconnected, this, &MacWindow::destroyThis); connect(m_sdk.get(), &ScreenPlaySDK::sdkDisconnected, this, &MacWindow::destroyThis);
} }
QDir workingDir(QGuiApplication::instance()->applicationDirPath());
workingDir.cdUp();
workingDir.cdUp();
workingDir.cdUp();
// OSX Development workaround: // OSX Development workaround:
// This folder needs then to be copied into the .app/Contents/MacOS/ // This folder needs then to be copied into the .app/Contents/MacOS/
// for the deploy version. // for the deploy version.
m_window.engine()->addImportPath(workingDir.path() + "/qml"); m_window.engine()->addImportPath(QGuiApplication::instance()->applicationDirPath()+ "/qml");
// WARNING: Setting Window flags must be called *here*! // WARNING: Setting Window flags must be called *here*!
Qt::WindowFlags flags = m_window.flags(); Qt::WindowFlags flags = m_window.flags();

View File

@ -11,15 +11,15 @@ import defines
from typing import Tuple from typing import Tuple
from shutil import copytree from shutil import copytree
from pathlib import Path from pathlib import Path
from util import sha256, cd_repo_root_path, zipdir, run, get_vs_env_dict from macos_lipo import run_lipo, check_fat_binary
import macos_sign
from util import sha256, cd_repo_root_path,repo_root_path, zipdir, run, get_vs_env_dict
from sys import stdout from sys import stdout
stdout.reconfigure(encoding='utf-8') stdout.reconfigure(encoding='utf-8')
def clean_build_dir(build_dir): def clean_build_dir(build_dir):
if isinstance(build_dir, str):
build_dir = Path(build_dir)
if build_dir.exists(): if build_dir.exists():
print(f"Remove previous build folder: {build_dir}") print(f"Remove previous build folder: {build_dir}")
# ignore_errors removes also not empty folders... # ignore_errors removes also not empty folders...
@ -49,6 +49,7 @@ class BuildConfig:
cmake_osx_architectures: str cmake_osx_architectures: str
cmake_target_triplet: str cmake_target_triplet: str
package: bool package: bool
osx_bundle: str
package_command: str package_command: str
executable_file_ending: str executable_file_ending: str
# qt_* use either aqt or from the maintenance tool # qt_* use either aqt or from the maintenance tool
@ -71,6 +72,7 @@ class BuildConfig:
build_type: str build_type: str
build_architecture: str build_architecture: str
create_installer: str create_installer: str
sign_osx: bool
def execute( def execute(
@ -100,7 +102,38 @@ def execute(
step_time = time.time() step_time = time.time()
build_result = build(build_config, build_result) build_result = build(build_config, build_result)
build_duration = time.time() - step_time build_duration = time.time() - step_time
print(f"⏱️ build_duration: {build_duration}s") print(f"⏱️ build_duration (for {build_config.build_architecture}): {build_duration}s")
if platform.system() == "Darwin":
# Swap the architecture for the second build
if build_config.build_architecture == "arm64":
build_config.build_architecture = "x64"
else:
build_config.build_architecture = "arm64"
# Make sure the script is always started from the same folder
build_config.root_path = cd_repo_root_path()
build_result = BuildResult()
# Sets all platform spesific paths, arguments etc.
setup_tuple = setup(build_config, build_result)
build_config = setup_tuple[0]
build_result = setup_tuple[1]
build_result.build = Path(build_config.build_folder)
build_result.bin = Path(build_config.bin_dir)
# Make sure to always delete everything first.
# 3rd party tools like the crashreporter create local
# temporary files in the build directory.
clean_build_dir(build_config.build_folder)
step_time = time.time()
build_result = build(build_config, build_result)
build_duration = time.time() - step_time
print(f"⏱️ Second build_duration (for {build_config.build_architecture}): {build_duration}s")
# Copies all needed libraries and assets into the bin folder # Copies all needed libraries and assets into the bin folder
step_time = time.time() step_time = time.time()
@ -108,6 +141,7 @@ def execute(
package_duration = time.time() - step_time package_duration = time.time() - step_time
print(f"⏱️ package_duration: {package_duration}s") print(f"⏱️ package_duration: {package_duration}s")
# Creates a Qt InstallerFrameWork (IFW) installer # Creates a Qt InstallerFrameWork (IFW) installer
if build_config.create_installer == "ON": if build_config.create_installer == "ON":
step_time = time.time() step_time = time.time()
@ -162,18 +196,16 @@ def setup(build_config: BuildConfig, build_result: BuildResult) -> Tuple[BuildCo
build_config.aqt_install_tool_packages = "windows desktop tools_ifw" build_config.aqt_install_tool_packages = "windows desktop tools_ifw"
elif platform.system() == "Darwin": elif platform.system() == "Darwin":
if(build_config.build_architecture == "arm64"): # Defalt to arm64
if(build_config.build_architecture == ""):
build_config.cmake_target_triplet = "arm64-osx" build_config.cmake_target_triplet = "arm64-osx"
build_config.cmake_osx_architectures = "-DCMAKE_OSX_ARCHITECTURES=arm64" build_config.cmake_osx_architectures = "-DCMAKE_OSX_ARCHITECTURES=arm64"
elif(build_config.build_architecture == "x64"): elif(build_config.build_architecture == "x64"):
build_config.cmake_target_triplet = "x64-osx" build_config.cmake_target_triplet = "x64-osx"
build_config.cmake_osx_architectures = "-DCMAKE_OSX_ARCHITECTURES=x86_64" build_config.cmake_osx_architectures = "-DCMAKE_OSX_ARCHITECTURES=x86_64"
else:
print("MISSING BUILD ARCH: SET arm64 or x64")
exit(1)
build_config.executable_file_ending = ".app" build_config.executable_file_ending = ".app"
# NO f string we fill it later! # NO f string we fill it later!
build_config.package_command = "{prefix_path}/bin/macdeployqt ScreenPlay.app -qmldir=../../{app}/qml -executable=ScreenPlay.app/Contents/MacOS/{app} -appstore-compliant" #build_config.package_command = "{prefix_path}/bin/macdeployqt ScreenPlay.app -qmldir=../../{app}/qml -executable=ScreenPlay.app/Contents/MacOS/{app} -appstore-compliant -timestamp -hardened-runtime"
build_config.aqt_install_qt_packages = f"mac desktop {build_config.qt_version} clang_64 -m all" build_config.aqt_install_qt_packages = f"mac desktop {build_config.qt_version} clang_64 -m all"
build_config.aqt_install_tool_packages = "mac desktop tools_ifw" build_config.aqt_install_tool_packages = "mac desktop tools_ifw"
@ -239,7 +271,36 @@ def build(build_config: BuildConfig, build_result: BuildResult) -> BuildResult:
def package(build_config: BuildConfig): def package(build_config: BuildConfig):
if platform.system() == "Windows" or platform.system() == "Darwin": if platform.system() == "Darwin":
universal_build_dir = Path(os.path.join(repo_root_path(), "build-universal-osx-release"))
if universal_build_dir.exists():
print(f"Remove previous build folder: {universal_build_dir}")
# ignore_errors removes also not empty folders...
shutil.rmtree(universal_build_dir, ignore_errors=True)
# Make sure to reset to tools path
os.chdir(repo_root_path())
# Create universal (fat) binary
run_lipo()
check_fat_binary()
cmd_raw = "{qt_bin_path}/macdeployqt {build_bin_dir}/ScreenPlay.app -qmldir={repo_root_path}/{app}/qml -executable={build_bin_dir}/ScreenPlay.app/Contents/MacOS/{app} -verbose=1 -appstore-compliant -timestamp -hardened-runtime " # -sign-for-notarization=\"Developer ID Application: Elias Steurer (V887LHYKRH)\"
build_bin_dir = Path(repo_root_path()).joinpath("build-universal-osx-release/bin/")
cwd = Path(repo_root_path()).joinpath("build-universal-osx-release/bin/ScreenPlay.app/Contents/MacOS/")
qt_bin_path = Path(defines.QT_BIN_PATH).resolve()
source_path = Path(repo_root_path()).resolve()
run(cmd=cmd_raw.format(qt_bin_path=qt_bin_path,repo_root_path=source_path, build_bin_dir=build_bin_dir, app="ScreenPlay"), cwd=cwd)
run(cmd=cmd_raw.format(qt_bin_path=qt_bin_path,repo_root_path=source_path, build_bin_dir=build_bin_dir, app="ScreenPlayWallpaper"), cwd=cwd)
run(cmd=cmd_raw.format(qt_bin_path=qt_bin_path,repo_root_path=source_path, build_bin_dir=build_bin_dir, app="ScreenPlayWidget"), cwd=cwd)
if(build_config.sign_osx):
build_config.bin_dir = os.path.join(repo_root_path(),'build-universal-osx-release/bin/')
print(f"Sign binary at: {build_config.bin_dir}")
macos_sign.sign(build_config=build_config)
if platform.system() == "Windows":
print("Executing deploy commands...") print("Executing deploy commands...")
run(build_config.package_command.format( run(build_config.package_command.format(
type=build_config.build_type, type=build_config.build_type,
@ -258,7 +319,8 @@ def package(build_config: BuildConfig):
prefix_path=build_config.qt_bin_path, prefix_path=build_config.qt_bin_path,
app="ScreenPlayWallpaper", app="ScreenPlayWallpaper",
executable_file_ending=build_config.executable_file_ending), cwd=build_config.bin_dir) executable_file_ending=build_config.executable_file_ending), cwd=build_config.bin_dir)
else:
if platform.system() == "Linux":
# Copy all .so files from the qt_bin_path lib folder into bin_dir # Copy all .so files from the qt_bin_path lib folder into bin_dir
qt_lib_path = build_config.qt_bin_path qt_lib_path = build_config.qt_bin_path
for file in qt_lib_path.joinpath("lib").glob("*.so"): for file in qt_lib_path.joinpath("lib").glob("*.so"):
@ -294,13 +356,7 @@ def package(build_config: BuildConfig):
shutil.copy(str(file), str(build_config.bin_dir)) shutil.copy(str(file), str(build_config.bin_dir))
print("Copied %s" % file) print("Copied %s" % file)
# Copy qml dir into all .app/Contents/MacOS/
if platform.system() == "Darwin":
qml_plugins_path = Path.joinpath(build_config.bin_dir, "qml")
copytree(qml_plugins_path, Path.joinpath(
build_config.bin_dir, "ScreenPlay.app/Contents/MacOS/qml"))
print(f"Deleting qml plugins path: {qml_plugins_path}")
shutil.rmtree(qml_plugins_path)
# Some dlls like openssl do no longer get copied automatically. # Some dlls like openssl do no longer get copied automatically.
# Lets just copy all of them into bin. # Lets just copy all of them into bin.
@ -324,14 +380,6 @@ def package(build_config: BuildConfig):
print(f"WORKAROUND: Copy qml folder from: {qt_qml_Qt_plugin_path}, to {qt_qml_Qt_plugin_target_path}") print(f"WORKAROUND: Copy qml folder from: {qt_qml_Qt_plugin_path}, to {qt_qml_Qt_plugin_target_path}")
shutil.copytree(str(qt_qml_Qt_plugin_path), str(qt_qml_Qt_plugin_target_path)) shutil.copytree(str(qt_qml_Qt_plugin_path), str(qt_qml_Qt_plugin_target_path))
if platform.system() == "Darwin":
# ⚠WORKAROUND. REMOVE ME WHEN FIXED:
# https://bugreports.qt.io/browse/QTBUG-110937
qt_bin_path = defines.QT_BIN_PATH
qt_qml_Qt_plugin_path = Path(qt_bin_path).joinpath("./../qml/Qt").resolve()
qt_qml_Qt_plugin_target_path = Path(build_config.bin_dir).joinpath("ScreenPlay.app/Contents/Resources/qml/Qt").resolve()
print(f"WORKAROUND: Copy qml folder from: {qt_qml_Qt_plugin_path}, to {qt_qml_Qt_plugin_target_path}")
shutil.copytree(str(qt_qml_Qt_plugin_path), str(qt_qml_Qt_plugin_target_path))
if not platform.system() == "Darwin": if not platform.system() == "Darwin":
file_endings = [".ninja_deps", ".ninja", ".ninja_log", ".lib", ".a", ".exp", file_endings = [".ninja_deps", ".ninja", ".ninja_log", ".lib", ".a", ".exp",
@ -394,9 +442,11 @@ if __name__ == "__main__":
help="Build tests.") help="Build tests.")
parser.add_argument('-installer', action="store_true", dest="create_installer", parser.add_argument('-installer', action="store_true", dest="create_installer",
help="Create a installer.") help="Create a installer.")
parser.add_argument('-sign_osx', action="store_true", dest="sign_osx", default=False,
help="Signs the executable on macOS. This requires a valid Apple Developer ID set up.")
parser.add_argument('-deploy-version', action="store_true", dest="build_deploy", parser.add_argument('-deploy-version', action="store_true", dest="build_deploy",
help="Create a deploy version of ScreenPlay for sharing with the world. A not deploy version is for local development only!") help="Create a deploy version of ScreenPlay for sharing with the world. A not deploy version is for local development only!")
parser.add_argument('-architecture', action="store", dest="build_architecture", parser.add_argument('-architecture', action="store", dest="build_architecture", default="",
help="Sets the build architecture. Used to build x86 and ARM osx versions. Currently only works with x86_64 and arm64") help="Sets the build architecture. Used to build x86 and ARM osx versions. Currently only works with x86_64 and arm64")
args = parser.parse_args() args = parser.parse_args()
@ -450,5 +500,6 @@ if __name__ == "__main__":
build_config.build_type = build_type build_config.build_type = build_type
build_config.screenplay_version = screenplay_version build_config.screenplay_version = screenplay_version
build_config.build_architecture = args.build_architecture build_config.build_architecture = args.build_architecture
build_config.sign_osx = args.sign_osx
execute(build_config) execute(build_config)

View File

@ -12,7 +12,7 @@ from macos_lipo import run_lipo, check_fat_binary
import platform import platform
import paramiko import paramiko
import defines import defines
from util import sftp_exists from util import sftp_exists, run, repo_root_path
from sys import stdout from sys import stdout
stdout.reconfigure(encoding='utf-8') stdout.reconfigure(encoding='utf-8')
@ -47,36 +47,14 @@ if __name__ == "__main__":
if platform.system() == "Darwin" and not args.skip_build: if platform.system() == "Darwin" and not args.skip_build:
# We do not yet support a standalone osx installer # We do not yet support a standalone osx installer
build_config.create_installer = "OFF" build_config.create_installer = "OFF"
# OSX builds needs to build for x86 and arm
# and also be signed!
# We need to manually package here at the end after # We need to manually package here at the end after
# we run
build_config.package = True build_config.package = True
build_config.sign_osx = True
# Remove old build-universal-osx-release dir that does not automatically # This will build both arm64 and x64 and sign the unversal binary
# deleted because it is not build directly but generated from x64 and arm64
universal_build_dir = Path(os.path.join(root_path, "build-universal-osx-release"))
if universal_build_dir.exists():
print(f"Remove previous build folder: {universal_build_dir}")
# ignore_errors removes also not empty folders...
shutil.rmtree(universal_build_dir, ignore_errors=True)
build_config.build_architecture = "arm64"
build_result = build.execute(build_config) build_result = build.execute(build_config)
build_config.build_architecture = "x64"
build_result = build.execute(build_config)
# Make sure to reset to tools path
os.chdir(root_path)
# Create universal (fat) binary
run_lipo()
check_fat_binary()
build_config.bin_dir = os.path.join(build_config.root_path,'build-universal-osx-release/bin/')
print(f"Change binary dir to: {build_config.bin_dir}")
macos_sign.sign(build_config=build_config)
if platform.system() == "Windows" and not args.skip_build: if platform.system() == "Windows" and not args.skip_build:
build_config.build_architecture = "x64" build_config.build_architecture = "x64"
@ -117,6 +95,10 @@ if __name__ == "__main__":
print("Skip publishing.") print("Skip publishing.")
sys.exit(0) sys.exit(0)
if args.steam_password is None:
print("Steam password is required.")
sys.exit(1)
# Make sure to reset to tools path # Make sure to reset to tools path
os.chdir(tools_path) os.chdir(tools_path)
steam_publish.publish( steam_publish.publish(

View File

@ -9,7 +9,13 @@ stdout.reconfigure(encoding='utf-8')
def sign(build_config: BuildConfig): def sign(build_config: BuildConfig):
print("Run codedesign") print("Run codedesign")
run("codesign --deep -f -s 'Developer ID Application: Elias Steurer (V887LHYKRH)' --timestamp --options 'runtime' -f --entitlements '../../ScreenPlay/entitlements.plist' --deep 'ScreenPlay.app/' ", #run("codesign -f -s 'Developer ID Application: Elias Steurer (V887LHYKRH)' --verbose --force --timestamp --options 'runtime' -f --entitlements '../../ScreenPlay/entitlements.plist' 'ScreenPlay.app/' ",
# cwd=build_config.bin_dir)
# Do not use --deep https://developer.apple.com/forums/thread/129980
# base_sign_command = "codesign -s \"Developer ID Application: Elias Steurer (V887LHYKRH)\" --verbose --force --timestamp --options \"runtime\" \"ScreenPlay.app/Contents/MacOS/{app}\""
# run(base_sign_command.format(app="ffmpeg"), cwd=build_config.bin_dir)
# run(base_sign_command.format(app="ffprobe"), cwd=build_config.bin_dir)
run("codesign --deep -s \"Developer ID Application: Elias Steurer (V887LHYKRH)\" --verbose --force --timestamp --options \"runtime\" --entitlements \"../../ScreenPlay/entitlements.plist\" \"ScreenPlay.app/\"",
cwd=build_config.bin_dir) cwd=build_config.bin_dir)
print("Run codedesign verify") print("Run codedesign verify")

View File

@ -82,6 +82,7 @@ def publish(
tmp_steam_config_dir = os.path.abspath(os.path.join(tools_path,tmp_steam_config_foldername)) tmp_steam_config_dir = os.path.abspath(os.path.join(tools_path,tmp_steam_config_foldername))
if os.path.isdir(tmp_steam_config_dir): if os.path.isdir(tmp_steam_config_dir):
print(f"Deleting tmp config {tmp_steam_config_dir}")
shutil.rmtree(tmp_steam_config_dir) shutil.rmtree(tmp_steam_config_dir)
os.mkdir(tmp_steam_config_dir) os.mkdir(tmp_steam_config_dir)