|
| 1 | +#!/bin/bash |
| 2 | +set -x |
| 3 | +################################################################################ |
| 4 | +# File: mac/buildDmg.sh |
| 5 | +# Purpose: Builds a self-contained dmg for a simple Hello World |
| 6 | +# GUI app using kivy. See also: |
| 7 | +# |
| 8 | +# * https://kivy.org/doc/stable/installation/installation-osx.html |
| 9 | +# * https://kivy.org/doc/stable/guide/packaging-osx.html |
| 10 | +# * https://github.com/kivy/buildozer/issues/494#issuecomment-390262889 |
| 11 | +# |
| 12 | +# Authors: Michael Altfield <[email protected]> |
| 13 | +# Created: 2020-06-22 |
| 14 | +# Updated: 2020-06-22 |
| 15 | +# Version: 0.1 |
| 16 | +################################################################################ |
| 17 | + |
| 18 | +# TODO: remove this after testing replacement with other python binaries that are available |
| 19 | +mkdir -p buildozer/dist |
| 20 | +cp /usr/bin/python3 buildozer/dist/usr-bin-python3 |
| 21 | +cp /usr/local/bin/python3 buildozer/dist/usr-local-bin-python3 |
| 22 | + |
| 23 | +exit 0 |
| 24 | + |
| 25 | +############ |
| 26 | +# SETTINGS # |
| 27 | +############ |
| 28 | + |
| 29 | +PYTHON_PATH='/usr/bin/python3' |
| 30 | +APP_NAME='helloWorld' |
| 31 | + |
| 32 | +PYTHON_VERSION="`${PYTHON_PATH} --version | cut -d' ' -f2`" |
| 33 | +PYTHON_EXEC_VERSION="`echo ${PYTHON_VERSION} | cut -d. -f1-2`" |
| 34 | + |
| 35 | +# attempt to overwrite brew's /usr/local/bin/python3 with /usr/bin/python3 |
| 36 | +alias python3='${PYTHON_PATH}' |
| 37 | + |
| 38 | +######## |
| 39 | +# INFO # |
| 40 | +######## |
| 41 | + |
| 42 | +# print some info for debugging failed builds |
| 43 | + |
| 44 | +uname -a |
| 45 | +sw_vers |
| 46 | +which python2 |
| 47 | +python2 --version |
| 48 | +which python3 |
| 49 | +python3 --version |
| 50 | +${PYTHON_PATH} --version |
| 51 | +echo $PATH |
| 52 | +pwd |
| 53 | +ls -lah |
| 54 | + |
| 55 | +echo "INFO: list of python* in /usr/bin/" |
| 56 | +ls -lah /usr/bin/python* |
| 57 | +find /usr/bin -type f -name python | xargs --version |
| 58 | +find /usr/bin -type f -name python3 | xargs --version |
| 59 | +md5 /usr/bin/python* |
| 60 | + |
| 61 | +echo "INFO: list of python* in /usr/local/bin/" |
| 62 | +ls -lah /usr/local/bin/python* |
| 63 | +find /usr/local/bin -type f -name python | xargs --version |
| 64 | +find /usr/local/bin -type f -name python3 | xargs --version |
| 65 | +md5 /usr/local/bin/python* |
| 66 | + |
| 67 | +################### |
| 68 | +# INSTALL DEPENDS # |
| 69 | +################### |
| 70 | + |
| 71 | +# install os-level depends |
| 72 | +brew install wget |
| 73 | +brew cask install platypus |
| 74 | + |
| 75 | +# first update our PATH so installed depends can be executed |
| 76 | +PATH=${PATH}:/Users/runner/Library/Python/${PYTHON_EXEC_VERSION}/bin |
| 77 | + |
| 78 | +# everything here is python3, except these bits. python2 is used in |
| 79 | +# package_app.py, which is used by buildozer and has a few depends |
| 80 | +sudo /usr/bin/python2 -m ensurepip |
| 81 | +/usr/bin/python2 -m pip install --upgrade --user docopt sh |
| 82 | + |
| 83 | +# setup a virtualenv to isolate our app's python depends |
| 84 | +sudo ${PYTHON_PATH} -m ensurepip |
| 85 | +${PYTHON_PATH} -m pip install --upgrade --user pip setuptools |
| 86 | +#${PYTHON_PATH} -m pip install --upgrade --user virtualenv |
| 87 | +#${PYTHON_PATH} -m virtualenv /tmp/kivy_venv |
| 88 | + |
| 89 | +# install kivy and all other python dependencies with pip into our virtual env |
| 90 | +#source /tmp/kivy_venv/bin/activate |
| 91 | +${PYTHON_PATH} -m pip install -r requirements.txt |
| 92 | + |
| 93 | +kivyVersion="`${PYTHON_PATH} -m pip list | grep -i 'kivy ' | awk '{print $2}'`" |
| 94 | + |
| 95 | +# install buildozer |
| 96 | +${PYTHON_PATH} -m pip install --upgrade git+http://github.com/kivy/buildozer |
| 97 | + |
| 98 | +# install a bunch of other shit so buildozer doesn't fail with python3 |
| 99 | +# see: https://github.com/kivy/buildozer/issues/494#issuecomment-390262889 |
| 100 | + |
| 101 | +## Install platypus |
| 102 | +if [[ $(which platypus > /dev/null; echo $?) != "0" ]]; then |
| 103 | + pushd ~/Downloads |
| 104 | + wget https://www.sveinbjorn.org/files/software/platypus/platypus5.2.zip |
| 105 | + unzip platypus5.2.zip |
| 106 | + rm platypus5.2.zip |
| 107 | + |
| 108 | + sudo cp Platypus-5.2/Platypus.app/Contents/Resources/platypus_clt /usr/local/bin/ |
| 109 | + sudo mv /usr/local/bin/platypus_clt /usr/local/bin/platypus |
| 110 | + |
| 111 | + sudo mkdir -p /usr/local/share/platypus |
| 112 | + sudo cp Platypus-5.2/Platypus.app/Contents/Resources/ScriptExec /usr/local/share/platypus |
| 113 | + sudo chmod +x /usr/local/share/platypus/ScriptExec |
| 114 | + sudo cp -R Platypus-5.2/Platypus.app/Contents/Resources/MainMenu.nib /usr/local/share/platypus |
| 115 | + |
| 116 | + rm -Rf Platypus-5.2 |
| 117 | + popd |
| 118 | +else |
| 119 | + echo "Platypus is already installed..." |
| 120 | +fi |
| 121 | + |
| 122 | +## Install GStreamer |
| 123 | +if [[ ! -d /Library/Frameworks/GStreamer.framework ]]; then |
| 124 | + pushd ~/Downloads |
| 125 | + |
| 126 | + # You need both, gstreamer runtime binaries and libs and the development package including the headers. |
| 127 | + |
| 128 | + wget https://gstreamer.freedesktop.org/data/pkg/osx/1.14.0/gstreamer-1.0-devel-1.14.0-x86_64.pkg |
| 129 | + sudo /usr/sbin/installer -pkg gstreamer-1.0-devel-1.14.0-x86_64.pkg -target / |
| 130 | + rm gstreamer-1.0-devel-1.14.0-x86_64.pkg |
| 131 | + |
| 132 | + wget https://gstreamer.freedesktop.org/data/pkg/osx/1.14.0/gstreamer-1.0-1.14.0-x86_64.pkg |
| 133 | + sudo /usr/sbin/installer -pkg gstreamer-1.0-1.14.0-x86_64.pkg -target / |
| 134 | + rm gstreamer-1.0-1.14.0-x86_64.pkg |
| 135 | + |
| 136 | + popd |
| 137 | +else |
| 138 | + echo "GStreamer is already installed..." |
| 139 | +fi |
| 140 | + |
| 141 | +## Install SDL2 stuff |
| 142 | +if [[ ! -d /Library/Frameworks/SDL2.framework ]]; then |
| 143 | + pushd ~/Downloads |
| 144 | + wget https://www.libsdl.org/release/SDL2-2.0.4.dmg |
| 145 | + hdiutil attach SDL2-2.0.4.dmg && sudo cp -R /Volumes/SDL2/SDL2.framework /Library/Frameworks |
| 146 | + hdiutil detach /Volumes/SDL2 |
| 147 | + rm SDL2-2.0.4.dmg |
| 148 | + popd |
| 149 | +else |
| 150 | + echo "SDL2 is already installed..." |
| 151 | +fi |
| 152 | + |
| 153 | +if [[ ! -d /Library/Frameworks/SDL2_image.framework ]]; then |
| 154 | + pushd ~/Downloads |
| 155 | + wget https://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.0.1.dmg |
| 156 | + hdiutil attach SDL2_image-2.0.1.dmg && sudo cp -R /Volumes/SDL2_image/SDL2_image.framework /Library/Frameworks |
| 157 | + hdiutil detach /Volumes/SDL2_image |
| 158 | + rm SDL2_image-2.0.1.dmg |
| 159 | + popd |
| 160 | +else |
| 161 | + echo "SDL2_image is already installed..." |
| 162 | +fi |
| 163 | + |
| 164 | +if [[ ! -d /Library/Frameworks/SDL2_ttf.framework ]]; then |
| 165 | + pushd ~/Downloads |
| 166 | + wget https://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-2.0.14.dmg |
| 167 | + hdiutil attach SDL2_ttf-2.0.14.dmg && sudo cp -R /Volumes/SDL2_ttf/SDL2_ttf.framework /Library/Frameworks |
| 168 | + hdiutil detach /Volumes/SDL2_ttf |
| 169 | + rm SDL2_ttf-2.0.14.dmg |
| 170 | + popd |
| 171 | +else |
| 172 | + echo "SDL2_ttf is already installed..." |
| 173 | +fi |
| 174 | + |
| 175 | +if [[ ! -d /Library/Frameworks/SDL2_mixer.framework ]]; then |
| 176 | + pushd ~/Downloads |
| 177 | + wget https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.1.dmg |
| 178 | + hdiutil attach SDL2_mixer-2.0.1.dmg && sudo cp -R /Volumes/SDL2_mixer/SDL2_mixer.framework /Library/Frameworks |
| 179 | + hdiutil detach /Volumes/SDL2_mixer |
| 180 | + rm SDL2_mixer-2.0.1.dmg |
| 181 | + popd |
| 182 | +else |
| 183 | + echo "SDL2_mixer is already installed..." |
| 184 | +fi |
| 185 | + |
| 186 | +##################### |
| 187 | +# PREPARE BUILDOZER # |
| 188 | +##################### |
| 189 | + |
| 190 | +# create and enter our new dir for buildozer |
| 191 | +mkdir buildozer |
| 192 | +cp requirements.txt buildozer/ |
| 193 | + |
| 194 | +# hack to fix "ERROR: You must give at least one requirement to install" |
| 195 | +echo "pip" >> buildozer/requirements.txt |
| 196 | + |
| 197 | +pushd buildozer |
| 198 | + |
| 199 | +# create buildozer.spec file |
| 200 | +cat > buildozer.spec << EOF |
| 201 | +[app] |
| 202 | +title = Hello World |
| 203 | +package.name = ${APP_NAME} |
| 204 | +package.domain = org.test |
| 205 | +source.dir = ../src/ |
| 206 | +source.include_exts = py,png,jpg,kv,atlas |
| 207 | +version = 0.1 |
| 208 | +requirements = kivy |
| 209 | +orientation = portrait |
| 210 | +osx.python_version = 3 |
| 211 | +osx.kivy_version = 1.9.1 |
| 212 | +fullscreen = 0 |
| 213 | +[buildozer] |
| 214 | +log_level = 2 |
| 215 | +warn_on_root = 1 |
| 216 | +EOF |
| 217 | + |
| 218 | +## Change buildozer to use a python3.7 virtual environment instead of python2.7 |
| 219 | +#pushd /usr/local/lib/$PYTHON_EXEC_VERSION/site-packages/buildozer |
| 220 | +#sed -i '' 's;virtualenv --python=python2.7;virtualenv --python=python3.7;g' __init__.py |
| 221 | +#popd |
| 222 | +# |
| 223 | +## Change the osx target to use python3 to run the package_app.py script. |
| 224 | +#pushd /usr/local/lib/$PYTHON_EXEC_VERSION/site-packages/buildozer/targets |
| 225 | +#sed -i '' "s;'python', 'package_app.py';'python3', 'package_app.py';g" osx.py |
| 226 | +#popd |
| 227 | + |
| 228 | +# First run fails but is necessary to create the directory .buildozer |
| 229 | +buildozer osx debug |
| 230 | +if [[ "$?" != 0 ]]; then |
| 231 | + echo "[INFO] First run of buildozer failed as expected." |
| 232 | +fi |
| 233 | + |
| 234 | +# Go into the kivy sdk directory to create the file Kivy.app |
| 235 | +pushd .buildozer/osx/platform/kivy-sdk-packager-master/osx |
| 236 | +rm -Rf Kivy3.dmg |
| 237 | +sed -i '' "s;3.5.0;$PYTHON_VERSION;g" create-osx-bundle.sh |
| 238 | +sed -i '' "s;python3.5;$PYTHON_EXEC_VERSION;g" create-osx-bundle.sh |
| 239 | +sed -i '' "s;rm {};rm -f {};g" create-osx-bundle.sh |
| 240 | + |
| 241 | +./create-osx-bundle.sh ${kivyVersion} ${PYTHON_VERSION} |
| 242 | + |
| 243 | +# TODO: remove this after you fix the python binary issues |
| 244 | +ls -lah /Users/runner/.pyenv/versions/ |
| 245 | +ls -lah /Users/runner/.pyenv/versions/*/bin/ |
| 246 | +md5 /Users/runner/.pyenv/versions/*/bin/* |
| 247 | +ls -lah Kivy.app/Contents/Resources/venv/bin/ |
| 248 | +ls -lah Kivy.app/Contents/Frameworks/python/${PYTHON_VERSION}/bin |
| 249 | +md5 Kivy.app/Contents/Frameworks/python/${PYTHON_VERSION}/bin/* |
| 250 | + |
| 251 | +# Repair symlink |
| 252 | +pushd Kivy.app/Contents/Resources/venv/bin/ |
| 253 | +rm ./python3 |
| 254 | +ln -s ../../../Frameworks/python/$PYTHON_VERSION/bin/python3 . |
| 255 | +popd |
| 256 | + |
| 257 | +# Go into kivy sdk directory and fix the script package_app.py to use the specified python version. |
| 258 | +cp package_app.py package_app.py.orig |
| 259 | +echo "===package_app.py.orig=======================================================" |
| 260 | +cat package_app.py.orig |
| 261 | +echo "===package_app.py.orig=======================================================" |
| 262 | +sed -i '' "s;3.5.0;$PYTHON_VERSION;g" package_app.py |
| 263 | + |
| 264 | +# prevent auto-thinning |
| 265 | +sed -i '' "s;if not strip:;if True:;g" package_app.py |
| 266 | + |
| 267 | +## Make it python3 compatible by removing decode(...) calls. |
| 268 | +#sed -i '' "s;\.decode('utf-8');;g" package_app.py |
| 269 | +diff package_app.py.orig package_app.py |
| 270 | +popd |
| 271 | + |
| 272 | +############# |
| 273 | +# BUILD APP # |
| 274 | +############# |
| 275 | + |
| 276 | +# buildozer should now be able to build our .app file |
| 277 | +buildozer osx debug |
| 278 | + |
| 279 | +# TODO: remove this after you fix the python binary issues |
| 280 | +echo "INFO: list of python binaries in the new .app dir" |
| 281 | +find /Users/runner/runners/2.263.0/work/cross-platform-python-gui/ -type f -name python |
| 282 | +find /Users/runner/runners/2.263.0/work/cross-platform-python-gui/ -type f -name python | xargs --version |
| 283 | +find /Users/runner/runners/2.263.0/work/cross-platform-python-gui/ -type f -name python | xargs md5 |
| 284 | +find /Users/runner/runners/2.263.0/work/cross-platform-python-gui/ -type f -name python3 |
| 285 | +find /Users/runner/runners/2.263.0/work/cross-platform-python-gui/ -type f -name python3 | xargs --version |
| 286 | +find /Users/runner/runners/2.263.0/work/cross-platform-python-gui/ -type f -name python3 | xargs md5 |
| 287 | + |
| 288 | +############ |
| 289 | +# THIN APP # |
| 290 | +############ |
| 291 | + |
| 292 | +# remove unnecessary libs |
| 293 | +pushd .buildozer/osx/platform/kivy-sdk-packager-master/osx |
| 294 | + |
| 295 | +# TODO: remove this after you fix the python binary issues |
| 296 | +ls -lah Kivy.app/Contents/Resources/ |
| 297 | +ls -lah Kivy.app/Contents/Resources/python |
| 298 | +ls -lah Kivy.app/Contents/Resources/venv/bin/ |
| 299 | +ls -lah Kivy.app/Contents/Resources/venv/bin/python |
| 300 | +ls -lah Kivy.app/Contents/Frameworks/python/3.7.3/bin/ |
| 301 | +ls -lah Kivy.app/Contents/Frameworks/python/3.7.3/bin/python |
| 302 | +ls -lah Kivy.app/Contents/Frameworks/python/3.7.3/bin/python3.7 |
| 303 | +md5 Kivy.app/Contents/Frameworks/python/3.7.3/bin/python3.7 |
| 304 | +Kivy.app/Contents/Frameworks/python/3.7.3/bin/python3.7 --version |
| 305 | +cp /usr/bin/python3 helloWorld.app/Contents/usr-bin-python3 |
| 306 | +cp /usr/local/bin/python3 helloWorld.app/Contents/usr-local-bin-python3 |
| 307 | + |
| 308 | +# GStreamer is the easiest; ~150M gone |
| 309 | +rm -rf "${APP_NAME}.app/Contents/Frameworks/GStreamer.framework" |
| 310 | + |
| 311 | +# TODO: after you actually get a working build, uncomment and test this thinning |
| 312 | +## kivy build, doc, and examples dirs total to ~50M |
| 313 | +#rm -rf "${APP_NAME}.app/Contents/Resources/kivy/build/" |
| 314 | +#rm -rf "${APP_NAME}.app/Contents/Resources/kivy/doc/" |
| 315 | +#rm -rf "${APP_NAME}.app/Contents/Resources/kivy/examples/" |
| 316 | +# |
| 317 | +## somehow it still works for me with this gone, but I wonder if it's because it |
| 318 | +## finds python outside the .app dir? Anyway, this python dir is ~150M |
| 319 | +#rm -rf "${APP_NAME}.app/Contents/Frameworks/python" |
| 320 | +# |
| 321 | +## the whole lib dir isn't necessary for our simple kivy app; I imagine if your |
| 322 | +## app has more depends, you'll have to be more selective here |
| 323 | +#rm -rf "${APP_NAME}.app/Contents/Resources/venv/lib" |
| 324 | + |
| 325 | +############# |
| 326 | +# BUILD DMG # |
| 327 | +############# |
| 328 | + |
| 329 | +# TODO: remove this after fixing .dmg generation |
| 330 | +# the dmg generation below fails on headless builds because you have to click |
| 331 | +# a button in a dialog granting finder some permissions from the apple script. |
| 332 | +# for now we include the .app |
| 333 | +mkdir -p ../../../../../dist |
| 334 | +cp -r "${APP_NAME}.app" ../../../../../dist/ |
| 335 | + |
| 336 | +# create a .dmg file from the .app file |
| 337 | +sudo ./create-osx-dmg.sh "${APP_NAME}.app" |
| 338 | + |
| 339 | +# create the dist dir for our result to be uploaded as an artifact |
| 340 | +mkdir -p ../../../../../dist |
| 341 | +cp "${APP_NAME}.dmg" ../../../../../dist/ |
| 342 | + |
| 343 | +popd # return to the buildozer dir in the sandbox root |
| 344 | +popd # return to the sandbox root dir |
| 345 | + |
| 346 | +####################### |
| 347 | +# OUTPUT VERSION INFO # |
| 348 | +####################### |
| 349 | + |
| 350 | +uname -a |
| 351 | +sw_vers |
| 352 | +which python2 |
| 353 | +python2 --version |
| 354 | +which python3 |
| 355 | +python3 --version |
| 356 | +${PYTHON_PATH} --version |
| 357 | +pwd |
| 358 | +echo $PATH |
| 359 | +ls -lah /Users/runner/Library/Python/3.7/bin |
| 360 | +ls -lah |
| 361 | +ls -lah dist |
| 362 | + |
| 363 | +################## |
| 364 | +# CLEANUP & EXIT # |
| 365 | +################## |
| 366 | + |
| 367 | +# exit cleanly |
| 368 | +exit 0 |
0 commit comments