Created
December 9, 2019 17:11
-
-
Save KosmicTask/d97904304f242308feaad94aa93c0513 to your computer and use it in GitHub Desktop.
Make an embeddable copy of Mono on macOS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# make-mono-framework.sh | |
# | |
# Generate ./Mono.framework from /Library/Frameworks/Mono.framework. | |
# The generated framework will be suitable for copying into an app bundle. | |
# | |
# Typical usage would be: | |
# sudo ./make-mono-framework.sh x.x.x | |
# | |
# | |
# Looking at how Xamarin package this up for Xamarin.mac apps it is clear that we could perhaps | |
# simplify the folder structure here. | |
# | |
USAGE="usage is make-mono-framework mono-version" | |
# arg 1 is Mono version | |
if [ -z "$1" ] | |
then | |
echo "Missing Mono version string; $USAGE " | |
exit 1 | |
fi | |
VERSION="$1" | |
#commands | |
MK_DIR='mkdir -vp' | |
# change to directory of this script | |
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" | |
cd $SCRIPT_DIR | |
# targets, we copy from LIB_ to OUT_ | |
FRAMEWORK=Mono.framework | |
LIB_FRAMEWORK=/Library/Frameworks/Mono.framework | |
OUT_FRAMEWORK=${SCRIPT_DIR}/${FRAMEWORK} | |
# remove existing framework | |
echo "Removing existing ${FRAMEWORK}" | |
rm -rf $FRAMEWORK | |
# make bundle from build products | |
echo "Making framework bundle" | |
$MK_DIR $FRAMEWORK | |
cd $FRAMEWORK | |
# folder names | |
F_VERSIONS='Versions' | |
F_VERSION=$VERSION | |
F_BIN='bin' | |
F_COMMANDS='commands' | |
F_ETC='etc' | |
F_MONO='mono' | |
F_NET_FRAMEWORK_VERSION='4.5' | |
F_LIB='lib' | |
F_GAC='gac' | |
# relative folder paths | |
P_VERSIONS=$F_VERSIONS | |
P_VERSION=${P_VERSIONS}/$F_VERSION | |
P_BIN=${P_VERSION}/$F_BIN | |
P_COMMANDS=${P_VERSION}/$F_COMMANDS | |
P_ETC=${P_VERSION}/$F_ETC | |
P_LIB=${P_VERSION}/$F_LIB | |
# make out paths | |
$MK_DIR ${OUT_FRAMEWORK}/$P_VERSIONS | |
$MK_DIR ${OUT_FRAMEWORK}/$P_VERSION | |
$MK_DIR ${OUT_FRAMEWORK}/$P_BIN | |
$MK_DIR ${OUT_FRAMEWORK}/$P_COMMANDS | |
$MK_DIR ${OUT_FRAMEWORK}/$P_ETC | |
$MK_DIR ${OUT_FRAMEWORK}/$P_LIB | |
# native libraries | |
LIB_MONO=libmonosgen-2.0.1.dylib | |
# | |
# copy_targets and srguments | |
# | |
SRC_PATH='' | |
OUT_PATH='' | |
TARGETS=() # passing array as function arg seems tricky | |
function copy_targets() { | |
if [ ! -d $OUT_PATH ]; then | |
$MK_DIR $OUT_PATH; | |
fi | |
for TARGET in "${TARGETS[@]}"; do | |
cp -R ${SRC_PATH}/${TARGET} $OUT_PATH | |
done | |
} | |
# | |
# do_lipo | |
# | |
function do_lipo() { | |
local TARGET=$1 | |
LIPO_TARGET=${TARGET}.lipotarget | |
cp $TARGET $LIPO_TARGET | |
rm -f $TARGET | |
lipo -extract 'x86_64' -output $TARGET $LIPO_TARGET | |
rm -f $LIPO_TARGET | |
} | |
# | |
# copy bin targets | |
# | |
SRC_PATH=${LIB_FRAMEWORK}/${P_BIN} | |
OUT_PATH=${OUT_FRAMEWORK}/${P_BIN} | |
TARGETS=( | |
mcs | |
mono-sgen64 | |
) | |
copy_targets | |
# | |
# copy etc/mono targets | |
# | |
SRC_PATH=${LIB_FRAMEWORK}/${P_ETC}/${F_MONO} | |
OUT_PATH=${OUT_FRAMEWORK}/${P_ETC}/${F_MONO} | |
TARGETS=( | |
config | |
mconfig | |
$F_NET_FRAMEWORK_VERSION | |
) | |
copy_targets | |
# | |
# copy lib targets | |
# | |
SRC_PATH=${LIB_FRAMEWORK}/${P_LIB} | |
OUT_PATH=${OUT_FRAMEWORK}/${P_LIB} | |
TARGETS=( | |
libMonoPosixHelper.dylib | |
$LIB_MONO | |
) | |
copy_targets | |
do_lipo ${OUT_PATH}/${LIB_MONO} | |
# | |
# copy lib/mono/${4.5} targets | |
# | |
SRC_PATH=${LIB_FRAMEWORK}/${P_LIB}/${F_MONO}/${F_NET_FRAMEWORK_VERSION} | |
OUT_PATH=${OUT_FRAMEWORK}/${P_LIB}/${F_MONO}/${F_NET_FRAMEWORK_VERSION} | |
TARGETS=( | |
mscorlib.dll | |
mcs.exe | |
) | |
copy_targets | |
# | |
# copy lib/mono/gac targets | |
# note that the gac contains folders named using the assembly name. | |
# each assembly folder then contsins subfolders identifying instances of the named assembly by its strong name. | |
# required assemblies available as monolinker -c link -a UK.BrightPay.Engine.OSX.exe -out minimal | |
# we should really run the monolinker here and dynamically extract the required GAC assemblies | |
SRC_PATH=${LIB_FRAMEWORK}/${P_LIB}/${F_MONO}/${F_GAC} | |
OUT_PATH=${OUT_FRAMEWORK}/${P_LIB}/${F_MONO}/${F_GAC} | |
TARGETS=( | |
I18N | |
I18N.CJK | |
I18N.MidEast | |
I18N.Other | |
I18N.Rare | |
I18N.West | |
Microsoft.CSharp | |
Mono.CSharp | |
Mono.Data.Tds | |
Mono.Posix | |
Mono.Security | |
System.ComponentModel.DataAnnotations | |
System.Configuration | |
System.Core | |
System.Data | |
System.Data.Entity | |
System.Drawing | |
System.EnterpriseServices | |
System.Management | |
System.Numerics | |
System.Runtime.Serialization | |
System.Security | |
System.Transactions | |
System.Web | |
System.Xml.Linq | |
System.Xml | |
System | |
) | |
copy_targets | |
# | |
# iterate over the GAC strong named folders and create symlinks in lib/mono/${4.5} pointing to actual dlls. | |
# these symlinks make it much easier to locate the mono system libraries and replicates the form of the mono framework bundle. | |
# | |
OUT_PATH=${OUT_FRAMEWORK}/${P_LIB}/${F_MONO}/${F_NET_FRAMEWORK_VERSION} | |
for TARGET in "${TARGETS[@]}"; do | |
SRC_FOLDER="$SRC_PATH"/"$TARGET" | |
# we loop here but there should only be one strong named subfolder | |
for d in "$SRC_FOLDER"/*/ ; do | |
STRONG_NAME="$(basename $d)" | |
ln -sv ../gac/"$TARGET"/"$STRONG_NAME"/"$TARGET".dll "$OUT_PATH"/"$TARGET".dll | |
done | |
done | |
# | |
# rename version folder to A. | |
# this makes life simpler as when the xcode does the signing it always looks for the A version | |
# | |
mv ./$P_VERSIONS/$F_VERSION ./$P_VERSIONS/A | |
# | |
# we must have a Current symlink otherwise codesign rejects bundle | |
# | |
ln -sv ./A ${OUT_FRAMEWORK}/$P_VERSIONS/Current | |
# | |
# create resources folder and copy in framework bundle plist. | |
# without this codesign will fail for the bundle citing an invalid format | |
# as an info.plist is a mandatory signature component. | |
# | |
OUT_PATH=${OUT_FRAMEWORK}/$P_VERSIONS/A/Resources | |
$MK_DIR ${OUT_PATH} | |
cp "$SCRIPT_DIR"/mono-framework-info.plist "$OUT_PATH"/info.plist |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment