Kaynağa Gözat

Implement WAMR-IDE with vscode extension (#943)

Implement WAMR-IDE with vscode extension to enable developing
WebAssembly applications with coding, building, running and
debugging support. Support both Linux and Windows, and only
support putting all the tools in a docker image, e.g. wasi-sdk, wamrc,
iwasm and so on.

Co-authored-by: Wang Ning <justdoitwn@163.com>
Wenyong Huang 4 yıl önce
ebeveyn
işleme
d925369a1f
66 değiştirilmiş dosya ile 2769 ekleme ve 0 silme
  1. 2 0
      .gitignore
  2. BIN
      test-tools/wamr-ide/Media/Config_building_target.png
  3. BIN
      test-tools/wamr-ide/Media/build_folder.png
  4. BIN
      test-tools/wamr-ide/Media/build_terminal.png
  5. BIN
      test-tools/wamr-ide/Media/change_workspace_dialog.png
  6. BIN
      test-tools/wamr-ide/Media/compilation_config.png
  7. BIN
      test-tools/wamr-ide/Media/compilation_config_2.png
  8. BIN
      test-tools/wamr-ide/Media/debug.png
  9. BIN
      test-tools/wamr-ide/Media/decoration_for_files.png
  10. BIN
      test-tools/wamr-ide/Media/install_from_vsix.png
  11. BIN
      test-tools/wamr-ide/Media/new_project_page.png
  12. BIN
      test-tools/wamr-ide/Media/open_project_page.png
  13. BIN
      test-tools/wamr-ide/Media/project_template.png
  14. BIN
      test-tools/wamr-ide/Media/right_click_menus_1.png
  15. BIN
      test-tools/wamr-ide/Media/right_click_menus_2.png
  16. BIN
      test-tools/wamr-ide/Media/run.png
  17. BIN
      test-tools/wamr-ide/Media/save_configuration.png
  18. BIN
      test-tools/wamr-ide/Media/set_up_workspace_message.png
  19. BIN
      test-tools/wamr-ide/Media/wamr_ide_main_menu.png
  20. 178 0
      test-tools/wamr-ide/README.md
  21. 24 0
      test-tools/wamr-ide/VSCode-Extension/.eslintrc.json
  22. 7 0
      test-tools/wamr-ide/VSCode-Extension/.gitignore
  23. 12 0
      test-tools/wamr-ide/VSCode-Extension/.prettierrc.json
  24. 5 0
      test-tools/wamr-ide/VSCode-Extension/.vscode/extensions.json
  25. 15 0
      test-tools/wamr-ide/VSCode-Extension/.vscode/launch.json
  26. 20 0
      test-tools/wamr-ide/VSCode-Extension/.vscode/tasks.json
  27. 12 0
      test-tools/wamr-ide/VSCode-Extension/.vscodeignore
  28. 25 0
      test-tools/wamr-ide/VSCode-Extension/README.md
  29. 238 0
      test-tools/wamr-ide/VSCode-Extension/package.json
  30. 11 0
      test-tools/wamr-ide/VSCode-Extension/resource/debug/README.md
  31. 40 0
      test-tools/wamr-ide/VSCode-Extension/resource/scripts/CMakeLists.txt
  32. 14 0
      test-tools/wamr-ide/VSCode-Extension/resource/scripts/boot_debugger_server.bat
  33. 14 0
      test-tools/wamr-ide/VSCode-Extension/resource/scripts/boot_debugger_server.sh
  34. 14 0
      test-tools/wamr-ide/VSCode-Extension/resource/scripts/build.bat
  35. 19 0
      test-tools/wamr-ide/VSCode-Extension/resource/scripts/build.sh
  36. 17 0
      test-tools/wamr-ide/VSCode-Extension/resource/scripts/project.cmake
  37. 13 0
      test-tools/wamr-ide/VSCode-Extension/resource/scripts/run.bat
  38. 12 0
      test-tools/wamr-ide/VSCode-Extension/resource/scripts/run.sh
  39. 70 0
      test-tools/wamr-ide/VSCode-Extension/resource/webview/css/style.css
  40. 28 0
      test-tools/wamr-ide/VSCode-Extension/resource/webview/js/configbuildtarget.js
  41. 37 0
      test-tools/wamr-ide/VSCode-Extension/resource/webview/js/newproj.js
  42. 63 0
      test-tools/wamr-ide/VSCode-Extension/resource/webview/page/configBuildTarget.html
  43. 55 0
      test-tools/wamr-ide/VSCode-Extension/resource/webview/page/newProject.html
  44. 65 0
      test-tools/wamr-ide/VSCode-Extension/src/debug/debugConfigurationProvider.ts
  45. 88 0
      test-tools/wamr-ide/VSCode-Extension/src/explorer/decorationProvider.ts
  46. 597 0
      test-tools/wamr-ide/VSCode-Extension/src/extension.ts
  47. 153 0
      test-tools/wamr-ide/VSCode-Extension/src/taskProvider.ts
  48. 83 0
      test-tools/wamr-ide/VSCode-Extension/src/utilities/directoryUtilities.ts
  49. 14 0
      test-tools/wamr-ide/VSCode-Extension/src/utilities/getUri.ts
  50. 253 0
      test-tools/wamr-ide/VSCode-Extension/src/view/NewProjectPanel.ts
  51. 260 0
      test-tools/wamr-ide/VSCode-Extension/src/view/TargetConfigPanel.ts
  52. 21 0
      test-tools/wamr-ide/VSCode-Extension/tsconfig.json
  53. 32 0
      test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/Dockerfile
  54. 15 0
      test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/README.md
  55. 8 0
      test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/build_docker_image.bat
  56. 8 0
      test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/build_docker_image.sh
  57. 6 0
      test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/resource/debug.sh
  58. 6 0
      test-tools/wamr-ide/WASM-Source-Debug-Server/Docker/resource/run.sh
  59. 4 0
      test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/.dockerignore
  60. 63 0
      test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/Dockerfile
  61. 71 0
      test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/README.md
  62. 12 0
      test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/build_docker_image.bat
  63. 10 0
      test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/build_docker_image.sh
  64. 24 0
      test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/resource/build_wasm.sh
  65. 16 0
      test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/run_container.bat
  66. 15 0
      test-tools/wamr-ide/WASM-Toolchain-Provider/Docker/run_container.sh

+ 2 - 0
.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

BIN
test-tools/wamr-ide/Media/Config_building_target.png


BIN
test-tools/wamr-ide/Media/build_folder.png


BIN
test-tools/wamr-ide/Media/build_terminal.png


BIN
test-tools/wamr-ide/Media/change_workspace_dialog.png


BIN
test-tools/wamr-ide/Media/compilation_config.png


BIN
test-tools/wamr-ide/Media/compilation_config_2.png


BIN
test-tools/wamr-ide/Media/debug.png


BIN
test-tools/wamr-ide/Media/decoration_for_files.png


BIN
test-tools/wamr-ide/Media/install_from_vsix.png


BIN
test-tools/wamr-ide/Media/new_project_page.png


BIN
test-tools/wamr-ide/Media/open_project_page.png


BIN
test-tools/wamr-ide/Media/project_template.png


BIN
test-tools/wamr-ide/Media/right_click_menus_1.png


BIN
test-tools/wamr-ide/Media/right_click_menus_2.png


BIN
test-tools/wamr-ide/Media/run.png


BIN
test-tools/wamr-ide/Media/save_configuration.png


BIN
test-tools/wamr-ide/Media/set_up_workspace_message.png


BIN
test-tools/wamr-ide/Media/wamr_ide_main_menu.png


+ 178 - 0
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.

+ 24 - 0
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"
+    ]
+}

