Index: /issm/trunk-jpl/jenkins/mac-silicon-binaries-matlab
===================================================================
--- /issm/trunk-jpl/jenkins/mac-silicon-binaries-matlab	(revision 28113)
+++ /issm/trunk-jpl/jenkins/mac-silicon-binaries-matlab	(revision 28113)
@@ -0,0 +1,96 @@
+MATLAB_PATH="/Applications/MATLAB_R2023b.app"
+
+#--------------------#
+# ISSM Configuration #
+#--------------------#
+
+# NOTE:
+# - We can disable dependency tracking in the Autotools because the binaries
+#	should always be a one-time build.
+#
+# TODO:
+# - Add static copy of libsqlite and make sure it is found during GMT configuration
+#
+
+ISSM_CONFIG='\
+	--prefix=${ISSM_DIR} \
+	--enable-standalone-executables \
+	--enable-standalone-modules \
+	--enable-standalone-libraries \
+	--disable-dependency-tracking \
+	--with-matlab-dir=${MATLAB_PATH} \
+	--with-python-version=3.9 \
+	--with-python-dir=/System/Volumes/Data/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9 \
+	--with-python-numpy-dir=/Library/Python/3.9/site-packages/numpy/core/include/numpy \
+	--with-fortran-lib="/usr/local/Cellar/gcc/12.2.0/lib/gcc/12/libgfortran.a /usr/local/Cellar/gcc/12.2.0/lib/gcc/12/libquadmath.a /usr/local/Cellar/gcc/12.2.0/lib/gcc/12/gcc/x86_64-apple-darwin21/12/libgcc.a" \
+	--with-mpi-include=${ISSM_DIR}/externalpackages/petsc/install/include \
+	--with-mpi-libflags="-L${ISSM_DIR}/externalpackages/petsc/install/lib -lmpi -lmpicxx -lmpifort" \
+	--with-blas-lapack-dir=${ISSM_DIR}/externalpackages/petsc/install \
+	--with-metis-dir=${ISSM_DIR}/externalpackages/petsc/install \
+	--with-parmetis-dir=${ISSM_DIR}/externalpackages/petsc/install \
+	--with-scalapack-dir=${ISSM_DIR}/externalpackages/petsc/install \
+	--with-mumps-dir=${ISSM_DIR}/externalpackages/petsc/install \
+	--with-hdf5-dir=${ISSM_DIR}/externalpackages/hdf5/install \
+	--with-petsc-dir=${ISSM_DIR}/externalpackages/petsc/install \
+	--with-gsl-dir=${ISSM_DIR}/externalpackages/gsl/install \
+	--with-boost-dir=${ISSM_DIR}/externalpackages/boost/install \
+	--with-dakota-dir=${ISSM_DIR}/externalpackages/dakota/install \
+	--with-chaco-dir=${ISSM_DIR}/externalpackages/chaco/install \
+	--with-proj-dir=${ISSM_DIR}/externalpackages/proj/install \
+	--with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \
+	--with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \
+	--with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \
+'
+
+#-------------------#
+# External Packages #
+#-------------------#
+
+EXTERNALPACKAGES="
+	autotools	install-mac.sh
+	cmake		install.sh
+	petsc		install-3.17-mac-silicon-static.sh
+	gsl			install-static.sh
+	boost		install-1.7-mac-static.sh
+	dakota		install-6.2-mac-static.sh
+	chaco		install-mac.sh
+	curl		install-7-mac-static.sh
+	hdf5		install-1-parallel-static.sh
+	netcdf		install-4.7-parallel-static.sh
+	proj		install-6-static.sh
+	gdal		install-3-static.sh
+	gshhg		install.sh
+	gmt			install-6-mac-static.sh
+	gmsh		install-4-mac-static.sh
+	triangle	install-mac-static.sh
+	m1qn3		install-mac-static.sh
+	semic		install.sh
+	shell2junit	install.sh
+"
+
+#---------#
+# Testing #
+#---------#
+
+# Test suites
+MATLAB_TEST=0
+PYTHON_TEST=0
+JAVASCRIPT_TEST=0
+EXAMPLES_TEST=0
+
+# Number of CPUs used in ISSM compilation
+#
+# NOTE: One is usually safer as some packages are very sensitive to parallel
+# 		compilation
+#
+NUMCPUS_INSTALL=4
+
+# Number of CPUs used in the nightly runs
+NUMCPUS_RUN=1
+
+# Nightly run options
+#
+# See documentation in test/NightlyRun/runme.* for more information.
+#
+PYTHON_NROPTIONS=""
+MATLAB_NROPTIONS=""
Index: /issm/trunk-jpl/jenkins/mac-silicon-binaries-python-3
===================================================================
--- /issm/trunk-jpl/jenkins/mac-silicon-binaries-python-3	(revision 28113)
+++ /issm/trunk-jpl/jenkins/mac-silicon-binaries-python-3	(revision 28113)
@@ -0,0 +1,94 @@
+#--------------------#
+# ISSM Configuration #
+#--------------------#
+
+# NOTE:
+# - We can disable dependency tracking in the Autotools because the binaries
+#	should always be a one-time build.
+#
+# TODO:
+# - Add static copy of libsqlite and make sure it is found during GMT configuration
+#
+
+ISSM_CONFIG='\
+	--prefix=${ISSM_DIR} \
+	--enable-standalone-executables \
+	--enable-standalone-modules \
+	--enable-standalone-libraries \
+	--disable-dependency-tracking \
+	--with-matlab-dir=${MATLAB_PATH} \
+	--with-python-version=3.9 \
+	--with-python-dir=/System/Volumes/Data/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9 \
+	--with-python-numpy-dir=/Library/Python/3.9/site-packages/numpy/core/include/numpy \
+	--with-fortran-lib="/usr/local/Cellar/gcc/12.2.0/lib/gcc/12/libgfortran.a /usr/local/Cellar/gcc/12.2.0/lib/gcc/12/libquadmath.a /usr/local/Cellar/gcc/12.2.0/lib/gcc/12/gcc/x86_64-apple-darwin21/12/libgcc.a" \
+	--with-mpi-include=${ISSM_DIR}/externalpackages/petsc/install/include \
+	--with-mpi-libflags="-L${ISSM_DIR}/externalpackages/petsc/install/lib -lmpi -lmpicxx -lmpifort" \
+	--with-blas-lapack-dir=${ISSM_DIR}/externalpackages/petsc/install \
+	--with-metis-dir=${ISSM_DIR}/externalpackages/petsc/install \
+	--with-parmetis-dir=${ISSM_DIR}/externalpackages/petsc/install \
+	--with-scalapack-dir=${ISSM_DIR}/externalpackages/petsc/install \
+	--with-mumps-dir=${ISSM_DIR}/externalpackages/petsc/install \
+	--with-hdf5-dir=${ISSM_DIR}/externalpackages/hdf5/install \
+	--with-petsc-dir=${ISSM_DIR}/externalpackages/petsc/install \
+	--with-gsl-dir=${ISSM_DIR}/externalpackages/gsl/install \
+	--with-boost-dir=${ISSM_DIR}/externalpackages/boost/install \
+	--with-dakota-dir=${ISSM_DIR}/externalpackages/dakota/install \
+	--with-chaco-dir=${ISSM_DIR}/externalpackages/chaco/install \
+	--with-proj-dir=${ISSM_DIR}/externalpackages/proj/install \
+	--with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \
+	--with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \
+	--with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \
+'
+
+#-------------------#
+# External Packages #
+#-------------------#
+
+EXTERNALPACKAGES="
+	autotools	install-mac.sh
+	cmake		install.sh
+	petsc		install-3.17-mac-silicon-static.sh
+	gsl			install-static.sh
+	boost		install-1.7-mac-static.sh
+	dakota		install-6.2-mac-static.sh
+	chaco		install-mac.sh
+	curl		install-7-mac-static.sh
+	hdf5		install-1-parallel-static.sh
+	netcdf		install-4.7-parallel-static.sh
+	proj		install-6-static.sh
+	gdal		install-3-python-static.sh
+	gshhg		install.sh
+	gmt			install-6-mac-static.sh
+	gmsh		install-4-mac-static.sh
+	triangle	install-mac-static.sh
+	m1qn3		install-mac-static.sh
+	semic		install.sh
+	shell2junit	install.sh
+"
+
+#---------#
+# Testing #
+#---------#
+
+# Test suites
+MATLAB_TEST=0
+PYTHON_TEST=0
+JAVASCRIPT_TEST=0
+EXAMPLES_TEST=0
+
+# Number of CPUs used in ISSM compilation
+#
+# NOTE: One is usually safer as some packages are very sensitive to parallel
+# 		compilation
+#
+NUMCPUS_INSTALL=8
+
+# Number of CPUs used in the nightly runs
+NUMCPUS_RUN=1
+
+# Nightly run options
+#
+# See documentation in test/NightlyRun/runme.* for more information.
+#
+PYTHON_NROPTIONS=""
+MATLAB_NROPTIONS=""
Index: /issm/trunk-jpl/packagers/mac/commit_for_signing-issm-mac-binaries.sh
===================================================================
--- /issm/trunk-jpl/packagers/mac/commit_for_signing-issm-mac-binaries.sh	(revision 28113)
+++ /issm/trunk-jpl/packagers/mac/commit_for_signing-issm-mac-binaries.sh	(revision 28113)
@@ -0,0 +1,249 @@
+#!/bin/bash
+
+################################################################################
+# Commits ISSM distributable package with for macOS running on to repository 
+# for signing. This repository is polled by a project running on a JPL 
+# Cybersecurity Jenkins server and performs the actual signing and 
+# notarization.
+#
+# NOTE: The following variables *must* be defined in order for this script to 
+# work properly,
+#
+#		COMPRESSED_PKG
+#		ISSM_BINARIES_REPO_PASS
+#		ISSM_BINARIES_REPO_USER
+#		SIGNED_REPO_COPY
+#		SIGNED_REPO_URL
+#		UNSIGNED_REPO_COPY
+#		UNSIGNED_REPO_URL
+#
+# Options:
+# -r/--resign			Skip ISSM compilation and packaging. Use to retrigger 
+#						signing/notarization if it fails but build and package 
+#						are valid.
+# -u/--unlock			Remove lock file from signed package repository. Use if 
+#						build is aborted to allow for subsequent fresh build.
+#
+# See also:
+# - packagers/mac/<ARCH>/complete-issm-mac-<ARCH>-binaries-<API>.sh
+#
+# TODO:
+# - Generalize checkout_*_repo_copy and validate_*_repo_copy functions (e.g. 
+#	pass 'signed' or 'unsigned' as argument)
+################################################################################
+
+# Expand aliases within the context of this script
+shopt -s expand_aliases
+
+# NOTE: For some reason, calling svn from within the context of this script 
+#		gives,
+#
+#			svn: command not found
+#
+#		even though it is installed via Homebrew and available at the following 
+#		path.
+#
+alias svn='/usr/local/bin/svn'
+
+## Override certain other aliases
+#
+alias cp=$(which cp)
+alias grep=$(which grep)
+
+## Constants
+#
+MAX_SIGNING_CHECK_ATTEMPTS=30
+NOTARIZATION_LOGFILE="notarization.log"
+RETRIGGER_SIGNING_FILE="retrigger.txt"
+SIGNING_CHECK_PERIOD=60 # in seconds
+SIGNING_LOCK_FILE="signing.lock"
+
+## Functions
+#
+checkout_signed_repo_copy(){
+	echo "Checking out copy of repository for signed packages"
+
+	# NOTE: Get empty copy because we do not want to have to check out package 
+	#		from previous signing.
+	#
+	svn checkout \
+		--trust-server-cert \
+		--non-interactive \
+		--depth empty \
+		--username ${ISSM_BINARIES_REPO_USER} \
+		--password ${ISSM_BINARIES_REPO_PASS} \
+		${SIGNED_REPO_URL} \
+		${SIGNED_REPO_COPY} > /dev/null 2>&1
+}
+checkout_unsigned_repo_copy(){
+	echo "Checking out copy of repository for unsigned packages"
+	svn checkout \
+		--trust-server-cert \
+		--non-interactive \
+		--username ${ISSM_BINARIES_REPO_USER} \
+		--password ${ISSM_BINARIES_REPO_PASS} \
+		${UNSIGNED_REPO_URL} \
+		${UNSIGNED_REPO_COPY} > /dev/null 2>&1
+}
+validate_signed_repo_copy(){
+	# Validate copy of repository for signed binaries (e.g. 
+	# 'Check-out Strategy' was set to 'Use 'svn update' as much as possible'; 
+	# initial checkout failed)
+	if [[ ! -d ${SIGNED_REPO_COPY} || ! -d ${SIGNED_REPO_COPY}/.svn ]]; then
+		rm -rf ${SIGNED_REPO_COPY}
+		checkout_signed_repo_copy
+	fi
+}
+validate_unsigned_repo_copy(){
+	# Validate copy of repository for unsigned binaries (e.g. 
+	# 'Check-out Strategy' was set to 'Use 'svn update' as much as possible'; 
+	# initial checkout failed)
+	if [[ ! -d ${UNSIGNED_REPO_COPY} || ! -d ${UNSIGNED_REPO_COPY}/.svn ]]; then
+		rm -rf ${UNSIGNED_REPO_COPY}
+		checkout_unsigned_repo_copy
+	fi
+}
+
+## Parse options
+#
+if [ $# -gt 1 ]; then
+	echo "Can use only one option at a time"
+	exit 1
+fi
+
+retrigger_signing=0
+unlock=0
+
+if [ $# -eq 1 ]; then
+	case $1 in
+		-r|--resign)	retrigger_signing=1;	;;
+		-u|--unlock)	unlock=1;				;;
+		*) echo "Unknown parameter passed: $1"; exit 1	;;
+	esac
+fi
+
+validate_signed_repo_copy
+
+if [ ${unlock} -eq 1 ]; then
+	# Remove signing lock file from signed package repository so that a new 
+	# build can run
+	echo "Removing lock file from repository for signed packages"
+	svn update \
+		--trust-server-cert \
+		--non-interactive \
+		--username ${ISSM_BINARIES_REPO_USER} \
+		--password ${ISSM_BINARIES_REPO_PASS} \
+		${SIGNED_REPO_COPY}/${SIGNING_LOCK_FILE} > /dev/null 2>&1
+	svn delete ${SIGNED_REPO_COPY}/${SIGNING_LOCK_FILE} > /dev/null 2>&1
+	svn commit \
+		--trust-server-cert \
+		--non-interactive \
+		--username ${ISSM_BINARIES_REPO_USER} \
+		--password ${ISSM_BINARIES_REPO_PASS} \
+		--message "DEL: Removing lock file after failed build" ${SIGNED_REPO_COPY} > /dev/null 2>&1
+	svn cleanup ${SIGNED_REPO_COPY} > /dev/null 2>&1
+
+	echo "Remove -u/--unlock option from configuration and run again"
+	exit 1
+fi
+
+# If lock file exists, a signing build is still in process by JPL Cybersecurity
+svn update \
+	--trust-server-cert \
+	--non-interactive \
+	--username ${ISSM_BINARIES_REPO_USER} \
+	--password ${ISSM_BINARIES_REPO_PASS} \
+	${SIGNED_REPO_COPY}/${SIGNING_LOCK_FILE} > /dev/null 2>&1
+
+if [ -f ${SIGNED_REPO_COPY}/${SIGNING_LOCK_FILE} ]; then
+	echo "Previous signing job still in process by JPL Cybersecurity. Please try again later."
+	exit 1
+fi
+
+# Commit lock file to repository for signed packages
+echo "Committing lock file to repository for signed packages"
+touch ${SIGNED_REPO_COPY}/${SIGNING_LOCK_FILE}
+svn add ${SIGNED_REPO_COPY}/${SIGNING_LOCK_FILE} > /dev/null 2>&1
+svn commit \
+	--trust-server-cert \
+	--non-interactive \
+	--username ${ISSM_BINARIES_REPO_USER} \
+	--password ${ISSM_BINARIES_REPO_PASS} \
+	--message "ADD: New lock file" ${SIGNED_REPO_COPY} > /dev/null 2>&1
+
+# Check out copy of repository for unsigned packages
+validate_unsigned_repo_copy
+
+if [ ${retrigger_signing} -eq 0 ]; then
+	# Commit new compressed package to repository for unsigned binaries
+	echo "Committing package to repository for unsigned packages"
+	cp ${COMPRESSED_PKG} ${UNSIGNED_REPO_COPY}
+	svn add ${UNSIGNED_REPO_COPY}/${COMPRESSED_PKG} > /dev/null 2>&1
+	svn commit \
+		--trust-server-cert \
+		--non-interactive \
+		--username ${ISSM_BINARIES_REPO_USER} \
+		--password ${ISSM_BINARIES_REPO_PASS} \
+		--message "CHG: New unsigned package" ${UNSIGNED_REPO_COPY} > /dev/null 2>&1
+else
+	# NOTE: If notarize_only == 1, we commit a dummy file as we do not want to 
+	#		have to commit the entire compressed package again simply to 
+	#		retrigger the signing build on the remote JPL Cybersecurity Jenkins 
+	#		server.
+	#
+	echo "Attempting to sign existing package again"
+	echo $(date +'%Y-%m-%d-%H-%M-%S') > ${UNSIGNED_REPO_COPY}/${RETRIGGER_SIGNING_FILE} # Write datetime stamp to file to ensure modification is made
+	svn add ${UNSIGNED_REPO_COPY}/${RETRIGGER_SIGNING_FILE} > /dev/null 2>&1
+	svn commit \
+		--trust-server-cert \
+		--non-interactive \
+		--username ${ISSM_BINARIES_REPO_USER} \
+		--password ${ISSM_BINARIES_REPO_PASS} \
+		--message "ADD: Retriggering signing with same package (previous attempt failed)" ${UNSIGNED_REPO_COPY} > /dev/null 2>&1
+fi
+
+# Check status of signing
+echo "Checking progress of signing..."
+SIGNING_CHECK_ATTEMPT=0
+while [ ${SIGNING_CHECK_ATTEMPT} -lt ${MAX_SIGNING_CHECK_ATTEMPTS} ]; do
+	echo "...in progress still; checking again in ${SIGNING_CHECK_PERIOD} seconds"
+	sleep ${SIGNING_CHECK_PERIOD}
+	svn update \
+		--trust-server-cert \
+		--non-interactive \
+		--username ${ISSM_BINARIES_REPO_USER} \
+		--password ${ISSM_BINARIES_REPO_PASS} \
+		${SIGNED_REPO_COPY} > /dev/null 2>&1
+
+	if [ ! -f ${SIGNED_REPO_COPY}/${SIGNING_LOCK_FILE} ]; then
+		# Retrieve notarization lock file
+		svn update \
+			--trust-server-cert \
+			--non-interactive \
+			--username ${ISSM_BINARIES_REPO_USER} \
+			--password ${ISSM_BINARIES_REPO_PASS} \
+			${SIGNED_REPO_COPY}/${NOTARIZATION_LOGFILE}
+
+		# Check status
+		STATUS=$(grep '"status": "Accepted"' ${SIGNED_REPO_COPY}/${NOTARIZATION_LOGFILE} | wc -l)
+
+		if [[ ${STATUS} -gt 0 ]]; then
+			echo "Notarization successful!"
+			break
+		else
+			echo "Notarization failed!"
+			echo "----------------------- Contents of notarization logfile -----------------------"
+			cat ${SIGNED_REPO_COPY}/${NOTARIZATION_LOGFILE}
+			echo "--------------------------------------------------------------------------------"
+
+			exit 1
+		fi
+	else
+		((++SIGNING_CHECK_ATTEMPT))
+	fi
+done
+
+if [ ! -f ${SIGNED_REPO_COPY}/${NOTARIZATION_LOGFILE} ]; then
+	echo "Signing timed out!"
+	exit 1
+fi
Index: /issm/trunk-jpl/packagers/mac/complete-issm-mac-intel-binaries-matlab.sh
===================================================================
--- /issm/trunk-jpl/packagers/mac/complete-issm-mac-intel-binaries-matlab.sh	(revision 28113)
+++ /issm/trunk-jpl/packagers/mac/complete-issm-mac-intel-binaries-matlab.sh	(revision 28113)
@@ -0,0 +1,160 @@
+#!/bin/bash
+
+################################################################################
+# Wrapper script to build, package, send for signing, and transfer to ISSM 
+# website ISSM distributable package with MATLAB API for macOS running on 
+# Intel.
+#
+# Normally, we would put this directly into the project configuration under 
+# 'Build' -> 'Execute shell', but because it is a bit more involved, it is a 
+# good idea to version it.
+#
+# When no failures/errors occur, performs the following:
+# - Builds ISSM according to configuration.
+# - Packages executables and libraries.
+# - Runs test suite against package.
+# - Commits compressed package to repository to be signed by JPL Cybersecurity.
+# - Retrieves signed package and transmits it to ISSM Web site for 
+#	distribution.
+#
+# Options:
+# -b/--skipbuild		Skip ISSM compilation.
+# -r/--resign			Skip ISSM compilation and packaging. Use to retrigger 
+#						signing/notarization if it fails but build and package 
+#						are valid.
+# -s/--skiptests		Skip ISSM compilation and testing during packaging 
+#						step. Use if packaging fails for some reason but build 
+#						is valid.
+# -t/--transferonly		Transfer package to ISSM Web site only. Use if transfer 
+#						fails for some reason to skip building, packaging, and 
+#						signing.
+# -u/--unlock			Remove lock file from signed package repository. Use if 
+#						build is aborted to allow for subsequent fresh build.
+#
+# Debugging:
+# - Relies on a very tight handshake with project on remote JPL Cybersecurity 
+#	Jenkins server. Debugging may be performed locally by running,
+#
+#		packagers/mac/sign-issm-mac-binaries.sh
+#
+#	with "AD_IDENTITY", "AD_USERNAME", and "ASC_PROVIDER" hardcoded to Apple 
+#	Developer credentials (make sure to also set keychain password in 
+#	"ALTOOL_PASSWORD") and "PKG" and "VARIANT_REPO_SUBPATH" properly set for 
+#	the package signing to be tested (should match constants "PKG" and 
+#	"REPO_BASE_URL" defined in this script).
+# - Removing stdout/stderr redirections to null device (> /dev/null 2>&1) can 
+#	help debug potential SVN issues.
+#
+# NOTE:
+# - Use only *one* of the above options at a time, and make sure it is removed 
+#	again after a single run.
+# - Builds will fail when any of the above options are used on a clean 
+#	workspace. For example, if 'Source Code Management' -> 'Check-out Strategy' 
+#	select menu is set to "Always check out a fresh copy".
+# - Assumes that "ISSM_BINARIES_USER" and "ISSM_BINARIES_PASS" are set up in 
+#	the 'Bindings' section under a 'Username and password (separated)' binding 
+#	(requires 'Credentials Binding Plugin') with 'Credentials' select menu set 
+#	to "jenkins/****** (SVN repository for ISSM binaries)".
+#
+# TODO:
+# - Generalize these wrapper scripts even further by defining only constants in 
+# config file (the rest of the script is identical).
+################################################################################
+
+## Constants
+#
+PKG="ISSM-macOS-Intel-MATLAB" # Name of directory to copy distributable files to
+REPO_BASE_URL="https://issm.ess.uci.edu/svn/issm-binaries/mac/intel/matlab"
+SIGNED_REPO_COPY="./signed"
+SIGNED_REPO_URL="${REPO_BASE_URL}/signed"
+UNSIGNED_REPO_COPY="./unsigned"
+UNSIGNED_REPO_URL="${REPO_BASE_URL}/unsigned"
+
+COMPRESSED_PKG="${PKG}.zip"
+
+## Environment
+#
+export COMPRESSED_PKG
+export PKG
+export SIGNED_REPO_COPY
+export SIGNED_REPO_URL
+export UNSIGNED_REPO_COPY
+export UNSIGNED_REPO_URL
+
+## Parse options
+#
+if [ $# -gt 1 ]; then
+	echo "Can use only one option at a time"
+	exit 1
+fi
+
+# NOTE: We could do this with binary switching (i.e. 0011 to sign and transfer, 
+#		but the following is self-documenting).
+#
+build=1
+package=1
+sign=1
+transfer=1
+
+if [ $# -eq 1 ]; then
+	case $1 in
+		-b|--skipbuild)		build=0;							shift	;;
+		-r|--resign)		build=0;	package=0;						;;
+		-s|--skiptests)		build=0;									;;
+		-t|--transferonly)	build=0;	package=0;	sign=0;				;;
+		-u|--unlock)		build=0;	package=0;	transfer=0;			;;
+		*) echo "Unknown parameter passed: $1"; exit 1 					;;
+	esac
+fi
+
+# Build
+if [ ${build} -eq 1 ]; then
+	./jenkins/jenkins.sh ./jenkins/mac-intel-binaries-matlab
+
+	if [ $? -ne 0 ]; then
+		echo "Failure while compiling"
+		exit 1
+	fi
+fi
+
+# Package
+if [ ${package} -eq 1 ]; then
+	./packagers/mac/intel/package-issm-mac-binaries-matlab.sh $1
+
+	if [ $? -ne 0 ]; then
+		echo "Failure during packaging"
+		exit 1
+	fi
+
+	shift # Clear $1 so that it is not passed to commit_for_signing script
+fi
+
+# Commit for signing
+if [ ${sign} -eq 1 ]; then
+	./packagers/mac/intel/commit_for_signing-issm-mac-binaries.sh $1
+
+	if [ $? -ne 0 ]; then
+		echo "Failure while committing package for signing"
+		exit 1
+	fi
+fi
+
+# NOTE: Because Mac build nodes are no longer directly connected to UCI 
+#		network and because remote access requires a VPN connection, we can 
+#		no longer transfer signed distributables via SSH. For now, there is 
+#		a cron job running every five minutes under user jenkins on 
+#		ross.ics.uci.edu that runs 
+#		/home/jenkins/bin/update-issm-mac-binaries.sh, which checks for 
+#		updated, signed distributables in the ISSM Binaries SVN repository
+#		and if they are available, copies them to the public directory.
+#
+
+# # Transfer distributable package to ISSM Web site
+# if [ ${transfer} -eq 1 ]; then
+# 	./packagers/mac/transfer-issm-mac-binaries.sh
+
+# 	if [ $? -ne 0 ]; then 
+# 		exit 1
+# 	fi
+# fi
+
Index: /issm/trunk-jpl/packagers/mac/complete-issm-mac-intel-binaries-python-3.sh
===================================================================
--- /issm/trunk-jpl/packagers/mac/complete-issm-mac-intel-binaries-python-3.sh	(revision 28113)
+++ /issm/trunk-jpl/packagers/mac/complete-issm-mac-intel-binaries-python-3.sh	(revision 28113)
@@ -0,0 +1,157 @@
+#!/bin/bash
+
+################################################################################
+# Wrapper script to build, package, send for signing, and transfer to ISSM 
+# website ISSM distributable package with Python 3 API for macOS running on 
+# Intel.
+#
+# Normally, we would put this directly into the project configuration under 
+# 'Build' -> 'Execute shell', but because it is a bit more involved, it is a 
+# good idea to version it.
+#
+# When no failures/errors occur, performs the following:
+# - Builds ISSM according to configuration.
+# - Packages executables and libraries.
+# - Runs test suite against package.
+# - Commits compressed package to repository to be signed by JPL Cybersecurity.
+# - Retrieves signed package and transmits it to ISSM Web site for 
+#	distribution.
+#
+# Options:
+# -b/--skipbuild		Skip ISSM compilation.
+# -r/--resign			Skip ISSM compilation and packaging. Use to retrigger 
+#						signing/notarization if it fails but build and package 
+#						are valid.
+# -s/--skiptests		Skip ISSM compilation and testing during packaging 
+#						step. Use if packaging fails for some reason but build 
+#						is valid.
+# -t/--transferonly		Transfer package to ISSM Web site only. Use if transfer 
+#						fails for some reason to skip building, packaging, and 
+#						signing.
+# -u/--unlock			Remove lock file from signed package repository. Use if 
+#						build is aborted to allow for subsequent fresh build.
+#
+# Debugging:
+# - Relies on a very tight handshake with project on remote JPL Cybersecurity 
+#	Jenkins server. Debugging may be performed locally by running,
+#
+#		packagers/mac/sign-issm-mac-binaries.sh
+#
+#	with "AD_IDENTITY", "AD_USERNAME", and "ASC_PROVIDER" hardcoded to Apple 
+#	Developer credentials (make sure to also set keychain password in 
+#	"ALTOOL_PASSWORD") and "PKG" and "VARIANT_REPO_SUBPATH" properly set for 
+#	the package signing to be tested (should match constants "PKG" and 
+#	"REPO_BASE_URL" defined in this script).
+# - Removing stdout/stderr redirections to null device (> /dev/null 2>&1) can 
+#	help debug potential SVN issues.
+#
+# NOTE:
+# - Use only *one* of the above options at a time, and make sure it is removed 
+#	again after a single run.
+# - Builds will fail when any of the above options are used on a clean 
+#	workspace. For example, if 'Source Code Management' -> 'Check-out Strategy' 
+#	select menu is set to "Always check out a fresh copy".
+# - Assumes that "ISSM_BINARIES_USER" and "ISSM_BINARIES_PASS" are set up in 
+#	the 'Bindings' section under a 'Username and password (separated)' binding 
+#	(requires 'Credentials Binding Plugin') with 'Credentials' select menu set 
+#	to "jenkins/****** (SVN repository for ISSM binaries)".
+#
+# TODO:
+# - Generalize these wrapper scripts even further by defining only constants in 
+# config file (the rest of the script is identical).
+################################################################################
+
+## Constants
+#
+PKG="ISSM-macOS-Intel-Python-3" # Name of directory to copy distributable files to
+REPO_BASE_URL="https://issm.ess.uci.edu/svn/issm-binaries/mac/intel/python/3"
+SIGNED_REPO_COPY="./signed"
+SIGNED_REPO_URL="${REPO_BASE_URL}/signed"
+UNSIGNED_REPO_COPY="./unsigned"
+UNSIGNED_REPO_URL="${REPO_BASE_URL}/unsigned"
+
+COMPRESSED_PKG="${PKG}.zip"
+
+## Environment
+#
+export COMPRESSED_PKG
+export PKG
+export SIGNED_REPO_COPY
+export SIGNED_REPO_URL
+export UNSIGNED_REPO_COPY
+export UNSIGNED_REPO_URL
+
+## Parse options
+#
+if [ $# -gt 1 ]; then
+	echo "Can use only one option at a time"
+	exit 1
+fi
+
+# NOTE: We could do this with binary switching (i.e. 0011 to sign and transfer, 
+#		but the following is self-documenting).
+#
+build=1
+package=1
+sign=1
+transfer=1
+
+if [ $# -eq 1 ]; then
+	case $1 in
+		-b|--skipbuild)		build=0;							shift	;;
+		-r|--resign)		build=0;	package=0;						;;
+		-s|--skiptests)		build=0;									;;
+		-t|--transferonly)	build=0;	package=0;	sign=0;				;;
+		-u|--unlock)		build=0;	package=0;	transfer=0;			;;
+		*) echo "Unknown parameter passed: $1"; exit 1 					;;
+	esac
+fi
+
+# Build
+if [ ${build} -eq 1 ]; then
+	./jenkins/jenkins.sh ./jenkins/mac-intel-binaries-python-3
+
+	if [ $? -ne 0 ]; then 
+		exit 1
+	fi
+fi
+
+# Package
+if [ ${package} -eq 1 ]; then
+	./packagers/mac/package-issm-mac-binaries-python-3.sh $1
+
+	if [ $? -ne 0 ]; then 
+		exit 1
+	fi
+
+	shift # Clear $1 so that it is not passed to commit_for_signing script
+fi
+
+# Commit for signing
+if [ ${sign} -eq 1 ]; then
+	./packagers/mac/commit_for_signing-issm-mac-binaries.sh $1
+
+	if [ $? -ne 0 ]; then 
+		exit 1
+	fi
+fi
+
+# NOTE: Because Mac build nodes are no longer directly connected to UCI 
+#		network and because remote access requires a VPN connection, we can 
+#		no longer transfer signed distributables via SSH. For now, there is 
+#		a cron job running every five minutes under user jenkins on 
+#		ross.ics.uci.edu that runs 
+#		/home/jenkins/bin/update-issm-mac-binaries.sh, which checks for 
+#		updated, signed distributables in the ISSM Binaries SVN repository
+#		and if they are available, copies them to the public directory.
+#
+
+# # Transfer distributable package to ISSM Web site
+# if [ ${transfer} -eq 1 ]; then
+# 	./packagers/mac/transfer-issm-mac-binaries.sh
+
+# 	if [ $? -ne 0 ]; then 
+# 		exit 1
+# 	fi
+# fi
+
Index: /issm/trunk-jpl/packagers/mac/complete-issm-mac-silicon-binaries-matlab.sh
===================================================================
--- /issm/trunk-jpl/packagers/mac/complete-issm-mac-silicon-binaries-matlab.sh	(revision 28113)
+++ /issm/trunk-jpl/packagers/mac/complete-issm-mac-silicon-binaries-matlab.sh	(revision 28113)
@@ -0,0 +1,160 @@
+#!/bin/bash
+
+################################################################################
+# Wrapper script to build, package, send for signing, and transfer to ISSM 
+# website ISSM distributable package with MATLAB API for macOS running on 
+# Intel.
+#
+# Normally, we would put this directly into the project configuration under 
+# 'Build' -> 'Execute shell', but because it is a bit more involved, it is a 
+# good idea to version it.
+#
+# When no failures/errors occur, performs the following:
+# - Builds ISSM according to configuration.
+# - Packages executables and libraries.
+# - Runs test suite against package.
+# - Commits compressed package to repository to be signed by JPL Cybersecurity.
+# - Retrieves signed package and transmits it to ISSM Web site for 
+#	distribution.
+#
+# Options:
+# -b/--skipbuild		Skip ISSM compilation.
+# -r/--resign			Skip ISSM compilation and packaging. Use to retrigger 
+#						signing/notarization if it fails but build and package 
+#						are valid.
+# -s/--skiptests		Skip ISSM compilation and testing during packaging 
+#						step. Use if packaging fails for some reason but build 
+#						is valid.
+# -t/--transferonly		Transfer package to ISSM Web site only. Use if transfer 
+#						fails for some reason to skip building, packaging, and 
+#						signing.
+# -u/--unlock			Remove lock file from signed package repository. Use if 
+#						build is aborted to allow for subsequent fresh build.
+#
+# Debugging:
+# - Relies on a very tight handshake with project on remote JPL Cybersecurity 
+#	Jenkins server. Debugging may be performed locally by running,
+#
+#		packagers/mac/sign-issm-mac-binaries.sh
+#
+#	with "AD_IDENTITY", "AD_USERNAME", and "ASC_PROVIDER" hardcoded to Apple 
+#	Developer credentials (make sure to also set keychain password in 
+#	"ALTOOL_PASSWORD") and "PKG" and "VARIANT_REPO_SUBPATH" properly set for 
+#	the package signing to be tested (should match constants "PKG" and 
+#	"REPO_BASE_URL" defined in this script).
+# - Removing stdout/stderr redirections to null device (> /dev/null 2>&1) can 
+#	help debug potential SVN issues.
+#
+# NOTE:
+# - Use only *one* of the above options at a time, and make sure it is removed 
+#	again after a single run.
+# - Builds will fail when any of the above options are used on a clean 
+#	workspace. For example, if 'Source Code Management' -> 'Check-out Strategy' 
+#	select menu is set to "Always check out a fresh copy".
+# - Assumes that "ISSM_BINARIES_USER" and "ISSM_BINARIES_PASS" are set up in 
+#	the 'Bindings' section under a 'Username and password (separated)' binding 
+#	(requires 'Credentials Binding Plugin') with 'Credentials' select menu set 
+#	to "jenkins/****** (SVN repository for ISSM binaries)".
+#
+# TODO:
+# - Generalize these wrapper scripts even further by defining only constants in 
+# config file (the rest of the script is identical).
+################################################################################
+
+## Constants
+#
+PKG="ISSM-macOS-Intel-MATLAB" # Name of directory to copy distributable files to
+REPO_BASE_URL="https://issm.ess.uci.edu/svn/issm-binaries/mac/intel/matlab"
+SIGNED_REPO_COPY="./signed"
+SIGNED_REPO_URL="${REPO_BASE_URL}/signed"
+UNSIGNED_REPO_COPY="./unsigned"
+UNSIGNED_REPO_URL="${REPO_BASE_URL}/unsigned"
+
+COMPRESSED_PKG="${PKG}.zip"
+
+## Environment
+#
+export COMPRESSED_PKG
+export PKG
+export SIGNED_REPO_COPY
+export SIGNED_REPO_URL
+export UNSIGNED_REPO_COPY
+export UNSIGNED_REPO_URL
+
+## Parse options
+#
+if [ $# -gt 1 ]; then
+	echo "Can use only one option at a time"
+	exit 1
+fi
+
+# NOTE: We could do this with binary switching (i.e. 0011 to sign and transfer, 
+#		but the following is self-documenting).
+#
+build=1
+package=1
+sign=1
+transfer=1
+
+if [ $# -eq 1 ]; then
+	case $1 in
+		-b|--skipbuild)		build=0;							shift	;;
+		-r|--resign)		build=0;	package=0;						;;
+		-s|--skiptests)		build=0;									;;
+		-t|--transferonly)	build=0;	package=0;	sign=0;				;;
+		-u|--unlock)		build=0;	package=0;	transfer=0;			;;
+		*) echo "Unknown parameter passed: $1"; exit 1 					;;
+	esac
+fi
+
+# Build
+if [ ${build} -eq 1 ]; then
+	./jenkins/jenkins.sh ./jenkins/mac-intel-binaries-matlab
+
+	if [ $? -ne 0 ]; then
+		echo "Failure while compiling"
+		exit 1
+	fi
+fi
+
+# Package
+if [ ${package} -eq 1 ]; then
+	./packagers/mac/intel/package-issm-mac-binaries-matlab.sh $1
+
+	if [ $? -ne 0 ]; then
+		echo "Failure during packaging"
+		exit 1
+	fi
+
+	shift # Clear $1 so that it is not passed to commit_for_signing script
+fi
+
+# Commit for signing
+if [ ${sign} -eq 1 ]; then
+	./packagers/mac/intel/commit_for_signing-issm-mac-binaries.sh $1
+
+	if [ $? -ne 0 ]; then
+		echo "Failure while committing package for signing"
+		exit 1
+	fi
+fi
+
+# NOTE: Because Mac build nodes are no longer directly connected to UCI 
+#		network and because remote access requires a VPN connection, we can 
+#		no longer transfer signed distributables via SSH. For now, there is 
+#		a cron job running every five minutes under user jenkins on 
+#		ross.ics.uci.edu that runs 
+#		/home/jenkins/bin/update-issm-mac-binaries.sh, which checks for 
+#		updated, signed distributables in the ISSM Binaries SVN repository
+#		and if they are available, copies them to the public directory.
+#
+
+# # Transfer distributable package to ISSM Web site
+# if [ ${transfer} -eq 1 ]; then
+# 	./packagers/mac/transfer-issm-mac-binaries.sh
+
+# 	if [ $? -ne 0 ]; then 
+# 		exit 1
+# 	fi
+# fi
+
Index: /issm/trunk-jpl/packagers/mac/complete-issm-mac-silicon-binaries-python-3.sh
===================================================================
--- /issm/trunk-jpl/packagers/mac/complete-issm-mac-silicon-binaries-python-3.sh	(revision 28113)
+++ /issm/trunk-jpl/packagers/mac/complete-issm-mac-silicon-binaries-python-3.sh	(revision 28113)
@@ -0,0 +1,157 @@
+#!/bin/bash
+
+################################################################################
+# Wrapper script to build, package, send for signing, and transfer to ISSM 
+# website ISSM distributable package with Python 3 API for macOS running on 
+# Intel.
+#
+# Normally, we would put this directly into the project configuration under 
+# 'Build' -> 'Execute shell', but because it is a bit more involved, it is a 
+# good idea to version it.
+#
+# When no failures/errors occur, performs the following:
+# - Builds ISSM according to configuration.
+# - Packages executables and libraries.
+# - Runs test suite against package.
+# - Commits compressed package to repository to be signed by JPL Cybersecurity.
+# - Retrieves signed package and transmits it to ISSM Web site for 
+#	distribution.
+#
+# Options:
+# -b/--skipbuild		Skip ISSM compilation.
+# -r/--resign			Skip ISSM compilation and packaging. Use to retrigger 
+#						signing/notarization if it fails but build and package 
+#						are valid.
+# -s/--skiptests		Skip ISSM compilation and testing during packaging 
+#						step. Use if packaging fails for some reason but build 
+#						is valid.
+# -t/--transferonly		Transfer package to ISSM Web site only. Use if transfer 
+#						fails for some reason to skip building, packaging, and 
+#						signing.
+# -u/--unlock			Remove lock file from signed package repository. Use if 
+#						build is aborted to allow for subsequent fresh build.
+#
+# Debugging:
+# - Relies on a very tight handshake with project on remote JPL Cybersecurity 
+#	Jenkins server. Debugging may be performed locally by running,
+#
+#		packagers/mac/sign-issm-mac-binaries.sh
+#
+#	with "AD_IDENTITY", "AD_USERNAME", and "ASC_PROVIDER" hardcoded to Apple 
+#	Developer credentials (make sure to also set keychain password in 
+#	"ALTOOL_PASSWORD") and "PKG" and "VARIANT_REPO_SUBPATH" properly set for 
+#	the package signing to be tested (should match constants "PKG" and 
+#	"REPO_BASE_URL" defined in this script).
+# - Removing stdout/stderr redirections to null device (> /dev/null 2>&1) can 
+#	help debug potential SVN issues.
+#
+# NOTE:
+# - Use only *one* of the above options at a time, and make sure it is removed 
+#	again after a single run.
+# - Builds will fail when any of the above options are used on a clean 
+#	workspace. For example, if 'Source Code Management' -> 'Check-out Strategy' 
+#	select menu is set to "Always check out a fresh copy".
+# - Assumes that "ISSM_BINARIES_USER" and "ISSM_BINARIES_PASS" are set up in 
+#	the 'Bindings' section under a 'Username and password (separated)' binding 
+#	(requires 'Credentials Binding Plugin') with 'Credentials' select menu set 
+#	to "jenkins/****** (SVN repository for ISSM binaries)".
+#
+# TODO:
+# - Generalize these wrapper scripts even further by defining only constants in 
+# config file (the rest of the script is identical).
+################################################################################
+
+## Constants
+#
+PKG="ISSM-macOS-Intel-Python-3" # Name of directory to copy distributable files to
+REPO_BASE_URL="https://issm.ess.uci.edu/svn/issm-binaries/mac/intel/python/3"
+SIGNED_REPO_COPY="./signed"
+SIGNED_REPO_URL="${REPO_BASE_URL}/signed"
+UNSIGNED_REPO_COPY="./unsigned"
+UNSIGNED_REPO_URL="${REPO_BASE_URL}/unsigned"
+
+COMPRESSED_PKG="${PKG}.zip"
+
+## Environment
+#
+export COMPRESSED_PKG
+export PKG
+export SIGNED_REPO_COPY
+export SIGNED_REPO_URL
+export UNSIGNED_REPO_COPY
+export UNSIGNED_REPO_URL
+
+## Parse options
+#
+if [ $# -gt 1 ]; then
+	echo "Can use only one option at a time"
+	exit 1
+fi
+
+# NOTE: We could do this with binary switching (i.e. 0011 to sign and transfer, 
+#		but the following is self-documenting).
+#
+build=1
+package=1
+sign=1
+transfer=1
+
+if [ $# -eq 1 ]; then
+	case $1 in
+		-b|--skipbuild)		build=0;							shift	;;
+		-r|--resign)		build=0;	package=0;						;;
+		-s|--skiptests)		build=0;									;;
+		-t|--transferonly)	build=0;	package=0;	sign=0;				;;
+		-u|--unlock)		build=0;	package=0;	transfer=0;			;;
+		*) echo "Unknown parameter passed: $1"; exit 1 					;;
+	esac
+fi
+
+# Build
+if [ ${build} -eq 1 ]; then
+	./jenkins/jenkins.sh ./jenkins/mac-intel-binaries-python-3
+
+	if [ $? -ne 0 ]; then 
+		exit 1
+	fi
+fi
+
+# Package
+if [ ${package} -eq 1 ]; then
+	./packagers/mac/package-issm-mac-binaries-python-3.sh $1
+
+	if [ $? -ne 0 ]; then 
+		exit 1
+	fi
+
+	shift # Clear $1 so that it is not passed to commit_for_signing script
+fi
+
+# Commit for signing
+if [ ${sign} -eq 1 ]; then
+	./packagers/mac/commit_for_signing-issm-mac-binaries.sh $1
+
+	if [ $? -ne 0 ]; then 
+		exit 1
+	fi
+fi
+
+# NOTE: Because Mac build nodes are no longer directly connected to UCI 
+#		network and because remote access requires a VPN connection, we can 
+#		no longer transfer signed distributables via SSH. For now, there is 
+#		a cron job running every five minutes under user jenkins on 
+#		ross.ics.uci.edu that runs 
+#		/home/jenkins/bin/update-issm-mac-binaries.sh, which checks for 
+#		updated, signed distributables in the ISSM Binaries SVN repository
+#		and if they are available, copies them to the public directory.
+#
+
+# # Transfer distributable package to ISSM Web site
+# if [ ${transfer} -eq 1 ]; then
+# 	./packagers/mac/transfer-issm-mac-binaries.sh
+
+# 	if [ $? -ne 0 ]; then 
+# 		exit 1
+# 	fi
+# fi
+
Index: /issm/trunk-jpl/packagers/mac/package-issm-mac-binaries-matlab.sh
===================================================================
--- /issm/trunk-jpl/packagers/mac/package-issm-mac-binaries-matlab.sh	(revision 28113)
+++ /issm/trunk-jpl/packagers/mac/package-issm-mac-binaries-matlab.sh	(revision 28113)
@@ -0,0 +1,191 @@
+#!/bin/bash
+
+################################################################################
+# Packages and tests ISSM distributable package with MATLAB API for macOS.
+#
+# Options:
+# -s/--skiptests		Skip testing during packaging Use if packaging fails 
+#						for some reason but build is valid.
+#
+# NOTE: The following variables *must* be defined in order for this script to 
+# work properly,
+#
+#		COMPRESSED_PKG
+#		ISSM_DIR
+#		PKG
+#
+# See also:
+# - packagers/mac/<ARCH>/complete-issm-mac-<ARCH>-binaries-<API>.sh
+################################################################################
+
+# Expand aliases within the context of this script
+shopt -s expand_aliases
+
+# NOTE: For some reason, calling svn from within the context of this script 
+#		gives,
+#
+#			svn: command not found
+#
+#		even though it is installed via Homebrew and available at the following 
+#		path.
+#
+alias svn='/usr/local/bin/svn'
+
+## Override certain other aliases
+#
+alias cp=$(which cp)
+alias grep=$(which grep)
+
+## Constants
+#
+MATLAB_NROPTIONS="'benchmark','all','exclude',[125,126,129,234,235,418,420,435,444,445,701,702,703,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1201,1202,1203,1204,1205,1206,1207,1208,1301,1302,1303,1304,1401,1402,1601,1602,2002,2003,2004,2006,2007,2008,2010,2011,2012,2013,2020,2021,2051,2052,2053,2084,2085,2090,2091,2092,2101,2424,2425,3001:3300,3480,3481,4001:4100]" # NOTE: Combination of test suites from basic, Dakota, and Solid Earth builds, with tests that require a restart and those that require the JVM excluded
+MATLAB_PATH="/Applications/MATLAB_R2023b.app"
+
+## Environment
+#
+export PATH="${ISSM_DIR}/bin:$(getconf PATH)" # Ensure that we pick up binaries from 'bin' directory rather than 'externalpackages'; used when running tests
+
+## Parse options
+#
+if [ $# -gt 1 ]; then
+	echo "Can use only one option at a time"
+	exit 1
+fi
+
+skip_tests=0
+
+if [ $# -eq 1 ]; then
+	case $1 in
+		-s|--skiptests)	skip_tests=1;					;;
+		*) echo "Unknown parameter passed: $1"; exit 1	;;
+	esac
+fi
+
+# Check if MATLAB exists
+if ! [ -d ${MATLAB_PATH} ]; then
+	echo "${MATLAB_PATH} does not point to a MATLAB installation! Please modify MATLAB_PATH variable in $(basename $0) and try again."
+	exit 1
+fi
+
+# Clean up from previous packaging
+echo "Cleaning up existing assets"
+cd ${ISSM_DIR}
+rm -rf ${PKG} ${COMPRESSED_PKG}
+mkdir ${PKG}
+
+# Add required binaries and libraries to package and modify them where needed
+cd ${ISSM_DIR}/bin
+
+echo "Modify generic"
+cat generic_static.m | sed -e "s/generic_static/generic/g" > generic.m
+
+echo "Moving MPICH binaries to bin/"
+if [ -f ${ISSM_DIR}/externalpackages/petsc/install/bin/mpiexec ]; then
+	cp ${ISSM_DIR}/externalpackages/petsc/install/bin/mpiexec .
+	cp ${ISSM_DIR}/externalpackages/petsc/install/bin/hydra_pmi_proxy .
+elif [ -f ${ISSM_DIR}/externalpackages/mpich/install/bin/mpiexec ]; then
+	cp ${ISSM_DIR}/externalpackages/mpich/install/bin/mpiexec .
+	cp ${ISSM_DIR}/externalpackages/mpich/install/bin/hydra_pmi_proxy .
+else
+	echo "MPICH not found"
+	exit 1
+fi
+
+echo "Moving GDAL binaries to bin/"
+if [ -f ${ISSM_DIR}/externalpackages/gdal/install/bin/gdal-config ]; then
+	cp ${ISSM_DIR}/externalpackages/gdal/install/bin/gdalsrsinfo .
+	cp ${ISSM_DIR}/externalpackages/gdal/install/bin/gdaltransform .
+else
+	echo "GDAL not found"
+	exit 1
+fi
+
+echo "Moving Gmsh binaries to bin/"
+if [ -f ${ISSM_DIR}/externalpackages/gmsh/install/bin/gmsh ]; then
+	cp ${ISSM_DIR}/externalpackages/gmsh/install/bin/gmsh .
+else
+	echo "Gmsh not found"
+	exit 1
+fi
+
+echo "Moving GMT binaries to bin/"
+if [ -f ${ISSM_DIR}/externalpackages/gmt/install/bin/gmt-config ]; then
+	cp ${ISSM_DIR}/externalpackages/gmt/install/bin/gmt .
+	cp ${ISSM_DIR}/externalpackages/gmt/install/bin/gmtselect .
+else
+	echo "GMT not found"
+	exit 1
+fi
+
+echo "Moving GSHHG assets to share/"
+if [ -d ${ISSM_DIR}/externalpackages/gmt/install/share/coast ]; then
+	mkdir ${ISSM_DIR}/share 2> /dev/null
+	cp -R ${ISSM_DIR}/externalpackages/gmt/install/share/coast ${ISSM_DIR}/share
+else
+	echo "GSHHG not found"
+	exit 1
+fi
+
+echo "Moving PROJ assets to share/"
+if [ -d ${ISSM_DIR}/externalpackages/proj/install/share/proj ]; then
+	mkdir ${ISSM_DIR}/share 2> /dev/null
+	cp -R ${ISSM_DIR}/externalpackages/proj/install/share/proj ${ISSM_DIR}/share
+else
+	echo "PROJ not found"
+	exit 1
+fi
+
+# Run tests
+if [ ${skip_tests} -eq 0 ]; then
+	echo "Running tests"
+	cd ${ISSM_DIR}/test/NightlyRun
+	rm matlab.log 2> /dev/null
+
+	# Run tests, redirecting output to logfile and suppressing output to console
+	${MATLAB_PATH}/bin/matlab -nojvm -nosplash -nojvm -r "try, addpath ${ISSM_DIR}/bin ${ISSM_DIR}/lib ${ISSM_DIR}/share; runme(${MATLAB_NROPTIONS}); exit; catch me,fprintf('%s',getReport(me)); exit; end" &> matlab.log
+
+	# Check that MATLAB did not exit in error
+	matlabExitedInError=`grep -c -E "Activation cannot proceed|Error in|Illegal|Invalid MEX-file|license|Warning: Name is nonexistent or not a directory" matlab.log`
+
+	if [ ${matlabExitedInError} -ne 0 ]; then
+		echo "----------MATLAB exited in error!----------"
+		cat matlab.log
+		echo "-----------End of matlab.log-----------"
+
+		# Clean up execution directory
+		rm -rf ${ISSM_DIR}/execution/*
+
+		exit 1
+	fi
+
+	# Check that all tests passed
+	sed -i '' "/FAILED TO establish the default connection to the WindowServer/d" matlab.log # First, need to remove WindowServer error message
+	numTestsFailed=`grep -c -E "FAILED|ERROR" matlab.log`
+
+	if [ ${numTestsFailed} -ne 0 ]; then
+		echo "One or more tests FAILED"
+		cat matlab.log
+		exit 1
+	else
+		echo "All tests PASSED"
+	fi
+else
+	echo "Skipping tests"
+fi
+
+# Create package
+cd ${ISSM_DIR}
+svn cleanup --remove-ignored --remove-unversioned test # Clean up test directory (before copying to package)
+echo "Copying assets to package: ${PKG}"
+cp -rf bin examples lib scripts share test ${PKG}
+mkdir ${PKG}/execution
+cp packagers/mac/issm-executable_entitlements.plist ${PKG}/bin/entitlements.plist
+echo "Cleaning up unneeded/unwanted files"
+rm -f ${PKG}/bin/generic_static.* # Remove static versions of generic cluster classes
+rm -f ${PKG}/lib/*.a # Remove static libraries from package
+rm -f ${PKG}/lib/*.la # Remove libtool libraries from package
+rm -rf ${PKG}/test/SandBox # Remove testing sandbox from package
+
+# Compress package
+echo "Compressing package"
+ditto -ck --sequesterRsrc --keepParent ${PKG} ${COMPRESSED_PKG}
Index: /issm/trunk-jpl/packagers/mac/sign-issm-mac-binaries.sh
===================================================================
--- /issm/trunk-jpl/packagers/mac/sign-issm-mac-binaries.sh	(revision 28113)
+++ /issm/trunk-jpl/packagers/mac/sign-issm-mac-binaries.sh	(revision 28113)
@@ -0,0 +1,311 @@
+#!/bin/bash
+
+################################################################################
+# Intended to be run in the context of a Jenkins project on a JPL 
+# Cybersecurity server for signing macOS applications. Polls SCM of the 
+# Subversion repository hosted at 
+# https://issm.ess.uci.edu/svn/issm-binaries/mac/<ARCH>/<API>[/<VER>]/unsigned to 
+# trigger new builds.
+#
+# In order to replicate the required Jenkins project configuration,
+# - first, navigate to 'Manage Jenkins' -> 'Manage Plugins' and install the 
+#	'Credentials Bindings Plugin' if it is not already installed.
+# - contact one of the members of the ISSM development team for credentials for 
+#	the ISSM binaries repository (mention that the credentials are stored in 
+#	ISSM-Infrastructure.pdf).
+# - navigate to 'Manage Jenkins' -> 'Manage Credentials' -> <domain> -> 
+#	'Add Credentials' and enter the credentials from above.
+# - from the 'Dashboard', select 'New Item' -> 'Freestyle project'.
+# - under 'Source Code Management', select 'Subversion',
+#		- the 'Repository URL' text field should be set to 
+#
+# 		https://issm.ess.uci.edu/svn/issm-binaries/mac/<ARCH>/<API>[/<VER>]/unsigned
+#
+#		where,
+#
+#		<ARCH>			'intel' or 'silicon'
+#		<API>[/<VER>]	'matlab' or 'python/3'
+#
+#		- the 'Credentials' select menu should be set to the new credentials 
+#		created previously.
+#		- the 'Local module directory' text field should be set to the same 
+#		value as the constant UNSIGNED_REPO_COPY (set below to './unsigned').
+# - under 'Build Triggers', check the box for 'Poll SCM' and set the 
+#	'Schedule' text area to "H/5 * * * *".
+# - under 'Build Environment', check the box for 'Use secret text(s) or 
+#	file(s)', then under 'Bindings' click the 'Add...' button and select 
+#	'Username and password (separated)',
+#		- set 'Username Variable' to "ISSM_BINARIES_USER".
+#		- set 'Password Variable' to "ISSM_BINARIES_PASS".
+# - under 'Credentials', select the same, new credentials that created 
+#	previously.
+# - the contents of this script can be copied/pasted directly into the ‘Build' 
+#	-> 'Execute Shell' -> ‘Command' textarea of the project configuration (or 
+#	you can simply store the script on disk and call it from there).
+# - make sure to click the 'Save' button.
+#
+# Current point of contact at JPL Cybersecurity:
+#	Alex Coward, alexander.g.coward@jpl.nasa.gov
+#
+# NOTE:
+# - Assumes that "ISSM_BINARIES_USER" and "ISSM_BINARIES_PASS" are set up in 
+#	the 'Bindings' section under a 'Username and password (separated)' binding 
+#	(requires 'Credentials Binding Plugin').
+# - For local debugging, the aforementioned credentials can be hardcoded into 
+#	the 'USERNAME' and 'PASSWORD' constants below.
+################################################################################
+
+# Expand aliases within the context of this script
+shopt -s expand_aliases
+
+# NOTE: For some reason, calling svn from within the context of this script 
+#		gives,
+#
+#			svn: command not found
+#
+#		even though it is installed via Homebrew and available at the following 
+#		path.
+#
+alias svn='/usr/local/bin/svn'
+
+## Override certain other aliases
+#
+alias cp=$(which cp)
+alias grep=$(which grep)
+
+## Constants
+#
+
+## NOTE: The following need to be set with the proper credentials
+#
+AD_IDENTITY="**********" # Apple Developer identity
+AD_USERNAME="**********" # Apple Developer username
+ALTOOL_PASSWORD="@keychain:**********" # altool password (assumed to be stored in keychain)
+ASC_PROVIDER="**********"
+
+## NOTE: The following need to be set for the particular signing job (see comments for options)
+#
+PKG="ISSM-macOS-<ARCH>-<API>[-<VER>]" # <ARCH>: 'Intel' or 'Silicon'; <API>[-<VER>]: 'MATLAB' or 'Python-3'
+VARIANT_REPO_SUBPATH="<ARCH>/<API>[/<VER>]" # <ARCH>: 'intel' or 'silicon'; <API>[-<VER>]: 'matlab' or 'python/3'
+
+MAX_SVN_ATTEMPTS=10
+NOTARIZATION_CHECK_ATTEMPTS=20
+NOTARIZATION_CHECK_PERIOD=60
+NOTARIZATION_LOGFILE="notarization.log"
+NOTARIZATION_LOGFILE_PATH="."
+PASSWORD=${ISSM_BINARIES_PASS}
+REPO_URL="https://issm.ess.uci.edu/svn/issm-binaries"
+SIGNED_REPO_COPY="./signed"
+SIGNED_REPO_URL="${REPO_URL}/${VARIANT_REPO_SUBPATH}/signed"
+SIGNING_LOCK_FILE="signing.lock"
+SUCCESS_LOGFILE="${SIGNED_REPO_COPY}/success.log"
+UNSIGNED_REPO_COPY="./unsigned"
+UNSIGNED_REPO_URL="${REPO_URL}/${VARIANT_REPO_SUBPATH}/unsigned"
+USERNAME=${ISSM_BINARIES_USER}
+
+COMPRESSED_PKG="${PKG}.zip"
+EXE_ENTITLEMENTS_PLIST="${PKG}/bin/entitlements.plist"
+
+# NOTE: Uncomment the following for local testing (Jenkins checks out copy of 
+#		repository for unsigned packages to working directory)
+#
+
+# # Clean up from previous packaging (not necessary for single builds on Jenkins, 
+# # but useful when testing packaging locally)
+# echo "Cleaning up existing assets"
+# rm -rf ${COMPRESSED_PKG} ${NOTARIZATION_LOGFILE_PATH}/${NOTARIZATION_LOGFILE} ${UNSIGNED_REPO_COPY}
+
+# # Check out copy of repository for unsigned packages
+# echo "Checking out copy of repository for unsigned packages"
+# svn checkout \
+# 	--trust-server-cert \
+# 	--non-interactive \
+# 	--username ${USERNAME} \
+# 	--password ${PASSWORD} \
+# 	${UNSIGNED_REPO_URL} \
+# 	${UNSIGNED_REPO_COPY}
+
+rm -rf ${PKG} ${SIGNED_REPO_COPY}
+
+# Extract package contents
+echo "Extracting package contents"
+ditto -xk ${UNSIGNED_REPO_COPY}/${COMPRESSED_PKG} .
+
+# Clear extended attributes on all files
+xattr -cr ${PKG}
+
+# Build list of ISSM executables
+ISSM_BINS=$(\
+	find ${PKG}/bin -type f -name *.exe; \
+	find ${PKG}/lib -type f -name *.mexmaci64; \
+	find ${PKG}/test -type f -name *.pkg; \
+)
+
+# Build list of third party executables
+THIRD_PARTY_BINS=$(\
+	echo ${PKG}/bin/mpiexec; \
+	echo ${PKG}/bin/hydra_pmi_proxy; \
+	echo ${PKG}/bin/gdalsrsinfo; \
+	echo ${PKG}/bin/gdaltransform; \
+	echo ${PKG}/bin/gmt; \
+	echo ${PKG}/bin/gmtselect; \
+	echo ${PKG}/bin/gmsh; \
+)
+
+# Sign all executables in package
+echo "Signing all executables in package"
+codesign -s ${AD_IDENTITY} --timestamp --options=runtime --entitlements ${EXE_ENTITLEMENTS_PLIST} ${ISSM_BINS}
+codesign -s ${AD_IDENTITY} --timestamp --options=runtime ${THIRD_PARTY_BINS}
+
+# NOTE: Skipping signature validation because this is not a true package nor app
+
+# Compress signed package
+echo "Compressing signed package"
+ditto -ck --sequesterRsrc --keepParent ${PKG} ${COMPRESSED_PKG}
+
+# Submit compressed package for notarization
+echo "Submitting signed package to Apple for notarization"
+xcrun notarytool submit ${COMPRESSED_PKG} --apple-id "$AD_USERNAME" --team-id "$TEAM_ID" --password "$NOTARY_PASSWORD" --wait &> ${NOTARIZATION_LOGFILE_PATH}/${NOTARIZATION_LOGFILE}
+
+echo "Notarization request response received"
+
+# Check if UUID exists in response
+HAS_UUID=$(grep 'id: ' ${NOTARIZATION_LOGFILE_PATH}/${NOTARIZATION_LOGFILE})
+if [ -z "${HAS_UUID}" ]; then
+	echo "Notarization failed!"
+	echo "----------------------- Contents of notarization logfile -----------------------"
+	cat ${NOTARIZATION_LOGFILE_PATH}/${NOTARIZATION_LOGFILE}
+	echo "--------------------------------------------------------------------------------"
+
+	# Clean up
+	rm -rf ${PKG} ${COMPRESSED_PKG}
+
+	exit 1
+fi
+
+# Get UUID from notarization request response
+UUID=$(echo ${HAS_UUID} | sed 's/[[:space:]]*id: //')
+echo "UUID: ${UUID}" 
+
+# Check notarization status
+#
+# NOTE: Currently, this checks if notarization was successful, but we are not 
+#		able to staple notarization as this is not a true package nor app and, 
+#		at the very least, MATLAB Mex files cannot be stapled. As such, clients 
+#		will not be able to clear Gatekeeper if they are offline.
+#
+echo "Checking notarization status"
+SUCCESS=0
+xcrun notarytool log ${UUID} --apple-id "$AD_USERNAME" --team-id "$TEAM_ID" --password "$NOTARY_PASSWORD" &> ${NOTARIZATION_LOGFILE_PATH}/${NOTARIZATION_LOGFILE}
+STATUS=$(grep '"status": "Accepted"' ${NOTARIZATION_LOGFILE_PATH}/${NOTARIZATION_LOGFILE} | wc -l)
+
+if [[ ${STATUS} -gt 0 ]]; then
+	# Staple notarization to all elements of package that were previously signed
+	#xcrun stapler staple ${THIRD_PARTY_BINS} # NOTE: Fails with "Stapler is incapable of working with MATLAB Mex files."
+
+	# Validate stapling of notarization
+	#xcrun stapler validation ${THIRD_PARTY_BINS} # NOTE: Skipping notarization stapling validation because this is not a true package nor app
+
+	# Compress signed and notarized package
+	ditto -ck --sequesterRsrc --keepParent ${PKG} ${COMPRESSED_PKG}
+
+	echo "Notarization successful!"
+
+	# Set flag indicating notarization was successful
+	SUCCESS=1
+else
+	echo "Notarization failed!"
+	echo "----------------------- Contents of notarization logfile -----------------------"
+	cat ${NOTARIZATION_LOGFILE_PATH}/${NOTARIZATION_LOGFILE}
+	echo "--------------------------------------------------------------------------------"
+fi
+
+# Check out copy of repository for signed packages
+echo "Checking out copy of repository for signed packages"
+SVN_ATTEMPT=0
+SVN_SUCCESS=0
+while [[ ${SVN_ATTEMPT} -lt ${MAX_SVN_ATTEMPTS} && ${SVN_SUCCESS} -eq 0 ]]; do
+	rm -rf ${SIGNED_REPO_COPY}
+	svn checkout \
+		--trust-server-cert \
+		--non-interactive \
+		--username ${USERNAME} \
+		--password ${PASSWORD} \
+		${SIGNED_REPO_URL} \
+		${SIGNED_REPO_COPY} > /dev/null 2>&1
+	if [ $? -eq 0 ]; then
+		SVN_SUCCESS=1
+		break
+	else
+		((++SVN_ATTEMPT))
+		sleep 5
+	fi
+done
+
+if [ ${SVN_SUCCESS} -eq 0 ]; then
+	echo "Checkout of repository for signed packages failed"
+	exit 1
+fi
+
+# Copy notarization file to repository for signed packages
+cp ${NOTARIZATION_LOGFILE_PATH}/${NOTARIZATION_LOGFILE} ${SIGNED_REPO_COPY}
+svn add ${SIGNED_REPO_COPY}/${NOTARIZATION_LOGFILE} > /dev/null 2>&1
+
+# Remove lock file from repository for signed packages
+svn delete ${SIGNED_REPO_COPY}/${SIGNING_LOCK_FILE} > /dev/null 2>&1
+
+SVN_ATTEMPT=0
+SVN_SUCCESS=0
+if [ ${SUCCESS} -eq 1 ]; then
+	# Copy signed package to repository for signed packages
+	cp ${COMPRESSED_PKG} ${SIGNED_REPO_COPY}
+	svn add ${SIGNED_REPO_COPY}/${COMPRESSED_PKG} > /dev/null 2>&1
+
+	# Commit changes
+	echo "Committing changes to repository for signed packages"
+	while [[ ${SVN_ATTEMPT} -lt ${MAX_SVN_ATTEMPTS} && ${SVN_SUCCESS} -eq 0 ]]; do
+		svn commit \
+			--trust-server-cert \
+			--non-interactive \
+			--username ${USERNAME} \
+			--password ${PASSWORD} \
+			--message "CHG: New signed package (success)" ${SIGNED_REPO_COPY} > /dev/null 2>&1
+		if [ $? -eq 0 ]; then
+			SVN_SUCCESS=1
+			break
+		else
+			((++SVN_ATTEMPT))
+			sleep 5
+		fi
+	done
+
+	if [ ${SVN_SUCCESS} -eq 0 ]; then
+		echo "Commit to repository for signed packages failed"
+		exit 1
+	fi
+else
+	# Commit changes
+	echo "Committing changes to repository for signed packages"
+	while [[ ${SVN_ATTEMPT} -lt ${MAX_SVN_ATTEMPTS} && ${SVN_SUCCESS} -eq 0 ]]; do
+		svn commit \
+			--trust-server-cert \
+			--non-interactive \
+			--username ${USERNAME} \
+			--password ${PASSWORD} \
+			--message "CHG: New signed package (failure)" ${SIGNED_REPO_COPY} > /dev/null 2>&1
+		if [ $? -eq 0 ]; then
+			SVN_SUCCESS=1
+			break
+		else
+			((++SVN_ATTEMPT))
+			sleep 5
+		fi
+	done
+
+	if [ ${SVN_SUCCESS} -eq 0 ]; then
+		echo "Commit to repository for signed packages failed"
+		exit 1
+	fi
+
+	exit 1
+fi
