summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMicah Lee <micah@micahflee.com>2022-01-13 15:13:03 -0800
committerMicah Lee <micah@micahflee.com>2022-01-13 15:13:03 -0800
commitfde9ac5628db0f809f1de9e27e58b4400d517b30 (patch)
treec8d8f0d307bcc8227b05c6425ee2869df57d1d75
parent78e8c4fa3651cc60bdcb2660e8c5b5b4509b4767 (diff)
downloadonionshare-fde9ac5628db0f809f1de9e27e58b4400d517b30.tar.gz
onionshare-fde9ac5628db0f809f1de9e27e58b4400d517b30.zip
Finish packaging and code signing for Mac
-rw-r--r--RELEASE.md10
-rwxr-xr-xdesktop/package/build-mac.py291
-rw-r--r--desktop/setup-freeze.py5
3 files changed, 297 insertions, 9 deletions
diff --git a/RELEASE.md b/RELEASE.md
index 209b611b..23e033f0 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -121,18 +121,18 @@ Set up the development environment described in `README.md`.
Then build an executable, make it a macOS app bundle, and package it in a dmg:
```sh
-poetry run python setup-freeze.py bdist_dmg
+poetry run ./package/build-mac.py
```
-The will create `build/OnionShare.dmg`.
+The will create `dist/OnionShare-$VERSION.dmg`.
Now, notarize the release. You must have an app-specific Apple ID password saved in the login keychain called `onionshare-notarize`.
-- Notarize it: `xcrun altool --notarize-app --primary-bundle-id "com.micahflee.onionshare" -u "micah@micahflee.com" -p "@keychain:onionshare-notarize" --file build/OnionShare.dmg`
+- Notarize it: `xcrun altool --notarize-app --primary-bundle-id "com.micahflee.onionshare" -u "micah@micahflee.com" -p "@keychain:onionshare-notarize" --file dist/OnionShare-$VERSION.dmg`
- Wait for it to get approved, check status with: `xcrun altool --notarization-history 0 -u "micah@micahflee.com" -p "@keychain:onionshare-notarize"`
-- After it's approved, staple the ticket: `xcrun stapler staple build/OnionShare.dmg`
+- After it's approved, staple the ticket: `xcrun stapler staple dist/OnionShare-$VERSION.dmg`
-This will create `desktop/build/OnionShare.dmg`, signed and notarized.
+This will create `desktop/dist/OnionShare-$VERSION.dmg`, signed and notarized.
## Source package
diff --git a/desktop/package/build-mac.py b/desktop/package/build-mac.py
new file mode 100755
index 00000000..7d08e9b3
--- /dev/null
+++ b/desktop/package/build-mac.py
@@ -0,0 +1,291 @@
+#!/usr/bin/env python3
+import os
+import inspect
+import subprocess
+import shutil
+import itertools
+import glob
+
+root = os.path.dirname(
+ os.path.dirname(
+ os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
+ )
+)
+
+
+def run(cmd, cwd=None, error_ok=False):
+ print(cmd)
+ subprocess.run(cmd, cwd=cwd, check=True)
+
+
+def get_size(dir):
+ size = 0
+ for path, dirs, files in os.walk(dir):
+ for f in files:
+ fp = os.path.join(path, f)
+ size += os.path.getsize(fp)
+ return size
+
+
+def codesign(path, entitlements, identity):
+ run(
+ [
+ "codesign",
+ "--sign",
+ identity,
+ "--entitlements",
+ str(entitlements),
+ "--timestamp",
+ "--deep",
+ str(path),
+ "--force",
+ "--options",
+ "runtime,library",
+ ]
+ )
+
+
+def main():
+ desktop_dir = os.path.join(root, "desktop")
+
+ print("○ Clean up from last build")
+ if os.path.exists(os.path.join(desktop_dir, "build")):
+ shutil.rmtree(os.path.join(desktop_dir, "build"))
+ if os.path.exists(os.path.join(desktop_dir, "dist")):
+ shutil.rmtree(os.path.join(desktop_dir, "dist"))
+
+ print("○ Building binaries")
+ run(
+ [
+ shutil.which("python"),
+ "setup-freeze.py",
+ "bdist_mac",
+ ],
+ desktop_dir,
+ )
+ before_size = get_size(
+ os.path.join(desktop_dir, "build", "OnionShare.app")
+ )
+
+ print("○ Delete unused PySide2 stuff to save space")
+ for dirname in [
+ "PySide2/Designer.app",
+ "PySide2/examples",
+ "PySide2/glue",
+ "PySide2/Qt/qml",
+ "shiboken2/files.dir",
+ ]:
+ shutil.rmtree(
+ os.path.join(
+ desktop_dir,
+ "build",
+ "OnionShare.app",
+ "Contents",
+ "MacOS",
+ "lib",
+ dirname,
+ )
+ )
+ shutil.rmtree(
+ os.path.join(
+ desktop_dir,
+ "build",
+ "OnionShare.app",
+ "Contents",
+ "MacOS",
+ "lib",
+ "shiboken2",
+ "docs",
+ )
+ )
+ for framework in [
+ "Qt3DAnimation",
+ "Qt3DCore",
+ "Qt3DExtras",
+ "Qt3DInput",
+ "Qt3DLogic",
+ "Qt3DQuick",
+ "Qt3DQuickAnimation",
+ "Qt3DQuickExtras",
+ "Qt3DQuickInput",
+ "Qt3DQuickRender",
+ "Qt3DQuickScene2D",
+ "Qt3DRender",
+ "QtBluetooth",
+ "QtBodymovin",
+ "QtCharts",
+ "QtConcurrent",
+ "QtDataVisualization",
+ "QtDesigner",
+ "QtDesignerComponents",
+ "QtGamepad",
+ "QtHelp",
+ "QtLocation",
+ "QtMultimedia",
+ "QtMultimediaQuick",
+ "QtMultimediaWidgets",
+ "QtNfc",
+ "QtOpenGL",
+ "QtPdf",
+ "QtPdfWidgets",
+ "QtPositioning",
+ "QtPositioningQuick",
+ "QtPurchasing",
+ "QtQml",
+ "QtQuick",
+ "QtQuick3D",
+ "QtQuick3DAssetImport",
+ "QtQuick3DRender",
+ "QtQuick3DRuntimeRender",
+ "QtQuick3DUtils",
+ "QtQuickControls2",
+ "QtQuickParticles",
+ "QtQuickShapes",
+ "QtQuickTemplates2",
+ "QtQuickTest",
+ "QtQuickWidgets",
+ "QtRemoteObjects",
+ "QtRepParser",
+ "QtScript",
+ "QtScriptTools",
+ "QtScxml",
+ "QtSensors",
+ "QtSerialBus",
+ "QtSerialPort",
+ "QtSql",
+ "QtSvg",
+ "QtTest",
+ "QtTextToSpeech",
+ "QtUiPlugin",
+ "QtVirtualKeyboard",
+ "QtWebChannel",
+ "QtWebEngine",
+ "QtWebEngineCore",
+ "QtWebEngineWidgets",
+ "QtWebSockets",
+ "QtWebView",
+ "QtXml",
+ "QtXmlPatterns",
+ ]:
+ shutil.rmtree(
+ os.path.join(
+ desktop_dir,
+ "build",
+ "OnionShare.app",
+ "Contents",
+ "MacOS",
+ "lib",
+ "PySide2",
+ "Qt",
+ "lib",
+ f"{framework}.framework",
+ )
+ )
+ try:
+ os.remove(
+ os.path.join(
+ desktop_dir,
+ "build",
+ "OnionShare.app",
+ "Contents",
+ "MacOS",
+ "lib",
+ "PySide2",
+ f"{framework}.abi3.so",
+ )
+ )
+ os.remove(
+ os.path.join(
+ desktop_dir,
+ "build",
+ "OnionShare.app",
+ "Contents",
+ "MacOS",
+ "lib",
+ "PySide2",
+ f"{framework}.pyi",
+ )
+ )
+ except FileNotFoundError:
+ pass
+
+ after_size = get_size(
+ os.path.join(desktop_dir, "build", "OnionShare.app")
+ )
+ freed_bytes = before_size - after_size
+ freed_mb = int(freed_bytes / 1024 / 1024)
+ print(f"○ Freed {freed_mb} mb")
+
+ print("○ Sign app bundle")
+ identity_name_application = "Developer ID Application: Micah Lee (N9B95FDWH4)"
+ entitlements_plist_path = os.path.join(desktop_dir, "package", "Entitlements.plist")
+
+ for path in itertools.chain(
+ glob.glob(
+ f"{desktop_dir}/build/OnionShare.app/Contents/MacOS/**/*.dylib",
+ recursive=True,
+ ),
+ glob.glob(
+ f"{desktop_dir}/build/OnionShare.app/Contents/MacOS/**/*.so", recursive=True
+ ),
+ [
+ f"{desktop_dir}/build/OnionShare.app/Contents/MacOS/lib/PySide2/pyside2-lupdate",
+ f"{desktop_dir}/build/OnionShare.app/Contents/MacOS/lib/PySide2/rcc",
+ f"{desktop_dir}/build/OnionShare.app/Contents/MacOS/lib/PySide2/uic",
+ ],
+ ):
+ codesign(path, entitlements_plist_path, identity_name_application)
+ codesign(
+ f"{desktop_dir}/build/OnionShare.app",
+ entitlements_plist_path,
+ identity_name_application,
+ )
+ print(f"○ Signed app bundle: {desktop_dir}/build/OnionShare.app")
+
+ if not os.path.exists("/usr/local/bin/create-dmg"):
+ print("○ Error: create-dmg is not installed")
+ return
+
+ print("○ Create DMG")
+ version_filename = os.path.join(
+ root, "cli", "onionshare_cli", "resources", "version.txt"
+ )
+ with open(version_filename) as f:
+ version = f.read().strip()
+
+ os.makedirs(os.path.join(desktop_dir, "dist"), exist_ok=True)
+ dmg_path = os.path.join(desktop_dir, "dist", f"OnionShare-{version}.dmg")
+ run(
+ [
+ "create-dmg",
+ "--volname",
+ "OnionShare",
+ "--volicon",
+ os.path.join(
+ desktop_dir, "onionshare", "resources", "onionshare.icns"
+ ),
+ "--window-size",
+ "400",
+ "200",
+ "--icon-size",
+ "100",
+ "--icon",
+ "OnionShare.app",
+ "100",
+ "70",
+ "--hide-extension",
+ "OnionShare.app",
+ "--app-drop-link",
+ "300",
+ "70",
+ dmg_path,
+ f"{desktop_dir}/build/OnionShare.app",
+ "--identity",
+ identity_name_application,
+ ]
+ )
+
+ print(f"○ Finished building DMG: {dmg_path}")
+
+if __name__ == "__main__":
+ main()
diff --git a/desktop/setup-freeze.py b/desktop/setup-freeze.py
index 14b05a7e..6026a9cd 100644
--- a/desktop/setup-freeze.py
+++ b/desktop/setup-freeze.py
@@ -214,10 +214,7 @@ setup(
# bdist_mac, making the macOS app bundle
"bdist_mac": {
"iconfile": os.path.join("onionshare", "resources", "onionshare.icns"),
- "bundle_name": "OnionShare",
- "codesign_identity": "Developer ID Application: Micah Lee (N9B95FDWH4)",
- "codesign_entitlements": os.path.join("package", "Entitlements.plist"),
- "codesign_deep": True,
+ "bundle_name": "OnionShare"
},
},
executables=[