Skip to content

Commit 0c5673c

Browse files
committed
NOT READY! | Rust support
Signed-off-by: paulober <[email protected]>
2 parents e594124 + 9ed53e1 commit 0c5673c

18 files changed

+1546
-86
lines changed

.vscodeignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ tmp.py
3131
!scripts/lwipopts.h
3232
!scripts/pico_configs.tsv
3333
!scripts/pico_project.py
34+
!scripts/portable-msvc.py
3435
!scripts/pico-vscode.cmake
3536
!scripts/Pico.code-profile
3637
!scripts/raspberrypi-swd.cfg

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ For optimal functionality, consider enabling:
8686

8787
When prompted, select the `Pico` kit in CMake Tools, and set your build and launch targets accordingly. Use CMake Tools for compilation, but continue using this extension for debugging, as CMake Tools debugging is not compatible with Pico.
8888

89+
## Rust Prerequisites
90+
91+
### Linux
92+
93+
- **GCC** for the host architecture
94+
8995
## VS Code Profiles
9096

9197
If you work with multiple microcontroller toolchains, consider installing this extension into a [VS Code Profile](https://code.visualstudio.com/docs/editor/profiles) to avoid conflicts with other toolchains. Follow these steps:

package.json

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
},
6666
"activationEvents": [
6767
"workspaceContains:./pico_sdk_import.cmake",
68+
"workspaceContains:./.pico-rs",
6869
"onWebviewPanel:newPicoProject",
6970
"onWebviewPanel:newPicoMicroPythonProject"
7071
],
@@ -79,13 +80,13 @@
7980
"command": "raspberry-pi-pico.switchSDK",
8081
"title": "Switch Pico SDK",
8182
"category": "Raspberry Pi Pico",
82-
"enablement": "raspberry-pi-pico.isPicoProject"
83+
"enablement": "raspberry-pi-pico.isPicoProject && !raspberry-pi-pico.isRustProject"
8384
},
8485
{
8586
"command": "raspberry-pi-pico.switchBoard",
8687
"title": "Switch Board",
8788
"category": "Raspberry Pi Pico",
88-
"enablement": "raspberry-pi-pico.isPicoProject"
89+
"enablement": "raspberry-pi-pico.isPicoProject && !raspberry-pi-pico.isRustProject"
8990
},
9091
{
9192
"command": "raspberry-pi-pico.launchTargetPath",
@@ -151,7 +152,7 @@
151152
"command": "raspberry-pi-pico.runProject",
152153
"title": "Run Pico Project (USB)",
153154
"category": "Raspberry Pi Pico",
154-
"enablement": "raspberry-pi-pico.isPicoProject"
155+
"enablement": "raspberry-pi-pico.isPicoProject && !raspberry-pi-pico.isRustProject"
155156
},
156157
{
157158
"command": "raspberry-pi-pico.clearGithubApiCache",
@@ -162,7 +163,7 @@
162163
"command": "raspberry-pi-pico.conditionalDebugging",
163164
"title": "Conditional Debugging",
164165
"category": "Raspberry Pi Pico",
165-
"enablement": "raspberry-pi-pico.isPicoProject && !inQuickOpen"
166+
"enablement": "raspberry-pi-pico.isPicoProject && !inQuickOpen && !raspberry-pi-pico.isRustProject"
166167
},
167168
{
168169
"command": "raspberry-pi-pico.debugLayout",
@@ -179,7 +180,7 @@
179180
"command": "raspberry-pi-pico.configureCmake",
180181
"title": "Configure CMake",
181182
"category": "Raspberry Pi Pico",
182-
"enablement": "raspberry-pi-pico.isPicoProject"
183+
"enablement": "raspberry-pi-pico.isPicoProject && !raspberry-pi-pico.isRustProject"
183184
},
184185
{
185186
"command": "raspberry-pi-pico.importProject",
@@ -200,7 +201,7 @@
200201
"command": "raspberry-pi-pico.flashProject",
201202
"title": "Flash Pico Project (SWD)",
202203
"category": "Raspberry Pi Pico",
203-
"enablement": "raspberry-pi-pico.isPicoProject"
204+
"enablement": "raspberry-pi-pico.isPicoProject && !raspberry-pi-pico.isRustProject"
204205
}
205206
],
206207
"configuration": {
@@ -307,6 +308,7 @@
307308
"got": "^14.4.2",
308309
"ini": "^4.1.3",
309310
"rimraf": "^5.0.7",
311+
"toml": "^3.0.0",
310312
"undici": "^6.19.7",
311313
"uuid": "^10.0.0",
312314
"which": "^4.0.0"

src/commands/compileProject.mts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { EventEmitter } from "events";
33
import { CommandWithResult } from "./command.mjs";
44
import Logger from "../logger.mjs";
55
import Settings, { SettingsKey } from "../settings.mjs";
6+
import { ContextKeys } from "../contextKeys.mjs";
7+
import State from "../state.mjs";
68

79
export default class CompileProjectCommand extends CommandWithResult<boolean> {
810
private _logger: Logger = new Logger("CompileProjectCommand");
@@ -18,9 +20,15 @@ export default class CompileProjectCommand extends CommandWithResult<boolean> {
1820
const task = (await tasks.fetchTasks()).find(
1921
task => task.name === "Compile Project"
2022
);
23+
/*const isRustProject = await commands.executeCommand(
24+
"getContext",
25+
ContextKeys.isRustProject
26+
);*/
27+
const isRustProject = State.getInstance().isRustProject;
2128

2229
const settings = Settings.getInstance();
2330
if (
31+
!isRustProject &&
2432
settings !== undefined &&
2533
settings.getBoolean(SettingsKey.useCmakeTools)
2634
) {

src/commands/newProject.mts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { window, type Uri } from "vscode";
44
import { NewProjectPanel } from "../webview/newProjectPanel.mjs";
55
// eslint-disable-next-line max-len
66
import { NewMicroPythonProjectPanel } from "../webview/newMicroPythonProjectPanel.mjs";
7+
import { NewRustProjectPanel } from "../webview/newRustProjectPanel.mjs";
78

89
/**
910
* Enum for the language of the project.
@@ -13,13 +14,15 @@ import { NewMicroPythonProjectPanel } from "../webview/newMicroPythonProjectPane
1314
export enum ProjectLang {
1415
cCpp = 1,
1516
micropython = 2,
17+
rust = 3,
1618
}
1719

1820
export default class NewProjectCommand extends CommandWithArgs {
1921
private readonly _logger: Logger = new Logger("NewProjectCommand");
2022
private readonly _extensionUri: Uri;
2123
private static readonly micropythonOption = "MicroPython";
2224
private static readonly cCppOption = "C/C++";
25+
private static readonly rustOption = "Rust (experimental)";
2326

2427
public static readonly id = "newProject";
2528

@@ -34,6 +37,8 @@ export default class NewProjectCommand extends CommandWithArgs {
3437
? NewProjectCommand.cCppOption
3538
: preSelectedType === ProjectLang.micropython
3639
? NewProjectCommand.micropythonOption
40+
: preSelectedType === ProjectLang.rust
41+
? NewProjectCommand.rustOption
3742
: undefined;
3843
}
3944

@@ -42,7 +47,11 @@ export default class NewProjectCommand extends CommandWithArgs {
4247
const lang =
4348
this.preSelectedTypeToStr(preSelectedType) ??
4449
(await window.showQuickPick(
45-
[NewProjectCommand.cCppOption, NewProjectCommand.micropythonOption],
50+
[
51+
NewProjectCommand.cCppOption,
52+
NewProjectCommand.micropythonOption,
53+
NewProjectCommand.rustOption,
54+
],
4655
{
4756
placeHolder: "Select which language to use for your new project",
4857
canPickMany: false,
@@ -58,6 +67,9 @@ export default class NewProjectCommand extends CommandWithArgs {
5867
if (lang === NewProjectCommand.micropythonOption) {
5968
// create a new project with MicroPython
6069
NewMicroPythonProjectPanel.createOrShow(this._extensionUri);
70+
} else if (lang === NewProjectCommand.rustOption) {
71+
// create a new project with Rust
72+
NewRustProjectPanel.createOrShow(this._extensionUri);
6173
} else {
6274
// show webview where the process of creating a new project is continued
6375
NewProjectPanel.createOrShow(this._extensionUri);

src/contextKeys.mts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ import { extensionName } from "./commands/command.mjs";
22

33
export enum ContextKeys {
44
isPicoProject = `${extensionName}.isPicoProject`,
5+
isRustProject = `${extensionName}.isRustProject`,
56
}

src/extension.mts

Lines changed: 78 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ import FlashProjectSWDCommand from "./commands/flashProjectSwd.mjs";
7676
import { NewMicroPythonProjectPanel } from "./webview/newMicroPythonProjectPanel.mjs";
7777
import type { Progress as GotProgress } from "got";
7878
import findPython, { showPythonNotFoundError } from "./utils/pythonHelper.mjs";
79+
import { downloadAndInstallRust } from "./utils/rustUtil.mjs";
80+
import State from "./state.mjs";
7981

8082
export async function activate(context: ExtensionContext): Promise<void> {
8183
Logger.info(LoggerSource.extension, "Extension activation triggered");
@@ -166,11 +168,15 @@ export async function activate(context: ExtensionContext): Promise<void> {
166168
);
167169

168170
const workspaceFolder = workspace.workspaceFolders?.[0];
171+
const isRustProject = workspaceFolder
172+
? existsSync(join(workspaceFolder.uri.fsPath, ".pico-rs"))
173+
: false;
169174

170175
// check if is a pico project
171176
if (
172177
workspaceFolder === undefined ||
173-
!existsSync(join(workspaceFolder.uri.fsPath, "pico_sdk_import.cmake"))
178+
(!existsSync(join(workspaceFolder.uri.fsPath, "pico_sdk_import.cmake")) &&
179+
!isRustProject)
174180
) {
175181
// finish activation
176182
Logger.warn(
@@ -186,55 +192,87 @@ export async function activate(context: ExtensionContext): Promise<void> {
186192
return;
187193
}
188194

189-
const cmakeListsFilePath = join(workspaceFolder.uri.fsPath, "CMakeLists.txt");
190-
if (!existsSync(cmakeListsFilePath)) {
191-
Logger.warn(
192-
LoggerSource.extension,
193-
"No CMakeLists.txt in workspace folder has been found."
194-
);
195-
await commands.executeCommand(
196-
"setContext",
197-
ContextKeys.isPicoProject,
198-
false
195+
/*void commands.executeCommand(
196+
"setContext",
197+
ContextKeys.isRustProject,
198+
isRustProject
199+
);*/
200+
State.getInstance().isRustProject = isRustProject;
201+
202+
if (!isRustProject) {
203+
const cmakeListsFilePath = join(
204+
workspaceFolder.uri.fsPath,
205+
"CMakeLists.txt"
199206
);
207+
if (!existsSync(cmakeListsFilePath)) {
208+
Logger.warn(
209+
LoggerSource.extension,
210+
"No CMakeLists.txt in workspace folder has been found."
211+
);
212+
await commands.executeCommand(
213+
"setContext",
214+
ContextKeys.isPicoProject,
215+
false
216+
);
200217

201-
return;
218+
return;
219+
}
220+
221+
// check if it has .vscode folder and cmake donotedit header in CMakelists.txt
222+
if (
223+
!existsSync(join(workspaceFolder.uri.fsPath, ".vscode")) ||
224+
!readFileSync(cmakeListsFilePath)
225+
.toString("utf-8")
226+
.includes(CMAKE_DO_NOT_EDIT_HEADER_PREFIX)
227+
) {
228+
Logger.warn(
229+
LoggerSource.extension,
230+
"No .vscode folder and/or cmake",
231+
'"DO NOT EDIT"-header in CMakelists.txt found.'
232+
);
233+
await commands.executeCommand(
234+
"setContext",
235+
ContextKeys.isPicoProject,
236+
false
237+
);
238+
const wantToImport = await window.showInformationMessage(
239+
"Do you want to import this project as Raspberry Pi Pico project?",
240+
"Yes",
241+
"No"
242+
);
243+
if (wantToImport === "Yes") {
244+
void commands.executeCommand(
245+
`${extensionName}.${ImportProjectCommand.id}`,
246+
workspaceFolder.uri
247+
);
248+
}
249+
250+
return;
251+
}
202252
}
203253

204-
// check if it has .vscode folder and cmake donotedit header in CMakelists.txt
205-
if (
206-
!existsSync(join(workspaceFolder.uri.fsPath, ".vscode")) ||
207-
!readFileSync(cmakeListsFilePath)
208-
.toString("utf-8")
209-
.includes(CMAKE_DO_NOT_EDIT_HEADER_PREFIX)
210-
) {
211-
Logger.warn(
212-
LoggerSource.extension,
213-
"No .vscode folder and/or cmake",
214-
'"DO NOT EDIT"-header in CMakelists.txt found.'
215-
);
216-
await commands.executeCommand(
217-
"setContext",
218-
ContextKeys.isPicoProject,
219-
false
220-
);
221-
const wantToImport = await window.showInformationMessage(
222-
"Do you want to import this project as Raspberry Pi Pico project?",
223-
"Yes",
224-
"No"
254+
await commands.executeCommand("setContext", ContextKeys.isPicoProject, true);
255+
256+
if (isRustProject) {
257+
const cargo = await window.withProgress(
258+
{
259+
location: ProgressLocation.Notification,
260+
title: "Downloading and installing Rust. This may take a while...",
261+
cancellable: false,
262+
},
263+
async () => downloadAndInstallRust()
225264
);
226-
if (wantToImport === "Yes") {
227-
void commands.executeCommand(
228-
`${extensionName}.${ImportProjectCommand.id}`,
229-
workspaceFolder.uri
230-
);
265+
if (!cargo) {
266+
void window.showErrorMessage("Failed to install Rust.");
267+
268+
return;
231269
}
232270

271+
ui.showStatusBarItems(isRustProject);
272+
233273
return;
234274
}
235275

236-
await commands.executeCommand("setContext", ContextKeys.isPicoProject, true);
237-
238276
// get sdk selected in the project
239277
const selectedToolchainAndSDKVersions =
240278
await cmakeGetSelectedToolchainAndSDKVersions(workspaceFolder.uri);

src/logger.mts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export enum LoggerSource {
4040
cmake = "cmakeUtil",
4141
downloadHelper = "downloadHelper",
4242
pythonHelper = "pythonHelper",
43+
rustUtil = "rustUtil",
4344
}
4445

4546
/**

src/state.mts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export default class State {
2+
private static instance?: State;
3+
public isRustProject = false;
4+
5+
public constructor() {}
6+
7+
public static getInstance(): State {
8+
if (!State.instance) {
9+
this.instance = new State();
10+
}
11+
12+
return this.instance!;
13+
}
14+
}

0 commit comments

Comments
 (0)