Skip to content

Commit

Permalink
Fix #39 - Add pico-vscode.cmake include
Browse files Browse the repository at this point in the history
Instead of different DO NEVER EDIT lines for each SDK version, include a common file which does all that logic

Update any existing CMakeLists.txt files to this new style when extension is loaded
  • Loading branch information
will-v-pi committed Aug 15, 2024
1 parent fa7ab82 commit f4ef8ce
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 92 deletions.
25 changes: 25 additions & 0 deletions scripts/pico-vscode.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
set(PICO_SDK_PATH "${USERHOME}/.pico-sdk/sdk/${sdkVersion}")
set(PICO_TOOLCHAIN_PATH "${USERHOME}/.pico-sdk/toolchain/${toolchainVersion}")

if (sdkVersion VERSION_LESS "2.0.0")
if(WIN32)
set(pico-sdk-tools_DIR "${USERHOME}/.pico-sdk/tools/${sdkVersion}")
include(${pico-sdk-tools_DIR}/pico-sdk-tools-config.cmake)
include(${pico-sdk-tools_DIR}/pico-sdk-tools-config-version.cmake)
endif()
else()
set(pioasm_HINT "${USERHOME}/.pico-sdk/tools/${sdkVersion}/pioasm")
if(EXISTS ${pioasm_HINT})
set(pioasm_DIR ${pioasm_HINT})
endif()
set(picotool_HINT "${USERHOME}/.pico-sdk/picotool/${picotoolVersion}/picotool")
if(EXISTS ${picotool_HINT})
set(picotool_DIR ${picotool_HINT})
endif()
if(PICO_TOOLCHAIN_PATH MATCHES "RISCV")
set(PICO_PLATFORM rp2350-riscv CACHE STRING "Pico Platform")
if(PICO_TOOLCHAIN_PATH MATCHES "COREV")
set(PICO_COMPILER pico_riscv_gcc_zcb_zcmp)
endif()
endif()
endif()
64 changes: 10 additions & 54 deletions scripts/pico_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,17 +361,8 @@ def relativePicotoolPath(picotoolVersion):
def relativeOpenOCDPath(openocdVersion):
return f"/.pico-sdk/openocd/{openocdVersion}"

def cmakeSdkPath(sdkVersion):
return f"${{USERHOME}}{relativeSDKPath(sdkVersion)}"

def cmakeToolchainPath(toolchainVersion):
return f"${{USERHOME}}{relativeToolchainPath(toolchainVersion)}"

def cmakeToolsPath(sdkVersion):
return f"${{USERHOME}}{relativeToolsPath(sdkVersion)}"

def cmakePicotoolPath(picotoolVersion):
return f"${{USERHOME}}{relativePicotoolPath(picotoolVersion)}"
def cmakeIncPath():
return "${USERHOME}/.pico-sdk/cmake/pico-vscode.cmake"

def propertiesSdkPath(sdkVersion, force_windows=False, force_non_windows=False):
if (isWindows or force_windows) and not force_non_windows:
Expand Down Expand Up @@ -561,7 +552,6 @@ def GenerateMain(folder, projectName, features, cpp):


def GenerateCMake(folder, params):

filename = Path(folder) / CMAKELIST_FILENAME
projectName = params['projectName']
board_type = params['boardtype']
Expand All @@ -578,69 +568,35 @@ def GenerateCMake(folder, params):
"# Initialise pico_sdk from installed location\n"
"# (note this can come from environment, CMake cache etc)\n\n"
)

