How to package a plugin that will work on Windows (Microsoft Store version)
Special actions need to be taken in order for plug-ins work on the Microsoft Store
version of GIMP. Specifically, they should be packaged and codesigned. This is due
to security restrictions and virtualization of MSIX packages that do not recommend
a direct installation at %LOCALAPPDATA%\Packages\GIMP*\LocalCache\Roaming\GIMP
,
for example. From start, they needs:
- AppxManifest.xml
- Assets folder and resources.pri
- Plug-in files in appropriate VFS folder
Configuring the ‘modification package’ manifest
The package that we will create isn’t a common one but a modification package, which should have the following AppxManifest.xml in the root folder:
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
xmlns:rescap6="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities/6">
<Identity Name="DEV-NAME.PLUG-IN-NAME-WITHOUT-SYMBOLS-OR-SPACES" Publisher="CERT-INFO" Version="MAJOR.MINOR.MICRO.0" ProcessorArchitecture="MSIX-ARCH" />
<Properties>
<DisplayName>PLUG-IN-NAME</DisplayName>
<PublisherDisplayName>DEV-NAME</PublisherDisplayName>
<Description>PLUG-IN-DESC</Description>
<Logo>Assets\StoreLogo.png</Logo>
<rescap6:ModificationPackage>true</rescap6:ModificationPackage>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22621.0" />
<uap4:MainPackageDependency Name="GIMP.GIMP" Publisher="CN=8705A20E-F3A1-463E-86D3-B71D4DE2E37D" />
</Dependencies>
<Resources>
<Resource Language="en-US" />
<Resource uap:Scale="100" />
<Resource uap:Scale="125" />
<Resource uap:Scale="150" />
<Resource uap:Scale="200" />
<Resource uap:Scale="400" />
</Resources>
</Package>
Change MSIX-ARCH
to arm64
if you support ARM 64-bit, x64
if x86 64-bit;
and neutral
if the plug-in doesn’t have binaries (eg. Lua, Python and Scheme).
Them, set the PLUG-IN-NAME
, DEV-NAME.PLUG-IN-NAME-WITHOUT-SYMBOLS-OR-SPACES
,
PLUG-IN-DESC
, MAJOR.MINOR.MICRO.0
and DEV-NAME
according.
Finally, put the same info of your CA trusted certificate in CERT-INFO
. Without a
certificate, you can test locally putting , OID.2.25.311729368913984317654407730594956997722=1
right after an arbitrary certificate info, but the plug-in willn’t be able to be
sideloaded by the users (as said before, codesigning will be really mandatory).
Generating the assets
The only asset needed by a modification package is the StoreLogo. And, for now, don’t be misleaded by the name: the plug-in (and any modification package) can not be deployed in Store, we will talk about an alternative below. Anyway, keep in mind that this file is needed for compliance. You can do the rendering of your icon to the following sizes:
Filename | Size |
---|---|
StoreLogo.png | 50px |
StoreLogo.scale-125.png | 65px (approx.) |
StoreLogo.scale-150.png | 75px |
StoreLogo.scale-200.png | 100px |
StoreLogo.scale-400.png | 200px |
Create a folder named Assets
in the root of the package folder and put the .pngs there.
Then, we will be almost ready to generate the resources.pri.
From now, you need to install Windows SDK.
Since the installer don’t configure any PATH,
set C:\Program Files (x86)\Windows Kits\10\bin\NT_MAJOR.MINOR.MICRO.0\x64
and
C:\Program Files (x86)\Windows Kits\10\App Certification Kit
.
Continuing, in the package folder, let’s make a priconfig.xml:
makepri createconfig /cf priconfig.xml /dq lang-en-US /pv 10.0.0
Now, in the uplevel folder (this is due CLI limitations of makepri):
makepri new /pr PACKAGE-FOLDER /cf PACKAGE-FOLDER\priconfig.xml /of PACKAGE-FOLDER
Once the .pri file is generated, you should remove the priconfig.xml file.
Copying the files to appropiate VFS folder
To be properly recognized by GIMP the plug-in will rely in a Windows feature
called Virtual File System. In package root folder, create the following:
VFS\ProgramFilesX64\GIMP\lib\gimp\*\plug-ins\DEV-NAME.PLUG-IN-NAME-WITHOUT-SYMBOLS-OR-SPACES
.
If it is a gegl OP, so: VFS\ProgramFilesX64\GIMP\lib\gegl-*\DEV-NAME.PLUG-IN-NAME-WITHOUT-SYMBOLS-OR-SPACES
.
Copy the plug-in or OP files to DEV-NAME.PLUG-IN-NAME-WITHOUT-SYMBOLS-OR-SPACES
.
- Don’t copy stripped .debug or other dead binaries to avoid signing issues.
Packaging and signing the .msix or .msixbundle
Assuming that you have a multiarch plug-in (the .msixbundle format is recommended for multiarch), package it this way:
makeappx pack /d PACKAGE-FOLDER /p _TempOutput\DEV-NAME.PLUG-IN-NAME-WITHOUT-SYMBOLS-OR-SPACES_MAJOR.MINOR.MICRO.0_MSIX-ARCH.msix
makeappx bundle /bv MAJOR.MINOR.MICRO.0 /d _TempOutput /p _Output\DEV-NAME.PLUG-IN-NAME-WITHOUT-SYMBOLS-OR-SPACES_MAJOR.MINOR.MICRO.0_neutral.msixbundle
Then sign the package:
SignTool sign /fd sha256 /a /f CERT-FILE.pfx /p CERT-PASSWORD _Output\*.msixbundle
Now, if necessary, test the packages installing them:
Add-AppxPackage -Path *.msixbundle
- Use
Add-AppPackage -Path *.msixbundle -AllowUnsigned
if you used the OID tag so didn’t signed
Almost the entire process must be done for each supported architecture (in the case of plug-ins with binaries) so, to save your time in the future, we recommend mimic the GIMP Store distribution script. But in this tutorial we still go further:
Distributing and auto-updating with .appinstaller
Typically, your plugin may continue to get new features and bug fixes. And the easiest way to ensure this for the users is to create a simple .appinstaller file. It works similar to a .flatpakref file and guarantees auto update outside the Store. To do this, create a file with this extension and configure the following content:
<?xml version="1.0" encoding="utf-8"?>
<AppInstaller
xmlns="http://schemas.microsoft.com/appx/appinstaller/2017/2"
Version="MAJOR.MINOR.MICRO.0"
Uri="http://mywebservice.net/DEV-NAME.PLUG-IN-NAME-WITHOUT-SYMBOLS-OR-SPACES_MAJOR.MINOR.MICRO.0_neutral.appinstaller" >
<MainBundle
Name="PLUG-IN-NAME"
Publisher="CERT-INFO"
Version="MAJOR.MINOR.MICRO.0"
Uri="http://mywebservice.net/DEV-NAME.PLUG-IN-NAME-WITHOUT-SYMBOLS-OR-SPACES_MAJOR.MINOR.MICRO.0_neutral.msixbundle" />
<UpdateSettings>
<OnLaunch HoursBetweenUpdateChecks="12"/>
</UpdateSettings>
</AppInstaller>
You can test your .appinstaller with:
Add-AppxPackage -Path *.appinstaller -Appinstaller
You also may configure your web server for this. More information at Microsoft Docs.