Skip to content

Commit

Permalink
Support arm64 since Node.js v16.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
seregamorph committed May 6, 2021
1 parent ba38eea commit 4a63273
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 18 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Last public release: [![Maven Central](https://maven-badges.herokuapp.com/maven-

## Changelog

### 1.11.2

### 1.11.4
* Support node arm64 binaries since v16 major release

### 1.11.1

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ private void installNodeDefault() throws InstallationException {
this.config.getPlatform().getLongNodeFilename(this.nodeVersion, false);
String downloadUrl = this.nodeDownloadRoot
+ this.config.getPlatform().getNodeDownloadFilename(this.nodeVersion, false);
String classifier = this.config.getPlatform().getNodeClassifier();
String classifier = this.config.getPlatform().getNodeClassifier(this.nodeVersion);

File tmpDirectory = getTempDirectory();

Expand Down Expand Up @@ -216,7 +216,7 @@ private void installNodeWithNpmForWindows() throws InstallationException {
this.config.getPlatform().getLongNodeFilename(this.nodeVersion, true);
String downloadUrl = this.nodeDownloadRoot
+ this.config.getPlatform().getNodeDownloadFilename(this.nodeVersion, true);
String classifier = this.config.getPlatform().getNodeClassifier();
String classifier = this.config.getPlatform().getNodeClassifier(this.nodeVersion);

File tmpDirectory = getTempDirectory();

Expand Down Expand Up @@ -274,7 +274,7 @@ private void installNodeForWindows() throws InstallationException {

File destination = new File(destinationDirectory, "node.exe");

String classifier = this.config.getPlatform().getNodeClassifier();
String classifier = this.config.getPlatform().getNodeClassifier(this.nodeVersion);

CacheDescriptor cacheDescriptor =
new CacheDescriptor("node", this.nodeVersion, classifier, "exe");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.github.eirslett.maven.plugins.frontend.lib;

import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

enum Architecture { x86, x64, ppc64le, s390x, arm64, armv7l, ppc, ppc64;
public static Architecture guess(){
Expand Down Expand Up @@ -60,6 +62,13 @@ public String getCodename(){
}

class Platform {

/**
* Node.js supports Apple silicon since v16
* https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V16.md#toolchain-and-compiler-upgrades
*/
private static final int NODE_VERSION_THRESHOLD_MAC_ARM64 = 16;

private final String nodeDownloadRoot;
private final OS os;
private final Architecture architecture;
Expand Down Expand Up @@ -117,7 +126,7 @@ public String getLongNodeFilename(String nodeVersion, boolean archiveOnWindows)
if(isWindows() && !archiveOnWindows){
return "node.exe";
} else {
return "node-" + nodeVersion + "-" + this.getNodeClassifier();
return "node-" + nodeVersion + "-" + this.getNodeClassifier(nodeVersion);
}
}

Expand All @@ -141,13 +150,30 @@ public String getNodeDownloadFilename(String nodeVersion, boolean archiveOnWindo
}
}

public String getNodeClassifier() {
final String result;
if(isMac() && architecture == Architecture.arm64) { // this check is required to download the x64 binary until there is an arm64 version available for macOS (darwin).
result = getCodename() + "-" + Architecture.x64.name();
public String getNodeClassifier(String nodeVersion) {
String result = getCodename() + "-" + resolveArchitecture(nodeVersion).name();
return classifier != null ? result + "-" + classifier : result;
}

private Architecture resolveArchitecture(String nodeVersion) {
if (isMac() && architecture == Architecture.arm64) {
Integer nodeMajorVersion = getNodeMajorVersion(nodeVersion);
if (nodeMajorVersion == null || nodeMajorVersion < NODE_VERSION_THRESHOLD_MAC_ARM64) {
return Architecture.x64;
}
}

return architecture;
}

static Integer getNodeMajorVersion(String nodeVersion) {
Matcher matcher = Pattern.compile("^v(\\d+)\\..*$").matcher(nodeVersion);
if (matcher.matches()) {
return Integer.parseInt(matcher.group(1));
} else {
result = getCodename() + "-" + architecture.name();
// malformed node version
return null;
}
return classifier != null ? result + "-" + classifier : result;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
@PrepareForTest({Platform.class, OS.class, Architecture.class, File.class})
public class PlatformTest {

private static final String NODE_VERSION_8 = "v8.17.2";
private static final String NODE_VERSION_15 = "v15.14.0";
private static final String NODE_VERSION_16 = "v16.1.0";

@Test
public void detect_win_doesntLookForAlpine() {
mockStatic(OS.class);
Expand All @@ -26,21 +30,33 @@ public void detect_win_doesntLookForAlpine() {
when(Architecture.guess()).thenReturn(Architecture.x86);

Platform platform = Platform.guess();
assertEquals("win-x86", platform.getNodeClassifier());
assertEquals("win-x86", platform.getNodeClassifier(NODE_VERSION_15));

verifyNoMoreInteractions(File.class); // doesn't look for a file path
}

@Test
public void detect_arm_mac_download_x64_binary() {
public void detect_arm_mac_download_x64_binary_node15() {
mockStatic(OS.class);
mockStatic(Architecture.class);

when(OS.guess()).thenReturn(OS.Mac);
when(Architecture.guess()).thenReturn(Architecture.arm64);

Platform platform = Platform.guess();
assertEquals("darwin-x64", platform.getNodeClassifier());
assertEquals("darwin-x64", platform.getNodeClassifier(NODE_VERSION_15));
}

@Test
public void detect_arm_mac_download_x64_binary_node16() {
mockStatic(OS.class);
mockStatic(Architecture.class);

when(OS.guess()).thenReturn(OS.Mac);
when(Architecture.guess()).thenReturn(Architecture.arm64);

Platform platform = Platform.guess();
assertEquals("darwin-arm64", platform.getNodeClassifier(NODE_VERSION_16));
}

@Test
Expand All @@ -58,7 +74,7 @@ public void detect_linux_notAlpine() throws Exception {
when(alpineRelease.exists()).thenReturn(false);

Platform platform = Platform.guess();
assertEquals("linux-x86", platform.getNodeClassifier());
assertEquals("linux-x86", platform.getNodeClassifier(NODE_VERSION_15));
assertEquals("https://nodejs.org/dist/", platform.getNodeDownloadRoot());
}

Expand All @@ -77,7 +93,7 @@ public void detect_linux_alpine() throws Exception {
when(alpineRelease.exists()).thenReturn(true);

Platform platform = Platform.guess();
assertEquals("linux-x86-musl", platform.getNodeClassifier());
assertEquals("linux-x86-musl", platform.getNodeClassifier(NODE_VERSION_15));
assertEquals("https://unofficial-builds.nodejs.org/download/release/",
platform.getNodeDownloadRoot());
}
Expand All @@ -91,6 +107,14 @@ public void detect_aix_ppc64() {
when(Architecture.guess()).thenReturn(Architecture.ppc64);

Platform platform = Platform.guess();
assertEquals("aix-ppc64", platform.getNodeClassifier());
assertEquals("aix-ppc64", platform.getNodeClassifier(NODE_VERSION_15));
}

@Test
public void getNodeMajorVersion() {
assertEquals(Integer.valueOf(8), Platform.getNodeMajorVersion(NODE_VERSION_8));
assertEquals(Integer.valueOf(15), Platform.getNodeMajorVersion(NODE_VERSION_15));
assertEquals(Integer.valueOf(16), Platform.getNodeMajorVersion(NODE_VERSION_16));
}

}

0 comments on commit 4a63273

Please sign in to comment.