diff --git a/.vscode/launch.json b/.vscode/launch.json index 7e6a37bf..8111b4ae 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,42 +1,42 @@ { "configurations": [ - { - "name": "(gdb) Launch twr-wasm unit tests", - "type": "cppdbg", - "request": "launch", - "program": "${workspaceFolder}/source/unit-test/out/test.exe", - "args": [], - "stopAtEntry": false, - "cwd": "${workspaceFolder}/source/unit-test/out/", - "environment": [], - "externalConsole": false, - "MIMode": "gdb", - "miDebuggerPath": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - }, - { - "description": "Set Disassembly Flavor to Intel", - "text": "-gdb-set disassembly-flavor intel", - "ignoreFailures": true - } - ] - }, - { - "name": "Examples", - "type": "chrome", - "request": "launch", - "runtimeArgs": [ - "--allow-file-access-from-files", - "--autoplay-policy=no-user-gesture-required", - "--enable-features=SharedArrayBuffer" - ], - "file": "${workspaceFolder}/examples/index.html", - "cwd": "${workspaceFolder}/examples/" - } + { + "name": "Examples", + "type": "chrome", + "request": "launch", + "runtimeArgs": [ + "--allow-file-access-from-files", + "--autoplay-policy=no-user-gesture-required", + "--enable-features=SharedArrayBuffer" + ], + "file": "${workspaceFolder}/examples/index.html", + "cwd": "${workspaceFolder}/examples/" + }, + { + "name": "(gdb) Launch twr-wasm unit tests", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/source/unit-test/out/test.exe", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}/source/unit-test/out/", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "miDebuggerPath": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Set Disassembly Flavor to Intel", + "text": "-gdb-set disassembly-flavor intel", + "ignoreFailures": true + } + ] + }, ], "version": "2.0.0" } \ No newline at end of file diff --git a/docs/examples/examples-overview.md b/docs/examples/examples-overview.md index 9f7f604c..1cb38bbd 100644 --- a/docs/examples/examples-overview.md +++ b/docs/examples/examples-overview.md @@ -48,13 +48,13 @@ These examples are a good place to learn how to configure clang and wasm-ld to c | tests-user | "cli" for tests using libc++ and `` | [tests-user](/examples/dist/tests-user/index.html) | | tests-libcxx | Smoke test for libc++. Shows how to use libc++. | [tests-libcxx](examples-libcxx.md) | -## Running the examples locally -To run the examples locally: +## Running or Building the examples locally +Online versions of the examples [can be viewed here.](https://twiddlingbits.dev/examples/dist/index.html) -- [clone the twr-wasm repo](../gettingstarted/installation.md#git-install) -- then from a shell with the repo root as the current directory, execute `python examples\server.py`. This small python script is a local http server that also [sets the needed cors headers](../more/production.md) -- http://localhost:8000/examples/ +You can also run the [examples locally, or build them.](https://github.com/twiddlingbits/twr-wasm/blob/main/examples/readme.md). -## Building the Examples +## Copying Examples to Start your own Project +All of the examples have makefiles that use a relative path for `twr.a` and `includes`. These paths will work fine if your code is in an examples sub-folder as a peer to the other examples. But assuming your code is in your own project folder elsewhere, you will need to determine the correct path to `twr.a` and `includes` for your project's makefile. Details on how to do this can be found in the following sections: [Hello World walk through](../gettingstarted/helloworld.md) and the [Compiler and Linker Options section](../gettingstarted/compiler-opts.md). + +Also see the section on [Import Resolution](../more/imports.md) if you installed with `git clone.` -See [Example Readme](https://github.com/twiddlingbits/twr-wasm/blob/main/examples/readme.md) for more information on building and running the examples. diff --git a/docs/gettingstarted/debugging.md b/docs/gettingstarted/debugging.md index 5d67feb1..e18bff38 100644 --- a/docs/gettingstarted/debugging.md +++ b/docs/gettingstarted/debugging.md @@ -25,6 +25,9 @@ In order to enable C/C++ source debugging with Wasm and clang, do the following: - you need to ensure that the web server/browser can find the source code - also see [Example Readme](https://github.com/twiddlingbits/twr-wasm/blob/main/examples/readme.md) +## Resolving Imports +If you are having issues with import resolution, [see this section.](../more/imports.md) + ## Useful twr-wasm Debug Functions Use `twr_conlog` to print to the JavaScript console from C (see API ref section). ~~~c diff --git a/docs/gettingstarted/helloworld.md b/docs/gettingstarted/helloworld.md index 1faf9821..54b288f1 100644 --- a/docs/gettingstarted/helloworld.md +++ b/docs/gettingstarted/helloworld.md @@ -84,6 +84,8 @@ This example uses Import Maps, which are used when **not** using a bundler like The path in the `importmap` section of `index.html` should point to the location where you installed `twr-wasm/lib-js`. The path above is correct for this project example with the indicated folder structure. +[For more detail on import resolution see this section.](../more/imports.md) + ## Step 3: Compile your C code to create your .wasm file ~~~sh cd hello-proj @@ -177,7 +179,7 @@ You can find a live link to hello world [on this page](../examples/examples-over ## Next steps after hello world A good way to get your own code up and running is to copy one of the [examples](../examples/examples-overview.md), get it to build and run, then start modifying it. Note you will need to modify the paths for `include`, `lib-js`, `lib-c`, etc. based on your project structure. The examples are all setup with relative paths assuming the folder structure `twr-wasm\examples\` -The examples include MakeFiles. +The examples include Makefiles. "Hello World" uses the twr-wasm class `twrWasmModule`. If you wish to use C blocking functions, such as `twr_getc32` or `twr_sleep`, you should use `twrWasmModuleAsync`. This [square calculator example](../examples/examples-divcon.md) shows how to do this. diff --git a/docs/gettingstarted/installation.md b/docs/gettingstarted/installation.md index f2717dfa..8de49b54 100644 --- a/docs/gettingstarted/installation.md +++ b/docs/gettingstarted/installation.md @@ -75,11 +75,19 @@ The [FFT example](../examples/examples-fft.md) uses the `paths` entry in the `ts The paths for `alias` and `paths` shown above are correct for the included examples, but will likely need to be adjust for your project. -## Note on Examples -All of the [examples](../examples/examples-overview.md) have makefiles that use a relative path for `twr.a` and `includes`. These paths will work fine if your code is in an examples sub-folder as a peer to the other examples. But assuming your code is in your own project folder elsewhere, you will need to determine the correct path to `twr.a` and `includes` for your project's makefile. Details on how to do this can be found in the following sections: [Hello World walk through](../gettingstarted/helloworld.md) and the [Compiler and Linker Options section](../gettingstarted/compiler-opts.md). +For more details [see this section on Import Resolution](../more/imports.md) ## clang and wasm-ld To build C/C++ code for use in your Wasm project, you will need to install clang and the wasm-ld linker. If you are using Windows, more details can be found at [the end of the Building Source section.](../more/building.md) -## python -To use the included `examples\server.py` you will need to install python. server.py is a simple HTTP server for local testing that sets the [correct CORS headers](../more/production.md) for `twrWasmModuleAsync`. As explained in the following Hello World walk through, you can alternately execute HTML files directly using VS Code and Chrome. +## python and more +To use the included `examples\server.py` to execute your project you will need to install python. `server.py` is a simple HTTP server for local testing that sets the [correct CORS headers](../more/production.md) for `twrWasmModuleAsync`. As explained in the Hello World walk through, you can alternately execute HTML files directly using VS Code and Chrome. + +You will likely want these tools installed to use twr-wasm: + +- gnu make (all the examples use make) +- VS Code (not required, but the repo includes VS Code launch.json, etc) +- TypeScript (not required, but the twr-wasm source code is TypeScript) + +## Note on Examples +[You can run the examples](../examples/examples-overview.md) either locally or with the online versions. diff --git a/docs/gettingstarted/stdio.md b/docs/gettingstarted/stdio.md index d6d79f48..0f4f8370 100644 --- a/docs/gettingstarted/stdio.md +++ b/docs/gettingstarted/stdio.md @@ -1,6 +1,6 @@ --- -title: Consoles (stdio, stderr, more) with C/C++ WebAssembly -description: Stream characters to a div or canvas tag. Likewise input from stdin. Configure a canvas tag as a terminal-console. With twr-wasm lib. +title: Consoles with C/C++ WebAssembly (stdio, stderr, more) +description: Stream characters to a div or canvas tag. Input from stdin. Configure a canvas tag as a terminal-console. With twr-wasm lib. --- # Consoles with C/C++ WebAssembly
stdio, stderr, and more diff --git a/docs/index.md b/docs/index.md index 40e794e6..42896325 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,16 +1,20 @@ --- -title: Learn WebAssembly with twr-wasm - Documentation and Examples +title: Easier WebAssembly with twr-wasm - Documentation and Examples description: An easier way to create C/C++ WebAssembly. Unlike emscripten, use clang directly. Examples of blocking functions, 2D drawing, char I/O with
tag, etc. --- -# Learn WebAssembly with twr-wasm
Documentation and Examples +# Easier WebAssembly with twr-wasm
Documentation and Examples ## Easier C/C++ WebAssembly Version 2.4.2 twr-wasm is a simple, lightweight and easy to use library for building C/C++ WebAssembly code directly with clang. It solves some common use cases with less work than the more feature rich emscripten. -twr-wasm is easy to understand, and has some great features. You can call blocking functions. You can input and print streaming character i/o to a `
` tag, use a `` element as an terminal, and use 2D drawing apis (that are compatible with JavaScript Canvas APIs) to draw to a `` element. +twr-wasm includes comprehensive console support for `stdio`. You can input and print to a `
` tag, or use a `` element as an terminal. + +twr-wasm makes it easy to `await` on blocking C/C++ functions. + +twr-wasm makes it easy to use C/C++ 2D drawing apis that are compatible with JavaScript Canvas APIs to draw to a `` element. twr-wasm allows you to run C/C++ code in a web browser. Legacy code, libraries, full applications, or single functions can be integrated with JavaScript and TypeScript. @@ -20,12 +24,11 @@ twr-wasm is designed to be used with the standard llvm clang compiler and tools. | Name | View Live Link | Source Link | | --------- | ------------ | ----------- | -| Bouncing Balls (C++) | [View bouncing balls](/examples/dist/balls/index.html) | [Source for balls](https://github.com/twiddlingbits/twr-wasm/tree/main/examples/balls) | -| Pong (C++) | [View Pong](/examples/dist/pong/index.html) | [Source for Pong](https://github.com/twiddlingbits/twr-wasm/tree/main/examples/pong) | -| Maze Gen/Solve (Win32 C Port) | [View live maze](/examples/dist/maze/index.html) | [Source for maze](https://github.com/twiddlingbits/twr-wasm/tree/main/examples/maze) | -| Input/Output with `
` | [View square demo](/examples/dist/divcon/index.html) | [Source](https://github.com/twiddlingbits/twr-wasm/tree/main/examples/divcon) | -|Mini-Terminal (hello world using ``)|[View demo](/examples/dist/terminal/index.html) |[Source](https://github.com/twiddlingbits/twr-wasm/tree/main/examples/terminal) | -|CLI using libc++ and ``)| [View console](/examples/dist/tests-user/index.html) | [Source](https://github.com/twiddlingbits/twr-wasm/tree/main/examples/tests-user) | +| Bouncing Balls (C++) | [View bouncing balls](https://twiddlingbits.dev/examples/dist/balls/index.html) | [Source for balls](https://github.com/twiddlingbits/twr-wasm/tree/main/examples/balls) | +| Maze Gen/Solve (Win32 C Port) | [View live maze](https://twiddlingbits.dev/examples/dist/maze/index.html) | [Source for maze](https://github.com/twiddlingbits/twr-wasm/tree/main/examples/maze) | +| Input/Output with `
` | [View square demo](https://twiddlingbits.dev/examples/dist/divcon/index.html) | [Source](https://github.com/twiddlingbits/twr-wasm/tree/main/examples/divcon) | +|I/O to terminal with ``|[View demo](https://twiddlingbits.dev/examples/dist/terminal/index.html) |[Source](https://github.com/twiddlingbits/twr-wasm/tree/main/examples/terminal) | +|CLI using libc++ and ``)| [View console](https://twiddlingbits.dev/examples/dist/tests-user/index.html) | [Source](https://github.com/twiddlingbits/twr-wasm/tree/main/examples/tests-user) | ## Key Features - compile and link C/C++ for use with WebAssembly using clang directly diff --git a/docs/more/imports.md b/docs/more/imports.md new file mode 100644 index 00000000..9dc5e7da --- /dev/null +++ b/docs/more/imports.md @@ -0,0 +1,59 @@ +--- +title: Resolving Import Statements +description: How tools like VS Code, the Parcel bundler, and Web browser's resolve import statements +--- + +# twr-wasm Import Resolution +This section covers path resolution for statements like this: +~~~ +import {twrWasmModule} from "twr-wasm"; +~~~ + +It can be confusing to determine how tools like VS Code, a bundler, or a Web Browser resolve imports like "twr-wasm". This section explains how it works, using the included examples as examples. + +If you have installed `twr-wasm` using `npm`, most tools will automatically resolve imports by finding the `node_modules` folder. + +However, if you installed using `git clone`, then other steps will need to be taken. The examples are in the git repo tree, and as a result there may be no `node_modules` for the twr-wasm libraries. This will also be the case for your project, if you installed with `git clone`. + +## Import path resolution by the bundler +A bundler will find the twr-wasm library using one of these methods: + +1. If twr-wasm has been installed with npm install, the bundler will find the `node_modules` folder +2. Alternately, If all your scripts are in TypeScript, use `paths` entry in `tsconfig.json` (see maze example) +3. Alternately, use alias option in package.json as in the helloworld example +~~~ + "alias": { + "twr-wasm": "../../lib-js/index.js" + }, +~~~ + +In the examples, the alias entry in the `package.json` exists so that the parcel bundler can find twr-wasm. + +If you are using a bundler, you don't need to add a ` +~~~ + +## Import resolution by VS Code and tsc +VS Code Intellisense and the typescript compiler need to find modules. If twr-wasm is installed using `npm` into a `node_modules` folder, this is probably automatic. But if this is not the case, you can add a line to the `tsconfig.json` as follows (this example assumes the `tsconfig.json` is in a examples/example folder). See the maze example. +~~~ +"paths": { + "twr-wasm": ["./../../lib-js/index"] +} +~~~ + + + + + diff --git a/examples/readme.md b/examples/readme.md index c8fdac4a..f551e1d7 100644 --- a/examples/readme.md +++ b/examples/readme.md @@ -1,17 +1,43 @@ # Examples -These examples demonstrate many of the features of twr-wasm. +These examples demonstrate the features of twr-wasm. -The examples will run without building using chrome and a file:// URL. The file "index.html" can be loaded to provide easy access to each example. If you have downloaded the source from github, and you are using VS Code, there is a launch.json entry to run the examples this way. You access it in the VS Code "run and debug" left-hand nav bar, then select it from the drop down at the top. If you are going to run Chrome from the shell, see the section below on some of the flags you will need to set. +These examples are running live here: https://twiddlingbits.dev/examples/dist/index.html -When using bundled examples with a local web server, because of the use of Shared Array Buffers, certain HTTP headers must be set -- see below and the included server.py script. +# Run Examples locally with pre-build `.wasm` +Each example incudes the built `.wasm` file in its folder, allowing you to execute the "unbundled version" of the examples without rebuilding. The `index.html` file in the examples root contains links to each example. -# Prerequisites +## Execute examples with local web server +When executing the examples with a local web server, because of the use of Shared Array Buffers, certain HTTP headers must be set. If you use the included `server.py` to create a local web server, these headers are set. + +To execute the examples: +~~~ +cd +python examples/server.py +~~~ + +then in your browser: + +~~~ +http://localhost:8000/examples/ +~~~ + +Note: Only the "unbundled" version of the examples are available if you don't build the examples. + +Note: You must run `python` from the twr-wasm root. + +## Execute Examples using Chrome without a local web server +An alternative and simple way to run the examples locally without using a local web server is to use the included VS Code `launch.json`. This file is not included if you install with `npm`. To access this file, you should [install using git clone](https://twiddlingbits.dev/docsite/gettingstarted/installation/). Then from VS Code, select "Run and Debug" in the left menu, and use the "start debugging" button at the top. + +The examples will run without building using chrome and a file:// URL. The file "index.html" can be loaded to provide links to each example. If you are going to run Chrome yourself from a shell, see the section below on some of the Chrome flags you will need to set. + +# Building the examples +## Prerequisites - Ensure clang and wasm-ld are installed - Ensure a version of gnu make is installed (to use the Makefiles). - the examples use parcel v2 as a bundler - to run the examples on your local machine using the provided server script (server.py), you need to install python. This script sets certain CORS headers needed by SharedArrayBuffer, that are not usually set using other dev servers. -# Build and execute the examples with a local http server +## Build and execute the examples with a local http server ~~~ cd examples @@ -31,7 +57,7 @@ then in your browser: http://localhost:8000/examples/ ~~~ -## Build and execute the examples without a http server +## Build and execute the examples without an http server ~~~ cd examples @@ -47,54 +73,11 @@ start "chrome" "--allow-file-access-from-files --autoplay-policy=no-user-gesture Ensure no chrome windows are open prior to running above. Otherwise, the file will open in an existing chrome instance without setting the flags. -# package.json -The 'alias' entry in package.json is only needed if using the bundler and twr-wasm is not installed in a node_modules folder (as is the case with these examples), and if tsconfig.json is not used (the maze and fft examples use tsconfig.json) - -# twr-wasm Import Resolution -This section covers path resolution for statements like this: -~~~ -import {twrWasmModule} from "twr-wasm"; -~~~ - -## import path resolution by the browser -This section apples to executing your javascript without first "bundling" it. Either from the filesystem directly in a browser or using a web server. - -In order for the browser to locate the twr-wasm path when import is used, you can add code like this to your HTML prior to the import. You should make sure the paths are correct. -~~~ - -~~~ - -## VS Code and tsc resolution -VS Code Intellisense and the typescript compiler need to find modules. If twr-wasm is installed using npm into a node_modules folder, this is probably automatic. But in these examples, we don't do that, and so, we added a line to the tsconfig.json as follows (this example assumes the tsconfig.json is in a examples/example folder) -~~~ -"paths": { - "twr-wasm": ["./../../lib-js/index"] -} -~~~ - -## Using the Parcel v2 bundler -If you are using a bundler, you don't need to add a \