-
@ Chris
2025-03-05 09:53:59How to package a macOS Desktop App
Introduction
Creating and distributing macOS desktop applications is a huge pain in the ass and can be very confusing. I'm writing this article as a reference for myself as well as any other developer who wants to package a desktop app for macOS.
Join the Apple Developer Program
-
Go to developer.apple.com and sign in with your Apple ID
-
Enroll in an individual ($99/year) or organization ($299/year) membership
-
Complete the enrollment process and wait for approval
Setup Xcode for some reason
-
Download Xcode from from the Mac App Store
-
Go to Xcode -> Settings -> Accounts
-
Click the "+" button and add your Apple Developer Account
Check if Xcode Command Line Tools are installed
xcode-select -p
If they are not installed for some reason you can install them with
xcode-select --install
Generate a Certificate Signing Request (CSR)
-
Open Keychain Access
-
Go to Keychain Access > Certificate Assistant > Request a Certificate From a Certificate Authority
-
Enter your email address and a common name (e.g., your name or company name)
-
Leave "CA Email Address" blank, select Saved to disk, and click Continue
-
Save the
.certSigningRequest
file somewhere
Request Certificate
-
Log in to developer.apple.com/account
-
Go to Certificates, Identifiers & Profiles > Certificates
-
Click the + button to add a new certificate
-
Under "Software," select Developer ID Application, then Continue
-
Choose G2 Sub-CA (Xcode 11.4.1 or later)
-
Upload the
.certSigningRequest
file you just created, then Continue -
Download the
.cer
file (e.g.,developerID_application.cer
)
Install the Certificate
-
Double-click the downloaded
.cer
file to add it to your Keychain Access under "My Certificates" -
Verify it’s there with a private key, after selecting the cert look at the top tabs, select "My Certificates" expand the certificate to see the key icon
Sign your Application
You can now try signing your application, if you run into issues check out the troubleshooting section at the bottom of this article.
codesign --deep --force --verify --verbose --sign "Developer ID Application: Your Name (TeamID)" --options=runtime --timestamp /path/to/YourApp.app
Package Your App
Most apps distributed via websites are packaged in a
.dmg
(disk image) for a polished user experience:- Use Disk Utility or a tool like
create-dmg
(install via Homebrew:brew install create-dmg
)
create-dmg --volname "YourApp" --app-drop-link 600 185 --window-pos 200 120 --window-size 800 400 "YourApp.dmg" /path/to/YourApp.app
This will setup the drag and drop thing for you app into the applications folder, when you run this command that drag and drop ui will pop up, ignore it.
You really should use a tool like this, if you try to do it on your own you'll need to deal with symlinks, applescript and other nonsense. I've done it this way and if there's interest I can write a part two for a more manual approach.
- Sign the
.dmg
codesign --deep --force --verify --verbose --sign "Developer ID Application: Your Name (TeamID)" --options=runtime --timestamp YourApp.dmg
Notarize your App
Apple requires notarization to confirm your app isn’t malicious. You’ll need an app-specific password (not your Apple ID password)
Create and App-Specific Password:
-
Go to appleid.apple.com, sign in, and under "Sign-In and Security," select App-Specific Passwords
-
Generate a new password (name it whatever you like) and save it
Submit for Notarization
- Use the
notarytool
command
xcrun notarytool submit /path/to/YourApp.dmg --apple-id "your@email.com" --password "app-specific-password" --team-id "YourTeamID" --wait
-
Replace placeholders with your Apple ID, the app-specific password, and your Team ID
-
The
--wait
flag shows the result immediately (takes a few minutes). You’ll get a "Success" message or a log ID with issues to fix
Staple the Notarization Ticket:
- After approval, attach the notarization ticket to your
.dmg
xcrun stapler staple /path/to/YourApp.dmg
- This ensures Gatekeeper can verify it offline
Upload and Distribute
-
Upload the notarized
.dmg
to your GitHub or your website -
Provide a download link (preferably HTTPS for security)
-
Users might see a Gatekeeper prompt on first launch; they can right-click > Open or allow it in System Settings > Security & Privacy
Troubleshooting
I have had countless issues when trying to sign applications
Unable to build chain to self-signed root
One issue that I've run into on both of my macbooks is:
Warning: unable to build chain to self-signed root for signer
Something I usually have to do is open the Developer Certificate, expand the trust section and set "When using this certificate:" to "Use System Defaults" Then I restart my laptop once or twice and eventually it works.
Can't delete cert in GUI
I have also had an issue where I can't delete the certs in the gui, in this case run the command to list the certs:
security find-identity -v -p codesigning
and delete it based on the hash in the beginning:
security delete-certificate -Z ABC123...
Notarization fails
This is usually due to not passing the hardened runtime option so try resigning the app and dmg with
--options runtime
You can use the command below to see what's wrong
xcrun notarytool log "notary id" --apple-id "your@email.com" --password "app-specific-password" --team-id "HGGSBC8HJF"
Conclusion
Having an article like this would have saved me a lot of time debugging.
npub1ygzj9skr9val9yqxkf67yf9jshtyhvvl0x76jp5er09nsc0p3j6qr260k2
Posted at notestack.com
-