Skip to content

Commit

Permalink
Add support for cmake-tools extension
Browse files Browse the repository at this point in the history
Add a cmake-kits.json, which allows the cmake-tools extension to compile the project, using the correct Ninja, Python, and compiler.

Signed-off-by: William Vinnicombe <[email protected]>
  • Loading branch information
will-v-pi committed Apr 8, 2024
1 parent d1272ff commit 01af8f5
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 58 deletions.
12 changes: 12 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,18 @@
"category": "Raspberry Pi Pico",
"enablement": "false"
},
{
"command": "raspberry-pi-pico.getPythonPath",
"title": "Get python path",
"category": "Raspberry Pi Pico",
"enablement": "false"
},
{
"command": "raspberry-pi-pico.getEnvPath",
"title": "Get environment path",
"category": "Raspberry Pi Pico",
"enablement": "false"
},
{
"command": "raspberry-pi-pico.compileProject",
"title": "Compile Pico Project",
Expand Down
25 changes: 24 additions & 1 deletion scripts/pico_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

VSCODE_LAUNCH_FILENAME = 'launch.json'
VSCODE_C_PROPERTIES_FILENAME = 'c_cpp_properties.json'
VSCODE_CMAKE_KITS_FILENAME ='cmake-kits.json'
VSCODE_SETTINGS_FILENAME ='settings.json'
VSCODE_EXTENSIONS_FILENAME ='extensions.json'
VSCODE_TASKS_FILENAME ='tasks.json'
Expand Down Expand Up @@ -740,7 +741,7 @@ def generateProjectFiles(projectPath, projectName, sdkPath, projects, debugger,
# Need to escape windows files paths backslashes
# TODO: env in currently not supported in compilerPath var
#cPath = f"${{env:PICO_TOOLCHAIN_PATH_{envSuffix}}}" + os.path.sep + os.path.basename(str(compilerPath).replace('\\', '\\\\' ))
cPath = compilerPath.as_posix()
cPath = compilerPath.as_posix() + (".exe" if isWindows else "")

# if this is a path in the .pico-sdk homedir tell the settings to use the homevar
user_home = os.path.expanduser("~").replace("\\", "/")
Expand Down Expand Up @@ -852,6 +853,24 @@ def generateProjectFiles(projectPath, projectName, sdkPath, projects, debugger,

pythonExe = sys.executable.replace("\\", "/").replace(user_home, "${HOME}") if use_home_var else sys.executable

# kits
kits = f'''[
{{
"name": "Pico",
"compilers": {{
"C": "{cPath}",
"CXX": "{cPath}"
}},
"toolchainFile": "{propertiesSdkPath(sdkVersion)}/cmake/preload/toolchains/pico_arm_gcc.cmake",
"environmentVariables": {{
"PATH": "${{command:raspberry-pi-pico.getEnvPath}};${{env:PATH}}"
}},
"cmakeSettings": {{
"Python3_EXECUTABLE": "${{command:raspberry-pi-pico.getPythonPath}}"
}}
}}
]'''

# settings
settings = f'''{{
"cmake.options.statusBarVisibility": "hidden",
Expand Down Expand Up @@ -965,6 +984,10 @@ def generateProjectFiles(projectPath, projectName, sdkPath, projects, debugger,
file.write(properties)
file.close()

file = open(VSCODE_CMAKE_KITS_FILENAME, 'w')
file.write(kits)
file.close()

file = open(VSCODE_SETTINGS_FILENAME, 'w')
file.write(settings)
file.close()
Expand Down
43 changes: 43 additions & 0 deletions src/commands/getPaths.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { CommandWithResult } from "./command.mjs";
import { workspace } from "vscode";
import { getPythonPath, getPath } from "../utils/cmakeUtil.mjs";

export class GetPythonPathCommand
extends CommandWithResult<string> {
constructor() {
super("getPythonPath");
}

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

const pythonPath = await getPythonPath();

return pythonPath;
}
}

export class GetEnvPathCommand
extends CommandWithResult<string> {
constructor() {
super("getEnvPath");
}

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

const path = await getPath();

return path;
}
}
6 changes: 6 additions & 0 deletions src/extension.mts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ import { existsSync, readFileSync } from "fs";
import { basename, join } from "path";
import CompileProjectCommand from "./commands/compileProject.mjs";
import LaunchTargetPathCommand from "./commands/launchTargetPath.mjs";
import {
GetPythonPathCommand,
GetEnvPathCommand
} from "./commands/getPaths.mjs";
import {
downloadAndInstallCmake,
downloadAndInstallNinja,
Expand Down Expand Up @@ -80,6 +84,8 @@ export async function activate(context: ExtensionContext): Promise<void> {
new NewProjectCommand(context.extensionUri),
new SwitchSDKCommand(ui, context.extensionUri),
new LaunchTargetPathCommand(),
new GetPythonPathCommand(),
new GetEnvPathCommand(),
new CompileProjectCommand(),
new ClearGithubApiCacheCommand(),
new ConditionalDebuggingCommand(),
Expand Down
146 changes: 89 additions & 57 deletions src/utils/cmakeUtil.mts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,88 @@ import { rimraf, windows as rimrafWindows } from "rimraf";
import { homedir } from "os";
import which from "which";

export async function getPythonPath(): Promise<string> {
const settings = Settings.getInstance();
if (settings === undefined) {
Logger.log("Error: Settings not initialized.");

return "";
}

const pythonPath = (
await which(
settings
.getString(SettingsKey.python3Path)
?.replace(HOME_VAR, homedir()) ||
(process.platform === "win32" ? "python" : "python3"),
{ nothrow: true }
)
).replaceAll("\\", "/");

return `${pythonPath.replaceAll("\\", "/")}`;
}

export async function getPath(): Promise<string> {
const settings = Settings.getInstance();
if (settings === undefined) {
Logger.log("Error: Settings not initialized.");

return "";
}

const ninjaPath = (
await which(
settings
.getString(SettingsKey.ninjaPath)
?.replace(HOME_VAR, homedir()) || "ninja",
{ nothrow: true }
)
).replaceAll("\\", "/");
const cmakePath = (
await which(
settings
.getString(SettingsKey.cmakePath)
?.replace(HOME_VAR, homedir()) || "cmake",
{ nothrow: true }
)
).replaceAll("\\", "/");
Logger.log(
settings.getString(SettingsKey.python3Path)?.replace(HOME_VAR, homedir())
);
// TODO: maybe also check for "python" on unix systems
const pythonPath = await getPythonPath();

if (ninjaPath === null || cmakePath === null) {
const missingTools = [];
if (ninjaPath === null) {
missingTools.push("Ninja");
}
if (cmakePath === null) {
missingTools.push("CMake");
}
if (pythonPath === null) {
missingTools.push("Python 3");
}
void showRequirementsNotMetErrorMessage(missingTools);

return "";
}

const isWindows = process.platform === "win32";

return `${
ninjaPath.includes("/") ? dirname(ninjaPath) : ""
}${
cmakePath.includes("/")
? `${isWindows ? ";" : ":"}${dirname(cmakePath)}`
: ""
}${
pythonPath.includes("/")
? `${dirname(pythonPath)}${isWindows ? ";" : ":"}`
: ""
}`;
}

export async function configureCmakeNinja(folder: Uri): Promise<boolean> {
const settings = Settings.getInstance();
if (settings === undefined) {
Expand All @@ -25,52 +107,6 @@ export async function configureCmakeNinja(folder: Uri): Promise<boolean> {
folder.with({ path: join(folder.fsPath, "CMakeLists.txt") })
);

const ninjaPath = (
await which(
settings
.getString(SettingsKey.ninjaPath)
?.replace(HOME_VAR, homedir()) || "ninja",
{ nothrow: true }
)
).replaceAll("\\", "/");
const cmakePath = (
await which(
settings
.getString(SettingsKey.cmakePath)
?.replace(HOME_VAR, homedir()) || "cmake",
{ nothrow: true }
)
).replaceAll("\\", "/");
Logger.log(
settings.getString(SettingsKey.python3Path)?.replace(HOME_VAR, homedir())
);
// TODO: maybe also check for "python" on unix systems
const pythonPath = (
await which(
settings
.getString(SettingsKey.python3Path)
?.replace(HOME_VAR, homedir()) ||
(process.platform === "win32" ? "python" : "python3"),
{ nothrow: true }
)
).replaceAll("\\", "/");

if (ninjaPath === null || cmakePath === null) {
const missingTools = [];
if (ninjaPath === null) {
missingTools.push("Ninja");
}
if (cmakePath === null) {
missingTools.push("CMake");
}
if (pythonPath === null) {
missingTools.push("Python 3");
}
void showRequirementsNotMetErrorMessage(missingTools);

return false;
}

void window.withProgress(
{
location: ProgressLocation.Notification,
Expand All @@ -93,17 +129,13 @@ export async function configureCmakeNinja(folder: Uri): Promise<boolean> {
? resolve(join(dirname(pythonPath), ".."))
: "";*/
const isWindows = process.platform === "win32";
customEnv[isWindows ? "Path" : "PATH"] = `${
ninjaPath.includes("/") ? dirname(ninjaPath) : ""
}${
cmakePath.includes("/")
? `${isWindows ? ";" : ":"}${dirname(cmakePath)}`
: ""
}${
pythonPath.includes("/")
? `${dirname(pythonPath)}${isWindows ? ";" : ":"}`
: ""
}${customEnv[isWindows ? "Path" : "PATH"]}`;
const customPath = await getPath();
if (!customPath) {
return false;
}
customEnv[isWindows ? "Path" : "PATH"] = customPath
+ customEnv[isWindows ? "Path" : "PATH"];
const pythonPath = await getPythonPath();

const command =
`${
Expand Down

0 comments on commit 01af8f5

Please sign in to comment.