Mercurial > hg > vamp-plugin-pack
changeset 34:efb73feb1061
Enough MacOS bits to be able to do a quick proof-of-concept test
author | Chris Cannam |
---|---|
date | Fri, 13 Dec 2019 14:14:57 +0000 |
parents | dd41d7369ed5 |
children | d88317090948 |
files | .hgignore deploy/osx/Entitlements.plist deploy/osx/Info.plist deploy/osx/copy-qt.sh deploy/osx/deploy-and-package.sh deploy/osx/deploy.sh deploy/osx/notarize.sh deploy/osx/paths.sh deploy/osx/qt.conf deploy/osx/sign.sh installer.cpp version.h |
diffstat | 12 files changed, 430 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Fri Dec 13 13:54:27 2019 +0000 +++ b/.hgignore Fri Dec 13 14:14:57 2019 +0000 @@ -41,3 +41,7 @@ out/.signed vamp-plugin-pack-installer o/ +.notarization-status +.notarization-uuid +*.dmg +*.app
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deploy/osx/Entitlements.plist Fri Dec 13 14:14:57 2019 +0000 @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<plist version="1.0"> + <dict> + <key>com.apple.security.app-sandbox</key> + <false/> + </dict> +</plist>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deploy/osx/Info.plist Fri Dec 13 14:14:57 2019 +0000 @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd"> +<plist version="0.9"> +<dict> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleName</key> + <string>Vamp Plugin Pack Installer</string> + <key>CFBundleExecutable</key> + <string>Vamp Plugin Pack Installer</string> + <key>CFBundleIdentifier</key> + <string>org.sonicvisualiser.VampPluginPackInstaller</string> + <key>CFBundleShortVersionString</key> + <string>PACK_VERSION</string> + + <!-- enable HiDPI --> + <key>NSPrincipalClass</key> + <string>NSApplication</string> + <key>NSHighResolutionCapable</key> + <string>True</string> + </dict> +</plist>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deploy/osx/copy-qt.sh Fri Dec 13 14:14:57 2019 +0000 @@ -0,0 +1,62 @@ +#!/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 QtXml QtSvg QtWidgets QtPrintSupport QtDBus" + +plugins="gif icns ico jpeg tga tiff wbmp webp cocoa minimal offscreen macstyle" + +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 + +# Sometimes the copied-in files are read-only: correct that +chmod -R u+w "$app.app" + +echo "Done" + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deploy/osx/deploy-and-package.sh Fri Dec 13 14:14:57 2019 +0000 @@ -0,0 +1,97 @@ +#!/bin/bash + +# Run this from the project root, without arguments, or with the +# single argument --no-notarization to skip the notarize step + +set -e + +notarize=yes +if [ "$1" = "--no-notarization" ]; then + notarize=no +elif [ -n "$1" ]; then + echo "Usage: $0 [--no-notarization]" + exit 2 +fi + +set -u + +app="Vamp Plugin Pack Installer" + +version=`perl -p -e 's/^[^"]*"([^"]*)".*$/$1/' version.h` + +source="$app.app" +volume="$app"-"$version" +target="$volume"/"$app".app +dmg="$volume".dmg + +if [ -d "$volume" ]; then + echo "Target directory $volume already exists, not overwriting" + exit 2 +fi + +if [ -f "$dmg" ]; then + echo "Target disc image $dmg already exists, not overwriting" + exit 2 +fi + +if [ "$notarize" = no ]; then + echo + echo "Note: The --no-notarization flag is set: won't be submitting for notarization" +fi + +echo +echo "(Re-)running deploy script..." + +deploy/osx/deploy.sh "$app" || exit 1 + +echo +echo "Making target tree." + +mkdir "$volume" || exit 1 + +ln -s /Applications "$volume"/Applications +#cp README.md "$volume/README.txt" +#cp README.OSC "$volume/README-OSC.txt" +#cp COPYING "$volume/COPYING.txt" +#cp CHANGELOG "$volume/CHANGELOG.txt" +#cp CITATION "$volume/CITATION.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..." + +rm -f "$dmg" + +hdiutil create -srcfolder "$volume" "$dmg" -volname "$volume" -fs HFS+ && + rm -r "$volume" + +echo "Done" + +echo +echo "Signing dmg..." + +codesign -s "Developer ID Application: Chris Cannam" -fv "$dmg" + +if [ "$notarize" = no ]; then + echo + echo "The --no-notarization flag was set: not submitting for notarization" +else + echo + echo "Submitting dmg for notarization..." + + deploy/osx/notarize.sh "$dmg" || exit 1 +fi + +echo "Done"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deploy/osx/deploy.sh Fri Dec 13 14:14:57 2019 +0000 @@ -0,0 +1,58 @@ +#!/bin/bash + +set -e + +# Execute this from the top-level directory of the project (the one +# that contains the .app bundle). Supply the name of the application +# as argument. +# +# This now performs *only* the app deployment step - copying in +# libraries and setting up paths etc. It does not create a +# package. Use deploy-and-package.sh for that. + +app="$1" +source="$app.app" + +if [ -z "$app" ] || [ ! -d "$source" ] || [ -n "$2" ]; then + echo "Usage: $0 <app>" + echo " e.g. $0 MyApplication" + echo " The app bundle must exist in ./<app>.app." + echo " Version number will be extracted from version.h." + exit 2 +fi + +set -u + +version=`perl -p -e 's/^[^"]*"([^"]*)".*$/$1/' version.h` +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 +echo "Copying in frameworks and plugins from Qt installation directory." + +deploy/osx/copy-qt.sh "$app" || exit 2 + +echo +echo "Fixing up paths." + +deploy/osx/paths.sh "$app" + +echo +echo "Copying in qt.conf to set local-only plugin paths." +echo "Make sure all necessary Qt plugins are in $source/Contents/plugins/*" +echo "You probably want platforms/, accessible/ and imageformats/ subdirectories." +cp deploy/osx/qt.conf "$source"/Contents/Resources/qt.conf + +echo +echo "Writing version $bundleVersion in to bundle." +echo "(This should be a three-part number: major.minor.point)" + +perl -p -e "s/PACK_VERSION/$bundleVersion/" deploy/osx/Info.plist \ + > "$source"/Contents/Info.plist + +echo "Done: check $source/Contents/Info.plist for sanity please"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deploy/osx/notarize.sh Fri Dec 13 14:14:57 2019 +0000 @@ -0,0 +1,83 @@ +#!/bin/bash + +## The following assumes we have generated an app password at +## appleid.apple.com and then stored it to keychain id "altool" using +## e.g. +## security add-generic-password -a "cannam+apple@all-day-breakfast.com" \ +## -w "generated-app-password" -s "altool" + +## NB to verify: +# spctl -a -v "/Applications/Application.app" + +user="cannam+apple@all-day-breakfast.com" +bundleid="org.sonicvisualiser.VampPluginPackInstaller" + +set -e + +dmg="$1" + +if [ ! -f "$dmg" ] || [ -n "$2" ]; then + echo "Usage: $0 <dmg>" + echo " e.g. $0 MyApplication-1.0.dmg" + exit 2 +fi + +set -u + +echo +echo "Uploading for notarization..." + +uuidfile=.notarization-uuid +statfile=.notarization-status +rm -f "$uuidfile" "$statfile" + +xcrun altool --notarize-app \ + -f "$dmg" \ + --primary-bundle-id "$bundleid" \ + -u "$user" \ + -p @keychain:altool 2>&1 | tee "$uuidfile" + +uuid=$(cat "$uuidfile" | grep RequestUUID | awk '{ print $3; }') + +if [ -z "$uuid" ]; then + echo + echo "Failed (no UUID returned, check output)" + exit 1 +fi + +echo "Done, UUID is $uuid" + +echo +echo "Waiting and checking for completion..." + +while true ; do + sleep 30 + + xcrun altool --notarization-info \ + "$uuid" \ + -u "$user" \ + -p @keychain:altool 2>&1 | tee "$statfile" + + if grep -q 'Package Approved' "$statfile"; then + echo + echo "Approved! Status output is:" + cat "$statfile" + break + elif grep -q 'in progress' "$statfile" ; then + echo + echo "Still in progress... Status output is:" + cat "$statfile" + echo "Waiting..." + else + echo + echo "Failure or unknown status in output:" + cat "$statfile" + exit 2 + fi +done + +echo +echo "Stapling to package..." + +xcrun stapler staple "$dmg" || exit 1 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deploy/osx/paths.sh Fri Dec 13 14:14:57 2019 +0000 @@ -0,0 +1,61 @@ +#!/bin/bash + +set -e + +app="$1" +if [ -z "$app" ]; then + echo "Usage: $0 <appname>" + echo "Provide appname without the .app extension, please" + exit 2 +fi + +set -u + +frameworks="QtCore QtNetwork QtGui QtXml QtSvg QtWidgets QtPrintSupport QtDBus" + +echo +echo "I expect you to have already copied these frameworks from the Qt installation to" +echo "$app.app/Contents/Frameworks -- expect errors to follow if they're missing:" +echo "$frameworks" +echo + +echo "Fixing up loader paths in binaries..." + +for fwk in $frameworks; do + install_name_tool -id $fwk "$app.app/Contents/Frameworks/$fwk" +done + +find "$app.app" -name \*.dylib -print | while read x; do + install_name_tool -id "`basename \"$x\"`" "$x" +done + +for fwk in $frameworks; do + find "$app.app" -type f -print | while read x; do + if [ -x "$x" ]; then + current=$(otool -L "$x" | grep "$fwk" | grep amework | grep -v ':$' | awk '{ print $1; }') + [ -z "$current" ] && continue + echo "$x has $current" + relative=$(echo "$x" | sed -e "s,$app.app/Contents/,," \ + -e 's,[^/]*/,../,g' \ + -e 's,/[^/]*$,/Frameworks/'"$fwk"',' ) + 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 + 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 + +echo "Done: be sure to run the app and see that it works!" + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deploy/osx/qt.conf Fri Dec 13 14:14:57 2019 +0000 @@ -0,0 +1,2 @@ +[Paths] +Plugins = plugins
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deploy/osx/sign.sh Fri Dec 13 14:14:57 2019 +0000 @@ -0,0 +1,25 @@ +#!/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 + +entitlements=deploy/osx/Entitlements.plist + +for app in "$dir"/*.app; do + find "$app" -name \*.dylib -print | while read fr; do + codesign -s "Developer ID Application: Chris Cannam" -fv --deep --options runtime "$fr" + done + codesign -s "Developer ID Application: Chris Cannam" -fv --deep --options runtime --entitlements "$entitlements" "$app/Contents/MacOS/Vamp Plugin Pack Installer" + codesign -s "Developer ID Application: Chris Cannam" -fv --deep --options runtime --entitlements "$entitlements" "$app" +done +
--- a/installer.cpp Fri Dec 13 13:54:27 2019 +0000 +++ b/installer.cpp Fri Dec 13 14:14:57 2019 +0000 @@ -24,7 +24,15 @@ if (!f.copy(target + e)) { cerr << "Failed to copy " << e.toStdString() << " to target " << (target + e).toStdString() << endl; + continue; } + if (!QFile::setPermissions(target + e, + QFile::ReadOwner | QFile::WriteOwner | + QFile::ExeOwner | QFile::ReadGroup | + QFile::ReadOther)) { + cerr << "Failed to set permissions on " << e.toStdString() << endl; + continue; + } } return 0;