Skip to content
This repository was archived by the owner on Nov 25, 2025. It is now read-only.
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
20 changes: 12 additions & 8 deletions src/versionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import which from "which";
import semver from "semver";

import * as minisign from "./minisign";
import { getHostZigName, getVersion, getZigArchName, getZigOSName } from "./zigUtil";
import * as zigUtil from "./zigUtil";

const execFile = util.promisify(childProcess.execFile);
const chmod = util.promisify(fs.chmod);
Expand Down Expand Up @@ -69,7 +69,7 @@ export async function install(config: Config, version: semver.SemVer): Promise<s

async function installGuarded(config: Config, version: semver.SemVer): Promise<string> {
const exeName = config.exeName + (process.platform === "win32" ? ".exe" : "");
const subDirName = `${getHostZigName()}-${version.raw}`;
const subDirName = `${getTargetName()}-${version.raw}`;
const exeUri = vscode.Uri.joinPath(config.context.globalStorageUri, config.exeName, subDirName, exeName);

await setLastAccessTime(config, version);
Expand Down Expand Up @@ -145,7 +145,7 @@ async function installFromMirror(

const isWindows = process.platform === "win32";
const exeName = config.exeName + (isWindows ? ".exe" : "");
const subDirName = `${getHostZigName()}-${version.raw}`;
const subDirName = `${getTargetName()}-${version.raw}`;
const fileName = config.getArtifactName(version);

const installDir = vscode.Uri.joinPath(config.context.globalStorageUri, config.exeName, subDirName);
Expand Down Expand Up @@ -249,7 +249,7 @@ async function installFromMirror(
} catch {}
}

const exeVersion = getVersion(exeUri.fsPath, config.versionArg);
const exeVersion = zigUtil.getVersion(exeUri.fsPath, config.versionArg);
if (!exeVersion || exeVersion.compare(version) !== 0) {
try {
await vscode.workspace.fs.delete(installDir, { recursive: true, useTrash: false });
Expand Down Expand Up @@ -278,7 +278,7 @@ async function installFromMirror(
/** Returns all locally installed versions */
export async function query(config: Config): Promise<semver.SemVer[]> {
const available: semver.SemVer[] = [];
const prefix = getHostZigName();
const prefix = getTargetName();

const storageDir = vscode.Uri.joinPath(config.context.globalStorageUri, config.exeName);
try {
Expand Down Expand Up @@ -315,7 +315,7 @@ async function getTarExePath(): Promise<string | null> {
/** Set the last access time of the (installed) version. */
async function setLastAccessTime(config: Config, version: semver.SemVer): Promise<void> {
await config.context.globalState.update(
`${config.exeName}-last-access-time-${getHostZigName()}-${version.raw}`,
`${config.exeName}-last-access-time-${getTargetName()}-${version.raw}`,
Date.now(),
);
}
Expand Down Expand Up @@ -357,8 +357,8 @@ async function removeUnusedInstallations(config: Config) {

/** Remove after some time has passed from the prefix change. */
export async function convertOldInstallPrefixes(config: Config): Promise<void> {
const oldPrefix = `${getZigOSName()}-${getZigArchName()}`;
const newPrefix = `${getZigArchName()}-${getZigOSName()}`;
const oldPrefix = `${zigUtil.getZigOSName()}-${zigUtil.getZigArchName("armv7a")}`;
const newPrefix = getTargetName();

const storageDir = vscode.Uri.joinPath(config.context.globalStorageUri, config.exeName);
try {
Expand Down Expand Up @@ -386,3 +386,7 @@ export async function convertOldInstallPrefixes(config: Config): Promise<void> {
}
} catch {}
}

function getTargetName(): string {
return `${zigUtil.getZigArchName("armv7a")}-${zigUtil.getZigOSName()}`;
}
51 changes: 26 additions & 25 deletions src/zigSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,7 @@ import semver from "semver";

import * as minisign from "./minisign";
import * as versionManager from "./versionManager";
import {
VersionIndex,
ZigVersion,
asyncDebounce,
getHostZigName,
getZigArchName,
getZigOSName,
resolveExePathAndVersion,
workspaceConfigUpdateNoThrow,
} from "./zigUtil";
import * as zigUtil from "./zigUtil";
import { ZigProvider } from "./zigProvider";

let statusItem: vscode.StatusBarItem;
Expand All @@ -41,7 +32,7 @@ async function installZig(context: vscode.ExtensionContext, temporaryVersion?: s

if (!version) {
// Lookup zig in $PATH
const result = resolveExePathAndVersion("zig", "version");
const result = zigUtil.resolveExePathAndVersion("zig", "version");
if ("exe" in result) {
await vscode.workspace.getConfiguration("zig").update("path", undefined, true);
zigProvider.set(result);
Expand All @@ -62,7 +53,7 @@ async function installZig(context: vscode.ExtensionContext, temporaryVersion?: s
try {
const exePath = await versionManager.install(versionManagerConfig, version);
const zigConfig = vscode.workspace.getConfiguration("zig");
await workspaceConfigUpdateNoThrow(zigConfig, "path", undefined, true);
await zigUtil.workspaceConfigUpdateNoThrow(zigConfig, "path", undefined, true);
zigProvider.set({ exe: exePath, version: version });
} catch (err) {
zigProvider.set(null);
Expand Down Expand Up @@ -116,21 +107,21 @@ async function getLatestTaggedZigVersion(context: vscode.ExtensionContext): Prom
*
* Throws an exception when no network connection is available.
*/
async function getVersions(): Promise<ZigVersion[]> {
async function getVersions(): Promise<zigUtil.ZigVersion[]> {
const [zigIndexJson, machIndexJson] = await Promise.all(
["https://ziglang.org/download/index.json", "https://pkg.machengine.org/zig/index.json"].map(async (url) => {
const response = await fetch(url);
return response.json() as Promise<VersionIndex>;
return response.json() as Promise<zigUtil.VersionIndex>;
}),
);
const indexJson = { ...machIndexJson, ...zigIndexJson };

const hostName = getHostZigName();
const result: ZigVersion[] = [];
const result: zigUtil.ZigVersion[] = [];
for (const [key, value] of Object.entries(indexJson)) {
const name = key === "master" ? "nightly" : key;
const version = new semver.SemVer(value.version ?? key);
const release = value[hostName];
const targetName = `${getZigArchName(version)}-${zigUtil.getZigOSName()}`;
const release = value[targetName];
if (release) {
result.push({
name: name,
Expand All @@ -144,13 +135,23 @@ async function getVersions(): Promise<ZigVersion[]> {
}
if (result.length === 0) {
throw Error(
`no pre-built Zig is available for your system '${hostName}', you can build it yourself using https://github.com/ziglang/zig-bootstrap`,
`no pre-built Zig is available for your system '${zigUtil.getZigArchName("arm")}-${zigUtil.getZigOSName()}}', you can build it yourself using https://github.com/ziglang/zig-bootstrap`,
);
}
sortVersions(result);
return result;
}

function getZigArchName(zigVersion: semver.SemVer): string {
switch (zigVersion.compare(new semver.SemVer("0.15.0-dev.836+080ee25ec"))) {
case -1:
case 0:
return zigUtil.getZigArchName("armv7a");
case 1:
return zigUtil.getZigArchName("arm");
}
}

function sortVersions(versions: { name?: string; version: semver.SemVer; isMach: boolean }[]) {
versions.sort((lhs, rhs) => {
// Mach versions except `mach-latest` move to the end
Expand Down Expand Up @@ -236,7 +237,7 @@ async function selectVersionAndInstall(context: vscode.ExtensionContext) {
});
}

const zigInPath = resolveExePathAndVersion("zig", "version");
const zigInPath = zigUtil.resolveExePathAndVersion("zig", "version");
if (!("message" in zigInPath)) {
items.push({
label: "Use Zig in PATH",
Expand Down Expand Up @@ -285,7 +286,7 @@ async function selectVersionAndInstall(context: vscode.ExtensionContext) {
break;
case "Use Zig in PATH":
const zigConfig = vscode.workspace.getConfiguration("zig");
await workspaceConfigUpdateNoThrow(zigConfig, "path", "zig", true);
await zigUtil.workspaceConfigUpdateNoThrow(zigConfig, "path", "zig", true);
break;
case "Manually Specify Path":
const uris = await vscode.window.showOpenDialog({
Expand Down Expand Up @@ -591,10 +592,10 @@ export async function setupZig(context: vscode.ExtensionContext) {
const zigConfig = vscode.workspace.getConfiguration("zig");
const zigPath = zigConfig.get<string>("path", "");
if (zigPath.startsWith(context.globalStorageUri.fsPath)) {
await workspaceConfigUpdateNoThrow(zigConfig, "path", undefined, true);
await zigUtil.workspaceConfigUpdateNoThrow(zigConfig, "path", undefined, true);
}

await workspaceConfigUpdateNoThrow(zigConfig, "initialSetupDone", undefined, true);
await zigUtil.workspaceConfigUpdateNoThrow(zigConfig, "initialSetupDone", undefined, true);

await context.workspaceState.update("zig-version", undefined);

Expand Down Expand Up @@ -668,9 +669,9 @@ export async function setupZig(context: vscode.ExtensionContext) {
(version.prerelease.length === 0 && semver.gte(version, "0.14.1")) ||
semver.gte(version, "0.15.0-dev.631+9a3540d61")
) {
return `zig-${getZigArchName()}-${getZigOSName()}-${version.raw}.${fileExtension}`;
return `zig-${getZigArchName(version)}-${zigUtil.getZigOSName()}-${version.raw}.${fileExtension}`;
} else {
return `zig-${getZigOSName()}-${getZigArchName()}-${version.raw}.${fileExtension}`;
return `zig-${zigUtil.getZigOSName()}-${getZigArchName(version)}-${version.raw}.${fileExtension}`;
}
},
};
Expand All @@ -689,7 +690,7 @@ export async function setupZig(context: vscode.ExtensionContext) {
const watcher1 = vscode.workspace.createFileSystemWatcher("**/.zigversion");
const watcher2 = vscode.workspace.createFileSystemWatcher("**/build.zig.zon");

const refreshZigInstallation = asyncDebounce(async () => {
const refreshZigInstallation = zigUtil.asyncDebounce(async () => {
if (!vscode.workspace.getConfiguration("zig").get<string>("path")) {
await installZig(context);
} else {
Expand Down
10 changes: 4 additions & 6 deletions src/zigUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,20 +170,22 @@ export async function shouldCheckUpdate(context: vscode.ExtensionContext, key: s
return true;
}

export function getZigArchName(): string {
export function getZigArchName(armName: string): string {
switch (process.arch) {
case "ia32":
return "x86";
case "x64":
return "x86_64";
case "arm":
return "armv7a";
return armName;
case "arm64":
return "aarch64";
case "ppc":
return "powerpc";
case "ppc64":
return "powerpc64le";
case "loong64":
return "loongarch64";
default:
return process.arch;
}
Expand All @@ -199,10 +201,6 @@ export function getZigOSName(): string {
}
}

export function getHostZigName(): string {
return `${getZigArchName()}-${getZigOSName()}`;
}

export function getVersion(
filePath: string,
/**
Expand Down
49 changes: 23 additions & 26 deletions src/zls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,7 @@ import semver from "semver";

import * as minisign from "./minisign";
import * as versionManager from "./versionManager";
import {
getHostZigName,
getZigArchName,
getZigOSName,
handleConfigOption,
resolveExePathAndVersion,
workspaceConfigUpdateNoThrow,
} from "./zigUtil";
import * as zigUtil from "./zigUtil";
import { zigProvider } from "./zigSetup";

const ZIG_MODE = [
Expand Down Expand Up @@ -114,16 +107,16 @@ async function getZLSPath(context: vscode.ExtensionContext): Promise<{ exe: stri
if (!!zlsExePath) {
// This will fail on older ZLS version that do not support `zls --version`.
// It should be more likely that the given executable is invalid than someone using ZLS 0.9.0 or older.
const result = resolveExePathAndVersion(zlsExePath, "--version");
const result = zigUtil.resolveExePathAndVersion(zlsExePath, "--version");
if ("message" in result) {
vscode.window
.showErrorMessage(`Unexpected 'zig.zls.path': ${result.message}`, "install ZLS", "open settings")
.then(async (response) => {
switch (response) {
case "install ZLS":
const zlsConfig = vscode.workspace.getConfiguration("zig.zls");
await workspaceConfigUpdateNoThrow(zlsConfig, "enabled", "on", true);
await workspaceConfigUpdateNoThrow(zlsConfig, "path", undefined);
await zigUtil.workspaceConfigUpdateNoThrow(zlsConfig, "enabled", "on", true);
await zigUtil.workspaceConfigUpdateNoThrow(zlsConfig, "path", undefined);
break;
case "open settings":
await vscode.commands.executeCommand("workbench.action.openSettings", "zig.zls.path");
Expand Down Expand Up @@ -179,7 +172,7 @@ function configurationMiddleware(params: ConfigurationParams): LSPAny[] | Respon

if (typeof value === "string") {
// Make sure that `""` gets converted to `undefined` and resolve predefined values
value = value ? handleConfigOption(value, workspaceFolder ?? "guess") : undefined;
value = value ? zigUtil.handleConfigOption(value, workspaceFolder ?? "guess") : undefined;
} else if (typeof value === "object" && value !== null && !Array.isArray(value)) {
// Recursively update the config options
const newValue: Record<string, unknown> = {};
Expand Down Expand Up @@ -277,13 +270,13 @@ async function validateAdditionalOptions(): Promise<void> {
switch (response) {
case `Use ${optionName} instead`:
const { [optionName]: newValue, ...updatedAdditionalOptions } = additionalOptions;
await workspaceConfigUpdateNoThrow(
await zigUtil.workspaceConfigUpdateNoThrow(
configuration,
"additionalOptions",
Object.keys(updatedAdditionalOptions).length ? updatedAdditionalOptions : undefined,
true,
);
await workspaceConfigUpdateNoThrow(configuration, section, newValue, true);
await zigUtil.workspaceConfigUpdateNoThrow(configuration, section, newValue, true);
break;
case "Show zig.zls.additionalOptions":
await vscode.commands.executeCommand("workbench.action.openSettingsJson", {
Expand Down Expand Up @@ -367,19 +360,20 @@ async function fetchVersion(
void vscode.window.showErrorMessage(`Unable to fetch ZLS: ${response.message as string}`);
return null;
}
const version = new semver.SemVer(response.version);
const armName = semver.gte(version, "0.15.0") ? "arm" : "armv7a";
const targetName = `${zigUtil.getZigArchName(armName)}-${zigUtil.getZigOSName()}`;

const hostName = getHostZigName();

if (!(hostName in response)) {
if (!(targetName in response)) {
void vscode.window.showErrorMessage(
`A prebuilt ZLS ${response.version} binary is not available for your system. You can build it yourself with https://github.com/zigtools/zls#from-source`,
);
return null;
}

return {
version: new semver.SemVer(response.version),
artifact: response[hostName] as ArtifactEntry,
version: version,
artifact: response[targetName] as ArtifactEntry,
};
}

Expand All @@ -401,10 +395,10 @@ async function isEnabled(): Promise<boolean> {
);
switch (response) {
case "Yes":
await workspaceConfigUpdateNoThrow(zlsConfig, "enabled", "on", true);
await zigUtil.workspaceConfigUpdateNoThrow(zlsConfig, "enabled", "on", true);
return true;
case "No":
await workspaceConfigUpdateNoThrow(zlsConfig, "enabled", "off", true);
await zigUtil.workspaceConfigUpdateNoThrow(zlsConfig, "enabled", "off", true);
return false;
case undefined:
return false;
Expand Down Expand Up @@ -455,8 +449,8 @@ export async function activate(context: vscode.ExtensionContext) {
const zlsConfig = vscode.workspace.getConfiguration("zig.zls");
const zlsPath = zlsConfig.get<string>("path", "");
if (zlsPath.startsWith(context.globalStorageUri.fsPath)) {
await workspaceConfigUpdateNoThrow(zlsConfig, "enabled", "on", true);
await workspaceConfigUpdateNoThrow(zlsConfig, "path", undefined, true);
await zigUtil.workspaceConfigUpdateNoThrow(zlsConfig, "enabled", "on", true);
await zigUtil.workspaceConfigUpdateNoThrow(zlsConfig, "path", undefined, true);
}
}

Expand All @@ -475,7 +469,10 @@ export async function activate(context: vscode.ExtensionContext) {
},
getArtifactName(version) {
const fileExtension = process.platform === "win32" ? "zip" : "tar.xz";
return `zls-${getZigOSName()}-${getZigArchName()}-${version.raw}.${fileExtension}`;
const targetName = semver.gte(version, "0.15.0")
? `${zigUtil.getZigArchName("arm")}-${zigUtil.getZigOSName()}`
: `${zigUtil.getZigOSName()}-${zigUtil.getZigArchName("armv7a")}`;
return `zls-${targetName}-${version.raw}.${fileExtension}`;
},
};

Expand All @@ -492,14 +489,14 @@ export async function activate(context: vscode.ExtensionContext) {
statusItem,
vscode.commands.registerCommand("zig.zls.enable", async () => {
const zlsConfig = vscode.workspace.getConfiguration("zig.zls");
await workspaceConfigUpdateNoThrow(zlsConfig, "enabled", "on", true);
await zigUtil.workspaceConfigUpdateNoThrow(zlsConfig, "enabled", "on", true);
}),
vscode.commands.registerCommand("zig.zls.stop", async () => {
await stopClient();
}),
vscode.commands.registerCommand("zig.zls.startRestart", async () => {
const zlsConfig = vscode.workspace.getConfiguration("zig.zls");
await workspaceConfigUpdateNoThrow(zlsConfig, "enabled", "on", true);
await zigUtil.workspaceConfigUpdateNoThrow(zlsConfig, "enabled", "on", true);
await restartClient(context);
}),
vscode.commands.registerCommand("zig.zls.openOutput", () => {
Expand Down