Skip to content

Instantly share code, notes, and snippets.

@colebrumley
Created January 6, 2017 15:47
Show Gist options
  • Save colebrumley/b4288a4211b06e8da2f2b94cd5368c38 to your computer and use it in GitHub Desktop.
Save colebrumley/b4288a4211b06e8da2f2b94cd5368c38 to your computer and use it in GitHub Desktop.
PyPy+Makeself standalone installer
#!/bin/bash -ex
# WHAT THIS IS
# This script creates a standalone "installer" for a pip-enabled Python package
# using Makeself. What is different about this script versus native Makeself is
# that each installer includes a dedicated Python installation (using PyPy) and
# wrapper scripts to make invocation transparent. Python is not required on the
# host, and changes to the host's Python installation will not affect apps
# installed using this script.
# REQUIREMENTS
# git, openssl, wget, and makeself are expected.
# SETTINGS
######################
PYPY_VERSION=5.6.0
PYPY_DIRECTORY=pypy
PIP_PACKAGE=$1
# Sometimes the binary name is not the same as the package name from pip
EXE_NAME=$2
# Where to put this app's Python
TARGET_LIB_DIRECTORY="${3:-/usr/lib/pynary}"
TARGET_BIN_DIRECTORY="${4:-/usr/bin}"
######################
bail(){ >&2 echo "${@}"; exit 1; }
cleanup() { rm -Rf "./$PYPY_DIRECTORY" ./*.bz2; }
get_pypy() {
local pypy_version=$1
local pypy_dirname=$2
local pypy_filename="pypy2-v${pypy_version}-linux64"
local pypy_dl_url="https://bitbucket.org/pypy/pypy/downloads/${pypy_filename}.tar.bz2"
wget -O- $pypy_dl_url | tar -xjf -
mv -n $pypy_filename $pypy_dirname
mkdir -p ${pypy_dirname}/{lib,bin}
# Lib fix if applicable
[[ -f /lib64/libncurses.so.5.9 ]] && \
cp /lib64/libncurses.so.5.9 ${pypy_dirname}/lib/libtinfo.so.5
cat > ${pypy_dirname}/bin/python <<-'EOF'
#!/bin/sh
LD_LIBRARY_PATH="$(dirname "$0")/../lib" exec "$(dirname "$0")/pypy" -E -s "${@}"
EOF
chmod +x ${pypy_dirname}/bin/python
# Install pip to make things easier later
${pypy_dirname}/bin/python -m ensurepip
}
mkself(){
local pkg=$1
cat > "$PYPY_DIRECTORY/bin/setup.sh" <<-'EOF'
#!/bin/bash
APP_NAME="$1"
EXE_NAME="$2"
LIBDIR="${3:-/usr/lib/pynary}/$APP_NAME"
BINDIR="${4:-/usr/bin}"
[ -d "$LIBDIR" ] || mkdir -p "$LIBDIR"
cp -r ./* "${LIBDIR}/"
cat > "${BINDIR}/${EXE_NAME}" <<EOD
#!/bin/sh
exec "$LIBDIR/bin/python" "$LIBDIR/bin/$EXE_NAME" "\$@"
EOD
chmod +x "${BINDIR}/${EXE_NAME}"
EOF
chmod +x "$PYPY_DIRECTORY/bin/setup.sh"
makeself "$PYPY_DIRECTORY" "$pkg.installer" "PyPy+Makeself installer for $PIP_PACKAGE" \
./bin/setup.sh "$pkg" "$EXE_NAME" "$TARGET_LIB_DIRECTORY" "$TARGET_BIN_DIRECTORY"
}
# Housekeeping
[[ "$PIP_PACKAGE" == "" ]] && bail No pip package defined
cd "$(dirname "$0")"
trap 'cleanup' EXIT
[[ -d "$PYPY_DIRECTORY" ]] || get_pypy "$PYPY_VERSION" "$PYPY_DIRECTORY"
LD_LIBRARY_PATH=${PYPY_DIRECTORY}/lib \
${PYPY_DIRECTORY}/bin/python -m pip --no-cache-dir install "$PIP_PACKAGE"
mkself $1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment