mirror of
https://github.com/penpot/penpot.git
synced 2026-09-30 07:46:16 +00:00
Protect shared setup, compilation, artifact copy, and target cleanup with one flock lock per checkout. Route watch builds and frontend cleanup through the protected scripts. Document the lock contract and normalize the frontend and exporter build:wasm commands. Closes #11901 AI-assisted-by: Space Bunny Free
115 lines
4.1 KiB
Markdown
115 lines
4.1 KiB
Markdown
# Penpot WASM render
|
|
|
|
This is the canvas-based WebAssembly render engine for Penpot.
|
|
|
|
## Rust & Emscripten
|
|
|
|
This project is a Rust crate that targets [Emscripten](https://emscripten.org/) (`wasm32-unknown-emscripten`).
|
|
|
|
We use `wasm32-unknown-emscripten` compilation target:
|
|
* It compiles Rust code into WASM
|
|
* It generates the JavaScript code (“glue”) to load and run the WASM code
|
|
|
|

|
|
|
|
### Skia
|
|
|
|
We use Skia, an Open Source 2D graphics library. In particular, the render engine uses Skia via [custom binaries](https://github.com/penpot/skia-binaries/releases/) of the [rust-skia crate](https://github.com/rust-skia/rust-skia).
|
|
|
|
## How to build
|
|
|
|
With the [Penpot Development Environment](https://help.penpot.app/technical-guide/developer/devenv/) running, create a new tab in the tmux.
|
|
|
|
```sh
|
|
cd penpot/render-wasm
|
|
./build
|
|
```
|
|
|
|
You can also use `./watch` to run the build on every change.
|
|
|
|
The build script compiles the project and copies the `.js` and `.wasm` files to the app that uses each target.
|
|
|
|
### Render targets
|
|
|
|
The same Rust source produces two artifacts, which differ only in compiler
|
|
options:
|
|
|
|
| Target | Tuned for | Cargo profile | Consumed by |
|
|
| ---------- | --------- | ----------------- | ------------------------------ |
|
|
| `frontend` | speed | `release` (`-O3`) | `frontend/resources/public/js` |
|
|
| `export` | size | `size` (`-Oz`) | `exporter/resources/wasm` |
|
|
|
|
```sh
|
|
./build # both targets, frontend first
|
|
./build frontend # workspace / viewer renderer
|
|
./build export # headless exporter renderer
|
|
```
|
|
|
|
`./watch` still follows a single target (`frontend` unless you pass one),
|
|
since watching both would rebuild twice on every keystroke.
|
|
|
|
Each target keeps its own `CARGO_TARGET_DIR` (`target/<target>`), so switching
|
|
between them does not invalidate the other's cache. Set `BUILD_MODE=release`
|
|
(or `NODE_ENV=production`) for an optimized build; the default is `debug`.
|
|
|
|
### Serialize builds in one checkout
|
|
|
|
All targets in one checkout share one `flock` lock stored at
|
|
`render-wasm/.render-wasm-build.lock`. The lock covers dependency setup, the
|
|
Cargo build, artifact copy, and target cleanup. If another build or cleanup
|
|
already holds the lock, the new process prints a waiting message and starts
|
|
only after the first process exits.
|
|
|
|
The watch command takes the lock for each build, then releases it while it
|
|
waits for source changes. The lock file stays in the checkout after a build,
|
|
but the operating system releases its lock when the process exits, including
|
|
after an error or signal.
|
|
|
|
The lock applies to one checkout and only to commands that use these scripts.
|
|
A manual Cargo build can still write to the same target without taking the
|
|
lock. Set `RENDER_WASM_LOCK_FILE` to the same path in each process when you
|
|
make different checkouts share a `CARGO_TARGET_DIR`. The supported Linux build
|
|
environment must provide `flock` from util-linux; `flock --version` checks this
|
|
dependency.
|
|
|
|
Use the target cleanup commands instead of running `cargo clean` on the shared
|
|
`target/` directory:
|
|
|
|
```sh
|
|
./clean frontend # remove target/frontend only
|
|
./clean export # remove target/export only
|
|
```
|
|
|
|
Each target writes its own generated `shared.js` (the enum discriminants the
|
|
CLJS side compiles against) next to the code that imports it — respectively
|
|
`frontend/src/app/render_wasm/api/shared.js` and
|
|
`exporter/src/app/wasm/shared.js`. Neither build writes to the other's paths.
|
|
|
|

|
|
|
|
|
|
Edit your local `frontend/resources/public/js/config.js` to add the following flags:
|
|
|
|
- `enable-feature-render-wasm` to enable this render engine.
|
|
- `enable-render-wasm-dpr` (optional), to enable using the device pixel ratio.
|
|
|
|
## How to test
|
|
|
|
We currently have two types of tests:
|
|
|
|
- Unit tests
|
|
|
|
```sh
|
|
cd penpot/render-wasm
|
|
./test
|
|
```
|
|
|
|
- [Visual Regression Test](./docs/visual_regression_tests.md)
|
|
|
|
## Technical documentation
|
|
|
|
- [Rendering Architecture (Live vs Vector/PDF)](./docs/rendering_architecture.md)
|
|
- [Serialization](./docs/serialization.md)
|
|
- [Tile Rendering](./docs/tile_rendering.md)
|
|
- [Texts](./docs/texts.md)
|