+ 7 - 0
test-tools/wamr-ide/VSCode-Extension/.gitignore

@@ -0,0 +1,7 @@
+out
+dist
+node_modules
+.vscode-test/
+*.vsix
+package-lock.json
+src/test

+ 12 - 0
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"
+}

+ 5 - 0
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"]
+}

+ 15 - 0
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}"
+        }
+    ]
+}

+ 20 - 0
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
+            }
+        }
+    ]
+}

+ 12 - 0
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

+ 25 - 0
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)

+ 238 - 0
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"
+    }
+}

+ 11 - 0
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.

+ 40 - 0
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})
+

+ 14 - 0
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

+ 14 - 0
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

+ 14 - 0
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

+ 19 - 0
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

+ 17 - 0
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)
+

+ 13 - 0
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

+ 12 - 0
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

+ 70 - 0
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;
+}

+ 28 - 0
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,
+    });
+}

+ 37 - 0
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;
+        }
+    });
+}

+ 63 - 0
test-tools/wamr-ide/VSCode-Extension/resource/webview/page/configBuildTarget.html

@@ -0,0 +1,63 @@
+<!--
+  -- Copyright (C) 2019 Intel Corporation.  All rights reserved.
+  -- SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+  -->
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <script type="module" src="${toolkitUri}"></script>
+    <script type="module" src="${mainUri}"></script>
+    <link rel="stylesheet" href="${styleUri}">
+    <title>New project</title>
+</head>
+
+<body>
+    <div class="box_wrapper">
+        <div class="config_form_heading">
+            <h2>Config building target</h2>
+            <vscode-divider></vscode-divider>
+        </div>
+    </div>
+
+    <div class="box_wrapper">
+        <div class="config_form_body">
+            <div>
+                <label><b>Output file name: </b></label>
+                <vscode-text-field id="output_file_name" value=${output_file_val}></vscode-text-field>
+            </div>
+            <div>
+                <label><b>Initial linear memory size: </b></label>
+                <vscode-text-field id="initial_mem_size" value=${initial_mem_size_val}></vscode-text-field>
+            </div>
+            <div>
+                <label><b>Max linear memory size: </b></label>
+                <vscode-text-field id="max_mem_size" value=${max_mem_size_val}></vscode-text-field>
+            </div>
+            <div>
+                <label><b>Stack size: </b></label>
+                <vscode-text-field id="stack_size" value=${stack_size_val}></vscode-text-field>
+            </div>
+            <div>
+                <label><b>Exported symbols: </b></label>
+                <vscode-text-area rows="3" id="exported_symbols" placeholder="Please split each symbol with comma. Like 'app_main,on_init'" value=${exported_symbols_val}></vscode-text-area>
+            </div>
+        </div>
+    </div>
+
+    <div class="box_wrapper">
+        <div class="config_form_bottom">
+            <vscode-divider></vscode-divider>
+            <div class="config_submit_btn_wrapper">
+                <div></div>
+                <div id="btn">
+                    <vscode-button id="btn_submit"><b>Modify</b></vscode-buton>
+                </div>
+            </div>
+        </div>
+    </div>
+
+</body>
+</html>

