From d81d8951744f9afaddf13d251564198f9682a711 Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Sat, 13 Mar 2021 22:26:06 +0100 Subject: [PATCH 1/2] * Will use existing kerl from `$PATH` (like installed by Homebrew) or fetch specific version when setting `ASDF_KERL_VERSION`. * Will use git to clone `kerl` quitly and checkout versioned tags instead of downloading from Github CDN. * Enable shell docs out of the box by default and allow opt out using `KERL_BUILD_DOCS="no" - technically any value will opt out, kerl just checks if it's set, and not its value. Since we're opting in by default, we will check `!= "yes"` for opt out. * Will come with out of the box settings for `KERL_CONFIGURE_OPTIONS` with additional settings for macOS that matches `Homebrew` * `--disable-debug` * `--disable-silent-rules` * `--enable-dynamic-ssl-lib` * `--enable-hipe` * `--enable-sctp` * `--enable-shared-zlib` * `--enable-smp-support` * `--enable-threads` * `--enable-wx` * `--without-javac` * macOS only: * `--with-ssl=$(brew --prefix openssl)` * `--enable-darwin-64bit` * `--enable-kernel-poll` * `--with-dynamic-trace=dtrace` * macOS only: Unless custom `KERL_CONFIGURE_OPTIONS`, asdf-erlang will default to using Homebrew for following dependencies: - `autoconf` - `libtool` - `openssl` - `wxmac` This will allow `asdf-erlang` & `asdf-elixir` to be used out of the box and be much easier for majority of macOS users. Avoiding using esotoric configuration and environment variables to keep track for various plugins should be a focus. Allowing someone to just put a plugin in, and pick a version without sifting through massive documentation and configuration is beneficial. --- bin/install | 80 ++++++++++++++++++++++++++++++++++++++++++++------- bin/list-all | 9 +++--- bin/uninstall | 10 +++---- bin/utils.sh | 45 ----------------------------- lib/utils.sh | 78 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 158 insertions(+), 64 deletions(-) delete mode 100755 bin/utils.sh create mode 100755 lib/utils.sh diff --git a/bin/install b/bin/install index 21ac644..263d583 100755 --- a/bin/install +++ b/bin/install @@ -1,12 +1,71 @@ #!/usr/bin/env bash +export KERL_BUILD_DOCS="${KERL_BUILD_DOCS:-yes}" + set -e -# shellcheck source=../bin/utils.sh -source "$(dirname "$0")/utils.sh" + +# shellcheck source=../lib/utils.sh +source "$(dirname $0)/../lib/utils.sh" +ensure_kerl_setup install_erlang() { - ensure_kerl_setup + + + if [ -z "$KERL_CONFIGURE_OPTIONS" ]; then + echo "KERL_CONFIGURE_OPTIONS is not set, will use default settings." + + export KERL_CONFIGURE_OPTIONS="--disable-debug --disable-silent-rules --enable-dynamic-ssl-lib" + export KERL_CONFIGURE_OPTIONS="$KERL_CONFIGURE_OPTIONS --enable-hipe --enable-sctp --enable-shared-zlib --enable-smp-support" + export KERL_CONFIGURE_OPTIONS="$KERL_CONFIGURE_OPTIONS --enable-threads --enable-wx --without-javac" + + if [ "$(uname -s)" = "Darwin" ]; then + echo "Using Homebrew for dependencies." + if [ -x "$(command -v brew)" ]; then + if [ ! -d "$(brew --prefix autoconf)" ]; then + echo "Missing autoconf from Homebrew" + echo "brew install autoconf" + exit 1 + fi + if [ ! -d "$(brew --prefix libtool)" ]; then + echo "Missing libtool from Homebrew" + echo "brew install libtool" + exit 1 + fi + if [ ! -d "$(brew --prefix openssl)" ]; then + echo "Missing openssl from Homebrew" + echo "brew install openssl" + exit 1 + fi + if [ ! -d "$(brew --prefix wxmac)" ]; then + echo "Missing wxmac from Homebrew" + echo "brew install wxmac" + exit 1 + fi + export KERL_CONFIGURE_OPTIONS="$KERL_CONFIGURE_OPTIONS --with-ssl=$(brew --prefix openssl) --enable-darwin-64bit --enable-kernel-poll --with-dynamic-trace=dtrace" + else + echo "Homebrew is not installed or in PATH" + echo "To install without Homebrew, set your own KERL_CONFIGURE_OPTIONS" + fi + fi + fi + + + + + + + echo "Installing Erlang $ASDF_INSTALL_VERSION" + if [ "$KERL_BUILD_DOCS" != "yes" ]; then + unset KERL_BUILD_DOCS + echo "without documentation" + else + echo "with documentation" + fi + echo "With KERL_CONFIGURE_OPTIONS set to: " + echo "$KERL_CONFIGURE_OPTIONS" + echo "---" + local asdf_activation_version local build_name @@ -14,19 +73,20 @@ install_erlang() { export MAKEFLAGS="-j$ASDF_CONCURRENCY" - $(kerl_path) delete installation "$build_name" || true - $(kerl_path) delete build "$build_name" || true + $(kerl_executable) delete installation "$build_name" || true + $(kerl_executable) delete build "$build_name" || true + if [ "$ASDF_INSTALL_TYPE" = "ref" ]; then asdf_activation_version="$ASDF_INSTALL_TYPE:$ASDF_INSTALL_VERSION" - $(kerl_path) build git "${OTP_GITHUB_URL:-https://github.com/erlang/otp.git}" "$ASDF_INSTALL_VERSION" "$build_name" + $(kerl_executable) build git "${OTP_GITHUB_URL:-https://github.com/erlang/otp.git}" "$ASDF_INSTALL_VERSION" "$build_name" else asdf_activation_version="$ASDF_INSTALL_VERSION" - $(kerl_path) build "$ASDF_INSTALL_VERSION" "$build_name" + $(kerl_executable) build "$ASDF_INSTALL_VERSION" "$build_name" fi - $(kerl_path) install "$build_name" "$ASDF_INSTALL_PATH" - $(kerl_path) cleanup "$ASDF_INSTALL_VERSION" + $(kerl_executable) install "$build_name" "$ASDF_INSTALL_PATH" + $(kerl_executable) cleanup "$ASDF_INSTALL_VERSION" link_app_executables "$ASDF_INSTALL_PATH" @@ -46,7 +106,7 @@ link_app_executables() { # Link other executables to the bin directory so that asdf shims are created for them cd "$install_path/bin" - + # ln call may fail if multiple executables are found with the same name ln -s ../lib/*/bin/* ../lib/*/priv/bin/* . || true } diff --git a/bin/list-all b/bin/list-all index fb4140f..4b521c8 100755 --- a/bin/list-all +++ b/bin/list-all @@ -1,11 +1,12 @@ #!/usr/bin/env bash -source "$(dirname $0)/utils.sh" +# shellcheck source=../lib/utils.sh +source "$(dirname $0)/../lib/utils.sh" +ensure_kerl_setup -list_all() { - ensure_kerl_setup - echo "$("$(kerl_path)" list releases | sed -e 's:Run.*::' | tr '\n' ' ')" +list_all() { + echo "$("$(kerl_executable)" list releases | sed -e 's:Run.*::' | tr '\n' ' ')" } list_all diff --git a/bin/uninstall b/bin/uninstall index f32b02a..8d2e7c8 100755 --- a/bin/uninstall +++ b/bin/uninstall @@ -2,14 +2,14 @@ set -e -source "$(dirname $0)/utils.sh" - +# shellcheck source=../lib/utils.sh +source "$(dirname $0)/../lib/utils.sh" ensure_kerl_setup # Remove the installation and build if the installation was done by kerl -if $(kerl_path) list installations | grep "$ASDF_INSTALL_PATH"; then - $(kerl_path) delete build "asdf_$ASDF_INSTALL_VERSION" - $(kerl_path) delete installation "$ASDF_INSTALL_PATH" +if $(kerl_executable) list installations | grep "$ASDF_INSTALL_PATH"; then + $(kerl_executable) delete build "asdf_$ASDF_INSTALL_VERSION" + $(kerl_executable) delete installation "$ASDF_INSTALL_PATH" fi # Finally make sure the directory is actually removed regardless of what the diff --git a/bin/utils.sh b/bin/utils.sh deleted file mode 100755 index 423c9db..0000000 --- a/bin/utils.sh +++ /dev/null @@ -1,45 +0,0 @@ -KERL_VERSION="2.1.0" - -ensure_kerl_setup() { - set_kerl_env - ensure_kerl_installed - update_available_versions -} - -ensure_kerl_installed() { - if [ ! -f "$(kerl_path)" ]; then - download_kerl - elif [ "$("$(kerl_path)" version)" != "$KERL_VERSION" ]; then - # If the kerl file already exists and the version does not match, remove - # it and download the correct version - rm "$(kerl_path)" - download_kerl - fi -} - -download_kerl() { - # Print to stderr so asdf doesn't assume this string is a list of versions - echo "Downloading kerl..." >&2 - - local kerl_url="https://raw.githubusercontent.com/kerl/kerl/${KERL_VERSION}/kerl" - - curl -Lso "$(kerl_path)" $kerl_url - chmod +x "$(kerl_path)" -} - -kerl_path() { - echo "$(dirname "$(dirname $0)")/kerl" -} - -set_kerl_env() { - local kerl_home - kerl_home="$(dirname "$(dirname "$0")")/kerl-home" - mkdir -p "$kerl_home" - export KERL_BASE_DIR="$kerl_home" - export KERL_BUILD_BACKEND="git" - export KERL_CONFIG="$kerl_home/.kerlrc" -} - -update_available_versions() { - "$(kerl_path)" update releases > /dev/null -} diff --git a/lib/utils.sh b/lib/utils.sh new file mode 100755 index 0000000..cf1b2c5 --- /dev/null +++ b/lib/utils.sh @@ -0,0 +1,78 @@ +export KERL_VERSION="${ASDF_KERL_VERSION:-2.1.1}" + + + +echoerr() { + >&2 echo -e "\033[0;31m$1\033[0m" +} + +ensure_kerl_setup() { + export KERL_BASE_DIR="$(kerl_path)" + export KERL_CONFIG="$(kerl_path)/kerlrc" + #export KERL_BUILD_BACKEND="git" + ensure_kerl_installed +} + +ensure_kerl_installed() { + # If kerl exists + if [ -x "$(kerl_executable)" ]; then + # But was passed an expected version + if [ -n "${ASDF_KERL_VERSION:-}" ]; then + current_kerl_version="$("$(kerl_executable)" version)" + # Check if expected version matches current version + if [ "$current_kerl_version" != "$KERL_VERSION" ]; then + # If not, reinstall with ASDF_KERL_VERSION + download_kerl + fi + fi + else + # kerl does not exist, so install using default value in KERL_VERSION + download_kerl + fi +} + + + +download_kerl() { + # Remove directory in case it still exists from last download + rm -rf "$(kerl_source_path)" + rm -rf "$(kerl_path)" + + # Print to stderr so asdf doesn't assume this string is a list of versions + echoerr "Downloading kerl $KERL_INSTALL_VERSION" + + # Clone down and checkout the correct kerl version + git clone https://github.com/kerl/kerl.git "$(kerl_source_path)" --quiet + (cd "$(kerl_source_path)"; git checkout $KERL_INSTALL_VERSION --quiet;) + + mkdir -p "$(kerl_path)/bin" + mv "$(kerl_source_path)/kerl" "$(kerl_executable)" + chmod +x "$(kerl_executable)" + + rm -rf "$(kerl_source_path)" +} + +asdf_erlang_plugin_path() { + echo "$(dirname "$(dirname "$0")")" +} + +plugin_name() { + basename $(asdf_erlang_plugin_path) +} +kerl_path() { + echo "$(asdf_erlang_plugin_path)/kerl" +} + +kerl_source_path() { + echo "$(kerl_path)-source" +} + + +kerl_executable() { + #Check if kerl exists without an expected version + if [ -x "$(command -v kerl)" ] && [ -z "${ASDF_KERL_VERSION:-}" ]; then + echo "$(command -v kerl)" + else + echo "$(kerl_path)/bin/kerl" + fi +} From de8c070b4eac31e863c98d9c3ca51da307b1ba63 Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Mon, 29 Mar 2021 00:16:26 +0200 Subject: [PATCH 2/2] Allow prebuilt binaries for macOS, opt out using ASDF_ERLANG_FROM_SOURCE=YES. Removed uninstall, asdf current uninstall will suffice. Added list-bin-paths so we can skip symlinking glob dirs. ASDF should preferably handle globs, it sorta does it for checking executables, but not when creating shims. --- README.md | 162 ++++++++++++++++++++++++--------------------- bin/install | 134 ++++++++++++++++++------------------- bin/list-all | 2 +- bin/list-bin-paths | 10 +++ bin/uninstall | 17 ----- lib/utils.sh | 123 ++++++++++++++++++++++++++++++++-- 6 files changed, 280 insertions(+), 168 deletions(-) create mode 100755 bin/list-bin-paths delete mode 100755 bin/uninstall diff --git a/README.md b/README.md index 5eefd69..4727888 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,7 @@ -# asdf-erlang -Erlang plugin for [asdf](https://github.com/asdf-vm/asdf) version manager that relies on [kerl](https://github.com/kerl/kerl) for builds. +## About -This plugin aims to combine the best of both worlds by using kerl. - -kerl's compatibility and build scripts, together with asdf's easy version switching and support for the .tool-versions file. You do not need to have kerl already installed to use this. The plugin will install it's own version of kerl automatically. +Under the hood, asdf-erlang will use existing [kerl](https://github.com/kerl/kerl) or install it if it's missing. ## Install @@ -12,38 +9,34 @@ kerl's compatibility and build scripts, together with asdf's easy version switch asdf plugin add erlang https://github.com/asdf-vm/asdf-erlang.git ``` -Important: Make sure to read the "Before asdf install" section below to install dependencies! - -## Use +## Requirements -Check [asdf](https://github.com/asdf-vm/asdf) readme for instructions on how to install & manage versions of Erlang. To specify custom options you [can set environment variables just as you would when using kerl](https://github.com/kerl/kerl#kerl_base_dir). For example, to skip the java dependency during installation use: +### macOS +* Homebrew +* Xcode CLI tools +* openssl +* wxmac -``` -$ export KERL_CONFIGURE_OPTIONS="--disable-debug --without-javac" -$ asdf install erlang -``` +`brew install openssl wxmac` -You can also install Erlang from git, or provide the url to a fork and build from git. +Addtional dependencies if building from source: +`brew install autoconf libtool ` -``` -$ asdf install erlang ref:master +macOS will by default try to fetch and use prebuilt. -$ export OTP_GITHUB_URL="https://github.com/basho/otp" -$ asdf install erlang ref:basho -``` +Note, for macOS 10.15.4 and newer, 22.3.1 is the earliest version that can be built from source. Earlier versions will fail to compile. See [this issue](https://github.com/kerl/kerl/issues/335#issuecomment-605487028) for details. -See [kerl](https://github.com/kerl/kerl) for the complete list of customization options. Note that the `KERL_BASE_DIR` and `KERL_CONFIG` environment variables are set by the plugin when it runs kerl so it will not be possible to customize them. -## Before `asdf install` -## Ubuntu and Debian +### Ubuntu and Debian Note that if you are using a previous version of Linux, you may need a different version of one of the below libraries. -### Ubuntu 16.04 LTS "Xenial Xerus" -Install the build tools (dpkg-dev g++ gcc libc6-dev make debianutils m4 perl) +#### Ubuntu 16.04 LTS "Xenial Xerus" + +Install the build tools (dpkg-dev g++ gcc libc6-dev make debianutils m4 perl) `apt-get -y install build-essential autoconf` Needed for HiPE (native code) support, but already installed by autoconf @@ -64,15 +57,15 @@ ODBC support (libltdl3-dev odbcinst1debian2 unixodbc) For building documentation: `apt-get install xsltproc fop` -If you want to install all the above: +If you want to install all the above: `apt-get -y install build-essential autoconf m4 libncurses5-dev libwxgtk3.0-dev libgl1-mesa-dev libglu1-mesa-dev libpng-dev libssh-dev unixodbc-dev xsltproc fop` -### Ubuntu 20.04 LTS +#### Ubuntu 20.04 LTS -If you want to install all the above: +If you want to install all the above: `apt-get -y install build-essential autoconf m4 libncurses5-dev libwxgtk3.0-gtk3-dev libgl1-mesa-dev libglu1-mesa-dev libpng-dev libssh-dev unixodbc-dev xsltproc fop libxml2-utils libncurses-dev openjdk-11-jdk` -## Arch Linux +#### Arch Linux Provides most of the needed build tools. `pacman -S --needed base-devel` @@ -88,38 +81,7 @@ For building ssl ODBC support `sudo pacman -S unixodbc` -## OSX - -Note, for MacOS 10.15.4 and newer, 22.3.1 is the earliest version that can be installed through `kerl` (and, therefore, `asdf`). Earlier versions will fail to compile. See [this issue](https://github.com/kerl/kerl/issues/335#issuecomment-605487028) for details. - -Install the build tools -`brew install autoconf` - -For building with wxWidgets (start observer or debugger!) -`brew install wxmac` - -### Dealing with OpenSSL issues on macOS - -You may encounter an SSL error with an output along these lines: - -``` -crypto : No usable OpenSSL found -ssh : No usable OpenSSL found -ssl : No usable OpenSSL found -``` - -This issue has been documented [on -`kerl`](https://github.com/kerl/kerl#compiling-crypto-on-macs). If you see this -error, you can use the `--with-ssl` flag with a path before installing Erlang. Here is -an example that skips the java dependency and also sets a specific (and existing) -path for OpenSSL installed via brew on macOS. - -``` -$ export KERL_CONFIGURE_OPTIONS="--without-javac --with-ssl=$(brew --prefix openssl)" -$ asdf install erlang -``` - -## CentOS & Fedora +#### CentOS & Fedora These steps assume a most recent build of CentOS (currently tested on CentOS 7.5 x64 & Fedora 28 x64) @@ -148,7 +110,7 @@ ODBC support for the documentation to be built `sudo yum install -y libxslt fop` -## Solus +#### Solus Install the build tools @@ -183,7 +145,7 @@ sudo eopkg it -c system.devel sudo eopkg install wxwidgets-devel mesalib-devel libglu-devel fop unixodbc-devel openjdk-8 openjdk-8-devel ``` -### OpenJDK issues on Solus +#### OpenJDK issues on Solus I ran into an issue where `javac` wasn't a recognized command in the terminal despite having installed `openjdk-8` and `openjdk-8-devel`. Turns out it wasn't added to `PATH` by default. So simply add it to `PATH` like so: @@ -196,24 +158,76 @@ PATH=$PATH:$JAVA_HOME/bin source ~/.bashrc ``` -## Getting Erlang documentation +## Use + +Check [asdf](https://github.com/asdf-vm/asdf) readme for instructions on how to install & manage versions of Erlang. To specify custom options you [can set environment variables just as you would when using kerl](https://github.com/kerl/kerl#build-configuration). + +### `KERL_CONFIGURE_OPTIONS ` +To use custom build options you could set: + +```shell +$ export KERL_CONFIGURE_OPTIONS="--disable-debug --without-javac" +$ asdf install erlang +``` +By default it will be set to: + +```shell + --disable-debug --disable-silent-rules --enable-dynamic-ssl-lib + --enable-hipe --enable-sctp --enable-shared-zlib --enable-smp-support + --enable-threads --enable-wx --without-javac +additional for macOS + --with-ssl=$(brew --prefix openssl) --enable-darwin-64bit --enable-kernel-poll --with-dynamic-trace=dtrace + +``` + +### `OTP_GITHUB_URL` +To use a different Erlang source from git set the url to a fork: + +```shell +$ asdf install erlang ref:master + +$ export OTP_GITHUB_URL="https://github.com/basho/otp" +$ asdf install erlang ref:basho +``` + +### Opting out of prebuilt for macOS + +By default macOS will use prebuilt binaries if they're available but you can opt out by setting any of these: +* `OTP_GITHUB_URL`, +* `KERL_CONFIGURE_OPTIONS` +* `ASDF_ERLANG_FROM_SOURCE` + +It will also opt out if `ASDF_INSTALL_TYPE` is `ref` + + +### Opting out of Erlang documentation +To opt out of building documenation you could set: +```shell +export KERL_BUILD_DOCS=NO +``` + +Erlang may come with documentation included (as man pages, pdfs and html files). This allows typing `erl -man mnesia` to get info on `mnesia` module. asdf-erlang uses kerl for builds, and [kerl](https://github.com/kerl/kerl) is capable of building the docs for specified version of Erlang. -Erlang may come with documentation included (as man pages, pdfs and html files). This allows typing `erl -man mnesia` to get info on `mnesia` module. asdf-erlang uses kerl for builds, and [kerl](https://github.com/kerl/kerl) is capable of building the docs for specified version of Erlang. +For kerl to be able to build Erlang documentation requirements have to be met with additional dependencies have to be installed. For detailed list of dependencies for your OS please refer to the specific section above. -For kerl to be able to build Erlang documentation two requirements have to be met: -1. `KERL_BUILD_DOCS` environment variable has to be set -2. Additional dependencies have to be installed. For detailed list of dependencies for your OS please refer to the specific section above -**Note:** Environment variable has to be set before `asdf install erlang ` is executed, to take effect. +### Use a specific version of Kerl -### Setting the environment variable in bash +To use a different version of kerl you could set: +```shell +export ASDF_KERL_VERSION="2.1.1" +``` + +### Kerl Config -Type: `export KERL_BUILD_DOCS=yes` to create `KERL_BUILD_DOCS` environment variable and set it to `true`. This line could be added to your `.bashrc` in case you want `KERL_BUILD_DOCS` to be set for future (future installations of Erlang). +Note that the `KERL_BASE_DIR` and `KERL_CONFIG` environment variables are set by the plugin to: +```shell +KERL_BASE_DIR="${ASDF_KERL_BASE_DIR:-${ASDF_DATA_DIR:-$HOME/.asdf}/tmp/$(plugin_name)/kerl}" +KERL_CONFIG="${KERL_BASE_DIR:-$(kerl_path)}/.kerlrc" +``` +You can override both. -To remove environment variable: `unset KERL_BUILD_DOCS`. +See [kerl](https://github.com/kerl/kerl#locations-on-disk) for the complete list of customization options. -### Setting the environment variable in fish shell -Type: `set -xg KERL_BUILD_DOCS yes` to set environment variable. In case you want it to be persisted between sessions (machine reboots - for example for future installations) type `set -xU KERL_BUILD_DOCS yes`. -To remove environment variable type: `set -e KERL_BUILD_DOCS`. diff --git a/bin/install b/bin/install index 263d583..1b7d878 100755 --- a/bin/install +++ b/bin/install @@ -5,110 +5,104 @@ export KERL_BUILD_DOCS="${KERL_BUILD_DOCS:-yes}" set -e + # shellcheck source=../lib/utils.sh source "$(dirname $0)/../lib/utils.sh" ensure_kerl_setup + install_erlang() { + if [ -z "$OTP_GITHUB_URL" ] && [ "$ASDF_INSTALL_TYPE" = "version" ] && [ -z "$KERL_CONFIGURE_OPTIONS"] && [ -z "$ASDF_ERLANG_FROM_SOURCE" ] && os_name="$(get_macos_marketing_name)"; then + if download_url="$(macos_get_download_url $os_name)"; then + macos_install_from_prebuilt "$download_url" + else + printf 'Fallback to building from source. \n' + install_from_source + fi + else + install_from_source + fi +} - if [ -z "$KERL_CONFIGURE_OPTIONS" ]; then - echo "KERL_CONFIGURE_OPTIONS is not set, will use default settings." - export KERL_CONFIGURE_OPTIONS="--disable-debug --disable-silent-rules --enable-dynamic-ssl-lib" - export KERL_CONFIGURE_OPTIONS="$KERL_CONFIGURE_OPTIONS --enable-hipe --enable-sctp --enable-shared-zlib --enable-smp-support" - export KERL_CONFIGURE_OPTIONS="$KERL_CONFIGURE_OPTIONS --enable-threads --enable-wx --without-javac" - if [ "$(uname -s)" = "Darwin" ]; then - echo "Using Homebrew for dependencies." - if [ -x "$(command -v brew)" ]; then - if [ ! -d "$(brew --prefix autoconf)" ]; then - echo "Missing autoconf from Homebrew" - echo "brew install autoconf" - exit 1 - fi - if [ ! -d "$(brew --prefix libtool)" ]; then - echo "Missing libtool from Homebrew" - echo "brew install libtool" - exit 1 - fi - if [ ! -d "$(brew --prefix openssl)" ]; then - echo "Missing openssl from Homebrew" - echo "brew install openssl" - exit 1 - fi - if [ ! -d "$(brew --prefix wxmac)" ]; then - echo "Missing wxmac from Homebrew" - echo "brew install wxmac" - exit 1 - fi - export KERL_CONFIGURE_OPTIONS="$KERL_CONFIGURE_OPTIONS --with-ssl=$(brew --prefix openssl) --enable-darwin-64bit --enable-kernel-poll --with-dynamic-trace=dtrace" - else - echo "Homebrew is not installed or in PATH" - echo "To install without Homebrew, set your own KERL_CONFIGURE_OPTIONS" - fi - fi - fi +macos_install_from_prebuilt() { + macos_check_homebrew_setup + + mkdir -p "$ASDF_INSTALL_PATH" + mkdir -p "$ASDF_DOWNLOAD_PATH" + local download_url="$1" + printf 'Downloading %s. \n' "$download_url" + # Strip "erlang/23.3" folder structure off the tarball when extracting. + curl -L "$download_url" | tar xf - --directory="$ASDF_DOWNLOAD_PATH" --strip-components=2 + # We're not keeping the same directory structure as Homebrew. + local replacement_pattern="@@HOMEBREW_CELLAR@@/erlang/$ASDF_INSTALL_VERSION/lib/erlang" + # Replace the homebrew URL with something compatible with asdf + grep -rl --null "$replacement_pattern" "$ASDF_DOWNLOAD_PATH/lib/erlang" | xargs -0 sed -i '' "s:$replacement_pattern:$ASDF_INSTALL_PATH:g" + + local linked_libs=( + "$ASDF_DOWNLOAD_PATH/lib/erlang/lib/"crypto-*"/priv/lib/crypto.so" + "$ASDF_DOWNLOAD_PATH/lib/erlang/lib/"wx-*"/priv/wxe_driver.so" + ) + + # Link Crypto & Wx to brew prefix + macos_update_linked_paths "${linked_libs[@]}" + + # Move from download to install + # In the future, maybe copy would be better, but I think keeping downloads is a bad design. + mv -f "$ASDF_DOWNLOAD_PATH/lib/erlang/"* "$ASDF_INSTALL_PATH" +} - echo "Installing Erlang $ASDF_INSTALL_VERSION" +install_from_source() { + printf 'Building version %s %s for from source' "$(plugin_name)" "$ASDF_INSTALL_VERSION" if [ "$KERL_BUILD_DOCS" != "yes" ]; then unset KERL_BUILD_DOCS - echo "without documentation" + printf ' without documentation. \n' else - echo "with documentation" + printf ' with documentation. \n' fi - echo "With KERL_CONFIGURE_OPTIONS set to: " - echo "$KERL_CONFIGURE_OPTIONS" - echo "---" - local asdf_activation_version - local build_name + if [ -z "$KERL_CONFIGURE_OPTIONS" ]; then + printf 'KERL_CONFIGURE_OPTIONS is not set, will use default settings. \n' - build_name="asdf_$ASDF_INSTALL_VERSION" + export KERL_CONFIGURE_OPTIONS="--disable-debug --disable-silent-rules --enable-dynamic-ssl-lib" + export KERL_CONFIGURE_OPTIONS="$KERL_CONFIGURE_OPTIONS --enable-hipe --enable-sctp --enable-shared-zlib --enable-smp-support" + export KERL_CONFIGURE_OPTIONS="$KERL_CONFIGURE_OPTIONS --enable-threads --enable-wx --without-javac" - export MAKEFLAGS="-j$ASDF_CONCURRENCY" + if [ "$(uname -s)" = "Darwin" ]; then + macos_check_homebrew_setup "SOURCE" + export KERL_CONFIGURE_OPTIONS="$KERL_CONFIGURE_OPTIONS --with-ssl=$(brew --prefix openssl) --enable-darwin-64bit --enable-kernel-poll --with-dynamic-trace=dtrace" + fi + fi - $(kerl_executable) delete installation "$build_name" || true - $(kerl_executable) delete build "$build_name" || true + + printf 'With KERL_CONFIGURE_OPTIONS set to: \n %s \n' "$KERL_CONFIGURE_OPTIONS" + + + local build_name="asdf_$ASDF_INSTALL_VERSION" + + export MAKEFLAGS="-j$ASDF_CONCURRENCY" if [ "$ASDF_INSTALL_TYPE" = "ref" ]; then - asdf_activation_version="$ASDF_INSTALL_TYPE:$ASDF_INSTALL_VERSION" $(kerl_executable) build git "${OTP_GITHUB_URL:-https://github.com/erlang/otp.git}" "$ASDF_INSTALL_VERSION" "$build_name" else - asdf_activation_version="$ASDF_INSTALL_VERSION" $(kerl_executable) build "$ASDF_INSTALL_VERSION" "$build_name" fi $(kerl_executable) install "$build_name" "$ASDF_INSTALL_PATH" - $(kerl_executable) cleanup "$ASDF_INSTALL_VERSION" - - link_app_executables "$ASDF_INSTALL_PATH" - - echo - echo "Erlang $ASDF_INSTALL_VERSION has been installed. Activate globally with:" - echo - echo " asdf global erlang $asdf_activation_version" - echo - echo "Activate locally in the current folder with:" - echo - echo " asdf local erlang $asdf_activation_version" - echo -} - -link_app_executables() { - local install_path=$1 - # Link other executables to the bin directory so that asdf shims are created for them - cd "$install_path/bin" + if [ -z "${ASDF_KERL_BASE_DIR:-}" ]; then + rm -rf "$KERL_BASE_DIR" + fi - # ln call may fail if multiple executables are found with the same name - ln -s ../lib/*/bin/* ../lib/*/priv/bin/* . || true } + install_erlang diff --git a/bin/list-all b/bin/list-all index 4b521c8..56e222b 100755 --- a/bin/list-all +++ b/bin/list-all @@ -6,7 +6,7 @@ ensure_kerl_setup list_all() { - echo "$("$(kerl_executable)" list releases | sed -e 's:Run.*::' | tr '\n' ' ')" + printf "$("$(kerl_executable)" list releases | sed -e 's:Run.*::' | tr '\n' ' ')" } list_all diff --git a/bin/list-bin-paths b/bin/list-bin-paths new file mode 100755 index 0000000..7f0c254 --- /dev/null +++ b/bin/list-bin-paths @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +if [ -d "$ASDF_INSTALL_PATH" ]; then +( + binary_paths="bin lib/*/bin lib/*/priv/bin" + cd "$ASDF_INSTALL_PATH" + printf '%s ' $binary_paths +) +fi + diff --git a/bin/uninstall b/bin/uninstall deleted file mode 100755 index 8d2e7c8..0000000 --- a/bin/uninstall +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -set -e - -# shellcheck source=../lib/utils.sh -source "$(dirname $0)/../lib/utils.sh" -ensure_kerl_setup - -# Remove the installation and build if the installation was done by kerl -if $(kerl_executable) list installations | grep "$ASDF_INSTALL_PATH"; then - $(kerl_executable) delete build "asdf_$ASDF_INSTALL_VERSION" - $(kerl_executable) delete installation "$ASDF_INSTALL_PATH" -fi - -# Finally make sure the directory is actually removed regardless of what the -# previous kerl commands did -rm -rf "$ASDF_INSTALL_PATH" || true diff --git a/lib/utils.sh b/lib/utils.sh index cf1b2c5..b7d2e1d 100755 --- a/lib/utils.sh +++ b/lib/utils.sh @@ -2,14 +2,15 @@ export KERL_VERSION="${ASDF_KERL_VERSION:-2.1.1}" -echoerr() { - >&2 echo -e "\033[0;31m$1\033[0m" +printerr() { + >&2 printf '\033[0;31m%s\033[0m \n' "$1" } ensure_kerl_setup() { - export KERL_BASE_DIR="$(kerl_path)" - export KERL_CONFIG="$(kerl_path)/kerlrc" - #export KERL_BUILD_BACKEND="git" + + export KERL_BASE_DIR="${ASDF_KERL_BASE_DIR:-${ASDF_DATA_DIR:-$HOME/.asdf}/tmp/$(plugin_name)/kerl}" + export KERL_CONFIG="${KERL_BASE_DIR:-$(kerl_path)}/.kerlrc" + ensure_kerl_installed } @@ -39,7 +40,7 @@ download_kerl() { rm -rf "$(kerl_path)" # Print to stderr so asdf doesn't assume this string is a list of versions - echoerr "Downloading kerl $KERL_INSTALL_VERSION" + printerr 'Installing %s ' "$KERL_INSTALL_VERSION" # Clone down and checkout the correct kerl version git clone https://github.com/kerl/kerl.git "$(kerl_source_path)" --quiet @@ -52,6 +53,7 @@ download_kerl() { rm -rf "$(kerl_source_path)" } + asdf_erlang_plugin_path() { echo "$(dirname "$(dirname "$0")")" } @@ -59,6 +61,7 @@ asdf_erlang_plugin_path() { plugin_name() { basename $(asdf_erlang_plugin_path) } + kerl_path() { echo "$(asdf_erlang_plugin_path)/kerl" } @@ -76,3 +79,111 @@ kerl_executable() { echo "$(kerl_path)/bin/kerl" fi } + +get_macos_marketing_name() { + if [ "$(uname -s)" = "Darwin" ]; then + osx_num=$(SYSTEM_VERSION_COMPAT=1 sw_vers -productVersion | awk -F '[.]' '{print $2}') + OSX_MARKETING=( + ["10"]="yosemite" + ["11"]="el_capitan" + ["12"]="sierra" + ["13"]="high_sierra" + ["14"]="mojave" + ["15"]="catalina" + ["16"]="big_sur" + ) + + if [[ -n "${OSX_MARKETING[$osx_num]}" ]]; then + printf '%s\n' "${OSX_MARKETING[$osx_num]}" + return 0 + else + return 1 + fi + else + return 1 + fi +} + +macos_get_download_url() { + local os_name=$( + if [ "$(uname -m)" = "arm64" ]; then + printf "arm64_%s" "$1" + else + printf "%s" "$1" + fi + ) + + printf 'Looking for prebuilt %s %s on %s. \n' "$(plugin_name)" "$ASDF_INSTALL_VERSION" "$os_name" >&2 + local erlang_version="erlang-$ASDF_INSTALL_VERSION" + local file_name="$erlang_version.$os_name.bottle.tar.gz" + local url="https://bintray.com/homebrew/bottles/download_file?file_path=$file_name" + + if curl --output /dev/null --silent --head --fail "$url"; then + printf '%s' $url + return 0 + else + printerr 'No prebuilt %s %s for %s is available. ' "$(plugin_name)" "$ASDF_INSTALL_VERSION" "$os_name" + return 1 + fi +} + +macos_update_linked_paths() { + + + local file_paths=("$@") + + local brew_prefix="$(brew --prefix)" + local replacement="@@HOMEBREW_PREFIX@@" + + for file in "${file_paths[@]}"; do + local changes=() + for line in $(otool -L "$file"); do + if [[ "$line" == "$replacement"* ]]; then + local result="${line/$replacement/$brew_prefix}" + changes+=("-change" "$line" "$result") + fi + done + local command=(install_name_tool "${changes[@]}" "$file") + "${command[@]}" + + # https://github.com/Homebrew/brew/blob/565becc90433df57c9ec6262dec1f41797fb680b/Library/Homebrew/os/mac/keg.rb#L21 + cp "$file" "$file.backup" + codesign -s - -f -vvvvvv "$file.backup" + mv -f "$file.backup" "$file" + done + +} + +macos_check_homebrew_setup() { + + local brew_function="${1:-PREBUILT}" + + printf 'Checking Homebrew for dependencies. \n' + if [ -x "$(command -v brew)" ]; then + if [ "$brew_function" = "SOURCE" ] && [ ! -d "$(brew --prefix autoconf)" ]; then + printerr 'Missing autoconf from Homebrew ' + printf 'Fix with: brew install autoconf \n' + exit 1 + fi + if [ "$brew_function" = "SOURCE" ] && [ ! -d "$(brew --prefix libtool)" ]; then + printerr 'Missing libtool from Homebrew' + printf 'Fix with: brew install libtool \n' + exit 1 + fi + if [ ! -d "$(brew --prefix openssl)" ]; then + printerr 'Missing openssl from Homebrew' + printf 'Fix with: brew install openssl \n' + exit 1 + fi + if [ ! -d "$(brew --prefix wxmac)" ]; then + printerr 'Missing wxmac from Homebrew' + printf 'Fix with: brew install wxmac \n' + exit 1 + fi + return 0 + else + printerr 'Homebrew is not installed or in PATH' + printf 'To install without Homebrew, set your own KERL_CONFIGURE_OPTIONS \n' + exit 1 + fi +}