Skip to content

Commit

Permalink
Adding cross-platform ruby-install file
Browse files Browse the repository at this point in the history
  • Loading branch information
kigster committed Oct 29, 2024
1 parent ae3b874 commit b9f4a36
Showing 1 changed file with 72 additions and 40 deletions.
112 changes: 72 additions & 40 deletions bin/ruby-install
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
#!/usr/bin/env bash
# vim: ft=bash
#
# @uthor Konstantin Gredeskoul
# @author Konstantin Gredeskoul <kig AT kig.re>
# @project Bashmatic
# @repo https://github.com/kigster/bashmatic
#
# @dependencies Expected to be pre-installed
# - rbenv
# - ruby-build
#
# @description
# By the default, the installer will skip existing installations
# with the same ruby version. If you pass -f or --force, however,
# any existing installation will be entirely replaced.
# This script installs Ruby with Jemalloc, YJIT and OpenSSL bindings.
# It works on Linux (with apt-get) and MacOS (using Brew). It uses
# rbenv and ruby-build to actuall install Ruby on both OSes.
#
# This script installs Ruby with Jemalloc, YJIT and OpenSSL bindings.
# The version of ruby is read from .ruby-version file in the current
# directory, any directory above the current, or the version can be
# passed as an argument, eg:
# The version of ruby is read from .ruby-version file in the current
# directory, any directory above the current, or the version can be
# passed as a command line argument, eg:
#
# @example Passing via arguments
# ruby-install [ -f | --force ] 3.3.5
# ruby-install [ -f | --force ] 3.3.5
#
# @example Reading .ruby-version
# echo '3.3.5' > .ruby-version
# ruby-install [ -f | --force ]
# echo '3.3.5' > .ruby-version
# ruby-install [ -f | --force ]
#
# @description
# By the default, the installer will skip existing installations
# with the same ruby version. If you pass -f or --force, however,
# any existing installation will be entirely replaced.

# We'll be catching $? manually, so for now turn off automatic erroring.
set +e
Expand All @@ -46,11 +44,6 @@ if [[ "$*" =~ -q|--quiet ]]; then
export option_quiet=true
fi

if [[ "$*" =~ -h|--help ]]; then
echo "Usage: ruby-install [ -f | --force ] [ -q | --quiet ] ruby-version"
exit 0
fi

# ┌────────────────────────────────────────────────────────────────────────┐
# │ Helper Functions │
# └────────────────────────────────────────────────────────────────────────┘
Expand All @@ -64,22 +57,22 @@ log.ts() {

log.info() {
local line="$*"
printf "\e[7;34m %s | INFO \e[0;34m ${line:0:70} \e[0m\n" "$(log.ts)"
printf "\e[7;34m %s | INFO \e[0;34m ${line:0:100} \e[0m\n" "$(log.ts)"
}

log.question() {
local line="$*"
printf "\e[7;35m %s | INPUT \e[0;35m ${line:0:70}\e[0m\e[1;33m " "$(log.ts)"
printf "\e[7;35m %s | INPUT \e[0;35m ${line:0:100}\e[0m\e[1;33m " "$(log.ts)"
}

log.warn() {
local line="$*"
printf "\e[7;33m %s | WARN \e[0;33m ${line:0:70} \e[0m\n" "$(log.ts)"
printf "\e[7;33m %s | WARN \e[0;33m ${line:0:100} \e[0m\n" "$(log.ts)"
}

log.error() {
local line="$*"
printf "\e[7;31m %s | ERROR \e[0;31m ${line:0:70} \e[0m\n" "$(log.ts)"
printf "\e[7;31m %s | ERROR \e[0;31m ${line:0:100} \e[0m\n" "$(log.ts)"
}

is.a-function () {
Expand All @@ -99,6 +92,9 @@ function ruby.version-valid() {
[[ ${rv} =~ ^([0-9]\.[0-9]+\.[0-9]+)$ ]]
}

# ┌────────────────────────────────────────────────────────────────────────┐
# │ Ruby Version Detection
# └────────────────────────────────────────────────────────────────────────┘
# @description
# This is perhaps the main function that attempts to guess which version
# we should be installing, assuming one wasn't provided as an CLI argument.
Expand All @@ -123,7 +119,6 @@ function ruby.detect-version() {
}

# otherwise seed .ruby-version in this and all parent folders

while true; do
if [[ -s "${current_dir}/${ruby_version_file_path}" ]]; then
export ruby_version_from_file="$(tr -d '\n' < <(cat "${current_dir}/${ruby_version_file_path}"))"
Expand Down Expand Up @@ -159,6 +154,10 @@ function ruby.detect-version() {
fi
}

# ┌────────────────────────────────────────────────────────────────────────┐
# │ Pre-Installation: detects OS and ensures dependencies are installed │
# │ Works on either Linux with apt-get or MacOS with brew
# └────────────────────────────────────────────────────────────────────────┘
function ruby.begin-install() {
ruby.version-valid "${ruby_version}" || {
log.error "Can not install Ruby with invalid version."
Expand All @@ -167,7 +166,7 @@ function ruby.begin-install() {
}

log.info "OS detected: \033[1;31m${osname}"

if ${rbenv_force_reinstall}; then
log.warn "Force-installing version ${ruby_version} due to --force flag."
else
Expand Down Expand Up @@ -219,7 +218,14 @@ function ruby.install() {
# Use up to 8 cores to compile ruby
[[ -n ${RUBY_MAKE_OPTS} ]] || export RUBY_MAKE_OPTS="-j 8"

local code=0
rbenv install ${extra_flags} ${version}
code=$?

if [[ ${code} -ne 0 ]]; then
log.error "Ruby Installation of version ${version} failed, exit code ${code}"
exit ${code}
fi

local time_finish=$(date '+%s')
local duration=$(( time_begin - time_finish ))
Expand All @@ -228,42 +234,55 @@ function ruby.install() {
set -e
rbenv local ${version}
export RUBY_YJIT_ENABLE=1
log.info "Ruby Interpreter:"
log.warn " $(log.arrows)$(ruby -v)"

log.info "Your Ruby Interpreter v${version}:"
log.warn " VERSION: $(log.arrows)$(ruby -v)"
log.warn " PATH: $(log.arrows)$(command -V ruby)"
echo
log.info "Remember to add the following to your ~/.bashrc or ~/.zshrc:"
log.warn "export RUBY_YJIT_ENABLE=1"

return 0
}

# ┌────────────────────────────────────────────────────────────────────────┐
#OS-X Pre-install Environment
#MacOS Pre-install Environment │
# └────────────────────────────────────────────────────────────────────────┘
function ruby.pre-install-darwin() {
local version="$1"

log.info "ruby.pre-install-darwin()"

if command -v brew >/dev/null; then
echo "Found brew located at $(command -v brew)"
if command -v brew >/dev/null 2>&1; then
echo "Found Homebrew located at $(command -v brew)"
else
echo "Please install homebrew, by following instructions here:"
echo "https://brew.sh"
exit 1
log.warn "HomeBrew was not found on your Mac OS-X, Installing..."
local code=0
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
code=$?
if [[ ${code} -ne 0 ]]; then
log.error "Failed to install Homebrew, exit code ${code}"
log.error "Please go to https://brew.sh and install it manually."
exit 1
fi
fi

set -x

brew update && brew upgrade rbenv ruby-build || true
brew install jemalloc rust openssl@3

eval "$(rbenv init -)"

export RUBY_CFLAGS="-Wno-error=implicit-function-declaration"
export CPPFLAGS="-I$HOMEBREW_PREFIX/opt/jemalloc/include"
export LDFLAGS="-L$HOMEBREW_PREFIX/opt/jemalloc/lib"
export RUBY_CONFIGURE_OPTS="--enable-yjit --with-jemalloc"

local openssl_dir="/opt/homebrew/opt/openssl@3"

if [[ -d "${openssl_dir}" ]]; then
local openssl_dir=/opt/homebrew/opt/openssl
if [[ -d ${openssl_dir} ]]; then
export RUBY_CONFIGURE_OPTS="${RUBY_CONFIGURE_OPTS} --with-openssl-dir=${openssl_dir}"
fi

set +x
}

Expand All @@ -276,13 +295,26 @@ function ruby.pre-install-linux() {

set -x
sudo apt-get install libjemalloc2 rustc
export RUBY_CONFIGURE_OPTS="--enable-yjit --with-jemalloc --with-openssl"
set +x
export RUBY_CONFIGURE_OPTS="--enable-yjit --with-jemalloc --with-openssl"

command -V rbenv >/dev/null 2>&1 || {
set -x
sudo apt-get install rbenv ruby-build
set +x
}

eval "$(rbenv init -)"
}

# ┌────────────────────────────────────────────────────────────────────────┐
# │ Installation │
# └────────────────────────────────────────────────────────────────────────┘

# sets ${ruby_version}
ruby.detect-version "$@"

# Installs it
ruby.install "${ruby_version}"


0 comments on commit b9f4a36

Please sign in to comment.