11#! /bin/bash
22
3- if [ -z " $DEBUG " ] || [ " $DEBUG " -eq " 0" ]; then
3+ if [[ -z " $DEBUG " ]] || [[ " $DEBUG " -eq " 0" ] ]; then
44 set -e
55else
66 set -ex
@@ -20,11 +20,18 @@ script=$(readlink -f $0)
2020exe_name=" $( basename ${APPIMAGE:- $script } ) "
2121BASEDIR=" ${APPDIR:- $(readlink -m $(dirname $script ))} "
2222
23+ prefix=" usr/python"
24+
25+
2326# Parse the CLI
2427show_usage () {
2528 echo " Usage: ${exe_name} --appdir <path to AppDir>"
2629 echo
27- echo " Bundle Python into an AppDir"
30+ echo " Bundle Python into an AppDir under \$ {APPDIR}/${prefix} . In addition"
31+ echo " extra packages can be bundled as well using \$ PIP_REQUIREMENTS."
32+ echo " Note that if an existing install of Python already exists then no new"
33+ echo " install of Python is done, i.e. \$ {PYTHON_SOURCE} and its related"
34+ echo " arguments are ignored. Yet, extra \$ PIP_REQUIREMENTS are installed."
2835 echo
2936 echo " Variables:"
3037 echo " NPROC=\" ${NPROC} \" "
@@ -54,7 +61,7 @@ show_usage () {
5461
5562APPDIR=
5663
57- while [ ! -z " $1 " ]; do
64+ while [[ ! -z " $1 " ] ]; do
5865 case " $1 " in
5966 --plugin-api-version)
6067 echo " 0"
@@ -78,7 +85,7 @@ while [ ! -z "$1" ]; do
7885 esac
7986done
8087
81- if [ -z " $APPDIR " ]; then
88+ if [[ -z " $APPDIR " ] ]; then
8289 show_usage
8390 exit 1
8491else
8895
8996
9097# Setup a temporary work space
91- if [ -z " ${PYTHON_BUILD_DIR} " ]; then
98+ if [[ -z " ${PYTHON_BUILD_DIR} " ] ]; then
9299 PYTHON_BUILD_DIR=$( mktemp -d)
93100
94101 atexit () {
@@ -101,48 +108,54 @@ else
101108 mkdir -p " ${PYTHON_BUILD_DIR} "
102109fi
103110
104- # check if the given sources are a local file or directory; if yes,
105- # "save" the full path. It might've been given relative to the current
106- # directory.
107- if [ -e " ${PYTHON_SOURCE} " ]; then
108- PYTHON_SOURCE=$( readlink -f " ${PYTHON_SOURCE} " )
109- fi
110-
111- cd " ${PYTHON_BUILD_DIR} "
112-
113111
112+ # Install Python from source, if not already in the AppDir
113+ set +e
114+ python=$( ls " ${APPDIR} /${prefix} /bin/python" ? " ." ? )
115+ set -e
114116
115- # Install Python from sources
116- source_file=$( basename " ${PYTHON_SOURCE} " )
117- if [[ " ${PYTHON_SOURCE} " == http* ]] || [[ " ${PYTHON_SOURCE} " == ftp* ]]; then
118- wget -c --no-check-certificate " ${PYTHON_SOURCE} "
117+ if [[ -x " ${python} " ]]; then
118+ echo " Found existing install under ${APPDIR} /${prefix} . Skipping Python build."
119119else
120- cp -r " ${PYTHON_SOURCE} " " ."
121- fi
122- if [[ " ${source_file} " == * .tgz ]] || [[ " ${source_file} " == * .tar.gz ]]; then
123- if [[ " ${source_file} " == * .tgz ]]; then
124- dirname=" ${source_file% .* } "
120+ # Check if the given sources are a local file or directory; if yes,
121+ # "save" the full path. It might've been given relative to the current
122+ # directory.
123+ if [[ -e " ${PYTHON_SOURCE} " ]]; then
124+ PYTHON_SOURCE=$( readlink -f " ${PYTHON_SOURCE} " )
125+ fi
126+
127+ cd " ${PYTHON_BUILD_DIR} "
128+ source_file=$( basename " ${PYTHON_SOURCE} " )
129+ if [[ " ${PYTHON_SOURCE} " == http* ]] || [[ " ${PYTHON_SOURCE} " == ftp* ]]; then
130+ wget -c --no-check-certificate " ${PYTHON_SOURCE} "
125131 else
126- dirname= " ${source_file % . * . * } "
132+ cp -r " ${PYTHON_SOURCE} " " . "
127133 fi
128- [[ -f $dirname ]] || tar -xzf " ${source_file} "
129- source_dir=" $dirname "
130- else
131- source_dir=" $source_file "
134+ if [[ " ${source_file} " == * .tgz ]] || [[ " ${source_file} " == * .tar.gz ]]; then
135+ if [[ " ${source_file} " == * .tgz ]]; then
136+ dirname=" ${source_file% .* } "
137+ else
138+ dirname=" ${source_file% .* .* } "
139+ fi
140+ [[ -f $dirname ]] || tar -xzf " ${source_file} "
141+ source_dir=" $dirname "
142+ else
143+ source_dir=" $source_file "
144+ fi
145+
146+ cd " ${source_dir} "
147+ ./configure ${PYTHON_CONFIG} " --with-ensurepip=install" " --prefix=/${prefix} " LDFLAGS=" ${LDFLAGS} -Wl,-rpath='" ' $$ORIGIN' " /../../lib'"
148+ HOME=" ${PYTHON_BUILD_DIR} " make -j" $NPROC " DESTDIR=" $APPDIR " install
132149fi
133150
134- prefix=" usr/python"
135- cd " ${source_dir} "
136- ./configure ${PYTHON_CONFIG} " --with-ensurepip=install" " --prefix=/${prefix} " LDFLAGS=" ${LDFLAGS} -Wl,-rpath='" ' $$ORIGIN' " /../../lib'"
137- HOME=" ${PYTHON_BUILD_DIR} " make -j" $NPROC " DESTDIR=" $APPDIR " install
151+ cd " ${APPDIR} /${prefix} /bin"
152+ PYTHON_X_Y=$( ls " python" ? " ." ? )
138153
139154
140155# Install any extra requirements with pip
141- if [ ! -z " ${PIP_REQUIREMENTS} " ]; then
142- cd " ${APPDIR} /${prefix} /bin"
143- pythons=( " python" ? " ." ? )
144- HOME=" ${PYTHON_BUILD_DIR} " PYTHONHOME=$( readlink -f ${PWD} /..) ./${pythons[0]} -m pip install ${PIP_OPTIONS} --upgrade pip
145- HOME=" ${PYTHON_BUILD_DIR} " PYTHONHOME=$( readlink -f ${PWD} /..) ./${pythons[0]} -m pip install ${PIP_OPTIONS} ${PIP_REQUIREMENTS}
156+ if [[ ! -z " ${PIP_REQUIREMENTS} " ]]; then
157+ HOME=" ${PYTHON_BUILD_DIR} " PYTHONHOME=$( readlink -f ${PWD} /..) ./${PYTHON_X_Y} -m pip install ${PIP_OPTIONS} --upgrade pip
158+ HOME=" ${PYTHON_BUILD_DIR} " PYTHONHOME=$( readlink -f ${PWD} /..) ./${PYTHON_X_Y} -m pip install ${PIP_OPTIONS} ${PIP_REQUIREMENTS}
146159fi
147160
148161
@@ -162,7 +175,7 @@ mkdir -p "$APPDIR/usr/bin"
162175cd " $APPDIR /usr/bin"
163176for python in $pythons
164177do
165- if [ ! -L " $python " ]; then
178+ if [[ ! -L " $python " ] ]; then
166179 strip " $APPDIR /${prefix} /bin/${python} "
167180 cp " ${BASEDIR} /share/python-wrapper.sh" " $python "
168181 sed -i " s|[{][{]PYTHON[}][}]|$python |g" " $python "
175188cd " $APPDIR /${prefix} /bin"
176189for exe in $( ls " ${APPDIR} /${prefix} /bin" * )
177190do
178- if [[ -f " $exe " ]] && [[ - x " $exe " ]]; then
191+ if [[ -x " $exe " ]]; then
179192 sed -i ' 1s|^#!.*\(python[0-9.]*\).*|#!/bin/sh\n"exec" "$(dirname $(readlink -f $\{0\}))/../../bin/\1" "$0" "$@"|' " $exe "
180193 fi
181194done
@@ -187,7 +200,7 @@ cp "$BASEDIR/share/sitecustomize.py" "$APPDIR"/${prefix}/lib/python*/site-packag
187200
188201# Patch binaries and install dependencies
189202excludelist=" ${BASEDIR} /share/excludelist"
190- if [ ! -f " ${excludelist} " ]; then
203+ if [[ ! -f " ${excludelist} " ] ]; then
191204 wget -cq --no-check-certificate " https://raw.githubusercontent.com/probonopd/AppImages/master/excludelist"
192205 excludelist=" excludelist"
193206fi
@@ -205,7 +218,7 @@ set +e
205218patchelf=$( command -v patchelf)
206219set -e
207220patchelf=" ${patchelf:- ${BASEDIR} / usr/ bin/ patchelf} "
208- if [ ! -f " ${patchelf} " ]; then
221+ if [[ ! -x " ${patchelf} " ] ]; then
209222 ARCH=" ${ARCH:- x86_64} "
210223 wget -cq https://github.com/niess/patchelf.appimage/releases/download/${ARCH} /patchelf-${ARCH} .AppImage
211224 patchelf=" $( pwd) /patchelf-${ARCH} .AppImage"
215228patch_binary () {
216229 local name=" $( basename $1 ) "
217230
218- if [ " ${name:: 3} " == " lib" ]; then
219- if [ ! -f " ${APPDIR} /usr/lib/${name} " ] && [ ! -L " ${APPDIR} /usr/lib/${name} " ]; then
231+ if [[ " ${name:: 3} " == " lib" ] ]; then
232+ if [[ ! -f " ${APPDIR} /usr/lib/${name} " ]] && [[ ! -L " ${APPDIR} /usr/lib/${name} " ] ]; then
220233 echo " Patching dependency ${name} "
221234 " ${patchelf} " --set-rpath ' $ORIGIN' " $1 "
222235 ln -s " $2 " /" $1 " " ${APPDIR} /usr/lib/${name} "
@@ -233,8 +246,8 @@ patch_binary() {
233246 for deps in $( ldd $1 ) ; do
234247 if [[ " ${deps:: 1} " == " /" ]] && [[ " ${deps} " != " ${APPDIR} " * ]]; then
235248 local lib=" $( basename ${deps} ) "
236- if [ ! -f " ${APPDIR} /usr/lib/${lib} " ]; then
237- if [ ! " $( is_excluded ${lib} ) " ]; then
249+ if [[ ! -f " ${APPDIR} /usr/lib/${lib} " ] ]; then
250+ if [[ ! " $( is_excluded ${lib} ) " ] ]; then
238251 echo " Installing dependency ${lib} "
239252 cp " ${deps} " " ${APPDIR} /usr/lib"
240253 " ${patchelf} " --set-rpath ' $ORIGIN' " ${APPDIR} /usr/lib/${lib} "
@@ -246,11 +259,10 @@ patch_binary() {
246259}
247260
248261cd " $APPDIR /${prefix} /bin"
249- [ -f python3 ] && ln -fs python3 python
250- python=$( ls " python" ? " ." ? )
262+ [[ -f python3 ]] && ln -fs python3 python
251263mkdir -p " ${APPDIR} /usr/lib"
252- cd " ${APPDIR} /${prefix} /lib/${python } "
253- relpath=" ../../${prefix} /lib/${python } "
264+ cd " ${APPDIR} /${prefix} /lib/${PYTHON_X_Y } "
265+ relpath=" ../../${prefix} /lib/${PYTHON_X_Y } "
254266find " lib-dynload" -name ' *.so' -type f | while read file; do patch_binary " ${file} " " ${relpath} " ; done
255267find " site-packages" -name ' *.so' -type f | while read file; do patch_binary " ${file} " " ${relpath} " ; done
256268find " site-packages" -name ' lib*.so*' -type f | while read file; do patch_binary " ${file} " " ${relpath} " ; done
0 commit comments