From 2f62811220093bb9ad4766e6aa075a47cf41fced Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Tue, 22 Feb 2022 19:17:19 +0000 Subject: [PATCH] feat(emacs): add hacky evm (Emacs Version Manager) script for Linux --- bin/evm | 312 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ zshenv | 5 + 2 files changed, 317 insertions(+) create mode 100755 bin/evm diff --git a/bin/evm b/bin/evm new file mode 100755 index 0000000..dd77511 --- /dev/null +++ b/bin/evm @@ -0,0 +1,312 @@ +#! /usr/bin/env bash +set -e + +show-help() { + echo 'usage: evm ' + echo '' + echo 'Commands:' + echo ' help - Show this message' + echo ' info - Show evm configuration details.' + echo ' list - List installed versions.' + echo ' use - Activate specified version.' + echo ' install - Download, compile and install Emacs.' + echo ' build-deps - Install build dependencies for Emacs.' +} + +main() { + local command="$1" + shift 1 + + check-os + + if [ -z "$command" ]; then + show-help 1>&2 + exit 1 + fi + + case "$command" in + build-deps | deps) + install-deps "$@" + ;; + info) + info + ;; + install) + install "$@" + ;; + use | switch | activate) + activate-version "$@" + ;; + list | ls | versions) + versions "$@" + ;; + *) + show-help + ;; + esac +} + +check-os() { + if [[ "$OSTYPE" != "linux"* ]]; then + echo "Only Linux-based operating systems are supported" 1>&2 + exit 2 + fi +} + +check-write-op() { + if conf-root-mode && [ "$UID" != "0" ]; then + echo "ERROR: evm must be run as root when" \ + "EVM_MODE is not empty or \"user\"." 1>&2 + exit 1 + fi +} + +trim() { + local string="$*" + string="${string#"${string%%[![:space:]]*}"}" + string="${string%"${string##*[![:space:]]}"}" + echo -n "$string" +} + +conf-emacs-src-repo() { + echo "${EVM_EMACS_SRC_REPO:-emacs-mirror/emacs}" +} + +conf-mode() { + if [ "${EVM_MODE:-user}" == "user" ]; then + echo "user" + else + echo "root" + fi +} + +conf-root-mode() { + if [ "$(conf-mode)" != "root" ]; then + return 1 + fi +} + +default-root-dir() { + if conf-root-mode; then + echo "/opt/evm" + else + echo "$HOME/.evm" + fi +} + +default-shims-dir() { + if conf-root-mode; then + echo "$(conf-root-dir)/bin" + else + echo "$(conf-root-dir)/shims" + fi +} + +conf-root-dir() { + echo "${EVM_ROOT_DIR:-$(default-root-dir)}" +} + +conf-shims-dir() { + echo "${EVM_VERSIONS_DIR:-$(default-shims-dir)}" +} + +conf-versions-dir() { + echo "${EVM_VERSIONS_DIR:-$(conf-root-dir)/versions}" +} + +conf-sources-dir() { + echo "${EVM_SOURCES_DIR:-$(conf-root-dir)/sources}" +} + +conf-native-full-aot() { + echo "${EVM_NATIVE_FULL_AOT:-1}" +} + +info() { + echo "---" + echo "# evm information" + echo "evm:" + echo " mode: $(conf-mode)" + echo " paths:" + echo " root: $(conf-root-dir)" + echo " shims: $(conf-shims-dir)" + echo " versions: $(conf-versions-dir)" + echo " sources: $(conf-sources-dir)" + echo " building:" + echo " native_full_aot: $(conf-native-full-aot)" +} + +install() { + local ref="$1" + local version + local workdir + local dir + local file + local prefix + + check-write-op + + if [ -z "$ref" ]; then + echo "ERROR: git ref to install must be specified" 1>&2 + exit 1 + fi + + version="${ref//\//-}_$(date +"%Y-%m-%d")" + workdir="$(conf-sources-dir)" + prefix="$(conf-versions-dir)/${version}" + + file="emacs-${version}.tar.gz" + dir="emacs-${version}" + + if [ -d "$prefix" ]; then + echo "target $prefix directory exists, remove to force-install" 1>&2 + exit 1 + fi + + mkdir -p "$workdir" + cd "$workdir" + if [ ! -d "$dir" ]; then + if [ ! -f "$file" ]; then + curl -L "https://github.com/$(conf-emacs-src-repo)/tarball/${ref}" > \ + "$file" + else + echo "source tarball ${workdir}/${file} exists, reusing..." 1>&2 + fi + mkdir "$dir" + tar -C "$dir" --strip-components 1 -zxf "$file" + else + echo "source directory ${workdir}/${dir} exists, reusing..." 1>&2 + fi + cd "$dir" + + if [ -f "autogen/copy_autogen" ]; then + ./autogen/copy_autogen + fi + + if [ -f "autogen.sh" ]; then + ./autogen.sh + fi + + export CFLAGS="-O2" + export CC=/usr/bin/gcc-10 CXX=/usr/bin/gcc-10 + ./configure \ + --prefix="$prefix" \ + --with-json \ + --with-modules \ + --with-native-compilation \ + --with-pgtk \ + --with-xinput2 \ + --with-xwidgets + make -j "$(nproc)" NATIVE_FULL_AOT="$(conf-native-full-aot)" + make install +} + +install-deps() { + sudo apt-get update + sudo apt-get install -y \ + build-essential \ + g++-10 \ + gcc-10 \ + libcairo2-dev \ + libgccjit-10-dev \ + libgccjit0 \ + libgconf2-dev \ + libgif-dev \ + libgnutls28-dev \ + libgpm-dev \ + libgtk-3-dev \ + libharfbuzz-dev \ + libjansson-dev \ + libjansson4 \ + libjpeg-dev \ + libjpeg-dev \ + libm17n-dev \ + libmagick++-dev \ + libmagickcore-dev \ + libmailutils-dev \ + libncurses-dev \ + libotf-dev \ + libpng-dev \ + librsvg2-dev \ + libtiff-dev \ + libwebp-dev \ + libx11-dev \ + libxft-dev \ + libxml2-dev \ + libxpm-dev \ + texinfo \ + xaw3dg-dev +} + +current-version() { + trim "$(cat "$(conf-root-dir)/current" 2> /dev/null)" +} + +activate-version() { + local version="$1" + local dir + local target + local base + + check-write-op + + if [ -z "$version" ]; then + echo "ERROR: version be specified" 1>&2 + exit 1 + fi + + dir="$(conf-versions-dir)/${version}" + + if [ ! -d "$dir" ]; then + echo "ERROR: version ${version} is not installed" 1>&2 + exit 1 + fi + + mkdir -p "$(conf-shims-dir)" + + # Remove old symlinks. + find "$(conf-shims-dir)" -maxdepth 1 -mindepth 1 -type l -delete + + # Create new symlinks. + find "${dir}/bin" -type f -perm -a=x -exec ln -s "{}" "$(conf-shims-dir)/" \; + + # Create symlink to `emacs` in case it is a symlink itself. + if [ -L "${dir}/bin/emacs" ]; then + ln -s "${dir}/bin/emacs" "$(conf-shims-dir)/" + fi + + echo "$(trim "$version")" > "$(conf-root-dir)/current" +} + +versions() { + local version_dirs + local version_dir + local version + + version_dirs="$(find "$(conf-versions-dir)" -maxdepth 1 -mindepth 1 -type d \ + -exec basename "{}" \;)" + + while read -r version_dir; do + version="$(basename "$version_dir")" + + if [ "$(trim "$version")" == "$(trim "$(current-version)")" ]; then + echo "* ${version}" + else + echo " ${version}" + fi + done < <(echo "$version_dirs") +} + +print-version() { + local version_dir="$1" + local version + version="$(basename "$version_dir")" + + if [ "$(trim "$version")" == "$(trim "$(current-version)")" ]; then + echo "* ${version}" + else + echo " ${version}" + fi +} + +main "$@" diff --git a/zshenv b/zshenv index 0c0ba60..d1027e5 100644 --- a/zshenv +++ b/zshenv @@ -150,6 +150,11 @@ fi # Use custom emacs install if available path_prepend "/opt/emacs/bin" +# evm setup. +export EVM_MODE=user +export EVM_NATIVE_FULL_AOT=1 +path_prepend "$HOME/.evm/shims" + # Set Emacs-related environment variables export EMACS="emacs" export EMACSCLIENT="emacsclient"