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

Update macos build scripts

This commit is contained in:
Elias Steurer 2022-07-22 13:21:30 +02:00
parent 376e96f96c
commit 3a917c18c4
7 changed files with 198 additions and 59 deletions

View File

@ -11,10 +11,15 @@
- Select `Developer ID Application` - Select `Developer ID Application`
- _This certificate is used to code sign your app for distribution outside of the Mac App Store._ - _This certificate is used to code sign your app for distribution outside of the Mac App Store._
## Adding an existing certificate
1. Go to https://developer.apple.com/account/resources/certificates/download
1. Download `Developer ID Application`
2. Add certificate `System`
## Sign the app locally with codesign ## Sign the app locally with codesign
We need to sign every single file in the .app file. For this we use the name from the installed cert. This can be copied from the `Keychain Access.app`. We need to sign every single file in the .app file. For this we use the name from the installed cert. This can be copied from the `Keychain Access.app`.
`codesign --deep -f -s "Developer ID Application: Elias Steurer (AAABCXYZAA)" --options "runtime" "ScreenPlay.app/"` `codesign --deep -f -s "Developer ID Application: Elias Steurer (V887LHYKRH)" --options "runtime" "ScreenPlay.app/"`
## Upload to apple for notization ## Upload to apple for notization
We use [xcnotary](https://github.com/akeru-inc/xcnotary) tools for fast automatic upload. Install it via brew: We use [xcnotary](https://github.com/akeru-inc/xcnotary) tools for fast automatic upload. Install it via brew:

View File

@ -110,6 +110,7 @@ def build(
deploy_command: str = "" deploy_command: str = ""
executable_file_ending: str = "" executable_file_ending: str = ""
qt_path: str = "" qt_path: str = ""
qt_bin_path: str = ""
aqt_install_qt_packages: str = "" aqt_install_qt_packages: str = ""
aqt_install_tool_packages: str = "" aqt_install_tool_packages: str = ""
cmake_target_triplet: str = "" cmake_target_triplet: str = ""
@ -120,11 +121,12 @@ def build(
cmake_target_triplet = "x64-windows" cmake_target_triplet = "x64-windows"
windows_msvc = "msvc2019_64" windows_msvc = "msvc2019_64"
executable_file_ending = ".exe" executable_file_ending = ".exe"
qt_path = aqt_path.joinpath(qt_version).joinpath( qt_path = aqt_path if use_aqt else Path("C:/Qt")
qt_bin_path = aqt_path.joinpath(qt_version).joinpath(
windows_msvc) if use_aqt else Path(f"C:/Qt/{qt_version}/{windows_msvc}") windows_msvc) if use_aqt else Path(f"C:/Qt/{qt_version}/{windows_msvc}")
vs_env_dict = get_vs_env_dict() vs_env_dict = get_vs_env_dict()
vs_env_dict["PATH"] = vs_env_dict["PATH"] + \ vs_env_dict["PATH"] = vs_env_dict["PATH"] + \
";" + str(qt_path) + "\\bin" ";" + str(qt_bin_path) + "\\bin"
os.environ.update(vs_env_dict) os.environ.update(vs_env_dict)
deploy_command = "windeployqt.exe --{type} --qmldir ../../{app}/qml {app}{executable_file_ending}" deploy_command = "windeployqt.exe --{type} --qmldir ../../{app}/qml {app}{executable_file_ending}"
@ -134,10 +136,13 @@ def build(
elif platform.system() == "Darwin": elif platform.system() == "Darwin":
if(build_architecture == "arm64"): if(build_architecture == "arm64"):
cmake_target_triplet = "arm64-osx" cmake_target_triplet = "arm64-osx"
else: elif(build_architecture == "x64"):
cmake_target_triplet = "x64-osx" cmake_target_triplet = "x64-osx"
else:
qt_path = aqt_path.joinpath( print("MISSING BUILD ARCH: SET arm64 or x64")
exit(1)
qt_path = aqt_path if use_aqt else Path("~/Qt/")
qt_bin_path = aqt_path.joinpath(
f"{qt_version}/macos") if use_aqt else Path(f"~/Qt/{qt_version}/macos") f"{qt_version}/macos") if use_aqt else Path(f"~/Qt/{qt_version}/macos")
deploy_command = "{prefix_path}/bin/macdeployqt {app}.app -qmldir=../../{app}/qml -executable={app}.app/Contents/MacOS/{app}" deploy_command = "{prefix_path}/bin/macdeployqt {app}.app -qmldir=../../{app}/qml -executable={app}.app/Contents/MacOS/{app}"
@ -146,7 +151,8 @@ def build(
elif platform.system() == "Linux": elif platform.system() == "Linux":
cmake_target_triplet = "x64-linux" cmake_target_triplet = "x64-linux"
qt_path = aqt_path.joinpath( qt_path = aqt_path if use_aqt else Path("~/Qt/")
qt_bin_path = aqt_path.joinpath(
f"{qt_version}/gcc_64") if use_aqt else Path(f"~/Qt/{qt_version}/gcc_64") f"{qt_version}/gcc_64") if use_aqt else Path(f"~/Qt/{qt_version}/gcc_64")
aqt_install_qt_packages = f"linux desktop {qt_version} gcc_64 -m all" aqt_install_qt_packages = f"linux desktop {qt_version} gcc_64 -m all"
aqt_install_tool_packages = "linux desktop tools_ifw" aqt_install_tool_packages = "linux desktop tools_ifw"
@ -155,7 +161,7 @@ def build(
else: else:
print("cqtdeployer not available, build may be incomplete and incompatible with some distro (typically Ubuntu)") print("cqtdeployer not available, build may be incomplete and incompatible with some distro (typically Ubuntu)")
home_path = str(Path.home()) home_path = str(Path.home())
qt_path = aqt_path.joinpath( qt_bin_path = aqt_path.joinpath(
f"{qt_version}/gcc_64") if use_aqt else Path(f"{home_path}/Qt/{qt_version}/gcc_64") f"{qt_version}/gcc_64") if use_aqt else Path(f"{home_path}/Qt/{qt_version}/gcc_64")
else: else:
raise NotImplementedError( raise NotImplementedError(
@ -163,7 +169,7 @@ def build(
# Default to QtMaintainance installation. # Default to QtMaintainance installation.
if use_aqt: if use_aqt:
print(f"qt_path: {qt_path}.") print(f"qt_bin_path: {qt_bin_path}.")
if not Path(aqt_path).exists(): if not Path(aqt_path).exists():
print( print(
f"aqt path does not exist at {aqt_path}. Installing now into...") f"aqt path does not exist at {aqt_path}. Installing now into...")
@ -173,11 +179,18 @@ def build(
# Prepare # Prepare
cmake_toolchain_file = f"'{root_path}/../ScreenPlay-vcpkg/scripts/buildsystems/vcpkg.cmake'" cmake_toolchain_file = f"'{root_path}/../ScreenPlay-vcpkg/scripts/buildsystems/vcpkg.cmake'"
ifw_root_path = f"{qt_path}\\Tools\\QtInstallerFramework\\{qt_ifw_version}" ifw_root_path = f"{qt_path}/Tools/QtInstallerFramework/{qt_ifw_version}"
print(f"cmake_toolchain_file: {cmake_toolchain_file}") print(f"cmake_toolchain_file: {cmake_toolchain_file}")
print( print(
f"Starting build with type {build_type}. Qt Version: {qt_version}. Root path: {root_path}") f"Starting build with type {build_type}. Qt Version: {qt_version}. Root path: {root_path}")
# Remove old build folder to before configuring to get rid of
# all cmake chaches
build_folder = root_path.joinpath(
f"build-{cmake_target_triplet}-{build_type}")
clean_build_dir(build_folder)
CMAKE_OSX_ARCHITECTURES: str = "" CMAKE_OSX_ARCHITECTURES: str = ""
# The entire parameter should be optional. We need this to explicity build # The entire parameter should be optional. We need this to explicity build
# x84 and arm version seperat, only because we cannot compile two at once with vcpkg # x84 and arm version seperat, only because we cannot compile two at once with vcpkg
@ -186,7 +199,7 @@ def build(
cmake_configure_command = f'cmake ../ \ cmake_configure_command = f'cmake ../ \
{CMAKE_OSX_ARCHITECTURES} \ {CMAKE_OSX_ARCHITECTURES} \
-DCMAKE_PREFIX_PATH={qt_path} \ -DCMAKE_PREFIX_PATH={qt_bin_path} \
-DCMAKE_BUILD_TYPE={build_type} \ -DCMAKE_BUILD_TYPE={build_type} \
-DVCPKG_TARGET_TRIPLET={cmake_target_triplet} \ -DVCPKG_TARGET_TRIPLET={cmake_target_triplet} \
-DCMAKE_TOOLCHAIN_FILE={cmake_toolchain_file} \ -DCMAKE_TOOLCHAIN_FILE={cmake_toolchain_file} \
@ -198,9 +211,6 @@ def build(
-G "CodeBlocks - Ninja" \ -G "CodeBlocks - Ninja" \
-B.' -B.'
build_folder = root_path.joinpath(
f"build-{cmake_target_triplet}-{build_type}")
clean_build_dir(build_folder)
# Build # Build
start_time = time.time() start_time = time.time()
@ -215,56 +225,56 @@ def build(
print("Executing deploy commands...") print("Executing deploy commands...")
run(deploy_command.format( run(deploy_command.format(
type=build_type, type=build_type,
prefix_path=qt_path, prefix_path=qt_bin_path,
app="ScreenPlay", app="ScreenPlay",
executable_file_ending=executable_file_ending), cwd=bin_dir) executable_file_ending=executable_file_ending), cwd=bin_dir)
run(deploy_command.format( run(deploy_command.format(
type=build_type, type=build_type,
prefix_path=qt_path, prefix_path=qt_bin_path,
app="ScreenPlayWidget", app="ScreenPlayWidget",
executable_file_ending=executable_file_ending), cwd=bin_dir) executable_file_ending=executable_file_ending), cwd=bin_dir)
run(deploy_command.format( run(deploy_command.format(
type=build_type, type=build_type,
prefix_path=qt_path, prefix_path=qt_bin_path,
app="ScreenPlayWallpaper", app="ScreenPlayWallpaper",
executable_file_ending=executable_file_ending), cwd=bin_dir) executable_file_ending=executable_file_ending), cwd=bin_dir)
else: else:
# just copy the folders and be done with it # just copy the folders and be done with it
if platform.system() == "Linux": if platform.system() == "Linux":
# Copy all .so files from the qt_path lib folder into bin_dir # Copy all .so files from the qt_bin_path lib folder into bin_dir
qt_lib_path = qt_path qt_lib_path = qt_bin_path
for file in qt_lib_path.joinpath("lib").glob("*.so"): for file in qt_lib_path.joinpath("lib").glob("*.so"):
shutil.copy(str(file), str(bin_dir)) shutil.copy(str(file), str(bin_dir))
# Copy qt_qml_path folder content into bin_dir # Copy qt_qml_path folder content into bin_dir
qt_qml_path = qt_path qt_qml_path = qt_bin_path
for folder in qt_qml_path.joinpath("qml").iterdir(): for folder in qt_qml_path.joinpath("qml").iterdir():
if not folder.is_file(): if not folder.is_file():
shutil.copytree(str(folder), str( shutil.copytree(str(folder), str(
bin_dir.joinpath(folder.name))) bin_dir.joinpath(folder.name)))
print("Copied %s" % folder) print("Copied %s" % folder)
# Copy all plugin folder from qt_path plugins subfolder into bin_dir # Copy all plugin folder from qt_bin_path plugins subfolder into bin_dir
qt_plugins_path = qt_path qt_plugins_path = qt_bin_path
for folder in qt_path.joinpath("plugins").iterdir(): for folder in qt_bin_path.joinpath("plugins").iterdir():
if not folder.is_file(): if not folder.is_file():
shutil.copytree(str(folder), str( shutil.copytree(str(folder), str(
bin_dir.joinpath(folder.name))) bin_dir.joinpath(folder.name)))
print("Copied %s" % folder) print("Copied %s" % folder)
# Copy all folder from qt_path translation files into bin_dir translation folder # Copy all folder from qt_bin_path translation files into bin_dir translation folder
qt_translations_path = qt_path qt_translations_path = qt_bin_path
for folder in qt_translations_path.joinpath("translations").iterdir(): for folder in qt_translations_path.joinpath("translations").iterdir():
if not folder.is_file(): if not folder.is_file():
shutil.copytree(str(folder), str( shutil.copytree(str(folder), str(
bin_dir.joinpath("translations").joinpath(folder.name))) bin_dir.joinpath("translations").joinpath(folder.name)))
print("Copied %s" % folder) print("Copied %s" % folder)
# Copy all filesfrom qt_path resources folder into bin_dir folder # Copy all filesfrom qt_bin_path resources folder into bin_dir folder
qt_resources_path = qt_path qt_resources_path = qt_bin_path
for file in qt_path.joinpath("resources").glob("*"): for file in qt_bin_path.joinpath("resources").glob("*"):
shutil.copy(str(file), str(bin_dir)) shutil.copy(str(file), str(bin_dir))
print("Copied %s" % file) print("Copied %s" % file)

View File

@ -1,8 +1,10 @@
import build from build import build
import steam_publish import steam_publish
import argparse import argparse
import os import os
from pathlib import Path from pathlib import Path
from macos_lipo import run_lipo, check_fat_binary
import platform
if __name__ == "__main__": if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Build and Package ScreenPlay') parser = argparse.ArgumentParser(description='Build and Package ScreenPlay')
@ -12,6 +14,12 @@ if __name__ == "__main__":
# Script needs to run in the tools folder # Script needs to run in the tools folder
tools_path = Path.cwd() tools_path = Path.cwd()
os.chdir(tools_path) os.chdir(tools_path)
root_path = tools_path.parent
print(f"Set root directory to: {root_path}")
if platform.system() == "Darwin":
# OSX builds needs to build for x86 and arm
# and also be signed!
build( build(
qt_version="6.4.0", qt_version="6.4.0",
qt_ifw_version="4.4", qt_ifw_version="4.4",
@ -20,13 +28,43 @@ if __name__ == "__main__":
build_release="ON", build_release="ON",
create_installer="ON", create_installer="ON",
build_type="release", build_type="release",
sign_build=True,
use_aqt=False,
build_architecture = "arm64"
)
build(
qt_version="6.4.0",
qt_ifw_version="4.4",
build_steam="ON",
build_tests="OFF",
build_release="ON",
create_installer="OFF",
build_type="release",
sign_build=True,
use_aqt=False,
build_architecture = "x64"
)
# Make sure to reset to tools path
os.chdir(root_path)
# Create universal (fat) binary
run_lipo()
check_fat_binary()
else:
build(
qt_version="6.4.0",
qt_ifw_version="4.4",
build_steam="ON",
build_tests="OFF",
build_release="ON",
create_installer="OFF",
build_type="release",
sign_build=False, sign_build=False,
use_aqt=False use_aqt=False
) )
# Make sure to reset to tools path # Make sure to reset to tools path
os.chdir(tools_path) os.chdir(tools_path)
steam_publish( #steam_publish(
steam_username="tachiom", # steam_username="tachiom",
steam_password=args.steam_password, # steam_password=args.steam_password,
set_live_branch_name="internal" # set_live_branch_name="internal"
) #)

88
Tools/macos_lipo.py Normal file
View File

@ -0,0 +1,88 @@
#!/usr/bin/python3
import platform
import os
import subprocess
import shutil
import argparse
import time
import zipfile
from shutil import copytree
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor
from datetime import datetime
from util import run
def listfiles(path):
files = []
extensions = ('.dylib', '.so','')
ignored = ('qmldir')
print(f"WALK: {path}")
for dirName, subdirList, fileList in os.walk(path):
dir = dirName.replace(path, '')
for fname in fileList:
if Path(fname).suffix in extensions and not fname in ignored:
file = path + os.path.join(dir, fname)
if(os.path.isfile(file)):
print(file)
files.append(file)
return files
def create_fat_binary():
# Make sure the script is always started from the same folder
root_path = Path.cwd()
if root_path.name == "Tools":
root_path = root_path.parent
print(f"Change root directory to: {root_path}")
os.chdir(root_path)
arm64_dir = 'build-arm64-osx-release/bin/ScreenPlay.app'
x64_dir = "build-x64-osx-release/bin/ScreenPlay.app"
arm64_files = listfiles(
str(Path.joinpath(root_path, arm64_dir)))
x64_files = listfiles(str(Path.joinpath(root_path, x64_dir)))
for file in arm64_files:
run(f"lipo -info {file}")
# print(arm64_files)
# print(x64_files)
def run_lipo():
# Make sure the script is always started from the same folder
root_path = Path.cwd()
if root_path.name == "Tools":
root_path = root_path.parent
print(f"Change root directory to: {root_path}")
os.chdir(root_path)
shutil.copytree(str(Path.joinpath(root_path, "build-arm64-osx-release/bin/")) ,
str(Path.joinpath(root_path, "build-universal-osx-release/bin/")) )
apps = ["ScreenPlay","ScreenPlayWallpaper", "ScreenPlayWidget"]
for app in apps:
arm64_dir = str(Path.joinpath(root_path, f"build-arm64-osx-release/bin/{app}.app/Contents/MacOS/{app}"))
x64_dir = str(Path.joinpath(root_path, f"build-x64-osx-release/bin/{app}.app/Contents/MacOS/{app}"))
universal_dir = str(Path.joinpath(root_path, f"build-universal-osx-release/bin/{app}.app/Contents/MacOS/{app}"))
run(f"lipo -create {arm64_dir} {x64_dir} -output {universal_dir}")
run(f"lipo -info {universal_dir}")
def check_fat_binary():
# Make sure the script is always started from the same folder
root_path = Path.cwd()
if root_path.name == "Tools":
root_path = root_path.parent
print(f"Change root directory to: {root_path}")
os.chdir(root_path)
dir = 'build-universal-osx-release/bin/'
files = listfiles(str(Path.joinpath(root_path, dir)))
for file in files:
run(f"lipo -info {file}")
if __name__ == "__main__":
run_lipo()
check_fat_binary()
#create_fat_binary()

View File

@ -5,7 +5,7 @@
// include all files recursively // include all files recursively
"FileMapping" "FileMapping"
{ {
"LocalPath" "build-x64-osx-release/bin/*" "LocalPath" "build-universal-osx-release/bin/*"
"DepotPath" "." "DepotPath" "."
"recursive" "1" "recursive" "1"
} }

View File

@ -1,13 +0,0 @@
"DepotBuildConfig"
{
"DepotID" "672872"
// include all files recursively
"FileMapping"
{
"LocalPath" "build-arm64-osx-release/bin/*"
"DepotPath" "."
"recursive" "1"
}
}

11
Tools/util.py Normal file
View File

@ -0,0 +1,11 @@
from pathlib import Path
import os
import subprocess
def run(cmd, cwd=Path.cwd()):
result = subprocess.run(cmd, shell=True, cwd=cwd)
if result.returncode != 0:
raise RuntimeError(f"Failed to execute {cmd}")