*Update* 5.5 years later (December 2025): No new changes. Still effective and correct as of this date.
**************************************
Nov 2023: Apple depreciated the notary utility "xcrun atool", and replaced it with "xcrun notarytool". The process is similar but with updated params. Also the minimum run version of x86_64 binaries accepted by Apple, and the FPC 3.2.2 defaults, collide and need adjusting before submitting to Apple for notarizing (see below).
**************************************
Now Apple have added App Bundle notarizing, where they co-sign and validate the bundle. From 10.14.x (Mojave) onwards, this is becoming enforced in various ways.
This procedure below applies to making and assembling your own app bundle, then placing it in a Package (.pkg) installer file, and then wrapping it all in a .dmg file for distribution.
The procedure I am using now is:
Setup:1/ Join the Mac Dev Center through Appstore. $119 a year - suck it up.
2/ In the Dev center, go to the certificate section, and create 2 new certificates: Go to: Certificates -> + to create new There are now many choices. Here I'm selecting "Developer ID Installer" and "Developer ID Application". We use these when making app's that we sign and distribute ourselves. You do this creating cert's in conjunction with KeyChain utility program and its Assistant and request a cert (use the saved to disk method)
3/ Download those two certs and install into your KeyChain (click the cer file).
4/ Download the Intermediate certs - Look for the Intermediate certs and get the WWDR and Developer ID Intermediate cert (now seem to be pre-installed via XCode). You might already have these installed. Install these to your KeyChain too.
Assemble your app bundle. Described here:
https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW1Note: With the introduction of XCode 15, a revised linker (ld) was added. This conflicts with FPC v3.2.2 with some missing and changed params, but none are fatal. One that affects notarizing is the -macos_version_min on x86_64 binaries. The FPC and ld will set this to 10.8, but notarizing needs 10.9 or better. Further still if the -macos_version_min is set to anything under 10.11 then the binary needs to be codesign'd with dual hashing using sha1 and sha256. All these issues are sidestepped by setting the x86_64 binary -macos_version_min to 10.11 or better. This needs to be done manually, before assembling the app bundle. If you use the Lazarus app bundle, then do this change below after compiling.
We can't override the -macos_version_min command that FPC tells the linker, so we instead replace the version in the finished binary like so:
vtool -set-version-min macos 10.11 10.11 -replace -output /path/to/my/x86_64/binary-new /path/to/my/x86_64/binaryCheck the result with
vtool -show-build /path/to/my/x86_64/binary-newAll of the above affects only the x86_64 binary. The aarch64 binary automatically get stamped as sdk 11.0 (the first M1 sdk), and it needs no further adjustments.
Note also that version 15.6 added new compiling problems for AARCH with conflicts with the (getting old) FPC 3.2.2. These are addressed here:
https://forum.lazarus.freepascal.org/index.php/topic,72172.msg568849.html#msg568849Signing:5/ Sign your .app bundle:
/usr/bin/codesign -f -o runtime --timestamp -s "Developer ID Application: My Software Corp." /path/to/my/app/bundle.app(use your real developer ID name per the cert).
Note: If you are using outside libraries, including linking to inbuilt 3rd party things like openssl through fcl-web package, then you may need to include entitlements - see below.
6/ Make your package file with your signed .app bundle above. I use the Packages utility (3rd party install making tool [link below]). Instead try the pkgbuild and productbuild command line tools.
7/ Sign your .pkg file:
/usr/bin/productsign --sign "Developer ID Installer: MyCoName inc." /input/path/to/package.pkg /OUTPUT/path/for/the/result.pkg
(use your real install ID name per the cert).
8/ Make your .dmg file as required. I use the command line tool
hdiutil create -ov -scrub -srcfolder /bundle_dir/ -volname dmgvolname /OUTPUT/path/for/the/result.dmgNotarizing:The app-specific passwords has been updated, and the old "atool" generated ones no longer function. Make a new app password with:
https://support.apple.com/en-us/102654 9/ Upload the finished dmg file to Apple:
/usr/bin/xcrun notarytool submit --apple-id "me@mysoftware.com" --password <app-specifc-password> --team-id <your 10 character team ID> /path/to/my/dmg/file.dmgWe recieve back a very long session identifier - keep this for the next move.
10/ wait.... it can take an hour... check the progress with:
/usr/bin/xcrun notarytool info --apple-id "me@mysoftware.com" --password <app-specifc-password> --team-id <your 10 character team ID> session-IDThey no longer send emails, but an "Accepted" status means success. To get details of a failure status, make the call above with param log instead info:
/usr/bin/xcrun notarytool log ....11/ After the above step registers "Accepted", have Apple staple notarized signature to the dmg file with
/usr/bin/xcrun stapler staple /path/to/my/dmg/file.dmgDone.
To verify, install the app and call
/usr/bin/spctl -a -v /Applications/my_installed_app.app...which will return "Notarized" and "accepted" if all is OK.
Most important... test the app by putting it in the Applications directory. It's treated differently by the OS (ATS/Gatekeeper) when in the "installed" location.
Effective 10.15, your app will generate errors messages and refuse to run, if any errors exist in the process above.
***************
Notes:
Step 9 requires you to have a new 2FA application sign in's. see:
https://support.apple.com/en-us/HT204397Apples guide to notarizing:
https://developer.apple.com/documentation/security/notarizing_macos_software_before_distributionEntitlements:Using the codesign's "-o runtime" option, enables the "hardened runtime" on the binary, which is required for notarizing. But it also limits variables passed into and the calling of .dylib files. If the external libraries are signed and notarized by you or Apple, then entitlements are not needed. The normal framework libraries are signed by Apple. But many third party .dylib's are not fully signed/notarized, or signed by third party but not you, so an entitlement is required to allow proper variable passing / library loading. For these you will need to add an entitlements file to the project and add it to the codesign process of the .app bundle, as follows.
Step 5 above becomes:/usr/bin/codesign -f -o runtime --entitlements path/to/my/app.entitlements --timestamp -s "Developer ID Application: My Software Corp." /path/to/my/app/bundle.appThe "app.entitlements" file does not ship with the bundle - it's for the code sign process only. The app.entitlements file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
</dict>
</plist>The above enables the "Allow DYLD Environment Variables", which is sufficient to use the openssl packages. You might also need the "Disable Library Validation" (com.apple.security.cs.disable-library-validation). All available options are listed here under "Hardened Runtime":
https://developer.apple.com/documentation/bundleresources/entitlements?language=objc#Aug 30th, 2019 - procedure updated
#July 11th, 2020 - added info.
#Feb 27th, 2022 - updated info.
#May 6th, 2024 - updated info.
#Dec 31, 2025 - confirmed still valid.
Packages app:
http://s.sudre.free.fr/Software/Packages/about.html