Skip to content

Commit 47f83c9

Browse files
committed
WIP: docs(hello-world): updates
1 parent a473cb9 commit 47f83c9

File tree

12 files changed

+457
-203
lines changed

12 files changed

+457
-203
lines changed

docs/cxx/tutorial/hello_world.md

Lines changed: 187 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -1,158 +1,187 @@
1-
# Hello Wasm World!
2-
3-
## Introduction
4-
5-
This example walks through how to compile a *hello world* executable written in C++ to [WebAssembly](https://webassembly.org/) and how to execute it with standalone WebAssembly runtimes, the Node.js JavaScript runtime, and web browser runtimes!
6-
7-
Before getting started, make sure [Node.js](https://nodejs.org/en/download/) and [Podman (recommended)](https://podman.io/docs/installation) or [Docker](https://docs.docker.com/install/) are installed. On Linux, make sure you can run [`podman` or `docker` without `sudo`](https://askubuntu.com/questions/477551/how-can-i-use-docker-without-sudo). On Windows, we highly recommend [Podman](https://podman.io/docs/installation).
8-
9-
While we recommend following along step-by-step, the complete example can also be found in the [`examples/` directory of the project repository](https://github.com/InsightSoftwareConsortium/ITK-Wasm/tree/main/examples/hello-world).
10-
11-
Let's get started! 🚀
12-
13-
## Write the code
14-
15-
First, let's create a new directory to house our project.
16-
17-
```sh
18-
mkdir HelloWorld
19-
cd HelloWorld
20-
```
21-
22-
Let's write some code! Populate *hello.cxx* with our Hello World program:
23-
24-
```cpp
25-
#include <iostream>
26-
27-
int main() {
28-
std::cout << "Hello Wasm world!" << std::endl;
29-
return 0;
30-
}
31-
```
32-
33-
Next, provide a [CMake](https://cmake.org/) build configuration at *CMakeLists.txt*:
34-
35-
```cmake
36-
cmake_minimum_required(VERSION 3.16)
37-
project(HelloWorld)
38-
39-
add_executable(hello hello.cxx)
40-
```
41-
42-
## Install itk-wasm
43-
44-
We use the `add_executable` command to build executables with itk-wasm. The [Emscripten](https://kripken.github.io/emscripten-site/) and [WASI](https://github.com/WebAssembly/wasi-sdk) toolchains along with itk-wasm build and execution configurations are contained in itk-wasm [dockcross](https://github.com/dockcross/dockcross) Docker images invoked by the itk-wasm command line interface (CLI). Note that the same code can also be built and tested with native operating system toolchains. This is useful for development and debugging.
45-
46-
Build the program with the itk-wasm CLI, `itk-wasm`. This is shipped with the `itk-wasm` Node.js package. First install *itk-wasm* with the Node Package Manager, `npm`, the CLI that ships with Node.js.
47-
48-
```sh
49-
# Initialize an empty project in the current directory
50-
npm init --yes
51-
npm install itk-wasm@1.0.0-b.106
52-
```
53-
54-
## WASI
55-
56-
Build the project with the WASI `itkwasm/wasi` toolchain in the `./wasi-build/` directory:
57-
58-
```sh
59-
npx itk-wasm -i itkwasm/wasi build
60-
```
61-
62-
A `hello.wasi.wasm` WebAssembly binary is built in the `./wasi-build/` directory.
63-
64-
```sh
65-
❯ ls wasi-build
66-
build.ninja CMakeFiles libwasi-exception-shim.a
67-
cmake_install.cmake hello.wasi.wasm
68-
```
69-
70-
Execute the binary with the `run` `itk-wasm` subcommand.
71-
72-
```sh
73-
❯ npx itk-wasm run wasi-build/hello.wasi.wasm
74-
Hello Wasm world!
75-
```
76-
77-
Congratulations! You just executed a C++ program compiled to WebAssembly. 🎉
78-
79-
The binary can also be executed with other [WASI runtimes](https://github.com/mbasso/awesome-wasm#non-web-embeddings).
80-
81-
## Node.js
82-
83-
For Node.js or the Browser, build the project with the default [Emscripten](https://emscripten.org/) toolchain. The project is built in the `./emscripten-build` directory by default.
84-
85-
```sh
86-
npx itk-wasm build
87-
```
88-
89-
To execute the project, create an `index.mjs` JavaScript file to [invoke the module](../api/node_pipelines.html):
90-
91-
```js
92-
import path from 'path'
93-
import { runPipelineNode } from 'itk-wasm'
94-
95-
const pipelinePath = path.resolve('emscripten-build', 'hello')
96-
const args = []
97-
await runPipelineNode(pipelinePath, args)
98-
```
99-
100-
**Important**: Inside the *package.json* file, we must also add `"type": "module",` to tell Node.js that we have a modern JavaScript project that uses [ES modules](https://nodejs.org/api/esm.html#modules-ecmascript-modules).
101-
102-
And run it!
103-
104-
```sh
105-
❯ npx node ./index.mjs
106-
Hello Wasm world!
107-
```
108-
109-
Congratulations! You just executed a C++ program in JavaScript. 🎉
110-
111-
## Browser
112-
113-
The same Emscripten Wasm module can be executed in a web browser.
114-
115-
Create an HTML file named `index.html` that will call the Wasm module through JavaScript and display its output in the HTML DOM:
116-
117-
```html
118-
<!DOCTYPE html>
119-
<html>
120-
<head>
121-
<title>itk-wasm Browser Hello World!</title>
122-
<meta charset="UTF-8" />
123-
<script src="https://cdn.jsdelivr.net/npm/itk-wasm@1.0.0-b.106/dist/umd/itk-wasm.min.js"></script>
124-
</head>
125-
126-
<body>
127-
<textarea readonly>WebAssembly output...</textarea>
128-
129-
<script>
130-
const outputTextArea = document.querySelector("textarea");
131-
outputTextArea.textContent = "Loading...";
132-
133-
const wasmURL = new URL('emscripten-build/hello', document.location)
134-
const args = []
135-
const inputs = null
136-
const outputs = null
137-
itk.runPipeline(null, wasmURL, args, inputs, outputs).then(
138-
({ stdout, webWorker }) => {
139-
webWorker.terminate()
140-
outputTextArea.textContent = stdout
141-
})
142-
</script>
143-
</body>
144-
</html>
145-
```
146-
147-
Serve the web page and Wasm module with an http server:
148-
149-
```sh
150-
npm install http-server
151-
http-server .
152-
```
153-
154-
And point your browser to `http://127.0.0.1:8080/`.
155-
156-
![Hello Wasm World!](/_static/tutorial/hello_wasm_world.png)
157-
158-
Congratulations! You just executed a C++ program in your web browser. 🎉
1+
# Hello Wasm World!
2+
3+
## Introduction
4+
5+
This example walks through how to compile a *hello world* executable written in C++ to [WebAssembly](https://webassembly.org/) and how to execute it with standalone WebAssembly runtimes, the Node.js JavaScript runtime, and web browser runtimes!
6+
7+
**Updated for create-itk-wasm**: This tutorial now demonstrates the modern ITK-Wasm development workflow using the `create-itk-wasm` CLI tool, which provides a complete development environment with automated build configurations, testing infrastructure, and language binding generation.
8+
9+
Before getting started, make sure [Node.js](https://nodejs.org/en/download/) and [Docker](https://docs.docker.com/install/) or [Podman](https://podman.io/docs/installation) are installed. On Linux, make sure you can run [`docker` without `sudo`](https://askubuntu.com/questions/477551/how-can-i-use-docker-without-sudo).
10+
11+
While we recommend following along step-by-step, the complete example can also be found in the [`examples/` directory of the project repository](https://github.com/InsightSoftwareConsortium/ITK-Wasm/tree/main/examples/hello-world).
12+
13+
Let's get started! 🚀
14+
15+
## Create the project
16+
17+
The easiest way to get started with ITK-Wasm is using the `create-itk-wasm` CLI tool, which scaffolds a complete development environment with all necessary build configurations and toolchains.
18+
19+
First, make sure [Node.js](https://nodejs.org/en/download/) and [Docker](https://docs.docker.com/install/) or [Podman](https://podman.io/docs/installation) are installed. On Linux, make sure you can run [`docker` without `sudo`](https://askubuntu.com/questions/477551/how-can-i-use-docker-without-sudo).
20+
21+
Create a new project:
22+
23+
```sh
24+
npx create-itk-wasm hello-world
25+
cd hello-world
26+
```
27+
28+
This creates a complete project structure with:
29+
- **Native C++ build** - Traditional compiled executables for development and testing
30+
- **Emscripten toolchain** - WebAssembly compilation for browser environments
31+
- **WASI toolchain** - WebAssembly System Interface for server-side execution
32+
- **Language bindings** - Automatic TypeScript and Python wrapper generation
33+
- **Testing infrastructure** - Example tests for all target platforms
34+
35+
## Write the code
36+
37+
The `create-itk-wasm` tool generates a pipeline template. Let's modify it to create our Hello World program. Edit the generated C++ file in the pipeline directory (e.g., `hello-world/hello-world.cxx`):
38+
39+
```cpp
40+
#include "itkPipeline.h"
41+
#include "itkOutputTextStream.h"
42+
#include <iostream>
43+
44+
int main(int argc, char * argv[])
45+
{
46+
itk::wasm::Pipeline pipeline("hello", "A simple hello world pipeline", argc, argv);
47+
48+
// Add an optional message parameter
49+
std::string message = "Hello Wasm world!";
50+
pipeline.add_option("--message", message, "Message to display");
51+
52+
// Add text output for the message
53+
itk::wasm::OutputTextStream textOutput;
54+
pipeline.add_option("text-output", textOutput, "Text output")->required()->type_name("OUTPUT_TEXT");
55+
56+
ITK_WASM_PARSE(pipeline);
57+
58+
// Output the message to both stdout and the text output stream
59+
std::cout << message << std::endl;
60+
61+
textOutput.Get() << message << std::endl;
62+
63+
return EXIT_SUCCESS;
64+
}
65+
```
66+
67+
The ITK-Wasm pipeline structure provides:
68+
- **CLI11 integration** for robust command-line argument parsing
69+
- **Standardized I/O** through the `itk::wasm::Pipeline` interface
70+
- **Cross-platform compatibility** with the same code running natively and in WebAssembly
71+
72+
## Project structure
73+
74+
The `create-itk-wasm` tool generates a complete project structure:
75+
76+
```
77+
hello-world/
78+
├── pixi.toml # Pixi environment and task configuration
79+
├── package.json # Node.js dependencies and scripts
80+
├── CMakeLists.txt # Main CMake configuration
81+
├── hello/ # Pipeline directory
82+
│ ├── hello.cxx # Pipeline C++ source code
83+
│ └── CMakeLists.txt # Pipeline-specific CMake config
84+
├── tests/ # Test files
85+
├── index.html # Browser demo page
86+
├── index.mjs # Node.js example
87+
└── README.md # Project documentation
88+
```
89+
90+
This structure supports:
91+
- **Multiple pipelines** - Add more pipelines as subdirectories
92+
- **Automatic binding generation** - TypeScript and Python wrappers are generated
93+
- **Comprehensive testing** - Native, WASI, Node.js, and browser tests
94+
- **Modern tooling** - Pixi for dependency management, pnpm for JavaScript packages
95+
96+
## Build and run
97+
98+
The generated project includes [pixi](https://pixi.sh/) for seamless dependency management and build orchestration. Pixi handles the installation of all required toolchains and provides consistent commands across platforms.
99+
100+
### WASI
101+
102+
Build and test the WASI WebAssembly binary:
103+
104+
```sh
105+
pixi run build:wasi
106+
pixi run test:wasi
107+
```
108+
109+
This creates a `hello.wasi.wasm` binary that can be executed with WASI runtimes.
110+
111+
```sh
112+
❯ pixi run test:wasi
113+
Hello Wasm world!
114+
```
115+
116+
## Next steps
117+
118+
Now that you have a working ITK-Wasm pipeline, you can:
119+
120+
1. **Add more functionality** - Modify the C++ code to perform image processing, analysis, or other computational tasks
121+
2. **Add inputs and outputs** - Use `create-itk-wasm` again to add more pipelines or modify the existing one to handle images, meshes, or other data types
122+
3. **Integrate with your application** - Use the generated TypeScript or Python bindings to integrate your pipeline into web applications, desktop software, or data analysis workflows
123+
4. **Publish your package** - Share your pipeline with the community by publishing it as an npm package or Python package
124+
125+
For more advanced examples and comprehensive documentation, visit [wasm.itk.org](https://wasm.itk.org).
126+
127+
Consider adding your project to the [ITK-Wasm packages list](https://wasm.itk.org/en/latest/introduction/packages.html) to help others discover your work!
128+
129+
The binary can also be executed with other [WASI runtimes](https://github.com/mbasso/awesome-wasm#non-web-embeddings).
130+
131+
## Node.js
132+
133+
Build and test with Node.js:
134+
135+
```sh
136+
pixi run build:emscripten
137+
pixi run test:node
138+
```
139+
140+
This builds the Emscripten WebAssembly module and tests it in Node.js using the generated TypeScript bindings.
141+
142+
```sh
143+
❯ pixi run test:node
144+
Hello Wasm world!
145+
```
146+
147+
The `create-itk-wasm` tool automatically generates TypeScript bindings that provide a clean, type-safe API for calling your pipeline from JavaScript/TypeScript.
148+
149+
## Browser
150+
151+
The same Emscripten WebAssembly module can be executed in a web browser using the generated web examples.
152+
153+
Start the development server:
154+
155+
```sh
156+
pixi run start
157+
```
158+
159+
Then open your browser to the URL shown (typically `http://localhost:8080`) to see the pipeline running in the browser.
160+
161+
![Hello Wasm World!](/_static/tutorial/hello_wasm_world.png)
162+
163+
The `create-itk-wasm` tool generates complete web examples demonstrating how to use your pipeline in browser environments.
164+
165+
## Native development
166+
167+
For development and debugging, you can also build and run the pipeline natively:
168+
169+
```sh
170+
pixi run build:native
171+
pixi run test:native
172+
```
173+
174+
This builds a traditional C++ executable that can be debugged with standard tools like `gdb` or IDE debuggers.
175+
176+
## Next steps
177+
178+
Now that you have a working ITK-Wasm pipeline, you can:
179+
180+
1. **Add more functionality** - Modify the C++ code to perform image processing, analysis, or other computational tasks
181+
2. **Add inputs and outputs** - Use `create-itk-wasm` again to add more pipelines or modify the existing one to handle images, meshes, or other data types
182+
3. **Integrate with your application** - Use the generated TypeScript or Python bindings to integrate your pipeline into web applications, desktop software, or data analysis workflows
183+
4. **Publish your package** - Share your pipeline with the community by publishing it as an npm package or Python package
184+
185+
For more advanced examples and comprehensive documentation, visit [wasm.itk.org](https://wasm.itk.org).
186+
187+
Consider adding your project to the [ITK-Wasm packages list](https://wasm.itk.org/en/latest/introduction/packages.html) to help others discover your work!

examples/hello-world/.gitignore

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,25 @@
1-
itk-wasm-hello-world
2-
wasi-build
1+
# Build directories
2+
emscripten-build/
3+
wasi-build/
4+
native-build/
5+
.pixi/
6+
7+
# Generated files
8+
typescript/
9+
python/
10+
pyodide/
11+
test-data/
12+
13+
# Dependencies
14+
node_modules/
15+
*.lock
16+
17+
# Test outputs
318
/test-results/
419
/playwright-report/
520
/blob-report/
621
/playwright/.cache/
22+
23+
# Output files
24+
*.txt
25+
*.json

examples/hello-world/CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ project(HelloWorld)
44
find_package(ITK REQUIRED COMPONENTS WebAssemblyInterface)
55
include(${ITK_USE_FILE})
66

7-
add_executable(hello hello.cxx)
8-
target_link_libraries(hello PUBLIC ${ITK_LIBRARIES})
7+
# Begin create-itk-wasm added pipelines.
8+
add_subdirectory(hello)
9+
# End create-itk-wasm added pipelines.

0 commit comments

Comments
 (0)