Skip to content
This repository was archived by the owner on Oct 1, 2024. It is now read-only.

Commit 2af8f11

Browse files
elektronikworkshopadiazulay
authored andcommitted
Pre-/post-build command improvements
* Full bash syntax support for pre-/post-build commands on UNIX systems * Environment variables for pre-/post-build commands which give the user access to several build process parameters like the sketch, the output directory, serial port, build mode (verify, upload, analyze, ...), board type and workspace path Addresses #786
1 parent d3bcf6e commit 2af8f11

File tree

2 files changed

+46
-19
lines changed

2 files changed

+46
-19
lines changed

src/arduino/arduino.ts

+42-15
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,7 @@ export class ArduinoApp {
133133
public async setPref(key, value) {
134134
try {
135135
await util.spawn(this._settings.commandPath,
136-
null,
137-
["--pref", `${key}=${value}`, "--save-prefs"]);
136+
["--pref", `${key}=${value}`, "--save-prefs"]);
138137
} catch (ex) {
139138
}
140139
}
@@ -331,30 +330,45 @@ export class ArduinoApp {
331330
arduinoChannel.start(`${buildMode} sketch '${dc.sketch}'`);
332331

333332
if ((buildDir || dc.output) && compile) {
334-
const outputPath = path.resolve(ArduinoWorkspace.rootPath, buildDir || dc.output);
335-
const dirPath = path.dirname(outputPath);
333+
buildDir = path.resolve(ArduinoWorkspace.rootPath, buildDir || dc.output);
334+
const dirPath = path.dirname(buildDir);
336335
if (!util.directoryExistsSync(dirPath)) {
337-
logger.notifyUserError("InvalidOutPutPath", new Error(constants.messages.INVALID_OUTPUT_PATH + outputPath));
336+
logger.notifyUserError("InvalidOutPutPath", new Error(constants.messages.INVALID_OUTPUT_PATH + buildDir));
338337
return false;
339338
}
340339

341340
if (this.useArduinoCli()) {
342-
args.push("--build-path", outputPath);
341+
args.push("--build-path", buildDir);
343342

344343
} else {
345-
args.push("--pref", `build.path=${outputPath}`);
344+
args.push("--pref", `build.path=${buildDir}`);
346345
}
347346

348-
arduinoChannel.info(`Please see the build logs in output path: ${outputPath}`);
347+
arduinoChannel.info(`Please see the build logs in output path: ${buildDir}`);
349348
} else {
350349
const msg = "Output path is not specified. Unable to reuse previously compiled files. Build will be slower. See README.";
351350
arduinoChannel.warning(msg);
352351
}
353352

353+
// Environment variables passed to pre- and post-build commands
354+
const env = {
355+
VSCA_BUILD_MODE: buildMode,
356+
VSCA_SKETCH: dc.sketch,
357+
VSCA_BOARD: boardDescriptor,
358+
VSCA_WORKSPACE_DIR: ArduinoWorkspace.rootPath,
359+
VSCA_LOG_LEVEL: verbose ? constants.LogLevel.Verbose : constants.LogLevel.Info,
360+
};
361+
if (dc.port) {
362+
env["VSCA_SERIAL"] = dc.port;
363+
}
364+
if (buildDir) {
365+
env["VSCA_BUILD_DIR"] = buildDir;
366+
}
367+
354368
// TODO EW: What should we do with pre-/post build commands when running
355369
// analysis? Some could use it to generate/manipulate code which could
356370
// be a prerequisite for a successful build
357-
if (!await this.runPrePostBuildCommand(dc, "pre")) {
371+
if (!await this.runPrePostBuildCommand(dc, env, "pre")) {
358372
return false;
359373
}
360374

@@ -370,7 +384,7 @@ export class ArduinoApp {
370384
const cleanup = async (result: "ok" | "error") => {
371385
let ret = true;
372386
if (result === "ok") {
373-
ret = await this.runPrePostBuildCommand(dc, "post");
387+
ret = await this.runPrePostBuildCommand(dc, env, "post");
374388
}
375389
await cocopa.conclude();
376390
if (buildMode === BuildMode.Upload || buildMode === BuildMode.UploadProgrammer) {
@@ -689,21 +703,34 @@ export class ArduinoApp {
689703
* @returns True if successful, false on error.
690704
*/
691705
protected async runPrePostBuildCommand(dc: DeviceContext,
706+
environment: any,
692707
what: "pre" | "post"): Promise<boolean> {
693708
const cmdline = what === "pre"
694709
? dc.prebuild
695710
: dc.postbuild;
696711

697712
if (cmdline) {
698713
arduinoChannel.info(`Running ${what}-build command: "${cmdline}"`);
699-
// TODO 2020-02-27, EW: We could call bash -c "cmd" here at least for
700-
// UNIX systems. Windows users must live with their poor system :)
701-
const args = cmdline.split(/\s+/);
702-
const cmd = args.shift();
714+
let cmd: string;
715+
let args: string[];
716+
// pre-/post-build commands feature full bash support on UNIX systems.
717+
// Windows users must live with their poor system unless someone is
718+
// willing to fight with the annoying Windows cmd escaping -- good luck!
719+
if (os.platform() === "win32") {
720+
args = cmdline.split(/\s+/);
721+
cmd = args.shift();
722+
} else {
723+
args = ["-c", cmdline];
724+
cmd = "bash";
725+
}
703726
try {
704727
await util.spawn(cmd,
705728
args,
706-
{ shell: true, cwd: ArduinoWorkspace.rootPath },
729+
{
730+
shell: os.platform() === "win32",
731+
cwd: ArduinoWorkspace.rootPath,
732+
env: {...environment},
733+
},
707734
{ channel: arduinoChannel.channel });
708735
} catch (ex) {
709736
const msg = ex.error

src/common/util.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

4-
import * as childProcess from "child_process";
4+
import * as child_process from "child_process";
55
import * as fs from "fs";
66
import * as iconv from "iconv-lite";
77
import * as os from "os";
@@ -196,19 +196,19 @@ export function isArduinoFile(filePath): boolean {
196196
export function spawn(
197197
command: string,
198198
args: string[] = [],
199-
options: any = {},
199+
options: child_process.SpawnOptions = {},
200200
output?: {channel?: vscode.OutputChannel,
201201
stdout?: (s: string) => void,
202202
stderr?: (s: string) => void},
203203
): Thenable<object> {
204204
return new Promise((resolve, reject) => {
205205
options.cwd = options.cwd || path.resolve(path.join(__dirname, ".."));
206-
const child = childProcess.spawn(command, args, options);
206+
const child = child_process.spawn(command, args, options);
207207

208208
let codepage = "65001";
209209
if (os.platform() === "win32") {
210210
try {
211-
const chcp = childProcess.execSync("chcp.com");
211+
const chcp = child_process.execSync("chcp.com");
212212
codepage = chcp.toString().split(":").pop().trim();
213213
} catch (error) {
214214
arduinoChannel.warning(`Defaulting to code page 850 because chcp.com failed.\

0 commit comments

Comments
 (0)