changeset 699:646e48a0d3a5

Some work on macOS packaging
author Chris Cannam
date Tue, 11 Dec 2018 16:40:57 +0000
parents 52b8a499f379
children 21e4df9865af
files deploy/osx/copy-qt.sh deploy/osx/deploy.sh deploy/osx/paths.sh deploy/osx/qt.conf deploy/osx/sign.sh src/fswatcher.cpp src/hgrunner.cpp
diffstat 7 files changed, 157 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deploy/osx/copy-qt.sh	Tue Dec 11 16:40:57 2018 +0000
@@ -0,0 +1,59 @@
+#!/bin/bash
+
+set -eu
+
+app="$1"
+if [ -z "$app" ]; then
+	echo "Usage: $0 <appname>"
+	echo "Provide appname without the .app extension, please"
+	exit 2
+fi
+
+frameworks="QtCore QtNetwork QtGui QtWidgets QtPrintSupport QtDBus"
+
+plugins="gif icns ico jpeg tga tiff wbmp webp cocoa macstyle minimal offscreen"
+
+qtdir=$(grep "Command:" Makefile | head -1 | awk '{ print $3; }' | sed s,/bin/.*,,)
+
+if [ ! -d "$qtdir" ]; then
+    echo "Failed to discover Qt installation directory from Makefile, exiting"
+    exit 2
+fi
+
+fdir="$app.app/Contents/Frameworks"
+pdir="$app.app/Contents/plugins"
+
+mkdir -p "$fdir"
+mkdir -p "$pdir"
+
+echo
+echo "Copying frameworks..."
+for fwk in $frameworks; do
+    if [ ! -d "$qtdir/lib/$fwk.framework" ]; then
+	if [ "$fwk" = "QtDBus" ]; then
+	    echo "QtDBus.framework not found, assuming Qt was built without DBus support"
+	    continue
+	fi
+    fi
+    cp -v "$qtdir/lib/$fwk.framework/$fwk" "$fdir" || exit 2
+done
+
+echo "Done"
+
+echo
+echo "Copying plugins..."
+for plug in $plugins; do
+    pfile=$(ls "$qtdir"/plugins/*/libq"$plug".dylib)
+    if [ ! -f "$pfile" ]; then
+	echo "Failed to find plugin $plug, exiting"
+	exit 2
+    fi
+    target="$pdir"/${pfile##?*plugins/}
+    tdir=`dirname "$target"`
+    mkdir -p "$tdir"
+    cp -v "$pfile" "$target" || exit 2
+done
+
+echo "Done"
+
+
--- a/deploy/osx/deploy.sh	Mon Dec 10 17:52:27 2018 +0000
+++ b/deploy/osx/deploy.sh	Tue Dec 11 16:40:57 2018 +0000
@@ -16,15 +16,17 @@
         echo "  but the .app name must include .app"
 	exit 2
 fi
-app=EasyMercurial
+app=`basename "$source" .app`
 
 set -u
 
 version=`perl -p -e 's/^[^"]*"([^"]*)".*$/$1/' src/version.h`
-case "$version" in
-    [0-9].[0-9]) bundleVersion="$version".0 ;;
-    [0-9].[0-9].[0-9]) bundleVersion="$version" ;;
-    *) echo "Error: Version $version is neither two- nor three-part number" ;;
+stem=${version%%-*}
+stem=${stem%%pre*}
+case "$stem" in
+    [0-9].[0-9]) bundleVersion="$stem".0 ;;
+    [0-9].[0-9].[0-9]) bundleVersion="$stem" ;;
+    *) echo "Error: Version stem $stem (of version $version) is neither two- nor three-part number" ;;
 esac
 
 echo
@@ -70,14 +72,27 @@
 cp COPYING "$volume/COPYING.txt"
 cp -rp "$source" "$target"
 
+# update file timestamps so as to make the build date apparent
+find "$volume" -exec touch \{\} \;
+
 echo "Done"
 
+echo
+echo "Code-signing volume..."
+
 deploy/osx/sign.sh "$volume" || exit 1
 
+echo "Done"
+
 echo
 echo "Making dmg..."
 
-hdiutil create -srcfolder "$volume" "$dmg" -volname "$volume" && 
+hdiutil create -srcfolder "$volume" "$dmg" -volname "$volume" -fs HFS+ && 
 	rm -r "$volume"
 
+echo
+echo "Signing dmg..."
+
+codesign -s "Developer ID Application: Chris Cannam" -fv "$dmg"
+
 echo "Done"
--- a/deploy/osx/paths.sh	Mon Dec 10 17:52:27 2018 +0000
+++ b/deploy/osx/paths.sh	Tue Dec 11 16:40:57 2018 +0000
@@ -31,45 +31,48 @@
 
 for fwk in $frameworks; do
     find "$app.app" -type f -print | while read x; do
-
-        current=$(otool -L "$x" | 
-	    grep "$fwk" | grep amework | grep -v ':$' | 
-	    awk '{ print $1; }')
+	if [ -x "$x" ]; then
+            current=$(otool -L "$x" | 
+		grep "$fwk" | grep amework | grep -v ':$' | 
+		awk '{ print $1; }')
 	
-        [ -z "$current" ] && continue
+            [ -z "$current" ] && continue
 	
-        echo "$x has $current"
+            echo "$x has $current"
 	
-	case "$x" in
-	    *PyQt4*)
-		# These are "special" Qt4 libraries used by
-		# the PyQt module. They need to refer to their
-		# own local neighbours. Ugh, but let's handle
-		# those manually here.
-		relative="$fwk.so"
-		;;
-	    *)
-		# The normal Qt5 case
-		relative=$(echo "$x" | 
-		    sed -e "s,$app.app/Contents/,," \
-			-e 's,[^/]*/,../,g' \
-			-e 's,/[^/]*$,/Frameworks/'"$fwk"',' )
-		;;
-	esac
+	    case "$x" in
+#		*PyQt*)
+		    # These are "special" Qt libraries used by
+		    # the PyQt module. They need to refer to their
+		    # own local neighbours. Ugh, but let's handle
+		    # those manually here.
+#		    relative="$fwk.so"
+#		    ;;
+		*)
+		    # The normal Qt case
+		    relative=$(echo "$x" | 
+			sed -e "s,$app.app/Contents/,," \
+			    -e 's,[^/]*/,../,g' \
+			    -e 's,/[^/]*$,/Frameworks/'"$fwk"',' )
+		    ;;
+	    esac
 	
