diff --git a/python_appimage/appimage/relocate.py b/python_appimage/appimage/relocate.py index f4456d5..ef27f58 100644 --- a/python_appimage/appimage/relocate.py +++ b/python_appimage/appimage/relocate.py @@ -9,7 +9,7 @@ from ..utils.deps import EXCLUDELIST, PATCHELF, PREFIX, ensure_excludelist, \ from ..utils.fs import make_tree, copy_file, copy_tree, remove_file, remove_tree from ..utils.log import debug, log from ..utils.system import ldd, system -from ..utils.template import copy_template +from ..utils.template import copy_template, load_template __all__ = ["patch_binary", "relocate_python"] @@ -122,6 +122,10 @@ def relocate_python(python=None, appdir=None): target = PYTHON_BIN + '/' + PYTHON_X_Y copy_file(source, target, update=True) + relpath = os.path.relpath(target, APPDIR_BIN) + make_tree(APPDIR_BIN) + os.symlink(relpath, APPDIR_BIN + '/' + PYTHON_X_Y) + copy_tree(HOST_PKG, PYTHON_PKG) copy_tree(HOST_INC, PYTHON_INC) @@ -146,7 +150,6 @@ def relocate_python(python=None, appdir=None): shutil.copymode(pip_source, target) relpath = os.path.relpath(target, APPDIR_BIN) - make_tree(APPDIR_BIN) os.symlink(relpath, APPDIR_BIN + '/' + PIP_X_Y) @@ -161,20 +164,6 @@ def relocate_python(python=None, appdir=None): remove_tree(path) - # Wrap the Python executable - log('WRAP', '%s executable', PYTHON_X_Y) - - with open(PREFIX + '/data/python-wrapper.sh') as f: - text = f.read() - text = text.replace('{{PYTHON}}', PYTHON_X_Y) - - make_tree(APPDIR_BIN) - target = APPDIR_BIN + '/' + PYTHON_X_Y - with open(target, 'w') as f: - f.write(text) - shutil.copymode(PYTHON_BIN + '/' + PYTHON_X_Y, target) - - # Set or update symlinks to python pythons = glob.glob(APPDIR_BIN + '/python?.*') versions = [os.path.basename(python)[6:] for python in pythons] @@ -285,7 +274,8 @@ def relocate_python(python=None, appdir=None): apprun = APPDIR + '/AppRun' if not os.path.exists(apprun): log('INSTALL', 'AppRun') - entrypoint = '"${{APPDIR}}/usr/bin/python{:}" "$@"'.format(VERSION) + entrypoint_path = PREFIX + '/data/entrypoint.sh' + entrypoint = load_template(entrypoint_path, python=PYTHON_X_Y) _copy_template('apprun.sh', apprun, entrypoint=entrypoint) diff --git a/python_appimage/data/apprun.sh b/python_appimage/data/apprun.sh index eb5c31e..41f0518 100755 --- a/python_appimage/data/apprun.sh +++ b/python_appimage/data/apprun.sh @@ -5,5 +5,10 @@ self="$(readlink -f -- $0)" here="${self%/*}" APPDIR="${APPDIR:-${here}}" +# Export TCl/Tk +export TCL_LIBRARY="${APPDIR}/usr/share/tcltk/tcl{{ tcl-version }}" +export TK_LIBRARY="${APPDIR}/usr/share/tcltk/tk{{ tk-version }}" +export TKPATH="${TK_LIBRARY}" + # Call the entry point {{ entrypoint }} diff --git a/python_appimage/data/entrypoint.sh b/python_appimage/data/entrypoint.sh new file mode 100755 index 0000000..a064c99 --- /dev/null +++ b/python_appimage/data/entrypoint.sh @@ -0,0 +1,25 @@ +for opt in "$@" +do + [ "${opt:0:1}" != "-" ] && break + if [[ "${opt}" =~ "I" ]] || [[ "${opt}" =~ "E" ]]; then + # Environment variables are disabled ($PYTHONHOME). Let's run in a safe + # mode from the raw Python binary inside the AppImage + "$APPDIR/opt/{{ python }}/bin/{{ python }}" "$@" + exit "$?" + fi +done + +# Get the executable name, i.e. the AppImage or the python binary if running from an +# extracted image +executable="${APPDIR}/opt/{{ python }}/{{ python }}" +if [[ "${ARGV0}" =~ "/" ]]; then + executable="$(cd $(dirname ${ARGV0}) && pwd)/$(basename ${ARGV0})" +elif [[ "${ARGV0}" != "" ]]; then + executable=$(which "${ARGV0}") +fi + +# Wrap the call to Python in order to mimic a call from the source +# executable ($ARGV0), but potentially located outside of the Python +# install ($PYTHONHOME) +(PYTHONHOME="${APPDIR}/opt/{{ python }}" exec -a "${executable}" "$APPDIR/opt/{{ python }}/bin/{{ python }}" "$@") +exit "$?" diff --git a/python_appimage/data/python-wrapper.sh b/python_appimage/data/python-wrapper.sh deleted file mode 100755 index c3efc48..0000000 --- a/python_appimage/data/python-wrapper.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -SCRIPT="$(readlink -f -- $0)" -SCRIPTPATH="$(dirname $SCRIPT)" -APPDIR="${APPDIR:-$SCRIPTPATH/../..}" - -# Configure the environment -if [ -d "${APPDIR}/usr/share/tcltk" ]; then - export TCL_LIBRARY="$(ls -d ${APPDIR}/usr/share/tcltk/tcl* | tail -1)" - export TK_LIBRARY="$(ls -d ${APPDIR}/usr/share/tcltk/tk* | tail -1)" - export TKPATH="${TK_LIBRARY}" -fi - -# Resolve symlinks within the image -prefix="opt/{{PYTHON}}" -nickname="{{PYTHON}}" -executable="${APPDIR}/${prefix}/bin/${nickname}" - -if [ -L "${executable}" ]; then - nickname="$(basename $(readlink -f ${executable}))" -fi - -for opt in "$@" -do - [ "${opt:0:1}" != "-" ] && break - if [[ "${opt}" =~ "I" ]] || [[ "${opt}" =~ "E" ]]; then - # Environment variables are disabled ($PYTHONHOME). Let's run in a safe - # mode from the raw Python binary inside the AppImage - "$APPDIR/${prefix}/bin/${nickname}" "$@" - exit "$?" - fi -done - -# But don't resolve symlinks from outside! -if [[ "${ARGV0}" =~ "/" ]]; then - executable="$(cd $(dirname ${ARGV0}) && pwd)/$(basename ${ARGV0})" -elif [[ "${ARGV0}" != "" ]]; then - executable=$(which "${ARGV0}") -fi - -# Wrap the call to Python in order to mimic a call from the source -# executable ($ARGV0), but potentially located outside of the Python -# install ($PYTHONHOME) -(PYTHONHOME="${APPDIR}/${prefix}" exec -a "${executable}" "$APPDIR/${prefix}/bin/${nickname}" "$@") -exit "$?"