Skip to content

Commit 45c003e

Browse files
authored
Add docker images auto check and setup support for WAMR-IDE (#1882)
1. Add docker images auto check and setup support for WAMR-IDE 2. Fix bug that the code goes on when user skips install
1 parent 5831663 commit 45c003e

File tree

5 files changed

+267
-53
lines changed

5 files changed

+267
-53
lines changed

test-tools/wamr-ide/VSCode-Extension/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
},
77
"displayName": "WAMR-IDE",
88
"description": "An Integrated Development Environment for WASM",
9-
"version": "1.0.0",
9+
"version": "1.1.2",
1010
"engines": {
1111
"vscode": "^1.59.0"
1212
},
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export const enum SelectionOfPrompt {
2+
skip = 'skip',
3+
setUp = 'setup',
4+
}
5+
export const enum Status {
6+
done = 'done',
7+
}

test-tools/wamr-ide/VSCode-Extension/src/extension.ts

Lines changed: 125 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ import {
2424
getWAMRExtensionVersion,
2525
} from './utilities/lldbUtilities';
2626

27+
import {
28+
checkIfDockerStarted,
29+
checkIfDockerImagesExist,
30+
promptSetupDockerImages,
31+
} from './utilities/dockerUtilities';
32+
import { SelectionOfPrompt } from './constants';
33+
2734
let wasmTaskProvider: WasmTaskProvider;
2835
let wasmDebugConfigProvider: WasmDebugConfigurationProvider;
2936
let currentPrjDir = '';
@@ -304,7 +311,7 @@ export async function activate(context: vscode.ExtensionContext) {
304311

305312
const disposableBuild = vscode.commands.registerCommand(
306313
'wamride.build',
307-
() => {
314+
async () => {
308315
if (!isWasmProject) {
309316
vscode.window.showErrorMessage('Build failed', {
310317
modal: true,
@@ -313,6 +320,28 @@ export async function activate(context: vscode.ExtensionContext) {
313320
return;
314321
}
315322

323+
try {
324+
/* check if docker images are ready before building */
325+
if (
326+
(await checkIfDockerStarted()) &&
327+
!(await checkIfDockerImagesExist(context))
328+
) {
329+
/**NOTE - if users select to skip install,
330+
* we should return rather than continue
331+
* the execution
332+
*/
333+
if (
334+
(await promptSetupDockerImages(context)) ===
335+
SelectionOfPrompt.skip
336+
) {
337+
return;
338+
}
339+
}
340+
} catch (e) {
341+
vscode.window.showWarningMessage((e as Error).message);
342+
return;
343+
}
344+
316345
generateCMakeFile(includePathArr, excludeFileArr);
317346
/* destroy the wasm-toolchain-ctr if it exists */
318347
vscode.commands
@@ -382,10 +411,35 @@ export async function activate(context: vscode.ExtensionContext) {
382411
/* we should check again whether the user installed lldb, as this can be skipped during activation */
383412
try {
384413
if (!isLLDBInstalled(context)) {
385-
await promptInstallLLDB(context);
414+
/**NOTE - if users select to skip install,
415+
* we should return rather than continue
416+
* the execution
417+
*/
418+
if (
419+
(await promptInstallLLDB(context)) ===
420+
SelectionOfPrompt.skip
421+
) {
422+
return;
423+
}
424+
}
425+
426+
if (
427+
(await checkIfDockerStarted()) &&
428+
!(await checkIfDockerImagesExist(context))
429+
) {
430+
/**NOTE - save as above lldb, should return if
431+
* users select to skip set up
432+
*/
433+
if (
434+
(await promptSetupDockerImages(context)) ===
435+
SelectionOfPrompt.skip
436+
) {
437+
return;
438+
}
386439
}
387440
} catch (e) {
388441
vscode.window.showWarningMessage((e as Error).message);
442+
return;
389443
}
390444

391445
/* refuse to debug if build process failed */
@@ -461,48 +515,70 @@ export async function activate(context: vscode.ExtensionContext) {
461515
}
462516
);
463517

464-
const disposableRun = vscode.commands.registerCommand('wamride.run', () => {
465-
if (!isWasmProject) {
466-
vscode.window.showErrorMessage('run failed', {
467-
modal: true,
468-
detail: 'Current project is not wasm project, please open wasm project and try again.',
469-
});
470-
return;
471-
}
518+
const disposableRun = vscode.commands.registerCommand(
519+
'wamride.run',
520+
async () => {
521+
if (!isWasmProject) {
522+
vscode.window.showErrorMessage('run failed', {
523+
modal: true,
524+
detail: 'Current project is not wasm project, please open wasm project and try again.',
525+
});
526+
return;
527+
}
472528

473-
/* refuse to debug if build process failed */
474-
if (!checkIfBuildSuccess()) {
475-
vscode.window.showErrorMessage('Debug failed', {
476-
modal: true,
477-
detail: 'Can not find WASM binary, please build WASM firstly.',
478-
});
479-
return;
480-
}
481-
vscode.commands
482-
.executeCommand(
483-
'workbench.action.tasks.runTask',
484-
'Destroy: Wasm-Container-Before-Run'
485-
)
486-
.then(() => {
487-
const disposableAft = vscode.tasks.onDidEndTaskProcess(e => {
488-
if (e.execution.task.name === 'Wasm-Container-Before-Run') {
489-
/* make sure that run wasm task will be executed after destroy task finish */
490-
vscode.commands
491-
.executeCommand(
492-
'workbench.action.tasks.runTask',
493-
'Run: Wasm'
494-
)
495-
.then(() => {
496-
if (e.exitCode !== 0) {
497-
disposableAft.dispose();
498-
return;
499-
}
500-
});
501-
disposableAft.dispose();
502-
}
529+
try {
530+
/* check if docker images are set up before building */
531+
if (
532+
(await checkIfDockerStarted()) &&
533+
!(await checkIfDockerImagesExist(context))
534+
) {
535+
await promptSetupDockerImages(context);
536+
}
537+
} catch (e) {
538+
vscode.window.showWarningMessage((e as Error).message);
539+
return;
540+
}
541+
542+
/* refuse to debug if build process failed */
543+
if (!checkIfBuildSuccess()) {
544+
vscode.window.showErrorMessage('Debug failed', {
545+
modal: true,
546+
detail: 'Can not find WASM binary, please build WASM firstly.',
503547
});
504-
});
505-
});
548+
return;
549+
}
550+
551+
vscode.commands
552+
.executeCommand(
553+
'workbench.action.tasks.runTask',
554+
'Destroy: Wasm-Container-Before-Run'
555+
)
556+
.then(() => {
557+
const disposableAft = vscode.tasks.onDidEndTaskProcess(
558+
e => {
559+
if (
560+
e.execution.task.name ===
561+
'Wasm-Container-Before-Run'
562+
) {
563+
/* make sure that run wasm task will be executed when destroy task finish */
564+
vscode.commands
565+
.executeCommand(
566+
'workbench.action.tasks.runTask',
567+
'Run: Wasm'
568+
)
569+
.then(() => {
570+
if (e.exitCode !== 0) {
571+
disposableAft.dispose();
572+
return;
573+
}
574+
});
575+
disposableAft.dispose();
576+
}
577+
}
578+
);
579+
});
580+
}
581+
);
506582

507583
const disposableToggleIncludePath = vscode.commands.registerCommand(
508584
'wamride.build.toggleStateIncludePath',
@@ -700,6 +776,13 @@ export async function activate(context: vscode.ExtensionContext) {
700776
if (!isLLDBInstalled(context)) {
701777
await promptInstallLLDB(context);
702778
}
779+
780+
if (
781+
(await checkIfDockerStarted()) &&
782+
!(await checkIfDockerImagesExist(context))
783+
) {
784+
await promptSetupDockerImages(context);
785+
}
703786
} catch (e) {
704787
vscode.window.showWarningMessage((e as Error).message);
705788
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* Copyright (C) 2019 Intel Corporation. All rights reserved.
3+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4+
*/
5+
6+
import * as vscode from 'vscode';
7+
import * as cp from 'child_process';
8+
import * as path from 'path';
9+
import * as fs from 'fs';
10+
import { getWAMRExtensionVersion } from './lldbUtilities';
11+
import { downloadFile, unzipFile } from './directoryUtilities';
12+
import { SelectionOfPrompt, Status } from '../constants';
13+
14+
const DOCKER_IMAGES_TEM_FOLDER_NAME = 'docker-resource';
15+
16+
type SelectionStatus = SelectionOfPrompt | Status;
17+
18+
const execShell = (cmd: string) =>
19+
new Promise<string>((resolve, reject) => {
20+
cp.exec(cmd, (error, result) => {
21+
if (error) {
22+
return reject(error);
23+
}
24+
return resolve(result);
25+
});
26+
});
27+
28+
export async function promptSetupDockerImages(
29+
context: vscode.ExtensionContext
30+
): Promise<SelectionStatus> {
31+
const extensionPath = context.extensionPath;
32+
const response = await vscode.window.showWarningMessage(
33+
'Necessary docker images are not found. Setup now?',
34+
SelectionOfPrompt.setUp,
35+
SelectionOfPrompt.skip
36+
);
37+
38+
if (response === SelectionOfPrompt.skip) {
39+
return response;
40+
}
41+
42+
const downloadUrlArray = getDockerImagesDownloadUrl(context);
43+
44+
const destinationFolder = path.resolve(
45+
extensionPath,
46+
'resource',
47+
DOCKER_IMAGES_TEM_FOLDER_NAME
48+
);
49+
50+
if (!fs.existsSync(destinationFolder)) {
51+
fs.mkdirSync(destinationFolder);
52+
}
53+
54+
vscode.window.showInformationMessage(`Downloading Docker Images...`);
55+
56+
for (const url of downloadUrlArray) {
57+
const imageZipName = path.basename(url);
58+
const imageStorePath = path.join(destinationFolder, imageZipName);
59+
await downloadFile(url, imageStorePath);
60+
61+
/**
62+
* extract docker image tar package to
63+
* '${destinationFolder}'
64+
*/
65+
const dockerImageFile = await unzipFile(imageStorePath, filename =>
66+
path.join(destinationFolder, filename)
67+
);
68+
/* give access before loading */
69+
dockerImageFile.forEach(file => fs.chmodSync(file, '0775'));
70+
71+
/**NOTE - load docker image tar package to host
72+
* right now there are just one file
73+
* `docker-image-name.tar` inside so we can
74+
* directly use files[0] here, should be modified
75+
* if the package's files change
76+
*/
77+
await execShell(`docker load -i ${dockerImageFile[0]}`);
78+
}
79+
80+
/* remove the DOCKER_IMAGES_TEM_FOLDER */
81+
fs.rmSync(destinationFolder, { recursive: true, force: true });
82+
83+
vscode.window.showInformationMessage(
84+
`Docker images are ready, please run '$docker images' to check.`
85+
);
86+
87+
return Status.done;
88+
}
89+
90+
export async function checkIfDockerStarted(): Promise<boolean> {
91+
try {
92+
await execShell('docker images');
93+
return true;
94+
} catch (e) {
95+
vscode.window.showWarningMessage((e as Error).message);
96+
return false;
97+
}
98+
}
99+
100+
export async function checkIfDockerImagesExist(
101+
context: vscode.ExtensionContext
102+
): Promise<boolean> {
103+
try {
104+
/* the tag of images is equal to extension's version */
105+
const imageTag = getWAMRExtensionVersion(context);
106+
await execShell(
107+
`docker image inspect wasm-debug-server:${imageTag} wasm-toolchain:${imageTag}`
108+
);
109+
return true;
110+
} catch (e) {
111+
return false;
112+
}
113+
}
114+
115+
function getDockerImagesDownloadUrl(
116+
context: vscode.ExtensionContext
117+
): string[] {
118+
const wamrVersion = getWAMRExtensionVersion(context);
119+
const wamrReleaseUrl = `https://github.com/bytecodealliance/wasm-micro-runtime/releases/download/WAMR`;
120+
121+
return [
122+
`${wamrReleaseUrl}-${wamrVersion}/wasm-debug-server-${wamrVersion}.zip`,
123+
`${wamrReleaseUrl}-${wamrVersion}/wasm-toolchain-${wamrVersion}.zip`,
124+
];
125+
}

test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
downloadFile,
1313
unzipFile,
1414
} from './directoryUtilities';
15+
import { SelectionOfPrompt, Status } from '../constants';
1516

1617
const LLDB_RESOURCE_DIR = 'resource/debug';
1718
const LLDB_OS_DOWNLOAD_URL_SUFFIX_MAP: Partial<
@@ -67,18 +68,17 @@ export function isLLDBInstalled(context: vscode.ExtensionContext): boolean {
6768

6869
export async function promptInstallLLDB(
6970
context: vscode.ExtensionContext
70-
): Promise<void> {
71+
): Promise<SelectionOfPrompt> {
7172
const extensionPath = context.extensionPath;
72-
const setupPrompt = 'setup';
73-
const skipPrompt = 'skip';
73+
7474
const response = await vscode.window.showWarningMessage(
7575
'No LLDB instance found. Setup now?',
76-
setupPrompt,
77-
skipPrompt
76+
SelectionOfPrompt.setUp,
77+
SelectionOfPrompt.skip
7878
);
7979

80-
if (response === skipPrompt) {
81-
return;
80+
if (response === SelectionOfPrompt.skip) {
81+
return response;
8282
}
8383

8484
const downloadUrl = getLLDBDownloadUrl(context);
@@ -114,7 +114,6 @@ export async function promptInstallLLDB(
114114
);
115115

116116
// Remove the bundle.zip
117-
fs.unlink(lldbZipPath, () => {
118-
return;
119-
});
117+
fs.unlinkSync(lldbZipPath);
118+
return SelectionOfPrompt.setUp;
120119
}

0 commit comments

Comments
 (0)