-	echo "replacing with relative path $relative"
-	install_name_tool -change \
-	    "$current" "@loader_path/$relative" "$x"
+	    echo "replacing with relative path $relative"
+	    install_name_tool -change \
+		"$current" "@loader_path/$relative" "$x"
+	fi
     done
 done
 
 find "$app.app" -type f -print | while read x; do
-    qtdep=$(otool -L "$x" | grep Qt | grep amework | grep -v ':$' | grep -v '@loader_path' | awk '{ print $1; }')
-    if [ -n "$qtdep" ]; then
-	echo
-	echo "ERROR: File $x depends on Qt framework(s) not apparently present in the bundle:"
-	echo $qtdep
-	exit 1
+    if [ -x "$x" ]; then
+	qtdep=$(otool -L "$x" | grep Qt | grep amework | grep -v ':$' | grep -v '@loader_path' | awk '{ print $1; }')
+	if [ -n "$qtdep" ]; then
+	    echo
+	    echo "ERROR: File $x depends on Qt framework(s) not apparently present in the bundle:"
+	    echo $qtdep
+	    exit 1
+	fi
     fi
 done
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deploy/osx/qt.conf	Tue Dec 11 16:40:57 2018 +0000
@@ -0,0 +1,2 @@
+[Paths]
+Plugins = plugins
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deploy/osx/sign.sh	Tue Dec 11 16:40:57 2018 +0000
@@ -0,0 +1,31 @@
+#!/bin/bash 
+
+set -eu
+
+# Execute this from the top-level directory of the project (the one
+# that contains the .app bundle).  Supply the name of the .app bundle
+# as argument
+dir="$1"
+if [ -z "$dir" ] || [ ! -d "$dir" ]; then
+	echo "Usage: $0 <pkgdir>"
+	echo "Where pkgdir is the directory containing <MyApplication>.app"
+	echo "All .app bundles in pkgdir will be signed"
+	exit 2
+fi
+
+for app in "$dir"/*.app; do
+    find "$app" -name Qt\* -print | while read fr; do
+	codesign -s "Developer ID Application: Chris Cannam" -fv --deep "$fr"
+    done
+    find "$app" -name \*.dylib -print | while read fr; do
+	codesign -s "Developer ID Application: Chris Cannam" -fv --deep "$fr"
+    done
+    find "$app" -name \*.so -print | while read fr; do
+	codesign -s "Developer ID Application: Chris Cannam" -fv --deep "$fr"
+    done
+    codesign -s "Developer ID Application: Chris Cannam" -fv --deep "$app"
+#    codesign -s "Developer ID Application: Chris Cannam" -fv \
+#         --requirements '=designated =>  identifier "org.easymercurial.EasyMercurial" and ( (anchor apple generic and    certificate leaf[field.1.2.840.113635.100.6.1.9] ) or (anchor apple generic and    certificate 1[field.1.2.840.113635.100.6.2.6]  and    certificate leaf[field.1.2.840.113635.100.6.1.13] and    certificate leaf[subject.OU] = "M2H8666U82"))' \
+#         "$app"
+done
+
--- a/src/fswatcher.cpp	Mon Dec 10 17:52:27 2018 +0000
+++ b/src/fswatcher.cpp	Tue Dec 11 16:40:57 2018 +0000
@@ -144,12 +144,12 @@
 
 #ifdef Q_OS_MAC
 static void
-fsEventsCallback(ConstFSEventStreamRef streamRef,
+fsEventsCallback(ConstFSEventStreamRef /* streamRef */,
                  void *clientCallBackInfo,
                  size_t numEvents,
                  void *paths,
