source: orange/install-scripts/mac/build-osx-app-template.sh @ 11637:0635b42377c2

Revision 11637:0635b42377c2, 9.8 KB checked in by Ales Erjavec <ales.erjavec@…>, 9 months ago (diff)

Changes to osx application template build script.

  • Property exe set to *
Line 
1#!/bin/bash -e
2#
3# Create (build) an Orange application bundle template
4#
5# example usage:
6#
7#   $ build-osx-app-template.sh $HOME/Orange.app
8#
9# Prerequisites:
10#     a working gcc compiler toolchain
11#     a working gfortran compiler on PATH
12
13
14function print_usage () {
15echo 'build-osx-app-template.sh [-t] [-k] some_path/Orange.app
16
17Build an Orange application template from scratch.
18This will download and build all requirements (Python, Qt4, ...) for a
19standalone .app distribution.
20
21Warning: This will take a lot of time.
22
23Options:
24    -t --build-temp DIR   A temporary build directory.
25    -k --keep-temp        Do not delete the temp directory after build.
26    -h --help             Print this help.
27'
28}
29
30while [[ ${1:0:1} = "-" ]]; do
31    case $1 in
32        -t|--build-temp)
33            BUILD_TEMP=$2
34            shift 2
35            ;;
36        -k|--keep-temp)
37            KEEP_TEMP=1
38            shift 1
39            ;;
40        -h|--help)
41            print_usage
42            exit 0
43            ;;
44        -*)
45            echo "Unknown option $1" >&2
46            print_usage
47            exit 1
48            ;;
49    esac
50done
51
52
53if [[ $BUILD_TEMP ]]; then
54    mkdir -p "$BUILD_TEMP"
55else
56    BUILD_TEMP=$(mktemp -d -t build-template)
57fi
58
59APP=$1
60
61if [[ ! $APP ]]; then
62    echo "Target application path must be specified" >&2
63    print_usage
64    exit 1
65fi
66
67mkdir -p "$APP"
68
69# Convert to absolute path
70APP=$(cd "$APP"; pwd)
71
72# Get absolute path to the bundle-lite template
73SCRIPT_DIR_NAME=$(dirname "$0")
74# Convert to absolute path
75SCRIPT_DIR_NAME=$(cd "$SCRIPT_DIR_NAME"; pwd)
76BUNDLE_LITE=$SCRIPT_DIR_NAME/bundle-lite/Orange.app
77
78
79# Versions of included 3rd party software
80
81PYTHON_VER=2.7.5
82PIP_VER=1.3.1
83DISTRIBUTE_VER=0.6.49
84NUMPY_VER=1.7.1
85SCIPY_VER=0.12.0
86QT_VER=4.7.4
87SIP_VER=4.14.6
88PYQT_VER=4.10.1
89PYQWT_VER=5.2.0
90
91# Number of make jobs
92MAKE_JOBS=${MAKE_JOBS:-$(sysctl -n hw.physicalcpu)}
93
94PYTHON=$APP/Contents/MacOS/python
95EASY_INSTALL=$APP/Contents/MacOS/easy_install
96PIP=$APP/Contents/MacOS/pip
97
98export MACOSX_DEPLOYMENT_TARGET=10.5
99
100SDK=/Developer/SDKs/MacOSX$MACOSX_DEPLOYMENT_TARGET.sdk
101
102
103function create_template {
104    # Create a minimal .app template with the expected dir structure
105    # Info.plist and icons.
106
107    mkdir -p "$APP"
108    mkdir -p "$APP"/Contents/MacOS
109    mkdir -p "$APP"/Contents/Resources
110
111    # Copy icons and Info.plist
112    cp "$BUNDLE_LITE"/Contents/Resources/* "$APP"/Contents/Resources
113    cp "$BUNDLE_LITE"/Contents/Info.plist "$APP"/Contents/Info.plist
114
115    cp "$BUNDLE_LITE"/Contents/PkgInfo $APP/Contents/PkgInfo
116
117    cat <<-'EOF' > "$APP"/Contents/MacOS/ENV
118        # Create an environment for running python from the bundle
119        # Should be run as "source ENV"
120
121        BUNDLE_DIR=`dirname "$0"`/../
122        BUNDLE_DIR=`perl -MCwd=realpath -e 'print realpath($ARGV[0])' "$BUNDLE_DIR"`/
123        FRAMEWORKS_DIR="$BUNDLE_DIR"Frameworks/
124        RESOURCES_DIR="$BUNDLE_DIR"Resources/
125
126        PYVERSION="2.7"
127
128        PYTHONEXECUTABLE="$FRAMEWORKS_DIR"Python.framework/Resources/Python.app/Contents/MacOS/Python
129        PYTHONHOME="$FRAMEWORKS_DIR"Python.framework/Versions/"$PYVERSION"/
130
131        DYLD_FRAMEWORK_PATH="$FRAMEWORKS_DIR"${DYLD_FRAMEWORK_PATH:+:$DYLD_FRAMEWORK_PATH}
132
133        export PYTHONEXECUTABLE
134        export PYTHONHOME
135
136        export DYLD_FRAMEWORK_PATH
137
138        # Some non framework libraries are put in $FRAMEWORKS_DIR by machlib standalone
139        export DYLD_LIBRARY_PATH="$FRAMEWORKS_DIR"${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}
140EOF
141
142}
143
144function install_python() {
145    download_and_extract "http://www.python.org/ftp/python/$PYTHON_VER/Python-$PYTHON_VER.tgz"
146
147    pushd Python-$PYTHON_VER
148
149    # _hashlib import fails with  Symbol not found: _EVP_MD_CTX_md
150    # The 10.5 sdk's libssl does not define it (even though it is v 0.9.7)
151    patch setup.py -i - <<-'EOF'
152        834c834
153        <         min_openssl_ver = 0x00907000
154        ---
155        >         min_openssl_ver = 0x00908000
156EOF
157
158    ./configure --enable-framework="$APP"/Contents/Frameworks \
159                --prefix="$APP"/Contents/Resources \
160                --with-universal-archs=intel \
161                --enable-universalsdk="$SDK"
162
163    make -j $MAKE_JOBS
164
165    # We don't want to install IDLE.app, Python Launcher.app, in /Applications
166    # on the build system.
167    make install PYTHONAPPSDIR=$(pwd)
168
169    popd
170
171    # PythonAppStart will be used for starting the application GUI.
172    # This needs to be symlinked here for Desktop services to read the app's
173    # Info.plist and not the contained Python.app's
174    ln -fs ../Frameworks/Python.framework/Resources/Python.app/Contents/MacOS/Python "$APP"/Contents/MacOS/PythonAppStart
175    ln -fs ../Frameworks/Python.framework/Resources/Python.app "$APP"/Contents/Resources/Python.app
176
177    cat <<-'EOF' > "$APP"/Contents/MacOS/python
178        #!/bin/bash
179
180        DIRNAME=$(dirname "$0")
181
182        # Set the proper env variables
183        source "$DIRNAME"/ENV
184
185        exec -a "$0" "$PYTHONEXECUTABLE" "$@"
186EOF
187
188    chmod +x "$APP"/Contents/MacOS/python
189
190    "$PYTHON" -c"import sys, hashlib"
191
192}
193
194function install_pip() {
195    download_and_extract "https://pypi.python.org/packages/source/p/pip/pip-$PIP_VER.tar.gz"
196
197    pushd pip-$PIP_VER
198
199    "$PYTHON" setup.py install
200    create_shell_start_script pip
201
202    "$PIP" --version
203
204    popd
205}
206
207function install_distribute() {
208    download_and_extract "https://pypi.python.org/packages/source/d/distribute/distribute-$DISTRIBUTE_VER.tar.gz"
209
210    pushd distribute-$DISTRIBUTE_VER
211
212    "$PYTHON" setup.py install
213    create_shell_start_script easy_install
214
215    "$EASY_INSTALL" --version
216
217    popd
218}
219
220function install_ipython {
221    # install with easy_install (does not work with pip)
222    "$EASY_INSTALL" ipython
223    create_shell_start_script ipython
224}
225
226function install_qt4 {
227    QT_VER_SHORT=${QT_VER%%\.[0-9]}
228
229    # 4.8.* (4.8 does not compile for x86_64 using 10.5 SDK)
230    #download_and_extract "http://download.qt-project.org/official_releases/qt/$QT_VER_SHORT/$QT_VER/qt-everywhere-opensource-src-$QT_VER.tar.gz"
231
232    # 4.7 or older
233    download_and_extract "http://download.qt-project.org/archive/qt/$QT_VER_SHORT/qt-everywhere-opensource-src-$QT_VER.tar.gz"
234
235    pushd qt-everywhere-opensource-src-$QT_VER
236
237    yes yes | ./configure -prefix "$APP"/Contents/Resources/Qt4 \
238                -libdir "$APP"/Contents/Frameworks \
239                -framework \
240                -release \
241                -opensource \
242                -no-qt3support \
243                -arch x86 -arch x86_64 \
244                -no-sql-psql \
245                -no-sql-ibase \
246                -no-sql-mysql \
247                -no-sql-odbc \
248                -no-sql-sqlite \
249                -no-sql-sqlite2 \
250                -nomake examples \
251                -nomake demos \
252                -nomake docs \
253                -nomake translations \
254                -sdk "$SDK"
255
256    make -j $MAKE_JOBS
257    make install
258
259    # Register plugins with Qt.
260    cat <<-EOF > "$APP"/Contents/Resources/qt.conf
261        [Paths]
262        Plugins = Resources/Qt4/plugins
263EOF
264
265    # In case the Python executable is invoked directly (not through
266    # Contents/MacOS/python) we also want it to find the plugins.
267    cat <<-EOF > "$APP"/Contents/Frameworks/Python.framework/Resources/Python.app/Contents/Resources/qt.conf
268        [Paths]
269        Plugins = ../../../../../Resources/Qt4/plugins
270EOF
271
272    popd
273}
274
275function install_sip {
276    download_and_extract "http://sourceforge.net/projects/pyqt/files/sip/sip-$SIP_VER/sip-$SIP_VER.tar.gz"
277    pushd sip-$SIP_VER
278
279    "$PYTHON" configure.py  --arch i386 --arch x86_64 --sdk "$SDK"
280
281    make -j $MAKE_JOBS
282    make install
283
284    "$PYTHON" -c"import sip"
285
286    popd
287
288}
289
290function install_pyqt4 {
291    download_and_extract "http://sourceforge.net/projects/pyqt/files/PyQt4/PyQt-$PYQT_VER/PyQt-mac-gpl-$PYQT_VER.tar.gz"
292    pushd PyQt-mac-gpl-$PYQT_VER
293
294    yes yes | "$PYTHON" configure.py --qmake "$APP"/Contents/Resources/Qt4/bin/qmake
295
296    make -j $MAKE_JOBS
297    make install
298
299    "$PYTHON" -c"from PyQt4 import QtGui, QtWebKit, QtSvg, QtNetwork"
300
301    popd
302}
303
304function install_pyqwt5 {
305    download_and_extract "http://sourceforge.net/projects/pyqwt/files/pyqwt5/PyQwt-$PYQWT_VER/PyQwt-$PYQWT_VER.tar.gz"
306
307    pushd PyQwt-$PYQWT_VER/configure
308
309    # configure.py fails (with ld: library not found for -lcrt1.10.5.o) trying to
310    # build static libraries
311    export CPPFLAGS="--shared"
312
313    PYQWT_VER_SHORT=${PYQWT_VER%%\.[0-9]}
314
315    "$PYTHON" configure.py -Q ../qwt-$PYQWT_VER_SHORT \
316                        --extra-cflags="-arch i386 -arch x86_64" \
317                        --extra-cxxflags="-arch i386 -arch x86_64" \
318                        --extra-lflags="-arch i386 -arch x86_64"
319    make -j $MAKE_JOBS
320    make install
321
322    unset CPPFLAGS
323
324    "$PYTHON" -c"import PyQt4.Qwt5"
325
326    popd
327}
328
329function install_numpy {
330    "$PIP" install numpy==$NUMPY_VER
331
332    "$PYTHON" -c"import numpy"
333}
334
335function install_scipy {
336    # This is tricky (req gfortran)
337    "$PIP" install scipy==$SCIPY_VER
338
339    "$PYTHON" -c"import scipy"
340}
341
342function download_and_extract() {
343    # Usage: download_and_extract http://example/source.tar.gz
344    #
345    # Download the specified .tar source package and extract it in the current dir
346    # If the source package is already present only extract it
347
348    URL=$1
349    if [[ ! $URL ]]; then
350        echo "An url expected"
351        exit 1
352    fi
353
354    SOURCE_TAR=$(basename "$URL")
355
356    if [[ ! -e $SOURCE_TAR ]]; then
357        echo "Downloading $SOURCE_TAR"
358        curl --fail -L --max-redirs 3 "$URL" -o "$SOURCE_TAR".part
359        mv "$SOURCE_TAR".part "$SOURCE_TAR"
360    fi
361    tar -xzf "$SOURCE_TAR"
362}
363
364
365function create_shell_start_script() {
366    # Usage: create_shell_start_script pip
367    #
368    # create a start script for the specified script in $APP/Contents/MacOS
369
370    SCRIPT=$1
371
372    cat <<-'EOF' > "$APP"/Contents/MacOS/"$SCRIPT"
373        #!/bin/bash
374
375        DIRNAME=$(dirname "$0")
376        NAME=$(basename "$0")
377
378        # Set the proper env variables
379        source "$DIRNAME"/ENV
380
381        exec -a "$0" "$DIRNAME"/python "$FRAMEWORKS_DIR"/Python.framework/Versions/Current/bin/"$NAME" "$@"
382EOF
383
384    chmod +x "$APP"/Contents/MacOS/"$SCRIPT"
385}
386
387function cleanup {
388    # Cleanup the application bundle by removing unnecesary files.
389    find "$APP"/Contents/ \( -name '*~' -or -name '*.bak' -or -name '*.pyc' -or -name '*.pyo' \) -delete
390
391    find "$APP"/Contents/Frameworks -name '*_debug*' -delete
392
393    find "$APP"/Contents/Frameworks -name '*.la' -delete
394    find "$APP"/Contents/Frameworks -name '*.a' -delete
395    find "$APP"/Contents/Frameworks -name '*.prl' -delete
396}
397
398function make_standalone {
399    "$PIP" install macholib
400    "$PYTHON" -m macholib standalone $APP
401    yes y | "$PIP" uninstall altgraph
402    yes y | "$PIP" uninstall macholib
403}
404
405pushd $BUILD_TEMP
406
407echo "Building template in $BUILD_TEMP"
408echo
409
410create_template
411
412install_python
413
414install_distribute
415
416install_pip
417
418install_numpy
419
420install_scipy
421
422install_qt4
423
424install_sip
425
426install_pyqt4
427
428install_pyqwt5
429
430install_ipython
431
432make_standalone
433
434cleanup
435
436popd
437
438if [[ ! $KEEP_TEMP ]]; then
439    rm -rf $BUILD_TEMP
440fi
Note: See TracBrowser for help on using the repository browser.