+ 55 - 0
test-tools/wamr-ide/VSCode-Extension/resource/webview/page/newProject.html

@@ -0,0 +1,55 @@
+<!--
+  -- Copyright (C) 2019 Intel Corporation.  All rights reserved.
+  -- SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+  -->
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <script type="module" src="${toolkitUri}"></script>
+    <script type="module" src="${mainUri}"></script>
+    <link rel="stylesheet" href="${styleUri}">
+    <title>Create project</title>
+</head>
+
+<body>
+        <div class="box_wrapper">
+            <div class="form_heading">
+                <h2>Create project</h2>
+                <vscode-divider class="divider_wrapper"></vscode-divider>
+            </div>
+        </div>
+
+        <div class="box_wrapper">
+            <div class="form_body">
+                <div id="text_filed_div">
+                        <label><b>Project Name: </b></label>
+                        <vscode-text-field id="ipt_projName"></vscode-text-field>
+                </div>
+
+                <div id="select_div">
+                        <label><b>Template:</b></label>
+                        <vscode-dropdown id="select_dropdown">
+                            <vscode-option value="" selected:disabled style="display:none"></vscode-option>
+                            <vscode-option value="default">default</vscode-option>
+                        </vscode-dropdown>
+                </div>
+            </div>
+        </div>
+
+        <div class="box_wrapper">
+            <div class="form_bottom">
+                <vscode-divider></vscode-divider>
+                <div class="proj_submit_btn_wrapper">
+                    <div></div>
+                    <div id="btn">
+                        <vscode-button id="btn_submit"><b>Create</b></vscode-buton>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+</body>
+</html>

