Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions src/install/managed.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { execFile } from "node:child_process";
import { createHash } from "node:crypto";
import { createReadStream, createWriteStream } from "node:fs";
import { createReadStream, createWriteStream, existsSync } from "node:fs";
import type { IncomingMessage, ClientRequest } from "node:http";
import * as https from "node:https";
import * as path from "node:path";
Expand All @@ -25,6 +25,8 @@ export type PatchloomTargetTriple =
| "x86_64-apple-darwin"
| "aarch64-unknown-linux-gnu"
| "x86_64-unknown-linux-gnu"
| "aarch64-unknown-linux-musl"
| "x86_64-unknown-linux-musl"
| "x86_64-pc-windows-msvc"
| "aarch64-pc-windows-msvc";

Expand Down Expand Up @@ -204,7 +206,8 @@ export async function clearManagedInstallFailureRecord(

export function detectManagedInstallTarget(
platform: NodeJS.Platform = process.platform,
arch: NodeJS.Architecture = process.arch
arch: NodeJS.Architecture = process.arch,
isMusl?: boolean
): ManagedInstallTarget | undefined {
if (platform === "darwin" && arch === "arm64") {
return {
Expand All @@ -225,19 +228,21 @@ export function detectManagedInstallTarget(
}

if (platform === "linux" && arch === "arm64") {
const musl = isMusl ?? isMuslLinux(arch);
return {
platform,
arch,
targetTriple: "aarch64-unknown-linux-gnu",
targetTriple: musl ? "aarch64-unknown-linux-musl" : "aarch64-unknown-linux-gnu",
archiveFormat: ".tar.xz"
};
}

if (platform === "linux" && arch === "x64") {
const musl = isMusl ?? isMuslLinux(arch);
return {
platform,
arch,
targetTriple: "x86_64-unknown-linux-gnu",
targetTriple: musl ? "x86_64-unknown-linux-musl" : "x86_64-unknown-linux-gnu",
archiveFormat: ".tar.xz"
};
}
Expand All @@ -263,6 +268,23 @@ export function detectManagedInstallTarget(
return undefined;
}

const MUSL_ARCH_MAP: Partial<Record<NodeJS.Architecture, string>> = {
x64: "x86_64",
arm64: "aarch64"
};

export function isMuslLinux(arch: NodeJS.Architecture = process.arch): boolean {
const muslArch = MUSL_ARCH_MAP[arch];
if (!muslArch) {
return false;
}
try {
return existsSync(`/lib/ld-musl-${muslArch}.so.1`);
} catch {
return false;
}
}

export function resolveManagedInstallPaths(
installRoot: string,
target: ManagedInstallTarget
Expand Down
51 changes: 51 additions & 0 deletions test/unit/binary.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
resolveManagedInstallPaths,
resolveManagedInstallTransactionPaths,
setManagedInstallFailure,
isMuslLinux,
verifyManagedInstallArchiveChecksum
} from "../../src/install/managed.js";
import { resolveMcpTargets } from "../../src/mcp/config.js";
Expand Down Expand Up @@ -235,6 +236,56 @@ test("detectManagedInstallTarget maps supported platforms to release targets", (
assert.equal(detectManagedInstallTarget("linux", "arm"), undefined);
});

test("detectManagedInstallTarget selects musl target when isMusl is true", () => {
assert.deepEqual(detectManagedInstallTarget("linux", "x64", true), {
platform: "linux",
arch: "x64",
targetTriple: "x86_64-unknown-linux-musl",
archiveFormat: ".tar.xz"
});
assert.deepEqual(detectManagedInstallTarget("linux", "arm64", true), {
platform: "linux",
arch: "arm64",
targetTriple: "aarch64-unknown-linux-musl",
archiveFormat: ".tar.xz"
});
});

test("detectManagedInstallTarget selects gnu target when isMusl is false", () => {
assert.deepEqual(detectManagedInstallTarget("linux", "x64", false), {
platform: "linux",
arch: "x64",
targetTriple: "x86_64-unknown-linux-gnu",
archiveFormat: ".tar.xz"
});
assert.deepEqual(detectManagedInstallTarget("linux", "arm64", false), {
platform: "linux",
arch: "arm64",
targetTriple: "aarch64-unknown-linux-gnu",
archiveFormat: ".tar.xz"
});
});

test("detectManagedInstallTarget ignores isMusl for non-Linux platforms", () => {
const darwinTarget = detectManagedInstallTarget("darwin", "arm64", true);
assert.equal(darwinTarget?.targetTriple, "aarch64-apple-darwin");
const windowsTarget = detectManagedInstallTarget("win32", "x64", true);
assert.equal(windowsTarget?.targetTriple, "x86_64-pc-windows-msvc");
});

test("isMuslLinux returns false on non-Linux platforms", () => {
// On macOS/Windows (where CI runs), the musl linker does not exist
if (process.platform !== "linux") {
assert.equal(isMuslLinux("x64"), false);
assert.equal(isMuslLinux("arm64"), false);
}
});

test("isMuslLinux returns false for unsupported architectures", () => {
assert.equal(isMuslLinux("arm" as NodeJS.Architecture), false);
assert.equal(isMuslLinux("ia32" as NodeJS.Architecture), false);
});

test("resolveManagedInstallPaths uses cargo-dist style archive names", () => {
const target = detectManagedInstallTarget("darwin", "arm64");
assert.ok(target);
Expand Down
Loading