Skip to content

Commit

Permalink
Fixed rust support
Browse files Browse the repository at this point in the history
Signed-off-by: paulober <[email protected]>
  • Loading branch information
paulober committed Oct 1, 2024
1 parent 6b3f029 commit 64d27cb
Show file tree
Hide file tree
Showing 11 changed files with 584 additions and 252 deletions.
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,12 @@
"category": "Raspberry Pi Pico",
"enablement": "false"
},
{
"command": "raspberry-pi-pico.getSVDPath",
"title": "Get SVD Path (rust only)",
"category": "Raspberry Pi Pico",
"enablement": "false"
},
{
"command": "raspberry-pi-pico.compileProject",
"title": "Compile Pico Project",
Expand Down
125 changes: 118 additions & 7 deletions src/commands/getPaths.mts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { CommandWithResult } from "./command.mjs";
import { commands, workspace } from "vscode";
import { commands, type Uri, window, workspace } from "vscode";
import {
getPythonPath,
getPath,
cmakeGetSelectedToolchainAndSDKVersions,
cmakeGetPicoVar,
} from "../utils/cmakeUtil.mjs";
import { join } from "path";
import { join as joinPosix } from "path/posix";
import {
buildOpenOCDPath,
buildPicotoolPath,
buildSDKPath,
buildToolchainPath,
downloadAndInstallOpenOCD,
downloadAndInstallPicotool,
Expand All @@ -19,6 +21,11 @@ import which from "which";
import { execSync } from "child_process";
import { getPicotoolReleases } from "../utils/githubREST.mjs";
import { openOCDVersion } from "../webview/newProjectPanel.mjs";
import State from "../state.mjs";
import VersionBundlesLoader from "../utils/versionBundles.mjs";
import { getSupportedToolchains } from "../utils/toolchainUtil.mjs";
import Logger from "../logger.mjs";
import { rustProjectGetSelectedChip } from "../utils/rustUtil.mjs";

export class GetPythonPathCommand extends CommandWithResult<string> {
constructor() {
Expand Down Expand Up @@ -59,7 +66,7 @@ export class GetEnvPathCommand extends CommandWithResult<string> {
}

export class GetGDBPathCommand extends CommandWithResult<string> {
constructor() {
constructor(private readonly _extensionUri: Uri) {
super("getGDBPath");
}

Expand All @@ -72,13 +79,48 @@ export class GetGDBPathCommand extends CommandWithResult<string> {
}

const workspaceFolder = workspace.workspaceFolders?.[0];
const isRustProject = State.getInstance().isRustProject;
let toolchainVersion = "";

const selectedToolchainAndSDKVersions =
await cmakeGetSelectedToolchainAndSDKVersions(workspaceFolder.uri);
if (selectedToolchainAndSDKVersions === null) {
return "";
if (isRustProject) {
// check if latest toolchain is installed
const vbl = new VersionBundlesLoader(this._extensionUri);
const latestVb = await vbl.getLatest();

if (!latestVb) {
void window.showErrorMessage("No version bundles found.");

return "";
}

const supportedToolchains = await getSupportedToolchains();
const latestSupportedToolchain = supportedToolchains.find(
t => t.version === latestVb.toolchain
);
if (!latestSupportedToolchain) {
void window.showErrorMessage(
"No supported toolchain found for the latest version."
);

return "";
}

const useRISCV = rustProjectGetSelectedChip(
workspaceFolder.uri.fsPath
)?.includes("riscv");

toolchainVersion = useRISCV
? latestVb.riscvToolchain
: latestVb.toolchain;
} else {
const selectedToolchainAndSDKVersions =
await cmakeGetSelectedToolchainAndSDKVersions(workspaceFolder.uri);
if (selectedToolchainAndSDKVersions === null) {
return "";
}

toolchainVersion = selectedToolchainAndSDKVersions[1];
}
const toolchainVersion = selectedToolchainAndSDKVersions[1];

let triple = "arm-none-eabi";
if (toolchainVersion.includes("RISCV")) {
Expand Down Expand Up @@ -154,6 +196,8 @@ export class GetCompilerPathCommand extends CommandWithResult<string> {
}

export class GetChipCommand extends CommandWithResult<string> {
private readonly _logger = new Logger("GetChipCommand");

constructor() {
super("getChip");
}
Expand All @@ -167,6 +211,19 @@ export class GetChipCommand extends CommandWithResult<string> {
}

const workspaceFolder = workspace.workspaceFolders?.[0];
const isRustProject = State.getInstance().isRustProject;

if (isRustProject) {
// read .pico-rs
const chip = rustProjectGetSelectedChip(workspaceFolder.uri.fsPath);
if (chip === null) {
this._logger.error("Failed to read .pico-rs");

return "";
}

return chip;
}

const settings = Settings.getInstance();
let buildDir = join(workspaceFolder.uri.fsPath, "build");
Expand Down Expand Up @@ -227,6 +284,13 @@ export class GetTargetCommand extends CommandWithResult<string> {
}

const workspaceFolder = workspace.workspaceFolders?.[0];
const isRustProject = State.getInstance().isRustProject;

if (isRustProject) {
const chip = rustProjectGetSelectedChip(workspaceFolder.uri.fsPath);

return chip === null ? "rp2040" : chip.toLowerCase();
}

const settings = Settings.getInstance();
let buildDir = join(workspaceFolder.uri.fsPath, "build");
Expand Down Expand Up @@ -343,3 +407,50 @@ export class GetOpenOCDRootCommand extends CommandWithResult<
return buildOpenOCDPath(openOCDVersion);
}
}

/**
* Currently rust only!
*/
export class GetSVDPathCommand extends CommandWithResult<string | undefined> {
public static readonly id = "getSVDPath";

constructor(private readonly _extensionUri: Uri) {
super(GetSVDPathCommand.id);
}

async execute(): Promise<string | undefined> {
if (
workspace.workspaceFolders === undefined ||
workspace.workspaceFolders.length === 0
) {
return "";
}

const isRustProject = State.getInstance().isRustProject;
if (!isRustProject) {
return;
}

const vs = new VersionBundlesLoader(this._extensionUri);
const latestSDK = await vs.getLatestSDK();
if (!latestSDK) {
return;
}

const chip = rustProjectGetSelectedChip(
workspace.workspaceFolders[0].uri.fsPath
);

if (!chip) {
return;
}

return joinPosix(
buildSDKPath(latestSDK),
"src",
chip,
"hardware_regs",
`${chip.toUpperCase()}.svd`
);
}
}
13 changes: 12 additions & 1 deletion src/commands/launchTargetPath.mts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Settings, { SettingsKey } from "../settings.mjs";
import State from "../state.mjs";
import { parse as parseToml } from "toml";
import { join as joinPosix } from "path/posix";
import { rustProjectGetSelectedChip } from "../utils/rustUtil.mjs";

export default class LaunchTargetPathCommand extends CommandWithResult<string> {
public static readonly id = "launchTargetPath";
Expand Down Expand Up @@ -81,10 +82,20 @@ export default class LaunchTargetPathCommand extends CommandWithResult<string> {
| undefined;

if (cargoToml?.package?.name) {
const chip = rustProjectGetSelectedChip(
workspace.workspaceFolders[0].uri.fsPath
);
const toolchain =
chip === "rp2040"
? "thumbv6m-none-eabi"
: chip === "rp2350"
? "thumbv8m.main-none-eabi"
: "riscv32imac-unknown-none-elf";

return joinPosix(
workspace.workspaceFolders[0].uri.fsPath.replaceAll("\\", "/"),
"target",
"thumbv6m-none-eabi",
toolchain,
"debug",
cargoToml.package.name
);
Expand Down
101 changes: 24 additions & 77 deletions src/commands/switchBoard.mts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
workspace,
type Uri,
} from "vscode";
import { existsSync, readdirSync, readFileSync } from "fs";
import { existsSync, readdirSync, readFileSync, writeFileSync } from "fs";
import {
buildSDKPath,
downloadAndInstallToolchain,
Expand All @@ -25,9 +25,6 @@ import { getSupportedToolchains } from "../utils/toolchainUtil.mjs";
import VersionBundlesLoader from "../utils/versionBundles.mjs";
import State from "../state.mjs";
import { unknownErrorToString } from "../utils/errorHelper.mjs";
import { writeFile } from "fs/promises";
import { parse as parseToml } from "toml";
import { writeTomlFile } from "../utils/projectGeneration/tomlUtil.mjs";

export default class SwitchBoardCommand extends Command {
private _logger: Logger = new Logger("SwitchBoardCommand");
Expand Down Expand Up @@ -93,108 +90,58 @@ export default class SwitchBoardCommand extends Command {
// check it has a CMakeLists.txt
if (
workspaceFolder === undefined ||
!existsSync(join(workspaceFolder.uri.fsPath, "CMakeLists.txt")) ||
isRustProject
(!existsSync(join(workspaceFolder.uri.fsPath, "CMakeLists.txt")) &&
!isRustProject)
) {
return;
}

if (isRustProject) {
const board = await window.showQuickPick(
["rp2040", "rp2350", "rp2350-RISCV"],
["RP2040", "RP2350", "RP2350-RISCV"],
{
placeHolder: "Select chip",
canPickMany: false,
ignoreFocusOut: false,
title: "Select chip",
title: "Switch project target chip",
}
);

if (board === undefined) {
return undefined;
}

const target =
board === "rp2350-RISCV"
? "riscv32imac-unknown-none-elf"
: board === "rp2350"
? "thumbv8m.main-none-eabihf"
: "thumbv6m-none-eabi";

// check if .cargo/config.toml already contains a line starting with
// target = "${target}" and if no replace target = "..." with it with the new target

try {
const cargoConfigPath = join(
workspaceFolder.uri.fsPath,
".cargo",
"config.toml"
);

const contents = readFileSync(cargoConfigPath, "utf-8");

const newContents = contents.replace(
/target = ".*"/,
`target = "${target}"`
writeFileSync(
join(workspaceFolder.uri.fsPath, ".pico-rs"),
board.toLowerCase(),
"utf8"
);

if (newContents === contents) {
return;
}

// write new contents to file
await writeFile(cargoConfigPath, newContents);

const cargoToml = (await parseToml(contents)) as {
features?: { default?: string[] };
};

let features = cargoToml.features?.default ?? [];

switch (board) {
case "rp2040":
features.push("rp2040");
// remove all other features rp2350 and rp2350-riscv
features = features.filter(
f => f !== "rp2350" && f !== "rp2350-riscv"
);
break;
case "rp2350":
features.push("rp2350");
// remove all other features rp2040 and rp2350-riscv
features = features.filter(
f => f !== "rp2040" && f !== "rp2350-riscv"
);
break;
case "rp2350-RISCV":
features.push("rp2350-riscv");
// remove all other features rp2040 and rp2350
features = features.filter(f => f !== "rp2040" && f !== "rp2350");
break;
}

if (cargoToml.features) {
cargoToml.features.default = features;
} else {
// not necessary becuase your project is broken at this point
cargoToml.features = { default: features };
}

await writeTomlFile(cargoConfigPath, cargoToml);
} catch (error) {
this._logger.error(
"Failed to update .cargo/config.toml",
unknownErrorToString(error)
`Failed to write .pico-rs file: ${unknownErrorToString(error)}`
);

void window.showErrorMessage(
"Failed to update Cargo.toml and " +
".cargo/config.toml - cannot update chip"
"Failed to write .pico-rs file. " +
"Please check the logs for more information."
);

return;
}

this._ui.updateBoard(board.toUpperCase());
const toolchain =
board === "RP2040"
? "thumbv6m-none-eabi"
: board === "RP2350"
? "thumbv8m.main-none-eabi"
: "riscv32imac-unknown-none-elf";

await workspace
.getConfiguration("rust-analyzer")
.update("cargo.target", toolchain, null);

return;
}

Expand Down
Loading

0 comments on commit 64d27cb

Please sign in to comment.