modify ruby-build for Python and import into pyenv as default plugin.

This commit is contained in:
Yamashita Yuu 2012-08-31 15:32:23 +09:00
parent 2457419b4a
commit 7953f573c6
13 changed files with 756 additions and 1 deletions

2
.gitignore vendored
View file

@ -1,4 +1,4 @@
/plugins #/plugins
/shims /shims
/version /version
/versions /versions

View file

@ -0,0 +1,21 @@
Copyright (c) 2011 Sam Stephenson
Copyright (c) 2012 Yamashita, Yuu
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,78 @@
#!/usr/bin/env bash
set -e
[ -n "$PYENV_DEBUG" ] && set -x
# Provide pyenv completions
if [ "$1" = "--complete" ]; then
exec python-build --definitions
fi
if [ -z "$PYENV_ROOT" ]; then
PYENV_ROOT="${HOME}/.pyenv"
fi
# Load shared library functions
eval "$(python-build --lib)"
usage() {
{ echo "usage: pyenv install [-k|--keep] [-v|--verbose] VERSION"
echo " pyenv install [-k|--keep] [-v|--verbose] /path/to/definition"
echo " pyenv install -l|--list"
echo
echo " -l/--list List all available versions"
echo " -k/--keep Keep source tree in \$PYENV_BUILD_ROOT after installation"
echo " (defaults to ${PYENV_ROOT}/sources)"
echo " -v/--verbose Verbose mode: print compilation status to stdout"
echo
} >&2
[ -z "$1" ] || exit "$1"
}
unset KEEP
unset VERBOSE
parse_options "$@"
for option in "${OPTIONS[@]}"; do
case "$option" in
"h" | "help" )
usage 0
;;
"l" | "list" )
echo "Available versions:"
python-build --definitions | sed 's/^/ /'
exit
;;
"k" | "keep" )
[ -n "${PYENV_BUILD_ROOT}" ] || PYENV_BUILD_ROOT="${PYENV_ROOT}/sources"
;;
"v" | "verbose" )
VERBOSE="-v"
;;
"version" )
exec python-build --version
;;
* )
usage 1
;;
esac
done
DEFINITION="${ARGUMENTS[0]}"
[ -n "$DEFINITION" ] || usage 1
for script in $(pyenv-hooks install); do
source "$script"
done
VERSION_NAME="${DEFINITION##*/}"
PREFIX="${PYENV_ROOT}/versions/${VERSION_NAME}"
# If PYENV_BUILD_ROOT is set, then always pass keep options to python-build
if [ -n "${PYENV_BUILD_ROOT}" ]; then
export PYTHON_BUILD_BUILD_PATH="${PYENV_BUILD_ROOT}/${VERSION_NAME}"
KEEP="-k"
fi
python-build $KEEP $VERBOSE "$DEFINITION" "$PREFIX"
pyenv rehash

View file

@ -0,0 +1,55 @@
#!/usr/bin/env bash
set -e
# Provide pyenv completions
if [ "$1" = "--complete" ]; then
exec pyenv versions --bare
fi
if [ -z "$PYENV_ROOT" ]; then
PYENV_ROOT="${HOME}/.pyenv"
fi
unset FORCE
if [ "$1" = "-f" ]; then
FORCE=true
shift
fi
DEFINITION="$1"
case "$DEFINITION" in
"" | -* )
{ echo "usage: pyenv uninstall [-f] VERSION"
echo
echo " -f Attempt to remove the specified version without prompting"
echo " for confirmation. If the version does not exist, do not"
echo " display an error message."
echo
echo "Installed versions:"
pyenv versions --bare | sed 's/^/ /'
echo
} >&2
exit 1
;;
esac
VERSION_NAME="${DEFINITION##*/}"
PREFIX="${PYENV_ROOT}/versions/${VERSION_NAME}"
if [ -z "$FORCE" ]; then
if [ ! -d "$PREFIX" ]; then
echo "pyenv: version \`$VERSION_NAME' not installed" >&2
exit 1
fi
read -p "pyenv: remove $PREFIX? "
case "$REPLY" in
y* | Y* ) ;;
* ) exit 1 ;;
esac
fi
if [ -d "$PREFIX" ]; then
rm -rf "$PREFIX"
pyenv rehash
fi

View file

@ -0,0 +1,527 @@
#!/usr/bin/env bash
PYTHON_BUILD_VERSION="20120815"
set -E
exec 3<&2 # preserve original stderr at fd 3
lib() {
parse_options() {
OPTIONS=()
ARGUMENTS=()
local arg option index
for arg in "$@"; do
if [ "${arg:0:1}" = "-" ]; then
if [ "${arg:1:1}" = "-" ]; then
OPTIONS[${#OPTIONS[*]}]="${arg:2}"
else
index=1
while option="${arg:$index:1}"; do
[ -n "$option" ] || break
OPTIONS[${#OPTIONS[*]}]="$option"
index=$(($index+1))
done
fi
else
ARGUMENTS[${#ARGUMENTS[*]}]="$arg"
fi
done
}
if [ "$1" == "--$FUNCNAME" ]; then
declare -f "$FUNCNAME"
echo "$FUNCNAME \"\$1\";"
exit
fi
}
lib "$1"
resolve_link() {
$(type -p greadlink readlink | head -1) "$1"
}
abs_dirname() {
local cwd="$(pwd)"
local path="$1"
while [ -n "$path" ]; do
cd "${path%/*}"
local name="${path##*/}"
path="$(resolve_link "$name" || true)"
done
pwd
cd "$cwd"
}
build_failed() {
{ echo
echo "BUILD FAILED"
echo
if ! rmdir "${BUILD_PATH}" 2>/dev/null; then
echo "Inspect or clean up the working tree at ${BUILD_PATH}"
if file_is_not_empty "$LOG_PATH"; then
echo "Results logged to ${LOG_PATH}"
echo
echo "Last 10 log lines:"
tail -n 10 "$LOG_PATH"
fi
fi
} >&3
exit 1
}
file_is_not_empty() {
local filename="$1"
local line_count="$(wc -l "$filename" 2>/dev/null || true)"
if [ -n "$line_count" ]; then
words=( $line_count )
[ "${words[0]}" -gt 0 ]
else
return 1
fi
}
install_package() {
install_package_using "tarball" 1 $*
}
install_git() {
install_package_using "git" 2 $*
}
install_jar() {
install_package_using "jar" 1 $*
}
install_package_using() {
local package_type="$1"
local package_type_nargs="$2"
local package_name="$3"
shift 3
pushd "$BUILD_PATH" >&4
"fetch_${package_type}" "$package_name" $*
shift $(($package_type_nargs))
make_package "$package_name" $*
popd >&4
echo "Installed ${package_name} to ${PREFIX_PATH}" >&2
}
make_package() {
local package_name="$1"
shift
pushd "$package_name" >&4
before_install_package "$package_name"
build_package "$package_name" $*
after_install_package "$package_name"
fix_directory_permissions
popd >&4
}
fetch_url() {
if type curl &>/dev/null; then
curl -L "$@"
elif type wget &>/dev/null; then
wget -O- "$@"
else
echo "error: please install \`curl\` or \`wget\` and try again" >&2
exit 1
fi
}
fetch_tarball() {
local package_name="$1"
local package_url="$2"
echo "Downloading ${package_url}..." >&2
{ fetch_url "$package_url" > "${package_name}.tar"
tar xvf "${package_name}.tar"
} >&4 2>&1
}
fetch_git() {
local package_name="$1"
local git_url="$2"
local git_ref="$3"
echo "Cloning ${git_url}..." >&2
if type git &>/dev/null; then
git clone --depth 1 --branch "$git_ref" "$git_url" "${package_name}" >&4 2>&1
else
echo "error: please install \`git\` and try again" >&2
exit 1
fi
}
fetch_jar() {
local package_name="$1"
local package_url="$2"
echo "Downloading ${package_url}..." >&2
{ fetch_url "$package_url" > "${package_name}.jar"
$JAVA -jar ${package_name}.jar -s -d ${package_name}
} >&4 2>&1
}
build_package() {
local package_name="$1"
shift
if [ "$#" -eq 0 ]; then
local commands="standard"
else
local commands="$*"
fi
echo "Installing ${package_name}..." >&2
for command in $commands; do
"build_package_${command}" "${package_name}"
done
if [ ! -f "$PYTHON_BIN" ]; then
for python in ${PREFIX_PATH}/bin/python*; do
if basename "$python" | grep '^python[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null; then
{
cd ${PREFIX_PATH}/bin
ln -fs "$(basename $python)" python
}
break
fi
done
fi
}
build_package_standard() {
local package_name="$1"
if [ "${MAKEOPTS+defined}" ]; then
MAKE_OPTS="$MAKEOPTS"
elif [ -z "${MAKE_OPTS+defined}" ]; then
MAKE_OPTS="-j 2"
fi
{ ./configure --prefix="$PREFIX_PATH" $CONFIGURE_OPTS
make $MAKE_OPTS
make install
} >&4 2>&1
}
build_package_autoconf() {
{ autoconf
} >&4 2>&1
}
build_package_python() {
local package_name="$1"
{
"$PYTHON_BIN" setup.py install
} >&4 2>&1
}
build_package_jython() {
{
build_package_copy
cd "${PREFIX_PATH}/bin"
ln -fs jython python
}
}
build_package_pypy() {
{
mkdir -p "$PREFIX_PATH"
cp -R . "$PREFIX_PATH"
cd "${PREFIX_PATH}/bin"
ln -fs pypy python
}
}
build_package_copy() {
mkdir -p "$PREFIX_PATH"
cp -R . "$PREFIX_PATH"
}
bild_package_noop() {
echo "Nothing to do."
}
before_install_package() {
local stub=1
}
after_install_package() {
local stub=1
}
fix_directory_permissions() {
# Ensure installed directories are not world-writable to avoid Bundler warnings
find "$PREFIX_PATH" -type d -exec chmod go-w {} \;
}
require_gcc() {
local gcc="$(locate_gcc || true)"
if [ -z "$gcc" ]; then
local esc=$'\033'
{ echo
echo "${esc}[1mERROR${esc}[0m: This package must be compiled with GCC, but python-build couldn't"
echo "find a suitable \`gcc\` executable on your system. Please install GCC"
echo "and try again."
echo
if [ "$(uname -s)" = "Darwin" ]; then
echo "${esc}[1mDETAILS${esc}[0m: Apple no longer includes the official GCC compiler with Xcode"
echo "as of version 4.2. Instead, the \`gcc\` executable is a symlink to"
echo "\`llvm-gcc\`, a modified version of GCC which outputs LLVM bytecode."
echo
echo "For most programs the \`llvm-gcc\` compiler works fine. However,"
echo "versions of Python older than 1.9.3-p125 are incompatible with"
echo "\`llvm-gcc\`. To build older versions of Python you must have the official"
echo "GCC compiler installed on your system."
echo
echo "${esc}[1mTO FIX THE PROBLEM${esc}[0m: Install the official GCC compiler using these"
echo "packages: ${esc}[4mhttps://github.com/kennethreitz/osx-gcc-installer/downloads${esc}[0m"
echo
echo "You will need to install the official GCC compiler to build older"
echo "versions of Python even if you have installed Apple's Command Line Tools"
echo "for Xcode package. The Command Line Tools for Xcode package only"
echo "includes \`llvm-gcc\`."
fi
} >&3
return 1
fi
export CC="$gcc"
}
locate_gcc() {
local gcc gccs
IFS=: gccs=($(gccs_in_path))
verify_gcc "$CC" ||
verify_gcc "$(command -v gcc || true)" || {
for gcc in "${gccs[@]}"; do
verify_gcc "$gcc" && break || true
done
}
return 1
}
gccs_in_path() {
local gcc path paths
local gccs=()
IFS=: paths=($PATH)
shopt -s nullglob
for path in "${paths[@]}"; do
for gcc in "$path"/gcc-*; do
gccs["${#gccs[@]}"]="$gcc"
done
done
shopt -u nullglob
printf :%s "${gccs[@]}"
}
verify_gcc() {
local gcc="$1"
if [ -z "$gcc" ]; then
return 1
fi
local version="$("$gcc" --version || true)"
if [ -z "$version" ]; then
return 1
fi
if echo "$version" | grep LLVM >/dev/null; then
return 1
fi
echo "$gcc"
}
require_java() {
local java="$(locate_java || true)"
if [ -z "$java" ]; then
local esc=$'\033'
{ echo
echo "${esc}[1mERROR${esc}[0m: This package must be installed with java, but python-build couldn't"
echo "find a suitable \`java\` executable on your system. Please install Java"
echo "and try again."
echo
} >&3
return 1
fi
export JAVA="$java"
}
locate_java() {
local java javas
IFS=: javas=($(javas_in_path))
verify_java "$JAVA" ||
verify_java "$(command -v java || true)" || {
for java in "${javas[@]}"; do
verify_java "$java" && break || true
done
}
return 1
}
javas_in_path() {
local java path paths
local javas=()
IFS=: paths=($PATH)
shopt -s nullglob
for path in "${paths[@]}"; do
local java="$path"/java
if [ -x "$java" ]; then
javas["${#javas[@]}"]="$java"
fi
done
shopt -u nullglob
printf :%s "${javas[@]}"
}
verify_java() {
local java="$1"
if [ -z "$java" ]; then
return 1
fi
if [ ! -x "$java" ]; then
return 1
fi
echo "$java"
}
version() {
echo "python-build ${PYTHON_BUILD_VERSION}"
}
usage() {
{ version
echo "usage: python-build [-k|--keep] [-v|--verbose] definition prefix"
echo " python-build --definitions"
} >&2
if [ -z "$1" ]; then
exit 1
fi
}
list_definitions() {
{ for definition in "${PYTHON_BUILD_ROOT}/share/python-build/"*; do
echo "${definition##*/}"
done
} | sort
}
unset VERBOSE
unset KEEP_BUILD_PATH
PYTHON_BUILD_ROOT="$(abs_dirname "$0")/.."
parse_options "$@"
for option in "${OPTIONS[@]}"; do
case "$option" in
"h" | "help" )
usage without_exiting
{ echo
echo " -k/--keep Do not remove source tree after installation"
echo " -v/--verbose Verbose mode: print compilation status to stdout"
echo " --definitions List all built-in definitions"
echo
} >&2
exit 0
;;
"definitions" )
list_definitions
exit 0
;;
"k" | "keep" )
KEEP_BUILD_PATH=true
;;
"v" | "verbose" )
VERBOSE=true
;;
"version" )
version
exit 0
;;
esac
done
DEFINITION_PATH="${ARGUMENTS[0]}"
if [ -z "$DEFINITION_PATH" ]; then
usage
elif [ ! -e "$DEFINITION_PATH" ]; then
BUILTIN_DEFINITION_PATH="${PYTHON_BUILD_ROOT}/share/python-build/${DEFINITION_PATH}"
if [ -e "$BUILTIN_DEFINITION_PATH" ]; then
DEFINITION_PATH="$BUILTIN_DEFINITION_PATH"
else
echo "python-build: definition not found: ${DEFINITION_PATH}" >&2
exit 1
fi
fi
PREFIX_PATH="${ARGUMENTS[1]}"
if [ -z "$PREFIX_PATH" ]; then
usage
fi
if [ -z "$TMPDIR" ]; then
TMP="/tmp"
else
TMP="${TMPDIR%/}"
fi
SEED="$(date "+%Y%m%d%H%M%S").$$"
LOG_PATH="${TMP}/python-build.${SEED}.log"
PYTHON_BIN="${PREFIX_PATH}/bin/python"
CWD="$(pwd)"
if [ -z $PYTHON_BUILD_BUILD_PATH ]; then
BUILD_PATH="${TMP}/python-build.${SEED}"
else
BUILD_PATH=$PYTHON_BUILD_BUILD_PATH
fi
exec 4<> "$LOG_PATH" # open the log file at fd 4
if [ -n "$VERBOSE" ]; then
tail -f "$LOG_PATH" &
trap "kill 0" SIGINT SIGTERM EXIT
fi
export LDFLAGS="-L'${PREFIX_PATH}/lib' ${LDFLAGS}"
export CPPFLAGS="-I'${PREFIX_PATH}/include' ${CPPFLAGS}"
unset PYTHONOPT
unset PYTHONLIB
trap build_failed ERR
mkdir -p "$BUILD_PATH"
source "$DEFINITION_PATH"
[ -z "${KEEP_BUILD_PATH}" ] && rm -fr "$BUILD_PATH"
trap - ERR

View file

@ -0,0 +1,14 @@
before_install_package() {
local package_name="$1"
case "$package_name" in
Python*)
fetch_url "https://raw.github.com/saghul/pythonz/346450868902fed0fe654c472b7b58e2e31fde70/pythonz/patches/all/common/patch-setup.py.diff" > setup.patch
patch -p0 < setup.patch
;;
esac
}
require_gcc
install_package "Python-2.6.8" "http://www.python.org/ftp/python/2.6.8/Python-2.6.8.tgz"
install_package "distribute-0.6.28" "http://pypi.python.org/packages/source/d/distribute/distribute-0.6.28.tar.gz" python
install_package "pip-1.1" "http://pypi.python.org/packages/source/p/pip/pip-1.1.tar.gz" python

View file

@ -0,0 +1,4 @@
require_gcc
install_package "Python-2.7.3" "http://www.python.org/ftp/python/2.7.3/Python-2.7.3.tgz"
install_package "distribute-0.6.28" "http://pypi.python.org/packages/source/d/distribute/distribute-0.6.28.tar.gz" python
install_package "pip-1.1" "http://pypi.python.org/packages/source/p/pip/pip-1.1.tar.gz" python

View file

@ -0,0 +1,14 @@
before_install_package() {
local package_name="$1"
case "$package_name" in
Python*)
fetch_url "https://raw.github.com/saghul/pythonz/346450868902fed0fe654c472b7b58e2e31fde70/pythonz/patches/all/python30/patch-setup.py.diff" > setup.patch
patch -p0 < setup.patch
;;
esac
}
require_gcc
install_package "Python-3.0.1" "http://www.python.org/ftp/python/3.0.1/Python-3.0.1.tgz"
install_package "distribute-0.6.28" "http://pypi.python.org/packages/source/d/distribute/distribute-0.6.28.tar.gz" python
install_package "pip-1.1" "http://pypi.python.org/packages/source/p/pip/pip-1.1.tar.gz" python

View file

@ -0,0 +1,4 @@
require_gcc
install_package "Python-3.1.5" "http://www.python.org/ftp/python/3.1.5/Python-3.1.5.tgz"
install_package "distribute-0.6.28" "http://pypi.python.org/packages/source/d/distribute/distribute-0.6.28.tar.gz" python
install_package "pip-1.1" "http://pypi.python.org/packages/source/p/pip/pip-1.1.tar.gz" python

View file

@ -0,0 +1,4 @@
require_gcc
install_package "Python-3.2.3" "http://www.python.org/ftp/python/3.2.3/Python-3.2.3.tgz"
install_package "distribute-0.6.28" "http://pypi.python.org/packages/source/d/distribute/distribute-0.6.28.tar.gz" python
install_package "pip-1.1" "http://pypi.python.org/packages/source/p/pip/pip-1.1.tar.gz" python

View file

@ -0,0 +1,4 @@
require_java
install_jar "Jython-2.5.2" "https://downloads.sourceforge.net/project/jython/jython/2.5.2/jython_installer-2.5.2.jar" jython
install_package "distribute-0.6.28" "http://pypi.python.org/packages/source/d/distribute/distribute-0.6.28.tar.gz" python
install_package "pip-1.1" "http://pypi.python.org/packages/source/p/pip/pip-1.1.tar.gz" python

View file

@ -0,0 +1,26 @@
require_gcc
case "$OSTYPE" in
darwin*)
PYPY_URL="https://bitbucket.org/pypy/pypy/downloads/pypy-1.9-osx64.tar.bz2"
;;
linux*)
case $(uname -m) in
i386|i486|i586|i686)
PYPY_URL="https://bitbucket.org/pypy/pypy/downloads/pypy-1.9-linux.tar.bz2"
;;
x86_64)
PYPY_URL="https://bitbucket.org/pypy/pypy/downloads/pypy-1.9-linux64.tar.bz2"
;;
esac
;;
cygwin*|mingw*)
PYPY_URL="https://bitbucket.org/pypy/pypy/downloads/pypy-1.9-win32.zip"
;;
esac
if [ -n "$PYPY_URL" ]; then
install_package "pypy-1.9" "$PYPY_URL" pypy
install_package "distribute-0.6.28" "http://pypi.python.org/packages/source/d/distribute/distribute-0.6.28.tar.gz" python
install_package "pip-1.1" "http://pypi.python.org/packages/source/p/pip/pip-1.1.tar.gz" python
fi

View file

@ -0,0 +1,4 @@
require_gcc
install_package "stackless-322-export" "http://www.stackless.com/binaries/stackless-322-export.tar.bz2"
install_package "distribute-0.6.28" "http://pypi.python.org/packages/source/d/distribute/distribute-0.6.28.tar.gz" python
install_package "pip-1.1" "http://pypi.python.org/packages/source/p/pip/pip-1.1.tar.gz" python