Warning, /graphics/krita/README.packagers.md is written in an unsupported language. File is not indexed.
0001 Notes on packaging Krita with G’MIC 0002 ================================== 0003 0004 Krita 3 and later are compatible with G’MIC, an open-source digital 0005 image processing framework. This support is provided by G’MIC-Qt, a 0006 Qt-based frontend for G’MIC. Since its inception, G’MIC-Qt was shipped 0007 as a standalone, externally built executable that is an optional, 0008 runtime dependency of Krita. 0009 0010 Krita 5 changes the way G’MIC-Qt is consumed. In order to support CentOS 0011 and macOS, G’MIC-Qt has been converted into a dynamically loadable 0012 library that is a dependent of Krita. 0013 0014 This file reviews these changes, and how to package Krita accordingly. 0015 0016 Rationale 0017 --------- 0018 0019 We have chosen to ship G’MIC-Qt as a library because of two longstanding 0020 bugs. 0021 0022 The Krita host for G’MIC-Qt relies on `QSharedMemory`, i.e. a shared 0023 memory segment, on wich a pipe is instantiated to pass messages to and 0024 from the host app. Firstly, this approach made opening two simultaneous 0025 G’MIC-Qt instances (each paired to its own Krita instance) impossible 0026 [^1]. Secondly, it also forbade using G’MIC-Qt with Krita on CentOS, as 0027 well as macOS, because the former doesn’t support `QSharedMemory` [^2], 0028 and the latter has a meager 4KB as the maximum shared segment size. 0029 While there’s no workaround (to our knowledge) in CentOS, the only 0030 workaround for macOS is to manipulate the maximum segment size via 0031 `sysctl` [^3], which was already difficult pre-Mojave [^4] and now, due 0032 to the significant security measures of recent macOS versions, is 0033 nothing short of a sysadmin task [^5]. 0034 0035 There were two approaches. One was to move to a `mmap`-d file, which is 0036 unpredictable to sync due to each canvas’s differing space requirements. 0037 The easiest, and the one we chose, was to move to a tighter coupled 0038 memory model– a dynamically loadable plugin, as shown in my proposal PR 0039 [^6]. This was rejected by the G’MIC developers because of the 0040 possibility of crashing the host app due to a G’MIC internal bug 0041 [^7][^8]. This decision was later enacted as part of G’MIC contributing 0042 policies [^9]. 0043 0044 How did you fix it? 0045 ------------------- 0046 0047 Due to the above, the only path forward was to fork G’MIC, which we did 0048 in Krita MR !581 [^10]. 0049 0050 From a source code point of view, our fork is based on top of the latest 0051 version’s tarball. Each tarball’s contents are committed to the `main` 0052 branch of the `amyspark/gmic` GitHub repository [^11]. For every covered 0053 release, there is a branch that in turn overlays our own plugin 0054 implementation, along with additional fixes that ensure that G’MIC-Qt 0055 doesn’t attempt to overwrite the internal state of the host application; 0056 namely, `QCoreApplication` settings, widget styles, and the installed 0057 translators. 0058 0059 From a technical point of view, this library interfaces with Krita 0060 through a new, purpose specific library, `kisqmicinterface`. This 0061 library contains nothing more than the previous iteration of the 0062 communications system, but now exported through namesake APIs [^12]. 0063 0064 In short, we have reversed the dependency flow; while in Krita v4 and 0065 earlier G’MIC-Qt was a runtime dependency, in v5, it’s G’MIC-Qt that 0066 depends on Krita as a build *and* runtime dependency. 0067 0068 Getting the source code 0069 ----------------------- 0070 0071 The patched version’s tarballs are GPG signed and available at the 0072 Releases section of the GitHub repository [^13]. Alternatively, the 0073 tarballs (though not the signatures) are also mirrored at our 0074 dependencies stash at files.kde.org [^14]. The tarballs are signed with 0075 the GPG key which is available at my GitHub profile. Its fingerprint is 0076 `4894424D2412FEE5176732A3FC00108CFD9DBF1E`. 0077 0078 Building Krita’s G’MIC-Qt library 0079 --------------------------------- 0080 0081 After building Krita with your standard process, the CMake install 0082 process should have put `kisqmicinterface.so` in your `lib` folder: 0083 0084 [2022-01-09T16:21:32.589Z] -- Installing: /home/appimage/appimage-workspace/krita.appdir/usr/lib/x86_64-linux-gnu/libkritaqmicinterface.so.18.0.0 0085 [2022-01-09T16:21:32.589Z] -- Installing: /home/appimage/appimage-workspace/krita.appdir/usr/lib/x86_64-linux-gnu/libkritaqmicinterface.so.18 0086 [2022-01-09T16:21:32.589Z] -- Set runtime path of "/home/appimage/appimage-workspace/krita.appdir/usr/lib/x86_64-linux-gnu/libkritaqmicinterface.so.18.0.0" to "/home/appimage/appimage-workspace/krita.appdir/usr/lib/x86_64-linux-gnu:/home/appimage/appimage-workspace/deps/usr/lib:/home/appimage/appimage-workspace/deps/usr/lib/x86_64-linux-gnu" 0087 [2022-01-09T16:21:32.589Z] -- Installing: /home/appimage/appimage-workspace/krita.appdir/usr/lib/x86_64-linux-gnu/libkritaqmicinterface.so 0088 0089 It should also install these headers, as illustrated below: 0090 0091 - `kis_qmic_plugin_interface.h` exports a G’MIC-alike `launch` entry 0092 point that the plugin will implement 0093 - `kis_qmic_interface.h` implements the G’MIC request-response APIs 0094 - `kritaqmicinterface_export.h` is the CMake auto-generated export 0095 decoration header 0096 0097 <!-- --> 0098 0099 [2022-01-09T16:21:32.589Z] -- Installing: /home/appimage/appimage-workspace/krita.appdir/usr/include/kis_qmic_interface.h 0100 [2022-01-09T16:21:32.589Z] -- Installing: /home/appimage/appimage-workspace/krita.appdir/usr/include/kis_qmic_plugin_interface.h 0101 [2022-01-09T16:21:32.589Z] -- Installing: /home/appimage/appimage-workspace/krita.appdir/usr/include/kritaqmicinterface_export.h 0102 0103 The three headers, along with the `libkritaqmicinterface.a` archive 0104 library (if building for Windows under MinGW), comprise a `krita-gmic-dev` 0105 package that’ll be a build dependency of the new G’MIC-Qt plugin. 0106 Please note that `libkritaqmicinterface.so` is consumed 0107 by Krita and MUST NOT be placed inside this dev package. 0108 0109 Now, download the G’MIC-Qt tarball from one of the sources listed 0110 previously, and unpack it to an isolated directory. Then, you can build 0111 it with these lines (adjust them as described): 0112 0113 mkdir build 0114 cmake -S ./gmic-$<the tarball's G'MIC version>-patched/gmic-qt \ 0115 -B ./build \ 0116 -DCMAKE_PREFIX_PATH=$<installation prefix of krita-gmic-dev> \ 0117 -DCMAKE_INSTALL_PREFIX=$<installation prefix of krita itself> \ 0118 -DENABLE_SYSTEM_GMIC=$<false if you don't want to use your system's G'MIC> \ 0119 -DGMIC_QT_HOST=krita-plugin 0120 cmake --build . --config $<your desired build type> --target install 0121 0122 The changes from a standard G’MIC build are: 0123 0124 - the new `GMIC_QT_HOST` value, `krita-plugin` 0125 - the requirement for the `krita-gmic-dev` package to be available in 0126 `CMAKE_PREFIX_PATH` 0127 0128 This process is illustrated in any of our official build scripts for 0129 Windows [^15] and for macOS/Linux [^16]. You can also check the 0130 `3rdparty_plugins` section of our source tree [^17] to see what other 0131 hardening we apply to the build. 0132 0133 ------------------------------------------------------------------------ 0134 0135 [^1]: Bug \#44 on c-koi/gmic-qt: “CentOS7: Krita 4.0.4 + gmic\_krita\_qt 0136 2.3.0/2.2.3 - QSharedMemory::attach”. 0137 <https://github.com/c-koi/gmic-qt/issues/44> 0138 0139 [^2]: Bug 424514 on krita: “Guaranteed crash when opening 2 G’MIC-qt”. 0140 <https://bugs.kde.org/show_bug.cgi?id=424514> 0141 0142 [^3]: <https://www.ssec.wisc.edu/mcidas/doc/users_guide/2017.1/SharedMemory.html> 0143 0144 [^4]: e.g. <https://stackoverflow.com/questions/2017004/setting-shmmax-etc-values-on-mac-os-x-10-6-for-postgresql> 0145 0146 [^5]: See <https://developer.apple.com/forums/thread/669625> for an 0147 approach applicable after `com.apple.rootless` was fully enforced. 0148 0149 [^6]: <https://github.com/c-koi/gmic-qt/pull/102> 0150 0151 [^7]: <https://github.com/c-koi/gmic-qt/pull/102> 0152 0153 [^8]: Note that this was already possible, simply by crashing G’MIC the 0154 host app would deadlock, waiting forever for a response. 0155 0156 [^9]: <https://github.com/c-koi/gmic-qt/blob/master/NEW_HOST_HOWTO.md> 0157 0158 [^10]: <https://invent.kde.org/graphics/krita/-/merge_requests/581> 0159 0160 [^11]: <https://github.com/amyspark/gmic> 0161 0162 [^12]: An older version of what’s 0163 <https://github.com/c-koi/gmic-qt/blob/master/src/Host/GmicQtHost.h> 0164 nowadays. 0165 0166 [^13]: <https://github.com/amyspark/gmic/releases> 0167 0168 [^14]: <https://files.kde.org/krita/build/dependencies/> 0169 0170 [^15]: <https://invent.kde.org/graphics/krita/-/tree/master/build-tools/windows> 0171 0172 [^16]: <https://invent.kde.org/graphics/krita/-/blob/master/packaging> 0173 0174 [^17]: <https://invent.kde.org/graphics/krita/-/tree/master/3rdparty_plugins>