+ 65 - 0
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<vscode.DebugConfiguration>
+        | undefined = undefined;
+
+    private wasmDebugConfig!: vscode.DebugConfiguration;
+
+    public resolveDebugConfiguration():
+        | Thenable<vscode.DebugConfiguration>
+        | undefined {
+        if (!this.providerPromise) {
+            this.providerPromise = Promise.resolve(this.wasmDebugConfig);
+            return this.providerPromise;
+        }
+        return this.providerPromise;
+    }
+
+    public setDebugConfig(hostPath: string, port: number) {
+        this.port = port;
+        this.hostPath = hostPath;
+        /* linux and windows has different debug configuration */
+        if (os.platform() === 'win32') {
+            this.wasmDebugConfig = {
+                type: 'wamr-debug',
+                name: 'Attach',
+                request: 'attach',
+                ['stopOnEntry']: true,
+                ['initCommands']: ['platform select remote-linux'],
+                ['attachCommands']: [
+                    'process connect -p wasm connect://127.0.0.1:' + port + '',
+                ],
+                ['sourceMap']: [['/mnt', hostPath]],
+            };
+        } else if (os.platform() === 'linux') {
+            this.wasmDebugConfig = {
+                type: 'wamr-debug',
+                name: 'Attach',
+                request: 'attach',
+                ['stopOnEntry']: true,
+                ['attachCommands']: [
+                    'process connect -p wasm connect://127.0.0.1:' + port + '',
+                ],
+                ['sourceMap']: [['/mnt', hostPath]],
+            };
+        }
+    }
+
+    public getDebugConfig() {
+        return this.wasmDebugConfig;
+    }
+}

+ 88 - 0
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<vscode.Uri | vscode.Uri[]>;
+
+    constructor() {
+        this._eventEmiter = new vscode.EventEmitter();
+        this.onDidChangeFileDecorations = this._eventEmiter.event;
+        this.disposables.push(
+            vscode.window.registerFileDecorationProvider(this)
+        );
+    }
+
+    public provideFileDecoration(
+        uri: vscode.Uri
+    ): vscode.ProviderResult<vscode.FileDecoration> {
+        let currentPrjDir,
+            prjConfigDir,
+            configFilePath,
+            configData,
+            includePathArr = new Array(),
+            excludeFileArr = new Array(),
+            pathRelative;
+
+        /* Read include_paths and exclude_fils from the config file */
+        currentPrjDir =
+            os.platform() === 'win32'
+                ? (vscode.workspace.workspaceFolders?.[0].uri.fsPath as string)
+                : os.platform() === 'linux'
+                ? (currentPrjDir = vscode.workspace.workspaceFolders?.[0].uri
+                      .path as string)
+                : '';
+
+        pathRelative = (uri.fsPath ? uri.fsPath : uri.toString()).replace(
+            currentPrjDir,
+            '..'
+        );
+
+        prjConfigDir = path.join(currentPrjDir, '.wamr');
+        configFilePath = path.join(prjConfigDir, 'compilation_config.json');
+        if (ReadFromFile(configFilePath) !== '') {
+            configData = JSON.parse(ReadFromFile(configFilePath));
+            includePathArr = configData['include_paths'];
+            excludeFileArr = configData['exclude_files'];
+
+            if (includePathArr.indexOf(pathRelative) > -1) {
+                return DECORATION_INCLUDE_PATHS;
+            } else if (excludeFileArr.indexOf(pathRelative) > -1) {
+                return DECORATION_EXCLUDE_FILES;
+            }
+        }
+    }
+
+    public dispose(): void {
+        this.disposables.forEach(d => d.dispose());
+    }
+
+    public updateDecorationsForSource(uri: vscode.Uri): void {
+        this._eventEmiter.fire(uri);
+    }
+}
+
+export const decorationProvider: DecorationProvider = new DecorationProvider();

+ 597 - 0
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);
+    }
+}

