Skip to content
How to package a plugin that will work on MacOS

How to package a plugin that will work on MacOS

Special actions need to be taken in order for binary plug-ins work on the macOS version of GIMP. Specifically, they should be packaged as .pkg. This is due to Apple security restrictions, for example. From start, they needs:

  • properly linked and codesigned binaries
  • distribution.xml file
  • .pkg notarization

Ensuring macOS linking and codesigning

Since the GIMP .dmg is generated from a choosen MACOSX_DEPLOYMENT_TARGET, binary plug-ins should be built accordingly to ensure the right symbols.

The devel-docs/os-support.txt file on GIMP source is the reference but you may need to double-check the https://gimp.org/downloads page to safe.

For babl, gegl and gimp symbols, we recommend to use GIMP SDK. It automatically sets MACOSX_DEPLOYMENT_TARGET and other macOS compiler flags.

Additionally, for x86_64 cross compile, use these commands when invoking gimptool:

softwareupdate --install-rosetta --agree-to-license
arch -x86_64 /path_to/gimptool

If you want to make your plug-in available for both x86_64 and arm64 macOS you can build them individually and then “glue” the two binaries together into a “universal binary”. After building the two binaries run:

lipo -create -arch x86_64 /path_to/x86_64/plug-in -arch arm64 /path_to/arm64/plug-in -output /path_to/where_you_want_it_stored/plug-in

After compiling, codesign the plug-in binaries. To codesign run the below command.

codesign -s "Developer ID Application" --timestamp --options runtime --entitlements /path_to/entitlements.plist /path_to/plug-in

Replace Developer ID Application with your developer ID (you need a paid developer account).

You will also need to codesign with hardened runtime which will also require you to point to an entitlements.plist file. This is the file that GIMP uses, which may or may not be right for a plugin: Hardening entitlements. Codesigning is only needed for distributing your plug-in.

If you do not properly codesign your plugin, it cannot be notarized later. And if it is not notarized, it will need to be manually unquarantined on the end user’s macOS, which is not recommended.

Creating a PKG installer

The best way to install your plugin is using a PKG package. Change GIMP-APP-VERSION, DEV-NAME, PLUG-IN-NAME-WITHOUT-SYMBOLS-OR-SPACES appropriately below.

First, create a folder structure in folder called package, with your plugin in a subfolder named gimp_plugin.

In another subfolder called script place a file called postinstall with the following content:

#!/bin/sh
mkdir -p $HOME/Library/Application\ Support/GIMP/GIMP-APP-VERSION/plug-ins/PLUG-IN-NAME-WITHOUT-SYMBOLS-OR-SPACES
cp -pf /tmp/gimp_plugin/* $HOME/Library/Application\ Support/GIMP/GIMP-APP-VERSION/plug-ins/PLUG-IN-NAME-WITHOUT-SYMBOLS-OR-SPACES

Change the file script/postinstall file to be executable (chmod +x ./script/postinstall).

Finally, create a file called distributions.xml in the folder package with the content:

distributions.xml
<?xml version="1.0" encoding="utf8"?>
<installer-gui-script minSpecVersion="2">
  <title>PLUG-IN-NAME</title>>
  <options customize="never"/>
  <domains enable_anywhere="false" enable_currentUserHome="true" enable_localSystem="false"/>
  <choices-outline>
    <line choice="plug-in"/>
  </choices-outline>
  <choice id="plug-in" visible="false" customLocation="/tmp/gimp_plugin">
    <pkg-ref id="org.DEV-NAME.PLUG-IN-NAME-WITHOUT-SYMBOLS-OR-SPACES.pkg" version="0" onConclusion="none">temp_plugin.pkg</pkg-ref>
  </choice>
</installer-gui-script>

Inside the package folder, run:

pkgbuild --nopayload --identifier org.DEV-NAME.PLUG-IN-NAME-WITHOUT-SYMBOLS-OR-SPACES.pkg --scripts ./script --root ./gimp_plugin/ temp_plugin.pkg

Then sign the package:

productbuild --distribution ./distribution.xml --sign "Developer ID Installer: YOUR NAME" --timestamp --package-path temp_plugin.pkg ./PLUG-IN-NAME-WITHOUT-SYMBOLS-OR-SPACES.pkg
Please take note that you need the Installer certificate for the pkg, not the Application one.
  • Use productbuild --distribution ./distribution.xml --package-path temp_plugin.pkg ./plugin_name.pkg if you don’t sign.

You can now delete the temp_plugin.pkg, it was only a temporary file.

Short breakdown of what this all does:

Pkgbuild packages your plugin and sets up the script. Productbuild uses this package, sets it to run as the installing user (enable_currentUserHome="true") and to install the plugin to a temporary folder /tmp/gimp_plugin.

When you run the installer, the plugin gets installed to /tmp/gimp_plugin and the script copies it over to $HOME/Library/Application\ Support/GIMP/GIMP-APP-VERSION/plug-ins/PLUG-IN-NAME-WITHOUT-SYMBOLS-OR-SPACES.

Notarization

To notarize your plug-in with Apple, after packaging your codesigned plug-in package (PKG), run:

xcrun notarytool submit --wait --keychain-profile 'cert_container' PLUG-IN-NAME-WITHOUT-SYMBOLS-OR-SPACES.pkg
xcrun stapler staple PLUG-IN-NAME-WITHOUT-SYMBOLS-OR-SPACES.pkg

Getting cert_container ready will require a certain amount of setup (maybe it’s already done with the certificates you used for codesigning) but follow Apple’s instructions. Here is some links with information on the code that does notarization for GIMP:

Last updated on