313 lines
10 KiB
Bash
Executable File
313 lines
10 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Create a signed and notarized JMRI macOS disk image (from diskimage.sh) from an unsigned one
|
|
# This is structured to use the Mac OS X tools when run on a Mac, and native Linux tools when run on a Linux box,
|
|
# but only the OS X version is being actively developed because it relies on some Apple-specific
|
|
# tools for notarization.
|
|
#
|
|
# arguments are:
|
|
# Release version string e.g. "4.5.5", e.g. "${release.version-string}" from Ant
|
|
# Output DMG file pathname e.g. dist/release/JMRI.4.5.5.dmg, "${dist.release}/JMRI.${release.version-string}.dmg" in Ant
|
|
# Input DMG file pathname e.g. dist/release/JMRI.4.5.5-unsigned.dmg,
|
|
# ID of signing certificate, i.e. "Developer ID Application: My Name"
|
|
# Apple ID for notarization
|
|
# Application-specific password on that Apple ID (see appleid.apple.com)
|
|
# Location of keychain file containing that certificate
|
|
# Password to unlock that keychain file
|
|
#
|
|
# Although it might be consuming additional space on the final disk image,
|
|
# we do the signing and jar-updating there to ensure this doesn't
|
|
# cause issues for other uses of the raw as-built files
|
|
#
|
|
# Copyright 2007, 2011, 2016, 2019 Bob Jacobsen, david d zuhn
|
|
#
|
|
|
|
set -e # bail on errors
|
|
set -x # show our work
|
|
|
|
whoami
|
|
|
|
REL_VER=$1
|
|
OUTPUT=$2
|
|
INPUTIMAGEFILE=$3
|
|
CERTIFICATE=$4
|
|
AC_USER=$5
|
|
AC_PASSWORD=$6
|
|
KEYCHAIN_FILE=$7
|
|
|
|
JAR=/usr/bin/jar
|
|
|
|
# -----------------------------------------
|
|
function trapExitHandler {
|
|
trap - 1 2 3 15
|
|
cp /tmp/php-temp-out-file.dmg /tmp/test.dmg
|
|
umount "$tmpimage2" && echo "Unmounted tmpimage2"
|
|
umount "$tmpindir" && echo "Unmounted tempindir"
|
|
rm -rf "$INPUTIMAGEFILE" && echo "Deleted input image file"
|
|
umount "$tmpoutdir" && echo "Unmounted tmpoutdir image"
|
|
rm -rf "$tmpimage1" "$tmpimage2" "$tmpoutdir" "$tmpindir" >/dev/null 2>&1
|
|
}
|
|
# -----------------------------------------
|
|
# Retry a command up to a specific number of times until it exits successfully.
|
|
# Waits 1 minute between retries
|
|
#
|
|
# $ retry 5 echo Hello
|
|
# Hello
|
|
#
|
|
#
|
|
function retry {
|
|
local retries=$1
|
|
shift
|
|
|
|
local count=0
|
|
until "$@"; do
|
|
exit=$?
|
|
wait=60
|
|
count=$(($count + 1))
|
|
if [ $count -lt $retries ]; then
|
|
echo "Retry $count/$retries exited $exit, retrying in $wait seconds..."
|
|
sleep $wait
|
|
else
|
|
echo "Retry $count/$retries exited $exit, no more retries left."
|
|
return $exit
|
|
fi
|
|
done
|
|
return 0
|
|
}
|
|
# -----------------------------------------
|
|
# Sign a file (2nd arg) with a jar file (1st arg) in place
|
|
#
|
|
function signJarMember {
|
|
local jar=$1
|
|
local file=$2
|
|
|
|
if [ -f "$jar" ]
|
|
then
|
|
export JAVA_HOME=`/usr/libexec/java_home -v 1.8`
|
|
$JAR xf $jar $file
|
|
signFile $file
|
|
$JAR uvf $jar $file
|
|
rm $file
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
# -----------------------------------------
|
|
# Sign a single file (1st arg)
|
|
#
|
|
function signFile {
|
|
local file=$1
|
|
echo sign $file
|
|
|
|
if [ -e "$file" ]
|
|
then
|
|
xattr -lr $file
|
|
xattr -cr $file
|
|
sudo -u jake codesign -v -s "$CERTIFICATE" --force --keychain "$KEYCHAIN_FILE" --deep $file
|
|
fi
|
|
return 0
|
|
}
|
|
# -----------------------------------------
|
|
|
|
|
|
if [ "$REL_VER" = "" -o "$OUTPUT" = "" -o "$INPUTIMAGEFILE" = "" ]
|
|
then
|
|
echo "usage: $0 VERSION OUTPUTIMAGEFILE INPUTIMAGEFILE" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
# switch to a directory with known-good permissions
|
|
if ! workdir=`mktemp -d -t workdir`
|
|
then
|
|
echo "Cannot create temporary working directory"
|
|
exit 1
|
|
fi
|
|
cd $workdir
|
|
echo 'workdir' $workdir
|
|
|
|
if [ -x /usr/bin/hdiutil ]
|
|
then
|
|
# if a Linux box were to have hdiutil, I think that would be the preferable route to follow
|
|
# although it's pretty unlikely
|
|
SYSTEM=MACOSX
|
|
|
|
export JAVA_HOME=`/usr/libexec/java_home -v 1.8`
|
|
java -version
|
|
else
|
|
SYSTEM=LINUX
|
|
fi
|
|
|
|
if ! tmpoutdir=`mktemp -d -t JMRI.output`
|
|
then
|
|
echo "Cannot create output temporary directory"
|
|
exit 1
|
|
fi
|
|
echo "tmpoutdir" $tmpoutdir
|
|
|
|
if ! tmpindir=`mktemp -d -t JMRI.input`
|
|
then
|
|
echo "Cannot create input temporary directory"
|
|
exit 1
|
|
fi
|
|
echo 'tmpindir' $tmpindir
|
|
|
|
if ! tmpimage1=`mktemp -t JMRI.tmp.image.1`
|
|
then
|
|
echo "Cannot create temp image 1"
|
|
exit
|
|
fi
|
|
echo 'tempimage1' $tmpimage1
|
|
|
|
if ! tmpimage2=`mktemp -t JMRI.tmp.image.2`
|
|
then
|
|
echo "Cannot create temp image 1"
|
|
exit 1
|
|
fi
|
|
echo 'tmpimage2' $tmpimage2
|
|
|
|
# handle cleanup on exit
|
|
trap trapExitHandler 0
|
|
# handle error signals by aborting
|
|
trap 'exit 2' 1 2 3 15
|
|
|
|
# shouldn't be anything left over, but if so, clean up
|
|
|
|
rm -f "$tmpimage1" "$tmpimage2"
|
|
|
|
# mount input image
|
|
sync
|
|
hdiutil attach "$INPUTIMAGEFILE" -mountpoint "$tmpindir" -nobrowse
|
|
echo "INPUTIMAGEFILE" $INPUTIMAGEFILE
|
|
|
|
# create disk image and mount
|
|
jmrisize=`du -ms "$tmpindir" | awk '{print $1}'`
|
|
imagesize=`expr $jmrisize + 80`
|
|
|
|
if [ "$SYSTEM" = "MACOSX" ]
|
|
then
|
|
hdiutil create -size ${imagesize}MB -fs HFS+ -layout SPUD -volname "JMRI ${REL_VER}" "$tmpimage2"
|
|
hdiutil attach ${tmpimage2}.dmg -mountpoint "$tmpoutdir" -nobrowse
|
|
else
|
|
dd if=/dev/zero of="$tmpimage2" bs=1M count=${imagesize}
|
|
mkfs.hfsplus -v "JMRI ${REL_VER}" "${tmpimage2}"
|
|
sudo mount -t hfsplus -o loop,rw,uid=$UID "$tmpimage2" $tmpoutdir
|
|
fi
|
|
|
|
# wait for the mountpoint to settle down...
|
|
# I don't think we need this on macOS
|
|
#sleep 10
|
|
|
|
if [ -w "$tmpoutdir" ]
|
|
then
|
|
SUDO=
|
|
else
|
|
SUDO=sudo
|
|
fi
|
|
|
|
# copy contents of the Mac OS X distribution to the newly mounted filesysten
|
|
tar -C "$tmpindir" -cf - JMRI | $SUDO tar -C "$tmpoutdir" -xf -
|
|
|
|
# unlock login keychain (if needed, which is when?)
|
|
#security unlock-keychain -p password /Users/jake/Library/Keychains/login.keychain-db
|
|
|
|
# display debug info for the keychain containing the certification
|
|
#security list-keychains
|
|
#security -v default-keychain
|
|
#security -v login-keychain
|
|
#security -v show-keychain-info "$KEYCHAIN_FILE"
|
|
#security -v show-keychain-info /Users/jake/Library/Keychains/login.keychain-db
|
|
#security -v find-certificate -c "$CERTIFICATE" "$KEYCHAIN_FILE"
|
|
|
|
# sign the app files in output
|
|
signFile $tmpoutdir/JMRI/PanelPro.app
|
|
signFile $tmpoutdir/JMRI/DecoderPro.app
|
|
signFile $tmpoutdir/JMRI/SoundPro.app
|
|
signFile $tmpoutdir/JMRI/LccPro.app
|
|
|
|
# clear attributes in lib
|
|
xattr -cr $tmpoutdir/JMRI/lib
|
|
|
|
# sign the individual library files
|
|
signFile $tmpoutdir/JMRI/lib/macosx/libgluegen-rt.jnilib
|
|
signFile $tmpoutdir/JMRI/lib/macosx/libjinput-osx.jnilib
|
|
signFile $tmpoutdir/JMRI/lib/macosx/libjoal.jnilib
|
|
|
|
signFile $tmpoutdir/JMRI/lib/macosx/libgluegen_rt.dylib
|
|
signFile $tmpoutdir/JMRI/lib/macosx/libjoal.dylib
|
|
signFile $tmpoutdir/JMRI/lib/macosx/libopenal.1.15.1.dylib
|
|
signFile $tmpoutdir/JMRI/lib/macosx/libopenal.1.dylib
|
|
signFile $tmpoutdir/JMRI/lib/macosx/libopenal.dylib
|
|
|
|
# sign libraries inside jar files
|
|
signJarMember $tmpoutdir/JMRI/lib/libusb4java-1.3.0-darwin-x86-64.jar org/usb4java/darwin-x86-64/libusb4java.dylib
|
|
signJarMember $tmpoutdir/JMRI/lib/libusb4java-1.3.0-darwin-aarch64.jar org/usb4java/darwin-aarch64/libusb4java.dylib
|
|
signJarMember $tmpoutdir/JMRI/lib/libusb4java-1.3.0-darwin-aarch64.jar org/usb4java/darwin-x86-64/libusb4java.dylib
|
|
signJarMember $tmpoutdir/JMRI/lib/bluecove-2.1.1-SNAPSHOT.jar libbluecove.jnilib
|
|
|
|
signJarMember $tmpoutdir/JMRI/lib/jna-4.4.0.jar com/sun/jna/darwin/libjnidispatch.jnilib
|
|
signJarMember $tmpoutdir/JMRI/lib/jna-5.9.0.jar com/sun/jna/darwin-x86-64/libjnidispatch.jnilib
|
|
signJarMember $tmpoutdir/JMRI/lib/jna-5.9.0.jar com/sun/jna/darwin-aarch64/libjnidispatch.jnilib
|
|
|
|
signJarMember $tmpoutdir/JMRI/lib/hid4java-0.5.0.jar darwin/libhidapi.dylib
|
|
# signJarMember $tmpoutdir/JMRI/lib/selenium-server-standalone-3.6.0.jar com/sun/jna/darwin/libjnidispatch.jnilib # OMITTED DUE TO TOC ISSUE
|
|
signJarMember $tmpoutdir/JMRI/lib/jython-standalone-2.7.2.jar META-INF/native/osx/libjansi.jnilib
|
|
signJarMember $tmpoutdir/JMRI/lib/jython-standalone-2.7.2.jar jni/Darwin/libjffi-1.2.jnilib
|
|
|
|
# added 2024-08-29
|
|
signJarMember $tmpoutdir/JMRI/lib/jinput-2.0.9-natives-all.jar libjinput-osx.jnilib
|
|
signJarMember $tmpoutdir/JMRI/lib/jna-5.13.0.jar com/sun/jna/darwin-aarch64/libjnidispatch.jnilib
|
|
signJarMember $tmpoutdir/JMRI/lib/jna-5.13.0.jar com/sun/jna/darwin-x86-64/libjnidispatch.jnilib
|
|
signJarMember $tmpoutdir/JMRI/lib/jSerialComm-2.10.4.jar OSX/x86/libjSerialComm.jnilib
|
|
signJarMember $tmpoutdir/JMRI/lib/jSerialComm-2.10.4.jar OSX/aarch64/libjSerialComm.jnilib
|
|
signJarMember $tmpoutdir/JMRI/lib/jSerialComm-2.10.4.jar OSX/x86_64/libjSerialComm.jnilib
|
|
signJarMember $tmpoutdir/JMRI/lib/jython-standalone-2.7.2.jar jni/Darwin/libjffi-1.2.jnilib
|
|
|
|
# added 2024-09-03
|
|
signJarMember $tmpoutdir/JMRI/lib/jython-standalone-2.7.4.jar META-INF/native/osx/libjansi.jnilib
|
|
signJarMember $tmpoutdir/JMRI/lib/jython-standalone-2.7.4.jar jni/Darwin/libjffi-1.2.jnilib
|
|
|
|
# added 2025-03-09 for DarkLAF
|
|
signJarMember $tmpoutdir/JMRI/lib/darklaf-macos-3.0.2.jar com/github/weisj/darklaf/platform/darklaf-macos/libdarklaf-macos-x86-64.dylib
|
|
signJarMember $tmpoutdir/JMRI/lib/darklaf-macos-3.0.2.jar com/github/weisj/darklaf/platform/darklaf-macos/libdarklaf-macos-arm64.dylib
|
|
|
|
# add an Applications icon
|
|
$SUDO ln -s /Applications "$tmpoutdir"
|
|
|
|
# now, how do we make a nice background picture in the folder with directions on how to drag'n'drop to Applications?
|
|
|
|
# eject the mounted disk image
|
|
if [ "$SYSTEM" = "MACOSX" ]
|
|
then
|
|
hdiutil detach "$tmpoutdir" && EJECTED=1
|
|
else
|
|
sudo umount "$tmpoutdir" && EJECTED=1
|
|
fi
|
|
|
|
|
|
# pack into a smaller disk image for distribution
|
|
if [ "$SYSTEM" = "MACOSX" ]
|
|
then
|
|
rm -f "$OUTPUT"
|
|
hdiutil convert ${tmpimage2}.dmg -format UDZO -imagekey zlib-level=9 -o "$OUTPUT"
|
|
else
|
|
# this relies on the 'dmg' tool from https://github.com/erwint/libdmg-hfsplus
|
|
dmg dmg "$tmpimage2" "$OUTPUT"
|
|
fi
|
|
|
|
# sign image file
|
|
signFile "$OUTPUT"
|
|
|
|
# notarize distribution: start by uploading
|
|
# xcrun altool --notarize-app --primary-bundle-id "org.jmri" --username "$AC_USER" --password "$AC_PASSWORD" --file "$OUTPUT"
|
|
xcrun notarytool submit /tmp/php-temp-out-file.dmg --apple-id "$AC_USER" --password "$AC_PASSWORD" --team-id V2UXGA8SJW --wait
|
|
|
|
# stapling result will temporarily fail while the notatization is still happening at Apple
|
|
# --wait in new (Nov 2022) notarytool operation above should make this redundant
|
|
sleep 30
|
|
retry 20 xcrun stapler staple "$OUTPUT"
|
|
|
|
# clean up
|
|
hdiutil detach $tmpindir
|
|
# this should also be handled by the trap, but it doesn't hurt...
|
|
rm -rf $tmpimage1 $tmpimage2 $tmpoutdir
|