-
Notifications
You must be signed in to change notification settings - Fork 62
/
build_python_framework
executable file
·128 lines (110 loc) · 5.79 KB
/
build_python_framework
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/bin/zsh
#
# Build script for universal Python 3 framework for InstallApplications
# Taken from https://github.com/munki/munki/blob/main/code/tools/build_python_framework.sh
# IMPORTANT
# Run this with your current directory being the path where this script is located
TOOLSDIR=$(dirname $0)
REQUIREMENTS="${TOOLSDIR}/py3_requirements.txt"
MACOS_VERSION=11.0 # use 10.9 for non-universal
PYTHON_BIN_VERSION=3.9
PYTHON_VERSION=3.9.1
PYTHON_PRERELEASE_VERSION=
PYTHON_BASEURL="https://www.python.org/ftp/python/%s/python-%s${PYTHON_PRERELEASE_VERSION}-macos%s.pkg"
PYTHONTOOLDIR="/tmp/relocatable-python-git"
CONSOLEUSER=$(/usr/bin/stat -f "%Su" /dev/console)
FRAMEWORKDIR="/Library/installapplications"
PIPCACHEDIR="/Users/${CONSOLEUSER}/Library/Caches/pip"
XCODE_SELECT=$(/usr/bin/xcode-select -p)
# Sanity checks.
GIT=$(which git)
WHICH_GIT_RESULT="$?"
if [ "${WHICH_GIT_RESULT}" != "0" ]; then
echo "Could not find git in command path. Maybe it's not installed?" 1>&2
echo "You can get a Git package here:" 1>&2
echo " https://git-scm.com/download/mac"
exit 1
fi
if [ ! -f "${REQUIREMENTS}" ]; then
echo "Missing requirements file at ${REQUIREMENTS}." 1>&2
exit 1
fi
# Create framework path if not present
if [ ! -d "${FRAMEWORKDIR}" ]; then
/usr/bin/sudo /bin/mkdir -p "${FRAMEWORKDIR}"
fi
# Give 777 permissions so we don't have to use sudo for other commands
if [ -d "${FRAMEWORKDIR}" ]; then
/usr/bin/sudo /bin/chmod -R 777 "${FRAMEWORKDIR}"
fi
# remove existing library Python.framework if present
if [ -d "${FRAMEWORKDIR}/Python.framework" ]; then
/bin/rm -rf "${FRAMEWORKDIR}/Python.framework"
fi
# clone our relocatable-python tool
if [ -d "${PYTHONTOOLDIR}" ]; then
/usr/bin/sudo /bin/rm -rf "${PYTHONTOOLDIR}"
fi
echo "Cloning relocatable-python tool from github..."
git clone https://github.com/gregneagle/relocatable-python.git "${PYTHONTOOLDIR}"
CLONE_RESULT="$?"
if [ "${CLONE_RESULT}" != "0" ]; then
echo "Error cloning relocatable-python tool repo: ${CLONE_RESULT}" 1>&2
exit 1
fi
# remove existing munki-pkg Python.framework if present
if [ -d "$TOOLSDIR/payload/${FRAMEWORKDIR}/Python.framework" ]; then
/bin/rm -rf "$TOOLSDIR/payload/${FRAMEWORKDIR}/Python.framework"
fi
# remove existing library Python.framework if present
if [ -d "${PIPCACHEDIR}" ]; then
echo "Removing pip cache to reduce framework build errors"
/usr/bin/sudo /bin/rm -rf "${PIPCACHEDIR}"
fi
# build the framework
if [[ "${XCODE_SELECT}" != "/Applications/Xcode.app/Contents/Developer" ]]; then
echo "Building the universal python framework may result in errors due to Xcode not being installed"
fi
"${PYTHONTOOLDIR}/make_relocatable_python_framework.py" \
--baseurl "${PYTHON_BASEURL}" \
--python-version "${PYTHON_VERSION}" \
--os-version "${MACOS_VERSION}" \
--pip-requirements "${REQUIREMENTS}" \
--destination "${FRAMEWORKDIR}" \
--upgrade-pip
# move the framework
echo "Moving Python.framework to InstallApplications munki-pkg payload folder"
/bin/mv "${FRAMEWORKDIR}/Python.framework" "$TOOLSDIR/payload/${FRAMEWORKDIR}"
# take ownership of the payload folder
echo "Taking ownership of the file to not break git"
/usr/bin/sudo /usr/sbin/chown -R ${CONSOLEUSER}:wheel "$TOOLSDIR/payload/${FRAMEWORKDIR}/Python.framework"
# ad-hoc re-sign the framework so it will run on Apple Silicon
echo "Adding ad-hoc code signing so the framework will run on Apple Silicon..."
/usr/bin/codesign -s - --deep --force --preserve-metadata=identifier,entitlements,flags,runtime "$TOOLSDIR/payload/${FRAMEWORKDIR}/Python.framework/Versions/${PYTHON_BIN_VERSION}/Resources/Python.app"
/usr/bin/codesign -s - --force --preserve-metadata=identifier,entitlements,flags,runtime "$TOOLSDIR/payload/${FRAMEWORKDIR}/Python.framework/Versions/Current/Python"
/usr/bin/find "$TOOLSDIR/payload/${FRAMEWORKDIR}/Python.framework/Versions/Current/bin/" -type f -perm -u=x -exec /usr/bin/codesign -s - --preserve-metadata=identifier,entitlements,flags,runtime -f {} \;
/usr/bin/find "$TOOLSDIR/payload/${FRAMEWORKDIR}/Python.framework/Versions/Current/lib/" -type f -perm -u=x -exec /usr/bin/codesign -s - --preserve-metadata=identifier,entitlements,flags,runtime -f {} \;
/usr/bin/find "$TOOLSDIR/payload/${FRAMEWORKDIR}/Python.framework/Versions/Current/lib/" -type f -name "*dylib" -exec /usr/bin/codesign -s - --preserve-metadata=identifier,entitlements,flags,runtime -f {} \;
# Clean up workspace
if [ -d "${FRAMEWORKDIR}" ]; then
/usr/bin/sudo /bin/rm -rf "${FRAMEWORKDIR}"
fi
# confirm truly universal
TOTAL_DYLIB=$(/usr/bin/find "$TOOLSDIR/payload/${FRAMEWORKDIR}/Python.framework/Versions/Current/lib" -name "*.dylib" | /usr/bin/wc -l | /usr/bin/xargs)
UNIVERSAL_DYLIB=$(/usr/bin/find "$TOOLSDIR/payload/${FRAMEWORKDIR}/Python.framework/Versions/Current/lib" -name "*.dylib" | /usr/bin/xargs file | /usr/bin/grep "2 architectures" | /usr/bin/wc -l | /usr/bin/xargs)
if [ "${TOTAL_DYLIB}" != "${UNIVERSAL_DYLIB}" ] ; then
echo "Dynamic Libraries do not match, resulting in a non-universal Python framework."
echo "Total Dynamic Libraries found: ${TOTAL_DYLIB}"
echo "Universal Dynamic Libraries found: ${UNIVERSAL_DYLIB}"
exit 1
fi
echo "Dynamic Libraries are confirmed as universal"
TOTAL_SO=$(/usr/bin/find "$TOOLSDIR/payload/${FRAMEWORKDIR}/Python.framework/Versions/Current/lib" -name "*.so" | /usr/bin/wc -l | /usr/bin/xargs)
UNIVERSAL_SO=$(/usr/bin/find "$TOOLSDIR/payload/${FRAMEWORKDIR}/Python.framework/Versions/Current/lib" -name "*.so" | /usr/bin/xargs file | /usr/bin/grep "2 architectures" | /usr/bin/wc -l | /usr/bin/xargs)
if [ "${TOTAL_SO}" != "${UNIVERSAL_SO}" ] ; then
echo "Shared objects do not match, resulting in a non-universal Python framework."
echo "Total shared objects found: ${TOTAL_SO}"
echo "Universal shared objects found: ${UNIVERSAL_SO}"
exit 1
fi
echo "Shared objects are confirmed as universal"