Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save duraki/bd8affd35444917c524d7992506fb5f9 to your computer and use it in GitHub Desktop.
Save duraki/bd8affd35444917c524d7992506fb5f9 to your computer and use it in GitHub Desktop.
<?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>
<!-- These are required for binaries built by PyInstaller -->
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>

Setup

  • Create a developer account with Apple
  • Download and install X-Code from the Apple App Store
  • Open and run X-Code app and install whatever extras it requires
  • Open the preferences pane (cmd+,)
    • click the + in the lower right corner
    • choose Apple ID
    • enter your apple ID and password
    • Previously created keys can be downloaded and installed from https://developer.apple.com

Create an App-Specific password for altool to use

  • Instructions from Apple
  • Open KeyChain Access
  • Create a "New Password Item"
    • Keychain Item Name: Developer-altool
    • Account Name: your developer account email
    • Password: the application-specific password you just created

Create an executable binary with Pyinstaller

NB! Additional args such as --add-data may be needed to build a functional binary

  • Create a onefile binary
    • pyinstaller --onefile myapp.py

Sign the executable

  • Add the entitements.plist to the directory (see below)
  • List the available keys and locate a Developer ID Application certificate:
    • security find-identity -p basic -v
    1) ABC123 "Apple Development: aaronciuffonl@gmail.com ()"
    2) XYZ234 "Developer ID Installer: Aaron Ciuffo ()"
    3) QRS333 "Developer ID Application: Aaron Ciuffo ()"
    4) LMN343 "Developer ID Application: Aaron Ciuffo ()"
    5) ZPQ234 "Apple Development: aaron.ciuffo@gmail.com ()"
    6) ASD234 "Developer ID Application: Aaron Ciuffo ()"
    7) 01010A "Developer ID Application: Aaron Ciuffo ()"
       7 valid identities found
    
  • codesign --deep --force --options=runtime --entitlements ./entitlements.plist --sign "HASH_OF_DEVELOPER_ID APPLICATION" --timestamp ./dist/foo.app

Package as a pkg for installation

  • Create a temp directory to build the package:
    • mkdir /tmp/myapp
  • Use ditto to build the pkg installer structure
    • ditto /path/to/myapp /tmp/myapp/path/to/install/location
    • repeat for all files that should be packaged
  • build the pkackage
  • productbuild --identifier "com.your.pkgname.pkg" --sign "HASH_OF_INSTALLER_ID" --timestamp --root /tmp/myapp / myapp.pkg

Notarize

  • xcrun altool --notarize-app --primary-bundle-id "com.foobar.fooapp" --username="developer@foo.com" --password "@keychain:Developer-altool" --file ./myapp.pkg
  • Check email for successful notarization
    • Alternatively check status using:
      • xcrun altool --notarization-history 0 -u "developer@***" -p "@keychain:Developer-altool"
  • If notarization fails use the following to review a detailed log:
  xcrun altool --notarization-info "Your-Request-UUID" \
             --username "username@example.com" \                                    
             --password "@keychain:Developer-altool"   

Staple notarization to pkg

  • add the notariztaion to the pkg
    • xcrun stapler staple ghostscript64.pkg

Useful Resources

Alternative workflows that may have issues:

Create a bundled app with pyinstaller

  • Only ".app" bundles appear to work using this procedure
    • pyinstaller --windowed --onefile foo.py
    • edit the spec file app = BUNDLE section to include a bundle_identifier
    app = BUNDLE(exe,
               name='helloworld.app',
               icon=None,
               bundle_identifier='com.txoof.helloworld'
               )
    
  • NOTE! Appbundles will not execute properly -- they must be run by execuing the bundle.app/Contents/MacOS/myapp

package as a dmg

NB! This may not work for single file executables -- use the PKG method above

  • Create a .dmg:
    • clean any uneeded files out of ./dist; only the .app should remain
    • hdiutil create ./myapp.dmg -ov -volname "MyApp" -fs HFS+ -srcfolder "./dist"
  • Shrink and make read-only:
    • $hdiutil convert ./myapp.dmg -format UDZO -o myapp.dmg
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment