1
0
Fork 0
mirror of https://github.com/rbenv/ruby-build.git synced 2025-06-15 16:28:07 +02:00
rbenv-ruby-build/bin/ruby-build

1273 lines
31 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# Usage: ruby-build [-kpv] <definition> <prefix>
# ruby-build --definitions
# ruby-build --version
#
# -k/--keep Do not remove source tree after installation
# -p/--patch Apply a patch from stdin before building
# -v/--verbose Verbose mode: print compilation status to stdout
# -4/--ipv4 Resolve names to IPv4 addresses only
# -6/--ipv6 Resolve names to IPv6 addresses only
# --definitions List all built-in definitions
# --version Show version of ruby-build
#
RUBY_BUILD_VERSION="20160111"
OLDIFS="$IFS"
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"
}
capitalize() {
printf "%s" "$1" | tr a-z A-Z
}
sanitize() {
printf "%s" "$1" | sed "s/[^A-Za-z0-9.-]/_/g; s/__*/_/g"
}
colorize() {
if [ -t 1 ]; then printf "\e[%sm%s\e[m" "$1" "$2"
else echo -n "$2"
fi
}
os_information() {
if type -p lsb_release >/dev/null; then
lsb_release -sir | xargs echo
elif type -p sw_vers >/dev/null; then
echo "OS X $(sw_vers -productVersion)"
elif [ -r /etc/os-release ]; then
source /etc/os-release
echo "$NAME" $VERSION_ID
else
local os="$(cat /etc/{centos,redhat,fedora,system}-release /etc/debian_version 2>/dev/null | head -1)"
echo "${os:-$(uname -sr)}"
fi
}
is_mac() {
[ "$(uname -s)" = "Darwin" ] || return 1
[ $# -eq 0 ] || [ "$(osx_version)" "$@" ]
}
# 9.1 -> 901
# 10.9 -> 1009
# 10.10 -> 1010
osx_version() {
local -a ver
IFS=. ver=( `sw_vers -productVersion` )
IFS="$OLDIFS"
echo $(( ${ver[0]}*100 + ${ver[1]} ))
}
build_failed() {
{ echo
colorize 1 "BUILD FAILED"
echo " ($(os_information) using $(version))"
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
colorize 33 "Results logged to ${LOG_PATH}"
printf "\n\n"
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
}
num_cpu_cores() {
local num
case "$(uname -s)" in
Darwin | *BSD )
num="$(sysctl -n hw.ncpu 2>/dev/null || true)"
;;
* )
num="$(grep ^processor /proc/cpuinfo 2>/dev/null | wc -l | xargs)"
num="${num#0}"
;;
esac
echo "${num:-2}"
}
install_package() {
install_package_using "tarball" 1 "$@"
}
install_git() {
install_package_using "git" 2 "$@"
}
install_svn() {
install_package_using "svn" 2 "$@"
}
install_package_using() {
local package_type="$1"
local package_type_nargs="$2"
local package_name="$3"
shift 3
local fetch_args=( "$package_name" "${@:1:$package_type_nargs}" )
local make_args=( "$package_name" )
local arg last_arg
for arg in "${@:$(( $package_type_nargs + 1 ))}"; do
if [ "$last_arg" = "--if" ]; then
"$arg" || return 0
elif [ "$arg" != "--if" ]; then
make_args["${#make_args[@]}"]="$arg"
fi
last_arg="$arg"
done
pushd "$BUILD_PATH" >&4
"fetch_${package_type}" "${fetch_args[@]}"
make_package "${make_args[@]}"
popd >&4
{ echo "Installed ${package_name} to ${PREFIX_PATH}"
echo
} >&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
}
compute_sha2() {
local output
if type shasum &>/dev/null; then
output="$(shasum -a 256 -b)" || return 1
echo "${output% *}"
elif type openssl &>/dev/null; then
local openssl="$(command -v "$(brew --prefix openssl 2>/dev/null || true)"/bin/openssl openssl | head -1)"
output="$("$openssl" dgst -sha256 2>/dev/null)" || return 1
echo "${output##* }"
elif type sha256sum &>/dev/null; then
output="$(sha256sum --quiet)" || return 1
echo "${output% *}"
else
return 1
fi
}
compute_md5() {
local output
if type md5 &>/dev/null; then
md5 -q
elif type openssl &>/dev/null; then
output="$(openssl md5)" || return 1
echo "${output##* }"
elif type md5sum &>/dev/null; then
output="$(md5sum -b)" || return 1
echo "${output% *}"
else
return 1
fi
}
verify_checksum() {
local checksum_command
# If the specified filename doesn't exist, return success
local filename="$1"
[ -e "$filename" ] || return 0
# If there's no expected checksum, return success
local expected_checksum="$(echo "$2" | tr [A-Z] [a-z])"
[ -n "$expected_checksum" ] || return 0
case "${#expected_checksum}" in
32) # MD5
[ -n "$HAS_MD5_SUPPORT" ] || return 0
checksum_command="compute_md5"
;;
64) # SHA2 256
[ -n "$HAS_SHA2_SUPPORT" ] || return 0
checksum_command="compute_sha2"
;;
*) # unknown checksum algorithm, return failure
return 1
;;
esac
# If the computed checksum is empty, return failure
local computed_checksum=`echo "$($checksum_command < "$filename")" | tr [A-Z] [a-z]`
[ -n "$computed_checksum" ] || return 1
if [ "$expected_checksum" != "$computed_checksum" ]; then
{ echo
echo "checksum mismatch: ${filename} (file is corrupt)"
echo "expected $expected_checksum, got $computed_checksum"
echo
} >&4
return 1
fi
}
http() {
local method="$1"
local url="$2"
local file="$3"
[ -n "$url" ] || return 1
if type curl &>/dev/null; then
"http_${method}_curl" "$url" "$file"
elif type wget &>/dev/null; then
"http_${method}_wget" "$url" "$file"
else
echo "error: please install \`curl\` or \`wget\` and try again" >&2
exit 1
fi
}
http_head_curl() {
options=""
[ -n "${IPV4}" ] && options="--ipv4"
[ -n "${IPV6}" ] && options="--ipv6"
curl -qsILf ${options} "$1" >&4 2>&1
}
http_get_curl() {
options=""
[ -n "${IPV4}" ] && options="--ipv4"
[ -n "${IPV6}" ] && options="--ipv6"
curl -q -o "${2:--}" -sSLf ${options} "$1"
}
http_head_wget() {
options=""
[ -n "${IPV4}" ] && options="--inet4-only"
[ -n "${IPV6}" ] && options="--inet6-only"
wget -q --spider ${options} "$1" >&4 2>&1
}
http_get_wget() {
options=""
[ -n "${IPV4}" ] && options="--inet4-only"
[ -n "${IPV6}" ] && options="--inet6-only"
wget -nv ${options} -O "${2:--}" "$1"
}
fetch_tarball() {
local package_name="$1"
local package_url="$2"
local mirror_url
local checksum
if [ "$package_url" != "${package_url/\#}" ]; then
checksum="${package_url#*#}"
package_url="${package_url%%#*}"
if [ -n "$RUBY_BUILD_MIRROR_URL" ]; then
if [[ -z "$RUBY_BUILD_DEFAULT_MIRROR" || $package_url != */cache.ruby-lang.org/* ]]; then
mirror_url="${RUBY_BUILD_MIRROR_URL}/$checksum"
fi
fi
fi
local tar_args="xzf"
local package_filename="${package_name}.tar.gz"
if [ "$package_url" != "${package_url%bz2}" ]; then
if ! type -p bzip2 >/dev/null; then
echo "warning: bzip2 not found; consider installing \`bzip2\` package" >&4
fi
package_filename="${package_filename%.gz}.bz2"
tar_args="${tar_args/z/j}"
fi
if ! reuse_existing_tarball "$package_filename" "$checksum"; then
local tarball_filename=$(basename $package_url)
echo "Downloading ${tarball_filename}..." >&2
http head "$mirror_url" &&
download_tarball "$mirror_url" "$package_filename" "$checksum" ||
download_tarball "$package_url" "$package_filename" "$checksum"
fi
{ if tar $tar_args "$package_filename"; then
if [ -z "$KEEP_BUILD_PATH" ]; then
rm -f "$package_filename"
else
true
fi
fi
} >&4 2>&1
}
reuse_existing_tarball() {
local package_filename="$1"
local checksum="$2"
# Reuse existing file in build location
if [ -e "$package_filename" ] && verify_checksum "$package_filename" "$checksum"; then
return 0
fi
# Reuse previously downloaded file in cache location
[ -n "$RUBY_BUILD_CACHE_PATH" ] || return 1
local cached_package_filename="${RUBY_BUILD_CACHE_PATH}/$package_filename"
[ -e "$cached_package_filename" ] || return 1
verify_checksum "$cached_package_filename" "$checksum" >&4 2>&1 || return 1
ln -s "$cached_package_filename" "$package_filename" >&4 2>&1 || return 1
}
download_tarball() {
local package_url="$1"
[ -n "$package_url" ] || return 1
local package_filename="$2"
local checksum="$3"
echo "-> $package_url" >&2
if http get "$package_url" "$package_filename" >&4 2>&1; then
verify_checksum "$package_filename" "$checksum" >&4 2>&1 || return 1
else
echo "error: failed to download $package_filename" >&2
return 1
fi
if [ -n "$RUBY_BUILD_CACHE_PATH" ]; then
local cached_package_filename="${RUBY_BUILD_CACHE_PATH}/$package_filename"
{ mv "$package_filename" "$cached_package_filename"
ln -s "$cached_package_filename" "$package_filename"
} >&4 2>&1 || return 1
fi
}
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
if [ -n "$RUBY_BUILD_CACHE_PATH" ]; then
pushd "$RUBY_BUILD_CACHE_PATH" >&4
local clone_name="$(sanitize "$git_url")"
if [ -e "${clone_name}" ]; then
{ cd "${clone_name}"
git fetch --force "$git_url" "+${git_ref}:${git_ref}"
} >&4 2>&1
else
git clone --bare --branch "$git_ref" "$git_url" "${clone_name}" >&4 2>&1
fi
git_url="$RUBY_BUILD_CACHE_PATH/${clone_name}"
popd >&4
fi
if [ -e "${package_name}" ]; then
( cd "${package_name}"
git fetch --depth 1 origin "+${git_ref}"
git checkout -q -B "$git_ref" "origin/${git_ref}"
) >&4 2>&1
else
git clone --depth 1 --branch "$git_ref" "$git_url" "${package_name}" >&4 2>&1
fi
else
echo "error: please install \`git\` and try again" >&2
exit 1
fi
}
fetch_svn() {
local package_name="$1"
local svn_url="$2"
local svn_rev="$3"
echo "Checking out ${svn_url}..." >&2
if type svn &>/dev/null; then
svn co -r "$svn_rev" "$svn_url" "${package_name}" >&4 2>&1
elif type svnlite &>/dev/null; then
svnlite co -r "$svn_rev" "$svn_url" "${package_name}" >&4 2>&1
else
echo "error: please install Subversion and try again" >&2
exit 1
fi
}
build_package() {
local package_name="$1"
shift
if [ "$#" -eq 0 ]; then
local commands="standard"
else
local commands="$*"
fi
echo "Installing ${package_name}..." >&2
[ -n "$HAS_PATCH" ] && apply_ruby_patch "$package_name"
for command in $commands; do
"build_package_${command}" "$package_name"
done
}
package_option() {
local package_name="$1"
local command_name="$2"
local variable="$(capitalize "${package_name}_${command_name}")_OPTS_ARRAY"
local array="$variable[@]"
shift 2
local value=( "${!array}" "$@" )
eval "$variable=( \"\${value[@]}\" )"
}
build_package_standard() {
local package_name="$1"
if [ "${MAKEOPTS+defined}" ]; then
MAKE_OPTS="$MAKEOPTS"
elif [ -z "${MAKE_OPTS+defined}" ]; then
MAKE_OPTS="-j $(num_cpu_cores)"
fi
# Support YAML_CONFIGURE_OPTS, RUBY_CONFIGURE_OPTS, etc.
local package_var_name="$(capitalize "${package_name%%-*}")"
local PACKAGE_CONFIGURE="${package_var_name}_CONFIGURE"
local PACKAGE_PREFIX_PATH="${package_var_name}_PREFIX_PATH"
local PACKAGE_CONFIGURE_OPTS="${package_var_name}_CONFIGURE_OPTS"
local PACKAGE_CONFIGURE_OPTS_ARRAY="${package_var_name}_CONFIGURE_OPTS_ARRAY[@]"
local PACKAGE_MAKE_OPTS="${package_var_name}_MAKE_OPTS"
local PACKAGE_MAKE_OPTS_ARRAY="${package_var_name}_MAKE_OPTS_ARRAY[@]"
local PACKAGE_MAKE_INSTALL_OPTS="${package_var_name}_MAKE_INSTALL_OPTS"
local PACKAGE_MAKE_INSTALL_OPTS_ARRAY="${package_var_name}_MAKE_INSTALL_OPTS_ARRAY[@]"
local PACKAGE_CFLAGS="${package_var_name}_CFLAGS"
[ "$package_var_name" = "RUBY" ] && use_homebrew_readline || true
( if [ "${CFLAGS+defined}" ] || [ "${!PACKAGE_CFLAGS+defined}" ]; then
export CFLAGS="$CFLAGS ${!PACKAGE_CFLAGS}"
fi
if [ -z "$CC" ] && is_mac -ge 1010; then
export CC=clang
fi
${!PACKAGE_CONFIGURE:-./configure} --prefix="${!PACKAGE_PREFIX_PATH:-$PREFIX_PATH}" \
$CONFIGURE_OPTS ${!PACKAGE_CONFIGURE_OPTS} "${!PACKAGE_CONFIGURE_OPTS_ARRAY}" || return 1
) >&4 2>&1
{ "$MAKE" $MAKE_OPTS ${!PACKAGE_MAKE_OPTS} "${!PACKAGE_MAKE_OPTS_ARRAY}"
"$MAKE" install $MAKE_INSTALL_OPTS ${!PACKAGE_MAKE_INSTALL_OPTS} "${!PACKAGE_MAKE_INSTALL_OPTS_ARRAY}"
} >&4 2>&1
}
build_package_autoconf() {
{ autoconf
} >&4 2>&1
}
build_package_ruby() {
local package_name="$1"
{ "$RUBY_BIN" setup.rb
} >&4 2>&1
}
build_package_ree_installer() {
build_package_auto_tcltk
local options=""
is_mac && options="--no-tcmalloc"
local option
for option in $RUBY_CONFIGURE_OPTS ${RUBY_CONFIGURE_OPTS_ARRAY[@]}; do
options="$options -c $option"
done
# Work around install_useful_libraries crash with --dont-install-useful-gems
mkdir -p "$PREFIX_PATH/lib/ruby/gems/1.8/gems"
{ ./installer --auto "$PREFIX_PATH" --dont-install-useful-gems $options $CONFIGURE_OPTS
} >&4 2>&1
}
build_package_rbx() {
local package_name="$1"
{ [ ! -e "Gemfile" ] || bundle --path=vendor/bundle
if [ -n "$RUBY_BUILD_CACHE_PATH" ]; then
mkdir -p vendor
ln -s "$RUBY_BUILD_CACHE_PATH" vendor/prebuilt
fi
local opt
local -a configure_opts
for opt in "${RUBY_CONFIGURE_OPTS_ARRAY[@]}"; do
if [[ $opt == --with-openssl-dir=* ]]; then
local openssl_dir="${opt#*=}"
configure_opts[${#configure_opts[@]}]="--with-lib-dir=${openssl_dir}/lib"
configure_opts[${#configure_opts[@]}]="--with-include-dir=${openssl_dir}/include"
else
configure_opts[${#configure_opts[@]}]="$opt"
fi
done
RUBYOPT="-rubygems $RUBYOPT" ./configure --prefix="$PREFIX_PATH" $RUBY_CONFIGURE_OPTS "${configure_opts[@]}"
rake install
fix_rbx_gem_binstubs "$PREFIX_PATH"
fix_rbx_irb "$PREFIX_PATH"
} >&4 2>&1
}
build_package_mruby() {
local package_name="$1"
{ rake
mkdir -p "$PREFIX_PATH"
cp -fR build/host/* "$PREFIX_PATH"
cd "$PREFIX_PATH/bin"
ln -fs mruby ruby
ln -fs mirb irb
} >&4 2>&1
}
build_package_maglev() {
build_package_copy
{ cd "${PREFIX_PATH}"
./install.sh
cd "${PREFIX_PATH}/bin"
echo "Creating symlink for ruby*"
ln -fs maglev-ruby ruby
echo "Creating symlink for irb*"
ln -fs maglev-irb irb
} >&4 2>&1
echo
echo "Run 'maglev start' to start up the stone before using 'ruby' or 'irb'"
}
build_package_topaz() {
build_package_copy
{ cd "${PREFIX_PATH}/bin"
echo "Creating symlink for ruby*"
ln -fs topaz ruby
} >&4 2>&1
}
topaz_architecture() {
case "$(uname -s)" in
"Darwin") echo "osx64";;
"Linux") [[ "$(uname -m)" = "x86_64" ]] && echo "linux64" || echo "linux32";;
*)
echo "no nightly builds available" >&2
exit 1;;
esac
}
build_package_jruby() {
build_package_copy
cd "${PREFIX_PATH}/bin"
ln -fs jruby ruby
chmod +x ruby
install_jruby_launcher
remove_windows_files
fix_jruby_shebangs
}
graal_architecture() {
if [ "$(uname -m)" != "x86_64" ]; then
echo "no nightly builds available" >&2
exit 1
fi
case "$(uname -s)" in
"Darwin") echo "macosx-x86_64";;
"Linux") echo "linux-x86_64";;
*)
echo "no nightly builds available" >&2
exit 1;;
esac
}
install_jruby_launcher() {
# If this version of JRuby has been modified for Graal, don't overwrite the
# launcher scripts
if ! grep -q graalvm "${PREFIX_PATH}/bin/jruby"; then
cd "${PREFIX_PATH}/bin"
{ ./ruby gem install jruby-launcher
} >&4 2>&1
fi
}
fix_jruby_shebangs() {
for file in "${PREFIX_PATH}/bin"/*; do
if [ "$(head -c 20 "$file")" = "#!/usr/bin/env jruby" ]; then
sed -i.bak "1 s:.*:#\!${PREFIX_PATH}\/bin\/jruby:" "$file"
rm "$file".bak
fi
done
}
remove_windows_files() {
cd "$PREFIX_PATH"
rm -f bin/*.exe bin/*.dll bin/*.bat bin/jruby.sh
}
build_package_copy() {
mkdir -p "$PREFIX_PATH"
cp -fR . "$PREFIX_PATH"
}
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 \( -perm -020 -o -perm -002 \) -exec chmod go-w {} \;
}
fix_rbx_gem_binstubs() {
local prefix="$1"
local gemdir="${prefix}/gems/bin"
local bindir="${prefix}/bin"
local file binstub
# Symlink Rubinius' `gems/bin/` into `bin/`
if [ -d "$gemdir" ] && [ ! -L "$gemdir" ]; then
for file in "$gemdir"/*; do
binstub="${bindir}/${file##*/}"
rm -f "$binstub"
{ echo "#!${bindir}/ruby"
grep -v '^#!' "$file"
} > "$binstub"
chmod +x "$binstub"
done
rm -rf "$gemdir"
ln -s ../bin "$gemdir"
fi
}
fix_rbx_irb() {
local prefix="$1"
"${prefix}/bin/irb" --version &>/dev/null ||
"${prefix}/bin/gem" install rubysl-tracer -v '~> 2.0' --no-rdoc --no-ri &>/dev/null ||
true
}
require_java7() {
local version="$(java -version 2>&1 | grep '\(java\|openjdk\) version' | head -1)"
if [[ $version != *1.[789]* ]]; then
colorize 1 "ERROR" >&3
echo ": Java 7 required. Please install a 1.7-compatible JRE." >&3
return 1
fi
}
require_gcc() {
local gcc="$(locate_gcc || true)"
if [ -z "$gcc" ]; then
{ echo
colorize 1 "ERROR"
echo ": This package must be compiled with GCC, but ruby-build couldn't"
echo "find a suitable \`gcc\` executable on your system. Please install GCC"
echo "and try again."
echo
if is_mac; then
colorize 1 "DETAILS"
echo ": 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 Ruby older than 1.9.3-p125 are incompatible with"
echo "\`llvm-gcc\`. To build older versions of Ruby you must have the official"
echo "GCC compiler installed on your system."
echo
colorize 1 "TO FIX THE PROBLEM"
if type brew &>/dev/null; then
echo ": Install Homebrew's apple-gcc42 package with this"
echo -n "command: "
colorize 4 "brew tap homebrew/dupes ; brew install apple-gcc42"
else
echo ": Install the official GCC compiler using these"
echo -n "packages: "
colorize 4 "https://github.com/kennethreitz/osx-gcc-installer/downloads"
fi
echo
echo
echo "You will need to install the official GCC compiler to build older"
echo "versions of Ruby 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"
if is_mac -ge 1010; then
export MACOSX_DEPLOYMENT_TARGET=10.9
fi
}
locate_gcc() {
local gcc gccs
IFS=: gccs=($(gccs_in_path))
IFS="$OLDIFS"
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)
IFS="$OLDIFS"
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 2>/dev/null || true)"
if [ -z "$version" ]; then
return 1
fi
if echo "$version" | grep LLVM >/dev/null; then
return 1
fi
echo "$gcc"
}
require_llvm() {
local llvm_version="$1"
if is_mac -ge 1010; then
if [[ "$RUBY_CONFIGURE_OPTS" != *--llvm-* ]]; then
case "$llvm_version" in
3.2 )
package_option ruby configure --prebuilt-name="llvm-3.2-x86_64-apple-darwin13.tar.bz2"
;;
3.5 )
local llvm_config="$(locate_llvm "$llvm_version")"
if [ -n "$llvm_config" ]; then
package_option ruby configure --llvm-config="$llvm_config"
else
{ echo
colorize 1 "ERROR"
echo ": Rubinius will not be able to compile using Apple's LLVM-based "
echo "build tools on OS X. You will need to install LLVM 3.5 first."
echo
colorize 1 "TO FIX THE PROBLEM"
echo ": Install Homebrew's llvm package with this"
echo -n "command: "
colorize 4 "brew tap homebrew/versions ; brew install llvm35"
echo
} >&3
return 1
fi
;;
esac
fi
fi
}
locate_llvm() {
local llvm_version="$1"
local package llvm_config
shopt -s nullglob
for package in `brew list 2>/dev/null | grep "^llvm"`; do
llvm_config="$(echo "$(brew --prefix "$package")/bin/llvm-config"*)"
if [ -n "$llvm_config" ] && [[ "$("$llvm_config" --version)" = "$llvm_version"* ]]; then
echo "$llvm_config"
break
fi
done
shopt -u nullglob
}
needs_yaml() {
[[ "$RUBY_CONFIGURE_OPTS" != *--with-libyaml-dir=* ]] &&
! use_homebrew_yaml
}
use_homebrew_yaml() {
local libdir="$(brew --prefix libyaml 2>/dev/null || true)"
if [ -d "$libdir" ]; then
package_option ruby configure --with-libyaml-dir="$libdir"
else
return 1
fi
}
use_homebrew_readline() {
if [[ "$RUBY_CONFIGURE_OPTS" != *--with-readline-dir=* ]]; then
local libdir="$(brew --prefix readline 2>/dev/null || true)"
if [ -d "$libdir" ]; then
package_option ruby configure --with-readline-dir="$libdir"
else
return 1
fi
fi
}
has_broken_mac_openssl() {
is_mac &&
[[ "$(/usr/bin/openssl version 2>/dev/null || true)" = "OpenSSL 0.9.8"?* ]] &&
[[ "$RUBY_CONFIGURE_OPTS" != *--with-openssl-dir=* ]] &&
! use_homebrew_openssl
}
use_homebrew_openssl() {
local ssldir="$(brew --prefix openssl 2>/dev/null || true)"
if [ -d "$ssldir" ]; then
package_option ruby configure --with-openssl-dir="$ssldir"
else
return 1
fi
}
build_package_mac_openssl() {
# Install to a subdirectory since we don't want shims for bin/openssl.
OPENSSL_PREFIX_PATH="${PREFIX_PATH}/openssl"
# Put openssl.conf, certs, etc in ~/.rbenv/versions/*/openssl/ssl
OPENSSLDIR="${OPENSSLDIR:-$OPENSSL_PREFIX_PATH/ssl}"
# Tell Ruby to use this openssl for its extension.
package_option ruby configure --with-openssl-dir="$OPENSSL_PREFIX_PATH"
# Hint OpenSSL that we prefer a 64-bit build.
export KERNEL_BITS="64"
OPENSSL_CONFIGURE="${OPENSSL_CONFIGURE:-./config}"
# Compile a shared lib with zlib dynamically linked, no kerberos.
package_option openssl configure --openssldir="$OPENSSLDIR" zlib-dynamic no-ssl2 no-ssl3 no-krb5 shared
# Default MAKE_OPTS are -j 2 which can confuse the build. Thankfully, make
# gives precedence to the last -j option, so we can override that.
package_option openssl make -j 1
build_package_standard "$@"
# Extract root certs from the system keychain in .pem format and rehash.
local pem_file="$OPENSSLDIR/cert.pem"
security find-certificate -a -p /Library/Keychains/System.keychain > "$pem_file"
security find-certificate -a -p /System/Library/Keychains/SystemRootCertificates.keychain >> "$pem_file"
}
# Post-install check that the openssl extension was built.
build_package_verify_openssl() {
"$RUBY_BIN" -e '
manager = ARGV[0]
packages = {
"apt-get" => Hash.new {|h,k| "lib#{k}-dev" }.update(
"openssl" => "libssl-dev",
"zlib" => "zlib1g-dev"
),
"yum" => Hash.new {|h,k| "#{k}-devel" }.update(
"yaml" => "libyaml-devel"
)
}
failed = %w[openssl readline zlib yaml].reject do |lib|
begin
require lib
rescue LoadError
$stderr.puts "The Ruby #{lib} extension was not compiled."
end
end
if failed.size > 0
$stderr.puts "ERROR: Ruby install aborted due to missing extensions"
$stderr.print "Try running `%s install -y %s` to fetch missing dependencies.\n\n" % [
manager,
failed.map { |lib| packages.fetch(manager)[lib] }.join(" ")
] unless manager.empty?
$stderr.puts "Configure options used:"
require "rbconfig"; require "shellwords"
RbConfig::CONFIG.fetch("configure_args").shellsplit.each { |arg| $stderr.puts " #{arg}" }
exit 1
end
' "$(basename "$(type -p yum apt-get | head -1)")" >&4 2>&1
}
# Ensure that directories listed in LDFLAGS exist
build_package_ldflags_dirs() {
local arg dir
set - $LDFLAGS
while [ $# -gt 0 ]; do
dir=""
case "$1" in
-L ) dir="$2" ;;
-L* ) dir="${1#-L}" ;;
esac
[ -z "$dir" ] || mkdir -p "$dir"
shift 1
done
}
build_package_auto_tcltk() {
if is_mac && [ ! -d /usr/include/X11 ]; then
if [ -d /opt/X11/include ]; then
if [[ "$CPPFLAGS" != *-I/opt/X11/include* ]]; then
export CPPFLAGS="-I/opt/X11/include $CPPFLAGS"
fi
else
package_option ruby configure --without-tk
fi
fi
}
rake() {
if [ -e "./Gemfile" ]; then
bundle exec rake "$@"
else
isolated_gem_dependency "rake --version" rake -v '~> 10.1.0'
command rake "$@"
fi
}
bundle() {
isolated_gem_dependency "bundle --version" bundler -v '~> 1.3.5'
command bundle "$@"
}
isolated_gem_dependency() {
set +E
( command $1 &>/dev/null ) || {
set -E
shift 1
isolated_gem_install "$@"
}
set -E
}
isolated_gem_install() {
export GEM_HOME="${PWD}/.gem"
export PATH="${GEM_HOME}/bin:${PATH}"
gem install "$@"
}
apply_ruby_patch() {
local patchfile
case "$1" in
ruby-* | jruby-* | rubinius-* )
patchfile="$(mktemp "${TMP}/ruby-patch.XXXXXX")"
cat "${2:--}" >"$patchfile"
local striplevel=0
grep -q '^diff --git a/' "$patchfile" && striplevel=1
patch -p$striplevel --force -i "$patchfile"
;;
esac
}
version() {
local git_revision
# Read the revision from git if the remote points to "ruby-build" repository
if GIT_DIR="$RUBY_BUILD_INSTALL_PREFIX/.git" git remote -v 2>/dev/null | grep -q /ruby-build; then
git_revision="$(GIT_DIR="$RUBY_BUILD_INSTALL_PREFIX/.git" git describe --tags HEAD 2>/dev/null || true)"
git_revision="${git_revision#v}"
fi
echo "ruby-build ${git_revision:-$RUBY_BUILD_VERSION}"
}
usage() {
sed -ne '/^#/!q;s/.\{1,2\}//;1,2d;p' < "$0"
[ -z "$1" ] || exit "$1"
}
list_definitions() {
{ for DEFINITION_DIR in "${RUBY_BUILD_DEFINITIONS[@]}"; do
[ -d "$DEFINITION_DIR" ] && ls "$DEFINITION_DIR"
done
} | sort_versions | uniq
}
sort_versions() {
sed 'h; s/[+-]/./g; s/.p\([[:digit:]]\)/.z\1/; s/$/.z/; G; s/\n/ /' | \
LC_ALL=C sort -t. -k 1,1 -k 2,2n -k 3,3n -k 4,4n -k 5,5n | awk '{print $2}'
}
unset VERBOSE
unset KEEP_BUILD_PATH
unset HAS_PATCH
unset IPV4
unset IPV6
RUBY_BUILD_INSTALL_PREFIX="$(abs_dirname "$0")/.."
IFS=: RUBY_BUILD_DEFINITIONS=($RUBY_BUILD_DEFINITIONS ${RUBY_BUILD_ROOT:-$RUBY_BUILD_INSTALL_PREFIX}/share/ruby-build)
IFS="$OLDIFS"
parse_options "$@"
for option in "${OPTIONS[@]}"; do
case "$option" in
"h" | "help" )
version
echo
usage 0
;;
"definitions" )
list_definitions
exit 0
;;
"k" | "keep" )
KEEP_BUILD_PATH=true
;;
"v" | "verbose" )
VERBOSE=true
;;
"p" | "patch" )
HAS_PATCH=true
;;
"4" | "ipv4")
IPV4=true
;;
"6" | "ipv6")
IPV6=true
;;
"version" )
version
exit 0
;;
esac
done
[ "${#ARGUMENTS[@]}" -eq 2 ] || usage 1 >&2
DEFINITION_PATH="${ARGUMENTS[0]}"
if [ -z "$DEFINITION_PATH" ]; then
usage 1 >&2
elif [ ! -f "$DEFINITION_PATH" ]; then
for DEFINITION_DIR in "${RUBY_BUILD_DEFINITIONS[@]}"; do
if [ -f "${DEFINITION_DIR}/${DEFINITION_PATH}" ]; then
DEFINITION_PATH="${DEFINITION_DIR}/${DEFINITION_PATH}"
break
fi
done
if [ ! -f "$DEFINITION_PATH" ]; then
echo "ruby-build: definition not found: ${DEFINITION_PATH}" >&2
exit 2
fi
fi
PREFIX_PATH="${ARGUMENTS[1]}"
if [ -z "$PREFIX_PATH" ]; then
usage 1 >&2
elif [ "${PREFIX_PATH#/}" = "$PREFIX_PATH" ]; then
PREFIX_PATH="${PWD}/${PREFIX_PATH}"
fi
if [ -z "$TMPDIR" ]; then
TMP="/tmp"
else
TMP="${TMPDIR%/}"
fi
# Check if TMPDIR is accessible and can hold executables.
tmp_executable="${TMP}/ruby-build-test.$$"
noexec=""
if mkdir -p "$TMP" && touch "$tmp_executable" 2>/dev/null; then
cat > "$tmp_executable" <<-EOF
#!${BASH}
exit 0
EOF
chmod +x "$tmp_executable"
else
echo "ruby-build: TMPDIR=$TMP is set to a non-accessible location" >&2
exit 1
fi
"$tmp_executable" 2>/dev/null || noexec=1
rm -f "$tmp_executable"
if [ -n "$noexec" ]; then
echo "ruby-build: TMPDIR=$TMP cannot hold executables (partition possibly mounted with \`noexec\`)" >&2
exit 1
fi
# Work around warnings building Ruby 2.0 on Clang 2.x:
# pass -Wno-error=shorten-64-to-32 if the compiler accepts it.
#
# When we set CFLAGS, Ruby won't apply its default flags, though. Since clang
# builds 1.9.x and 2.x only, where -O3 is default, we can safely set that flag.
# Ensure it's the first flag since later flags take precedence.
if "${CC:-cc}" -x c /dev/null -E -Wno-error=shorten-64-to-32 &>/dev/null; then
RUBY_CFLAGS="-O3 -Wno-error=shorten-64-to-32 $RUBY_CFLAGS"
fi
if [ -z "$MAKE" ]; then
if [ "FreeBSD" = "$(uname -s)" ] && [ "$(uname -r | sed 's/[^[:digit:]].*//')" -lt 10 ]; then
export MAKE="gmake"
else
export MAKE="make"
fi
fi
if [ -n "$RUBY_BUILD_CACHE_PATH" ] && [ -d "$RUBY_BUILD_CACHE_PATH" ]; then
RUBY_BUILD_CACHE_PATH="${RUBY_BUILD_CACHE_PATH%/}"
else
unset RUBY_BUILD_CACHE_PATH
fi
if [ -z "$RUBY_BUILD_MIRROR_URL" ]; then
RUBY_BUILD_MIRROR_URL="https://dqw8nmjcqpjn7.cloudfront.net"
RUBY_BUILD_DEFAULT_MIRROR=1
else
RUBY_BUILD_MIRROR_URL="${RUBY_BUILD_MIRROR_URL%/}"
RUBY_BUILD_DEFAULT_MIRROR=
fi
if [ -n "$RUBY_BUILD_SKIP_MIRROR" ]; then
unset RUBY_BUILD_MIRROR_URL
fi
if echo test | compute_sha2 >/dev/null; then
HAS_SHA2_SUPPORT=1
else
unset HAS_SHA2_SUPPORT
unset RUBY_BUILD_MIRROR_URL
fi
if echo test | compute_md5 >/dev/null; then
HAS_MD5_SUPPORT=1
else
unset HAS_MD5_SUPPORT
fi
SEED="$(date "+%Y%m%d%H%M%S").$$"
LOG_PATH="${TMP}/ruby-build.${SEED}.log"
RUBY_BIN="${PREFIX_PATH}/bin/ruby"
CWD="$(pwd)"
if [ -z "$RUBY_BUILD_BUILD_PATH" ]; then
BUILD_PATH="${TMP}/ruby-build.${SEED}"
else
BUILD_PATH="$RUBY_BUILD_BUILD_PATH"
fi
exec 4<> "$LOG_PATH" # open the log file at fd 4
if [ -n "$VERBOSE" ]; then
tail -f "$LOG_PATH" &
TAIL_PID=$!
trap "kill $TAIL_PID" SIGINT SIGTERM EXIT
fi
export LDFLAGS="-L${PREFIX_PATH}/lib ${LDFLAGS}"
export CPPFLAGS="-I${PREFIX_PATH}/include ${CPPFLAGS}"
unset RUBYOPT
unset RUBYLIB
trap build_failed ERR
mkdir -p "$BUILD_PATH"
source "$DEFINITION_PATH"
[ -z "${KEEP_BUILD_PATH}" ] && rm -fr "$BUILD_PATH"
trap - ERR