mirror of
https://gitlab.com/kelteseth/ScreenPlay.git
synced 2024-11-22 10:42:29 +01:00
Fix macOS universal signing
This commit is contained in:
parent
ed59c18f80
commit
73078edee6
@ -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)
|
||||||
|
@ -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`
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
@ -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,16 +34,26 @@ 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"
|
||||||
#)
|
)
|
||||||
|
@ -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
72
Tools/macos_sign.py
Normal 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)
|
||||||
|
|
@ -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)
|
||||||
@ -53,3 +52,35 @@ def run_io_tasks_in_parallel(tasks):
|
|||||||
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)
|
||||||
|
Loading…
Reference in New Issue
Block a user