Implement WAMR-IDE with vscode extension (#943)
Implement WAMR-IDE with vscode extension to enable developing WebAssembly applications with coding, building, running and debugging support. Support both Linux and Windows, and only support putting all the tools in a docker image, e.g. wasi-sdk, wamrc, iwasm and so on. Co-authored-by: Wang Ning <justdoitwn@163.com>
This commit is contained in:
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as os from 'os';
|
||||
|
||||
export class WasmDebugConfigurationProvider
|
||||
implements vscode.DebugConfigurationProvider {
|
||||
constructor() {}
|
||||
|
||||
/* default port set as 1234 */
|
||||
private port = 1234;
|
||||
private hostPath!: string;
|
||||
private providerPromise:
|
||||
| Thenable<vscode.DebugConfiguration>
|
||||
| undefined = undefined;
|
||||
|
||||
private wasmDebugConfig!: vscode.DebugConfiguration;
|
||||
|
||||
public resolveDebugConfiguration():
|
||||
| Thenable<vscode.DebugConfiguration>
|
||||
| undefined {
|
||||
if (!this.providerPromise) {
|
||||
this.providerPromise = Promise.resolve(this.wasmDebugConfig);
|
||||
return this.providerPromise;
|
||||
}
|
||||
return this.providerPromise;
|
||||
}
|
||||
|
||||
public setDebugConfig(hostPath: string, port: number) {
|
||||
this.port = port;
|
||||
this.hostPath = hostPath;
|
||||
/* linux and windows has different debug configuration */
|
||||
if (os.platform() === 'win32') {
|
||||
this.wasmDebugConfig = {
|
||||
type: 'wamr-debug',
|
||||
name: 'Attach',
|
||||
request: 'attach',
|
||||
['stopOnEntry']: true,
|
||||
['initCommands']: ['platform select remote-linux'],
|
||||
['attachCommands']: [
|
||||
'process connect -p wasm connect://127.0.0.1:' + port + '',
|
||||
],
|
||||
['sourceMap']: [['/mnt', hostPath]],
|
||||
};
|
||||
} else if (os.platform() === 'linux') {
|
||||
this.wasmDebugConfig = {
|
||||
type: 'wamr-debug',
|
||||
name: 'Attach',
|
||||
request: 'attach',
|
||||
['stopOnEntry']: true,
|
||||
['attachCommands']: [
|
||||
'process connect -p wasm connect://127.0.0.1:' + port + '',
|
||||
],
|
||||
['sourceMap']: [['/mnt', hostPath]],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public getDebugConfig() {
|
||||
return this.wasmDebugConfig;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { ReadFromFile } from '../utilities/directoryUtilities';
|
||||
import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
|
||||
const DECORATION_INCLUDE_PATHS: vscode.FileDecoration =
|
||||
new vscode.FileDecoration(
|
||||
'✔',
|
||||
'Included',
|
||||
new vscode.ThemeColor('list.highlightForeground')
|
||||
);
|
||||
const DECORATION_EXCLUDE_FILES: vscode.FileDecoration =
|
||||
new vscode.FileDecoration(
|
||||
'✗',
|
||||
'Excluded',
|
||||
new vscode.ThemeColor('list.errorForeground')
|
||||
);
|
||||
|
||||
export class DecorationProvider implements vscode.FileDecorationProvider {
|
||||
private disposables: vscode.Disposable[] = [];
|
||||
public onDidChangeFileDecorations: vscode.Event<
|
||||
vscode.Uri | vscode.Uri[] | undefined
|
||||
>;
|
||||
private _eventEmiter: vscode.EventEmitter<vscode.Uri | vscode.Uri[]>;
|
||||
|
||||
constructor() {
|
||||
this._eventEmiter = new vscode.EventEmitter();
|
||||
this.onDidChangeFileDecorations = this._eventEmiter.event;
|
||||
this.disposables.push(
|
||||
vscode.window.registerFileDecorationProvider(this)
|
||||
);
|
||||
}
|
||||
|
||||
public provideFileDecoration(
|
||||
uri: vscode.Uri
|
||||
): vscode.ProviderResult<vscode.FileDecoration> {
|
||||
let currentPrjDir,
|
||||
prjConfigDir,
|
||||
configFilePath,
|
||||
configData,
|
||||
includePathArr = new Array(),
|
||||
excludeFileArr = new Array(),
|
||||
pathRelative;
|
||||
|
||||
/* Read include_paths and exclude_fils from the config file */
|
||||
currentPrjDir =
|
||||
os.platform() === 'win32'
|
||||
? (vscode.workspace.workspaceFolders?.[0].uri.fsPath as string)
|
||||
: os.platform() === 'linux'
|
||||
? (currentPrjDir = vscode.workspace.workspaceFolders?.[0].uri
|
||||
.path as string)
|
||||
: '';
|
||||
|
||||
pathRelative = (uri.fsPath ? uri.fsPath : uri.toString()).replace(
|
||||
currentPrjDir,
|
||||
'..'
|
||||
);
|
||||
|
||||
prjConfigDir = path.join(currentPrjDir, '.wamr');
|
||||
configFilePath = path.join(prjConfigDir, 'compilation_config.json');
|
||||
if (ReadFromFile(configFilePath) !== '') {
|
||||
configData = JSON.parse(ReadFromFile(configFilePath));
|
||||
includePathArr = configData['include_paths'];
|
||||
excludeFileArr = configData['exclude_files'];
|
||||
|
||||
if (includePathArr.indexOf(pathRelative) > -1) {
|
||||
return DECORATION_INCLUDE_PATHS;
|
||||
} else if (excludeFileArr.indexOf(pathRelative) > -1) {
|
||||
return DECORATION_EXCLUDE_FILES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.disposables.forEach(d => d.dispose());
|
||||
}
|
||||
|
||||
public updateDecorationsForSource(uri: vscode.Uri): void {
|
||||
this._eventEmiter.fire(uri);
|
||||
}
|
||||
}
|
||||
|
||||
export const decorationProvider: DecorationProvider = new DecorationProvider();
|
||||
597
test-tools/wamr-ide/VSCode-Extension/src/extension.ts
Normal file
597
test-tools/wamr-ide/VSCode-Extension/src/extension.ts
Normal file
@ -0,0 +1,597 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
import * as fileSystem from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import { WasmTaskProvider } from './taskProvider';
|
||||
import { TargetConfigPanel } from './view/TargetConfigPanel';
|
||||
import { NewProjectPanel } from './view/NewProjectPanel';
|
||||
import {
|
||||
WriteIntoFile,
|
||||
ReadFromFile,
|
||||
WriteIntoFileAsync,
|
||||
} from './utilities/directoryUtilities';
|
||||
import { decorationProvider } from './explorer/decorationProvider';
|
||||
|
||||
import { WasmDebugConfigurationProvider } from './debug/debugConfigurationProvider';
|
||||
|
||||
let wasmTaskProvider: WasmTaskProvider;
|
||||
let wasmDebugConfigProvider: WasmDebugConfigurationProvider;
|
||||
var currentPrjDir = '';
|
||||
var extensionPath = '';
|
||||
|
||||
export async function activate(context: vscode.ExtensionContext) {
|
||||
var OS_PLATFORM = '',
|
||||
buildScript = '',
|
||||
runScript = '',
|
||||
debugScript = '',
|
||||
buildScriptFullPath = '',
|
||||
runScriptFullPath = '',
|
||||
debugScriptFullPath = '',
|
||||
typeMap = new Map(),
|
||||
/* include paths array used for written into config file */
|
||||
includePathArr = new Array(),
|
||||
/* exclude files array used for written into config file */
|
||||
excludeFileArr = new Array(),
|
||||
scriptMap = new Map();
|
||||
|
||||
/**
|
||||
* Get OS platform information for differ windows and linux execution script
|
||||
*/
|
||||
OS_PLATFORM = os.platform();
|
||||
|
||||
/**
|
||||
* Provide Build & Run Task with Task Provider instead of "tasks.json"
|
||||
*/
|
||||
|
||||
/* set relative path of build.bat|sh script */
|
||||
let scriptPrefix = 'resource/scripts/';
|
||||
if (OS_PLATFORM === 'win32') {
|
||||
buildScript = scriptPrefix.concat('build.bat');
|
||||
runScript = scriptPrefix.concat('run.bat');
|
||||
debugScript = scriptPrefix.concat('boot_debugger_server.bat');
|
||||
} else if (OS_PLATFORM === 'linux') {
|
||||
buildScript = scriptPrefix.concat('build.sh');
|
||||
runScript = scriptPrefix.concat('run.sh');
|
||||
debugScript = scriptPrefix.concat('boot_debugger_server.sh');
|
||||
}
|
||||
|
||||
/* get extension's path, and set scripts' absolute path */
|
||||
extensionPath = context.extensionPath;
|
||||
|
||||
buildScriptFullPath = path.join(extensionPath, buildScript);
|
||||
runScriptFullPath = path.join(extensionPath, runScript);
|
||||
debugScriptFullPath = path.join(extensionPath, debugScript);
|
||||
|
||||
scriptMap.set('buildScript', buildScriptFullPath);
|
||||
scriptMap.set('runScript', runScriptFullPath);
|
||||
scriptMap.set('debugScript', debugScriptFullPath);
|
||||
|
||||
typeMap.set('Build', 'Build');
|
||||
typeMap.set('Run', 'Run');
|
||||
typeMap.set('Debug', 'Debug');
|
||||
|
||||
wasmTaskProvider = new WasmTaskProvider(typeMap, scriptMap);
|
||||
|
||||
vscode.tasks.registerTaskProvider('wasm', wasmTaskProvider);
|
||||
|
||||
/* set current project directory */
|
||||
if (vscode.workspace.workspaceFolders?.[0]) {
|
||||
if (OS_PLATFORM === 'win32') {
|
||||
currentPrjDir = vscode.workspace.workspaceFolders?.[0].uri
|
||||
.fsPath as string;
|
||||
} else if (OS_PLATFORM === 'linux') {
|
||||
currentPrjDir = vscode.workspace.workspaceFolders?.[0].uri
|
||||
.path as string;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* check whether current project opened in vscode workspace is wasm project
|
||||
* it not, `build`, `run` and `debug` will be disabled
|
||||
*/
|
||||
if (currentPrjDir !== '') {
|
||||
let wamrFolder = fileSystem
|
||||
.readdirSync(currentPrjDir, {
|
||||
withFileTypes: true,
|
||||
})
|
||||
.filter(folder => folder.isDirectory() && folder.name === '.wamr');
|
||||
|
||||
if (wamrFolder.length !== 0) {
|
||||
vscode.commands.executeCommand(
|
||||
'setContext',
|
||||
'ext.isWasmProject',
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* register debug configuration */
|
||||
wasmDebugConfigProvider = new WasmDebugConfigurationProvider();
|
||||
wasmDebugConfigProvider.setDebugConfig(currentPrjDir, 1234);
|
||||
|
||||
vscode.debug.registerDebugConfigurationProvider(
|
||||
'wamr-debug',
|
||||
wasmDebugConfigProvider
|
||||
);
|
||||
|
||||
/* update ext.includePaths to show or hide 'Remove' button in menus */
|
||||
vscode.commands.executeCommand('setContext', 'ext.supportedFileType', [
|
||||
'.c',
|
||||
'.cpp',
|
||||
'.cxx',
|
||||
]);
|
||||
|
||||
if (readFromConfigFile() !== '') {
|
||||
let configData = JSON.parse(readFromConfigFile());
|
||||
includePathArr = configData['include_paths'];
|
||||
excludeFileArr = configData['exclude_files'];
|
||||
|
||||
if (Object.keys(configData['build_args']).length !== 0) {
|
||||
TargetConfigPanel.BUILD_ARGS = configData['build_args'];
|
||||
}
|
||||
}
|
||||
|
||||
let disposableNewProj = vscode.commands.registerCommand(
|
||||
'wamride.newProject',
|
||||
() => {
|
||||
let _ok = 'Set up now';
|
||||
let _cancle = 'Maybe later';
|
||||
let curWorkspace = vscode.workspace
|
||||
.getConfiguration()
|
||||
.get('WAMR-IDE.configWorkspace');
|
||||
|
||||
/* if user has not set up workspace yet, prompt to set up */
|
||||
if (curWorkspace === '' || curWorkspace === undefined) {
|
||||
vscode.window
|
||||
.showWarningMessage(
|
||||
'Please setup your workspace firstly.',
|
||||
_ok,
|
||||
_cancle
|
||||
)
|
||||
.then(item => {
|
||||
if (item === _ok) {
|
||||
vscode.commands.executeCommand(
|
||||
'wamride.changeWorkspace'
|
||||
);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
NewProjectPanel.render(context);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let disposableTargetConfig = vscode.commands.registerCommand(
|
||||
'wamride.targetConfig',
|
||||
() => {
|
||||
if (currentPrjDir !== '') {
|
||||
TargetConfigPanel.render(context);
|
||||
} else {
|
||||
vscode.window.showWarningMessage(
|
||||
'Please create and open project firstly.',
|
||||
'OK'
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let disposableChangeWorkspace = vscode.commands.registerCommand(
|
||||
'wamride.changeWorkspace',
|
||||
async () => {
|
||||
let options: vscode.OpenDialogOptions = {
|
||||
canSelectFiles: false,
|
||||
canSelectFolders: true,
|
||||
openLabel: 'Select Workspace',
|
||||
};
|
||||
|
||||
let Workspace = await vscode.window
|
||||
.showOpenDialog(options)
|
||||
.then(res => {
|
||||
if (res) {
|
||||
return res[0].fsPath as string;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
/* update workspace value to vscode global settings */
|
||||
await vscode.workspace
|
||||
.getConfiguration()
|
||||
.update(
|
||||
'WAMR-IDE.configWorkspace',
|
||||
Workspace.trim(),
|
||||
vscode.ConfigurationTarget.Global
|
||||
)
|
||||
.then(
|
||||
success => {
|
||||
vscode.window.showInformationMessage(
|
||||
'Workspace has been set up successfully!'
|
||||
);
|
||||
},
|
||||
error => {
|
||||
vscode.window.showErrorMessage(
|
||||
'Set up Workspace failed!'
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
let disposableBuild = vscode.commands.registerCommand(
|
||||
'wamride.build',
|
||||
() => {
|
||||
generateCMakeFile(includePathArr, excludeFileArr);
|
||||
|
||||
return vscode.commands.executeCommand(
|
||||
'workbench.action.tasks.runTask',
|
||||
'Build: Wasm'
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
let disposableDebug = vscode.commands.registerCommand(
|
||||
'wamride.debug',
|
||||
() => {
|
||||
vscode.commands
|
||||
.executeCommand('workbench.action.tasks.runTask', 'Debug: Wasm')
|
||||
.then(() => {
|
||||
vscode.debug.startDebugging(
|
||||
undefined,
|
||||
wasmDebugConfigProvider.getDebugConfig()
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
let disposableRun = vscode.commands.registerCommand('wamride.run', () => {
|
||||
return vscode.commands.executeCommand(
|
||||
'workbench.action.tasks.runTask',
|
||||
'Run: Wasm'
|
||||
);
|
||||
});
|
||||
|
||||
let disposableToggleIncludePath = vscode.commands.registerCommand(
|
||||
'wamride.build.toggleStateIncludePath',
|
||||
fileUri => {
|
||||
let pathRelative: string;
|
||||
let path =
|
||||
fileUri._fsPath !== null && fileUri._fsPath !== undefined
|
||||
? fileUri._fsPath
|
||||
: vscode.Uri.parse(fileUri.path as string).fsPath;
|
||||
pathRelative = path.replace(currentPrjDir, '..');
|
||||
|
||||
if (includePathArr.indexOf(pathRelative) > -1) {
|
||||
/* this folder has been added to include path, remove it */
|
||||
includePathArr = includePathArr.filter(value => {
|
||||
return value !== pathRelative;
|
||||
});
|
||||
} else {
|
||||
includePathArr.push(pathRelative);
|
||||
}
|
||||
|
||||
writeIntoConfigFile(
|
||||
includePathArr,
|
||||
excludeFileArr,
|
||||
TargetConfigPanel.BUILD_ARGS
|
||||
);
|
||||
|
||||
decorationProvider.updateDecorationsForSource(fileUri);
|
||||
}
|
||||
);
|
||||
|
||||
let disposableToggleExcludeFile = vscode.commands.registerCommand(
|
||||
'wamride.build.toggleStateExclude',
|
||||
fileUri => {
|
||||
let pathRelative: string;
|
||||
|
||||
let path =
|
||||
fileUri._fsPath !== null && fileUri._fsPath !== undefined
|
||||
? fileUri._fsPath
|
||||
: vscode.Uri.parse(fileUri.path as string).fsPath;
|
||||
|
||||
/* replace the current project absolute path with .. to change to relative path */
|
||||
pathRelative = path.replace(currentPrjDir, '..');
|
||||
|
||||
if (excludeFileArr.indexOf(pathRelative) > -1) {
|
||||
excludeFileArr = excludeFileArr.filter(val => {
|
||||
return val !== pathRelative;
|
||||
});
|
||||
} else {
|
||||
excludeFileArr.push(pathRelative);
|
||||
}
|
||||
|
||||
writeIntoConfigFile(
|
||||
includePathArr,
|
||||
excludeFileArr,
|
||||
TargetConfigPanel.BUILD_ARGS
|
||||
);
|
||||
|
||||
/* update decoration for this source file */
|
||||
decorationProvider.updateDecorationsForSource(fileUri);
|
||||
}
|
||||
);
|
||||
|
||||
let disposableOpenFolder = vscode.commands.registerCommand(
|
||||
'wamride.openFolder',
|
||||
() => {
|
||||
let _ok = 'Set up now';
|
||||
let _cancle = 'Maybe later';
|
||||
let curWorkspace = vscode.workspace
|
||||
.getConfiguration()
|
||||
.get('WAMR-IDE.configWorkspace') as string;
|
||||
|
||||
/* if user has not set up workspace yet, prompt to set up */
|
||||
if (curWorkspace === '' || curWorkspace === undefined) {
|
||||
vscode.window
|
||||
.showWarningMessage(
|
||||
'Please setup your workspace firstly.',
|
||||
_ok,
|
||||
_cancle
|
||||
)
|
||||
.then(item => {
|
||||
if (item === _ok) {
|
||||
vscode.commands.executeCommand(
|
||||
'wamride.changeWorkspace'
|
||||
);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
/* get all directories within directory, ignore files */
|
||||
let directoryArrDirent, directoryArr;
|
||||
try {
|
||||
directoryArrDirent = fileSystem.readdirSync(curWorkspace, {
|
||||
withFileTypes: true,
|
||||
});
|
||||
} catch (err) {
|
||||
vscode.window.showErrorMessage(
|
||||
'Read from current workspace failed, please check.'
|
||||
);
|
||||
}
|
||||
|
||||
if (directoryArrDirent !== undefined) {
|
||||
directoryArr = directoryArrDirent
|
||||
.filter(dirent => dirent.isDirectory())
|
||||
.map(dirent => dirent.name);
|
||||
|
||||
vscode.window
|
||||
.showQuickPick(directoryArr, {
|
||||
title: 'Select project',
|
||||
placeHolder: 'Please select project',
|
||||
})
|
||||
.then(option => {
|
||||
if (!option) {
|
||||
return;
|
||||
}
|
||||
|
||||
let _path = curWorkspace.concat(
|
||||
OS_PLATFORM === 'win32'
|
||||
? '\\'
|
||||
: OS_PLATFORM === 'linux'
|
||||
? '/'
|
||||
: '',
|
||||
option
|
||||
);
|
||||
|
||||
openWindoWithSituation(vscode.Uri.file(_path));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
context.subscriptions.push(
|
||||
disposableNewProj,
|
||||
disposableTargetConfig,
|
||||
disposableChangeWorkspace,
|
||||
disposableBuild,
|
||||
disposableRun,
|
||||
disposableToggleIncludePath,
|
||||
disposableOpenFolder,
|
||||
disposableToggleExcludeFile,
|
||||
disposableDebug
|
||||
);
|
||||
}
|
||||
|
||||
function openWindoWithSituation(uri: vscode.Uri) {
|
||||
/**
|
||||
* check if the workspace folder is empty,
|
||||
* if yes, open new window, else open in current window
|
||||
*/
|
||||
let isWorkspaceEmpty: boolean;
|
||||
isWorkspaceEmpty = !vscode.workspace.workspaceFolders?.[0] ? true : false;
|
||||
|
||||
isWorkspaceEmpty === false
|
||||
? vscode.commands.executeCommand('vscode.openFolder', uri, {
|
||||
forceNewWindow: true,
|
||||
})
|
||||
: vscode.commands.executeCommand('vscode.openFolder', uri);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
interface BuildArgs {
|
||||
output_file_name: string;
|
||||
init_memory_size: string;
|
||||
max_memory_size: string;
|
||||
stack_size: string;
|
||||
exported_symbols: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param: includePathArr
|
||||
* @param: excludeFileArr
|
||||
* Get current includePathArr and excludeFileArr from the json string that
|
||||
* will be written into compilation_config.json
|
||||
*/
|
||||
export function writeIntoConfigFile(
|
||||
includePathArr: string[],
|
||||
excludeFileArr: string[],
|
||||
buildArgs?: BuildArgs
|
||||
) {
|
||||
let jsonStr = JSON.stringify({
|
||||
include_paths: includePathArr,
|
||||
exclude_files: excludeFileArr,
|
||||
build_args: buildArgs ? buildArgs : '{}',
|
||||
});
|
||||
|
||||
let prjConfigDir = path.join(currentPrjDir, '.wamr');
|
||||
let configFilePath = path.join(prjConfigDir, 'compilation_config.json');
|
||||
WriteIntoFile(configFilePath, jsonStr);
|
||||
}
|
||||
|
||||
export function readFromConfigFile(): string {
|
||||
let prjConfigDir = path.join(currentPrjDir, '.wamr');
|
||||
let configFilePath = path.join(prjConfigDir, 'compilation_config.json');
|
||||
return ReadFromFile(configFilePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* will be triggered when the user clicking `build` button
|
||||
*/
|
||||
function generateCMakeFile(
|
||||
includePathArr: string[],
|
||||
excludeFileArr: string[]
|
||||
): void {
|
||||
// -Wl,--export=${EXPORT_SYMBOLS}
|
||||
let srcFilePath = path.join(currentPrjDir, 'src');
|
||||
let prjConfigDir = path.join(currentPrjDir, '.wamr');
|
||||
let cmakeFilePath = path.join(prjConfigDir, 'project.cmake');
|
||||
|
||||
let strIncludeList = 'set (PROJECT_INCLUDES';
|
||||
let strSrcList = 'set (PROJECT_SRC_LIST';
|
||||
|
||||
let strOutputFileName = 'set (OUTPUT_FILE_NAME';
|
||||
let strInitMemSize = 'set (INIT_MEM_SIZE';
|
||||
let strMaxMemSize = 'set (MAX_MEM_SIZE';
|
||||
let strStackSize = 'set (STACK_SIZE';
|
||||
let strExportedSymbols = 'set (EXPORTED_SYMBOLS';
|
||||
|
||||
let fullStr = '';
|
||||
let i, s, e: number;
|
||||
|
||||
/* change the absolute path into relative path */
|
||||
let _re = currentPrjDir;
|
||||
let _substr = '${CMAKE_CURRENT_SOURCE_DIR}/..';
|
||||
|
||||
let srcPathArr: Array<{ path: string }> | undefined;
|
||||
/**
|
||||
* set PROJECT_SRC_LIST
|
||||
* default ADD every c OR c++ OR cpp under the src/ path
|
||||
* except the files saved in the exclude_files array
|
||||
*/
|
||||
|
||||
srcPathArr = getAllSrcFiles(srcFilePath);
|
||||
|
||||
if (srcPathArr === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (s = 0; s < srcPathArr.length; s++) {
|
||||
if (
|
||||
excludeFileArr.indexOf(
|
||||
srcPathArr[s].path.replace(currentPrjDir, '..')
|
||||
) === -1
|
||||
) {
|
||||
/* replace currentPrjDir with ${CMAKE_CURRENT_SOURCE_DIR} */
|
||||
let _newStr = srcPathArr[s].path
|
||||
.replace(_re, _substr)
|
||||
.replace(/\\/g, '/');
|
||||
|
||||
strSrcList = strSrcList.concat(' ', _newStr);
|
||||
}
|
||||
}
|
||||
strSrcList = strSrcList.concat(' )');
|
||||
|
||||
for (i = 0; i < includePathArr.length; i++) {
|
||||
let _newStr = includePathArr[i]
|
||||
.replace(/../, _substr)
|
||||
.replace(/\\/g, '/');
|
||||
strIncludeList = strIncludeList.concat(' ', _newStr);
|
||||
}
|
||||
strIncludeList = strIncludeList.concat(' )');
|
||||
|
||||
/* set up user customized input in configBuildArgs webview */
|
||||
strOutputFileName = strOutputFileName.concat(
|
||||
' ',
|
||||
TargetConfigPanel.BUILD_ARGS.output_file_name + ')'
|
||||
);
|
||||
|
||||
strInitMemSize = strInitMemSize.concat(
|
||||
' ',
|
||||
TargetConfigPanel.BUILD_ARGS.init_memory_size + ')'
|
||||
);
|
||||
|
||||
strMaxMemSize = strMaxMemSize.concat(
|
||||
' ',
|
||||
TargetConfigPanel.BUILD_ARGS.max_memory_size + ')'
|
||||
);
|
||||
|
||||
strStackSize = strStackSize.concat(
|
||||
' ',
|
||||
TargetConfigPanel.BUILD_ARGS.stack_size + ')'
|
||||
);
|
||||
|
||||
let exportedSymbolArr =
|
||||
TargetConfigPanel.BUILD_ARGS.exported_symbols.split(',');
|
||||
|
||||
strExportedSymbols = strExportedSymbols.concat(' "');
|
||||
|
||||
for (e = 0; e < exportedSymbolArr.length; e++) {
|
||||
strExportedSymbols = strExportedSymbols.concat(
|
||||
' -Wl,',
|
||||
'--export=',
|
||||
exportedSymbolArr[e]
|
||||
);
|
||||
}
|
||||
|
||||
strExportedSymbols = strExportedSymbols.concat('")');
|
||||
|
||||
fullStr = strOutputFileName
|
||||
.concat('\n', strInitMemSize)
|
||||
.concat('\n', strMaxMemSize)
|
||||
.concat('\n', strStackSize)
|
||||
.concat('\n', strExportedSymbols)
|
||||
.concat('\n', strSrcList)
|
||||
.concat('\n', strIncludeList);
|
||||
|
||||
WriteIntoFile(cmakeFilePath, fullStr);
|
||||
}
|
||||
|
||||
function getAllSrcFiles(_path: string) {
|
||||
try {
|
||||
const entries = fileSystem.readdirSync(_path, {
|
||||
withFileTypes: true,
|
||||
});
|
||||
|
||||
const files = entries
|
||||
.filter(
|
||||
/* filter files mismatch .c |.cpp |.cxx */
|
||||
file =>
|
||||
!file.isDirectory() && file.name.match('(.c|.cpp|.cxx)$')
|
||||
)
|
||||
.map(file => ({
|
||||
path: path.join(_path, file.name),
|
||||
}));
|
||||
|
||||
const folders = entries.filter(folder => folder.isDirectory());
|
||||
|
||||
for (const folder of folders) {
|
||||
let fileArr = getAllSrcFiles(path.join(_path, folder.name));
|
||||
fileArr ? files.push(...fileArr) : '';
|
||||
}
|
||||
|
||||
return files;
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(error as string);
|
||||
}
|
||||
}
|
||||
153
test-tools/wamr-ide/VSCode-Extension/src/taskProvider.ts
Normal file
153
test-tools/wamr-ide/VSCode-Extension/src/taskProvider.ts
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as os from 'os';
|
||||
import { TargetConfigPanel } from './view/TargetConfigPanel';
|
||||
|
||||
interface WasmTaskDefinition extends vscode.TaskDefinition {
|
||||
/**
|
||||
* The build flavor.
|
||||
*/
|
||||
flavor: string;
|
||||
}
|
||||
|
||||
export interface OwnShellOption {
|
||||
cmd: string;
|
||||
options: vscode.ShellExecutionOptions;
|
||||
}
|
||||
|
||||
export class WasmTaskProvider implements vscode.TaskProvider {
|
||||
constructor(
|
||||
public _type: Map<string, string>,
|
||||
public _script: Map<string, string>
|
||||
) {}
|
||||
|
||||
buildShellOption: OwnShellOption | undefined;
|
||||
runShellOption: OwnShellOption | undefined;
|
||||
debugShellOption: OwnShellOption | undefined;
|
||||
|
||||
private wasmPromise: Thenable<vscode.Task[]> | undefined = undefined;
|
||||
|
||||
public provideTasks(): Thenable<vscode.Task[]> | undefined {
|
||||
let targetName =
|
||||
TargetConfigPanel.BUILD_ARGS.output_file_name.split('.')[0];
|
||||
|
||||
if (os.platform() === 'linux') {
|
||||
/* build */
|
||||
this.buildShellOption = {
|
||||
cmd: 'bash',
|
||||
options: {
|
||||
executable: this._script.get('buildScript'),
|
||||
shellArgs: [targetName],
|
||||
},
|
||||
};
|
||||
|
||||
/* debug */
|
||||
this.debugShellOption = {
|
||||
cmd: 'bash',
|
||||
options: {
|
||||
executable: this._script.get('debugScript'),
|
||||
shellArgs: [targetName],
|
||||
},
|
||||
};
|
||||
|
||||
/* run */
|
||||
this.runShellOption = {
|
||||
cmd: 'bash',
|
||||
options: {
|
||||
executable: this._script.get('runScript'),
|
||||
shellArgs: [targetName],
|
||||
},
|
||||
};
|
||||
} else if (os.platform() === 'win32') {
|
||||
this.buildShellOption = {
|
||||
cmd: this._script.get('buildScript') as string,
|
||||
options: {
|
||||
executable: this._script.get('buildScript'),
|
||||
shellArgs: [targetName],
|
||||
},
|
||||
};
|
||||
/* debug */
|
||||
this.debugShellOption = {
|
||||
cmd: this._script.get('debugScript') as string,
|
||||
options: {
|
||||
executable: this._script.get('debugScript'),
|
||||
shellArgs: [targetName],
|
||||
},
|
||||
};
|
||||
/* run */
|
||||
this.runShellOption = {
|
||||
cmd: this._script.get('runScript') as string,
|
||||
options: {
|
||||
executable: this._script.get('runScript'),
|
||||
shellArgs: [targetName],
|
||||
},
|
||||
};
|
||||
} else {
|
||||
this.buildShellOption = {
|
||||
cmd: "echo 'os platform is not supported yet'",
|
||||
options: {},
|
||||
};
|
||||
|
||||
this.debugShellOption = {
|
||||
cmd: "echo 'os platform is not supported yet'",
|
||||
options: {},
|
||||
};
|
||||
|
||||
this.runShellOption = {
|
||||
cmd: "echo 'os platform is not supported yet'",
|
||||
options: {},
|
||||
};
|
||||
}
|
||||
|
||||
this.wasmPromise = Promise.resolve([
|
||||
new vscode.Task(
|
||||
{ type: 'wasm' },
|
||||
vscode.TaskScope.Workspace,
|
||||
'Wasm',
|
||||
this._type.get('Build') as string,
|
||||
new vscode.ShellExecution(
|
||||
this.buildShellOption.cmd,
|
||||
this.buildShellOption.options
|
||||
)
|
||||
),
|
||||
|
||||
new vscode.Task(
|
||||
{ type: 'wasm' },
|
||||
vscode.TaskScope.Workspace,
|
||||
'Wasm',
|
||||
this._type.get('Run') as string,
|
||||
new vscode.ShellExecution(
|
||||
this.runShellOption.cmd,
|
||||
this.runShellOption.options
|
||||
)
|
||||
),
|
||||
|
||||
new vscode.Task(
|
||||
{ type: 'wasm' },
|
||||
vscode.TaskScope.Workspace,
|
||||
'Wasm',
|
||||
this._type.get('Debug') as string,
|
||||
new vscode.ShellExecution(
|
||||
this.debugShellOption.cmd,
|
||||
this.debugShellOption.options
|
||||
)
|
||||
),
|
||||
]);
|
||||
return this.wasmPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* if the task or task in tasks.json does not set command, `
|
||||
* resolveTask` will be invoked,
|
||||
* otherwise, `provideTasks` will be invoked
|
||||
* @param _task
|
||||
* @returns
|
||||
*/
|
||||
public resolveTask(_task: vscode.Task): vscode.Task | undefined {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
import fileSystem = require('fs');
|
||||
import vscode = require('vscode');
|
||||
import path = require('path');
|
||||
|
||||
/**
|
||||
*
|
||||
* @param path destination path
|
||||
*/
|
||||
export function CreateDirectory(
|
||||
dest: string,
|
||||
mode: string | number | null | undefined = undefined
|
||||
): boolean {
|
||||
try {
|
||||
if (fileSystem.existsSync(dest)) {
|
||||
if (fileSystem.lstatSync(dest).isDirectory()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let parent = path.dirname(dest);
|
||||
if (!CreateDirectory(parent, mode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fileSystem.mkdirSync(dest, mode);
|
||||
return true;
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(error as string);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function CopyFiles(src: string, dest: string, flags?: number): boolean {
|
||||
try {
|
||||
fileSystem.copyFileSync(src, dest);
|
||||
return true;
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(error as string);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function WriteIntoFile(path: string, data: string): void {
|
||||
try {
|
||||
fileSystem.writeFileSync(path, data, null);
|
||||
} catch (err) {
|
||||
vscode.window.showErrorMessage(err as string);
|
||||
}
|
||||
}
|
||||
|
||||
export function ReadFromFile(path: string): string {
|
||||
try {
|
||||
let data = fileSystem.readFileSync(path, { encoding: 'utf-8' });
|
||||
return data as string;
|
||||
} catch (err) {
|
||||
vscode.window.showErrorMessage(err as string);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
export function WriteIntoFileAsync(
|
||||
path: string,
|
||||
data: string,
|
||||
callback: fileSystem.NoParamCallback
|
||||
): void {
|
||||
try {
|
||||
fileSystem.writeFile(path, data, callback);
|
||||
} catch (err) {
|
||||
vscode.window.showErrorMessage(err as string);
|
||||
return;
|
||||
}
|
||||
}
|
||||
14
test-tools/wamr-ide/VSCode-Extension/src/utilities/getUri.ts
Normal file
14
test-tools/wamr-ide/VSCode-Extension/src/utilities/getUri.ts
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
import { Uri, Webview } from 'vscode';
|
||||
|
||||
export function getUri(
|
||||
webview: Webview,
|
||||
extensionUri: Uri,
|
||||
pathList: string[]
|
||||
) {
|
||||
return webview.asWebviewUri(Uri.joinPath(extensionUri, ...pathList));
|
||||
}
|
||||
253
test-tools/wamr-ide/VSCode-Extension/src/view/NewProjectPanel.ts
Normal file
253
test-tools/wamr-ide/VSCode-Extension/src/view/NewProjectPanel.ts
Normal file
@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import { CreateDirectory, CopyFiles } from '../utilities/directoryUtilities';
|
||||
import { getUri } from '../utilities/getUri';
|
||||
|
||||
export class NewProjectPanel {
|
||||
static USER_SET_WORKSPACE: string;
|
||||
public static currentPanel: NewProjectPanel | undefined;
|
||||
private readonly _panel: vscode.WebviewPanel;
|
||||
private _disposables: vscode.Disposable[] = [];
|
||||
|
||||
static readonly USER_INTPUT_ERR: number = -2;
|
||||
static readonly DIR_EXSITED_ERR: number = -1;
|
||||
static readonly EXCUTION_SUCCESS: number = 0;
|
||||
|
||||
/**
|
||||
* @param context extension context from extension.ts active func
|
||||
*/
|
||||
constructor(extensionUri: vscode.Uri, panel: vscode.WebviewPanel) {
|
||||
this._panel = panel;
|
||||
this._panel.webview.html = this._getHtmlForWebview(
|
||||
this._panel.webview,
|
||||
extensionUri,
|
||||
'resource/webview/page/newProject.html'
|
||||
);
|
||||
this._setWebviewMessageListener(this._panel.webview, extensionUri);
|
||||
this._panel.onDidDispose(this.dispose, null, this._disposables);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
public static render(context: vscode.ExtensionContext) {
|
||||
NewProjectPanel.USER_SET_WORKSPACE = vscode.workspace
|
||||
.getConfiguration()
|
||||
.get('WAMR-IDE.configWorkspace') as string;
|
||||
|
||||
/* check if current panel is initialized */
|
||||
if (NewProjectPanel.currentPanel) {
|
||||
NewProjectPanel.currentPanel._panel.reveal(vscode.ViewColumn.One);
|
||||
} else {
|
||||
const panel = vscode.window.createWebviewPanel(
|
||||
'newProject',
|
||||
'Create project',
|
||||
vscode.ViewColumn.One,
|
||||
{
|
||||
enableScripts: true,
|
||||
retainContextWhenHidden: true,
|
||||
}
|
||||
);
|
||||
|
||||
/* create new project panel obj */
|
||||
NewProjectPanel.currentPanel = new NewProjectPanel(
|
||||
context.extensionUri,
|
||||
panel
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param projName project name input by user
|
||||
* @param template
|
||||
*/
|
||||
private _creatNewProject(
|
||||
projName: string,
|
||||
template: string,
|
||||
extensionUri: vscode.Uri
|
||||
): number {
|
||||
if (projName === '' || template === '') {
|
||||
return NewProjectPanel.USER_INTPUT_ERR;
|
||||
}
|
||||
|
||||
let ROOT_PATH = path.join(NewProjectPanel.USER_SET_WORKSPACE, projName);
|
||||
let EXT_PATH = extensionUri.fsPath;
|
||||
|
||||
/* if the direcotry has exsited, then ignore the creation and return */
|
||||
if (fs.existsSync(ROOT_PATH)) {
|
||||
if (fs.lstatSync(ROOT_PATH).isDirectory()) {
|
||||
return NewProjectPanel.DIR_EXSITED_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
/* create necessary floders under the project directory */
|
||||
CreateDirectory(path.join(ROOT_PATH, '.wamr'));
|
||||
CreateDirectory(path.join(ROOT_PATH, 'include'));
|
||||
CreateDirectory(path.join(ROOT_PATH, 'src'));
|
||||
|
||||
/* copy scripts files to project_root_path/.wamr */
|
||||
CopyFiles(
|
||||
path.join(EXT_PATH, 'resource/scripts/CMakeLists.txt'),
|
||||
path.join(ROOT_PATH, '.wamr/CMakeLists.txt')
|
||||
);
|
||||
|
||||
CopyFiles(
|
||||
path.join(EXT_PATH, 'resource/scripts/project.cmake'),
|
||||
path.join(ROOT_PATH, '.wamr/project.cmake')
|
||||
);
|
||||
|
||||
return NewProjectPanel.EXCUTION_SUCCESS;
|
||||
}
|
||||
|
||||
public _getHtmlForWebview(
|
||||
webview: vscode.Webview,
|
||||
extensionUri: vscode.Uri,
|
||||
templatePath: string
|
||||
) {
|
||||
/* get toolkit uri */
|
||||
const toolkitUri = getUri(webview, extensionUri, [
|
||||
'node_modules',
|
||||
'@vscode',
|
||||
'webview-ui-toolkit',
|
||||
'dist',
|
||||
'toolkit.js',
|
||||
]);
|
||||
|
||||
const styleUri = getUri(webview, extensionUri, [
|
||||
'resource',
|
||||
'webview',
|
||||
'css',
|
||||
'style.css',
|
||||
]);
|
||||
|
||||
const mainUri = getUri(webview, extensionUri, [
|
||||
'resource',
|
||||
'webview',
|
||||
'js',
|
||||
'newproj.js',
|
||||
]);
|
||||
|
||||
const resourcePath = path.join(extensionUri.fsPath, templatePath);
|
||||
let html = fs.readFileSync(resourcePath, 'utf-8');
|
||||
html = html
|
||||
.replace(/(\${toolkitUri})/, toolkitUri.toString())
|
||||
.replace(/(\${mainUri})/, mainUri.toString())
|
||||
.replace(/(\${styleUri})/, styleUri.toString());
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
private _setWebviewMessageListener(
|
||||
webview: vscode.Webview,
|
||||
extensionUri: vscode.Uri
|
||||
) {
|
||||
// Handle messages from the webview
|
||||
webview.onDidReceiveMessage(
|
||||
message => {
|
||||
switch (message.command) {
|
||||
case 'create_new_project':
|
||||
if (
|
||||
this._creatNewProject(
|
||||
message.projectName,
|
||||
message.template,
|
||||
extensionUri
|
||||
) === NewProjectPanel.EXCUTION_SUCCESS
|
||||
) {
|
||||
/* post message to page to inform the project creation has finished */
|
||||
webview.postMessage({
|
||||
command: 'proj_creation_finish',
|
||||
prjName: message.projectName,
|
||||
});
|
||||
} else if (
|
||||
this._creatNewProject(
|
||||
message.projectName,
|
||||
message.template,
|
||||
extensionUri
|
||||
) === NewProjectPanel.DIR_EXSITED_ERR
|
||||
) {
|
||||
vscode.window.showErrorMessage(
|
||||
'Project : ' +
|
||||
message.projectName +
|
||||
' exsits in your current root path, please change project name or root path!'
|
||||
);
|
||||
return;
|
||||
} else if (
|
||||
this._creatNewProject(
|
||||
message.projectName,
|
||||
message.template,
|
||||
extensionUri
|
||||
) === NewProjectPanel.USER_INTPUT_ERR
|
||||
) {
|
||||
vscode.window.showErrorMessage(
|
||||
'Please fill chart before your submit!'
|
||||
);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
||||
case 'open_project':
|
||||
vscode.window.showInformationMessage(
|
||||
'Project : ' +
|
||||
message.projectName +
|
||||
' will be opened!'
|
||||
);
|
||||
let isWorkspaceEmpty: boolean;
|
||||
|
||||
let projPath = path.join(
|
||||
NewProjectPanel.USER_SET_WORKSPACE,
|
||||
message.projectName
|
||||
);
|
||||
let uri = vscode.Uri.file(projPath);
|
||||
|
||||
/**
|
||||
* check if the vscode workspace folder is empty,
|
||||
* if yes, open new window, else open in current window
|
||||
*/
|
||||
isWorkspaceEmpty = !vscode.workspace
|
||||
.workspaceFolders?.[0]
|
||||
? true
|
||||
: false;
|
||||
isWorkspaceEmpty === false
|
||||
? vscode.commands.executeCommand(
|
||||
'vscode.openFolder',
|
||||
uri,
|
||||
{
|
||||
forceNewWindow: true,
|
||||
}
|
||||
)
|
||||
: vscode.commands.executeCommand(
|
||||
'vscode.openFolder',
|
||||
uri
|
||||
);
|
||||
|
||||
case 'close_webview':
|
||||
this._panel.dispose();
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
undefined,
|
||||
this._disposables
|
||||
);
|
||||
}
|
||||
|
||||
private dispose() {
|
||||
NewProjectPanel.currentPanel = undefined;
|
||||
this._panel.dispose();
|
||||
|
||||
while (this._disposables.length) {
|
||||
const disposable = this._disposables.pop();
|
||||
if (disposable) {
|
||||
disposable.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import { readFromConfigFile, writeIntoConfigFile } from '../extension';
|
||||
import { getUri } from '../utilities/getUri';
|
||||
|
||||
export class TargetConfigPanel {
|
||||
public static currentPanel: TargetConfigPanel | undefined;
|
||||
private readonly _panel: vscode.WebviewPanel;
|
||||
|
||||
private _disposables: vscode.Disposable[] = [];
|
||||
public static BUILD_ARGS = {
|
||||
output_file_name: 'main.wasm',
|
||||
init_memory_size: '131072',
|
||||
max_memory_size: '131072',
|
||||
stack_size: '4096',
|
||||
exported_symbols: 'main',
|
||||
};
|
||||
|
||||
static readonly USER_INTPUT_ERR: number = -2;
|
||||
static readonly EXCUTION_SUCCESS: number = 0;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param context extension context from extension.ts active func
|
||||
* @param panelName
|
||||
*/
|
||||
constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) {
|
||||
this._panel = panel;
|
||||
this._panel.webview.html = this._getHtmlForWebview(
|
||||
this._panel.webview,
|
||||
extensionUri,
|
||||
'resource/webview/page/configBuildTarget.html'
|
||||
);
|
||||
this._panel.onDidDispose(this.dispose, null, this._disposables);
|
||||
this._setWebviewMessageListener(this._panel.webview);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
public static render(context: vscode.ExtensionContext) {
|
||||
/* check if current panel is initialized */
|
||||
if (TargetConfigPanel.currentPanel) {
|
||||
TargetConfigPanel.currentPanel._panel.reveal(vscode.ViewColumn.One);
|
||||
} else {
|
||||
const panel = vscode.window.createWebviewPanel(
|
||||
'targetConfig',
|
||||
'Config building target',
|
||||
vscode.ViewColumn.One,
|
||||
{
|
||||
enableScripts: true,
|
||||
retainContextWhenHidden: true,
|
||||
}
|
||||
);
|
||||
|
||||
TargetConfigPanel.currentPanel = new TargetConfigPanel(
|
||||
panel,
|
||||
context.extensionUri
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private _configBuildArgs(
|
||||
outputFileName: string,
|
||||
initmemSize: string,
|
||||
maxmemSize: string,
|
||||
stackSize: string,
|
||||
exportedSymbols: string
|
||||
): number {
|
||||
if (
|
||||
outputFileName === '' ||
|
||||
initmemSize === '' ||
|
||||
maxmemSize === '' ||
|
||||
stackSize === '' ||
|
||||
exportedSymbols === ''
|
||||
) {
|
||||
return TargetConfigPanel.USER_INTPUT_ERR;
|
||||
}
|
||||
|
||||
let _configStr: string;
|
||||
let includePathArr = new Array();
|
||||
let excludeFileArr = new Array();
|
||||
let configJson: any;
|
||||
|
||||
let _configObj = {
|
||||
output_file_name: outputFileName,
|
||||
init_memory_size: initmemSize,
|
||||
max_memory_size: maxmemSize,
|
||||
stack_size: stackSize,
|
||||
exported_symbols: exportedSymbols,
|
||||
};
|
||||
|
||||
TargetConfigPanel.BUILD_ARGS = _configObj;
|
||||
|
||||
_configStr = readFromConfigFile();
|
||||
|
||||
if (_configStr !== '' && _configStr !== undefined) {
|
||||
configJson = JSON.parse(_configStr);
|
||||
includePathArr =
|
||||
configJson['include_paths'] === undefined
|
||||
? []
|
||||
: configJson['include_paths'];
|
||||
excludeFileArr =
|
||||
configJson['exclude_files'] === undefined
|
||||
? []
|
||||
: configJson['exclude_files'];
|
||||
}
|
||||
|
||||
writeIntoConfigFile(
|
||||
includePathArr,
|
||||
excludeFileArr,
|
||||
TargetConfigPanel.BUILD_ARGS
|
||||
);
|
||||
|
||||
return TargetConfigPanel.EXCUTION_SUCCESS;
|
||||
}
|
||||
|
||||
private _getHtmlForWebview(
|
||||
webview: vscode.Webview,
|
||||
extensionUri: vscode.Uri,
|
||||
templatePath: string
|
||||
) {
|
||||
/* get toolkit uri */
|
||||
const toolkitUri = getUri(webview, extensionUri, [
|
||||
'node_modules',
|
||||
'@vscode',
|
||||
'webview-ui-toolkit',
|
||||
'dist',
|
||||
'toolkit.js',
|
||||
]);
|
||||
|
||||
const styleUri = getUri(webview, extensionUri, [
|
||||
'resource',
|
||||
'webview',
|
||||
'css',
|
||||
'style.css',
|
||||
]);
|
||||
|
||||
const mainUri = getUri(webview, extensionUri, [
|
||||
'resource',
|
||||
'webview',
|
||||
'js',
|
||||
'configbuildtarget.js',
|
||||
]);
|
||||
|
||||
/* get config build target values and set into webview page */
|
||||
let configData, buildArgObj;
|
||||
let _output_file_name,
|
||||
_init_memory_size,
|
||||
_max_memory_size,
|
||||
_stack_size,
|
||||
_exported_symbols;
|
||||
|
||||
if (readFromConfigFile() !== '') {
|
||||
configData = JSON.parse(readFromConfigFile());
|
||||
buildArgObj = configData['build_args'];
|
||||
if (buildArgObj !== undefined) {
|
||||
_output_file_name = buildArgObj['output_file_name'];
|
||||
_init_memory_size = buildArgObj['init_memory_size'];
|
||||
_max_memory_size = buildArgObj['max_memory_size'];
|
||||
_stack_size = buildArgObj['stack_size'];
|
||||
_exported_symbols = buildArgObj['exported_symbols'];
|
||||
}
|
||||
}
|
||||
|
||||
const resourcePath = path.join(extensionUri.fsPath, templatePath);
|
||||
let html = fs.readFileSync(resourcePath, 'utf-8');
|
||||
html = html
|
||||
.replace(/(\${toolkitUri})/, toolkitUri.toString())
|
||||
.replace(/(\${mainUri})/, mainUri.toString())
|
||||
.replace(/(\${styleUri})/, styleUri.toString())
|
||||
.replace(
|
||||
/(\${output_file_val})/,
|
||||
_output_file_name === undefined ? '' : _output_file_name
|
||||
)
|
||||
.replace(
|
||||
/(\${initial_mem_size_val})/,
|
||||
_init_memory_size === undefined ? '' : _init_memory_size
|
||||
)
|
||||
.replace(
|
||||
/(\${max_mem_size_val})/,
|
||||
_max_memory_size === undefined ? '' : _max_memory_size
|
||||
)
|
||||
.replace(
|
||||
/(\${stack_size_val})/,
|
||||
_stack_size === undefined ? '' : _stack_size
|
||||
)
|
||||
.replace(
|
||||
/(\${exported_symbols_val})/,
|
||||
_exported_symbols === undefined ? '' : _exported_symbols
|
||||
);
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
private _setWebviewMessageListener(webview: vscode.Webview) {
|
||||
webview.onDidReceiveMessage(
|
||||
message => {
|
||||
switch (message.command) {
|
||||
case 'config_build_target':
|
||||
if (
|
||||
message.outputFileName === '' ||
|
||||
message.initmemSize === '' ||
|
||||
message.maxmemSize === '' ||
|
||||
message.stackSize === '' ||
|
||||
message.exportedSymbols === ''
|
||||
) {
|
||||
vscode.window.showErrorMessage(
|
||||
'Please fill chart before your submit!'
|
||||
);
|
||||
return;
|
||||
} else if (
|
||||
this._configBuildArgs(
|
||||
message.outputFileName,
|
||||
message.initmemSize,
|
||||
message.maxmemSize,
|
||||
message.stackSize,
|
||||
message.exportedSymbols
|
||||
) === TargetConfigPanel.EXCUTION_SUCCESS
|
||||
) {
|
||||
vscode.window
|
||||
.showInformationMessage(
|
||||
'Configurations have been saved!',
|
||||
'OK'
|
||||
)
|
||||
.then(() => {
|
||||
this._panel.dispose();
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
undefined,
|
||||
this._disposables
|
||||
);
|
||||
}
|
||||
|
||||
private dispose() {
|
||||
TargetConfigPanel.currentPanel = undefined;
|
||||
this._panel.dispose();
|
||||
|
||||
while (this._disposables.length) {
|
||||
const disposable = this._disposables.pop();
|
||||
if (disposable) {
|
||||
disposable.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user