From edc9d040ace23c46e8199d03dcc38f479aef141b Mon Sep 17 00:00:00 2001 From: John Gee Date: Mon, 19 Apr 2021 20:21:53 +1200 Subject: [PATCH] Add support for new Node.js builds for Apple silicon (#664) * On Darwin, default to x64 for node versions below 16 * Prepare for release * Add caveat about hole opened by searching for two architectures at once. * Add Apple silicon details to README --- CHANGELOG.md | 8 +++++++- README.md | 13 ++++++++++--- bin/n | 47 ++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00fce5a..22edbfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 -## [Unreleased] (date goes here) +## [7.2.0] (2021-04-18) + +### Added + +- install native arm64 Node.js on Macs with Apple silicon for Node.js 16 and higher (#664) ## [7.1.0] (2021-03-12) @@ -355,10 +359,12 @@ Only minor functional changes, but technically could break scripts relying on sp [#644]: https://github.com/tj/n/pull/644 [#649]: https://github.com/tj/n/issues/649 [#654]: https://github.com/tj/n/issues/654 +[#654]: https://github.com/tj/n/pull/664 [Unreleased]: https://github.com/tj/n/compare/master...develop +[7.2.0]: https://github.com/tj/n/compare/v7.1.0...v7.2.0 [7.1.0]: https://github.com/tj/n/compare/v7.0.2...v7.1.0 [7.0.2]: https://github.com/tj/n/compare/v7.0.1...v7.0.2 [7.0.1]: https://github.com/tj/n/compare/v7.0.0...v7.0.1 diff --git a/README.md b/README.md index 7d81f0a..f18776b 100644 --- a/README.md +++ b/README.md @@ -219,11 +219,18 @@ There is also `N_NODE_DOWNLOAD_MIRROR` for a different mirror with same layout a ## Custom Architecture -By default `n` picks the binaries matching your system architecture, e.g. `n` will download 64 bit binaries for a 64 bit system. You can override this by using the `-a` or `--arch` option. +By default `n` picks the binaries matching your system architecture. For example, on a 64 bit system `n` will download 64 bit binaries. -Download and use latest 32 bit version of Node.js: +On a Mac with Apple silicon: +- for Node.js 16 and higher, `n` defaults to arm64 binaries which run natively +- for older versions of Node.js, `n` defaults to x64 binaries which run in Rosetta 2 - n --arch x86 latest +You can override the default architecture by using the `-a` or `--arch` option. + +e.g. reinstall latest version of Node.js with x64 binaries: + + n rm current + n --arch x64 current ## Optional Environment Variables diff --git a/bin/n b/bin/n index 73e0968..c80f687 100755 --- a/bin/n +++ b/bin/n @@ -49,7 +49,7 @@ function n_grep() { # Setup and state # -VERSION="7.1.1-0" +VERSION="7.2.0" N_PREFIX="${N_PREFIX-/usr/local}" N_PREFIX=${N_PREFIX%/} @@ -169,6 +169,16 @@ function set_insecure() { WGET_OPTIONS+=( "--no-check-certificate" ) } +# +# Synposis: display_major_version numeric-version +# +display_major_version() { + local version=$1 + version="${version#v}" + version="${version%%.*}" + echo "${version}" +} + # # Synopsis: update_mirror_settings_for_version version # e.g. means using download mirror and folder is nightly @@ -190,7 +200,7 @@ function update_mirror_settings_for_version() { } # -# Synopsis: update_xz_settings_for_version version +# Synopsis: update_xz_settings_for_version numeric-version # Globals modified: # - N_USE_XZ # @@ -198,14 +208,30 @@ function update_mirror_settings_for_version() { function update_xz_settings_for_version() { # tarballs in xz format were available in later version of iojs, but KISS and only use xz from v4. if [[ "${N_USE_XZ}" = "true" ]]; then - local resolved_major_version - resolved_major_version="$(echo "${1#v}" | cut -d '.' -f '1')" - if [[ "${resolved_major_version}" -lt 4 ]]; then + local major_version="$(display_major_version "$1")" + if [[ "${major_version}" -lt 4 ]]; then N_USE_XZ="false" fi fi } +# +# Synopsis: update_arch_settings_for_version numeric-version +# Globals modified: +# - ARCH +# + +function update_arch_settings_for_version() { + local tarball_platform="$(display_tarball_platform)" + if [[ -z "${ARCH}" && "${tarball_platform}" = "darwin-arm64" ]]; then + # First native builds were for v16, but can use x64 in rosetta for older versions. + local major_version="$(display_major_version "$1")" + if [[ "${major_version}" -lt 16 ]]; then + ARCH=x64 + fi + fi +} + # # Synopsis: is_lts_codename version # @@ -709,6 +735,7 @@ install() { [[ -n "${version}" ]] || abort "no version found for '$1'" update_mirror_settings_for_version "$1" update_xz_settings_for_version "${version}" + update_arch_settings_for_version "${version}" local dir="${CACHE_DIR}/${g_mirror_folder_name}/${version}" @@ -952,10 +979,8 @@ function display_tarball_platform() { arch="${uname_m}" ;; esac - # Override from command line. + # Override from command line, or version specific adjustment. [ -n "$ARCH" ] && arch="$ARCH" - # Fallback to x64 if autodetecting on Apple M1, native versions not available yet. - [[ -z "$ARCH" && "$os" == "darwin" && "$arch" == "arm64" ]] && arch=x64 echo "${os}-${arch}" } @@ -967,7 +992,11 @@ function display_tarball_platform() { function display_compatible_file_field { local compatible_file_field="$(display_tarball_platform)" - if [[ "${compatible_file_field}" =~ darwin-(.*) ]]; then + if [[ -z "${ARCH}" && "${compatible_file_field}" = "darwin-arm64" ]]; then + # Look for arm64 for native but also x64 for older versions which can run in rosetta. + # (Downside is will get an install error if install version above 16 with x64 and not arm64.) + compatible_file_field="osx-arm64-tar|osx-x64-tar" + elif [[ "${compatible_file_field}" =~ darwin-(.*) ]]; then compatible_file_field="osx-${BASH_REMATCH[1]}-tar" fi echo "${compatible_file_field}"