diff --git a/.gitignore b/.gitignore
index f36cdc72..61153f78 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ node_modules
src/views/app/sprites-generated
test/**/c_cpp_properties.json
*.vsix
+assets/platform/*/arduino-cli
diff --git a/NOTICE_arduino-cli.txt b/NOTICE_arduino-cli.txt
new file mode 100644
index 00000000..b61411f9
--- /dev/null
+++ b/NOTICE_arduino-cli.txt
@@ -0,0 +1,16 @@
+NOTICES AND INFORMATION
+Do Not Translate or Localize
+
+Microsoft makes the arduino-cli open source code available at
+https://3rdpartysource.microsoft.com, or you may send a check or money order for
+US $5.00, including the product name, the open source component name, platform,
+and version number, to:
+
+Source Code Compliance Team
+Microsoft Corporation
+One Microsoft Way
+Redmond, WA 98052
+USA
+
+Notwithstanding any other terms, you may reverse engineer this software to the extent
+required to debug changes to any libraries licensed under the GNU Lesser General Public License.
\ No newline at end of file
diff --git a/README.md b/README.md
index 60b29a54..72bfaed8 100644
--- a/README.md
+++ b/README.md
@@ -15,19 +15,31 @@ Welcome to the Visual Studio Code extension for **Arduino** preview !
* Integrated Arduino Debugging New
## Prerequisites
-Either the Arduino IDE or Arduino CLI are required.
+Either the legacy Arduino IDE or Arduino CLI are required. The recommended
+approach is to use the version of Arduino CLI that comes bundled with the
+extension, which works out of the box. Support for the legacy Arduino IDE will
+be removed in a future version of the extension.
-### Arduino IDE
-The Arduino IDE can be installed the Arduino [download page](https://www.arduino.cc/en/main/software#download).
-- The supported Arduino IDE versions are `1.6.x` and up to, but not including, 2.0.0.
+### Arduino CLI
+To use the bundled version of Arduino CLI, `arduino.useArduinoCli` should be `true`,
+and `arduino.path` and `arduino.commandPath` should be empty or unset.
+`arduino.useArduinoCli` defaults to `false` while we deprecate support for the
+Arduino IDE, but there will be a prompt when the extension first activates to
+switch to the Arduino CLI.
+
+If you want to use a custom version of Arduino CLI, it can be downloaded from
+the repository's [release page](https://github.com/arduino/arduino-cli/releases/).
+For custom versions, `arduino.path` must be set to the directory containing the
+Arduino CLI executable.
+
+### Legacy Arduino IDE
+Use of the legacy Arduino IDE is not recommended, and support for the legacy
+Arduino IDE will be removed in a future version of the extension. The legacy
+Arduino IDE can be installed from the Arduino [download page](https://www.arduino.cc/en/main/software#download).
+- The supported legacy Arduino IDE versions are `1.6.x` and up to, but not including, `2.0.0`.
- The Windows Store's version of the Arduino IDE is not supported because of the sandbox environment that the application runs in.
- *Note:* Arduino IDE `1.8.7` had some breaking changes, causing board package and library installation failures. These failures were corrected in `1.8.8` and later.
-- *Note:* Arduino IDE `2.X.Y` is not supported at this time [issue 1477](https://github.com/microsoft/vscode-arduino/issues/1477)
-
-### Arduino CLI
-The Arduino CLI can be downloaded from the repository's [release page](https://github.com/arduino/arduino-cli/releases/tag/0.13.0)
-- The extension has only been tested with v0.13.0.
-- If you use the CLI you will have to set `arduino.path` since the CLI does not have a default path.
+- *Note:* Arduino IDE `2.X.Y` is not supported and there are no plans for support in the future ([issue 1477](https://github.com/microsoft/vscode-arduino/issues/1477)).
## Installation
Open VS Code and press F1 or Ctrl + Shift + P *or* Cmd + Shift + P to open command palette, select **Install Extension** and type `vscode-arduino`.
@@ -71,9 +83,9 @@ This extension provides several commands in the Command Palette (F1 o
## Options
| Option | Description |
| --- | --- |
-| `arduino.useArduinoCli` | Whether to use the Arduino CLI (`true`) or the Arduino IDE (`false`) -- defaults to `false`. If using `true`, make sure to set the `arduino.path` and `arduino.commandPath` values correctly. |
-| `arduino.path` | Path to the Arduino installation. You can use a custom version of Arduino by modifying this setting to include the full path. Example: `C:\\Program Files\\Arduino` for Windows, `/Applications` for Mac, `/home//Downloads/arduino-1.8.1` for Linux. (Requires a restart after change). The default value is automatically detected from your Arduino IDE installation path. To use the Arduino CLI, use the path that contains the `arduino-cli` executable (e.g. `/usr/local/bin`). |
-| `arduino.commandPath` | Path to an executable (or script) relative to `arduino.path`. The default value is `arduino_debug.exe` for Windows, `Contents/MacOS/Arduino` for Mac and `arduino` for Linux, You also can use a custom launch script to run Arduino by modifying this setting. (Requires a restart after change) Example: `run-arduino.bat` for Windows, `Contents/MacOS/run-arduino.sh` for Mac and `bin/run-arduino.sh` for Linux. To use the Arduino CLI, use `arduino-cli`. |
+| `arduino.useArduinoCli` | Whether to use the Arduino CLI (`true`) or the legacy Arduino IDE (`false`) -- defaults to `false`. If using `true`, either leave the `arduino.path` and `arduino.commandPath` values unset to use the bundled version of Arduino CLI, or point them at a custom version of Arduino CLI. Note that a future version of the extension will change this default to `true` and remove support for legacy Arduino IDE. |
+| `arduino.path` | Path to the Arduino installation. You can use a custom version of Arduino by modifying this setting to include the full path. Example: `C:\\Program Files\\Arduino` for Windows, `/Applications` for Mac, `/home//Downloads/arduino-1.8.1` for Linux. (Requires a restart after change). The default value is automatically detected from your legacy Arduino IDE installation path. To use the Arduino CLI, use the path that contains the `arduino-cli` executable (e.g. `/usr/local/bin`), or leave it unset to use the bundled version of Arduino CLI. |
+| `arduino.commandPath` | Path to an executable (or script) relative to `arduino.path`. The default value is `arduino_debug.exe` for Windows, `Contents/MacOS/Arduino` for Mac and `arduino` for Linux, You also can use a custom launch script to run Arduino by modifying this setting. (Requires a restart after change) Example: `run-arduino.bat` for Windows, `Contents/MacOS/run-arduino.sh` for Mac and `bin/run-arduino.sh` for Linux. To use the bundled version of Arduino CLI, leave this option unset. To use a custom version of Arduino CLI, use `arduino-cli`. |
| `arduino.additionalUrls` | Additional Boards Manager URLs for 3rd party packages as a string array. The default value is empty. |
| `arduino.logLevel` | CLI output log level. Could be info or verbose. The default value is `"info"`. |
| `arduino.clearOutputOnBuild` | Clear the output logs before uploading or verifying. Default value is `false`. |
@@ -91,8 +103,7 @@ The following Visual Studio Code settings are available for the Arduino extensio
```json
{
- "arduino.path": "C:/Program Files (x86)/Arduino",
- "arduino.commandPath": "arduino_debug.exe",
+ "arduino.useArduinoCli": true,
"arduino.logLevel": "info",
"arduino.allowPDEFiletype": false,
"arduino.enableUSBDetection": true,
@@ -105,7 +116,6 @@ The following Visual Studio Code settings are available for the Arduino extensio
"arduino.defaultBaudRate": 115200
}
```
-*Note:* You only need to set `arduino.path` in Visual Studio Code settings, other options are not required.
The following settings are as per sketch settings of the Arduino extension. You can find them in
`.vscode/arduino.json` under the workspace.
diff --git a/build/assets.json b/build/assets.json
new file mode 100644
index 00000000..0cce4e73
--- /dev/null
+++ b/build/assets.json
@@ -0,0 +1,33 @@
+{
+ "version": "0.30.0",
+ "assets": {
+ "arduino-cli_0.30.0_Linux_64bit.tar.gz": {
+ "hash": "f6b1cddf3459b1b6ca9dafe36315c2fa1f6f77386ab3795bbad6a117cbe4230b",
+ "platforms": ["linux-x64"]
+ },
+ "arduino-cli_0.30.0_Linux_ARM64.tar.gz": {
+ "hash": "20d2d036a5af4586b5a046f65d926ed012f7fd85469b484a5fc57ef9ef72fb4b",
+ "platforms": ["linux-arm64"]
+ },
+ "arduino-cli_0.30.0_Linux_ARMv7.tar.gz": {
+ "hash": "1d873f3cb2b939b2df5a7d25e998bded9a4f0c8ac1226d1d5f9abc2bd95a66c3",
+ "platforms": ["linux-armhf"]
+ },
+ "arduino-cli_0.30.0_macOS_64bit.tar.gz": {
+ "hash": "ece83e0bd15813e728d07ce584388a278d62e54529deb84ad07d1521bfe74748",
+ "platforms": ["darwin-x64"]
+ },
+ "arduino-cli_0.30.0_macOS_ARM64.tar.gz": {
+ "hash": "e6c1a35df995ecb464ffa85fe8a96b82bd06135ea5ae961cb34d9c9e99e6c2fa",
+ "platforms": ["darwin-arm64"]
+ },
+ "arduino-cli_0.30.0_Windows_32bit.zip": {
+ "hash": "cccd4b90524581783cf78a3e4942a5c6bf7508a2a5ec4e008bb9c43f1cdb5dbe",
+ "platforms": ["win32-ia32"]
+ },
+ "arduino-cli_0.30.0_Windows_64bit.zip": {
+ "hash": "1808d288382f16594ad73f4797303058b2074b1b375fbb19fca0978033a633af",
+ "platforms": ["win32-x64"]
+ }
+ }
+}
diff --git a/build/downloadAssets.js b/build/downloadAssets.js
new file mode 100644
index 00000000..850ddf65
--- /dev/null
+++ b/build/downloadAssets.js
@@ -0,0 +1,72 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+// This script downloads and verifies platform-specific arduino-cli binaries
+// from GitHub releases. The release is specified by the "version" field in
+// assets.json.
+
+const { execSync } = require("child_process");
+const { createHash } = require("crypto");
+const { readFileSync, mkdirSync, rmSync, renameSync } = require("fs");
+const { resolve } = require("path");
+
+function run(command) {
+ console.log(command);
+ execSync(command);
+}
+
+const config = require('./assets.json');
+
+for (const asset in config.assets) {
+ if (Object.hasOwnProperty.call(config.assets, asset)) {
+ const platforms = config.assets[asset].platforms;
+ const hash = config.assets[asset].hash;
+ for (const platform of platforms) {
+ const directory = resolve(__dirname, "..", "assets", "platform", platform);
+ const destination = resolve(directory, asset);
+
+ // Download the asset.
+ run([
+ "curl",
+ `https://github.com/arduino/arduino-cli/releases/download/${config.version}/${asset}`,
+ "--location",
+ `--output-dir ${directory}`,
+ `--remote-name`,
+ "--silent",
+ "--show-error",
+ ].join(" "));
+
+ // Verify the hash.
+ const actualHash = createHash("sha256")
+ .update(readFileSync(destination))
+ .digest("hex");
+ if (actualHash !== hash) {
+ throw new Error(
+ `Hash mismatch for ${asset} on ${platform}. Expected ${hash} but got ${actualHash}.`
+ );
+ }
+
+ // Extract to an "arduino-cli" directory.
+ const extractDirectory = resolve(directory, "arduino-cli");
+ mkdirSync(extractDirectory, { recursive: true });
+ // tar on Linux doesn't understand zip files.
+ if (asset.endsWith(".zip") && process.platform === 'linux') {
+ run(`unzip ${destination} -d ${extractDirectory}`);
+ } else {
+ run(`tar -xf ${destination} -C ${extractDirectory}`);
+ }
+
+ // Remove the downloaded archive. We don't need to ship it.
+ rmSync(destination);
+
+ // VSIX signing will silently strip any extensionless files. Artificially
+ // add a ".app" extension to extensionless executables.
+ const executable = resolve(extractDirectory, "arduino-cli");
+ try {
+ renameSync(executable, `${executable}.app`);
+ } catch {
+ // The file might not exist. This is expected for Windows.
+ }
+ }
+ }
+}
diff --git a/cgmanifest.json b/cgmanifest.json
new file mode 100644
index 00000000..235a6276
--- /dev/null
+++ b/cgmanifest.json
@@ -0,0 +1,76 @@
+{
+ "$schema": "https://json.schemastore.org/component-detection-manifest.json",
+ "version": 1,
+ "registrations": [
+ {
+ "component": {
+ "type": "other",
+ "other": {
+ "name": "arduino-cli (Linux x64)",
+ "version": "0.30.0",
+ "downloadUrl": "https://github.com/arduino/arduino-cli/releases/download/0.30.0/arduino-cli_0.30.0_Linux_64bit.tar.gz",
+ }
+ }
+ },
+ {
+ "component": {
+ "type": "other",
+ "other": {
+ "name": "arduino-cli (Linux ARM64)",
+ "version": "0.30.0",
+ "downloadUrl": "https://github.com/arduino/arduino-cli/releases/download/0.30.0/arduino-cli_0.30.0_Linux_ARM64.tar.gz",
+ }
+ }
+ },
+ {
+ "component": {
+ "type": "other",
+ "other": {
+ "name": "arduino-cli (Linux ARMv7)",
+ "version": "0.30.0",
+ "downloadUrl": "https://github.com/arduino/arduino-cli/releases/download/0.30.0/arduino-cli_0.30.0_Linux_ARMv7.tar.gz",
+ }
+ }
+ },
+ {
+ "component": {
+ "type": "other",
+ "other": {
+ "name": "arduino-cli (macOS x64)",
+ "version": "0.30.0",
+ "downloadUrl": "https://github.com/arduino/arduino-cli/releases/download/0.30.0/arduino-cli_0.30.0_macOS_64bit.tar.gz",
+ }
+ }
+ },
+ {
+ "component": {
+ "type": "other",
+ "other": {
+ "name": "arduino-cli (macOS ARM64)",
+ "version": "0.30.0",
+ "downloadUrl": "https://github.com/arduino/arduino-cli/releases/download/0.30.0/arduino-cli_0.30.0_macOS_ARM64.tar.gz",
+ }
+ }
+ },
+ {
+ "component": {
+ "type": "other",
+ "other": {
+ "name": "arduino-cli (Windows x86)",
+ "version": "0.30.0",
+ "downloadUrl": "https://github.com/arduino/arduino-cli/releases/download/0.30.0/arduino-cli_0.30.0_Windows_32bit.zip",
+ }
+ }
+ },
+ {
+ "component": {
+ "type": "other",
+ "other": {
+ "name": "arduino-cli (Windows x64)",
+ "version": "0.30.0",
+ "downloadUrl": "https://github.com/arduino/arduino-cli/releases/download/0.30.0/arduino-cli_0.30.0_Windows_64bit.zip",
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index e34173d7..56fbfe85 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -72,7 +72,7 @@
"webpack": "^4.44.1"
},
"engines": {
- "vscode": "^1.56.0"
+ "vscode": "^1.61.0"
}
},
"node_modules/@ampproject/remapping": {
diff --git a/package.json b/package.json
index b2ebfec4..4531ba2d 100644
--- a/package.json
+++ b/package.json
@@ -473,7 +473,7 @@
"arduino.useArduinoCli": {
"type": "boolean",
"default": false,
- "markdownDescription": "Use Arduino CLI installed instead of Arduino IDE. `#arduino.path#` must be set, as there is no default path for 'arduino-cli'. (Requires a restart after change)"
+ "markdownDescription": "Use Arduino CLI installed instead of the legacy Arduino IDE. If `#arduino.path#` and `#arduino.commandPath#` are not set, the extension will use a version of Arduino CLI bundled with the extension. (Requires a restart after change)"
},
"arduino.path": {
"type": "string",
@@ -596,7 +596,7 @@
},
"scripts": {
"build": "gulp build --mode=production",
- "postinstall": "cd ./src/views && npm install",
+ "postinstall": "node ./build/downloadAssets.js && cd ./src/views && npm install",
"test": "gulp test"
},
"extensionDependencies": [
diff --git a/src/arduino/arduinoSettings.ts b/src/arduino/arduinoSettings.ts
index e8f9bbba..26bacaef 100644
--- a/src/arduino/arduinoSettings.ts
+++ b/src/arduino/arduinoSettings.ts
@@ -1,13 +1,16 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
+import { chmod } from "fs/promises";
import * as os from "os";
import * as path from "path";
+import * as vscode from "vscode";
import * as WinReg from "winreg";
import * as util from "../common/util";
import { resolveArduinoPath } from "../common/platform";
+import * as Logger from "../logger/logger";
import { VscodeSettings } from "./vscodeSettings";
export interface IArduinoSettings {
@@ -22,6 +25,7 @@ export interface IArduinoSettings {
defaultBaudRate: number;
preferences: Map;
useArduinoCli: boolean;
+ usingBundledArduinoCli: boolean;
defaultTimestampFormat: string;
analyzeOnSettingChange: boolean;
reloadPreferences(): void;
@@ -44,7 +48,19 @@ export class ArduinoSettings implements IArduinoSettings {
private _defaultTimestampFormat: string;
- public constructor() {
+ private _usingBundledArduinoCli: boolean = false;
+
+ private readonly bundledArduinoCliName: { [platform: string]: string } = {
+ "darwin-arm64": "arduino-cli.app",
+ "darwin-x64": "arduino-cli.app",
+ "linux-arm64": "arduino-cli.app",
+ "linux-armhf": "arduino-cli.app",
+ "linux-x64": "arduino-cli.app",
+ "win32-ia32": "arduino-cli.exe",
+ "win32-x64": "arduino-cli.exe",
+ };
+
+ public constructor(private readonly _context: vscode.ExtensionContext) {
}
public async initialize() {
@@ -136,7 +152,7 @@ export class ArduinoSettings implements IArduinoSettings {
public get commandPath(): string {
const platform = os.platform();
- if (platform === "darwin") {
+ if (platform === "darwin" && !this._usingBundledArduinoCli) {
return path.join(util.resolveMacArduinoAppPath(this._arduinoPath, this._useArduinoCli), path.normalize(this._commandPath));
} else {
return path.join(this._arduinoPath, path.normalize(this._commandPath));
@@ -162,6 +178,10 @@ export class ArduinoSettings implements IArduinoSettings {
return this._useArduinoCli;
}
+ public get usingBundledArduinoCli() {
+ return this._usingBundledArduinoCli;
+ }
+
public get defaultBaudRate() {
return this._defaultBaudRate;
}
@@ -225,14 +245,35 @@ export class ArduinoSettings implements IArduinoSettings {
}
}
+ private async bundledArduinoCliPath(): Promise {
+ const platform = await util.getPlatform();
+ const name = this.bundledArduinoCliName[platform];
+ if (!name) {
+ return undefined;
+ }
+ return this._context.asAbsolutePath(path.join("assets", "platform", platform, "arduino-cli", name));
+ }
+
private async tryResolveArduinoPath(): Promise {
// Query arduino path sequentially from the following places such as "vscode user settings", "system environment variables",
// "usual software installation directory for each os".
// 1. Search vscode user settings first.
const configValue = VscodeSettings.getInstance().arduinoPath;
if (!configValue || !configValue.trim()) {
- // 2 & 3. Resolve arduino path from system environment variables and usual software installation directory.
- this._arduinoPath = await Promise.resolve(resolveArduinoPath());
+ // 2. Resolve arduino path from the bundled arduino-cli, if CLI support is enabled.
+ const bundledPath = await this.bundledArduinoCliPath();
+ if (bundledPath && this._useArduinoCli && !this._commandPath) {
+ // The extension VSIX stripped the executable bit, so we need to set it.
+ // 0x755 means rwxr-xr-x (read and execute for everyone, write for owner).
+ await chmod(bundledPath, 0o755);
+ this._usingBundledArduinoCli = true;
+ Logger.traceUserData("using-bundled-arduino-cli");
+ this._arduinoPath = path.dirname(bundledPath);
+ this._commandPath = path.basename(bundledPath);
+ } else {
+ // 3 & 4. Resolve arduino path from system environment variables and usual software installation directory.
+ this._arduinoPath = await Promise.resolve(resolveArduinoPath());
+ }
} else {
this._arduinoPath = configValue;
}
diff --git a/src/arduino/vscodeSettings.ts b/src/arduino/vscodeSettings.ts
index ae2617d4..54d43dfb 100644
--- a/src/arduino/vscodeSettings.ts
+++ b/src/arduino/vscodeSettings.ts
@@ -42,6 +42,9 @@ export interface IVscodeSettings {
analyzeOnOpen: boolean;
analyzeOnSettingChange: boolean;
updateAdditionalUrls(urls: string[]): void;
+ setUseArduinoCli(value: boolean): Promise;
+ setArduinoPath(value: string): Promise;
+ setCommandPath(value: string): Promise;
}
export class VscodeSettings implements IVscodeSettings {
@@ -60,10 +63,18 @@ export class VscodeSettings implements IVscodeSettings {
return this.getConfigValue(configKeys.ARDUINO_PATH);
}
+ public setArduinoPath(value: string): Promise {
+ return this.setConfigValue(configKeys.ARDUINO_PATH, value, true);
+ }
+
public get commandPath(): string {
return this.getConfigValue(configKeys.ARDUINO_COMMAND_PATH);
}
+ public setCommandPath(value: string): Promise {
+ return this.setConfigValue(configKeys.ARDUINO_COMMAND_PATH, value, true);
+ }
+
public get additionalUrls(): string[] {
const value = this.getConfigValue(configKeys.ADDITIONAL_URLS);
@@ -116,6 +127,10 @@ export class VscodeSettings implements IVscodeSettings {
return this.getConfigValue(configKeys.USE_ARDUINO_CLI);
}
+ public setUseArduinoCli(value: boolean): Promise {
+ return this.setConfigValue(configKeys.USE_ARDUINO_CLI, value, true);
+ }
+
public get skipHeaderProvider(): boolean {
return this.getConfigValue(configKeys.SKIP_HEADER_PROVIDER);
}
diff --git a/src/arduinoActivator.ts b/src/arduinoActivator.ts
index a593a311..2758e52e 100644
--- a/src/arduinoActivator.ts
+++ b/src/arduinoActivator.ts
@@ -15,6 +15,7 @@ import ArduinoContext from "./arduinoContext";
import { DeviceContext } from "./deviceContext";
class ArduinoActivator {
+ public context: vscode.ExtensionContext;
private _initializePromise: Promise;
public async activate() {
if (this._initializePromise) {
@@ -23,7 +24,7 @@ class ArduinoActivator {
}
this._initializePromise = (async () => {
- const arduinoSettings = new ArduinoSettings();
+ const arduinoSettings = new ArduinoSettings(this.context);
await arduinoSettings.initialize();
const arduinoApp = new ArduinoApp(arduinoSettings);
diff --git a/src/common/constants.ts b/src/common/constants.ts
index c8a7de10..d3ed20b4 100644
--- a/src/common/constants.ts
+++ b/src/common/constants.ts
@@ -29,9 +29,10 @@ export const EXAMPLES_URI = vscode.Uri.parse("arduino-manager://arduino/arduino-
export const messages = {
ARDUINO_FILE_ERROR: "The arduino.json file format is not correct.",
NO_BOARD_SELECTED: "Please select the board type first.",
- INVALID_ARDUINO_PATH: "Cannot find Arduino IDE. Please specify the \"arduino.path\" in the User Settings. Requires a restart after change.",
- INVALID_COMMAND_PATH: "Please check the \"arduino.commandPath\" in the User Settings." +
-"Requires a restart after change.Cannot find the command file:",
+ INVALID_ARDUINO_PATH: "Cannot find Arduino tools.",
+ INVALID_COMMAND_PATH: "Cannot find the command file:",
+ SWITCH_TO_BUNDLED_CLI: "Use Arduino CLI bundled with this extension instead?",
+ REMOVE_ARDUINO_IDE_SUPPORT: "Support for the legacy Arduino IDE will be removed soon.",
FAILED_SEND_SERIALPORT: "Failed to send message to serial port.",
SERIAL_PORT_NOT_STARTED: "Serial Monitor has not been started.",
SEND_BEFORE_OPEN_SERIALPORT: "Please open a serial port first.",
diff --git a/src/common/util.ts b/src/common/util.ts
index c1ba5f26..eff20d34 100644
--- a/src/common/util.ts
+++ b/src/common/util.ts
@@ -468,3 +468,32 @@ export function toStringArray(value: string | string[]): string[] {
return [];
}
+
+// Ideally VS Code would provide an API to get the target platform name. For
+// now, copy the logic from VS Code.
+// https://github.com/microsoft/vscode/issues/170196
+// tslint:disable-next-line
+// https://github.com/microsoft/vscode/blob/78d05ca56a6881e7503a5173131c9803b059012d/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts#L171-L196
+export async function getPlatform(): Promise {
+ let platform: string = process.platform;
+ if (platform === "linux") {
+ let content: string | undefined;
+ try {
+ content = await fs.promises.readFile("/etc/os-release", "ascii");
+ } catch (error) {
+ try {
+ content = await fs.promises.readFile("/usr/lib/os-release", "ascii");
+ } catch (error) {
+ /* Ignore */
+ }
+ }
+ if (
+ !!content &&
+ // eslint-disable-next-line no-control-regex
+ (content.match(/^ID=([^\u001b\r\n]*)/m) || [])[1] === "alpine"
+ ) {
+ platform = "alpine";
+ }
+ }
+ return `${platform}-${process.arch}`;
+}
diff --git a/src/extension.ts b/src/extension.ts
index fdcf1ba9..fafbd7a1 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -33,6 +33,7 @@ const usbDetectorModule = impor("./serialmonitor/usbDetector") as typeof import
export async function activate(context: vscode.ExtensionContext) {
Logger.configure(context);
+ arduinoActivatorModule.default.context = context;
const activeGuid = uuidModule().replace(/-/g, "");
Logger.traceUserData("start-activate-extension", { correlationId: activeGuid });
// Show a warning message if the working file is not under the workspace folder.
@@ -78,6 +79,39 @@ export async function activate(context: vscode.ExtensionContext) {
nsatModule.NSAT.takeSurvey(context);
};
+
+ async function askSwitchToBundledCli(message: string): Promise {
+ const result = await vscode.window.showErrorMessage(
+ message, "Use bundled arduino-cli", "View settings");
+ switch (result) {
+ case "Use bundled arduino-cli": {
+ Logger.traceUserData("switched-to-bundled-arduino-cli");
+ await vscodeSettings.setUseArduinoCli(true);
+ await vscodeSettings.setArduinoPath(undefined);
+ await vscodeSettings.setCommandPath(undefined);
+ await vscode.commands.executeCommand("workbench.action.reloadWindow");
+ break;
+ }
+ case "View settings":
+ await vscode.commands.executeCommand("workbench.action.openGlobalSettings");
+ break;
+ }
+ }
+
+ if (!vscodeSettings.useArduinoCli) {
+ // This notification is intentionally a little bit annoying (popping on
+ // workspace open with no permanent dismissal) because we want to move
+ // users off of Arduino IDE.
+ //
+ // Unfortunately, we can't simply switch the default value of
+ // useArduinoCli to true because that would break users that were
+ // intentionally using the Arduino IDE but relied on the current default
+ // value of false. A future will make this breaking change with
+ // appropriate messaging.
+ Logger.traceUserData("using-legacy-arduino-ide");
+ void askSwitchToBundledCli(constants.messages.REMOVE_ARDUINO_IDE_SUPPORT + " " + constants.messages.SWITCH_TO_BUNDLED_CLI);
+ }
+
const registerArduinoCommand = (command: string, commandBody: (...args: any[]) => any, getUserData?: () => any): number => {
return context.subscriptions.push(vscode.commands.registerCommand(command, async (...args: any[]) => {
if (!arduinoContextModule.default.initialized) {
@@ -91,12 +125,20 @@ export async function activate(context: vscode.ExtensionContext) {
const arduinoPath = arduinoContextModule.default.arduinoApp.settings.arduinoPath;
const commandPath = arduinoContextModule.default.arduinoApp.settings.commandPath;
const useArduinoCli = arduinoContextModule.default.arduinoApp.settings.useArduinoCli;
- // Pop up vscode User Settings page when cannot resolve arduino path.
- if (!arduinoPath || !validateArduinoPath(arduinoPath, useArduinoCli)) {
- Logger.notifyUserError("InvalidArduinoPath", new Error(constants.messages.INVALID_ARDUINO_PATH));
- vscode.commands.executeCommand("workbench.action.openGlobalSettings");
+ const usingBundledArduinoCli = arduinoContextModule.default.arduinoApp.settings.usingBundledArduinoCli;
+
+ // Ask the user to switch to the bundled Arduino CLI if we can't resolve the specified path.
+ if (!usingBundledArduinoCli && (!arduinoPath || !validateArduinoPath(arduinoPath, useArduinoCli))) {
+ Logger.traceError("InvalidArduinoPath", new Error(constants.messages.INVALID_ARDUINO_PATH));
+ await askSwitchToBundledCli(constants.messages.INVALID_ARDUINO_PATH + " " + constants.messages.SWITCH_TO_BUNDLED_CLI);
} else if (!commandPath || !util.fileExistsSync(commandPath)) {
- Logger.notifyUserError("InvalidCommandPath", new Error(constants.messages.INVALID_COMMAND_PATH + commandPath));
+ const error = new Error(constants.messages.INVALID_COMMAND_PATH + commandPath);
+ if (usingBundledArduinoCli) {
+ Logger.notifyUserError("InvalidCommandPath", error);
+ } else {
+ Logger.traceError("InvalidCommandPath", error);
+ await askSwitchToBundledCli(error.message + " " + constants.messages.SWITCH_TO_BUNDLED_CLI);
+ }
} else {
await commandExecution(command, commandBody, args, getUserData);
}