How to package a macOS Desktop App

How to package a macOS Desktop App

How to package a macOS Desktop App

Mac: Desktop - Apple Education Community

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

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.

@ygzj…60k2

Posted at notestack.com

No comments yet.