1
0
mirror of https://gitlab.com/kelteseth/ScreenPlay.git synced 2024-11-25 12:13:00 +01:00

Fix macOS universal signing

This commit is contained in:
Elias Steurer 2022-08-26 15:45:49 +02:00
parent ed59c18f80
commit 73078edee6
10 changed files with 213 additions and 144 deletions

View File

@ -105,6 +105,7 @@ export PATH="~/.local/bin:$PATH"
``` ```
## MacOSX ## MacOSX
1. Install XCode 13+ , open and restart your device.
1. Install [brew](https://brew.sh) that is needed by some third party vcpkg packages. Do not forget to add brew to your path as outlined at the on of the installation! 1. Install [brew](https://brew.sh) that is needed by some third party vcpkg packages. Do not forget to add brew to your path as outlined at the on of the installation!
- `brew install pkg-config git llvm cmake ninja` - `brew install pkg-config git llvm cmake ninja`
1. [Download and install Qt binary installer from qt.io](https://www.qt.io/download-qt-installer) 1. [Download and install Qt binary installer from qt.io](https://www.qt.io/download-qt-installer)

View File

@ -5,21 +5,64 @@
2. Create a app password for distribution outside of the app store 2. Create a app password for distribution outside of the app store
- Go to https://appleid.apple.com/account/manage - Go to https://appleid.apple.com/account/manage
- Call it ScreenPlay and save the password! - Call it ScreenPlay and save the password!
3. Next we need a developer certificate:
- Go to https://developer.apple.com/account/resources/certificates/list
- Click the blue plus sign
- Select `Developer ID Application`
- _This certificate is used to code sign your app for distribution outside of the Mac App Store._
## Adding an existing certificate ## Add a new device
1. Go to https://developer.apple.com/account/resources/certificates/download Based on: https://developer.apple.com/forums/thread/699268
1. Download `Developer ID Application`
2. Add certificate `System` 1. You run Keychain Access and choose Certificate Assistant > Request a Certificate from a Certificate Authority.
1. You run through the workflow as described in Developer [Account Help > Create certificates > Create a certificate signing](https://help.apple.com/developer-account/#/devbfa00fef7) request. This does two things:
- It generates a public / private key pair in your keychain. To see these, run Keychain Access and select “login” on the left and Keys at the top. Look for keys whose names match the Common Name you entered in step 2.
- It prompts you to save a .certSigningRequest file (CSR). This contains a copy of the public key.
1. You upload the CSR file to the [developer web site](https://developer.apple.com/account/resources/certificates/list). Select `Developer ID Application` and upload your new `CertificateSigningRequest.certSigningRequest`.
1. The developer web site issues you a certificate. In human terms this certificate says “Apple certifies that the subject of this certificate holds the private key that matches the public key embedded in this certificate.”
> Note The developer web site sets the subject information in the certificate based on your developer account. It ignores the subject information in the CSR. So, you can enter any information you want in step 2. This is a good way to distinguish between different keys in your keychain. For example, you might set the Common Name field in step 2 to include a unique identifier that allows you to easily identify the public / private key pair generated in step 3.
5. Download the certificate and add it to your keychain.
## Testing
There should be at least one valid identity:
```
security find-identity -p codesigning -v
```
should print:
```
1) xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx "Developer ID Application: Elias Steurer (V887LHYKRH)"
1 valid identities found
```
## 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 (V887LHYKRH)" --options "runtime" "ScreenPlay.app/"` ```
codesign --deep -f -s "Developer ID Application: Elias Steurer (V887LHYKRH)" --options "runtime" "ScreenPlay.app/"
```
## Add App Store Connect API private key:
- [Create Private Key](https://appstoreconnect.apple.com/access/users)
- Save private key as a file, KEY ID, Issuer ID. We need them next:
```
xcrun notarytool store-credentials
```
1. Profile name:
- Profile name: tachiom
2. Path to App Store Connect API private key:
- `/Users/eliassteurer/Documents/AuthKey_xxxxxxx.p8`
3. App Store Connect API Key ID:
- KEY ID at: https://appstoreconnect.apple.com/access/api
4. App Store Connect API Issuer ID:
- USER ID at: https://appstoreconnect.apple.com/access/api
## Get an App-Specific Password
https://stackoverflow.com/questions/56890749/macos-notarize-in-script
```
security add-generic-password -a "kelteseth@gmail.com" -w "xxxx-xxx-xxx-xxx" -s "Developer ID Application: Elias Steurer (V887LHYKRH)"
```
## 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:
@ -32,3 +75,4 @@ Then run it with the
- `-k` command is here the keychain name that contains your password from the app password step above! - `-k` command is here the keychain name that contains your password from the app password step above!
`xcnotary notarize ScreenPlay.app -d yourDeveloperAccountEmail@example.com -k ScreenPlay` `xcnotary notarize ScreenPlay.app -d yourDeveloperAccountEmail@example.com -k ScreenPlay`

View File

@ -5,7 +5,7 @@
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>English</string> <string>English</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string> <string>ScreenPlay</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string></string> <string></string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
@ -17,9 +17,9 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>0.14</string> <string>0.15</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>0.14</string> <string>0.15</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>ScreenPlay</string> <string>ScreenPlay</string>
</dict> </dict>

View File

@ -5,7 +5,7 @@
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>English</string> <string>English</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string> <string>ScreenPlayWallpaper</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string></string> <string></string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
@ -13,15 +13,15 @@
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>${PRODUCT_NAME}</string> <string>ScreenPlayWallpaper</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>ScreenPlayWallpaper</string> <string>ScreenPlayWallpaper</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>0.14</string> <string>0.15</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>0.14</string> <string>0.15</string>
<key>NSUIElement</key> <key>NSUIElement</key>
<string>1</string> <string>1</string>
<key>LSUIElement</key> <key>LSUIElement</key>

View File

@ -5,7 +5,7 @@
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>English</string> <string>English</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string> <string>ScreenPlayWidget</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string></string> <string></string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
@ -13,15 +13,15 @@
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>${PRODUCT_NAME}</string> <string>ScreenPlayWidget</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>ScreenPlayWidget</string> <string>ScreenPlayWidget</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>0.14</string> <string>0.15</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>0.14</string> <string>0.15</string>
<key>NSUIElement</key> <key>NSUIElement</key>
<string>1</string> <string>1</string>
<key>LSUIElement</key> <key>LSUIElement</key>

View File

@ -1,7 +1,6 @@
#!/usr/bin/python3 #!/usr/bin/python3
import platform import platform
import os import os
import subprocess
import platform import platform
import shutil import shutil
import argparse import argparse
@ -10,41 +9,7 @@ import zipfile
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 datetime import datetime from util import sha256, cd_repo_root_path, zipdir, run, get_vs_env_dict
from util import sha256, cd_repo_root_path, zipdir, run
# Based on https://gist.github.com/l2m2/0d3146c53c767841c6ba8c4edbeb4c2c
def get_vs_env_dict():
vcvars: str # We support 2019 or 2022
# Hardcoded VS path
# check if vcvars64.bat is available.
msvc_2019_path = "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat"
msvc_2022_path = "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat"
if Path(msvc_2019_path).exists():
vcvars = msvc_2019_path
# Prefer newer MSVC and override if exists
if Path(msvc_2022_path).exists():
vcvars = msvc_2022_path
if not vcvars:
raise RuntimeError(
"No Visual Studio installation found, only 2019 and 2022 are supported.")
print(f"\n\nLoading MSVC env variables via {vcvars}\n\n")
cmd = [vcvars, '&&', 'set']
popen = subprocess.Popen(
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = popen.communicate()
if popen.wait() != 0:
raise ValueError(stderr.decode("mbcs"))
output = stdout.decode("mbcs").split("\r\n")
return dict((e[0].upper(), e[1]) for e in [p.rstrip().split("=", 1) for p in output] if len(e) == 2)
def clean_build_dir(build_dir): def clean_build_dir(build_dir):
if isinstance(build_dir, str): if isinstance(build_dir, str):
@ -74,6 +39,7 @@ class BuildConfig:
root_path: str root_path: str
cmake_osx_architectures: str cmake_osx_architectures: str
cmake_target_triplet: str cmake_target_triplet: str
package: bool
package_command: str package_command: str
executable_file_ending: str executable_file_ending: str
qt_path: str qt_path: str
@ -89,7 +55,6 @@ class BuildConfig:
executable_file_ending: str executable_file_ending: str
build_folder: str build_folder: str
bin_dir: str bin_dir: str
sign_build: bool
screenplay_version: str screenplay_version: str
# CMake variables need str: "ON" or "OFF" # CMake variables need str: "ON" or "OFF"
build_steam: str build_steam: str
@ -134,10 +99,6 @@ def execute(
if build_config.create_installer == "ON": if build_config.create_installer == "ON":
build_installer(build_config, build_result) build_installer(build_config, build_result)
# Mac needs signed builds for user to run the app
if platform.system() == "Darwin" and build_config.sign_build:
sign(build_config)
# Create a zip file for scoop & chocolatey # Create a zip file for scoop & chocolatey
if platform.system() == "Windows": if platform.system() == "Windows":
build_result = zip(build_config, build_result) build_result = zip(build_config, build_result)
@ -201,7 +162,7 @@ def setup(build_config: BuildConfig, build_result: BuildResult) -> Tuple[BuildCo
build_config.qt_bin_path = build_config.aqt_path.joinpath( build_config.qt_bin_path = build_config.aqt_path.joinpath(
f"{build_config.qt_version}/macos") if build_config.use_aqt else Path(f"~/Qt/{build_config.qt_version}/macos") f"{build_config.qt_version}/macos") if build_config.use_aqt else Path(f"~/Qt/{build_config.qt_version}/macos")
# NO f string we fill it later! # NO f string we fill it later!
build_config.package_command = "{prefix_path}/bin/macdeployqt {app}.app -qmldir=../../{app}/qml -executable={app}.app/Contents/MacOS/{app}" build_config.package_command = "{prefix_path}/bin/macdeployqt {app}.app -qmldir=../../{app}/qml -executable={app}.app/Contents/MacOS/{app} -appstore-compliant"
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"
@ -379,52 +340,6 @@ def build_installer(build_config: BuildConfig, build_result: BuildResult):
print("Running cpack at: ", os.getcwd()) print("Running cpack at: ", os.getcwd())
run("cpack", cwd=build_config.build_folder) run("cpack", cwd=build_config.build_folder)
def sign(build_config: BuildConfig):
run("codesign --deep -f -s \"Developer ID Application: Elias Steurer (V887LHYKRH)\" --timestamp --options \"runtime\" -f --entitlements \"../../ScreenPlay/entitlements.plist\" --deep \"ScreenPlay.app/\"", cwd=build_config.bin_dir)
run("codesign --deep -f -s \"Developer ID Application: Elias Steurer (V887LHYKRH)\" --timestamp --options \"runtime\" -f --deep \"ScreenPlayWallpaper.app/\"", cwd=build_config.bin_dir)
run("codesign --deep -f -s \"Developer ID Application: Elias Steurer (V887LHYKRH)\" --timestamp --options \"runtime\" -f --deep \"ScreenPlayWidget.app/\"", cwd=build_config.bin_dir)
run("codesign --verify --verbose=4 \"ScreenPlay.app/\"", cwd=build_config.bin_dir)
run("codesign --verify --verbose=4 \"ScreenPlayWallpaper.app/\"",
cwd=build_config.bin_dir)
run("codesign --verify --verbose=4 \"ScreenPlayWidget.app/\"",
cwd=build_config.bin_dir)
# TODO: Replace with https://github.com/akeru-inc/xcnotary/issues/22#issuecomment-1179170957
run("xcnotary notarize ScreenPlay.app -d kelteseth@gmail.com -k ScreenPlay",
cwd=build_config.bin_dir),
run("xcnotary notarize ScreenPlayWallpaper.app -d kelteseth@gmail.com -k ScreenPlay",
cwd=build_config.bin_dir),
run("xcnotary notarize ScreenPlayWidget.app -d kelteseth@gmail.com -k ScreenPlay",
cwd=build_config.bin_dir)
run("spctl --assess --verbose \"ScreenPlay.app/\"", cwd=build_config.bin_dir)
run("spctl --assess --verbose \"ScreenPlayWallpaper.app/\"",
cwd=build_config.bin_dir)
run("spctl --assess --verbose \"ScreenPlayWidget.app/\"",
cwd=build_config.bin_dir)
# We also need to sign the installer in osx:
if build_config.create_installer == "ON":
run("codesign --deep -f -s \"Developer ID Application: Elias Steurer (V887LHYKRH)\" --timestamp --options \"runtime\" -f --deep \"ScreenPlay-Installer.dmg/ScreenPlay-Installer.app/Contents/MacOS/ScreenPlay-Installer\"", cwd=build_config.build_folder)
run("codesign --verify --verbose=4 \"ScreenPlay-Installer.dmg/ScreenPlay-Installer.app/Contents/MacOS/ScreenPlay-Installer\"",
cwd=build_config.build_folder)
run("xcnotary notarize ScreenPlay-Installer.dmg/ScreenPlay-Installer.app -d kelteseth@gmail.com -k ScreenPlay",
cwd=build_config.build_folder)
run("spctl --assess --verbose \"ScreenPlay-Installer.dmg/ScreenPlay-Installer.app/\"",
cwd=build_config.build_folder)
run("codesign --deep -f -s \"Developer ID Application: Elias Steurer (V887LHYKRH)\" --timestamp --options \"runtime\" -f --deep \"ScreenPlay-Installer.dmg/\"", cwd=build_config.build_folder)
run("codesign --verify --verbose=4 \"ScreenPlay-Installer.dmg/\"",
cwd=build_config.build_folder)
run("xcnotary notarize ScreenPlay-Installer.dmg -d kelteseth@gmail.com -k ScreenPlay",
cwd=build_config.build_folder)
run("spctl --assess --verbose \"ScreenPlay-Installer.dmg/\"",
cwd=build_config.build_folder)
def zip(build_config: BuildConfig, build_result: BuildResult) -> BuildResult: def zip(build_config: BuildConfig, build_result: BuildResult) -> BuildResult:
zipName = f"ScreenPlay-{build_config.screenplay_version}-{build_config.cmake_target_triplet}-{build_config.build_type}.zip" zipName = f"ScreenPlay-{build_config.screenplay_version}-{build_config.cmake_target_triplet}-{build_config.build_type}.zip"
build_result.build_zip = Path(build_result.build).joinpath(zipName) build_result.build_zip = Path(build_result.build).joinpath(zipName)
@ -465,8 +380,6 @@ if __name__ == "__main__":
help="Build type. This is either debug or release.") help="Build type. This is either debug or release.")
parser.add_argument('-use-aqt', action="store_true", dest="use_aqt", parser.add_argument('-use-aqt', action="store_true", dest="use_aqt",
help="Absolute qt path. If not set the default path is used\Windows: C:\Qt\nLinux & macOS:~/Qt/.") help="Absolute qt path. If not set the default path is used\Windows: C:\Qt\nLinux & macOS:~/Qt/.")
parser.add_argument('-sign', action="store_true", dest="sign_build",
help="Enable if you want to sign the apps. This is macOS only for now.")
parser.add_argument('-steam', action="store_true", dest="build_steam", parser.add_argument('-steam', action="store_true", dest="build_steam",
help="Enable if you want to build the Steam workshop plugin.") help="Enable if you want to build the Steam workshop plugin.")
parser.add_argument('-tests', action="store_true", dest="build_tests", parser.add_argument('-tests', action="store_true", dest="build_tests",
@ -516,10 +429,6 @@ if __name__ == "__main__":
if args.create_installer: if args.create_installer:
create_installer = "ON" create_installer = "ON"
sign_build = False
if args.sign_build:
sign_build = True
if args.use_aqt: if args.use_aqt:
use_aqt = True use_aqt = True
@ -531,7 +440,6 @@ if __name__ == "__main__":
build_config.build_deploy = build_deploy build_config.build_deploy = build_deploy
build_config.create_installer = create_installer build_config.create_installer = create_installer
build_config.build_type = build_type build_config.build_type = build_type
build_config.sign_build = args.sign_build
build_config.use_aqt = use_aqt build_config.use_aqt = use_aqt
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

View File

@ -1,4 +1,7 @@
import steam_publish import steam_publish
import shutil
import sys
import macos_sign
import argparse import argparse
import os import os
import build import build
@ -31,15 +34,25 @@ if __name__ == "__main__":
build_config.build_deploy = "ON" build_config.build_deploy = "ON"
build_config.create_installer = "ON" build_config.create_installer = "ON"
build_config.build_type = "release" build_config.build_type = "release"
build_config.sign_build = True
build_config.use_aqt = False build_config.use_aqt = False
if platform.system() == "Darwin": if platform.system() == "Darwin":
# 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 # OSX builds needs to build for x86 and arm
# and also be signed! # and also be signed!
# We need to manually package here at the end after
# we run
build_config.package = True
# Remove old build-universal-osx-release dir that does not automatically
# 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_config.build_architecture = "arm64"
build_result = build.execute(build_config) build_result = build.execute(build_config)
@ -52,6 +65,10 @@ if __name__ == "__main__":
# Create universal (fat) binary # Create universal (fat) binary
run_lipo() run_lipo()
check_fat_binary() 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)
else: else:
build_config.build_architecture = "x64" build_config.build_architecture = "x64"
build_result = build.execute(build_config) build_result = build.execute(build_config)
@ -74,9 +91,9 @@ if __name__ == "__main__":
# 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(
# 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"
#) )

View File

@ -1,16 +1,11 @@
#!/usr/bin/python3 #!/usr/bin/python3
import platform from distutils.dir_util import mkpath
import os import os
import subprocess
import shutil import shutil
import argparse import pathlib
import time
import zipfile
from shutil import copytree
from pathlib import Path from pathlib import Path
from concurrent.futures import ThreadPoolExecutor from util import run, run_and_capture_output, cd_repo_root_path
from datetime import datetime import warnings
from util import run, run_and_capture_output
def listfiles(path): def listfiles(path):
files = [] files = []
@ -24,18 +19,19 @@ def listfiles(path):
file = path + os.path.join(dir, fname) file = path + os.path.join(dir, fname)
if(os.path.isfile(file)): if(os.path.isfile(file)):
files.append(file) files.append(file)
if os.path.islink(file):
print(f"Warning: file {file} is a symlink!")
print("Symlink target: ", os.readlink(file))
return files return files
def run_lipo(): # Merges x64 and arm64 build into universal
# Make sure the script is always started from the same folder def run_lipo() :
root_path = Path.cwd() root_path = cd_repo_root_path()
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/")) , # Looks like it is ok the contain symlinks otherwise we get these errors for qml plugins:
str(Path.joinpath(root_path, "build-universal-osx-release/bin/")) ) # bundle format is ambiguous (could be app or framework)
# https://bugreports.qt.io/browse/QTBUG-101338
run("cp -a build-arm64-osx-release build-universal-osx-release",root_path)
apps = ["ScreenPlay","ScreenPlayWallpaper", "ScreenPlayWidget"] apps = ["ScreenPlay","ScreenPlayWallpaper", "ScreenPlayWidget"]
for app in apps: for app in apps:

72
Tools/macos_sign.py Normal file
View File

@ -0,0 +1,72 @@
#!/usr/bin/python3
import platform
import os
from build import BuildConfig
from util import run
def sign(build_config: BuildConfig):
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/\"",
cwd=build_config.bin_dir)
run("codesign --deep -f -s \"Developer ID Application: Elias Steurer (V887LHYKRH)\" --timestamp --options \"runtime\" -f --deep \"ScreenPlayWallpaper.app/\"",
cwd=build_config.bin_dir)
run("codesign --deep -f -s \"Developer ID Application: Elias Steurer (V887LHYKRH)\" --timestamp --options \"runtime\" -f --deep \"ScreenPlayWidget.app/\"",
cwd=build_config.bin_dir)
print("Run codedesign verify")
run("codesign --verify --verbose=4 \"ScreenPlay.app/\"",
cwd=build_config.bin_dir)
run("codesign --verify --verbose=4 \"ScreenPlayWallpaper.app/\"",
cwd=build_config.bin_dir)
run("codesign --verify --verbose=4 \"ScreenPlayWidget.app/\"",
cwd=build_config.bin_dir)
# TODO: Replace with https://github.com/akeru-inc/xcnotary/issues/22#issuecomment-1179170957
# ditto -c -k --keepParent "ScreenPlay.app" "ScreenPlay.app.zip"
# Note the profile is the one name of the first step of (App Store Connect API) in the macOSSigning.md
# xcrun notarytool submit "ScreenPlay.app.zip" --keychain-profile "ScreenPlay" --wait
# xcrun stapler staple "ScreenPlay.app"
print("Packing .apps for upload")
run("ditto -c -k --keepParent 'ScreenPlay.app' 'ScreenPlay.app.zip'", cwd=build_config.bin_dir)
run("ditto -c -k --keepParent 'ScreenPlayWallpaper.app' 'ScreenPlayWallpaper.app.zip'", cwd=build_config.bin_dir)
run("ditto -c -k --keepParent 'ScreenPlayWidget.app' 'ScreenPlayWidget.app.zip'", cwd=build_config.bin_dir)
print("Run xcnotary submit")
run("xcrun notarytool submit ScreenPlay.app.zip --keychain-profile 'ScreenPlay' --wait", cwd=build_config.bin_dir)
run("xcrun notarytool submit ScreenPlayWallpaper.app.zip --keychain-profile 'ScreenPlay' --wait", cwd=build_config.bin_dir)
run("xcrun notarytool submit ScreenPlayWidget.app.zip --keychain-profile 'ScreenPlay' --wait", cwd=build_config.bin_dir)
print("Run stapler staple")
run("xcrun stapler staple ScreenPlay.app", cwd=build_config.bin_dir)
run("xcrun stapler staple ScreenPlayWallpaper.app", cwd=build_config.bin_dir)
run("xcrun stapler staple ScreenPlayWidget.app", cwd=build_config.bin_dir)
print("Run spctl assess")
run("spctl --assess --verbose \"ScreenPlay.app/\"", cwd=build_config.bin_dir)
run("spctl --assess --verbose \"ScreenPlayWallpaper.app/\"", cwd=build_config.bin_dir)
run("spctl --assess --verbose \"ScreenPlayWidget.app/\"", cwd=build_config.bin_dir)
print("Remove *.app.zip files.")
run("rm ScreenPlay.app.zip", cwd=build_config.bin_dir)
run("rm ScreenPlayWallpaper.app.zip", cwd=build_config.bin_dir)
run("rm ScreenPlayWidget.app.zip", cwd=build_config.bin_dir)
# We also need to sign the installer in osx:
if build_config.create_installer == "ON":
run("codesign --deep -f -s \"Developer ID Application: Elias Steurer (V887LHYKRH)\" --timestamp --options \"runtime\" -f --deep \"ScreenPlay-Installer.dmg/ScreenPlay-Installer.app/Contents/MacOS/ScreenPlay-Installer\"", cwd=build_config.build_folder)
run("codesign --verify --verbose=4 \"ScreenPlay-Installer.dmg/ScreenPlay-Installer.app/Contents/MacOS/ScreenPlay-Installer\"",
cwd=build_config.build_folder)
run("xcnotary notarize ScreenPlay-Installer.dmg/ScreenPlay-Installer.app -d kelteseth@gmail.com -k ScreenPlay",
cwd=build_config.build_folder)
run("spctl --assess --verbose \"ScreenPlay-Installer.dmg/ScreenPlay-Installer.app/\"",
cwd=build_config.build_folder)
run("codesign --deep -f -s \"Developer ID Application: Elias Steurer (V887LHYKRH)\" --timestamp --options \"runtime\" -f --deep \"ScreenPlay-Installer.dmg/\"", cwd=build_config.build_folder)
run("codesign --verify --verbose=4 \"ScreenPlay-Installer.dmg/\"",
cwd=build_config.build_folder)
run("xcnotary notarize ScreenPlay-Installer.dmg -d kelteseth@gmail.com -k ScreenPlay",
cwd=build_config.build_folder)
run("spctl --assess --verbose \"ScreenPlay-Installer.dmg/\"",
cwd=build_config.build_folder)

View File

@ -5,7 +5,6 @@ from os import chdir
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
import os import os
import subprocess import subprocess
import zipfile
def run(cmd, cwd=Path.cwd()): def run(cmd, cwd=Path.cwd()):
result = subprocess.run(cmd, shell=True, cwd=cwd) result = subprocess.run(cmd, shell=True, cwd=cwd)
@ -52,4 +51,36 @@ def run_io_tasks_in_parallel(tasks):
with ThreadPoolExecutor() as executor: with ThreadPoolExecutor() as executor:
running_tasks = [executor.submit(task) for task in tasks] running_tasks = [executor.submit(task) for task in tasks]
for running_task in running_tasks: for running_task in running_tasks:
running_task.result() running_task.result()
# Based on https://gist.github.com/l2m2/0d3146c53c767841c6ba8c4edbeb4c2c
def get_vs_env_dict():
vcvars: str # We support 2019 or 2022
# Hardcoded VS path
# check if vcvars64.bat is available.
msvc_2019_path = "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat"
msvc_2022_path = "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat"
if Path(msvc_2019_path).exists():
vcvars = msvc_2019_path
# Prefer newer MSVC and override if exists
if Path(msvc_2022_path).exists():
vcvars = msvc_2022_path
if not vcvars:
raise RuntimeError(
"No Visual Studio installation found, only 2019 and 2022 are supported.")
print(f"\n\nLoading MSVC env variables via {vcvars}\n\n")
cmd = [vcvars, '&&', 'set']
popen = subprocess.Popen(
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = popen.communicate()
if popen.wait() != 0:
raise ValueError(stderr.decode("mbcs"))
output = stdout.decode("mbcs").split("\r\n")
return dict((e[0].upper(), e[1]) for e in [p.rstrip().split("=", 1) for p in output] if len(e) == 2)