# if you change the do never edit headline you need to change the check for it in extension.mts
cmake_header_us_1_5_1 = (
"# == DO NEVER EDIT THE NEXT LINES for Raspberry Pi Pico VS Code Extension to work ==\n"
"if(WIN32)\n"
" set(USERHOME $ENV{USERPROFILE})\n"
"else()\n"
" set(USERHOME $ENV{HOME})\n"
"endif()\n"
f"set(PICO_SDK_PATH {cmakeSdkPath(params['sdkVersion'])})\n"
f"set(PICO_TOOLCHAIN_PATH {cmakeToolchainPath(params['toolchainVersion'])})\n"
"if(WIN32)\n"
f" set(pico-sdk-tools_DIR {cmakeToolsPath(params['sdkVersion'])})\n"
" include(${pico-sdk-tools_DIR}/pico-sdk-tools-config.cmake)\n"
" include(${pico-sdk-tools_DIR}/pico-sdk-tools-config-version.cmake)\n"
"endif()\n"
"# ====================================================================================\n"
)
cmake_header_us = (
"# == DO NEVER EDIT THE NEXT LINES for Raspberry Pi Pico VS Code Extension to work ==\n"
"if(WIN32)\n"
" set(USERHOME $ENV{USERPROFILE})\n"
" set(USERHOME $ENV{USERPROFILE})\n"
"else()\n"
" set(USERHOME $ENV{HOME})\n"
"endif()\n"
f"set(PICO_SDK_PATH {cmakeSdkPath(params['sdkVersion'])})\n"
f"set(PICO_TOOLCHAIN_PATH {cmakeToolchainPath(params['toolchainVersion'])})\n"
f"set(pioasm_HINT {cmakeToolsPath(params['sdkVersion'])}/pioasm)\n"
"if(EXISTS ${pioasm_HINT})\n"
" set(pioasm_DIR ${pioasm_HINT})\n"
"endif()\n"
f"set(picotool_HINT {cmakePicotoolPath(params['picotoolVersion'])}/picotool)\n"
"if(EXISTS ${picotool_HINT})\n"
" set(picotool_DIR ${picotool_HINT})\n"
"endif()\n"
"if(PICO_TOOLCHAIN_PATH MATCHES \"RISCV\")\n"
" set(PICO_PLATFORM rp2350-riscv CACHE STRING \"Pico Platform\")\n"
" if(PICO_TOOLCHAIN_PATH MATCHES \"COREV\")\n"
" set(PICO_COMPILER pico_riscv_gcc_zcb_zcmp)\n"
" endif()\n"
"endif()\n"
f"set(sdkVersion {params['sdkVersion']})\n"
f"set(toolchainVersion {params['toolchainVersion']})\n"
f"set(picotoolVersion {params['picotoolVersion']})\n"
f"include({cmakeIncPath()})\n"
"# ====================================================================================\n"
)

# Use old header for version less than 2.0.0
if params['sdkVersion'].split(".")[0] < "2":
cmake_header_us = cmake_header_us_1_5_1
cmake_header2 = (
f"set(PICO_BOARD {board_type} CACHE STRING \"Board type\")\n\n"
"# Pull in Raspberry Pi Pico SDK (must be before project)\n"
"include(pico_sdk_import.cmake)\n\n"
"if (PICO_SDK_VERSION_STRING VERSION_LESS \"1.4.0\")\n"
" message(FATAL_ERROR \"Raspberry Pi Pico SDK version 1.4.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}\")\n"
"endif()\n\n"
f"project({projectName} C CXX ASM)\n"
)

cmake_header3 = (
"\n# Initialise the Raspberry Pi Pico SDK\n"
"pico_sdk_init()\n\n"
"# Add executable. Default name is the project name, version 0.1\n\n"
)


if params['wantConvert']:
with open(filename, 'r+') as file:
Expand Down
6 changes: 3 additions & 3 deletions src/commands/getPaths.mts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export class GetGDBPathCommand
super("getGDBPath");
}

