How to distribute a SwiftPM executable on macOS

Hey there,

I've been trying to build and distribute a simple internal CLI tool. I am building with SwiftPM

swift build -c release --product mytoolcli --arch arm64 --arch x86_64

And then code signing,

xcrun codesign -s ${CODESIGN_IDENTITY} \
               --options=runtime \
               --timestamp \
               ${BINARY}

Then package the CLI in a DMG together with a simple Bash Script INSTALL that copies the file to /usr/local/bin.

hdiutil create -volname "mytoolcli" -srcfolder "${PKG_DIR}" -ov -format UDZO "${PKG_DMG}"
xcrun codesign -s ${CODESIGN_IDENTITY} "${PKG_DMG}"

The I upload for notarization:

xcrun altool --notarize-app \
               --primary-bundle-id ${BUNDLE_ID} \
               --username "${USERNAME}" \
               --password "@keychain:${PASSWORD_ID}" \
               --asc-provider ${ASC_PROVIDER} \
               --file "${PKG_DMG}"

And once the notarization is successful, I staple it on the DMG

xcrun stapler staple "${SIGNED_PKG}"

But, when I send the DMG to a coworker and she tries to open the INSTALL script in the DMG (or the cli executable), she gets the infamous "macOS cannot verify the developer".

Am I missing something obvious?

$ spctl -a -t install -vvv /path/to/mytoolcli.dmg
/path/to/mytoolcli.dmg: accepted
source=Notarized Developer ID
origin=Developer ID Application: Name (IDXXXX)

When I try running

$ spctl -a -t exec -vvv /Volumes/mytoolcli/mytoolcli

on the executable in the mounted disk image, I get

/Volumes/mytoolcli/mytoolcli: rejected (the code is valid but does not seem to be an app)
origin=Developer ID Application: Name (IDXXXX)

So, I guess my question is: how can I package a swift executable built with swift for distribution on macOS?

Thanks!

Tobias

But, when I send the DMG to a coworker and she tries to open the
INSTALL script in the DMG (or the cli executable), she gets the
infamous "macOS cannot verify the developer".

Open how? By running the executable from Terminal? Or by double clicking the Finder? If it’s the latter, try the former (the latter never works due to a bad interaction between Terminal and Gatekeeper (r. 58097824)).

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

Thanks, I think this was indeed the problem. I always tried to just double-click the file. Now I've packaged the binary in a .pkg inside a .dmg and this seems to work fine. :crossed_fingers:

Would you be so kind as to show the process with a pkg instead of a dmg?

I have been wanting to do this with one of my projects gitlab-fusion.

Sure, essentially my workflow is now as follows

  1. Build the binary and code sign it with "Developer ID Application" identity.
  2. Create a .pkg for installation in /usr/local/bin and sign with with "Developer ID Installer".
  3. Submit .pkg for notarization.
  4. Staple ticket onto .pkg
  5. Package .pkg inside a .dmg.

or:

make notarize

and later

make image

VERSION = 0.1.0
PRODUCT = my-tool

BINARY = .build/apple/Products/Release/${PRODUCT}
PKG_ROOT = ./pkg/${PRODUCT}-${VERSION}
PKG_DIR =  ${PKG_ROOT}/usr/local/bin
PKG_DMG = ./pkg/${PRODUCT}-${VERSION}.dmg
PKG_DMG_ROOT = ./pkg/out
PKG = ${PKG_DMG_ROOT}/${PRODUCT}-${VERSION}.pkg

CODESIGN_IDENTITY = "Developer ID Application: John Appleseed (1234AAPL)"
PKG_CODESIGN_IDENTITY = "Developer ID Installer: John Appleseed (1234AAPL)"
BUNDLE_ID = dev.appleseed.${PRODUCT}
USERNAME = john.appleseed@me.com
PASSWORD_ID = AC_PASSWORD
ASC_PROVIDER = 47MVPF48NE
	
	
${BINARY}:
	swift build -c release --product ${PRODUCT}  --arch arm64 --arch x86_64
	xcrun codesign -s ${CODESIGN_IDENTITY} \
               --options=runtime \
               --timestamp \
               ${BINARY}
               
${PKG}: ${BINARY}
	rm -rf "${PKG_ROOT}" || true
	rm -rf "${PKG_DMG_ROOT}" || true
	mkdir -p ${PKG_DIR}
	mkdir -p ${PKG_DMG_ROOT}
	cp ${BINARY} ${PKG_DIR}
	xcrun pkgbuild --root ${PKG_ROOT} \
           --identifier "${BUNDLE_ID}" \
           --version "${VERSION}" \
           --install-location "/" \
           --sign ${PKG_CODESIGN_IDENTITY} \
           ${PKG}
           
${PKG_DMG}: ${PKG} staple
	hdiutil create -volname "${PRODUCT}" -srcfolder "${PKG_DMG_ROOT}" -ov -format UDZO "${PKG_DMG}"

.PHONY: build
build: ${BINARY}

.PHONY: package
package: ${PKG}

.PHONY: notarize
notarize: ${PKG}
	xcrun altool --notarize-app \
               --primary-bundle-id ${BUNDLE_ID} \
               --username "${USERNAME}" \
               --password "@keychain:${PASSWORD_ID}" \
               --asc-provider ${ASC_PROVIDER} \
               --file "${PKG}"
               
.PHONY: staple
staple:
	xcrun stapler staple "${PKG}"

.PHONY: image
image: ${PKG_DMG}
2 Likes

Really appreciate that. Thank you @t089.

Terms of Service

Privacy Policy

Cookie Policy