diff --git a/.gitignore b/.gitignore
index fbd9b8e31..fa9e05133 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,5 @@ product-mini/platforms/linux-sgx/enclave-sample/iwasm
build_out
tests/wamr-test-suites/workspace
+
+!/test-tools/wamr-ide/VSCode-Extension/.vscode
\ No newline at end of file
diff --git a/test-tools/wamr-ide/Media/Config_building_target.png b/test-tools/wamr-ide/Media/Config_building_target.png
new file mode 100644
index 000000000..a1270007f
Binary files /dev/null and b/test-tools/wamr-ide/Media/Config_building_target.png differ
diff --git a/test-tools/wamr-ide/Media/build_folder.png b/test-tools/wamr-ide/Media/build_folder.png
new file mode 100644
index 000000000..f69c5b3d6
Binary files /dev/null and b/test-tools/wamr-ide/Media/build_folder.png differ
diff --git a/test-tools/wamr-ide/Media/build_terminal.png b/test-tools/wamr-ide/Media/build_terminal.png
new file mode 100644
index 000000000..a65ae9b2d
Binary files /dev/null and b/test-tools/wamr-ide/Media/build_terminal.png differ
diff --git a/test-tools/wamr-ide/Media/change_workspace_dialog.png b/test-tools/wamr-ide/Media/change_workspace_dialog.png
new file mode 100644
index 000000000..9f6a61428
Binary files /dev/null and b/test-tools/wamr-ide/Media/change_workspace_dialog.png differ
diff --git a/test-tools/wamr-ide/Media/compilation_config.png b/test-tools/wamr-ide/Media/compilation_config.png
new file mode 100644
index 000000000..43c60a21f
Binary files /dev/null and b/test-tools/wamr-ide/Media/compilation_config.png differ
diff --git a/test-tools/wamr-ide/Media/compilation_config_2.png b/test-tools/wamr-ide/Media/compilation_config_2.png
new file mode 100644
index 000000000..c16bb09ec
Binary files /dev/null and b/test-tools/wamr-ide/Media/compilation_config_2.png differ
diff --git a/test-tools/wamr-ide/Media/debug.png b/test-tools/wamr-ide/Media/debug.png
new file mode 100644
index 000000000..15c8e8de6
Binary files /dev/null and b/test-tools/wamr-ide/Media/debug.png differ
diff --git a/test-tools/wamr-ide/Media/decoration_for_files.png b/test-tools/wamr-ide/Media/decoration_for_files.png
new file mode 100644
index 000000000..dd5c0bd74
Binary files /dev/null and b/test-tools/wamr-ide/Media/decoration_for_files.png differ
diff --git a/test-tools/wamr-ide/Media/install_from_vsix.png b/test-tools/wamr-ide/Media/install_from_vsix.png
new file mode 100644
index 000000000..f313ec590
Binary files /dev/null and b/test-tools/wamr-ide/Media/install_from_vsix.png differ
diff --git a/test-tools/wamr-ide/Media/new_project_page.png b/test-tools/wamr-ide/Media/new_project_page.png
new file mode 100644
index 000000000..b498aca4b
Binary files /dev/null and b/test-tools/wamr-ide/Media/new_project_page.png differ
diff --git a/test-tools/wamr-ide/Media/open_project_page.png b/test-tools/wamr-ide/Media/open_project_page.png
new file mode 100644
index 000000000..d4e534307
Binary files /dev/null and b/test-tools/wamr-ide/Media/open_project_page.png differ
diff --git a/test-tools/wamr-ide/Media/project_template.png b/test-tools/wamr-ide/Media/project_template.png
new file mode 100644
index 000000000..e10b102ec
Binary files /dev/null and b/test-tools/wamr-ide/Media/project_template.png differ
diff --git a/test-tools/wamr-ide/Media/right_click_menus_1.png b/test-tools/wamr-ide/Media/right_click_menus_1.png
new file mode 100644
index 000000000..0649f2f49
Binary files /dev/null and b/test-tools/wamr-ide/Media/right_click_menus_1.png differ
diff --git a/test-tools/wamr-ide/Media/right_click_menus_2.png b/test-tools/wamr-ide/Media/right_click_menus_2.png
new file mode 100644
index 000000000..9d8e32216
Binary files /dev/null and b/test-tools/wamr-ide/Media/right_click_menus_2.png differ
diff --git a/test-tools/wamr-ide/Media/run.png b/test-tools/wamr-ide/Media/run.png
new file mode 100644
index 000000000..7a98e0fbb
Binary files /dev/null and b/test-tools/wamr-ide/Media/run.png differ
diff --git a/test-tools/wamr-ide/Media/save_configuration.png b/test-tools/wamr-ide/Media/save_configuration.png
new file mode 100644
index 000000000..39a5c1c4a
Binary files /dev/null and b/test-tools/wamr-ide/Media/save_configuration.png differ
diff --git a/test-tools/wamr-ide/Media/set_up_workspace_message.png b/test-tools/wamr-ide/Media/set_up_workspace_message.png
new file mode 100644
index 000000000..c812a59a4
Binary files /dev/null and b/test-tools/wamr-ide/Media/set_up_workspace_message.png differ
diff --git a/test-tools/wamr-ide/Media/wamr_ide_main_menu.png b/test-tools/wamr-ide/Media/wamr_ide_main_menu.png
new file mode 100644
index 000000000..d9ac2fddd
Binary files /dev/null and b/test-tools/wamr-ide/Media/wamr_ide_main_menu.png differ
diff --git a/test-tools/wamr-ide/README.md b/test-tools/wamr-ide/README.md
new file mode 100644
index 000000000..7e11695bd
--- /dev/null
+++ b/test-tools/wamr-ide/README.md
@@ -0,0 +1,178 @@
+# WAMR-IDE
+
+## Introduction
+
+The WAMR-IDE is an Integrated Development Environment to develop WebAssembly application with coding, compiling and source debugging support. It contains 3 components: `VSCode extension`, `WASM-toolchain-provider docker image` and `WASM source debug server docker image`.
+
+- `VSCode extension` is an extension which can be installed in `vscode`, with which user can build and manage projects, develop `wasm application`, including `building`, `running` and `debugging`.
+
+- `WASM-toolchain-provider` is a docker image which provides building environment for wasm.
+
+- `WASM source debug server` is a docker image which provides running and source debugging environment for wasm application.
+
+---
+
+## How to setup WAMR IDE
+
+1. Install `VSCode` on host.
+
+ - make sure the version of [vscode](https://code.visualstudio.com/Download) you installed is at least _1.59.0_
+
+2. Install `Docker` on host.
+
+ 1. [Windows: Docker Desktop](https://docs.docker.com/desktop/windows/install/)
+ 2. [Ubuntu: Docker Engine](https://docs.docker.com/engine/install/ubuntu)
+ ```xml
+ OS requirements:
+ To install Docker Engine, you need the 64-bit version of one of these Ubuntu versions:
+ - Ubuntu Impish 21.10
+ - Ubuntu Hirsute 21.04
+ - Ubuntu Focal 20.04(LTS)
+ - Ubuntu Bionic 18.04(LTS)
+ ```
+
+3. Build docker images
+
+ We have 2 docker images which should be built or loaded on your host, `wasm-toolchain-provider` and `wamr-debug-server`. To build these 2 images, please enter the `WASM_Source_Debug_Server/Docker` & `WASM_Toolchain/Docker`, then execute the `build_docker_image` script respectively.
+
+ ```shell
+ $ cd WASM_Toolchain/Docker
+ $ ./build_docker_image.bat # or ./build_docker_image.sh on linux
+ $ cd WASM_Source_Debug_Server/Docker
+ $ ./build_docker_image.bat # or ./build_docker_image.sh on linux
+ ```
+
+4. Generate wamride extension package file
+
+ `wamride-0.0.1.vsix` can be packaged by [`npm vsce`](https://code.visualstudio.com/api/working-with-extensions/publishing-extension).
+
+ > Note that patched `lldb` should be built and put into the `VSCode_Extension/resource/debug` folder before your package or extension debug process if you want to enable `source debugging` feature. Please follow this [instruction](../../doc/source_debugging.md#debugging-with-interpreter) to build `lldb`.
+ >
+ > **You can also debug the extension directly follow this [instruction](./VSCode_Extension/README.md) without packing the extension.**
+
+5. Install extension from vsix
+
+ ![install_from_vsix](./Media/install_from_vsix.png "install wamr-ide from vsix")
+
+ and select `wamride-0.0.1.vsix` which you have saved on your host.
+
+---
+
+## How to use `wamr-ide`
+
+#### `WAMR-IDE` extension contains 2 components as following picture showing. `Project management` and `Execution management`
+
+![wamr_ide_main_menu](../Media/wamr_ide_main_menu.png "wamr-ide main menu")
+
+### Project Management
+
+1. New project
+
+ When you click `New project` button, extension will pop up a message box at the bottom right of the screen as picture showing.
+
+ ![set_up_workspace_message](./Media/set_up_workspace_message.png "set up workspace message box")
+
+ You can click `Set up now` and select the target folder to create project workspace, click `Maybe later` to close the message box.
+
+ > Note that your selected workspace folder should be **empty**.
+
+ After setting up workspace, extension will prompt successful message:
+
+ ```xml
+ workspace set up successfully!
+ ```
+
+ Then click `New project` button again, a new page will show as following.
+
+ ![new_project_page](./Media/new_project_page.png "new project page")
+
+ Enter the `project name` and select the `template`, then click `Create` button. And a new project will be generated and opened in your current `vscode window` or in a new `vscode window`.
+
+ > Opening in current windows or a new one depends on whether your `vscode's explorer` is empty or not. If empty, open in current window, or open in the new vscode window.
+
+ A new initialized project is as following picture shows.
+
+ ![project_template](./Media/project_template.png "default project template")
+
+ `.wamr` is the project configuration folder which contains 3 files, `CMakeLists.txt`, `project.cmake` and `compilation_config.json`. `CMakeLists.txt` is used to build `wasm target` and the `project.cmake` is included in `CMakeLists.txt`. `project.cmake` includes the user's customized configuration like those folders which should be added include path.
+
+2. Open project
+
+ Click `Open project` button, `quick-pick-box` will show as following. All projects under your current workspace will be shown and can be selected.
+
+ ![configuration file](./Media/open_project_page.png "configuration file")
+
+3. Change workspace
+
+ Click `Change workspace` button, a dialog will show as following. You can select 1 folder in file system as workspace, and the new workspace path will override previous workspace, and all new created projects will be generated in the new workspace.
+
+ ![change workspace ](./Media/change_workspace_dialog.png "change workspace dialog")
+
+4. Configuration
+ Click `Configuration` button, a new page will be shown as following. You can config building target with `Include paths`, `Initial & Max linear memory`, `stack size`, `exported_symbols` and `include paths`, `exclude files`.
+
+ ![config building target](./Media/Config_building_target.png "config building target")
+
+ Then click `Modify` button to confirm, if configurations are modified successfully and following message will pop. Click `OK`, the page will be auto closed.
+
+ ![save configuration](./Media/save_configuration.png "save configuration")
+
+ And all configuration will be saved in `.wamr/compilation_config.json`.
+
+ ![configuration file](./Media/compilation_config.png "configuration file")
+
+5. Customize `include paths` and `exclude source files`
+
+ Extension supports adding header file folder to `include path` and excluding source file from build.
+
+- `Add to include path`
+
+ - Move the cursor to the `folder` and right click, then `menus` will be shown as following. Click `Toggle state of path including`.
+
+ ![right click menus](./Media/right_click_menus_1.png "right click menus")
+
+- `Exclude source file from build`
+
+ - Move the cursor to the `source file` and right click, then `menus` will be shown as following. Click `Toggle state of excluding`.
+
+ ![right click menus](./Media/right_click_menus_2.png "right click menus")
+
+ #### After setting up `include path` and `exclude files`, the corresponding folder and files will be decorated with color and icon as following picture shows.
+
+ ![decoration for files](./Media/decoration_for_files.png "decoration for files")
+
+ At the same time, all added `include path` and `exclude files` will be saved in `.wamr/compilation_config.json` as json array.
+
+ ![compilation config](./Media/compilation_config_2.png "compilation config")
+
+> `Toggle state of path including` just shows when selecting `folder` and hides with other resources.
+>
+> `Toggle state of excluding` just shows when selecting `[.c | .cpp | .cxx] source files` and hides with other resources.
+
+### Execution Management
+
+1. `Build`
+
+ When you have completed coding and ready to build target, click `build` button and the `wasm-toolchain` will auto start a container and execute the building process.
+
+ ![build terminal output](./Media/build_terminal.png "build terminal output")
+
+ After successful building execution, `build` folder will be generated in `explorer`, in which `${output_file_name}.wasm` is exist.
+
+ ![build folder](./Media/build_folder.png "build folder")
+
+ > Note that to start `docker service` firstly.
+
+2. `Run`
+
+ Click `Run` button and `wasm-debug-server` docker image will auto start a container and execute the running process.
+
+ ![run](./Media/run.png "run wasm")
+
+3. `Debug`
+
+ Click `Debug` button will trigger start ip `wamr-debug-server` docker image, and boot up `lldb debug server` inside of iwasm. Then start a debugging session with configuration to connect. Tap `F11` or click `step into` to start debugging.
+
+ ![debug](./Media/debug.png "source debugging")
+
+ > Docker containers will be auto stopped and removed after the execution.
diff --git a/test-tools/wamr-ide/VSCode-Extension/.eslintrc.json b/test-tools/wamr-ide/VSCode-Extension/.eslintrc.json
new file mode 100644
index 000000000..f9b22b793
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/.eslintrc.json
@@ -0,0 +1,24 @@
+{
+ "root": true,
+ "parser": "@typescript-eslint/parser",
+ "parserOptions": {
+ "ecmaVersion": 6,
+ "sourceType": "module"
+ },
+ "plugins": [
+ "@typescript-eslint"
+ ],
+ "rules": {
+ "@typescript-eslint/naming-convention": "warn",
+ "@typescript-eslint/semi": "warn",
+ "curly": "warn",
+ "eqeqeq": "warn",
+ "no-throw-literal": "warn",
+ "semi": "off"
+ },
+ "ignorePatterns": [
+ "out",
+ "dist",
+ "**/*.d.ts"
+ ]
+}
diff --git a/test-tools/wamr-ide/VSCode-Extension/.gitignore b/test-tools/wamr-ide/VSCode-Extension/.gitignore
new file mode 100644
index 000000000..a5697da9f
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/.gitignore
@@ -0,0 +1,7 @@
+out
+dist
+node_modules
+.vscode-test/
+*.vsix
+package-lock.json
+src/test
\ No newline at end of file
diff --git a/test-tools/wamr-ide/VSCode-Extension/.prettierrc.json b/test-tools/wamr-ide/VSCode-Extension/.prettierrc.json
new file mode 100644
index 000000000..3c85a97fe
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/.prettierrc.json
@@ -0,0 +1,12 @@
+{
+ "printWidth": 80,
+ "tabWidth": 4,
+ "useTabs": false,
+ "semi": true,
+ "singleQuote": true,
+ "trailingComma": "es5",
+ "bracketSpacing": true,
+ "jsxBracketSameLine": false,
+ "arrowParens": "avoid",
+ "proseWrap": "always"
+}
diff --git a/test-tools/wamr-ide/VSCode-Extension/.vscode/extensions.json b/test-tools/wamr-ide/VSCode-Extension/.vscode/extensions.json
new file mode 100644
index 000000000..0d8ed8b15
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/.vscode/extensions.json
@@ -0,0 +1,5 @@
+{
+ // See http://go.microsoft.com/fwlink/?LinkId=827846
+ // for the documentation about the extensions.json format
+ "recommendations": ["dbaeumer.vscode-eslint"]
+}
diff --git a/test-tools/wamr-ide/VSCode-Extension/.vscode/launch.json b/test-tools/wamr-ide/VSCode-Extension/.vscode/launch.json
new file mode 100644
index 000000000..b75b8ccaa
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/.vscode/launch.json
@@ -0,0 +1,15 @@
+// A launch configuration that compiles the extension and then opens it inside a new window
+
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Launch Extension",
+ "type": "extensionHost",
+ "request": "launch",
+ "args": ["--extensionDevelopmentPath=${workspaceFolder}"],
+ "outFiles": ["${workspaceFolder}/out/**/*.js"],
+ "preLaunchTask": "${defaultBuildTask}"
+ }
+ ]
+}
diff --git a/test-tools/wamr-ide/VSCode-Extension/.vscode/tasks.json b/test-tools/wamr-ide/VSCode-Extension/.vscode/tasks.json
new file mode 100644
index 000000000..65a9dcf8e
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/.vscode/tasks.json
@@ -0,0 +1,20 @@
+// See https://go.microsoft.com/fwlink/?LinkId=733558
+// for the documentation about the tasks.json format
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "type": "npm",
+ "script": "watch",
+ "problemMatcher": "$tsc-watch",
+ "isBackground": true,
+ "presentation": {
+ "reveal": "never"
+ },
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ }
+ }
+ ]
+}
diff --git a/test-tools/wamr-ide/VSCode-Extension/.vscodeignore b/test-tools/wamr-ide/VSCode-Extension/.vscodeignore
new file mode 100644
index 000000000..fbd882434
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/.vscodeignore
@@ -0,0 +1,12 @@
+.vscode/**
+.vscode-test/**
+out/test/**
+
+src/**
+.gitignore
+.yarnrc
+vsc-extension-quickstart.md
+**/tsconfig.json
+**/.eslintrc.json
+**/*.map
+**/*.ts
diff --git a/test-tools/wamr-ide/VSCode-Extension/README.md b/test-tools/wamr-ide/VSCode-Extension/README.md
new file mode 100644
index 000000000..65d5ecaea
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/README.md
@@ -0,0 +1,25 @@
+# Introduction
+
+### An integrated development environment for WASM.
+
+# How to debug this extension
+
+> Note that please build `lldb` firstly follow this
+> [instruction](./resource/debug/README.md) if you want to enable
+> `source debugging` feature of this extension
+
+### 1. open `VSCode_Extension` directory with the `vscode`
+
+```xml
+File -> Open Folder -> select `VSCode_Extension`
+```
+
+### 2. run `npm install` in `terminal` to install necessary dependencies.
+
+### 3. click `F5` or `ctrl+shift+D` switch to `Run and Debug` panel and click `Run Extension` to boot.
+
+# Code Format
+
+`prettier` is recommended and `.prettierrc.json` has been provided in workspace.
+More details and usage guidance please refer
+[prettier](https://prettier.io/docs/en/install.html)
diff --git a/test-tools/wamr-ide/VSCode-Extension/package.json b/test-tools/wamr-ide/VSCode-Extension/package.json
new file mode 100644
index 000000000..1d8b1c8a7
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/package.json
@@ -0,0 +1,238 @@
+{
+ "name": "wamride",
+ "publisher": "wamr",
+ "displayName": "WAMR-IDE",
+ "description": "An Integrated Development Environment for WASM",
+ "version": "0.0.1",
+ "engines": {
+ "vscode": "^1.59.0"
+ },
+ "categories": [
+ "Other"
+ ],
+ "activationEvents": [
+ "*"
+ ],
+ "main": "./out/extension.js",
+ "contributes": {
+ "commands": [
+ {
+ "command": "wamride.newProject",
+ "title": "Create new project",
+ "category": "New project"
+ },
+ {
+ "command": "wamride.changeWorkspace",
+ "title": "Change workspace",
+ "category": "Change Workspace"
+ },
+ {
+ "command": "wamride.build",
+ "title": "WAMRIDE:Build Wasm"
+ },
+ {
+ "command": "wamride.run",
+ "title": "WAMRIDE:Run Wasm"
+ },
+ {
+ "command": "wamride.debug",
+ "title": "WAMRIDE:Source Debug"
+ },
+ {
+ "command": "wamride.openFolder",
+ "title": "WAMRIDE:openWorkspace"
+ },
+ {
+ "command": "wamride.build.toggleStateIncludePath",
+ "title": "Toggle state of path including"
+ },
+ {
+ "command": "wamride.build.toggleStateExclude",
+ "title": "Toggle state of excluding"
+ },
+ {
+ "command": "wamride.targetConfig",
+ "title": "Target Configuration"
+ }
+ ],
+ "viewsContainers": {
+ "activitybar": [
+ {
+ "id": "wamride",
+ "title": "WAMRIDE",
+ "icon": "$(star)"
+ }
+ ]
+ },
+ "views": {
+ "wamride": [
+ {
+ "id": "wamride.views.welcome",
+ "name": "Quick Access"
+ }
+ ]
+ },
+ "viewsWelcome": [
+ {
+ "view": "wamride.views.welcome",
+ "contents": "[ Project Management ]\n[$(project)New project](command:wamride.newProject)\n[$(files)Open project](command:wamride.openFolder)\n[$(book)Change workspace](command:wamride.changeWorkspace)\n[$(pencil)Configuration](command:wamride.targetConfig)"
+ },
+ {
+ "view": "wamride.views.welcome",
+ "contents": "[ Execution Management ]\n[$(gear)Build](command:wamride.build)\n[$(run)Run](command:wamride.run)\n[$(debug-alt) Debug](command:wamride.debug)",
+ "enablement": "ext.isWasmProject"
+ }
+ ],
+ "menus": {
+ "explorer/context": [
+ {
+ "command": "wamride.build.toggleStateIncludePath",
+ "alt": "wamride.build.toggleStateIncludePath",
+ "group": "config",
+ "when": "explorerResourceIsFolder"
+ },
+ {
+ "command": "wamride.build.toggleStateExclude",
+ "alt": "wamride.build.toggleStateExclude",
+ "group": "config",
+ "when": "!explorerResourceIsFolder && resourceExtname in ext.supportedFileType"
+ }
+ ]
+ },
+ "debuggers": [
+ {
+ "type": "wamr-debug",
+ "label": "WAMR lldb debugger",
+ "enableBreakpointsFor": {
+ "languageIds": [
+ "ada",
+ "arm",
+ "asm",
+ "c",
+ "cpp",
+ "crystal",
+ "d",
+ "fortan",
+ "fortran-modern",
+ "nim",
+ "objective-c",
+ "objectpascal",
+ "pascal",
+ "rust",
+ "swift"
+ ]
+ },
+ "program": "./resource/debug/bin/lldb-vscode",
+ "windows": {
+ "program": "./resource/debug/bin/lldb-vscode.exe"
+ },
+ "configurationAttributes": {
+ "attach": {
+ "properties": {
+ "sourcePath": {
+ "type": "string",
+ "description": "Specify a source path to remap \"./\" to allow full paths to be used when setting breakpoints in binaries that have relative source paths."
+ },
+ "sourceMap": {
+ "type": "array",
+ "description": "Specify an array of path remappings; each element must itself be a two element array containing a source and destination pathname. Overrides sourcePath.",
+ "default": []
+ },
+ "debuggerRoot": {
+ "type": "string",
+ "description": "Specify a working directory to set the debug adaptor to so relative object files can be located."
+ },
+ "attachCommands": {
+ "type": "array",
+ "description": "Custom commands that are executed instead of attaching to a process ID or to a process by name. These commands may optionally create a new target and must perform an attach. A valid process must exist after these commands complete or the \"attach\" will fail.",
+ "default": []
+ },
+ "initCommands": {
+ "type": "array",
+ "description": "Initialization commands executed upon debugger startup.",
+ "default": []
+ },
+ "preRunCommands": {
+ "type": "array",
+ "description": "Commands executed just before the program is attached to.",
+ "default": []
+ },
+ "stopCommands": {
+ "type": "array",
+ "description": "Commands executed each time the program stops.",
+ "default": []
+ },
+ "exitCommands": {
+ "type": "array",
+ "description": "Commands executed at the end of debugging session.",
+ "default": []
+ }
+ }
+ }
+ },
+ "initialConfigurations": [
+ {
+ "type": "wamr-debug",
+ "request": "attach",
+ "name": "Debug",
+ "stopOnEntry": true,
+ "attachCommands": [
+ "process connect -p wasm connect://127.0.0.1:1234"
+ ]
+ }
+ ],
+ "configurationSnippets": [
+ {
+ "label": "WAMR: Attach",
+ "description": "",
+ "body": {
+ "type": "wamr-debug",
+ "request": "attach",
+ "name": "${2:Attach}",
+ "stopOnEntry": true,
+ "attachCommands": [
+ "process connect -p wasm connect://${3:127.0.0.1}:${4:1234}"
+ ]
+ }
+ }
+ ]
+ }
+ ],
+ "configuration": [
+ {
+ "title": "WAMR-IDE",
+ "properties": {
+ "WAMR-IDE.configWorkspace": {
+ "type": "string",
+ "description": "Config the workspace for WebAssembly project."
+ }
+ }
+ }
+ ]
+ },
+ "scripts": {
+ "vscode:prepublish": "npm run compile",
+ "compile": "tsc -p ./",
+ "watch": "tsc -watch -p ./",
+ "pretest": "npm run compile && npm run lint",
+ "lint": "eslint src --ext ts",
+ "test": "node ./out/test/runTest.js"
+ },
+ "devDependencies": {
+ "@types/glob": "^7.1.3",
+ "@types/mocha": "^8.2.2",
+ "@types/node": "14.x",
+ "@types/vscode": "^1.54.0",
+ "@typescript-eslint/eslint-plugin": "^4.26.0",
+ "@typescript-eslint/parser": "^4.26.0",
+ "eslint": "^7.32.0",
+ "glob": "^7.1.7",
+ "mocha": "^8.4.0",
+ "prettier": "2.5.1",
+ "typescript": "^4.3.2",
+ "vscode-test": "^1.5.2"
+ },
+ "dependencies": {
+ "@vscode/webview-ui-toolkit": "^0.8.4"
+ }
+}
diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/debug/README.md b/test-tools/wamr-ide/VSCode-Extension/resource/debug/README.md
new file mode 100644
index 000000000..e672d8b22
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/resource/debug/README.md
@@ -0,0 +1,11 @@
+### If you want to enable `source debugging` for this extension, please build `lldb` firstly following this [instruction](../../../../../doc/source_debugging.md#debugging-with-interpreter).
+
+### After building(`linux` for example), create `bin` folder and `lib` folder respectively in current directory, add following necessary target files into the folders.
+
+ ```shell
+ /llvm/build-lldb/bin/lldb # move this file to resource/debug/bin/
+ /llvm/build-lldb/bin/lldb-vscode # move this file to resource/debug/bin/
+ /llvm/build-lldb/lib/liblldb.so.13 # move this file to resource/debug/lib/
+ ```
+
+### Then you can start the extension and run the execute source debugging by clicking the `debug` button in the extension panel.
diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/CMakeLists.txt b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/CMakeLists.txt
new file mode 100644
index 000000000..4752623d5
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/CMakeLists.txt
@@ -0,0 +1,40 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required (VERSION 2.9)
+
+project(Main)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/project.cmake)
+
+set (CMAKE_SYSROOT /opt/wamr-sdk/app/libc-builtin-sysroot)
+
+set (CMAKE_C_FLAGS " -nostdlib -g -Wno-unused-command-line-argument " CACHE INTERNAL "")
+
+set (CMAKE_CXX_FLAGS " -nostdlib -g" CACHE INTERNAL "")
+
+set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -z stack-size=${STACK_SIZE}")
+
+set (CMAKE_EXE_LINKER_FLAGS
+ "-Wl,--initial-memory=${INIT_MEM_SIZE},--max-memory=${MAX_MEM_SIZE}, \
+ -Wl,--no-entry,")
+
+set (CMAKE_EXE_LINKER_FLAGS
+ "${CMAKE_EXE_LINKER_FLAGS} \
+ ${EXPORTED_SYMBOLS},")
+
+set (CMAKE_EXE_LINKER_FLAGS
+ "${CMAKE_EXE_LINKER_FLAGS} \
+ -Wl,--allow-undefined-file=${CMAKE_SYSROOT}/share/defined-symbols.txt" CACHE INTERNAL "")
+
+set (SRC_LIST
+ ${PROJECT_SRC_LIST})
+
+set (HEADER_LIST
+ ${CMAKE_CURRENT_SOURCE_DIR}/../include
+ ${PROJECT_INCLUDES})
+
+include_directories(${HEADER_LIST})
+
+add_executable (${OUTPUT_FILE_NAME} ${SRC_LIST})
+
diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/boot_debugger_server.bat b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/boot_debugger_server.bat
new file mode 100644
index 000000000..9b8459b6b
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/boot_debugger_server.bat
@@ -0,0 +1,14 @@
+@REM Copyright (C) 2019 Intel Corporation. All rights reserved.
+@REM SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+@echo off
+set target_name=%1
+
+docker run -it --name=wasm-debug-server-ctr ^
+ -v "%cd%":/mnt ^
+ -p 1234:1234 ^
+ wasm-debug-server:1.0 ^
+ /bin/bash -c "./debug.sh %target_name%"
+
+@REM stop and remove wasm-debug-server-container
+docker stop wasm-debug-server-ctr && docker rm wasm-debug-server-ctr
diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/boot_debugger_server.sh b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/boot_debugger_server.sh
new file mode 100644
index 000000000..b963685cf
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/boot_debugger_server.sh
@@ -0,0 +1,14 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#!/bin/bash
+
+target_name=$1
+
+docker run -it --name=wasm-debug-server-ctr \
+ -v $(pwd):/mnt \
+ -p 1234:1234 \
+ wasm-debug-server:1.0 \
+ /bin/bash -c "./debug.sh ${target_name}"
+
+docker stop wasm-debug-server-ctr && docker rm wasm-debug-server-ctr
\ No newline at end of file
diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/build.bat b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/build.bat
new file mode 100644
index 000000000..aaf89a3d9
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/build.bat
@@ -0,0 +1,14 @@
+@REM Copyright (C) 2019 Intel Corporation. All rights reserved.
+@REM SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+@echo off
+set AoT_Binary_Name=%1
+
+@REM start a container, mount current project path to container/mnt
+docker run --name=wasm-toolchain-provider-ctr ^
+ -it -v %cd%:/mnt ^
+ wasm-toolchain-provider:1.0 ^
+ /bin/bash -c "./build_wasm.sh %AoT_Binary_Name%"
+
+@REM stop and remove wasm-toolchain-ctr container
+docker stop wasm-toolchain-provider-ctr && docker rm wasm-toolchain-provider-ctr
diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/build.sh b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/build.sh
new file mode 100644
index 000000000..d6b794059
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/build.sh
@@ -0,0 +1,19 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#!/bin/bash
+
+AoT_Binary_Name=$1
+
+# start & run docker image and build wasm
+if test ! -z "$(docker ps -a | grep wasm-toolchain-ctr)"; then
+ sudo docker rm wasm-toolchain-ctr
+fi
+
+sudo docker run --name=wasm-toolchain-provider-ctr \
+ -it -v $(pwd):/mnt \
+ wasm-toolchain-provider:1.0 \
+ /bin/bash -c "./build_wasm.sh $AoT_Binary_Name"
+
+# stop and remove wasm-toolchain-ctr container
+sudo docker stop wasm-toolchain-provider-ctr && sudo docker rm wasm-toolchain-provider-ctr
diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/project.cmake b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/project.cmake
new file mode 100644
index 000000000..7248979cf
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/project.cmake
@@ -0,0 +1,17 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (OUTPUT_FILE_NAME)
+
+set (INIT_MEM_SIZE)
+
+set (MAX_MEM_SIZE)
+
+set (STACK_SIZE)
+
+set (EXPORTED_SYMBOLS)
+
+set (PROJECT_SRC_LIST)
+
+set (PROJECT_INCLUDES)
+
diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/run.bat b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/run.bat
new file mode 100644
index 000000000..5e7ac83f4
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/run.bat
@@ -0,0 +1,13 @@
+@REM Copyright (C) 2019 Intel Corporation. All rights reserved.
+@REM SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+@echo off
+set target_name=%1
+
+docker run -it --name=wasm-executor-ctr ^
+ -v "%cd%":/mnt ^
+ wasm-debug-server:1.0 ^
+ /bin/bash -c "./run.sh %target_name%"
+
+@REM stop and remove wasm-executor-ctr
+docker stop wasm-executor-ctr && docker rm wasm-executor-ctr
diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/scripts/run.sh b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/run.sh
new file mode 100644
index 000000000..b8087a823
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/resource/scripts/run.sh
@@ -0,0 +1,12 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#!/bin/bash
+target_name=$1
+
+docker run -it --name=wasm-debug-server-ctr \
+ -v $(pwd):/mnt \
+ wasm-debug-server:1.0 \
+ /bin/bash -c "./run.sh ${target_name}"
+
+docker stop wasm-debug-server-ctr && docker rm wasm-debug-server-ctr
\ No newline at end of file
diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/webview/css/style.css b/test-tools/wamr-ide/VSCode-Extension/resource/webview/css/style.css
new file mode 100644
index 000000000..8975ecf7e
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/resource/webview/css/style.css
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+.box_wrapper {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.form_heading {
+ text-align: left;
+}
+
+.form_heading vscode-divider,
+.config_form_heading vscode-divider,
+.form_bottom vscode-divider,
+.config_form_bottom vscode-divider {
+ padding-bottom: 0.5rem;
+}
+
+.form_body,
+.config_form_body {
+ display: grid;
+ grid-row-gap: 1rem;
+ padding-bottom: 0.5rem;
+}
+
+.config_form_body div,
+.config_submit_btn_wrapper {
+ display: grid;
+ grid-template-columns: 4fr 8fr;
+ grid-column-gap: 0.5rem;
+}
+
+.form_heading,
+.form_body,
+.form_bottom {
+ width: 400px;
+}
+
+.config_form_body,
+.config_form_heading,
+.config_form_bottom {
+ width: 550px;
+}
+
+#btn_submit {
+ border-radius: 5px;
+}
+
+#select_div,
+#text_filed_div,
+.proj_submit_btn_wrapper {
+ display: grid;
+ grid-template-columns: 3fr 9fr;
+ grid-column-gap: 0.5rem;
+}
+
+#ipt_projName,
+#tselect_dropdown,
+.config_form_body vscode-text-field,
+.config_form_body vscode-text-area {
+ width: 100%;
+}
+
+#btn {
+ text-align: center;
+}
diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/webview/js/configbuildtarget.js b/test-tools/wamr-ide/VSCode-Extension/resource/webview/js/configbuildtarget.js
new file mode 100644
index 000000000..58b5afe23
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/resource/webview/js/configbuildtarget.js
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+
+const vscode = acquireVsCodeApi();
+
+document.getElementById('btn_submit').onclick = () => {
+ submitFunc();
+};
+
+function submitFunc() {
+ let outputFileName = document.getElementById('output_file_name').value;
+ let initmemSize = document.getElementById('initial_mem_size').value;
+ let maxmemSize = document.getElementById('max_mem_size').value;
+ let stackSize = document.getElementById('stack_size').value;
+ let exportedSymbols = document.getElementById('exported_symbols').value;
+
+ vscode.postMessage({
+ command: 'config_build_target',
+ outputFileName: outputFileName,
+ initmemSize: initmemSize,
+ maxmemSize: maxmemSize,
+ stackSize: stackSize,
+ exportedSymbols: exportedSymbols,
+ });
+}
diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/webview/js/newproj.js b/test-tools/wamr-ide/VSCode-Extension/resource/webview/js/newproj.js
new file mode 100644
index 000000000..30e169788
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/resource/webview/js/newproj.js
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+const vscode = acquireVsCodeApi();
+
+document.getElementById('btn_submit').onclick = () => {
+ submitFunc();
+};
+
+function submitFunc() {
+ let projectName = document.getElementById('ipt_projName').value;
+ let template = document.getElementById('select_dropdown').value;
+
+ vscode.postMessage({
+ command: 'create_new_project',
+ projectName: projectName,
+ template: template,
+ });
+
+ /* get msg from ext */
+ window.addEventListener('message', event => {
+ const message = event.data;
+ switch (message.command) {
+ /* send command to open the project */
+ case 'proj_creation_finish':
+ vscode.postMessage({
+ command: 'open_project',
+ projectName: message.prjName,
+ });
+ break;
+ default:
+ break;
+ }
+ });
+}
diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/webview/page/configBuildTarget.html b/test-tools/wamr-ide/VSCode-Extension/resource/webview/page/configBuildTarget.html
new file mode 100644
index 000000000..b4c431511
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/resource/webview/page/configBuildTarget.html
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+ New project
+
+
+
+
+
+
Config building target
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/webview/page/newProject.html b/test-tools/wamr-ide/VSCode-Extension/resource/webview/page/newProject.html
new file mode 100644
index 000000000..71e67bd89
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/resource/webview/page/newProject.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+ Create project
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ default
+
+
+
+
+
+
+
+
+
diff --git a/test-tools/wamr-ide/VSCode-Extension/src/debug/debugConfigurationProvider.ts b/test-tools/wamr-ide/VSCode-Extension/src/debug/debugConfigurationProvider.ts
new file mode 100644
index 000000000..09793d791
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/src/debug/debugConfigurationProvider.ts
@@ -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
+ | undefined = undefined;
+
+ private wasmDebugConfig!: vscode.DebugConfiguration;
+
+ public resolveDebugConfiguration():
+ | Thenable
+ | 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;
+ }
+}
diff --git a/test-tools/wamr-ide/VSCode-Extension/src/explorer/decorationProvider.ts b/test-tools/wamr-ide/VSCode-Extension/src/explorer/decorationProvider.ts
new file mode 100644
index 000000000..39b269571
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/src/explorer/decorationProvider.ts
@@ -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;
+
+ 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 {
+ 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();
diff --git a/test-tools/wamr-ide/VSCode-Extension/src/extension.ts b/test-tools/wamr-ide/VSCode-Extension/src/extension.ts
new file mode 100644
index 000000000..845162129
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/src/extension.ts
@@ -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);
+ }
+}
diff --git a/test-tools/wamr-ide/VSCode-Extension/src/taskProvider.ts b/test-tools/wamr-ide/VSCode-Extension/src/taskProvider.ts
new file mode 100644
index 000000000..323e97f4c
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/src/taskProvider.ts
@@ -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,
+ public _script: Map
+ ) {}
+
+ buildShellOption: OwnShellOption | undefined;
+ runShellOption: OwnShellOption | undefined;
+ debugShellOption: OwnShellOption | undefined;
+
+ private wasmPromise: Thenable | undefined = undefined;
+
+ public provideTasks(): Thenable | 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;
+ }
+}
diff --git a/test-tools/wamr-ide/VSCode-Extension/src/utilities/directoryUtilities.ts b/test-tools/wamr-ide/VSCode-Extension/src/utilities/directoryUtilities.ts
new file mode 100644
index 000000000..eab82090d
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/src/utilities/directoryUtilities.ts
@@ -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;
+ }
+}
diff --git a/test-tools/wamr-ide/VSCode-Extension/src/utilities/getUri.ts b/test-tools/wamr-ide/VSCode-Extension/src/utilities/getUri.ts
new file mode 100644
index 000000000..d897489d7
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/src/utilities/getUri.ts
@@ -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));
+}
diff --git a/test-tools/wamr-ide/VSCode-Extension/src/view/NewProjectPanel.ts b/test-tools/wamr-ide/VSCode-Extension/src/view/NewProjectPanel.ts
new file mode 100644
index 000000000..17732ec00
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/src/view/NewProjectPanel.ts
@@ -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();
+ }
+ }
+ }
+}
diff --git a/test-tools/wamr-ide/VSCode-Extension/src/view/TargetConfigPanel.ts b/test-tools/wamr-ide/VSCode-Extension/src/view/TargetConfigPanel.ts
new file mode 100644
index 000000000..1f4a544aa
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/src/view/TargetConfigPanel.ts
@@ -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();
+ }
+ }
+ }
+}
diff --git a/test-tools/wamr-ide/VSCode-Extension/tsconfig.json b/test-tools/wamr-ide/VSCode-Extension/tsconfig.json
new file mode 100644
index 000000000..b65c74510
--- /dev/null
+++ b/test-tools/wamr-ide/VSCode-Extension/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "target": "es6",
+ "outDir": "out",
+ "lib": [
+ "es6"
+ ],
+ "sourceMap": true,
+ "rootDir": "src",
+ "strict": true /* enable all strict type-checking options */
+ /* Additional Checks */
+ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
+ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
+ // "noUnusedParameters": true, /* Report errors on unused parameters. */
+ },
+ "exclude": [
+ "node_modules",
+ ".vscode-test"
+ ]
+}
diff --git a/test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/Dockerfile b/test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/Dockerfile
new file mode 100644
index 000000000..fd24b0cde
--- /dev/null
+++ b/test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/Dockerfile
@@ -0,0 +1,32 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+FROM gcc:9.3.0 AS BASE
+
+## set work directory
+WORKDIR /root/
+COPY resource /root/
+
+## - download cmake with wget and set up
+RUN wget https://github.com/Kitware/CMake/releases/download/v3.21.1/cmake-3.21.1-linux-x86_64.tar.gz \
+ && tar -zxvf cmake-3.21.1-linux-x86_64.tar.gz \
+ && rm -f cmake-3.21.1-linux-x86_64.tar.gz \
+ && mv cmake-3.21.1-linux-x86_64 /opt/cmake \
+ && ln -s /opt/cmake/bin/cmake /bin/cmake \
+ && apt-get install make
+
+## -clone wamr-repo and build iwasm
+RUN git clone -b main --depth=1 https://github.com/bytecodealliance/wasm-micro-runtime.git \
+ && cd /root/wasm-micro-runtime/product-mini/platforms/linux \
+ && mkdir build && cd build \
+ && cmake .. -DWAMR_BUILD_DEBUG_INTERP=1 && make \
+ && cp /root/wasm-micro-runtime/product-mini/platforms/linux/build/iwasm /root/iwasm \
+ && rm -fr /root/wasm-micro-runtime
+
+FROM ubuntu:20.04
+# COPY files from BASE image
+COPY --from=BASE /root/iwasm /root
+COPY --from=BASE /root/debug.sh /root
+COPY --from=BASE /root/run.sh /root
+
+WORKDIR /root/
\ No newline at end of file
diff --git a/test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/README.md b/test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/README.md
new file mode 100644
index 000000000..a21165657
--- /dev/null
+++ b/test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/README.md
@@ -0,0 +1,15 @@
+### Build Docker Image
+
+- execute `build_docker_image.bat` on `Windows`
+- execute `build_docker_image.sh` on `Linux`
+
+ ```shell
+ chmod +x resource/*
+ ./build_docker_image.sh
+ ```
+
+### Resource Details
+
+- `Dockerflie` is the source file to build `wasm-debug-server` docker image
+- `resource/debug.sh` is the script to execute the `/mnt/build/${target}.wasm` in debug mode, will start up the debugger server inside of the `iwasm` and hold to wait for connecting.
+- `resource/run.sh` is the script to execute the `/mnt/build/${target}.wasm` directly.
diff --git a/test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/build_docker_image.bat b/test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/build_docker_image.bat
new file mode 100644
index 000000000..54a224ef2
--- /dev/null
+++ b/test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/build_docker_image.bat
@@ -0,0 +1,8 @@
+@REM Copyright (C) 2019 Intel Corporation. All rights reserved.
+@REM SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+@echo off
+docker build -t wasm-debug-server:1.0 .
+
+@REM delete intermediate docker image
+sudo docker image prune -f
\ No newline at end of file
diff --git a/test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/build_docker_image.sh b/test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/build_docker_image.sh
new file mode 100644
index 000000000..6cf95dbef
--- /dev/null
+++ b/test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/build_docker_image.sh
@@ -0,0 +1,8 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#!/bin/bash
+docker build -t wasm-debug-server:1.0 .
+
+# delete intermediate docker image
+sudo docker image prune -f
\ No newline at end of file
diff --git a/test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/resource/debug.sh b/test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/resource/debug.sh
new file mode 100644
index 000000000..48458870f
--- /dev/null
+++ b/test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/resource/debug.sh
@@ -0,0 +1,6 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#!/bin/bash
+TARGET=$1
+./iwasm -g=0.0.0.0:1234 /mnt/build/${TARGET}.wasm
\ No newline at end of file
diff --git a/test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/resource/run.sh b/test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/resource/run.sh
new file mode 100644
index 000000000..4e3acecba
--- /dev/null
+++ b/test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/resource/run.sh
@@ -0,0 +1,6 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#!/bin/bash
+TARGET=$1
+./iwasm /mnt/build/${TARGET}.wasm
\ No newline at end of file
diff --git a/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/.dockerignore b/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/.dockerignore
new file mode 100644
index 000000000..a49cbd220
--- /dev/null
+++ b/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/.dockerignore
@@ -0,0 +1,4 @@
+# move unnecessary files here to save build time cost and image size
+*.md
+*.sh
+*.bat
\ No newline at end of file
diff --git a/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/Dockerfile b/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/Dockerfile
new file mode 100644
index 000000000..8f9da4d48
--- /dev/null
+++ b/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/Dockerfile
@@ -0,0 +1,63 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+## Build docker image that consists of gcc, cmake, wasi-sdk
+FROM gcc:9.3.0 AS BASE
+
+## set work directory
+WORKDIR /root/
+
+COPY resource /root/
+
+## set compilation environment for wamrc
+# - cmake
+# - wasi-sdk
+# - wamr-sdk
+
+## - download cmake with wget and set up
+RUN wget https://github.com/Kitware/CMake/releases/download/v3.21.1/cmake-3.21.1-linux-x86_64.tar.gz \
+ && tar -zxvf cmake-3.21.1-linux-x86_64.tar.gz \
+ && rm -f cmake-3.21.1-linux-x86_64.tar.gz \
+ && mv cmake-3.21.1-linux-x86_64 /opt/cmake \
+ && ln -s /opt/cmake/bin/cmake /bin/cmake \
+ && apt-get install make
+
+## - download wasi-sdk with wget and set up to /opt/wasi-sdk
+RUN wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz \
+ && tar -zxvf wasi-sdk-12.0-linux.tar.gz \
+ && rm -f wasi-sdk-12.0-linux.tar.gz
+
+RUN git clone -b main --depth=1 https://github.com/bytecodealliance/wasm-micro-runtime.git \
+ && cd /root/wasm-micro-runtime/wamr-compiler \
+ && ./build_llvm.sh \
+ # - build wamrc
+ && cd /root/wasm-micro-runtime/wamr-compiler \
+ && mkdir build \
+ && cd build \
+ && cmake .. \
+ && make \
+ # - copy the wamrc to /root
+ && cp /root/wasm-micro-runtime/wamr-compiler/build/wamrc /root/wamrc \
+ && mkdir -p /opt/wamr-sdk/app \
+ && cp -r /root/wasm-micro-runtime/wamr-sdk/app/libc-builtin-sysroot /opt/wamr-sdk/app/ \
+ # - remove the wamr repo to save the size
+ && rm -fr /root/wasm-micro-runtime
+
+## STAGE 2
+FROM ubuntu:20.04
+RUN mkdir -p /opt/wasi-sdk \
+ && mkdir -p /opt/cmake \
+ && mkdir -p /opt/wamr-sdk/app
+
+# COPY files from BASE image
+COPY --from=BASE /opt/cmake/ /opt/cmake/
+COPY --from=BASE /opt/wamr-sdk/app/ /opt/wamr-sdk/app/
+COPY --from=BASE /root/wasi-sdk-12.0/ /opt/wasi-sdk/
+COPY --from=BASE /root/wamrc /root
+COPY --from=BASE /root/build_wasm.sh /root
+
+RUN ln -s /opt/cmake/bin/cmake /usr/bin/cmake \
+ && ln -s /root/wamrc /usr/bin/wamrc
+RUN apt-get update && apt-get install make
+
+WORKDIR /root
\ No newline at end of file
diff --git a/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/README.md b/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/README.md
new file mode 100644
index 000000000..ceacc77f3
--- /dev/null
+++ b/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/README.md
@@ -0,0 +1,71 @@
+# WASM Toolchain Provider Introduction
+
+## Files on HOST
+
+#### Dockerfile
+
+- ubuntu : 20.04
+- set up the necessary toolchains
+ - WASI-SDK (version: 12.0)
+ - WAMR-SDK
+ - repo: bytecode-alliance/wasm-micro-runtime
+ - branch: main
+ - LLVM (latest repo build)
+ - CMake (version: 3.21.1)
+
+#### build_docker_image.sh
+
+- the script to build docker image for Linux platform
+- tag: 1.0
+
+#### build_docker_image.bat
+
+- the script to build docker image for windows platform
+- tag: 1.0
+
+#### run_container.sh
+
+- the script to start and run the docker container for Linux platform
+- mount `host directory` and `container directory`
+ - temporally using `$(pwd)/host_mnt_test` in **host** and `/mnt` in **container**
+- set docker container name with `--name`
+ - temporally set to _wasm-toolchain-ctr_
+
+#### run_container.bat
+
+- the script to start and run the docker container for windows platform
+
+## Files inside docker
+
+### `wamrc`
+
+### `wasi-sdk`
+
+# Build Docker Image
+
+- Linux
+
+```shell
+chmod +x resource/*
+./build_docker_image.sh
+```
+
+- Windows
+
+```shell
+./build_docker_image.bat
+```
+
+# Run Docker Container
+
+- Linux
+
+```shell
+./run_container.sh
+```
+
+- Windows
+
+```shell
+./run_container.bat
+```
diff --git a/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/build_docker_image.bat b/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/build_docker_image.bat
new file mode 100644
index 000000000..4438ce562
--- /dev/null
+++ b/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/build_docker_image.bat
@@ -0,0 +1,12 @@
+@REM Copyright (C) 2019 Intel Corporation. All rights reserved.
+@REM SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+@echo off
+
+@REM pull gcc and ubuntu image firstly no matter whether exist or not.
+docker pull gcc:9.3.0
+docker pull ubuntu:20.04
+docker build -t wasm-toolchain-provider:1.0 .
+
+@REM delete intermediate docker image
+sudo docker image prune -f
diff --git a/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/build_docker_image.sh b/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/build_docker_image.sh
new file mode 100644
index 000000000..0ad021440
--- /dev/null
+++ b/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/build_docker_image.sh
@@ -0,0 +1,10 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#!/bin/bash
+sudo docker pull gcc:9.3.0
+sudo docker pull ubuntu:20.04
+sudo docker build -t wasm-toolchain-provider:1.0 .
+
+# delete intermediate docker image
+sudo docker image prune -f
diff --git a/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/resource/build_wasm.sh b/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/resource/build_wasm.sh
new file mode 100644
index 000000000..8b98a10cc
--- /dev/null
+++ b/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/resource/build_wasm.sh
@@ -0,0 +1,24 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#!/bin/bash
+export CC=/opt/wasi-sdk/bin/clang
+export CXX=/opt/wasi-sdk/bin/clang++
+
+if [ -d /mnt/build ];then
+ rm -fr /mnt/build
+fi
+
+mkdir -p /mnt/build
+cd /mnt/build/
+echo "========> compile wasm with wasi-sdk"
+cmake ../.wamr && make
+
+echo && echo
+echo "========> compile wasm to AoT with wamrc"
+# target name will be provided:
+# - user input the target name in IDE
+# - generated wasm binary name will be set as user's input target name
+# - aot binary name should be the same as wasm binary name
+# - target name will be provided through 1st parameter
+wamrc -o $1.aot $1.wasm
\ No newline at end of file
diff --git a/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/run_container.bat b/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/run_container.bat
new file mode 100644
index 000000000..efab908d2
--- /dev/null
+++ b/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/run_container.bat
@@ -0,0 +1,16 @@
+@REM Copyright (C) 2019 Intel Corporation. All rights reserved.
+@REM SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+@echo off
+
+@REM # create mount directory on host
+
+if not exist host_mnt (
+ md host_mnt
+)
+
+docker run -it ^
+ -v %cd%\host_mnt:/mnt ^
+ --name wasm-toolchain-provider-ctr ^
+ wasm-toolchain-provider:1.0 ^
+ /bin/bash
\ No newline at end of file
diff --git a/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/run_container.sh b/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/run_container.sh
new file mode 100644
index 000000000..b9bc91ef9
--- /dev/null
+++ b/test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/run_container.sh
@@ -0,0 +1,15 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#!/bin/bash
+set -x
+
+# create mount directory on host
+if [ ! -d host_mnt ];then
+ mkdir host_mnt
+fi
+
+sudo docker run --name=wasm-toolchain-provider-ctr \
+ -it -v $(pwd)/host_mnt:/mnt \
+ wasm-toolchain-provider:1.0 \
+ /bin/bash