+ 153 - 0
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<string, string>,
+        public _script: Map<string, string>
+    ) {}
+
+    buildShellOption: OwnShellOption | undefined;
+    runShellOption: OwnShellOption | undefined;
+    debugShellOption: OwnShellOption | undefined;
+
+    private wasmPromise: Thenable<vscode.Task[]> | undefined = undefined;
+
+    public provideTasks(): Thenable<vscode.Task[]> | undefined {
+        let targetName =
+            TargetConfigPanel.BUILD_ARGS.output_file_name.split('.')[0];
+
+        if (os.platform() === 'linux') {
+            /* build */
+            this.buildShellOption = {
+                cmd: 'bash',
+                options: {
+                    executable: this._script.get('buildScript'),
+                    shellArgs: [targetName],
+                },
+            };
+
+            /* debug */
+            this.debugShellOption = {
+                cmd: 'bash',
+                options: {
+                    executable: this._script.get('debugScript'),
+                    shellArgs: [targetName],
+                },
+            };
+
+            /* run */
+            this.runShellOption = {
+                cmd: 'bash',
+                options: {
+                    executable: this._script.get('runScript'),
+                    shellArgs: [targetName],
+                },
+            };
+        } else if (os.platform() === 'win32') {
+            this.buildShellOption = {
+                cmd: this._script.get('buildScript') as string,
+                options: {
+                    executable: this._script.get('buildScript'),
+                    shellArgs: [targetName],
+                },
+            };
+            /* debug */
+            this.debugShellOption = {
+                cmd: this._script.get('debugScript') as string,
+                options: {
+                    executable: this._script.get('debugScript'),
+                    shellArgs: [targetName],
+                },
+            };
+            /* run */
+            this.runShellOption = {
+                cmd: this._script.get('runScript') as string,
+                options: {
+                    executable: this._script.get('runScript'),
+                    shellArgs: [targetName],
+                },
+            };
+        } else {
+            this.buildShellOption = {
+                cmd: "echo 'os platform is not supported yet'",
+                options: {},
+            };
+
+            this.debugShellOption = {
+                cmd: "echo 'os platform is not supported yet'",
+                options: {},
+            };
+
+            this.runShellOption = {
+                cmd: "echo 'os platform is not supported yet'",
+                options: {},
+            };
+        }
+
+        this.wasmPromise = Promise.resolve([
+            new vscode.Task(
+                { type: 'wasm' },
+                vscode.TaskScope.Workspace,
+                'Wasm',
+                this._type.get('Build') as string,
+                new vscode.ShellExecution(
+                    this.buildShellOption.cmd,
+                    this.buildShellOption.options
+                )
+            ),
+
+            new vscode.Task(
+                { type: 'wasm' },
+                vscode.TaskScope.Workspace,
+                'Wasm',
+                this._type.get('Run') as string,
+                new vscode.ShellExecution(
+                    this.runShellOption.cmd,
+                    this.runShellOption.options
+                )
+            ),
+
+            new vscode.Task(
+                { type: 'wasm' },
+                vscode.TaskScope.Workspace,
+                'Wasm',
+                this._type.get('Debug') as string,
+                new vscode.ShellExecution(
+                    this.debugShellOption.cmd,
+                    this.debugShellOption.options
+                )
+            ),
+        ]);
+        return this.wasmPromise;
+    }
+
+    /**
+     * if the task or task in tasks.json does not set command, `
+     * resolveTask` will be invoked,
+     * otherwise, `provideTasks` will be invoked
+     * @param _task
+     * @returns
+     */
+    public resolveTask(_task: vscode.Task): vscode.Task | undefined {
+        return undefined;
+    }
+}

+ 83 - 0
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;
+    }
+}

+ 14 - 0
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));
+}

+ 253 - 0
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();
+            }
+        }
+    }
+}

+ 260 - 0
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();
+            }
+        }
+    }
+}

+ 21 - 0
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"
+	]
+}

+ 32 - 0
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/

+ 15 - 0
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.

+ 8 - 0
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

+ 8 - 0
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

+ 6 - 0
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

+ 6 - 0
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

+ 4 - 0
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

+ 63 - 0
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

+ 71 - 0
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
+```

+ 12 - 0
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

+ 10 - 0
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

+ 24 - 0
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

+ 16 - 0
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

+ 15 - 0
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