-                 const FSEventStreamEventFlags eventFlags[],
-                 const FSEventStreamEventId eventIDs[])
+                 const FSEventStreamEventFlags /* eventFlags */[],
+                 const FSEventStreamEventId /*eventIDs */[])
 {
     FsWatcher *watcher = reinterpret_cast<FsWatcher *>(clientCallBackInfo);
     const char *const *cpaths = reinterpret_cast<const char *const *>(paths);
--- a/src/hgrunner.cpp	Mon Dec 10 17:52:27 2018 +0000
+++ b/src/hgrunner.cpp	Tue Dec 11 16:40:57 2018 +0000
@@ -28,6 +28,7 @@
 #include <QProgressBar>
 #include <QPushButton>
 #include <QGridLayout>
+#include <QCoreApplication>
 
 #include <iostream>
 #include <errno.h>
@@ -44,8 +45,9 @@
 
 HgRunner::HgRunner(QString myDirPath, QWidget *parent) :
     QWidget(parent),
-    m_myDirPath(myDirPath),
-    m_ptyFile(0)
+    m_ptyFile(0),
+    m_proc(0),
+    m_myDirPath(myDirPath)
 {
     QGridLayout *layout = new QGridLayout(this);
     layout->setMargin(0);
@@ -586,6 +588,9 @@
     if (QSettings().value("python32", false).toBool()) {
         env.insert("VERSIONER_PYTHON_PREFER_32_BIT", "1");
     }
+    QDir pluginDir(QCoreApplication::applicationDirPath());
+    pluginDir.cd("../plugins");
+    env.insert("QT_PLUGIN_PATH", pluginDir.canonicalPath());
 #endif
 
     env.insert("LANG", "en_US.utf8");