mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-09-08 18:59:35 +00:00

Download and install the WAMR patched LLDB binary on vscode extension activation. This allows the user to download the packaged .vsix file, where the activation script should handle determining what LLDB binary they should use, and install it in the correct location.
947 lines
34 KiB
TypeScript
947 lines
34 KiB
TypeScript
/*
|
|
* 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 {
|
|
checkIfDirectoryExists,
|
|
writeIntoFile,
|
|
readFromFile,
|
|
} from './utilities/directoryUtilities';
|
|
import { decorationProvider } from './decorationProvider';
|
|
import { WasmDebugConfigurationProvider } from './debugConfigurationProvider';
|
|
import { isLLDBInstalled, promptInstallLLDB } from './utilities/lldbUtilities';
|
|
|
|
let wasmTaskProvider: WasmTaskProvider;
|
|
let wasmDebugConfigProvider: WasmDebugConfigurationProvider;
|
|
var currentPrjDir = '';
|
|
var extensionPath = '';
|
|
var isWasmProject = false;
|
|
|
|
export async function activate(context: vscode.ExtensionContext) {
|
|
var OS_PLATFORM = '',
|
|
buildScript = '',
|
|
runScript = '',
|
|
debugScript = '',
|
|
destroyScript = '',
|
|
buildScriptFullPath = '',
|
|
runScriptFullPath = '',
|
|
debugScriptFullPath = '',
|
|
destroyScriptFullPath = '',
|
|
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');
|
|
destroyScript = scriptPrefix.concat('destroy.bat');
|
|
} else if (OS_PLATFORM === 'linux' || OS_PLATFORM === 'darwin') {
|
|
buildScript = scriptPrefix.concat('build.sh');
|
|
runScript = scriptPrefix.concat('run.sh');
|
|
debugScript = scriptPrefix.concat('boot_debugger_server.sh');
|
|
destroyScript = scriptPrefix.concat('destroy.sh');
|
|
}
|
|
|
|
extensionPath = context.extensionPath;
|
|
|
|
buildScriptFullPath = path.join(extensionPath, buildScript);
|
|
runScriptFullPath = path.join(extensionPath, runScript);
|
|
debugScriptFullPath = path.join(extensionPath, debugScript);
|
|
destroyScriptFullPath = path.join(extensionPath, destroyScript);
|
|
|
|
scriptMap.set('buildScript', buildScriptFullPath);
|
|
scriptMap.set('runScript', runScriptFullPath);
|
|
scriptMap.set('debugScript', debugScriptFullPath);
|
|
scriptMap.set('destroyScript', destroyScriptFullPath);
|
|
|
|
typeMap.set('Build', 'Build');
|
|
typeMap.set('Run', 'Run');
|
|
typeMap.set('Debug', 'Debug');
|
|
typeMap.set('Destroy', 'Destroy');
|
|
|
|
wasmTaskProvider = new WasmTaskProvider(typeMap, scriptMap);
|
|
|
|
vscode.tasks.registerTaskProvider('wasm', wasmTaskProvider);
|
|
|
|
if (vscode.workspace.workspaceFolders?.[0]) {
|
|
if (OS_PLATFORM === 'win32') {
|
|
currentPrjDir = vscode.workspace.workspaceFolders?.[0].uri
|
|
.fsPath as string;
|
|
} else if (OS_PLATFORM === 'linux' || OS_PLATFORM === 'darwin') {
|
|
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) {
|
|
isWasmProject = true;
|
|
vscode.commands.executeCommand(
|
|
'setContext',
|
|
'ext.isWasmProject',
|
|
isWasmProject
|
|
);
|
|
if (
|
|
vscode.workspace
|
|
.getConfiguration()
|
|
.has('C_Cpp.default.systemIncludePath')
|
|
) {
|
|
let newIncludeInCppArr: string[] | undefined | null;
|
|
|
|
newIncludeInCppArr = vscode.workspace
|
|
.getConfiguration()
|
|
.get('C_Cpp.default.systemIncludePath');
|
|
|
|
let LibcBuiltinHeaderPath = path.join(
|
|
extensionPath,
|
|
'resource/wamr-sdk/libc-builtin-sysroot/include'
|
|
);
|
|
|
|
if (newIncludeInCppArr !== undefined) {
|
|
/* in case the configuration has not been set up, push directly */
|
|
if (newIncludeInCppArr === null) {
|
|
newIncludeInCppArr = new Array();
|
|
newIncludeInCppArr.push(LibcBuiltinHeaderPath);
|
|
} else {
|
|
/* if the configuration has been set up, check the condition */
|
|
if (
|
|
/* include libc-builtin-sysroot */
|
|
newIncludeInCppArr.indexOf(
|
|
LibcBuiltinHeaderPath
|
|
) < 0
|
|
) {
|
|
newIncludeInCppArr.push(LibcBuiltinHeaderPath);
|
|
}
|
|
}
|
|
|
|
vscode.workspace
|
|
.getConfiguration()
|
|
.update(
|
|
'C_Cpp.default.systemIncludePath',
|
|
newIncludeInCppArr,
|
|
vscode.ConfigurationTarget.Workspace
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 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 if (!checkIfDirectoryExists(curWorkspace as string)) {
|
|
vscode.window
|
|
.showWarningMessage(
|
|
'Invalid workspace:',
|
|
{
|
|
modal: true,
|
|
detail:
|
|
'' +
|
|
vscode.workspace
|
|
.getConfiguration()
|
|
.get('WAMR-IDE.configWorkspace') +
|
|
'',
|
|
},
|
|
_ok
|
|
)
|
|
.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 */
|
|
if (Workspace !== '' && Workspace !== undefined) {
|
|
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',
|
|
() => {
|
|
if (!isWasmProject) {
|
|
vscode.window.showErrorMessage('Build failed', {
|
|
modal: true,
|
|
detail: 'Current project is not wasm project, please open wasm project and try again.',
|
|
});
|
|
return;
|
|
}
|
|
|
|
generateCMakeFile(includePathArr, excludeFileArr);
|
|
/* destroy the wasm-toolchain-ctr if it exists */
|
|
vscode.commands
|
|
.executeCommand(
|
|
'workbench.action.tasks.runTask',
|
|
'Destroy: Wasm-Container-Before-Build'
|
|
)
|
|
.then(() => {
|
|
let disposable = vscode.tasks.onDidEndTaskProcess(t => {
|
|
if (
|
|
t.execution.task.name ===
|
|
'Wasm-Container-Before-Build'
|
|
) {
|
|
if (t.exitCode !== 0) {
|
|
disposable.dispose();
|
|
return;
|
|
}
|
|
|
|
/* execute the build task */
|
|
vscode.commands
|
|
.executeCommand(
|
|
'workbench.action.tasks.runTask',
|
|
'Build: Wasm'
|
|
)
|
|
.then(() => {
|
|
/* destroy the wasm-toolchain-ctr after building */
|
|
let disposable_aft =
|
|
vscode.tasks.onDidEndTask(a => {
|
|
if (
|
|
a.execution.task.name ===
|
|
'Wasm' &&
|
|
a.execution.task.source ===
|
|
'Build'
|
|
) {
|
|
vscode.commands
|
|
.executeCommand(
|
|
'workbench.action.tasks.runTask',
|
|
'Destroy: Wasm-Container-After-Build'
|
|
)
|
|
.then(() => {
|
|
/* dispose the event after this building process
|
|
*/
|
|
disposable_aft.dispose();
|
|
});
|
|
}
|
|
});
|
|
});
|
|
/* dispose the event after this building process */
|
|
disposable.dispose();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
);
|
|
|
|
let disposableDebug = vscode.commands.registerCommand(
|
|
'wamride.debug',
|
|
async () => {
|
|
if (!isWasmProject) {
|
|
vscode.window.showErrorMessage('debug failed', {
|
|
modal: true,
|
|
detail: 'Current project is not wasm project, please open wasm project and try again.',
|
|
});
|
|
return;
|
|
}
|
|
|
|
/* we should check again whether the user installed lldb, as this can be skipped during activation */
|
|
try {
|
|
if (!isLLDBInstalled(context)) {
|
|
await promptInstallLLDB(context);
|
|
}
|
|
} catch (e) {
|
|
vscode.window.showWarningMessage((e as Error).message);
|
|
}
|
|
|
|
/* refuse to debug if build process failed */
|
|
if (!checkIfBuildSuccess()) {
|
|
vscode.window.showErrorMessage('Debug failed', {
|
|
modal: true,
|
|
detail: 'Can not find WASM binary, please build WASM firstly.',
|
|
});
|
|
return;
|
|
}
|
|
|
|
/* show debug view */
|
|
vscode.commands.executeCommand('workbench.view.debug');
|
|
|
|
/* should destroy the wasm-debug-server-ctr before debugging */
|
|
vscode.commands
|
|
.executeCommand(
|
|
'workbench.action.tasks.runTask',
|
|
'Destroy: Wasm-Container-Before-Debug'
|
|
)
|
|
.then(() => {
|
|
/* execute the debug task when destroy task finish */
|
|
let disposable_bfr = vscode.tasks.onDidEndTask(t => {
|
|
if (
|
|
t.execution.task.name ===
|
|
'Wasm-Container-Before-Debug'
|
|
) {
|
|
vscode.commands
|
|
.executeCommand(
|
|
'workbench.action.tasks.runTask',
|
|
'Debug: Wasm'
|
|
)
|
|
.then(() => {
|
|
vscode.debug
|
|
.startDebugging(
|
|
undefined,
|
|
wasmDebugConfigProvider.getDebugConfig()
|
|
)
|
|
.then(() => {
|
|
/* register to listen debug session finish event */
|
|
let dispose_aft =
|
|
vscode.debug.onDidTerminateDebugSession(
|
|
s => {
|
|
if (
|
|
s.type !==
|
|
'wamr-debug'
|
|
) {
|
|
return;
|
|
}
|
|
|
|
/* execute the task to destroy
|
|
* wasm-debug-server-ctr */
|
|
vscode.commands.executeCommand(
|
|
'workbench.action.tasks.runTask',
|
|
'Destroy: Wasm-Container-After-Debug'
|
|
);
|
|
|
|
/* execute the task to kill the terminal */
|
|
vscode.commands.executeCommand(
|
|
'workbench.action.terminal.kill',
|
|
'Debug: Wasm'
|
|
);
|
|
|
|
dispose_aft.dispose();
|
|
}
|
|
);
|
|
});
|
|
});
|
|
}
|
|
disposable_bfr.dispose();
|
|
});
|
|
});
|
|
}
|
|
);
|
|
let disposableRun = vscode.commands.registerCommand('wamride.run', () => {
|
|
if (!isWasmProject) {
|
|
vscode.window.showErrorMessage('run failed', {
|
|
modal: true,
|
|
detail: 'Current project is not wasm project, please open wasm project and try again.',
|
|
});
|
|
return;
|
|
}
|
|
|
|
/* refuse to debug if build process failed */
|
|
if (!checkIfBuildSuccess()) {
|
|
vscode.window.showErrorMessage('Debug failed', {
|
|
modal: true,
|
|
detail: 'Can not find WASM binary, please build WASM firstly.',
|
|
});
|
|
return;
|
|
}
|
|
vscode.commands
|
|
.executeCommand(
|
|
'workbench.action.tasks.runTask',
|
|
'Destroy: Wasm-Container-Before-Run'
|
|
)
|
|
.then(() => {
|
|
let dispose_bfr = vscode.tasks.onDidEndTaskProcess(e => {
|
|
if (e.execution.task.name === 'Wasm-Container-Before-Run') {
|
|
/* make sure that run wasm task will be executed after destroy task finish */
|
|
vscode.commands
|
|
.executeCommand(
|
|
'workbench.action.tasks.runTask',
|
|
'Run: Wasm'
|
|
)
|
|
.then(() => {
|
|
if (e.exitCode !== 0) {
|
|
dispose_bfr.dispose();
|
|
return;
|
|
}
|
|
});
|
|
dispose_bfr.dispose();
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
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',
|
|
() => {
|
|
/* get projects list under current workspace */
|
|
let _ok = 'Set up now';
|
|
let _cancle = 'Maybe later';
|
|
let _create = 'Create now';
|
|
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 if (!checkIfDirectoryExists(curWorkspace as string)) {
|
|
vscode.window
|
|
.showWarningMessage(
|
|
'Invalid workspace:',
|
|
{
|
|
modal: true,
|
|
detail:
|
|
'' +
|
|
vscode.workspace
|
|
.getConfiguration()
|
|
.get('WAMR-IDE.configWorkspace') +
|
|
'',
|
|
},
|
|
_ok
|
|
)
|
|
.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 projects from current workspace failed.'
|
|
);
|
|
}
|
|
|
|
if (directoryArrDirent !== undefined) {
|
|
directoryArr = directoryArrDirent
|
|
.filter(dirent => dirent.isDirectory())
|
|
.map(dirent => dirent.name);
|
|
|
|
let projFilesArr = directoryArr.filter(obj => {
|
|
if (checkIfWasmProj(path.join(curWorkspace, obj))) {
|
|
return true;
|
|
}
|
|
});
|
|
|
|
if (projFilesArr.length === 0) {
|
|
vscode.window
|
|
.showWarningMessage(
|
|
'Current workspace is empty, please create your project firstly.',
|
|
_create,
|
|
_cancle
|
|
)
|
|
.then(item => {
|
|
if (item === _create) {
|
|
vscode.commands.executeCommand(
|
|
'wamride.newProject'
|
|
);
|
|
} else {
|
|
return;
|
|
}
|
|
});
|
|
} else {
|
|
vscode.window
|
|
.showQuickPick(projFilesArr, {
|
|
title: 'Select project',
|
|
placeHolder: 'Please select project',
|
|
})
|
|
.then(option => {
|
|
if (!option) {
|
|
return;
|
|
}
|
|
|
|
let _path = curWorkspace.concat(
|
|
OS_PLATFORM === 'win32'
|
|
? '\\'
|
|
: OS_PLATFORM === 'linux' || OS_PLATFORM === 'darwin'
|
|
? '/'
|
|
: '',
|
|
option
|
|
);
|
|
|
|
/* open the selected wasm project */
|
|
openWindoWithSituation(vscode.Uri.file(_path));
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
);
|
|
|
|
context.subscriptions.push(
|
|
disposableNewProj,
|
|
disposableTargetConfig,
|
|
disposableChangeWorkspace,
|
|
disposableBuild,
|
|
disposableRun,
|
|
disposableToggleIncludePath,
|
|
disposableOpenFolder,
|
|
disposableToggleExcludeFile,
|
|
disposableDebug
|
|
);
|
|
|
|
try {
|
|
if (!isLLDBInstalled(context)) {
|
|
await promptInstallLLDB(context);
|
|
}
|
|
} catch (e) {
|
|
vscode.window.showWarningMessage((e as Error).message);
|
|
}
|
|
}
|
|
|
|
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 : '{}',
|
|
},
|
|
null,
|
|
'\t'
|
|
);
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
function checkIfBuildSuccess(): Boolean {
|
|
try {
|
|
let wasmExist = false;
|
|
const entries = fileSystem.readdirSync(
|
|
path.join(currentPrjDir, 'build'),
|
|
{
|
|
withFileTypes: true,
|
|
}
|
|
);
|
|
|
|
entries.map(e => {
|
|
if (e.name.match('(.wasm)$')) {
|
|
wasmExist = true;
|
|
}
|
|
});
|
|
|
|
return wasmExist;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function checkIfWasmProj(_path: string): Boolean {
|
|
try {
|
|
let isWasmProj = false;
|
|
const entries = fileSystem.readdirSync(_path, {
|
|
withFileTypes: true,
|
|
});
|
|
|
|
entries.map(e => {
|
|
if (e.isDirectory() && e.name === '.wamr') {
|
|
isWasmProj = true;
|
|
}
|
|
});
|
|
|
|
return isWasmProj;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|