changeset 700:21e4df9865af

Some work on Linux packaging
author Chris Cannam
date Wed, 12 Dec 2018 10:16:11 +0000
parents 646e48a0d3a5
children 0720152d1914
files .hgignore deploy/linux/AppRun deploy/linux/EasyMercurial.desktop deploy/linux/appimage-excludelist deploy/linux/control deploy/linux/debian-dependencies.sh deploy/linux/deploy-appimage.sh deploy/linux/deploy-deb.sh deploy/linux/fix-lintian-bits.sh
diffstat 9 files changed, 462 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Tue Dec 11 16:40:57 2018 +0000
+++ b/.hgignore	Wed Dec 12 10:16:11 2018 +0000
@@ -30,3 +30,7 @@
 easyhg-kdiff3
 mercurial-*-x86
 build_win32
+*.AppDir
+*.AppImage
+.qmake.stash
+squashfs-root
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deploy/linux/AppRun	Wed Dec 12 10:16:11 2018 +0000
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+mydir=$(dirname "$0")
+case "$mydir" in
+    /*) ;;
+    *) mydir="$PWD/$mydir";;
+esac
+
+echo "AppImage root is $mydir"
+
+PATH="$mydir/usr/bin:$mydir/bin:$PATH"
+export PATH
+
+LD_LIBRARY_PATH="$mydir/usr/lib:$mydir/usr/lib/x86_64-linux-gnu:$mydir/usr/lib64:$LD_LIBRARY_PATH"
+export LD_LIBRARY_PATH
+
+QT_PLUGIN_PATH="$mydir/usr/lib/qt5/plugins/:$mydir/usr/lib/x86_64-linux-gnu/qt5/plugins/:$mydir/usr/lib64/qt5/plugins/:$QT_PLUGIN_PATH"
+export QT_PLUGIN_PATH
+
+XDG_DATA_DIRS="$mydir/usr/share:$XDG_DATA_DIRS:/usr/local/share:/usr/share"
+export XDG_DATA_DIRS
+
+GSETTINGS_SCHEMA_DIR="$mydir/usr/share/glib-2.0/schemas:$GSETTINGS_SCHEMA_DIR"
+export GSETTINGS_SCHEMA_DIR
+
+exec "$mydir/usr/bin/EasyMercurial" "$@"
--- a/deploy/linux/EasyMercurial.desktop	Tue Dec 11 16:40:57 2018 +0000
+++ b/deploy/linux/EasyMercurial.desktop	Wed Dec 12 10:16:11 2018 +0000
@@ -1,7 +1,6 @@
 [Desktop Entry]
-Encoding=UTF-8
 Type=Application
-Categories=Development
+Categories=Development;
 Exec=EasyMercurial %f
 MimeType=
 X-KDE-NativeMimeType=
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deploy/linux/appimage-excludelist	Wed Dec 12 10:16:11 2018 +0000
@@ -0,0 +1,184 @@
+# This file lists libraries that we will assume to be present on the host system and hence
+# should NOT be bundled inside AppImages. This is a working document; expect it to change
+# over time. File format: one filename per line. Each entry should have a justification comment.
+
+# See the useful tool at https://abi-laboratory.pro/index.php?view=navigator&symbol=hb_buffer_set_cluster_level#result
+# to investigate issues with missing symbols.
+
+ld-linux.so.2
+ld-linux-x86-64.so.2
+libanl.so.1
+libBrokenLocale.so.1
+libcidn.so.1
+libcrypt.so.1
+libc.so.6
+libdl.so.2
+libm.so.6
+libmvec.so.1
+libnsl.so.1
+libnss_compat.so.2
+libnss_db.so.2
+libnss_dns.so.2
+libnss_files.so.2
+libnss_hesiod.so.2
+libnss_nisplus.so.2
+libnss_nis.so.2
+libpthread.so.0
+libresolv.so.2
+librt.so.1
+libthread_db.so.1
+libutil.so.1
+# These files are all part of the GNU C Library which should never be bundled.
+# List was generated from a fresh build of glibc 2.25.
+
+libstdc++.so.6
+# Workaround for:
+# usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.21' not found
+
+libGL.so.1
+# Part of the video driver (OpenGL); present on any regular
+# desktop system, may also be provided by proprietary drivers.
+# Known to cause issues if it's bundled.
+
+libdrm.so.2
+# Workaround for:
+# Antergos Linux release 2015.11 (ISO-Rolling)
+# /usr/lib/libdrm_amdgpu.so.1: error: symbol lookup error: undefined symbol: drmGetNodeTypeFromFd (fatal)
+# libGL error: unable to load driver: swrast_dri.so
+# libGL error: failed to load driver: swrast
+# Unrecognized OpenGL version
+
+# TODO:
+# Consider to blackilst also libEGL.so.1
+# see https://github.com/knapsu/plex-media-player-appimage/issues/11#issuecomment-394203370
+
+libglapi.so.0
+# Part of mesa
+# known to cause problems with graphics, see https://github.com/RPCS3/rpcs3/issues/4427#issuecomment-381674910
+
+libxcb.so.1
+# Workaround for:
+# Fedora 23
+# symbol lookup error: /lib64/libxcb-dri3.so.0: undefined symbol: xcb_send_fd
+# 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
+# Fedora 25:
+# undefined symbol: xcb_send_request_with_fds
+# https://github.com/AppImage/AppImages/issues/128
+
+libX11.so.6
+# Workaround for:
+# Fedora 23
+# symbol lookup error: ./lib/libX11.so.6: undefined symbol: xcb_wait_for_reply64
+# 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
+
+libgio-2.0.so.0
+# Workaround for:
+# On Ubuntu, "symbol lookup error: /usr/lib/x86_64-linux-gnu/gtk-2.0/modules/liboverlay-scrollbar.so: undefined symbol: g_settings_new"
+
+# libgdk-x11-2.0.so.0 # Missing on openSUSE-Tumbleweed-KDE-Live-x86_64-Snapshot20170601-Media.iso
+# libgtk-x11-2.0.so.0 # Missing on openSUSE-Tumbleweed-KDE-Live-x86_64-Snapshot20170601-Media.iso
+
+libasound.so.2
+# Workaround for:
+# No sound, e.g., in VLC.AppImage (does not find sound cards)
+
+libgdk_pixbuf-2.0.so.0
+# Workaround for:
+# On Ubuntu, get (inkscape:25621): GdkPixbuf-WARNING **: Error loading XPM image loader: Image type 'xpm' is not supported
+
+libfontconfig.so.1
+# Workaround for:
+# Application stalls when loading fonts during application launch; e.g., KiCad on ubuntu-mate
+
+libthai.so.0
+# Workaround for:
+# audacity: /tmp/.mount_AudaciUsFbON/usr/lib/libthai.so.0: version `LIBTHAI_0.1.25' not found (required by /usr/lib64/libpango-1.0.so.0)
+# on openSUSE Tumbleweed
+
+# other "low-level" font rendering libraries
+# should fix https://github.com/probonopd/linuxdeployqt/issues/261#issuecomment-377522251
+# and https://github.com/probonopd/linuxdeployqt/issues/157#issuecomment-320755694
+libfreetype.so.6
+libharfbuzz.so.0
+
+# Note, after discussion we do not exlude this, but we can use a dummy library that just does nothing
+# libselinux.so.1
+# Workaround for:
+# sed: error while loading shared libraries: libpcre.so.3: cannot open shared object file: No such file or directory
+# Some distributions, such as Arch Linux, do not come with libselinux.so.1 by default.
+# The solution is to bundle a dummy mock library:
+# echo "extern int is_selinux_enabled(void){return 0;}" >> selinux-mock.c
+# gcc -s -shared -o libselinux.so.1 -Wl,-soname,libselinux.so.1 selinux-mock.c 
+# strip libselinux.so.1
+# More information: https://github.com/AppImage/AppImages/issues/83
+
+# The following are assumed to be part of the base system
+# Removing these has worked e.g., for Krita. Feel free to report if
+# you think that some of these should go into AppImages and why.
+libcom_err.so.2
+libcrypt.so.1
+libexpat.so.1
+libgcc_s.so.1
+libglib-2.0.so.0
+libgpg-error.so.0
+# libgssapi_krb5.so.2 # Disputed, seemingly needed by Arch Linux since Kerberos is named differently there
+# libgssapi.so.3 # Seemingly needed when running Ubuntu 14.04 binaries on Fedora 23
+# libhcrypto.so.4 # Missing on openSUSE LEAP 42.0
+# libheimbase.so.1 # Seemingly needed when running Ubuntu 14.04 binaries on Fedora 23
+# libheimntlm.so.0 # Seemingly needed when running Ubuntu 14.04 binaries on Fedora 23
+# libhx509.so.5 # Missing on openSUSE LEAP 42.0
+libICE.so.6
+# libidn.so.11 # Does not come with Solus by default
+# libk5crypto.so.3 # Runnning AppImage built on Debian 9 or Ubuntu 16.04 on an Archlinux fails otherwise; https://github.com/AppImage/AppImages/issues/301
+libkeyutils.so.1
+# libkrb5.so.26 # Disputed, seemingly needed by Arch Linux since Kerberos is named differently there. Missing on openSUSE LEAP 42.0
+# libkrb5.so.3 # Disputed, seemingly needed by Arch Linux since Kerberos is named differently there
+# libkrb5support.so.0 # Disputed, seemingly needed by Arch Linux since Kerberos is named differently there
+libp11-kit.so.0
+# libpcre.so.3 # Missing on Fedora 24, SLED 12 SP1, and openSUSE Leap 42.2
+# libroken.so.18 # Mission on openSUSE LEAP 42.0
+# libsasl2.so.2 # Seemingly needed when running Ubuntu 14.04 binaries on Fedora 23
+libSM.so.6
+libusb-1.0.so.0
+libuuid.so.1
+# libwind.so.0 # Missing on openSUSE LEAP 42.0
+libz.so.1
+
+# Potentially dangerous libraries
+libgobject-2.0.so.0
+
+# Workaround for:
+# Rectangles instead of fonts
+# https://github.com/AppImage/AppImages/issues/240
+libpangoft2-1.0.so.0
+libpangocairo-1.0.so.0
+libpango-1.0.so.0
+
+# Workaround for:
+# e.g., Spotify
+# relocation error: /lib/x86_64-linux-gnu/libgcrypt.so.20: 
+# symbol gpgrt_lock_lock, version GPG_ERROR_1.0 not defined
+# in file libgpg-error.so.0 with link time reference
+libgpg-error.so.0
+
+libjack.so.0
+# it must match the ABI of the JACK server which is installed in the base system
+# rncbc confirmed this
+
+# Unsolved issue:
+# https://github.com/probonopd/linuxdeployqt/issues/35
+# Error initializing NSS with a persistent database (sql:/home/me/.pki/nssdb): libsoftokn3.so: cannot open shared object file: No such file or directory
+# Error initializing NSS without a persistent database: NSS error code: -5925
+# nss_error=-5925, os_error=0
+# libnss3.so should not be removed from the bundles, as this causes other issues, e.g.,
+# https://github.com/probonopd/linuxdeployqt/issues/35#issuecomment-256213517
+# and https://github.com/AppImage/AppImages/pull/114
+# libnss3.so
+
+# The following cannot be excluded, see
+# https://github.com/AppImage/AppImages/commit/6c7473d8cdaaa2572248dcc53d7f617a577ade6b
+# http://stackoverflow.com/questions/32644157/forcing-a-binary-to-use-a-specific-newer-version-of-a-shared-library-so
+# libssl.so.1
+# libssl.so.1.0.0
+# libcrypto.so.1
+# libcrypto.so.1.0.0
--- a/deploy/linux/control	Tue Dec 11 16:40:57 2018 +0000
+++ b/deploy/linux/control	Wed Dec 12 10:16:11 2018 +0000
@@ -1,7 +1,7 @@
 Package: easymercurial
 Priority: optional
 Maintainer: Chris Cannam <cannam@all-day-breakfast.com>
-Architecture: amd64
-Version: 0.9.8cc-1
-Depends: mercurial (>= 1.7.0),libqtgui4 (>= 4.6.0),libqt4-network,python-crypto,python-qt4
+Architecture: ###
+Version: ###
+Depends: ###
 Description: A simple user interface for the Mercurial version-control system
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deploy/linux/debian-dependencies.sh	Wed Dec 12 10:16:11 2018 +0000
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+target=$1
+
+if [ ! -f "$target" ]; then 
+    echo "Usage: $0 target-executable"
+    exit 1
+fi
+
+set -eu
+
+pfile=/tmp/packages_$$
+rfile=/tmp/redundant_$$
+
+trap "rm -f $pfile $rfile" 0
+echo 1>&2
+
+ldd "$target" | awk '{ print $3; }' | grep '^/' | while read lib; do
+    if test -n "$lib" ; then
+	dpkg-query -S "$lib"
+    fi
+    done | grep ': ' | awk -F: '{ print $1 }' | sort | uniq > $pfile
+
+echo "Packages providing required libraries:" 1>&2
+cat $pfile 1>&2
+echo 1>&2
+
+for p in `cat $pfile`; do 
+    echo Looking at $p 1>&2
+    apt-cache showpkg "$p" | grep '^  ' | grep ',' | awk -F, '{ print $1; }' | \
+	while read d; do 
+	    if grep -q '^'$d'$' $pfile; then
+		echo $p
+	    fi
+    done
+done | sort | uniq > $rfile
+
+echo "Packages that can be eliminated because other packages depend on them:" 1>&2
+cat $rfile 1>&2
+echo 1>&2
+
+cat $pfile $rfile | sort | uniq -u | sed 's/$/,/' | fmt -1000 | sed 's/^/Depends: /' | sed 's/,$/, libc6/' | sed 's/libjack0,/jackd,/'
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deploy/linux/deploy-appimage.sh	Wed Dec 12 10:16:11 2018 +0000
@@ -0,0 +1,117 @@
+#!/bin/bash
+
+set -eu
+
+program=EasyMercurial
+
+get_id() {
+    if [ -d .hg ]; then
+        hg id | sed 's/[+ ].*$//'
+    elif [ -d .git ]; then
+        git rev-parse --short HEAD
+    else
+        echo "WARNING: can't figure out revision from VCS metadata" 1>&2
+        echo "unknown"
+    fi
+}
+
+version=$(get_id)
+
+if [ ! -x ./appimagetool-x86_64.AppImage ]; then
+    echo "Failed to find executable ./appimagetool-x86_64.AppImage, please provide that first"
+    exit 2
+fi
+
+targetdir="${program}.AppDir"
+
+echo "Target dir is $targetdir"
+
+if [ -d "$targetdir" ]; then
+    echo "Target directory exists, not overwriting"
+    exit 2
+fi
+
+mkdir "$targetdir"
+
+mkdir -p "$targetdir"/usr/bin
+mkdir -p "$targetdir"/usr/lib
+
+cp "$program" "$targetdir"/usr/bin/
+
+add_dependencies() {
+
+    local binary="$1"
+
+    echo "ldd $binary yields:"
+    ldd "$binary"
+    
+    for lib in $(ldd "$binary" | grep '=> [^ ]*/lib/' | \
+                     sed 's/^.*=> //' | sed 's/ .*$//'); do
+
+        base=$(basename "$lib")
+        if grep -v '^#' deploy/linux/appimage-excludelist |
+                grep -q "^$base$" ; then
+            echo "excluding: $lib"
+            continue
+        fi
+
+        target="$targetdir/usr/lib/$(basename $lib)"
+        
+        mkdir -p "$(dirname $target)"
+
+        if [ ! -f "$target" ]; then
+
+            cp -Lv "$lib" "$target"
+            chmod +x "$target"
+            
+            add_dependencies "$lib"
+            
+        fi
+    done
+}
+
+add_dependencies "$program"
+
+qtplugins="gif icns ico jpeg tga tiff wbmp webp cocoa minimal offscreen xcb"
+qtlibdirs="/usr/lib/x86_64-linux-gnu/qt5 /usr/lib/x86_64-linux-gnu/qt /usr/lib/qt5 /usr/lib/qt"
+
+QTDIR=${QTDIR:-}
+if [ -n "$QTDIR" ]; then
+    qtlibdirs="$QTDIR $qtlibdirs"
+fi
+
+for plug in $qtplugins; do
+    for libdir in $qtlibdirs; do
+        lib=$(find $libdir/plugins -name libq$plug.so -print 2>/dev/null || true)
+        if [ -n "$lib" ]; then
+            if [ -f "$lib" ]; then
+                subdir=$(basename $(dirname $lib))
+                if [ t"$subdir" = t"plugins" ]; then
+                    subdir=""
+                fi
+                target="$targetdir/usr/lib/qt5/plugins/$subdir/$(basename $lib)"
+                mkdir -p "$(dirname $target)"
+                cp -v "$lib" "$target"
+                chmod +x "$target"
+                add_dependencies "$lib"
+                break
+            fi
+        fi
+    done
+done
+
+cp "deploy/linux/$program.desktop" "$targetdir/"
+
+cp images/icon/scalable/easyhg-icon.svg "$targetdir/"
+cp images/icon/scalable/easyhg-icon.svg "$targetdir/$program.svg"
+cp images/icon/128/easyhg-icon.png "$targetdir/"
+
+cp "deploy/linux/AppRun" "$targetdir/"
+
+chmod +x "$targetdir/AppRun"
+
+# Do this with a separate extraction step, so as to make it work even
+# in situations where FUSE is unavailable like in a Docker container
+export ARCH=x86_64
+./appimagetool-x86_64.AppImage --appimage-extract
+./squashfs-root/AppRun "$targetdir" "$program-$version-x86_64.AppImage"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deploy/linux/deploy-deb.sh	Wed Dec 12 10:16:11 2018 +0000
@@ -0,0 +1,65 @@
+#!/bin/bash
+# 
+# Run this from the build root (with sudo, I think)
+
+usage() {
+    echo
+    echo "Usage:"
+    echo
+    echo "$0 <version> <architecture>"
+    echo
+    echo "For example: $0 1.4cc1-1 amd64"
+    echo
+    exit 2
+}
+
+version="$1"
+arch="$2"
+
+if [ -z "$version" ] || [ -z "$arch" ]; then
+    usage
+fi
+
+set -eu
+
+program=EasyMercurial
+depdir=deploy/linux
+
+targetdir="${program}_${version}_${arch}"
+
+echo "Target dir is $targetdir"
+
+if [ -d "$targetdir" ]; then
+    echo "Target directory exists, not overwriting"
+    exit
+fi
+
+mkdir "$targetdir"
+
+mkdir "$targetdir/DEBIAN"
+
+cp "$depdir"/control "$targetdir"/DEBIAN/
+
+mkdir -p "$targetdir"/usr/bin "$targetdir"/usr/share/pixmaps "$targetdir"/usr/share/applications "$targetdir"/usr/share/doc/"$program"
+
+cp "$program" "$targetdir"/usr/bin/
+
+cp images/icon/scalable/easyhg-icon.svg "$targetdir"/usr/share/pixmaps/
+cp images/icon/128/easyhg-icon.png "$targetdir"/usr/share/pixmaps/
+cp deploy/linux/"$program".desktop "$targetdir"/usr/share/applications/
+cp README.txt "$targetdir"/usr/share/doc/"$program"/
+
+perl -i -p -e "s/Architecture: .*/Architecture: $arch/" "$targetdir"/DEBIAN/control
+
+deps=`bash "$depdir"/debian-dependencies.sh "$program"`
+
+perl -i -p -e "s/Depends: .*/$deps/" "$targetdir"/DEBIAN/control
+
+control_ver=${version%-?}
+
+perl -i -p -e "s/Version: .*/Version: $control_ver/" "$targetdir"/DEBIAN/control
+
+bash "$depdir"/fix-lintian-bits.sh "$targetdir"
+
+dpkg-deb --build "$targetdir" && lintian "$targetdir".deb
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deploy/linux/fix-lintian-bits.sh	Wed Dec 12 10:16:11 2018 +0000
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+dir=$1
+
+[ -d "$dir" ] || exit 1
+
+set -eu
+
+strip "$dir"/usr/bin/*
+
+sz=`du -sx --exclude DEBIAN "$dir" | awk '{ print $1; }'`
+perl -i -p -e "s/Installed-Size: .*/Installed-Size: $sz/" "$dir"/DEBIAN/control
+
+find "$dir" -name \*~ -exec rm \{\} \;
+
+chown -R root.root "$dir"/*
+
+chmod -R g-w "$dir"/*