execute(): string {
async execute(): Promise<string> {
if (
workspace.workspaceFolders === undefined ||
workspace.workspaceFolders.length === 0
Expand All @@ -65,8 +65,8 @@ export class GetGDBPathCommand
const workspaceFolder = workspace.workspaceFolders?.[0];

const selectedToolchainAndSDKVersions =
cmakeGetSelectedToolchainAndSDKVersions(
join(workspaceFolder.uri.fsPath, "CMakeLists.txt")
await cmakeGetSelectedToolchainAndSDKVersions(
workspaceFolder.uri
);
if (selectedToolchainAndSDKVersions === null) {
return "";
Expand Down
6 changes: 3 additions & 3 deletions src/extension.mts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ import VersionBundlesLoader from "./utils/versionBundles.mjs";
import { pyenvInstallPython, setupPyenv } from "./utils/pyenvUtil.mjs";
import NewExampleProjectCommand from "./commands/newExampleProject.mjs";

const CMAKE_DO_NOT_EDIT_HEADER_PREFIX =
export const CMAKE_DO_NOT_EDIT_HEADER_PREFIX =
// eslint-disable-next-line max-len
"== DO NEVER EDIT THE NEXT LINES for Raspberry Pi Pico VS Code Extension to work ==";

Expand Down Expand Up @@ -199,8 +199,8 @@ export async function activate(context: ExtensionContext): Promise<void> {

// get sdk selected in the project
const selectedToolchainAndSDKVersions =
cmakeGetSelectedToolchainAndSDKVersions(
join(workspaceFolder.uri.fsPath, "CMakeLists.txt")
await cmakeGetSelectedToolchainAndSDKVersions(
workspaceFolder.uri
);
if (selectedToolchainAndSDKVersions === null) {
return;
Expand Down
85 changes: 53 additions & 32 deletions src/utils/cmakeUtil.mts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import { rimraf, windows as rimrafWindows } from "rimraf";
import { homedir } from "os";
import which from "which";
import { compareLtMajor } from "./semverUtil.mjs";
import { picotoolVersion } from "../webview/newProjectPanel.mjs";
import { CMAKE_DO_NOT_EDIT_HEADER_PREFIX } from "../extension.mjs";
import { buildCMakeIncPath } from "./download.mjs";

export async function getPythonPath(): Promise<string> {
const settings = Settings.getInstance();
Expand Down Expand Up @@ -238,9 +241,8 @@ export async function cmakeUpdateSDK(
): Promise<boolean> {
// TODO: support for scaning for seperate locations of the CMakeLists.txt file in the project
const cmakeFilePath = join(folder.fsPath, "CMakeLists.txt");
const sdkPathRegex = /^set\(PICO_SDK_PATH\s+([^)]+)\)$/m;
const toolchainPathRegex = /^set\(PICO_TOOLCHAIN_PATH\s+([^)]+)\)$/m;
const toolsPathRegex = /^set\(pico-sdk-tools_DIR\s+([^)]+)\)$/m;
const updateSectionRegex =
new RegExp(`^# ${CMAKE_DO_NOT_EDIT_HEADER_PREFIX}.*# =+$`, "ms");
const picoBoardRegex = /^set\(PICO_BOARD\s+([^)]+)\)$/m;

const settings = Settings.getInstance();
Expand All @@ -258,17 +260,19 @@ export async function cmakeUpdateSDK(

let modifiedContent = content
.replace(
sdkPathRegex,
`set(PICO_SDK_PATH \${USERHOME}/.pico-sdk/sdk/${newSDKVersion})`
)
.replace(
toolchainPathRegex,
"set(PICO_TOOLCHAIN_PATH ${USERHOME}/.pico-sdk" +
`/toolchain/${newToolchainVersion})`
)
.replace(
toolsPathRegex,
`set(pico-sdk-tools_DIR \${USERHOME}/.pico-sdk/tools/${newSDKVersion})`
updateSectionRegex,
`# ${CMAKE_DO_NOT_EDIT_HEADER_PREFIX}\n` +
"if(WIN32)\n" +
" set(USERHOME $ENV{USERPROFILE})\n" +
"else()\n" +
" set(USERHOME $ENV{HOME})\n" +
"endif()\n" +
`set(sdkVersion ${newSDKVersion})\n` +
`set(toolchainVersion ${newToolchainVersion})\n` +
`set(picotoolVersion ${picotoolVersion})\n` +
`include(${buildCMakeIncPath()})\n` +
// eslint-disable-next-line max-len
"# ===================================================================================="
);

const picoBoard = content.match(picoBoardRegex);
Expand Down Expand Up @@ -328,31 +332,48 @@ export async function cmakeUpdateSDK(
* @returns An tupple with the [sdk, toolchain] versions or null if the file could not
* be read or the versions could not be extracted.
*/
export function cmakeGetSelectedToolchainAndSDKVersions(
cmakeFilePath: string
): [string, string] | null {
export async function cmakeGetSelectedToolchainAndSDKVersions(
folder: Uri
): Promise<[string, string, string] | null> {
const cmakeFilePath = join(folder.fsPath, "CMakeLists.txt");
const content = readFileSync(cmakeFilePath, "utf8");

// 0.15.1 and before
const sdkPathRegex = /^set\(PICO_SDK_PATH\s+([^)]+)\)$/m;
const toolchainPathRegex = /^set\(PICO_TOOLCHAIN_PATH\s+([^)]+)\)$/m;
const match = content.match(sdkPathRegex);
const match2 = content.match(toolchainPathRegex);

if (match === null || match2 === null) {
return null;
}
const oldMatch = content.match(sdkPathRegex);
const oldMatch2 = content.match(toolchainPathRegex);

// Current
const sdkVersionRegex = /^set\(sdkVersion\s+([^)]+)\)$/m;
const toolchainVersionRegex = /^set\(toolchainVersion\s+([^)]+)\)$/m;
const picotoolVersionRegex = /^set\(picotoolVersion\s+([^)]+)\)$/m;
const match = content.match(sdkVersionRegex);
const match2 = content.match(toolchainVersionRegex);
const match3 = content.match(picotoolVersionRegex);

if (match !== null && match2 !== null && match3 !== null) {
return [match[1], match2[1], match3[1]];
} else if (oldMatch !== null && oldMatch2 !== null) {
const path = oldMatch[1];
const path2 = oldMatch2[1];
const versionRegex = /^\${USERHOME}\/\.pico-sdk\/sdk\/([^)]+)$/m;
const versionRegex2 = /^\${USERHOME}\/\.pico-sdk\/toolchain\/([^)]+)$/m;
const versionMatch = path.match(versionRegex);
const versionMatch2 = path2.match(versionRegex2);

if (versionMatch === null || versionMatch2 === null) {
return null;
}

const path = match[1];
const path2 = match2[1];
const versionRegex = /^\${USERHOME}\/\.pico-sdk\/sdk\/([^)]+)$/m;
const versionRegex2 = /^\${USERHOME}\/\.pico-sdk\/toolchain\/([^)]+)$/m;
const versionMatch = path.match(versionRegex);
const versionMatch2 = path2.match(versionRegex2);
Logger.log("Updating extension lines in CMake file");
await cmakeUpdateSDK(folder, versionMatch[1], versionMatch2[1]);
Logger.log("Extension lines updated");

if (versionMatch === null || versionMatch2 === null) {
return [versionMatch[1], versionMatch2[1], picotoolVersion];
} else {
return null;
}

return [versionMatch[1], versionMatch2[1]];
}

/**
Expand Down
17 changes: 17 additions & 0 deletions src/utils/download.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
copyFileSync,
createWriteStream, existsSync, readdirSync, symlinkSync, unlinkSync
} from "fs";
import { mkdir } from "fs/promises";
Expand Down Expand Up @@ -85,6 +86,16 @@ export function buildSDKPath(version: string): string {
);
}

export function buildCMakeIncPath(): string {
// TODO: maybe replace . with _
return joinPosix(
homedir().replaceAll("\\", "/"),
".pico-sdk",
"cmake",
"pico-vscode.cmake"
);
}

export function buildToolsPath(version: string): string {
// TODO: maybe replace . with _
return joinPosix(
Expand Down Expand Up @@ -291,6 +302,12 @@ export async function downloadAndInstallSDK(
return false;
}

// Install pico-vscode.cmake file - overwrite if it's already there
copyFileSync(
joinPosix(getScriptsRoot(), "pico-vscode.cmake"),
buildCMakeIncPath()
);

const targetDirectory = buildSDKPath(version);

// Check if the SDK is already installed
Expand Down

0 comments on commit f4ef8ce

Please sign in to comment.