├── .gitignore ├── appimage-helper-scripts ├── appimage-exec-wrapper2 │ ├── Makefile │ ├── env.h │ ├── debug.h │ ├── env.c │ └── exec.c ├── bundle-gobject-introspection.sh ├── bundle-exec-wrapper.sh ├── zenity.sh ├── bundle-python.sh ├── bundle-python3.sh ├── bundle-gtk2.sh ├── excludelist ├── apprun-helper.sh ├── app.wrapper ├── functions.sh └── LICENSE ├── startup_scripts └── gmic.sh ├── scripts ├── gmic.sh └── gimp.sh ├── gimp-glib-splash.patch ├── gtkimageview-Werror.patch ├── gimp-mypaint-brush-dir.patch ├── mkappimage.sh ├── .travis.yml ├── README.md ├── AppRun.sh ├── AppRun-v3.sh ├── package-appimage.sh └── gimp.wrapper /.gitignore: -------------------------------------------------------------------------------- 1 | gimp 2 | work 3 | out 4 | run_gimp 5 | upload.sh 6 | -------------------------------------------------------------------------------- /appimage-helper-scripts/appimage-exec-wrapper2/Makefile: -------------------------------------------------------------------------------- 1 | exec.so: exec.c env.c 2 | gcc -std=c99 -o exec.so -shared exec.c env.c -Wall -Wfatal-errors -fPIC -g -ldl 3 | 4 | clean: exec.c exec.so 5 | rm exec.so 6 | -------------------------------------------------------------------------------- /appimage-helper-scripts/appimage-exec-wrapper2/env.h: -------------------------------------------------------------------------------- 1 | #ifndef ENV_H 2 | #define END_H 3 | 4 | #include 5 | 6 | char* const* read_parent_env(); 7 | void env_free(char* const *env); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /startup_scripts/gmic.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | export QT_PLUGIN_PATH="$APPDIR/usr/lib/qt5/plugins":$QT_PLUGIN_PATH 4 | 5 | #if [ ! -e /etc/pki/nssdb ]; then 6 | # echo "Setting SSL_DIR=$APPDIR/usr/etc/pki/nssdb" 7 | # export SSL_DIR="$APPDIR/usr/etc/pki/nssdb" 8 | #fi -------------------------------------------------------------------------------- /appimage-helper-scripts/bundle-gobject-introspection.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # Bundle the gobject-introspection runtime 4 | mkdir -p "$APPDIR/usr/lib" 5 | cp -a /usr/lib64/girepository-1.0 "$APPDIR/usr/lib" 6 | cp -a /usr/local/gimp/lib*/girepository-1.0/* "$APPDIR/usr/lib/girepository-1.0" 7 | -------------------------------------------------------------------------------- /appimage-helper-scripts/appimage-exec-wrapper2/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef DEBUG_H 2 | #define DEBUG_H 3 | 4 | #include 5 | #include 6 | 7 | #define DEBUG(...) do { \ 8 | if (getenv("APPIMAGE_CHECKRT_DEBUG")) \ 9 | printf("APPIMAGE_CHECKRT>> " __VA_ARGS__); \ 10 | } while (0) 11 | 12 | #endif // DEBUG_H 13 | -------------------------------------------------------------------------------- /appimage-helper-scripts/bundle-exec-wrapper.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # build and bundle the exec wrapper 4 | # it is used to restore the origin environment when executing 5 | # commands that are outside of the AppImage bundle 6 | (rm -rf /tmp/appimage-exec-wrapper2 && \ 7 | cp -a /sources/appimage-helper-scripts/appimage-exec-wrapper2 /tmp && \ 8 | cd /tmp/appimage-exec-wrapper2 && make && \ 9 | cp -a exec.so "$APPDIR/usr/lib/exec_wrapper.so") || exit 1 10 | -------------------------------------------------------------------------------- /scripts/gmic.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # Copy Qt5 plugins 4 | QT5PLUGINDIR=$(pkg-config --variable=plugindir Qt5) 5 | if [ x"$QT5PLUGINDIR" != "x" ]; then 6 | mkdir -p "$APPDIR/usr/lib/qt5/plugins" 7 | cp -a "$QT5PLUGINDIR"/* "$APPDIR/usr/lib/qt5/plugins" 8 | fi 9 | 10 | #(mkdir -p "$APPDIR/usr/etc" && cp -a /etc/pki "$APPDIR/usr/etc") || exit 1 11 | 12 | (mkdir -p "$APPDIR/startup_scripts" && \ 13 | cp -a /sources/startup_scripts/gmic.sh "$APPDIR/startup_scripts") || exit 1 -------------------------------------------------------------------------------- /gimp-glib-splash.patch: -------------------------------------------------------------------------------- 1 | *** app/gui/splash.c Thu Aug 23 12:47:24 2018 2 | --- app/gui/splash.c.new Thu Aug 23 12:56:17 2018 3 | *************** 4 | *** 567,574 **** 5 | GFileInputStream *input; 6 | gboolean is_svg = FALSE; 7 | 8 | ! if (be_verbose) 9 | ! g_printerr ("Trying splash '%s' ... ", g_file_peek_path (file)); 10 | 11 | info = g_file_query_info (file, 12 | G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, 13 | --- 567,574 ---- 14 | GFileInputStream *input; 15 | gboolean is_svg = FALSE; 16 | 17 | ! /*if (be_verbose) 18 | ! g_printerr ("Trying splash '%s' ... ", g_file_peek_path (file));*/ 19 | 20 | info = g_file_query_info (file, 21 | G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, 22 | -------------------------------------------------------------------------------- /gtkimageview-Werror.patch: -------------------------------------------------------------------------------- 1 | *** configure.in Sat Sep 8 14:56:27 2018 2 | --- configure.in.new Sat Sep 8 15:14:59 2018 3 | *************** 4 | *** 40,46 **** 5 | ##### Twiddle CFLAGS ################################################# 6 | ###################################################################### 7 | if test "x$GCC" = "xyes"; then 8 | ! CFLAGS="${CFLAGS} -Wall -Werror -Wno-error=deprecated-declarations -std=c99 -Wmissing-prototypes -DGTK_DISABLE_SINGLE_INCLUDES -DGSEAL_ENABLE" 9 | fi 10 | 11 | 12 | --- 40,46 ---- 13 | ##### Twiddle CFLAGS ################################################# 14 | ###################################################################### 15 | if test "x$GCC" = "xyes"; then 16 | ! CFLAGS="${CFLAGS} -Wall -Wno-error=deprecated-declarations -std=c99 -Wmissing-prototypes -DGTK_DISABLE_SINGLE_INCLUDES -DGSEAL_ENABLE" 17 | fi 18 | 19 | 20 | -------------------------------------------------------------------------------- /gimp-mypaint-brush-dir.patch: -------------------------------------------------------------------------------- 1 | *** gimp/app/config/gimpcoreconfig.c Sun May 19 20:03:55 2019 2 | --- gimp-new/app/config/gimpcoreconfig.c Sun May 19 20:06:37 2019 3 | *************** 4 | *** 304,311 **** 5 | g_free (path); 6 | 7 | #ifdef ENABLE_RELOCATABLE_RESOURCES 8 | ! mypaint_brushes = g_build_filename ("${gimp_installation_dir}", 9 | ! "share", "mypaint-data", 10 | "1.0", "brushes", NULL); 11 | #else 12 | mypaint_brushes = g_strdup (MYPAINT_BRUSHES_DIR); 13 | --- 304,311 ---- 14 | g_free (path); 15 | 16 | #ifdef ENABLE_RELOCATABLE_RESOURCES 17 | ! mypaint_brushes = g_build_filename ("${gimp_data_dir}", 18 | ! "mypaint-data", 19 | "1.0", "brushes", NULL); 20 | #else 21 | mypaint_brushes = g_strdup (MYPAINT_BRUSHES_DIR); 22 | -------------------------------------------------------------------------------- /appimage-helper-scripts/zenity.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export PATH="$APPDIR/usr/bin:${PATH}:/sbin:/usr/sbin" 4 | export LD_LIBRARY_PATH="$AILIBDIR:/usr/lib:$LD_LIBRARY_PATH" 5 | export XDG_DATA_DIRS="${APPDIR}/usr/share/:${XDG_DATA_DIRS}:/usr/local/share/:/usr/share/" 6 | export ZENITY_DATA_DIR="$APPDIR/usr/share/zenity" 7 | 8 | export GTK_PATH="${APPDIR}/usr/lib/gtk-2.0:${GTK_PATH}" 9 | export PANGO_LIBDIR="${APPDIR}/usr/lib" 10 | export GCONV_PATH="${APPDIR}/usr/lib/gconv" 11 | export GDK_PIXBUF_MODULEDIR="${APPDIR}/usr/lib/gdk-pixbuf-2.0/loaders" 12 | export GDK_PIXBUF_MODULE_FILE="${APPDIR}/usr/lib/gdk-pixbuf-2.0/loaders.cache" 13 | export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$GDK_PIXBUF_MODULEDIR" 14 | 15 | if [ "x" = "y" ]; then 16 | mkdir -p "$AILIBDIR/gdk-pixbuf-2.0" 17 | cp "${APPDIR}/usr/lib/gdk-pixbuf-2.0/loaders.cache" "$AILIBDIR/gdk-pixbuf-2.0" 18 | sed -i -e "s|LOADERSDIR|${APPDIR}/usr/lib/gdk-pixbuf-2.0/loaders|g" "$AILIBDIR/gdk-pixbuf-2.0/loaders.cache" 19 | export GDK_PIXBUF_MODULE_FILE="$AILIBDIR/gdk-pixbuf-2.0/loaders.cache" 20 | fi 21 | 22 | "$APPDIR/usr/bin/zenity" "$@" --no-wrap -------------------------------------------------------------------------------- /mkappimage.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | if [ x"${GTK_VERSION}" = "x" ]; then 4 | export GTK_VERSION=2 5 | fi 6 | 7 | 8 | if [ x"${GTK_VERSION}" = "x3" ]; then 9 | bash /sources/build-appimage-gtk3.sh || exit 1 10 | else 11 | bash /sources/build-appimage.sh || exit 1 12 | fi 13 | 14 | export APPROOT=/work/appimage 15 | 16 | # copy hook scripts 17 | (mkdir -p "${APPROOT}/scripts" && \ 18 | cp -a /sources/scripts/gimp.sh "${APPROOT}/scripts" && \ 19 | cp -a /sources/appimage-helper-scripts/bundle-gtk2.sh "${APPROOT}/scripts" && 20 | cp -a /sources/appimage-helper-scripts/bundle-gobject-introspection.sh "${APPROOT}/scripts") || exit 1 21 | if [ x"${GTK_VERSION}" = "x3" ]; then 22 | cp -a /sources/appimage-helper-scripts/bundle-python3.sh "${APPROOT}/scripts" || exit 1 23 | else 24 | cp -a /sources/appimage-helper-scripts/bundle-python.sh "${APPROOT}/scripts" || exit 1 25 | fi 26 | bash /sources/package-appimage.sh || exit 1 27 | exit 0 28 | 29 | if [ x"${GTK_VERSION}" = "x4" ]; then 30 | # fill and package the AppImage bundle 31 | bash /sources/package-appimage.sh || exit 1 32 | exit 0 33 | fi 34 | 35 | (mkdir -p "${APPROOT}/scripts" && cp -a /sources/scripts/gmic.sh "${APPROOT}/scripts") || exit 1 36 | bash /sources/build-appimage-plugins.sh || exit 1 37 | bash /sources/package-appimage.sh "-withplugins" || exit 1 38 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: generic 2 | os: linux 3 | dist: trusty 4 | compiler: g++ 5 | sudo: required 6 | services: docker 7 | env: 8 | - GTK_VERSION=2 9 | - GTK_VERSION=3 10 | #- BABL_GIT_TAG=BABL_0_1_72 11 | #- GEGL_GIT_TAG=GEGL_0_4_18 12 | - GIMP_GIT_TAG=GIMP_2_10_22 13 | #- TARGET_SYSTEM=Linux 14 | 15 | before_script: 16 | - travis_wait 120 sleep infinity & sudo docker pull photoflow/docker-centos7-gimp 17 | #- sudo docker run -it -v $(pwd):/sources -e BABL_GIT_TAG="$BABL_GIT_TAG" -e GEGL_GIT_TAG="$GEGL_GIT_TAG" -e GIMP_GIT_TAG="$GIMP_GIT_TAG" photoflow/docker-trusty-gimp bash /sources/build-appimage.sh 18 | #- sudo docker run -it -v $(pwd):/sources -e GTK_VERSION="${GTK_VERSION}" -e BABL_GIT_TAG="BABL_0_1_62" -e GEGL_GIT_TAG="GEGL_0_4_14" -e GIMP_GIT_TAG="$GIMP_GIT_TAG" photoflow/docker-centos7-gimp bash /sources/mkappimage.sh 19 | - sudo docker run -it -v $(pwd):/sources -e GTK_VERSION="${GTK_VERSION}" -e BABL_GIT_TAG="BABL_0_1_82" -e GEGL_GIT_TAG="GEGL_0_4_26" -e GIMP_GIT_TAG="${GIMP_GIT_TAG}" photoflow/docker-centos7-gimp bash /sources/mkappimage.sh 20 | after_success: 21 | - cd $TRAVIS_BUILD_DIR 22 | - ls -lh 23 | - ls out/* 24 | - wget -c https://github.com/aferrero2707/uploadtool/raw/master/upload_rotate.sh 25 | - bash ./upload_rotate.sh "continuous" out/* >& /dev/null 26 | branches: 27 | except: 28 | - # Do not build tags that we create when we upload to GitHub Releases 29 | - /^(?i:continuous)$/ 30 | - /^(?i:unstable)$/ 31 | -------------------------------------------------------------------------------- /appimage-helper-scripts/bundle-python.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # Bundle the python runtime 4 | PYTHON_PREFIX=$(pkg-config --variable=prefix python) 5 | PYTHON_LIBDIR=$(pkg-config --variable=libdir python) 6 | PYTHON_VERSION=$(pkg-config --modversion python) 7 | echo "PYTHON_PREFIX=${PYTHON_PREFIX}" 8 | echo "PYTHON_LIBDIR=${PYTHON_LIBDIR}" 9 | echo "PYTHON_VERSION=${PYTHON_VERSION}" 10 | if [ x"${PYTHON_PREFIX}" = "x" ]; then 11 | echo "Could not determine PYTHON installation prefix, exiting." 12 | exit 1 13 | fi 14 | if [ x"${PYTHON_LIBDIR}" = "x" ]; then 15 | echo "Could not determine PYTHON library path, exiting." 16 | exit 1 17 | fi 18 | if [ x"${PYTHON_VERSION}" = "x" ]; then 19 | echo "Could not determine PYTHON version, exiting." 20 | exit 1 21 | fi 22 | 23 | cp -a "${PYTHON_PREFIX}/bin"/python* "$APPDIR/usr/bin" || exit 1 24 | rm -rf "$APPDIR/usr/lib/python${PYTHON_VERSION}" 25 | mkdir -p "$APPDIR/usr/lib" 26 | cp -a "${PYTHON_LIBDIR}/python${PYTHON_VERSION}" "$APPDIR/usr/lib" || exit 1 27 | PYGLIB_LIBDIR=$(pkg-config --variable=libdir pygobject-2.0) 28 | if [ x"${PYGLIB_LIBDIR}" = "x" ]; then 29 | echo "Could not determine PYGOBJECT library path, exiting." 30 | exit 1 31 | fi 32 | cp -a "${PYGLIB_LIBDIR}"/libpyglib*.so* "$APPDIR/usr/lib" 33 | (cd "$APPDIR/usr" && mkdir -p lib64 && cd lib64 && rm -rf python${PYTHON_VERSION} && ln -s ../lib/python${PYTHON_VERSION} .) || exit 1 34 | ls -l "$APPDIR/usr/lib64" 35 | 36 | 37 | 38 | gssapilib=$(ldconfig -p | grep 'libgssapi_krb5.so.2 (libc6,x86-64)'| awk 'NR==1{print $NF}') 39 | if [ x"$gssapilib" != "x" ]; then 40 | gssapilibdir=$(dirname "$gssapilib") 41 | cp -a "$gssapilibdir"/libgssapi_krb5*.so* "$APPDIR/usr/lib" 42 | fi 43 | 44 | -------------------------------------------------------------------------------- /appimage-helper-scripts/bundle-python3.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # Bundle the python runtime 4 | PYTHON_PREFIX=$(pkg-config --variable=prefix python3) 5 | PYTHON_LIBDIR=$(pkg-config --variable=libdir python3) 6 | PYTHON_VERSION=$(pkg-config --modversion python3) 7 | echo "PYTHON_PREFIX=${PYTHON_PREFIX}" 8 | echo "PYTHON_LIBDIR=${PYTHON_LIBDIR}" 9 | echo "PYTHON_VERSION=${PYTHON_VERSION}" 10 | if [ x"${PYTHON_PREFIX}" = "x" ]; then 11 | echo "Could not determine PYTHON installation prefix, exiting." 12 | exit 1 13 | fi 14 | if [ x"${PYTHON_LIBDIR}" = "x" ]; then 15 | echo "Could not determine PYTHON library path, exiting." 16 | exit 1 17 | fi 18 | if [ x"${PYTHON_VERSION}" = "x" ]; then 19 | echo "Could not determine PYTHON version, exiting." 20 | exit 1 21 | fi 22 | 23 | cp -a "${PYTHON_PREFIX}/bin"/python* "$APPDIR/usr/bin" || exit 1 24 | rm -rf "$APPDIR/usr/lib/python${PYTHON_VERSION}" 25 | mkdir -p "$APPDIR/usr/lib" 26 | cp -a "${PYTHON_LIBDIR}/python${PYTHON_VERSION}" "$APPDIR/usr/lib" || exit 1 27 | 28 | mkdir -p "$APPDIR/usr/lib/python${PYTHON_VERSION}/site-packages" 29 | cp -a /usr/local/lib64/python${PYTHON_VERSION}/site-packages/* "$APPDIR/usr/lib/python${PYTHON_VERSION}/site-packages" 30 | 31 | PYGLIB_LIBDIR=$(pkg-config --variable=libdir pygobject-2.0) 32 | if [ x"${PYGLIB_LIBDIR}" = "x" ]; then 33 | echo "Could not determine PYGOBJECT library path, exiting." 34 | exit 1 35 | fi 36 | cp -a "${PYGLIB_LIBDIR}"/libpyglib*.so* "$APPDIR/usr/lib" 37 | (cd "$APPDIR/usr" && mkdir -p lib64 && cd lib64 && rm -rf python${PYTHON_VERSION} && ln -s ../lib/python${PYTHON_VERSION} .) || exit 1 38 | ls -l "$APPDIR/usr/lib64" 39 | 40 | 41 | 42 | gssapilib=$(ldconfig -p | grep 'libgssapi_krb5.so.2 (libc6,x86-64)'| awk 'NR==1{print $NF}') 43 | if [ x"$gssapilib" != "x" ]; then 44 | gssapilibdir=$(dirname "$gssapilib") 45 | cp -a "$gssapilibdir"/libgssapi_krb5*.so* "$APPDIR/usr/lib" 46 | fi 47 | 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/aferrero2707/gimp-appimage.svg?branch=master)](https://travis-ci.org/aferrero2707/gimp-appimage) 2 | 3 | # Introduction 4 | 5 | The GIMP AppImage is built on CentOS 7, using a custom [Docker container](https://github.com/aferrero2707/docker-centos7-gimp) that provides all the required up-to-date dependencies. 6 | 7 | The compilation of the BABL/GEGL/GIMP code under Docker is performed by the [build-appimage-centos7.sh](https://github.com/aferrero2707/gimp-appimage/blob/master/build-appimage-centos7.sh) shell script, while the [AppImage](https://appimage.org) bundle is created and packaged by the [package-appimage.sh](https://github.com/aferrero2707/gimp-appimage/blob/master/package-appimage.sh) script. 8 | 9 | A second step in the build process compiles a set of useful plug-ins ([build-appimage-plugins-centos7.sh](https://github.com/aferrero2707/gimp-appimage/blob/master/build-appimage-plugins-centos7.sh)), which are then bundled into an additional, full-featured AppImage package. 10 | 11 | The whole build process is automated with [Travis CI](https://travis-ci.org/aferrero2707/gimp-appimage), using [this configuration file](https://github.com/aferrero2707/gimp-appimage/blob/master/.travis.yml). A cron job is scheduled to run on a weekly basis and builds the git HEAD version of BABL/GEGL/GIMP. The updated AppImage package is automatically uploaded to the [continuous release page](https://github.com/aferrero2707/gimp-appimage/releases/tag/continuous). 12 | 13 | # GIMP plug-ins 14 | 15 | Several GIMP plug-ins that can work in combination with the AppImage can be downloaded from [here](https://github.com/aferrero2707/gimp-plugins-collection/releases/tag/continuous). 16 | 17 | This is the current list of available plug-ins: 18 | * [Resynthesizer](http://registry.gimp.org/node/25219) - texture synthesis 19 | * [Liquid rescale](http://liquidrescale.wikidot.com/) - content-aware image resizing based on seam carving 20 | * [NUfraw](https://sourceforge.net/projects/nufraw/) - RAW image processing 21 | * [G'MIC-Qt](https://gmic.eu/gimp.shtml) - the plug-in for the G'MIC filters library 22 | * [PhFGIMP](https://github.com/aferrero2707/PhFGimp) - front-end for the PhotoFlow editor 23 | 24 | Follow the instructions in the plug-ins release page to install them in your system. 25 | 26 | # Credits 27 | 28 | The AppImage uses a modified version of the exec-wrapper originally available from here: 29 | 30 | https://github.com/TheAssassin/linuxdeploy-plugin-checkrt 31 | 32 | It allows GIMP to spawn external commands with the original shell environment instead of the one proper to the AppImage itself. 33 | -------------------------------------------------------------------------------- /AppRun.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DIR="`dirname \"$0\"`" 4 | DIR="`( cd \"$DIR\" && readlink -f $(pwd) )`" 5 | echo "DIR: $DIR" 6 | export APPDIR=$DIR 7 | 8 | source "$APPDIR/apprun-helper.sh" 9 | save_environment 10 | make_temp_libdir 11 | link_libraries 12 | echo "AILIBDIR=$AILIBDIR" 13 | #export APPDIR2=$AILIBDIR 14 | fix_libxcb_dri3 15 | fix_stdlibcxx 16 | #fix_fontconfig 17 | fix_library "libfontconfig" 18 | fix_library "libfreetype" 19 | 20 | 21 | init_environment 22 | export APPDIRS=$AILIBDIR:$AILIBDIR/gimp/2.0/plug-ins:$HOME/.config/GIMP-AppImage/2.10/plug-ins:$APPDIRS 23 | echo "APPDIRS: $APPDIRS" 24 | 25 | init_gtk 26 | 27 | export PYTHONHOME=$DIR/usr/ 28 | 29 | export PATH=$DIR/usr/bin:$PATH 30 | 31 | export PYTHONPATH=$DIR/usr/share/pyshared/:$(readlink -f "$DIR/usr/lib/gimp/2.0/python"):$PYTHONPATH 32 | 33 | #export XDG_CONFIG_DIRS=$DIR/usr/share:$XDG_CONFIG_DIRS 34 | 35 | export PERLLIB=$DIR/usr/share/perl5/:$DIR/usr/lib/perl5/:$PERLLIB 36 | 37 | export GSETTINGS_SCHEMA_DIR=$DIR/usr/share/glib-2.0/schemas/:$GSETTINGS_SCHEMA_DIR 38 | 39 | export BABL_PATH=$(readlink -f "$DIR/usr/lib64/babl-0.1") 40 | echo "BABL_PATH $BABL_PATH" 41 | 42 | export GEGL_PATH=$(readlink -f "$DIR/usr/lib64/gegl-0.4") 43 | echo "GEGL_PATH $GEGL_PATH" 44 | 45 | mkdir -p "$AILIBDIR/gimp/2.0" 46 | 47 | ln -s $(readlink -f "$DIR/usr/lib/gimp/2.0")/* "$AILIBDIR/gimp/2.0" 48 | rm -f "$AILIBDIR/gimp/2.0/interpreters" 49 | cp -a $(readlink -f "$DIR/usr/lib/gimp/2.0")/interpreters "$AILIBDIR/gimp/2.0" 50 | sed -i -e "s|/usr/bin|$DIR/usr/bin|g" "$AILIBDIR/gimp/2.0/interpreters/pygimp.interp" 51 | cat "$AILIBDIR/gimp/2.0/interpreters/pygimp.interp" 52 | 53 | rm -f "$AILIBDIR/gimp/2.0/plug-ins" 54 | mkdir -p "$AILIBDIR/gimp/2.0/plug-ins" 55 | ln -s $(readlink -f "$DIR/usr/lib/gimp/2.0/plug-ins")/* "$AILIBDIR/gimp/2.0/plug-ins" 56 | #export GIMP2_PLUGINDIR=$(readlink -f "$DIR/usr/lib/gimp/2.0") 57 | export GIMP2_PLUGINDIR="$AILIBDIR/gimp/2.0" 58 | echo "GIMP2_PLUGINDIR: $GIMP2_PLUGINDIR" 59 | 60 | export GIMP2_DATADIR="$DIR/usr/share/gimp/2.0" 61 | export GIMP2_LOCALEDIR="$DIR/usr/share/locale" 62 | export GIMP2_SYSCONFDIR="$DIR/usr/etc/gimp/2.0" 63 | 64 | if [ -e /etc/fonts/fonts.conf ]; then 65 | export FONTCONFIG_PATH=/etc/fonts 66 | fi 67 | 68 | run_hooks 69 | 70 | load_external_plugins 71 | 72 | 73 | #cd $DIR/usr 74 | 75 | #bin/gimp "$@"; exit 76 | 77 | echo "Input parameters: \"$@\"" 78 | echo "" 79 | echo "Input File: $1" 80 | ldd $DIR/usr/bin/gimp.bin 81 | echo "" 82 | echo "$DIR/usr/bin/gimp.bin --pdb-compat-mode=on \"$@\"" 83 | #gdb -ex "run --pdb-compat-mode=on \"$@\"" $HERE/gimp.bin 84 | #gdb $HERE/gimp.bin 85 | which python 86 | #GDB=$(which gdb) 87 | #echo "Starting GDB ($GDB)" 88 | #$GDB 89 | #echo "GDB finished" 90 | 91 | export LD_PRELOAD=$DIR/usr/lib/exec_wrapper.so 92 | $DIR/usr/bin/gimp.wrapper --pdb-compat-mode=on "$@" 93 | 94 | rm -rf "$AILIBDIR" 95 | -------------------------------------------------------------------------------- /AppRun-v3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DIR="`dirname \"$0\"`" 4 | DIR="`( cd \"$DIR\" && readlink -f $(pwd) )`" 5 | echo "DIR: $DIR" 6 | export APPDIR=$DIR 7 | 8 | source "$APPDIR/apprun-helper.sh" 9 | save_environment 10 | make_temp_libdir 11 | link_libraries 12 | echo "AILIBDIR=$AILIBDIR" 13 | #export APPDIR2=$AILIBDIR 14 | fix_libxcb_dri3 15 | fix_stdlibcxx 16 | #fix_fontconfig 17 | fix_library "libfontconfig" 18 | fix_library "libfreetype" 19 | 20 | 21 | init_environment 22 | export APPDIRS=$AILIBDIR:$AILIBDIR/gimp/2.99/plug-ins:$HOME/.config/GIMP-AppImage/2.99/plug-ins:$APPDIRS 23 | echo "APPDIRS: $APPDIRS" 24 | 25 | init_gtk 26 | 27 | export PYTHONHOME=$DIR/usr/ 28 | 29 | export PATH=$DIR/usr/bin:$PATH 30 | 31 | export PYTHONPATH=$DIR/usr/share/pyshared/:$(readlink -f "$DIR/usr/lib/gimp/2.0/python"):$PYTHONPATH 32 | 33 | #export XDG_CONFIG_DIRS=$DIR/usr/share:$XDG_CONFIG_DIRS 34 | 35 | export PERLLIB=$DIR/usr/share/perl5/:$DIR/usr/lib/perl5/:$PERLLIB 36 | 37 | export GSETTINGS_SCHEMA_DIR=$DIR/usr/share/glib-2.0/schemas/:$GSETTINGS_SCHEMA_DIR 38 | 39 | export BABL_PATH=$(readlink -f "$DIR/usr/lib64/babl-0.1") 40 | echo "BABL_PATH $BABL_PATH" 41 | 42 | export GEGL_PATH=$(readlink -f "$DIR/usr/lib64/gegl-0.4") 43 | echo "GEGL_PATH $GEGL_PATH" 44 | 45 | export GI_TYPELIB_PATH=$DIR/usr/lib/girepository-1.0:${GI_TYPELIB_PATH} 46 | echo "GI_TYPELIB_PATH $GI_TYPELIB_PATH" 47 | 48 | mkdir -p "$AILIBDIR/gimp/2.99" 49 | 50 | ln -s $(readlink -f "$DIR/usr/lib/gimp/2.99")/* "$AILIBDIR/gimp/2.99" 51 | rm -rf "$AILIBDIR/gimp/2.99/interpreters" 52 | cp -a $(readlink -f "$DIR/usr/lib/gimp/2.99")/interpreters "$AILIBDIR/gimp/2.99" 53 | sed -i -e "s|/usr/bin|$DIR/usr/bin|g" "$AILIBDIR/gimp/2.99/interpreters/pygimp.interp" 54 | cat "$AILIBDIR/gimp/2.99/interpreters/pygimp.interp" 55 | 56 | rm -f "$AILIBDIR/gimp/2.99/plug-ins" 57 | mkdir -p "$AILIBDIR/gimp/2.99/plug-ins" 58 | ln -s $(readlink -f "$DIR/usr/lib/gimp/2.99/plug-ins")/* "$AILIBDIR/gimp/2.99/plug-ins" 59 | export GIMP3_PLUGINDIR="$AILIBDIR/gimp/2.99" 60 | echo "GIMP3_PLUGINDIR: $GIMP3_PLUGINDIR" 61 | export GIMP2_PLUGINDIR="$GIMP3_PLUGINDIR" 62 | echo "GIMP2_PLUGINDIR: $GIMP3_PLUGINDIR" 63 | 64 | export GIMP3_DATADIR="$DIR/usr/share/gimp/2.99" 65 | export GIMP3_LOCALEDIR="$DIR/usr/share/locale" 66 | export GIMP3_SYSCONFDIR="$DIR/usr/etc/gimp/2.99" 67 | 68 | if [ -e /etc/fonts/fonts.conf ]; then 69 | export FONTCONFIG_PATH=/etc/fonts 70 | fi 71 | 72 | run_hooks 73 | 74 | load_external_plugins 75 | 76 | 77 | #cd $DIR/usr 78 | 79 | #bin/gimp "$@"; exit 80 | 81 | echo "Input parameters: \"$@\"" 82 | echo "" 83 | echo "Input File: $1" 84 | ldd $DIR/usr/bin/gimp.bin 85 | echo "" 86 | echo "$DIR/usr/bin/gimp.bin --pdb-compat-mode=on \"$@\"" 87 | #gdb -ex "run --pdb-compat-mode=on \"$@\"" $HERE/gimp.bin 88 | #gdb $HERE/gimp.bin 89 | which python 90 | #GDB=$(which gdb) 91 | #echo "Starting GDB ($GDB)" 92 | #$GDB 93 | #echo "GDB finished" 94 | 95 | export LD_PRELOAD=$DIR/usr/lib/exec_wrapper.so 96 | $DIR/usr/bin/gimp.wrapper --pdb-compat-mode=on "$@" 97 | 98 | rm -rf "$AILIBDIR" 99 | -------------------------------------------------------------------------------- /appimage-helper-scripts/bundle-gtk2.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | echo "" 4 | echo "########################################################################" 5 | echo "" 6 | echo "Copying GTK libraries and configuration files" 7 | echo "" 8 | 9 | # Manually copy librsvg, because it is not picked automatically by copy_deps 10 | echo "========= copying LibRSVG =========" 11 | mkdir -p "$APPDIR/usr/lib" 12 | RSVG_LIBDIR=$(pkg-config --variable=libdir librsvg-2.0) 13 | if [ x"${RSVG_LIBDIR}" != "x" ]; then 14 | echo "cp -a ${RSVG_LIBDIR}/librsvg*.so* $APPDIR/usr/lib" 15 | cp -a "${RSVG_LIBDIR}"/librsvg*.so* "$APPDIR/usr/lib" 16 | fi 17 | 18 | 19 | echo "" 20 | echo "========= compile Glib schemas =========" 21 | # Compile Glib schemas 22 | glib_prefix="$(pkg-config --variable=prefix glib-2.0)" 23 | (mkdir -p "$APPDIR/usr/share/glib-2.0/schemas/" && \ 24 | cp -a ${glib_prefix}/share/glib-2.0/schemas/* "$APPDIR/usr/share/glib-2.0/schemas" && \ 25 | cd "$APPDIR/usr/share/glib-2.0/schemas/" && \ 26 | glib-compile-schemas .) || exit 1 27 | 28 | # Copy gconv ??? 29 | #cp -a /usr/lib64/gconv usr/lib 30 | 31 | 32 | 33 | echo "" 34 | echo "========= copy gdk-pixbuf modules and cache file =========" 35 | # Copy gdk-pixbuf modules and cache file, and patch the cache file 36 | # so that modules are picked from the AppImage bundle 37 | gdk_pixbuf_moduledir="$(pkg-config --variable=gdk_pixbuf_moduledir gdk-pixbuf-2.0)" 38 | gdk_pixbuf_cache_file="$(pkg-config --variable=gdk_pixbuf_cache_file gdk-pixbuf-2.0)" 39 | gdk_pixbuf_libdir_bundle="lib/gdk-pixbuf-2.0" 40 | gdk_pixbuf_cache_file_bundle="$APPDIR/usr/${gdk_pixbuf_libdir_bundle}/loaders.cache" 41 | 42 | mkdir -p "$APPDIR/usr/${gdk_pixbuf_libdir_bundle}" 43 | cp -a "$gdk_pixbuf_moduledir" "$APPDIR/usr/${gdk_pixbuf_libdir_bundle}" 44 | cp -a "$gdk_pixbuf_cache_file" "$APPDIR/usr/${gdk_pixbuf_libdir_bundle}" 45 | #sed -i -e "s|${gdk_pixbuf_moduledir}/|LOADERSDIR/|g" "$gdk_pixbuf_cache_file_bundle" 46 | sed -i -e "s|${gdk_pixbuf_moduledir}/||g" "$gdk_pixbuf_cache_file_bundle" 47 | 48 | printf '%s\n' "" "==================" "gdk-pixbuf cache:" 49 | cat "$gdk_pixbuf_cache_file_bundle" 50 | printf '%s\n' "==================" "gdk-pixbuf loaders:" 51 | ls "$APPDIR/usr/${gdk_pixbuf_libdir_bundle}/loaders" 52 | printf '%s\n' "==================" 53 | 54 | 55 | echo "" 56 | echo "========= copy the theme engines =========" 57 | # Copy the theme engines 58 | mkdir -p "$APPDIR/usr/lib/gtk-2.0" 59 | GTK_LIBDIR=$(pkg-config --variable=libdir gtk+-2.0) 60 | GTK_BINARY_VERSION=$(pkg-config --variable=gtk_binary_version gtk+-2.0) 61 | cp -a "${GTK_LIBDIR}/gtk-2.0/${GTK_BINARY_VERSION}"/* "$APPDIR/usr/lib/gtk-2.0" 62 | 63 | 64 | echo "" 65 | echo "========= fix PANGO cache file =========" 66 | # Remove absolute paths from pango modules cache (if existing) 67 | pqm="$(which pango-querymodules)" 68 | if [[ ! -z $pqm ]]; then 69 | version="$(pango-querymodules --version | tail -n 1 | tr -d " " | cut -d':' -f 2)" 70 | cat "/${PREFIX}/lib/pango/${version}/modules.cache" | sed "s|/${PREFIX}/lib/pango/${version}/modules/||g" > "$APPDIR/usr/lib/pango/${version}/modules.cache" 71 | fi 72 | 73 | 74 | -------------------------------------------------------------------------------- /appimage-helper-scripts/appimage-exec-wrapper2/env.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2018 Pablo Marcos Oltra 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all 11 | * copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | #define _GNU_SOURCE 23 | 24 | #include "env.h" 25 | #include "debug.h" 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | static char** env_allocate(size_t size) { 34 | return calloc(size + 1, sizeof(char*)); 35 | } 36 | 37 | void env_free(char* const *env) { 38 | size_t len = 0; 39 | while (env[len] != 0) { 40 | free(env[len]); 41 | len++; 42 | } 43 | free((char**)env); 44 | } 45 | 46 | static size_t get_number_of_variables(FILE *file, char **buffer, size_t *len) { 47 | size_t number = 0; 48 | 49 | if (getline(buffer, len, file) < 0) 50 | return -1; 51 | 52 | char *ptr = *buffer; 53 | while (ptr < *buffer + *len) { 54 | size_t var_len = strlen(ptr); 55 | ptr += var_len + 1; 56 | if (var_len == 0) 57 | break; 58 | number++; 59 | } 60 | 61 | return number != 0 ? (ssize_t)number : -1; 62 | } 63 | 64 | static char* const* env_from_buffer(FILE *file) { 65 | char *buffer = NULL; 66 | size_t len = 0; 67 | size_t num_vars = get_number_of_variables(file, &buffer, &len); 68 | char** env = env_allocate(num_vars); 69 | 70 | size_t n = 0; 71 | char *ptr = buffer; 72 | while (ptr < buffer + len && n < num_vars) { 73 | size_t var_len = strlen(ptr); 74 | if (var_len == 0) 75 | break; 76 | 77 | env[n] = calloc(sizeof(char*), var_len + 1); 78 | strncpy(env[n], ptr, var_len + 1); 79 | DEBUG("\tenv var copied: %s\n", env[n]); 80 | /*printf("\tenv var copied: %s\n", env[n]);*/ 81 | ptr += var_len + 1; 82 | n++; 83 | } 84 | free(buffer); 85 | DEBUG("\tenv: %p\n", (void*)env); 86 | 87 | return env; 88 | } 89 | 90 | static char* const* read_env_from_process(pid_t pid) { 91 | char buffer[256] = {0}; 92 | 93 | const char *envfile = getenv("AIPENV"); 94 | if (!envfile) 95 | return NULL; 96 | DEBUG("AIPENV = %s\n", envfile); 97 | 98 | 99 | snprintf(buffer, sizeof(buffer), "%s", envfile); 100 | /*snprintf(buffer, sizeof(buffer), "/proc/%d/environ", pid);*/ 101 | DEBUG("Reading env from parent process: %s\n", buffer); 102 | FILE *env_file = fopen(buffer, "r"); 103 | if (!env_file) { 104 | DEBUG("Error reading file: %s (%s)\n", buffer, strerror(errno)); 105 | return NULL; 106 | } 107 | 108 | char* const* env = env_from_buffer(env_file); 109 | fclose(env_file); 110 | 111 | return env; 112 | } 113 | 114 | char* const* read_parent_env() { 115 | pid_t ppid = getppid(); 116 | return read_env_from_process(ppid); 117 | } 118 | 119 | #ifdef ENV_TEST 120 | int main() { 121 | putenv("APPIMAGE_CHECKRT_DEBUG=1"); 122 | DEBUG("ENV TEST\n"); 123 | char **env = NULL; 124 | read_parent_env(&env); 125 | 126 | return 0; 127 | } 128 | #endif 129 | 130 | -------------------------------------------------------------------------------- /scripts/gimp.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | pwd 4 | export GIMPPREFIX=/usr/local/gimp 5 | export PKG_CONFIG_PATH=${GIMPPREFIX}/lib64/pkgconfig:${GIMPPREFIX}/lib/pkgconfig:${GIMPPREFIX}/share/pkgconfig:$PKG_CONFIG_PATH 6 | export ACLOCAL_PATH=${GIMPPREFIX}/share/aclocal:$ACLOCAL_PATH 7 | export LD_LIBRARY_PATH=${GIMPPREFIX}/lib64:${GIMPPREFIX}/lib:$LD_LIBRARY_PATH 8 | export PATH=${GIMPPREFIX}/bin:$PATH 9 | 10 | 11 | # Copy executable, icon and desktop file 12 | if [ x"${GTK_VERSION}" = "x3" ]; then 13 | GIMP_PREFIX=$(pkg-config --variable=prefix gimp-3.0) 14 | else 15 | GIMP_PREFIX=$(pkg-config --variable=prefix gimp-2.0) 16 | fi 17 | if [ x"${GIMP_PREFIX}" = "x" ]; then 18 | echo "Could not determine GIMP installation prefix, exiting." 19 | exit 1 20 | fi 21 | 22 | echo "Copying GIMP executable and desktop file" 23 | echo "GIMP_PREFIX: ${GIMP_PREFIX}" 24 | cp -a ${GIMP_PREFIX}/bin/gimp* "$APPDIR/usr/bin" || exit 1 25 | GIMP_EXE_NAME=$(cat ${GIMP_PREFIX}/share/applications/gimp.desktop | grep "^Exec=" | cut -d"=" -f 2 | cut -d" " -f 1) 26 | (cd "$APPDIR/usr/bin" && rm -f $LOWERAPP.bin && ln -s ${GIMP_EXE_NAME} $LOWERAPP.bin) || exit 1 27 | 28 | (mkdir -p "$APPDIR/usr/share" && cp -a ${GIMP_PREFIX}/share/$LOWERAPP "$APPDIR/usr/share") || exit 1 29 | (mkdir -p "$APPDIR/usr/share/applications" && cp ${GIMP_PREFIX}/share/applications/$LOWERAPP.desktop "$APPDIR/usr/share/applications") || exit 1 30 | 31 | echo "Copying GIMP icon" 32 | pwd 33 | WD="$(pwd)" 34 | cd ${GIMP_PREFIX}/share/icons/hicolor 35 | pwd 36 | for f in *; do 37 | echo "f: \"$f\"" 38 | ls $f/apps/$LOWERAPP.png 39 | if [ -e $f/apps/$LOWERAPP.png ]; then 40 | mkdir -p "$APPDIR/usr/share/icons/hicolor/$f/apps" || exit 1 41 | cp $f/apps/$LOWERAPP.png "$APPDIR/usr/share/icons/hicolor/$f/apps" || exit 1 42 | fi 43 | done 44 | cd "$WD" 45 | pwd 46 | 47 | echo "ls ${GIMP_PREFIX}/lib/gimp/" 48 | ls ${GIMP_PREFIX}/lib/gimp/ 49 | 50 | # Copy the GIMP python interpreter configuration 51 | (mkdir -p "$APPDIR/usr/lib/gimp" && \ 52 | cp -a ${GIMP_PREFIX}/lib/gimp/?.* "$APPDIR/usr/lib/gimp") || exit 1 53 | echo "ls $APPDIR/usr/lib/gimp" 54 | ls $APPDIR/usr/lib/gimp 55 | 56 | (mkdir -p "$APPDIR/usr/share/locale" && \ 57 | cp -a ${GIMP_PREFIX}/share/locale/* "$APPDIR/usr/share/locale") || exit 1 58 | echo "ls $APPDIR/usr/share/locale" 59 | ls $APPDIR/usr/share/locale 60 | 61 | (mkdir -p "$APPDIR/usr/share/gimp" && \ 62 | cp -a ${GIMP_PREFIX}/share/gimp/?.* "$APPDIR/usr/share/gimp") || exit 1 63 | echo "ls $APPDIR/usr/share/gimp" 64 | ls $APPDIR/usr/share/gimp 65 | 66 | (mkdir -p "$APPDIR/usr/etc/gimp" && \ 67 | cp -a ${GIMP_PREFIX}/etc/gimp/?.* "$APPDIR/usr/etc/gimp") || exit 1 68 | echo "ls $APPDIR/usr/etc/gimp" 69 | ls $APPDIR/usr/etc/gimp 70 | 71 | BABL_LIBDIR=$(pkg-config --variable=libdir babl) 72 | if [ x"${BABL_LIBDIR}" = "x" ]; then 73 | echo "Cannot determine BABL libdir, exiting"; exit 1; 74 | fi 75 | echo "BABL_LIBDIR: ${BABL_LIBDIR}" 76 | BABL_LIBDIR_NAME="$(basename ${BABL_LIBDIR})" 77 | mkdir -p "$APPDIR/usr/${BABL_LIBDIR_NAME}" || exit 1 78 | cp -a "${BABL_LIBDIR}/babl-0.1" "$APPDIR/usr/${BABL_LIBDIR_NAME}" || exit 1 79 | ls -l "$APPDIR/usr/${BABL_LIBDIR_NAME}" 80 | 81 | GEGL_LIBDIR=$(pkg-config --variable=libdir gegl-0.4) 82 | echo "GEGL_LIBDIR: ${GEGL_LIBDIR}" 83 | GEGL_LIBDIR_NAME="$(basename ${GEGL_LIBDIR})" 84 | mkdir -p "$APPDIR/usr/${GEGL_LIBDIR_NAME}" || exit 1 85 | GEGL_PLUGDIR=$(pkg-config --variable=pluginsdir gegl-0.4) 86 | if [ x"${GEGL_PLUGDIR}" = "x" ]; then 87 | echo "Cannot determine GEGL pluginsdir, exiting"; exit 1; 88 | fi 89 | echo "GEGL_PLUGDIR: ${GEGL_PLUGDIR}" 90 | mkdir -p "$APPDIR/usr/${GEGL_LIBDIR_NAME}" || exit 1 91 | cp -a "${GEGL_PLUGDIR}" "$APPDIR/usr/${GEGL_LIBDIR_NAME}" || exit 1 92 | ls -l "$APPDIR/usr/${GEGL_LIBDIR_NAME}" 93 | 94 | 95 | cp -a "/${PREFIX}/share/mypaint-data" "$APPDIR/usr/share/gimp/2.0" 96 | 97 | 98 | 99 | # Package BABL/GEGL/GIMP header and pkg-config files, 100 | # so that the AppImage can be used to compile plug-ins 101 | mkdir "$APPDIR/usr/include" 102 | mkdir "$APPDIR/usr/lib/pkgconfig" 103 | for dir in babl gegl gimp; do 104 | cp -a "${GIMP_PREFIX}/include/${dir}"* "$APPDIR/usr/include" 105 | done 106 | 107 | mkdir -p "$APPDIR/usr/${BABL_LIBDIR_NAME}/pkgconfig" || exit 1 108 | cp -a "${BABL_LIBDIR}/pkgconfig/babl"*.pc "$APPDIR/usr/${BABL_LIBDIR_NAME}/pkgconfig" || exit 1 109 | 110 | mkdir -p "$APPDIR/usr/${GEGL_LIBDIR_NAME}/pkgconfig" || exit 1 111 | cp -a "${GEGL_LIBDIR}/pkgconfig/gegl"*.pc "$APPDIR/usr/${GEGL_LIBDIR_NAME}/pkgconfig" || exit 1 112 | 113 | 114 | if [ x"${GTK_VERSION}" = "x3" ]; then 115 | GIMP_LIBDIR=$(pkg-config --variable=libdir gimp-3.0) 116 | else 117 | GIMP_LIBDIR=$(pkg-config --variable=libdir gimp-2.0) 118 | fi 119 | echo "GIMP_LIBDIR: ${GIMP_LIBDIR}" 120 | GIMP_LIBDIR_NAME="$(basename ${GIMP_LIBDIR})" 121 | mkdir -p "$APPDIR/usr/${GIMP_LIBDIR_NAME}/pkgconfig" || exit 1 122 | cp -a "${GIMP_LIBDIR}/pkgconfig/gimp"*.pc "$APPDIR/usr/${GIMP_LIBDIR_NAME}/pkgconfig" || exit 1 123 | -------------------------------------------------------------------------------- /package-appimage.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | VER_SUFFIX="$1" 4 | PREFIX=zyx 5 | APP=gimp 6 | LOWERAPP=${APP,,} 7 | export PATH=/$PREFIX/bin:$PATH 8 | export LD_LIBRARY_PATH=/$PREFIX/lib64:/$PREFIX/lib:$LD_LIBRARY_PATH 9 | export XDG_DATA_DIRS=/$PREFIX/share:$XDG_DATA_DIRS 10 | export PKG_CONFIG_PATH=/$PREFIX/lib/pkgconfig:/$PREFIX/share/pkgconfig:$PKG_CONFIG_PATH 11 | 12 | 13 | # get some useful helper functions 14 | source /sources/appimage-helper-scripts/functions.sh 15 | 16 | 17 | # copy the list of libraries that have to be excluded from the bundle 18 | export APPDIR="${APPROOT}/$APP.AppDir" 19 | (rm -rf "${APPDIR}" && mkdir -p "${APPROOT}/$APP.AppDir/usr/bin") || exit 1 20 | cp /sources/appimage-helper-scripts/excludelist "${APPROOT}" 21 | 22 | 23 | # copy the MIME database 24 | mkdir -p "$APPDIR/usr/share/image" 25 | cp -a /usr/share/mime/image/x-*.xml "$APPDIR/usr/share/image" || exit 1 26 | 27 | 28 | # run the hook scripts 29 | run_hooks 30 | 31 | 32 | # build and install zenity 33 | (cd /work && rm -rf zenity && git clone https://github.com/aferrero2707/zenity.git && \ 34 | cd zenity && ./autogen.sh && ./configure --prefix=/usr/local && make install && \ 35 | cp -a /usr/local/bin/zenity "$APPDIR/usr/bin" && \ 36 | cp -a /usr/local/share/zenity "$APPDIR/usr/share" && \ 37 | cp /sources/appimage-helper-scripts/zenity.sh "$APPDIR/usr/bin/zenity.sh") || exit 1 38 | 39 | 40 | 41 | 42 | # enter the AppImage bundle 43 | cd "$APPDIR" || exit 1 44 | 45 | 46 | # Copy in the indirect dependencies 47 | # Three runs to ensure we catch indirect ones 48 | copy_deps2 ; copy_deps2 ; copy_deps2 ; 49 | 50 | 51 | # Remove unneeded libraries 52 | delete_blacklisted2 53 | 54 | # Put the gcc libraries in optional folders 55 | copy_gcc_libs 56 | 57 | 58 | # copy the startup scripts 59 | if [ x"${GTK_VERSION}" = "x3" ]; then 60 | cp -a /sources/AppRun-v3.sh "$APPDIR/AppRun" || exit 1 61 | else 62 | cp -a /sources/AppRun.sh "$APPDIR/AppRun" || exit 1 63 | fi 64 | 65 | cp /sources/appimage-helper-scripts/apprun-helper.sh "$APPDIR/apprun-helper.sh" || exit 1 66 | 67 | # bundle the desktop file and application icon 68 | get_desktop 69 | get_icon 70 | 71 | 72 | # Workaround for: 73 | # ImportError: /usr/lib/x86_64-linux-gnu/libgdk-x11-2.0.so.0: undefined symbol: XRRGetMonitors 74 | cp $(ldconfig -p | grep libgdk-x11-2.0.so.0 | cut -d ">" -f 2 | xargs) ./usr/lib/ 75 | cp $(ldconfig -p | grep libgtk-x11-2.0.so.0 | cut -d ">" -f 2 | xargs) ./usr/lib/ 76 | 77 | 78 | # build and bundle the exec wrapper 79 | # it is used to restore the origin environment when executing 80 | # commands that are outside of the AppImage bundle 81 | source /sources/appimage-helper-scripts/bundle-exec-wrapper.sh || exit 1 82 | 83 | 84 | # remove debugging symbols for bundled executables and libraries (saves some space) 85 | #strip_binaries 86 | 87 | 88 | # assemble the version string 89 | echo "GIMP_GIT_TAG = \"$GIMP_GIT_TAG\"" 90 | VERSION="" 91 | if [ x"${GTK_VERSION}" = "x3" ]; then 92 | VERSION=git-$(pkg-config --modversion gimp-3.0)${VER_SUFFIX}-$(date +%Y%m%d) 93 | else 94 | if [ x"$GIMP_GIT_TAG" = "x" ]; then 95 | VERSION=git-$(pkg-config --modversion gimp-2.0)${VER_SUFFIX}-$(date +%Y%m%d) 96 | else 97 | VERSION=release-$(pkg-config --modversion gimp-2.0)${VER_SUFFIX} 98 | fi 99 | fi 100 | GLIBC_NEEDED=$(glibc_needed) 101 | echo $VERSION 102 | 103 | 104 | # cinfigure the desktop integration 105 | get_desktopintegration $LOWERAPP 106 | cp -a "/sources/appimage-helper-scripts/app.wrapper" "$APPDIR/usr/bin/$LOWERAPP.wrapper" || exit 1 107 | 108 | echo "ls $APPDIR/usr/share/gimp" 109 | ls $APPDIR/usr/share/gimp 110 | 111 | 112 | # Go out of AppImage 113 | cd .. 114 | 115 | echo "Building AppImage..." 116 | pwd 117 | rm -rf ../out 118 | 119 | export ARCH="x86_64" 120 | export NO_GLIBC_VERSION=true 121 | export DOCKER_BUILD=true 122 | mkdir -p /sources/out 123 | generate_type2_appimage 124 | cp -a ../out/*.AppImage /sources/out/GIMP_AppImage-${VERSION}-${ARCH}.AppImage 125 | 126 | 127 | # do not bundle plugins for 2.99 128 | if [ x"${GTK_VERSION}" = "x3" ]; then exit 0; fi 129 | 130 | 131 | rm -f /tmp/plugin-list.txt 132 | wget -O /tmp/plugin-list.txt https://raw.githubusercontent.com/aferrero2707/gimp-plugins-collection/check/plugin-list.txt 133 | cat /tmp/plugin-list.txt 134 | 135 | mkdir -p "$APPDIR/plug-ins" || exit 1 136 | while IFS='' read -r line || [[ -n "$line" ]]; do 137 | PLUGIN=${line} 138 | RELEASE_URL="https://github.com/aferrero2707/gimp-plugins-collection/releases/download/continuous" 139 | wget -O "/tmp/${PLUGIN}-Gimp-2.10-linux.AppImage" "${RELEASE_URL}/${PLUGIN}-Gimp-2.10-linux.AppImage" 140 | if [ ! -e "/tmp/${PLUGIN}-Gimp-2.10-linux.AppImage" ]; then continue; fi 141 | chmod +x "/tmp/${PLUGIN}-Gimp-2.10-linux.AppImage" 142 | 143 | (mkdir -p "/tmp/${PLUGIN}.AppDir" && cd "/tmp/${PLUGIN}.AppDir" && \ 144 | "/tmp/${PLUGIN}-Gimp-2.10-linux.AppImage" --appimage-extract) || exit 1 145 | bash "/tmp/${PLUGIN}.AppDir/squashfs-root/AppRun" "$APPDIR/plug-ins" 146 | 147 | rm -rf "/tmp/${PLUGIN}.AppDir" "/tmp/${PLUGIN}-Gimp-2.10-linux.AppImage" 148 | 149 | done < /tmp/plugin-list.txt 150 | 151 | generate_type2_appimage 152 | cp -a ../out/*.AppImage /sources/out/GIMP_AppImage-${VERSION}-withplugins-${ARCH}.AppImage 153 | -------------------------------------------------------------------------------- /appimage-helper-scripts/excludelist: -------------------------------------------------------------------------------- 1 | # This file lists libraries that we will assume to be present on the host system and hence 2 | # should NOT be bundled inside AppImages. This is a working document; expect it to change 3 | # over time. File format: one filename per line. Each entry should have a justification comment. 4 | 5 | ld-linux.so.2 6 | ld-linux-x86-64.so.2 7 | libanl.so.1 8 | libBrokenLocale.so.1 9 | libcidn.so.1 10 | libcrypt.so.1 11 | libc.so.6 12 | libdl.so.2 13 | libm.so.6 14 | libmvec.so.1 15 | libnsl.so.1 16 | libnss_compat.so.2 17 | libnss_db.so.2 18 | libnss_dns.so.2 19 | libnss_files.so.2 20 | libnss_hesiod.so.2 21 | libnss_nisplus.so.2 22 | libnss_nis.so.2 23 | libpthread.so.0 24 | libresolv.so.2 25 | librt.so.1 26 | libthread_db.so.1 27 | libutil.so.1 28 | # These files are all part of the GNU C Library which should never be bundled. 29 | # List was generated from a fresh build of glibc 2.25. 30 | 31 | libstdc++.so.6 32 | # Workaround for: 33 | # usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.21' not found 34 | 35 | libGL.so.1 36 | # Part of the video driver (OpenGL); present on any regular 37 | # desktop system, may also be provided by proprietary drivers. 38 | # Known to cause issues if it's bundled. 39 | 40 | libdrm.so.2 41 | # Workaround for: 42 | # Antergos Linux release 2015.11 (ISO-Rolling) 43 | # /usr/lib/libdrm_amdgpu.so.1: error: symbol lookup error: undefined symbol: drmGetNodeTypeFromFd (fatal) 44 | # libGL error: unable to load driver: swrast_dri.so 45 | # libGL error: failed to load driver: swrast 46 | # Unrecognized OpenGL version 47 | 48 | #libxcb.so.1 49 | # Workaround for: 50 | # Fedora 23 51 | # symbol lookup error: /lib64/libxcb-dri3.so.0: undefined symbol: xcb_send_fd 52 | # Uncertain if this is required to be bundled for some distributions - if so we need to write a version check script and use LD_PRELOAD to load the system version if it is newer 53 | # Fedora 25: 54 | # undefined symbol: xcb_send_request_with_fds 55 | # https://github.com/probonopd/AppImages/issues/128 56 | 57 | libX11.so.6 58 | # Workaround for: 59 | # Fedora 23 60 | # symbol lookup error: ./lib/libX11.so.6: undefined symbol: xcb_wait_for_reply64 61 | # Uncertain if this is required to be bundled for some distributions - if so we need to write a version check script and use LD_PRELOAD to load the system version if it is newer 62 | 63 | #libxkbcommon.so.0 64 | #libxkbcommon-x11.so.0 65 | # Workaround for: 66 | # xkbcommon: ERROR: failed to add default include path ././/share/X11/xkb 67 | 68 | libdbus-1.so.3.6.0 69 | libdbus-1.so.3 70 | libdbus-1.so 71 | # Workaround for: 72 | # D-Bus library appears to be incorrectly set up; failed to read machine uuid: Failed to open "././/var/lib/dbus/machine-id": No such file or directory 73 | 74 | #libgio-2.0.so.0 75 | # Workaround for: 76 | # On Ubuntu, "symbol lookup error: /usr/lib/x86_64-linux-gnu/gtk-2.0/modules/liboverlay-scrollbar.so: undefined symbol: g_settings_new" 77 | 78 | libgdk-x11-2.0.so.0 79 | libgtk-x11-2.0.so.0 80 | # Simply to reduce size - not known to cause issues 81 | 82 | libasound.so.2 83 | # Workaround for: 84 | # No sound, e.g., in VLC.AppImage (does not find sound cards) 85 | 86 | #libgdk_pixbuf-2.0.so.0 87 | # Workaround for: 88 | # On Ubuntu, get (inkscape:25621): GdkPixbuf-WARNING **: Error loading XPM image loader: Image type 'xpm' is not supported 89 | 90 | #libfontconfig.so.1 91 | # Workaround for: 92 | # Application stalls when loading fonts during application launch; e.g., KiCad on ubuntu-mate 93 | 94 | #libselinux.so.1 95 | # Workaround for: 96 | # sed: error while loading shared libraries: libpcre.so.3: cannot open shared object file: No such file or directory 97 | 98 | # The following are assumed to be part of the base system 99 | # Removing these has worked e.g., for Krita. Feel free to report if 100 | # you think that some of these should go into AppImages and why. 101 | libcom_err.so.2 102 | libcrypt.so.1 103 | #libexpat.so.1 104 | libgcc_s.so.1 105 | #libglib-2.0.so.0 106 | libgpg-error.so.0 107 | libgpg-error.so.0.6.0 108 | #libgssapi_krb5.so.2 # Disputed, seemingly needed by Arch Linux since Kerberos is named differently there 109 | # libgssapi.so.3 # Seemingly needed when running Ubuntu 14.04 binaries on Fedora 23 110 | libhcrypto.so.4 111 | # libheimbase.so.1 # Seemingly needed when running Ubuntu 14.04 binaries on Fedora 23 112 | # libheimntlm.so.0 # Seemingly needed when running Ubuntu 14.04 binaries on Fedora 23 113 | libhx509.so.5 114 | libICE.so.6 115 | #libidn.so.11 # Needed on systems with newer versions 116 | #libk5crypto.so.3 117 | #libkeyutils.so.1 118 | #libkrb5.so.26 # Disputed, seemingly needed by Arch Linux since Kerberos is named differently there 119 | #libkrb5.so.3 # Disputed, seemingly needed by Arch Linux since Kerberos is named differently there 120 | #libkrb5support.so.0 # Disputed, seemingly needed by Arch Linux since Kerberos is named differently there 121 | libp11-kit.so.0 122 | # libpcre.so.3 # Missing on Fedora 24 and on SLED 12 SP1 123 | libroken.so.18 124 | # libsasl2.so.2 # Seemingly needed when running Ubuntu 14.04 binaries on Fedora 23 125 | libSM.so.6 126 | libusb-1.0.so.0 127 | libuuid.so.1 128 | libwind.so.0 129 | libz.so.1 130 | 131 | # Potentially dangerous libraries 132 | #libgobject-2.0.so.0 133 | 134 | # Workaround for: 135 | # e.g., Spotify 136 | # relocation error: /lib/x86_64-linux-gnu/libgcrypt.so.20: 137 | # symbol gpgrt_lock_lock, version GPG_ERROR_1.0 not defined 138 | # in file libgpg-error.so.0 with link time reference 139 | libgpg-error.so.0 140 | 141 | # Unsolved issue: 142 | # https://github.com/probonopd/linuxdeployqt/issues/35 143 | # Error initializing NSS with a persistent database (sql:/home/me/.pki/nssdb): libsoftokn3.so: cannot open shared object file: No such file or directory 144 | # Error initializing NSS without a persistent database: NSS error code: -5925 145 | # nss_error=-5925, os_error=0 146 | # libnss3.so should not be removed from the bundles, as this causes other issues, e.g., 147 | # https://github.com/probonopd/linuxdeployqt/issues/35#issuecomment-256213517 148 | # and https://github.com/probonopd/AppImages/pull/114 149 | # libnss3.so 150 | 151 | # The following cannot be excluded, see 152 | # https://github.com/probonopd/AppImages/commit/6c7473d8cdaaa2572248dcc53d7f617a577ade6b 153 | # http://stackoverflow.com/questions/32644157/forcing-a-binary-to-use-a-specific-newer-version-of-a-shared-library-so 154 | # libssl.so.1 155 | # libssl.so.1.0.0 156 | # libcrypto.so.1 157 | # libcrypto.so.1.0.0 158 | -------------------------------------------------------------------------------- /appimage-helper-scripts/appimage-exec-wrapper2/exec.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2018 Pablo Marcos Oltra 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all 11 | * copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | /* 23 | * This exec.so library is intended to restore the environment of the AppImage's 24 | * parent process. This is done to avoid library clashing of bundled libraries 25 | * with external processes. e.g when running the web browser 26 | * 27 | * The intended usage is as follows: 28 | * 29 | * 1. This library is injected to the dynamic loader through LD_PRELOAD 30 | * automatically in AppRun **only** if `usr/optional/exec.so` exists: 31 | * e.g `LD_PRELOAD=$APPDIR/usr/optional/exec.so My.AppImage` 32 | * 33 | * 2. This library will intercept calls to new processes and will detect whether 34 | * those calls are for binaries within the AppImage bundle or external ones. 35 | * 36 | * 3. In case it's an internal process, it will not change anything. 37 | * In case it's an external process, it will restore the environment of 38 | * the AppImage parent by reading `/proc/[pid]/environ`. 39 | * This is the conservative approach taken. 40 | */ 41 | 42 | #define _GNU_SOURCE 43 | 44 | #include "env.h" 45 | #include "debug.h" 46 | 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | 53 | typedef int (*execve_func_t)(const char *filename, char *const argv[], char *const envp[]); 54 | 55 | #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) 56 | 57 | static const char* get_fullpath(const char *filename) { 58 | // Try to get the canonical path in case it's a relative path or symbolic 59 | // link. Otherwise, use which to get the fullpath of the binary 60 | char *fullpath = canonicalize_file_name(filename); 61 | DEBUG("filename %s, canonical path %s\n", filename, fullpath); 62 | if (fullpath) 63 | return fullpath; 64 | 65 | return filename; 66 | } 67 | 68 | static int is_external_process(const char *filename) { 69 | const char *appdirs = getenv("APPDIRS"); 70 | if (!appdirs) 71 | return 0; 72 | DEBUG("APPDIRS = %s\n", appdirs); 73 | /*printf("is_external_process: filename = %s\n", filename);*/ 74 | /*printf("is_external_process: APPDIRS = %s\n", appdirs);*/ 75 | int pos = 0; 76 | int len = strlen(appdirs); 77 | /*printf("is_external_process: len = %d\n", len);*/ 78 | while( pos < len) { 79 | int start = pos; 80 | /*printf("is_external_process: start = %d\n", start);*/ 81 | while( pos < len) { 82 | //printf("is_external_process: appdirs[%d] = %c\n", pos, appdirs[pos]); 83 | if(appdirs[pos] == ':') { 84 | /*printf("is_external_process: path delimiter found\n");*/ 85 | break; 86 | } 87 | pos += 1; 88 | } 89 | if(pos > start) { 90 | char* appdir = (char*)malloc(pos-start+1); 91 | strncpy(appdir, &(appdirs[start]), pos-start); 92 | appdir[pos-start] = '\0'; 93 | /*printf("is_external_process: appdir = %s\n", appdir);*/ 94 | int result = strncmp(filename, appdir, MIN(strlen(filename), strlen(appdir))); 95 | free(appdir); 96 | if( result==0 ) { 97 | printf("is_external_process: bundled process found: %s\n", filename); 98 | return 0; 99 | } 100 | } 101 | pos += 1; 102 | } 103 | 104 | /*printf("is_external_process: external process found\n");*/ 105 | return 1; 106 | } 107 | 108 | static int exec_common(execve_func_t function, const char *filename, char* const argv[], char* const envp[]) { 109 | const char *fullpath = get_fullpath(filename); 110 | DEBUG("filename %s, fullpath %s\n", filename, fullpath); 111 | char* const *env = envp; 112 | if (is_external_process(fullpath)) { 113 | DEBUG("External process detected. Restoring env vars from parent %d\n", getppid()); 114 | env = read_parent_env(); 115 | DEBUG("exec_common: env: %p\n", (void*)env); 116 | if (!env) 117 | env = envp; 118 | else 119 | DEBUG("Error restoring env vars from parent\n"); 120 | } 121 | int ret = function(filename, argv, env); 122 | 123 | if (fullpath != filename) 124 | free((char*)fullpath); 125 | if (env != envp) 126 | env_free(env); 127 | 128 | return ret; 129 | } 130 | 131 | int execve(const char *filename, char *const argv[], char *const envp[]) { 132 | DEBUG("execve call hijacked: %s\n", filename); 133 | execve_func_t execve_orig = dlsym(RTLD_NEXT, "execve"); 134 | if (!execve_orig) 135 | DEBUG("Error getting execve original symbol: %s\n", strerror(errno)); 136 | 137 | return exec_common(execve_orig, filename, argv, envp); 138 | } 139 | 140 | int execv(const char *filename, char *const argv[]) { 141 | DEBUG("execv call hijacked: %s\n", filename); 142 | return execve(filename, argv, environ); 143 | } 144 | 145 | int execvpe(const char *filename, char *const argv[], char *const envp[]) { 146 | DEBUG("execvpe call hijacked: %s\n", filename); 147 | execve_func_t execve_orig = dlsym(RTLD_NEXT, "execvpe"); 148 | if (!execve_orig) 149 | DEBUG("Error getting execvpe original symbol: %s\n", strerror(errno)); 150 | 151 | return exec_common(execve_orig, filename, argv, envp); 152 | } 153 | 154 | int execvp(const char *filename, char *const argv[]) { 155 | DEBUG("execvp call hijacked: %s\n", filename); 156 | return execvpe(filename, argv, environ); 157 | } 158 | 159 | #ifdef EXEC_TEST 160 | int main(int argc, char *argv[]) { 161 | putenv("APPIMAGE_CHECKRT_DEBUG=1"); 162 | DEBUG("EXEC TEST\n"); 163 | execv("./env_test", argv); 164 | 165 | return 0; 166 | } 167 | #endif 168 | -------------------------------------------------------------------------------- /appimage-helper-scripts/apprun-helper.sh: -------------------------------------------------------------------------------- 1 | save_environment() { 2 | TMPFILE="$(mktemp)" 3 | env | tr '\n' '\0' > "$TMPFILE" 4 | export AIPENV="$TMPFILE" 5 | } 6 | 7 | 8 | make_temp_libdir() { 9 | AILIBDIR="$(mktemp -d)" 10 | export AILIBDIR 11 | #export LD_LIBRARY_PATH=$AILIBDIR:$LD_LIBRARY_PATH 12 | } 13 | 14 | 15 | link_libraries() { 16 | ln -s "$APPDIR/usr/lib"/*.so* "$AILIBDIR" 17 | } 18 | 19 | 20 | fix_libxcb_dri3() { 21 | libxcbdri3="$(/sbin/ldconfig -p | grep 'libxcb-dri3.so.0 (libc6,x86-64'| awk 'NR==1{print $NF}')" 22 | temp="$(strings $libxcbdri3 | grep xcb_dri3_get_supported_modifiers)" 23 | if [ -n "$temp" ]; then 24 | echo "deleting $AILIBDIR/libxcb-dri3.so*" 25 | rm -f "$AILIBDIR"/libxcb-dri3.so* 26 | fi 27 | } 28 | 29 | 30 | fix_stdlibcxx() { 31 | # libstdc++ version detection 32 | stdcxxlib="$(/sbin/ldconfig -p | grep 'libstdc++.so.6 (libc6,x86-64)'| awk 'NR==1{print $NF}')" 33 | echo "System stdc++ library: \"$stdcxxlib\"" 34 | stdcxxver1=$(strings "$stdcxxlib" | grep '^GLIBCXX_[0-9].[0-9]*' | cut -d"_" -f 2 | sort -V | tail -n 1) 35 | echo "System stdc++ library version: \"$stdcxxver1\"" 36 | stdcxxver2=$(strings "$APPDIR/usr/optional/libstdc++/libstdc++.so.6" | grep '^GLIBCXX_[0-9].[0-9]*' | cut -d"_" -f 2 | sort -V | tail -n 1) 37 | echo "Bundled stdc++ library version: \"$stdcxxver2\"" 38 | stdcxxnewest=$(echo "$stdcxxver1 $stdcxxver2" | tr " " "\n" | sort -V | tail -n 1) 39 | echo "Newest stdc++ library version: \"$stdcxxnewest\"" 40 | if [[ x"$stdcxxnewest" = x"$stdcxxver1" ]]; then 41 | echo "Using system stdc++ library" 42 | else 43 | echo "Using bundled stdc++ library" 44 | ln -s "$APPDIR/usr/optional/libstdc++"/*.so* "$AILIBDIR" 45 | fi 46 | 47 | atomiclib="$(/sbin/ldconfig -p | grep 'libatomic.so.1 (libc6,x86-64)'| awk 'NR==1{print $NF}')" 48 | echo "atomiclib: $atomiclib" 49 | if [[ x"$atomiclib" = "x" ]]; then 50 | echo "Using bundled atomic library" 51 | ln -s "$APPDIR/usr/optional/libstdc++"/libatomic.so* "$AILIBDIR" 52 | fi 53 | } 54 | 55 | 56 | fix_fontconfig() { 57 | # fonconfig version detection 58 | fclib="$(/sbin/ldconfig -p | grep 'libfontconfig' | grep '(libc6,x86-64)'| awk 'NR==1{print $NF}')" 59 | if [ -n "$fclib" ]; then 60 | fclib=$(readlink -f "$fclib") 61 | fcv=$(basename "$fclib" | tail -c +18) 62 | fi 63 | fclib2="$(ls $APPDIR/usr/optional/fontconfig/libfontconfig.so.*.*.* | head -n 1)" 64 | if [ -n "$fclib2" ]; then 65 | fclib2=$(readlink -f "$fclib2") 66 | fcv2=$(basename "$fclib2" | tail -c +18) 67 | fi 68 | echo "fcv: \"$fcv\" fcv2: \"$fcv2\"" 69 | if [ x"$fclib" = "x" ]; then 70 | echo "Ssystem fontconfig missing, using bundled fontconfig library" 71 | ln -s "$APPDIR/usr/optional/fontconfig"/*.so* "$AILIBDIR" 72 | export FONTCONFIG_PATH="$APPDIR/usr/etc/fonts/fonts.conf" 73 | fi 74 | if [ x"$fclib" != "x" -a x"$fclib2" != "x" ]; then 75 | echo "echo \"$fcv $fcv2\" | tr \" \" \"\n\" | sort -V | tail -n 1" 76 | fcvnewest=$(echo "$fcv $fcv2" | tr " " "\n" | sort -V | tail -n 1) 77 | 78 | echo "Newest fontconfig library version: \"$fcvnewest\"" 79 | if [[ x"$fcvnewest" = x"$fcv" ]]; then 80 | echo "Using system fontconfig library" 81 | rm -f "$AILIBDIR"/libfontconfig*.so* 82 | else 83 | echo "Using bundled fontconfig library" 84 | ln -s "$APPDIR/usr/optional/fontconfig"/*.so* "$AILIBDIR" 85 | export FONTCONFIG_PATH="$APPDIR/usr/etc/fonts/fonts.conf" 86 | fi 87 | fi 88 | } 89 | 90 | 91 | fix_library() { 92 | lib="$1" 93 | echo "Checking versions of library \"$lib\"" 94 | syslib="$(/sbin/ldconfig -p | grep "$lib" | grep '(libc6,x86-64)'| awk 'NR==1{print $NF}')" 95 | if [ -n "$syslib" ]; then 96 | syslib2="$(ls -1 "${syslib}"* | tail -n 1)" 97 | syslib3="$(basename "$syslib2")" 98 | echo " system library: \"$syslib2\" ($syslib3)" 99 | lv="$(echo "$syslib3" | sed 's/so\./\n/' | tail -n 1)" 100 | else 101 | lv="" 102 | fi 103 | echo " system library version: $lv" 104 | 105 | ailib="$(realpath "$(ls "$AILIBDIR/$lib.so"* | tail -n 1)")" 106 | echo " ailib: \"$ailib\"" 107 | if [ -n "$ailib" ]; then 108 | ailib3="$(basename "$ailib")" 109 | echo " bundled library: \"$ailib\" ($ailib3)" 110 | lv2="$(echo "$ailib3" | sed 's/so\./\n/' | tail -n 1)" 111 | else 112 | lv2="" 113 | fi 114 | echo " bundled library version: $lv2" 115 | 116 | lvn=$(echo "$lv $lv2" | tr " " "\n" | sort -V | tail -n 1) 117 | echo " newest library version: \"$lvn\"" 118 | if [ "$lvn" = "$lv" ]; then 119 | echo "Removing bundled \"$lib\"" 120 | rm -v -f "${AILIBDIR}/$lib.so"* 121 | fi 122 | } 123 | 124 | 125 | 126 | 127 | # Execute user-supplied startup hook scripts 128 | load_external_plugins() 129 | { 130 | for pd in "$HOME/.config/GIMP-AppImage/2.10/plug-ins"/*; do 131 | if [ ! -e "$pd/plug-ins" ]; then continue; fi 132 | echo "load_external_plugins: linking plug-ins under $pd" 133 | ln -f -s "$pd" "$GIMP2_PLUGINDIR/plug-ins" 134 | ln -f -s "$pd/plug-ins"/* "${GIMP2_PLUGINDIR}/plug-ins" 135 | 136 | if [ -e "$pd"/scripts/set_exists.sh ]; then 137 | echo "load_external_plugins: sourcing $pd/scripts/set_exists.sh" 138 | source "$pd"/scripts/set_exists.sh 139 | fi 140 | 141 | if [ -e "$pd"/scripts/startup.sh ]; then 142 | echo "load_external_plugins: sourcing $pd/scripts/startup.sh" 143 | source "$pd"/scripts/startup.sh 144 | fi 145 | done 146 | 147 | for pd in "$APPDIR/plug-ins"/*; do 148 | if [ ! -e "$pd/plug-ins" ]; then continue; fi 149 | if [ ! -e "$pd"/scripts/check_exists.sh ]; then continue; fi 150 | bash "$pd"/scripts/check_exists.sh 151 | if [ $? -ne 0 ]; then continue; fi 152 | 153 | echo "load_external_plugins: linking plug-ins under $pd" 154 | echo "ln -f -s \"$pd\" \"$GIMP2_PLUGINDIR/plug-ins\"" 155 | ln -f -s "$pd" "$GIMP2_PLUGINDIR/plug-ins" 156 | ln -f -s "$pd/plug-ins"/* "${GIMP2_PLUGINDIR}/plug-ins" 157 | 158 | if [ -e "$pd"/scripts/set_exists.sh ]; then 159 | echo "load_external_plugins: sourcing $pd/scripts/set_exists.sh" 160 | source "$pd"/scripts/set_exists.sh 161 | fi 162 | 163 | if [ -e "$pd"/scripts/startup.sh ]; then 164 | echo "load_external_plugins: sourcing $pd/scripts/startup.sh" 165 | source "$pd"/scripts/startup.sh 166 | fi 167 | done 168 | 169 | echo "LD_LIBRARY_PATH: $LD_LIBRARY_PATH" 170 | echo "QT_PLUGIN_PATH: $QT_PLUGIN_PATH" 171 | } 172 | 173 | 174 | 175 | # Execute user-supplied startup hook scripts 176 | run_hooks() 177 | { 178 | for h in "$APPDIR/startup_scripts"/*.sh; do 179 | source "$h" 180 | done 181 | } 182 | 183 | 184 | init_environment() 185 | { 186 | export APPDIRS=$APPDIR:$APPDIRS 187 | export PATH="$APPDIR/usr/bin:${PATH}:/sbin:/usr/sbin" 188 | export LD_LIBRARY_PATH="$AILIBDIR:/usr/lib:$LD_LIBRARY_PATH" 189 | #export XDG_DATA_DIRS="${APPDIR}/usr/share/:${APPDIR}/usr/share/mime/:${XDG_DATA_DIRS}" 190 | export XDG_DATA_DIRS="${APPDIR}/usr/share/:${XDG_DATA_DIRS}:/usr/local/share/:/usr/share/" 191 | export ZENITY_DATA_DIR="$APPDIR/usr/share/zenity" 192 | export GCONV_PATH="${APPDIR}/usr/lib/gconv" 193 | } 194 | 195 | 196 | init_gdk_pixbuf() 197 | { 198 | #mkdir -p "$AILIBDIR/gdk-pixbuf-2.0" 199 | #cp "${APPDIR}/usr/lib/gdk-pixbuf-2.0/loaders.cache" "$AILIBDIR/gdk-pixbuf-2.0" 200 | #sed -i -e "s|LOADERSDIR|${APPDIR}/usr/lib/gdk-pixbuf-2.0/loaders|g" "$AILIBDIR/gdk-pixbuf-2.0/loaders.cache" 201 | #export GDK_PIXBUF_MODULE_FILE="$AILIBDIR/gdk-pixbuf-2.0/loaders.cache" 202 | export GDK_PIXBUF_MODULEDIR="${APPDIR}/usr/lib/gdk-pixbuf-2.0/loaders" 203 | export GDK_PIXBUF_MODULE_FILE="${APPDIR}/usr/lib/gdk-pixbuf-2.0/loaders.cache" 204 | #echo "GDK_PIXBUF_MODULE_FILE: $GDK_PIXBUF_MODULE_FILE" 205 | #echo "GDK_PIXBUF_MODULEDIR: $GDK_PIXBUF_MODULEDIR" 206 | 207 | export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$GDK_PIXBUF_MODULEDIR" 208 | 209 | #cat $GDK_PIXBUF_MODULE_FILE 210 | } 211 | 212 | 213 | init_gtk() 214 | { 215 | init_gdk_pixbuf 216 | export GTK_PATH="$APPDIR/usr/lib/gtk-2.0" 217 | echo "GTK_PATH=${GTK_PATH}" 218 | 219 | export GTK_IM_MODULE_FILE="$APPDIR/usr/lib/gtk-2.0:$GTK_PATH" 220 | echo "GTK_IM_MODULE_FILE=${GTK_IM_MODULE_FILE}" 221 | 222 | export PANGO_LIBDIR="$APPDIR/usr/lib" 223 | echo "PANGO_LIBDIR=${PANGO_LIBDIR}" 224 | } -------------------------------------------------------------------------------- /gimp.wrapper: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # The purpose of this script is to provide lightweight desktop integration 4 | # into the host system without special help from the host system. 5 | # If you want to use it, then place this in usr/bin/$APPNAME.wrapper 6 | # and set it as the Exec= line of the .desktop file in the AppImage. 7 | # 8 | # For example, to install the appropriate icons for Scribus, 9 | # put them into the AppDir at the following locations: 10 | # 11 | # ./usr/share/icons/default/128x128/apps/scribus.png 12 | # ./usr/share/icons/default/128x128/mimetypes/application-vnd.scribus.png 13 | # 14 | # Note that the filename application-vnd.scribus.png is derived from 15 | # and must be match MimeType=application/vnd.scribus; in scribus.desktop 16 | # (with "/" characters replaced by "-"). 17 | # 18 | # Then, change Exec=scribus to Exec=scribus.wrapper and place the script 19 | # below in usr/bin/scribus.wrapper and make it executable. 20 | # When you run AppRun, then AppRun runs the wrapper script below 21 | # which in turn will run the main application. 22 | # 23 | # TODO: 24 | # Handle multiple versions of the same AppImage? 25 | # Handle removed AppImages? Currently we are just setting TryExec= 26 | # See http://specifications.freedesktop.org/thumbnail-spec/thumbnail-spec-latest.html#DELETE 27 | # Possibly move this to the C runtime that is part of every AppImage? 28 | 29 | # Exit on errors 30 | set -e 31 | 32 | # Be verbose if $DEBUG=1 is set 33 | if [ ! -z "$DEBUG" ] ; then 34 | env 35 | set -x 36 | fi 37 | 38 | THIS="$0" 39 | args=("$@") # http://stackoverflow.com/questions/3190818/ 40 | NUMBER_OF_ARGS="$#" 41 | 42 | # Please do not change $VENDORPREFIX as it will allow for desktop files 43 | # belonging to AppImages to be recognized by future AppImageKit components 44 | # such as desktop integration daemons 45 | VENDORPREFIX=appimagekit 46 | 47 | find-up () { 48 | path="$(dirname "$(readlink -f "${THIS}")")" 49 | while [[ "$path" != "" && ! -e "$path/$1" ]]; do 50 | path=${path%/*} 51 | done 52 | # echo "$path" 53 | } 54 | 55 | if [ -z $APPDIR ] ; then 56 | # Find the AppDir. It is the directory that contains AppRun. 57 | # This assumes that this script resides inside the AppDir or a subdirectory. 58 | # If this script is run inside an AppImage, then the AppImage runtime 59 | # likely has already set $APPDIR 60 | APPDIR=$(find-up "AppRun") 61 | fi 62 | 63 | # echo "$APPDIR" 64 | 65 | FILENAME="$(readlink -f "${THIS}")" 66 | 67 | # echo "$FILENAME" 68 | 69 | if [[ "$FILENAME" != *.wrapper ]] ; then 70 | echo "${THIS} is not named correctly. It should be named \$Exec.wrapper" 71 | exit 0 72 | fi 73 | 74 | BIN=$(echo "$FILENAME" | sed -e 's|.wrapper||g') 75 | if [[ ! -f "$BIN" ]] ; then 76 | echo "$BIN not found" 77 | exit 0 78 | fi 79 | 80 | trap atexit EXIT 81 | 82 | # Note that the following handles 0, 1 or more arguments (file paths) 83 | # which can include blanks but uses a bashism; can the same be achieved 84 | # in POSIX-shell? (FIXME) 85 | # http://stackoverflow.com/questions/3190818 86 | atexit() 87 | { 88 | if [ $NUMBER_OF_ARGS -eq 0 ] ; then 89 | exec "${BIN}" 90 | else 91 | exec "${BIN}" "${args[@]}" 92 | fi 93 | } 94 | 95 | error() 96 | { 97 | if [ -x /usr/bin/zenity ] ; then 98 | LD_LIBRARY_PATH="" zenity --error --text "${1}" 2>/dev/null 99 | elif [ -x /usr/bin/kdialog ] ; then 100 | LD_LIBRARY_PATH="" kdialog --msgbox "${1}" 2>/dev/null 101 | elif [ -x /usr/bin/Xdialog ] ; then 102 | LD_LIBRARY_PATH="" Xdialog --msgbox "${1}" 2>/dev/null 103 | else 104 | echo "${1}" 105 | fi 106 | exit 1 107 | } 108 | 109 | yesno() 110 | { 111 | TITLE=$1 112 | TEXT=$2 113 | if [ -x /usr/bin/zenity ] ; then 114 | LD_LIBRARY_PATH="" zenity --question --title="$TITLE" --text="$TEXT" 2>/dev/null || exit 0 115 | elif [ -x /usr/bin/kdialog ] ; then 116 | LD_LIBRARY_PATH="" kdialog --caption "Disk auswerfen?" --title "$TITLE" -yesno "$TEXT" || exit 0 117 | elif [ -x /usr/bin/Xdialog ] ; then 118 | LD_LIBRARY_PATH="" Xdialog --title "$TITLE" --clear --yesno "$TEXT" 10 80 || exit 0 119 | else 120 | echo "zenity, kdialog, Xdialog missing. Skipping ${THIS}." 121 | exit 0 122 | fi 123 | } 124 | 125 | check_prevent() 126 | { 127 | FILE=$1 128 | if [ -e "$FILE" ] ; then 129 | exit 0 130 | fi 131 | } 132 | 133 | # Exit immediately of one of these files is present 134 | # (e.g., because the desktop environment wants to handle desktop integration itself) 135 | check_prevent "$HOME/.local/share/$VENDORPREFIX/no_desktopintegration" 136 | check_prevent "/usr/share/$VENDORPREFIX/no_desktopintegration" 137 | check_prevent "/etc/$VENDORPREFIX/no_desktopintegration" 138 | 139 | # Exit immediately if appimaged is running 140 | pidof appimaged 2>/dev/null && exit 0 141 | 142 | # Exit immediately if $DESKTOPINTEGRATION is not empty 143 | if [ ! -z "$DESKTOPINTEGRATION" ] ; then 144 | exit 0 145 | fi 146 | 147 | check_dep() 148 | { 149 | DEP=$1 150 | if [ -z $(which $DEP) ] ; then 151 | echo "$DEP is missing. Skipping ${THIS}." 152 | exit 0 153 | fi 154 | } 155 | 156 | DIRNAME=$(dirname $FILENAME) 157 | 158 | # Check whether dependencies are present in base system (we do not bundle these) 159 | # http://cgit.freedesktop.org/xdg/desktop-file-utils/ 160 | check_dep desktop-file-validate 161 | check_dep update-desktop-database 162 | check_dep desktop-file-install 163 | check_dep xdg-icon-resource 164 | check_dep xdg-mime 165 | check_dep xdg-desktop-menu 166 | 167 | DESKTOPFILE=$(find "$APPDIR" -maxdepth 1 -name "*.desktop" | head -n 1) 168 | # echo "$DESKTOPFILE" 169 | DESKTOPFILE_NAME=$(basename "${DESKTOPFILE}") 170 | 171 | if [ ! -f "$DESKTOPFILE" ] ; then 172 | echo "Desktop file is missing. Please run ${THIS} from within an AppImage." 173 | exit 0 174 | fi 175 | 176 | if [ -z "$APPIMAGE" ] ; then 177 | APPIMAGE="$APPDIR/AppRun" 178 | # Not running from within an AppImage; hence using the AppRun for Exec= 179 | fi 180 | 181 | # Construct path to the icon according to 182 | # http://specifications.freedesktop.org/thumbnail-spec/thumbnail-spec-latest.html 183 | ABS_APPIMAGE=$(readlink -e "$APPIMAGE") 184 | ICONURL="file://$ABS_APPIMAGE" 185 | MD5=$(echo -n $ICONURL | md5sum | cut -c -32) 186 | ICONFILE="$HOME/.cache/thumbnails/normal/$MD5.png" 187 | if [ ! -f "$ICONFILE" ] ; then 188 | echo "$ICONFILE is missing. Probably not running ${THIS} from within an AppImage." 189 | echo "Hence falling back to using .DirIcon" 190 | ICONFILE="$APPDIR/.DirIcon" 191 | fi 192 | 193 | # $XDG_DATA_DIRS contains the default paths /usr/local/share:/usr/share 194 | # desktop file has to be installed in an applications subdirectory 195 | # of one of the $XDG_DATA_DIRS components 196 | if [ -z "$XDG_DATA_DIRS" ] ; then 197 | echo "\$XDG_DATA_DIRS is missing. Please run ${THIS} from within an AppImage." 198 | exit 0 199 | fi 200 | 201 | # Determine where the desktop file should be installed 202 | if [[ $EUID -ne 0 ]]; then 203 | DESTINATION_DIR_DESKTOP="$HOME/.local/share/applications" 204 | SYSTEM_WIDE="" 205 | else 206 | # TODO: Check $XDG_DATA_DIRS 207 | DESTINATION_DIR_DESKTOP="/usr/local/share/applications" 208 | SYSTEM_WIDE="--mode system" # for xdg-mime and xdg-icon-resource 209 | fi 210 | 211 | # Check if the desktop file is already there 212 | # and if so, whether it points to the same AppImage 213 | if [ -e "$DESTINATION_DIR_DESKTOP/$VENDORPREFIX-$DESKTOPFILE_NAME" ] ; then 214 | # echo "$DESTINATION_DIR_DESKTOP/$VENDORPREFIX-$DESKTOPFILE_NAME already there" 215 | EXEC=$(grep "^Exec=" "$DESTINATION_DIR_DESKTOP/$VENDORPREFIX-$DESKTOPFILE_NAME" | head -n 1 | cut -d " " -f 1) 216 | # echo $EXEC 217 | if [ "Exec=\"$APPIMAGE\"" == "$EXEC" ] ; then 218 | exit 0 219 | fi 220 | fi 221 | 222 | # We ask the user only if we have found no reason to skip until here 223 | if [ -z "$SKIP" ] ; then 224 | yesno "Install" "Should a desktop file for $APPIMAGE be installed?" 225 | fi 226 | 227 | APP=$(echo "$DESKTOPFILE_NAME" | sed -e 's/.desktop//g') 228 | 229 | # If the user has agreed, rewrite and install the desktop file, and the MIME information 230 | if [ -z "$SKIP" ] ; then 231 | # desktop-file-install is supposed to install .desktop files to the user's 232 | # applications directory when run as a non-root user, 233 | # and to /usr/share/applications if run as root 234 | # but that does not really work for me... 235 | # 236 | # For Exec we must use quotes 237 | # For TryExec quotes is not supported, so, space must be replaced to \s 238 | # https://askubuntu.com/questions/175404/how-to-add-space-to-exec-path-in-a-thumbnailer-descrption/175567 239 | echo "Before desktop-file-install" 240 | desktop-file-install --rebuild-mime-info-cache \ 241 | --vendor=$VENDORPREFIX --set-key=Exec --set-value="\"${APPIMAGE}\" %U" \ 242 | --set-key=X-AppImage-Comment --set-value="Generated by ${THIS}" \ 243 | --set-icon="$ICONFILE" --set-key=TryExec --set-value=${APPIMAGE// /\\s} "$DESKTOPFILE" \ 244 | --dir "$DESTINATION_DIR_DESKTOP" 245 | echo "After desktop-file-install" 246 | chmod a+x "$DESTINATION_DIR_DESKTOP/"* 247 | RESOURCE_NAME=$(echo "$VENDORPREFIX-$DESKTOPFILE_NAME" | sed -e 's/.desktop//g') 248 | # echo $RESOURCE_NAME 249 | 250 | # Install the icon files for the application; TODO: scalable 251 | ICONS=$(find "${APPDIR}/usr/share/icons/" -wholename "*/apps/${APP}.png" 2>/dev/null || true) 252 | for ICON in $ICONS ; do 253 | ICON_SIZE=$(echo "${ICON}" | rev | cut -d "/" -f 3 | rev | cut -d "x" -f 1) 254 | echo "Before xdg-icon-resource install (1)" 255 | xdg-icon-resource install --context apps --size ${ICON_SIZE} "${ICON}" "${RESOURCE_NAME}" 256 | echo "After xdg-icon-resource install (1)" 257 | done 258 | 259 | # Install mime type 260 | find "${APPDIR}/usr/share/mime/" -type f -name *xml -exec echo -n "Before xdg-mime install " \; -exec echo {} \; -exec xdg-mime install $SYSTEM_WIDE --novendor {} \; 2>/dev/null || true 261 | 262 | # Install the icon files for the mime type; TODO: scalable 263 | ICONS=$(find "${APPDIR}/usr/share/icons/" -wholename "*/mimetypes/*.png" 2>/dev/null || true) 264 | for ICON in $ICONS ; do 265 | ICON_SIZE=$(echo "${ICON}" | rev | cut -d "/" -f 3 | rev | cut -d "x" -f 1) 266 | echo "Before xdg-icon-resource install (2)" 267 | xdg-icon-resource install --context mimetypes --size ${ICON_SIZE} "${ICON}" $(basename $ICON | sed -e 's/.png//g') 268 | echo "After xdg-icon-resource install (2)" 269 | done 270 | 271 | echo "Before xdg-desktop-menu forceupdate" 272 | xdg-desktop-menu forceupdate 273 | echo "After xdg-desktop-menu forceupdate" 274 | echo "Before gtk-update-icon-cache" 275 | gtk-update-icon-cache # for MIME 276 | echo "After gtk-update-icon-cache" 277 | fi 278 | -------------------------------------------------------------------------------- /appimage-helper-scripts/app.wrapper: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # The purpose of this script is to provide lightweight desktop integration 4 | # into the host system without special help from the host system. 5 | # If you want to use it, then place this in usr/bin/$APPNAME.wrapper 6 | # and set it as the Exec= line of the .desktop file in the AppImage. 7 | # 8 | # For example, to install the appropriate icons for Scribus, 9 | # put them into the AppDir at the following locations: 10 | # 11 | # ./usr/share/icons/default/128x128/apps/scribus.png 12 | # ./usr/share/icons/default/128x128/mimetypes/application-vnd.scribus.png 13 | # 14 | # Note that the filename application-vnd.scribus.png is derived from 15 | # and must be match MimeType=application/vnd.scribus; in scribus.desktop 16 | # (with "/" characters replaced by "-"). 17 | # 18 | # Then, change Exec=scribus to Exec=scribus.wrapper and place the script 19 | # below in usr/bin/scribus.wrapper and make it executable. 20 | # When you run AppRun, then AppRun runs the wrapper script below 21 | # which in turn will run the main application. 22 | # 23 | # TODO: 24 | # Handle multiple versions of the same AppImage? 25 | # Handle removed AppImages? Currently we are just setting TryExec= 26 | # See http://specifications.freedesktop.org/thumbnail-spec/thumbnail-spec-latest.html#DELETE 27 | # Possibly move this to the C runtime that is part of every AppImage? 28 | 29 | # Exit on errors 30 | set -e 31 | 32 | # Be verbose if $DEBUG=1 is set 33 | if [ ! -z "$DEBUG" ] ; then 34 | env 35 | set -x 36 | fi 37 | 38 | THIS="$0" 39 | args=("$@") # http://stackoverflow.com/questions/3190818/ 40 | NUMBER_OF_ARGS="$#" 41 | 42 | # Please do not change $VENDORPREFIX as it will allow for desktop files 43 | # belonging to AppImages to be recognized by future AppImageKit components 44 | # such as desktop integration daemons 45 | VENDORPREFIX=appimagekit 46 | 47 | log () { 48 | echo "$@" 1>&2 49 | } 50 | 51 | find-up () { 52 | path="$(dirname "$(readlink -f "${THIS}")")" 53 | while [[ "$path" != "" && ! -e "$path/$1" ]]; do 54 | path=${path%/*} 55 | done 56 | echo -n "$path" # Needs to return something 57 | } 58 | 59 | if [ -z $APPDIR ] ; then 60 | # Find the AppDir. It is the directory that contains AppRun. 61 | # This assumes that this script resides inside the AppDir or a subdirectory. 62 | # If this script is run inside an AppImage, then the AppImage runtime 63 | # likely has already set $APPDIR 64 | APPDIR=$(find-up "AppRun") 65 | fi 66 | 67 | FILENAME="$(readlink -f "${THIS}")" 68 | DIRNAME=$(dirname $FILENAME) 69 | echo "DIRNAME: $DIRNAME" 70 | 71 | DESKTOPFILE=$(find "$APPDIR" -maxdepth 1 -name "*.desktop" | head -n 1) 72 | DESKTOPFILE_NAME=$(basename "${DESKTOPFILE}") 73 | echo "DESKTOPFILE_NAME: $DESKTOPFILE_NAME" 74 | 75 | APP_FULL=$(sed -n -e 's/^Name=//p' "${DESKTOPFILE}" | head -n 1) 76 | APP=$(echo "$APP_FULL" | tr -c -d '[:alnum:]') 77 | echo "APP_FULL: $APP_FULL" 78 | echo "APP: $APP" 79 | if [ -z "$APP" ] || [ -z "$APP_FULL" ] ; then 80 | APP=$(echo "$DESKTOPFILE_NAME" | sed -e 's/.desktop//g') 81 | APP_FULL="$APP" 82 | fi 83 | echo "APP_FULL: $APP_FULL" 84 | echo "APP: $APP" 85 | 86 | RETURN="yes" 87 | 88 | if [[ "$FILENAME" != *.wrapper ]] ; then 89 | log "${THIS} is not named correctly. It should be named \$Exec.wrapper" 90 | exit 0 91 | fi 92 | 93 | BIN=$(echo "$FILENAME" | sed -e 's|.wrapper|.bin|g') 94 | if [[ ! -f "$BIN" ]] ; then 95 | log "$BIN not found" 96 | exit 0 97 | fi 98 | echo "BIN: $BIN" 99 | 100 | trap atexit EXIT 101 | 102 | # Note that the following handles 0, 1 or more arguments (file paths) 103 | # which can include blanks but uses a bashism; can the same be achieved 104 | # in POSIX-shell? (FIXME) 105 | # http://stackoverflow.com/questions/3190818 106 | atexit() 107 | { 108 | if [ -z "$SKIP" ] ; then 109 | if [ $NUMBER_OF_ARGS -eq 0 ] ; then 110 | exec "${BIN}" 111 | else 112 | exec "${BIN}" "${args[@]}" 113 | fi 114 | fi 115 | } 116 | 117 | error() 118 | { 119 | zenity --error --text "${1}" --no-wrap 2>/dev/null 120 | exit 1 121 | } 122 | 123 | yesno() 124 | { 125 | TITLE=$1 126 | TEXT=$2 127 | zenity --question --title="$TITLE" --text="$TEXT" --no-wrap && RETURN="yes" || RETURN="no" 128 | echo "yesno finished" 129 | } 130 | 131 | check_prevent() 132 | { 133 | FILE=$1 134 | if [ -e "$FILE" ] ; then 135 | echo "File \"$FILE\" is exiting - skipping desktop integration" 136 | exit 0 137 | fi 138 | } 139 | 140 | check_dep() 141 | { 142 | if [ -z "$(command -v $1)" ]; then 143 | log "$1 is missing. Skipping ${THIS}." 144 | exit 145 | fi 146 | } 147 | 148 | # Determine where the desktop file should be installed 149 | if [[ $EUID -ne 0 ]]; then 150 | DESTINATION_DIR_DESKTOP="$HOME/.local/share/applications" 151 | STAMP_DIR="$HOME/.local/share/$VENDORPREFIX" 152 | SYSTEM_WIDE="" 153 | else 154 | # TODO: Check $XDG_DATA_DIRS 155 | DESTINATION_DIR_DESKTOP="/usr/local/share/applications" 156 | STAMP_DIR="/etc/$VENDORPREFIX" 157 | SYSTEM_WIDE="--mode system" # for xdg-mime and xdg-icon-resource 158 | fi 159 | 160 | # Remove desktop integration for this AppImage 161 | if [ "x$1" = "x--remove-appimage-desktop-integration" ] ; then 162 | SKIP="yes" 163 | rm -f "$STAMP_DIR/${APP}_no_desktopintegration" "$DESTINATION_DIR_DESKTOP/$VENDORPREFIX-$DESKTOPFILE_NAME" 164 | check_dep xdg-desktop-menu 165 | xdg-desktop-menu forceupdate 166 | exit 0 167 | fi 168 | 169 | # Exit immediately if one of these files is present 170 | # (e.g., because the desktop environment wants to handle desktop integration itself) 171 | check_prevent "$HOME/.local/share/$VENDORPREFIX/no_desktopintegration" 172 | check_prevent "/usr/share/$VENDORPREFIX/no_desktopintegration" 173 | check_prevent "/etc/$VENDORPREFIX/no_desktopintegration" 174 | 175 | # Exit immediately if appimaged is running 176 | pidof appimaged >/dev/null 2>&1 && exit 0 177 | 178 | echo "DESKTOPINTEGRATION: $DESKTOPINTEGRATION" 179 | # Exit immediately if $DESKTOPINTEGRATION is not empty 180 | if [ ! -z "$DESKTOPINTEGRATION" ] ; then 181 | exit 0 182 | fi 183 | 184 | # Check whether dependencies are present in base system (we do not bundle these) 185 | # http://cgit.freedesktop.org/xdg/desktop-file-utils/ 186 | check_dep desktop-file-validate 187 | check_dep update-desktop-database 188 | check_dep desktop-file-install 189 | check_dep xdg-icon-resource 190 | check_dep xdg-mime 191 | check_dep xdg-desktop-menu 192 | 193 | # Exit immediately if one of these files is present (disabled per app) 194 | check_prevent "$HOME/.local/share/$VENDORPREFIX/${APP}_no_desktopintegration" 195 | check_prevent "/usr/share/$VENDORPREFIX/${APP}_no_desktopintegration" 196 | check_prevent "/etc/$VENDORPREFIX/${APP}_no_desktopintegration" 197 | 198 | if [ ! -f "$DESKTOPFILE" ] ; then 199 | log "Desktop file is missing. Please run ${THIS} from within an AppImage." 200 | exit 0 201 | fi 202 | 203 | if [ -z "$APPIMAGE" ] ; then 204 | APPIMAGE="$APPDIR/AppRun" 205 | # Not running from within an AppImage; hence using the AppRun for Exec= 206 | fi 207 | 208 | ICONFILE="$APPDIR/.DirIcon" 209 | 210 | # $XDG_DATA_DIRS contains the default paths /usr/local/share:/usr/share 211 | # desktop file has to be installed in an applications subdirectory 212 | # of one of the $XDG_DATA_DIRS components 213 | if [ -z "$XDG_DATA_DIRS" ] ; then 214 | log "\$XDG_DATA_DIRS is missing. Please run ${THIS} from within an AppImage." 215 | exit 0 216 | fi 217 | 218 | # Check if the desktop file is already there 219 | # and if so, whether it points to the same AppImage 220 | if [ -e "$DESTINATION_DIR_DESKTOP/$VENDORPREFIX-$DESKTOPFILE_NAME" ] ; then 221 | # echo "$DESTINATION_DIR_DESKTOP/$VENDORPREFIX-$DESKTOPFILE_NAME already there" 222 | EXEC=$(grep "^Exec=" "$DESTINATION_DIR_DESKTOP/$VENDORPREFIX-$DESKTOPFILE_NAME" | head -n 1 | cut -d " " -f 1) 223 | # echo $EXEC 224 | if [ "Exec=\"$APPIMAGE\"" == "$EXEC" ] ; then 225 | exit 0 226 | fi 227 | fi 228 | 229 | echo "HERE!!!" 230 | 231 | 232 | 233 | # We ask the user only if we have found no reason to skip until here 234 | if [ -z "$SKIP" ] ; then 235 | yesno "Install" "Would you like to integrate $APPIMAGE with your system?\n\nThis will add it to your applications menu and install icons.\nIf you don't do this you can still launch the application by double-clicking on the AppImage." 236 | fi 237 | 238 | if [ "$RETURN" = "no" ] ; then 239 | yesno "Disable question?" "Should this question be permanently disabled for $APP?\n\nTo re-enable this question you have to delete\n\"$STAMP_DIR/${APP}_no_desktopintegration\"" 240 | if [ "$RETURN" = "yes" ] ; then 241 | mkdir -p "$STAMP_DIR" 242 | touch "$STAMP_DIR/${APP}_no_desktopintegration" 243 | fi 244 | exit 0 245 | fi 246 | 247 | zenity --info --text "Installing desktop file\nPlease wait..." --no-wrap & 248 | ZENITY_PID=$! 249 | echo "Installing desktop file\nPlease wait..." 250 | # If the user has agreed, rewrite and install the desktop file, and the MIME information 251 | if [ -z "$SKIP" ] ; then 252 | # desktop-file-install is supposed to install .desktop files to the user's 253 | # applications directory when run as a non-root user, 254 | # and to /usr/share/applications if run as root 255 | # but that does not really work for me... 256 | # 257 | # For Exec we must use quotes 258 | # For TryExec quotes is not supported, so, space must be replaced to \s 259 | # https://askubuntu.com/questions/175404/how-to-add-space-to-exec-path-in-a-thumbnailer-descrption/175567 260 | RESOURCE_NAME=$(echo "$VENDORPREFIX-$DESKTOPFILE_NAME" | sed -e 's/\.desktop//g') 261 | desktop-file-install --rebuild-mime-info-cache \ 262 | --vendor=$VENDORPREFIX --set-key=Exec --set-value="\"${APPIMAGE}\" %U" \ 263 | --set-key=X-AppImage-Comment --set-value="Generated by ${THIS}" \ 264 | --set-key=TryExec --set-value=${APPIMAGE// /\\s} "$DESKTOPFILE" \ 265 | --dir "$DESTINATION_DIR_DESKTOP" 266 | chmod a+x "$DESTINATION_DIR_DESKTOP/"* 267 | # echo $RESOURCE_NAME 268 | 269 | # add "(AppImage)" to the application name 270 | DESKTOP_NAME=$(cat "$DESTINATION_DIR_DESKTOP/$VENDORPREFIX-$DESKTOPFILE_NAME" | grep "^Name=.*") 271 | sed -i -e "s|${DESKTOP_NAME}|${DESKTOP_NAME} (AppImage)|g" "$DESTINATION_DIR_DESKTOP/$VENDORPREFIX-$DESKTOPFILE_NAME" 272 | 273 | # delete "Actions" entry and add an "Uninstall" action 274 | sed -i -e '/^Actions=/d' "$DESTINATION_DIR_DESKTOP/$VENDORPREFIX-$DESKTOPFILE_NAME" 275 | cat >> "$DESTINATION_DIR_DESKTOP/$VENDORPREFIX-$DESKTOPFILE_NAME" << EOF 276 | 277 | Actions=Uninstall; 278 | 279 | [Uninstall] 280 | Name=Remove desktop integration for $APP_FULL 281 | Exec="$APPIMAGE" --remove-appimage-desktop-integration 282 | 283 | EOF 284 | 285 | # Install the icon files for the application; TODO: scalable 286 | ICONS=$(find "${APPDIR}/usr/share/icons/" -iwholename "*/apps/${APP}.png" 2>/dev/null || true) 287 | for ICON in $ICONS ; do 288 | ICON_SIZE=$(echo "${ICON}" | rev | cut -d "/" -f 3 | rev | cut -d "x" -f 1) 289 | xdg-icon-resource install --context apps --size ${ICON_SIZE} "${ICON}" "${RESOURCE_NAME}" 290 | done 291 | 292 | # Install mime type 293 | find "${APPDIR}/usr/share/mime/" -type f -name *xml -exec xdg-mime install $SYSTEM_WIDE --novendor {} \; 2>/dev/null || true 294 | 295 | # Install the icon files for the mime type; TODO: scalable 296 | ICONS=$(find "${APPDIR}/usr/share/icons/" -iwholename "*/mimetypes/*.png" 2>/dev/null || true) 297 | for ICON in $ICONS ; do 298 | ICON_SIZE=$(echo "${ICON}" | rev | cut -d "/" -f 3 | rev | cut -d "x" -f 1) 299 | xdg-icon-resource install --context mimetypes --size ${ICON_SIZE} "${ICON}" $(basename $ICON | sed -e 's/.png//g') 300 | done 301 | 302 | xdg-desktop-menu forceupdate 303 | gtk-update-icon-cache # for MIME 304 | fi 305 | kill -9 $ZENITY_PID 306 | -------------------------------------------------------------------------------- /appimage-helper-scripts/functions.sh: -------------------------------------------------------------------------------- 1 | # This file is supposed to be sourced by each Recipe 2 | # that wants to use the functions contained herein 3 | # like so: 4 | # wget -q https://github.com/AppImage/AppImages/raw/${PKG2AICOMMIT}/functions.sh -O ./functions.sh 5 | # . ./functions.sh 6 | 7 | # RECIPE=$(realpath "$0") 8 | 9 | # Specify a certain commit if you do not want to use master 10 | # by using: 11 | # export PKG2AICOMMIT= 12 | if [ -z "$PKG2AICOMMIT" ] ; then 13 | PKG2AICOMMIT=master 14 | fi 15 | 16 | # Options for apt-get to use local files rather than the system ones 17 | OPTIONS="-o Debug::NoLocking=1 18 | -o APT::Cache-Limit=125829120 19 | -o Dir::Etc::sourcelist=./sources.list 20 | -o Dir::State=./tmp 21 | -o Dir::Cache=./tmp 22 | -o Dir::State::status=./status 23 | -o Dir::Etc::sourceparts=- 24 | -o APT::Get::List-Cleanup=0 25 | -o APT::Get::AllowUnauthenticated=1 26 | -o Debug::pkgProblemResolver=true 27 | -o Debug::pkgDepCache::AutoInstall=true 28 | -o APT::Install-Recommends=0 29 | -o APT::Install-Suggests=0 30 | " 31 | 32 | # Detect system architecture to know which binaries of AppImage tools 33 | # should be downloaded and used. 34 | case "$(uname -i)" in 35 | x86_64|amd64) 36 | # echo "x86-64 system architecture" 37 | SYSTEM_ARCH="x86_64";; 38 | i?86) 39 | # echo "x86 system architecture" 40 | SYSTEM_ARCH="i686";; 41 | # arm*) 42 | # echo "ARM system architecture" 43 | # SYSTEM_ARCH="";; 44 | unknown|AuthenticAMD|GenuineIntel) 45 | # uname -i not answer on debian, then: 46 | case "$(uname -m)" in 47 | x86_64|amd64) 48 | # echo "x86-64 system architecture" 49 | SYSTEM_ARCH="x86_64";; 50 | i?86) 51 | # echo "x86 system architecture" 52 | SYSTEM_ARCH="i686";; 53 | esac ;; 54 | *) 55 | echo "Unsupported system architecture" 56 | exit 1;; 57 | esac 58 | 59 | # Either get the file from remote or from a static place. 60 | # critical for builds without network access like in Open Build Service 61 | cat_file_from_url() 62 | { 63 | cat_excludelist="wget -q $1 -O -" 64 | [ -e "$STATIC_FILES/${1##*/}" ] && cat_excludelist="cat $STATIC_FILES/${1##*/}" 65 | $cat_excludelist 66 | } 67 | 68 | git_pull_rebase_helper() 69 | { 70 | git reset --hard HEAD 71 | git pull 72 | } 73 | 74 | # Patch /usr to ././ in ./usr 75 | # to make the contents of usr/ relocateable 76 | # (this requires us to cd ./usr before running the application; AppRun does that) 77 | patch_usr() 78 | { 79 | find usr/ -type f -executable -exec sed -i -e "s|/usr|././|g" {} \; 80 | } 81 | 82 | patch_files() 83 | { 84 | __prefix__=$1 85 | find usr/ -type f -executable -exec sed -i -e "s|/${__prefix__}/|././/|g" {} \; 86 | } 87 | 88 | # Download AppRun and make it executable 89 | get_apprun() 90 | { 91 | TARGET_ARCH=${ARCH:-$SYSTEM_ARCH} 92 | wget -c https://github.com/AppImage/AppImageKit/releases/download/continuous/AppRun-${TARGET_ARCH} -O AppRun 93 | chmod a+x AppRun 94 | } 95 | 96 | # Copy the library dependencies of all exectuable files in the current directory 97 | # (it can be beneficial to run this multiple times) 98 | copy_deps() 99 | { 100 | PWD=$(readlink -f .) 101 | FILES=$(find . -type f -executable -or -name *.so.* -or -name *.so | sort | uniq ) 102 | for FILE in $FILES ; do 103 | ldd "${FILE}" | grep "=>" | awk '{print $3}' | xargs -I '{}' echo '{}' >> DEPSFILE 104 | done 105 | DEPS=$(cat DEPSFILE | sort | uniq) 106 | for FILE in $DEPS ; do 107 | if [ -e $FILE ] && [[ $(readlink -f $FILE)/ != $PWD/* ]] ; then 108 | cp -v --parents -rfL $FILE ./ || true 109 | fi 110 | done 111 | rm -f DEPSFILE 112 | } 113 | 114 | # Copy the library dependencies of all exectuable files in the current directory 115 | # (it can be beneficial to run this multiple times) 116 | copy_deps2() 117 | { 118 | mkdir -p usr/lib 119 | PWD=$(readlink -f .) 120 | FILES=$(find . -type f -executable -or -name *.so.* -or -name *.so | sort | uniq ) 121 | for FILE in $FILES ; do 122 | ldd "${FILE}" | grep "=>" | awk '{print $3}' | xargs -I '{}' echo '{}' >> DEPSFILE 123 | done 124 | DEPS=$(cat DEPSFILE | sort | uniq) 125 | for FILE in $DEPS ; do 126 | if [ -e $FILE ] && [[ $(readlink -f $FILE)/ != $PWD/* ]] ; then 127 | echo "Copying library \"$FILE\"..." 128 | PARENT="" 129 | if [[ -h "$FILE" ]]; then 130 | PARENT=$(readlink "$FILE") 131 | fi 132 | #echo " parent: $PARENT" 133 | while [ -n "$PARENT" ]; do 134 | DIR=$(dirname "$FILE") 135 | PDIR=$(dirname "$PARENT") 136 | if [ "$PDIR" != "." ]; then 137 | cp -u -v -L "$FILE" ./usr/lib 138 | else 139 | cp -u -v -a "$FILE" ./usr/lib 140 | fi 141 | 142 | ROOT=$(echo "$PARENT" | cut -c 1) 143 | if [ x"$ROOT" != "x/" ]; then 144 | FILE="$DIR/$PARENT" 145 | else 146 | FILE="$PARENT" 147 | fi 148 | 149 | #echo " file: $FILE" 150 | PARENT="" 151 | if [[ -h "$FILE" ]]; then 152 | PARENT=$(readlink "$FILE") 153 | fi 154 | #echo " parent: $PARENT" 155 | done 156 | cp -u -v -a "$FILE" ./usr/lib 157 | fi 158 | done 159 | rm -f DEPSFILE 160 | } 161 | 162 | # Copy the library dependencies of all exectuable files in the current directory 163 | # (it can be beneficial to run this multiple times) 164 | copy_deps3() 165 | { 166 | mkdir -p usr/lib 167 | PWD=$(readlink -f .) 168 | FILES=$(find . -type f -executable -or -name *.so.* -or -name *.so | sort | uniq ) 169 | for FILE in $FILES ; do 170 | echo "copy_deps2: collecting dependencies of \"${FILE}\"" 171 | ldd "${FILE}" 172 | ldd "${FILE}" | grep "=>" | awk '{print $3}' | xargs -I '{}' echo '{}' >> DEPSFILE 173 | done 174 | DEPS=$(cat DEPSFILE | sort | uniq) 175 | for FILE in $DEPS ; do 176 | if [ -e $FILE ] && [[ $(readlink -f $FILE)/ != $PWD/* ]] ; then 177 | echo "Copying library \"$FILE\"..." 178 | PARENT="" 179 | if [[ -h "$FILE" ]]; then 180 | PARENT=$(readlink "$FILE") 181 | fi 182 | #echo " parent: $PARENT" 183 | while [ -n "$PARENT" ]; do 184 | DIR=$(dirname "$FILE") 185 | PDIR=$(dirname "$PARENT") 186 | if [ "$PDIR" != "." ]; then 187 | cp -u -v -L "$FILE" ./usr/lib 188 | else 189 | cp -u -v -a "$FILE" ./usr/lib 190 | fi 191 | 192 | ROOT=$(echo "$PARENT" | cut -c 1) 193 | if [ x"$ROOT" != "x/" ]; then 194 | FILE="$DIR/$PARENT" 195 | else 196 | FILE="$PARENT" 197 | fi 198 | 199 | #echo " file: $FILE" 200 | PARENT="" 201 | if [[ -h "$FILE" ]]; then 202 | PARENT=$(readlink "$FILE") 203 | fi 204 | #echo " parent: $PARENT" 205 | done 206 | cp -u -v -a "$FILE" ./usr/lib 207 | fi 208 | done 209 | rm -f DEPSFILE 210 | } 211 | 212 | 213 | copy_gcc_libs() 214 | { 215 | stdcxxlib=$(PATH="/sbin:$PATH" ldconfig -p | grep 'libstdc++.so.6' | grep 'x86-64' | awk 'NR==1 {print $NF}') 216 | echo "stdcxxlib: $stdcxxlib" 217 | if [ x"$stdcxxlib" != "x" ]; then 218 | mkdir -p usr/optional/libstdc++ 219 | cp -L "$stdcxxlib" usr/optional/libstdc++ 220 | fi 221 | 222 | gomplib=$(PATH="/sbin:$PATH" ldconfig -p | grep 'libgomp.so.1' | grep 'x86-64' | awk 'NR==1{print $NF}') 223 | echo "gomplib: $gomplib" 224 | if [ x"$gomplib" != "x" ]; then 225 | mkdir -p usr/optional/libstdc++ 226 | cp -L "$gomplib" usr/optional/libstdc++ 227 | fi 228 | 229 | gcclib=$(PATH="/sbin:$PATH" ldconfig -p | grep 'libgcc_s.so.1' | grep 'x86-64' | awk 'NR==1{print $NF}') 230 | echo "gcclib: $gcclib" 231 | if [ x"$gcclib" != "x" ]; then 232 | mkdir -p usr/optional/libgcc_s 233 | cp -L "$gcclib" usr/optional/libgcc_s 234 | fi 235 | } 236 | 237 | 238 | # Move ./lib/ tree to ./usr/lib/ 239 | move_lib() 240 | { 241 | mkdir -p ./usr/lib ./lib && find ./lib/ -exec cp -v --parents -rfL {} ./usr/ \; && rm -rf ./lib 242 | mkdir -p ./usr/lib ./lib64 && find ./lib64/ -exec cp -v --parents -rfL {} ./usr/ \; && rm -rf ./lib64 243 | } 244 | 245 | # Delete blacklisted files 246 | delete_blacklisted() 247 | { 248 | BLACKLISTED_FILES=$(cat_file_from_url https://github.com/AppImage/AppImages/raw/${PKG2AICOMMIT}/excludelist | sed 's|#.*||g') 249 | echo $BLACKLISTED_FILES 250 | for FILE in $BLACKLISTED_FILES ; do 251 | FILES="$(find . -name "${FILE}" -not -path "./usr/optional/*")" 252 | for FOUND in $FILES ; do 253 | rm -vf "$FOUND" "$(readlink -f "$FOUND")" 254 | done 255 | done 256 | 257 | # Do not bundle developer stuff 258 | rm -rf usr/include || true 259 | rm -rf usr/lib/cmake || true 260 | rm -rf usr/lib/pkgconfig || true 261 | find . -name '*.la' | xargs -i rm {} 262 | } 263 | 264 | 265 | # Delete blacklisted libraries 266 | delete_blacklisted2() 267 | { 268 | #printf '%s\n' "APPIMAGEBASE: ${APPIMAGEBASE}" 269 | #ls "${APPIMAGEBASE}" 270 | 271 | pwd 272 | while IFS= read -r line; do 273 | #echo "line: ${line}" 274 | #find . -name "${line}*" 275 | #find . -name "${line}*" -delete 276 | FLIST=$(find . -name "${line}*") 277 | for F in $FLIST; do 278 | rm -v -f "$F" 279 | done 280 | done < <(cat "$APPDIR/../excludelist" | sed '/^[[:space:]]*$/d' | sed '/^#.*$/d') 281 | # TODO Try this, its cleaner if it works: 282 | #done < "$APPIMAGEBASE/excludelist" | sed '/^[[:space:]]*$/d' | sed '/^#.*$/d' 283 | } 284 | 285 | 286 | # Echo highest glibc version needed by the executable files in the current directory 287 | glibc_needed() 288 | { 289 | find . -name *.so -or -name *.so.* -or -type f -executable -exec strings {} \; | grep ^GLIBC_2 | sed s/GLIBC_//g | sort --version-sort | uniq | tail -n 1 290 | # find . -name *.so -or -name *.so.* -or -type f -executable -exec readelf -s '{}' 2>/dev/null \; | sed -n 's/.*@GLIBC_//p'| awk '{print $1}' | sort --version-sort | tail -n 1 291 | } 292 | # Add desktop integration 293 | # Usage: get_desktopintegration name_of_desktop_file_and_exectuable 294 | get_desktopintegration() 295 | { 296 | REALBIN=$(grep -o "^Exec=.*" *.desktop | sed -e 's|Exec=||g' | cut -d " " -f 1 | head -n 1) 297 | cat_file_from_url https://raw.githubusercontent.com/AppImage/AppImageKit/master/desktopintegration > ./usr/bin/$REALBIN.wrapper 298 | chmod a+x ./usr/bin/$REALBIN.wrapper 299 | 300 | sed -i -e "s|^Exec=$REALBIN|Exec=$REALBIN.wrapper|g" $1.desktop 301 | } 302 | 303 | 304 | # Remove debugging symbols from bundled executables and libraries 305 | strip_binaries() 306 | { 307 | chmod u+w -R "$APPDIR" 308 | { 309 | find $APPDIR/usr -type f -name "rawtherapee*" -print0 310 | find "$APPDIR" -type f -regex '.*\.so\(\.[0-9.]+\)?$' -print0 311 | } | xargs -0 --no-run-if-empty --verbose -n1 strip 312 | } 313 | 314 | 315 | # Generate AppImage; this expects $ARCH, $APP and $VERSION to be set 316 | generate_appimage() 317 | { 318 | # Download AppImageAssistant 319 | URL="https://github.com/AppImage/AppImageKit/releases/download/6/AppImageAssistant_6-${SYSTEM_ARCH}.AppImage" 320 | wget -c "$URL" -O AppImageAssistant 321 | chmod a+x ./AppImageAssistant 322 | 323 | # if [[ "$RECIPE" == *ecipe ]] ; then 324 | # echo "#!/bin/bash -ex" > ./$APP.AppDir/Recipe 325 | # echo "# This recipe was used to generate this AppImage." >> ./$APP.AppDir/Recipe 326 | # echo "# See http://appimage.org for more information." >> ./$APP.AppDir/Recipe 327 | # echo "" >> ./$APP.AppDir/Recipe 328 | # cat $RECIPE >> ./$APP.AppDir/Recipe 329 | # fi 330 | # 331 | # Detect the architecture of what we are packaging. 332 | # The main binary could be a script, so let's use a .so library 333 | BIN=$(find . -name *.so* -type f | head -n 1) 334 | INFO=$(file "$BIN") 335 | if [ -z $ARCH ] ; then 336 | if [[ $INFO == *"x86-64"* ]] ; then 337 | ARCH=x86_64 338 | elif [[ $INFO == *"i686"* ]] ; then 339 | ARCH=i686 340 | elif [[ $INFO == *"armv6l"* ]] ; then 341 | ARCH=armhf 342 | else 343 | echo "Could not automatically detect the architecture." 344 | echo "Please set the \$ARCH environment variable." 345 | exit 1 346 | fi 347 | fi 348 | 349 | mkdir -p ../out || true 350 | rm ../out/$APP"-"$VERSION".glibc"$GLIBC_NEEDED"-"$ARCH".AppImage" 2>/dev/null || true 351 | GLIBC_NEEDED=$(glibc_needed) 352 | ./AppImageAssistant ./$APP.AppDir/ ../out/$APP"-"$VERSION".glibc"$GLIBC_NEEDED"-"$ARCH".AppImage" 353 | } 354 | 355 | # Generate AppImage type 2 356 | # Additional parameters given to this routine will be passed on to appimagetool 357 | # 358 | # If the environment variable NO_GLIBC_VERSION is set, the required glibc version 359 | # will not be added to the AppImage filename 360 | generate_type2_appimage() 361 | { 362 | # Get the ID of the last successful build on Travis CI 363 | # ID=$(wget -q https://api.travis-ci.org/repos/AppImage/appimagetool/builds -O - | head -n 1 | sed -e 's|}|\n|g' | grep '"result":0' | head -n 1 | sed -e 's|,|\n|g' | grep '"id"' | cut -d ":" -f 2) 364 | # Get the transfer.sh URL from the logfile of the last successful build on Travis CI 365 | # Only Travis knows why build ID and job ID don't match and why the above doesn't give both... 366 | # URL=$(wget -q "https://s3.amazonaws.com/archive.travis-ci.org/jobs/$((ID+1))/log.txt" -O - | grep "https://transfer.sh/.*/appimagetool" | tail -n 1 | sed -e 's|\r||g') 367 | # if [ -z "$URL" ] ; then 368 | # URL=$(wget -q "https://s3.amazonaws.com/archive.travis-ci.org/jobs/$((ID+2))/log.txt" -O - | grep "https://transfer.sh/.*/appimagetool" | tail -n 1 | sed -e 's|\r||g') 369 | # fi 370 | URL="https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-${SYSTEM_ARCH}.AppImage" 371 | wget -c "$URL" -O appimagetool 372 | chmod a+x ./appimagetool 373 | appimagetool=$(readlink -f appimagetool) 374 | 375 | if [ "$DOCKER_BUILD" ]; then 376 | appimagetool_tempdir=$(mktemp -d) 377 | mv appimagetool "$appimagetool_tempdir" 378 | pushd "$appimagetool_tempdir" &>/dev/null 379 | ls -al 380 | ./appimagetool --appimage-extract 381 | rm appimagetool 382 | appimagetool=$(readlink -f squashfs-root/AppRun) 383 | popd &>/dev/null 384 | _appimagetool_cleanup() { [ -d "$appimagetool_tempdir" ] && rm -r "$appimagetool_tempdir"; } 385 | trap _appimagetool_cleanup EXIT 386 | fi 387 | 388 | if [ -z ${NO_GLIBC_VERSION+true} ]; then 389 | GLIBC_NEEDED=$(glibc_needed) 390 | VERSION_EXPANDED=$VERSION.glibc$GLIBC_NEEDED 391 | else 392 | VERSION_EXPANDED=$VERSION 393 | fi 394 | 395 | set +x 396 | GLIBC_NEEDED=$(glibc_needed) 397 | if ( [ ! -z "$KEY" ] ) && ( ! -z "$TRAVIS" ) ; then 398 | wget https://github.com/AppImage/AppImageKit/files/584665/data.zip -O data.tar.gz.gpg 399 | ( set +x ; echo $KEY | gpg2 --batch --passphrase-fd 0 --no-tty --skip-verify --output data.tar.gz --decrypt data.tar.gz.gpg ) 400 | tar xf data.tar.gz 401 | sudo chown -R $USER .gnu* 402 | mv $HOME/.gnu* $HOME/.gnu_old ; mv .gnu* $HOME/ 403 | VERSION=$VERSION_EXPANDED "$appimagetool" $@ -n -s --bintray-user $BINTRAY_USER --bintray-repo $BINTRAY_REPO -v ./$APP.AppDir/ 404 | else 405 | VERSION=$VERSION_EXPANDED "$appimagetool" $@ -n --bintray-user $BINTRAY_USER --bintray-repo $BINTRAY_REPO -v ./$APP.AppDir/ 406 | fi 407 | set -x 408 | mkdir -p ../out/ || true 409 | mv *.AppImage* ../out/ 410 | } 411 | 412 | # Generate status file for use by apt-get; assuming that the recipe uses no newer 413 | # ingredients than what would require more recent dependencies than what we assume 414 | # to be part of the base system 415 | generate_status() 416 | { 417 | mkdir -p ./tmp/archives/ 418 | mkdir -p ./tmp/lists/partial 419 | touch tmp/pkgcache.bin tmp/srcpkgcache.bin 420 | wget -q -c "https://github.com/AppImage/AppImages/raw/${PKG2AICOMMIT}/excludedeblist" 421 | rm status 2>/dev/null || true 422 | for PACKAGE in $(cat excludedeblist | cut -d "#" -f 1) ; do 423 | printf "Package: $PACKAGE\nStatus: install ok installed\nArchitecture: all\nVersion: 9:999.999.999\n\n" >> status 424 | done 425 | } 426 | 427 | # Find the desktop file and copy it to the AppDir 428 | get_desktop() 429 | { 430 | find usr/share/applications -iname "*${LOWERAPP}.desktop" -exec cp {} . \; || true 431 | } 432 | 433 | fix_desktop() { 434 | # fix trailing semicolons 435 | for key in Actions Categories Implements Keywords MimeType NotShowIn OnlyShowIn; do 436 | sed -i '/'"$key"'.*[^;]$/s/$/;/' $1 437 | done 438 | } 439 | 440 | # Find the icon file and copy it to the AppDir 441 | get_icon() 442 | { 443 | find ./usr/share/pixmaps/$LOWERAPP.png -exec cp {} . \; 2>/dev/null || true 444 | find ./usr/share/icons -path *64* -name $LOWERAPP.png -exec cp {} . \; 2>/dev/null || true 445 | find ./usr/share/icons -path *128* -name $LOWERAPP.png -exec cp {} . \; 2>/dev/null || true 446 | find ./usr/share/icons -path *512* -name $LOWERAPP.png -exec cp {} . \; 2>/dev/null || true 447 | find ./usr/share/icons -path *256* -name $LOWERAPP.png -exec cp {} . \; 2>/dev/null || true 448 | ls -lh $LOWERAPP.png || true 449 | } 450 | 451 | # Find out the version 452 | get_version() 453 | { 454 | THEDEB=$(find ../*.deb -name $LOWERAPP"_*" | head -n 1) 455 | if [ -z "$THEDEB" ] ; then 456 | echo "Version could not be determined from the .deb; you need to determine it manually" 457 | fi 458 | VERSION=$(echo $THEDEB | cut -d "~" -f 1 | cut -d "_" -f 2 | cut -d "-" -f 1 | sed -e 's|1%3a||g' | sed -e 's|.dfsg||g' ) 459 | echo $VERSION 460 | } 461 | 462 | 463 | # Execute user-supplied hook scripts 464 | run_hooks() 465 | { 466 | for h in "${APPDIR}/../scripts"/*.sh; do 467 | echo ""; echo "Running hook script: \"$h\""; echo ""; 468 | source "$h" 469 | done 470 | } 471 | 472 | 473 | # transfer.sh 474 | transfer() { if [ $# -eq 0 ]; then echo "No arguments specified. Usage:\necho transfer /tmp/test.md\ncat /tmp/test.md | transfer test.md"; return 1; fi 475 | tmpfile=$( mktemp -t transferXXX ); if tty -s; then basefile=$(basename "$1" | sed -e 's/[^a-zA-Z0-9._-]/-/g'); curl --progress-bar --upload-file "$1" "https://transfer.sh/$basefile" >> $tmpfile; else curl --progress-bar --upload-file "-" "https://transfer.sh/$1" >> $tmpfile ; fi; cat $tmpfile; rm -f $tmpfile; } 476 | 477 | # Patch binary files; fill with padding if replacement is shorter than original 478 | # http://everydaywithlinux.blogspot.de/2012/11/patch-strings-in-binary-files-with-sed.html 479 | # Example: patch_strings_in_file foo "/usr/local/lib/foo" "/usr/lib/foo" 480 | patch_strings_in_file() { 481 | local FILE="$1" 482 | local PATTERN="$2" 483 | local REPLACEMENT="$3" 484 | # Find all unique strings in FILE that contain the pattern 485 | STRINGS=$(strings ${FILE} | grep ${PATTERN} | sort -u -r) 486 | if [ "${STRINGS}" != "" ] ; then 487 | echo "File '${FILE}' contain strings with '${PATTERN}' in them:" 488 | for OLD_STRING in ${STRINGS} ; do 489 | # Create the new string with a simple bash-replacement 490 | NEW_STRING=${OLD_STRING//${PATTERN}/${REPLACEMENT}} 491 | # Create null terminated ASCII HEX representations of the strings 492 | OLD_STRING_HEX="$(echo -n ${OLD_STRING} | xxd -g 0 -u -ps -c 256)00" 493 | NEW_STRING_HEX="$(echo -n ${NEW_STRING} | xxd -g 0 -u -ps -c 256)00" 494 | if [ ${#NEW_STRING_HEX} -le ${#OLD_STRING_HEX} ] ; then 495 | # Pad the replacement string with null terminations so the 496 | # length matches the original string 497 | while [ ${#NEW_STRING_HEX} -lt ${#OLD_STRING_HEX} ] ; do 498 | NEW_STRING_HEX="${NEW_STRING_HEX}00" 499 | done 500 | # Now, replace every occurrence of OLD_STRING with NEW_STRING 501 | echo -n "Replacing ${OLD_STRING} with ${NEW_STRING}... " 502 | hexdump -ve '1/1 "%.2X"' ${FILE} | \ 503 | sed "s/${OLD_STRING_HEX}/${NEW_STRING_HEX}/g" | \ 504 | xxd -r -p > ${FILE}.tmp 505 | chmod --reference ${FILE} ${FILE}.tmp 506 | mv ${FILE}.tmp ${FILE} 507 | echo "Done!" 508 | else 509 | echo "New string '${NEW_STRING}' is longer than old" \ 510 | "string '${OLD_STRING}'. Skipping." 511 | fi 512 | done 513 | fi 514 | } 515 | -------------------------------------------------------------------------------- /appimage-helper-scripts/LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | --------------------------------------------------------------------------------