@thi.ng/wasm-api 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2022-11-30T22:27:37Z
3
+ - **Last updated**: 2022-12-01T18:02:30Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
@@ -9,6 +9,12 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
9
9
  **Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
10
10
  and/or version bumps of transitive dependencies.
11
11
 
12
+ ## [1.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api@1.2.0) (2022-12-01)
13
+
14
+ #### 🚀 Features
15
+
16
+ - add build script for user projects ([7164f5e](https://github.com/thi-ng/umbrella/commit/7164f5e))
17
+
12
18
  ## [1.1.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api@1.1.0) (2022-11-28)
13
19
 
14
20
  #### 🚀 Features
package/README.md CHANGED
@@ -11,11 +11,12 @@ This project is part of the
11
11
 
12
12
  - [About](#about)
13
13
  - [Custom API modules](#custom-api-modules)
14
- - [Building Zig projects with these hybrid API modules](#building-zig-projects-with-these-hybrid-api-modules)
15
14
  - [String handling](#string-handling)
16
15
  - [Memory allocations](#memory-allocations)
17
16
  - [API module auto-initialization](#api-module-auto-initialization)
18
17
  - [Object indices & handles](#object-indices--handles)
18
+ - [Using the Zig build system](#using-the-zig-build-system)
19
+ - [Naming & structural conventions](#naming--structural-conventions)
19
20
  - [Status](#status)
20
21
  - [Support packages](#support-packages)
21
22
  - [Installation](#installation)
@@ -55,13 +56,15 @@ WebGL, WebGPU, WebAudio etc. is being actively worked on.
55
56
  defining glue code for the TypeScript [core
56
57
  API](https://docs.thi.ng/umbrella/wasm-api/interfaces/CoreAPI.html) defined
57
58
  by this package
58
- 7. Extensible shared [datatype code generator
59
+ 7. [Zig build files]() to simplify using hybrid TS/Zig packages with the
60
+ built-in build system
61
+ 8. Extensible shared [datatype code generator
59
62
  infrastructure](https://github.com/thi-ng/umbrella/tree/develop/packages/wasm-api-bindgen/)
60
63
  for (currently) Zig & TypeScript and C11. For TS fully type checked and
61
64
  memory-mapped (zero-copy) accessors of WASM-side data are generated. In
62
65
  principle, all languages with a WASM target are supported, however currently
63
66
  only bindings for these mentioned langs are included.
64
- 8. [CLI
67
+ 9. [CLI
65
68
  frontend/utility](https://github.com/thi-ng/umbrella/blob/develop/packages/wasm-api-bindgen/README.md#cli-generator)
66
69
  for the code generator(s)
67
70
 
@@ -165,19 +168,6 @@ export fn test_randomVec4() void {
165
168
  }
166
169
  ```
167
170
 
168
- ### Building Zig projects with these hybrid API modules
169
-
170
- Some example projects (see [list below](#usage-examples)) provide custom
171
- [`build.zig`](https://github.com/thi-ng/umbrella/blob/develop/examples/zig-canvas/build.zig)
172
- &
173
- [`npm.zig`](https://github.com/thi-ng/umbrella/blob/develop/examples/zig-canvas/npm.zig)
174
- build scripts to easily integrate these hybrid TS/Zig packages into users'
175
- development processes.
176
-
177
- To avoid guesswork about the internals of these API modules, all of them are
178
- using an overall uniform structure, with the main Zig entry point in
179
- `/zig/lib.zig`...
180
-
181
171
  ## String handling
182
172
 
183
173
  Most low-level languages deal with strings very differently and alas there's no
@@ -313,6 +303,38 @@ in the
313
303
  [@thi.ng/wasm-api-schedule](https://github.com/thi-ng/umbrella/blob/develop/packages/wasm-api-schedule/)
314
304
  packages this is used to manage Zig-side event listeners.
315
305
 
306
+ ## Using the Zig build system
307
+
308
+ This package provides utilities to simplify using hybrid TS/Zig WASM API modules which are distributed as NPM packages. Using these utils, a build file for Zig's built-in build system is as simple as:
309
+
310
+ ```zig
311
+ const std = @import("std");
312
+
313
+ pub fn build(b: *std.build.Builder) void {
314
+ @import("node_modules/@thi.ng/wasm-api/zig/build.zig").wasmLib(b, .{
315
+ // Declare extra WASM API packages to use
316
+ // Each package can also declare its dependencies
317
+ .packages = &.{
318
+ .{ .id = "wasm-api-dom", .path = "@thi.ng/wasm-api-dom/zig/lib.zig" },
319
+ .{ .id = "wasm-api-schedule", .path = "@thi.ng/wasm-api-schedule/zig/lib.zig" },
320
+ },
321
+ // (optional) build mode override
322
+ .mode = .ReleaseSmall,
323
+ }).install();
324
+ }
325
+ ```
326
+
327
+ All bundled example projects (see [list below](#usage-examples)) are being built
328
+ via this script. **Please find more details/options in the commented source
329
+ code:**
330
+ [`/zig/build.zig`](https://github.com/thi-ng/umbrella/blob/develop/packages/wasm-api/zig/build.zig)
331
+
332
+ ## Naming & structural conventions
333
+
334
+ To avoid guesswork about the internals of any of the supplied WASM API modules,
335
+ please also consult the information in
336
+ [#368](https://github.com/thi-ng/umbrella/issues/368).
337
+
316
338
  ## Status
317
339
 
318
340
  **ALPHA** - bleeding edge / work-in-progress
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/wasm-api",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "Generic, modular, extensible API bridge and infrastructure for hybrid JS & WebAssembly projects",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -110,5 +110,5 @@
110
110
  "status": "alpha",
111
111
  "year": 2022
112
112
  },
113
- "gitHead": "1fe40da507070653f420156d91e6b27cf682004f\n"
113
+ "gitHead": "199dcde33bf3d0b0bbd205d3b870dff43b735b22\n"
114
114
  }
package/zig/build.zig ADDED
@@ -0,0 +1,135 @@
1
+ const std = @import("std");
2
+
3
+ /// Definition for a (usually hybrid) Zig package which will be distributed via NPM
4
+ pub const Pkg = struct {
5
+ /// Package ID used for @import
6
+ id: []const u8,
7
+ /// Package sub path (appended to base path)
8
+ path: []const u8,
9
+ /// Package dependencies aka other package IDs.
10
+ /// All of them must already have been registered
11
+ deps: ?[]const []const u8 = null,
12
+ };
13
+
14
+ pub const PkgOpts = struct {
15
+ /// Base path to common node_modules directory under which
16
+ /// all to be imported packages are located
17
+ base: []const u8 = "node_modules",
18
+ /// Additional WASM API support packages.
19
+ /// We don't need to specify core wasmapi, only custom/extra ones
20
+ /// `wasm-api` and `wasm-api-bindgen` are also auto-added
21
+ /// as dependency for each of these...
22
+ packages: ?[]const Pkg = null,
23
+ };
24
+
25
+ /// Dependency graph for WASM API packages
26
+ /// Expands & resolves the more compact/convenient/human friendly format of PkgOpts
27
+ /// into the data structures used by Zig's build system
28
+ /// Provides a `addAllTo()` function to add all declared packages to a build step
29
+ pub const PkgGraph = struct {
30
+ arena: std.heap.ArenaAllocator,
31
+ basePath: []const u8,
32
+ packages: std.StringArrayHashMap(std.build.Pkg),
33
+
34
+ const Self = @This();
35
+
36
+ pub fn init(opts: PkgOpts) Self {
37
+ var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
38
+ var self = Self{
39
+ .arena = arena,
40
+ .basePath = opts.base,
41
+ .packages = std.StringArrayHashMap(std.build.Pkg).init(arena.allocator()),
42
+ };
43
+ const api = "wasm-api";
44
+ self.packages.put(api, .{
45
+ .name = api,
46
+ .source = .{ .path = self.modulePath("@thi.ng/wasm-api/zig/lib.zig") },
47
+ }) catch unreachable;
48
+ const apiTypes = "wasm-api-bindgen";
49
+ self.packages.put(apiTypes, .{
50
+ .name = apiTypes,
51
+ .source = .{ .path = self.modulePath("@thi.ng/wasm-api-bindgen/zig/lib.zig") },
52
+ }) catch unreachable;
53
+ if (opts.packages) |pkgs| {
54
+ for (pkgs) |pkg| {
55
+ self.register(pkg.id, pkg.path, pkg.deps);
56
+ }
57
+ }
58
+ return self;
59
+ }
60
+
61
+ pub fn deinit(self: *const Self) void {
62
+ self.arena.deinit();
63
+ }
64
+
65
+ /// Registers a single package and its deps (also injects core wasm-api deps)
66
+ pub fn register(
67
+ self: *Self,
68
+ name: []const u8,
69
+ path: []const u8,
70
+ dependencies: ?[]const []const u8,
71
+ ) void {
72
+ var pkg = std.build.Pkg{
73
+ .name = name,
74
+ .source = .{ .path = self.modulePath(path) },
75
+ };
76
+ const num = if (dependencies) |deps| deps.len else 0;
77
+ var dpkgs = self.arena.allocator().alloc(std.build.Pkg, num + 2) catch unreachable;
78
+ dpkgs[0] = if (self.packages.get("wasm-api")) |p| p else unreachable;
79
+ dpkgs[1] = if (self.packages.get("wasm-api-bindgen")) |p| p else unreachable;
80
+ if (dependencies) |deps| {
81
+ var i: usize = 0;
82
+ while (i < deps.len) : (i += 1) {
83
+ if (self.packages.get(deps[i])) |p| {
84
+ dpkgs[i + 1] = p;
85
+ } else @panic("unknown dependency");
86
+ }
87
+ }
88
+ pkg.dependencies = dpkgs;
89
+ self.packages.put(name, pkg) catch unreachable;
90
+ }
91
+
92
+ /// Adds all registered packages to the given build step
93
+ pub fn addAllTo(self: *const Self, step: *std.build.LibExeObjStep) void {
94
+ for (self.packages.values()) |pkg| step.addPackage(pkg);
95
+ }
96
+
97
+ fn modulePath(self: *Self, path: []const u8) []const u8 {
98
+ return std.fs.path.join(self.arena.allocator(), &.{ self.basePath, path }) catch unreachable;
99
+ }
100
+ };
101
+
102
+ /// Config options
103
+ pub const WasmLibOpts = struct {
104
+ /// Relative path to base directory for WASM API packages
105
+ base: []const u8 = "node_modules",
106
+ /// Relative path to root source file
107
+ root: []const u8 = "zig/main.zig",
108
+ /// Relative path to output directory
109
+ out: []const u8 = "src",
110
+ /// Package definitions for additional WASM API modules
111
+ packages: ?[]const Pkg = null,
112
+ /// Build mode override (else allows config via CLI args)
113
+ mode: ?std.builtin.Mode = null,
114
+ /// Additional WASM target features, e.g. `.simd128` to enable SIMD
115
+ features: ?[]const std.Target.wasm.Feature = null,
116
+ };
117
+
118
+ /// Creates and returns a build step to build a dynamic WASM library, configured
119
+ /// with given options and package declarations. The given package specs will be inserted
120
+ pub fn wasmLib(b: *std.build.Builder, opts: WasmLibOpts) *std.build.LibExeObjStep {
121
+ const lib = b.addSharedLibrary("main", opts.root, .unversioned);
122
+ lib.setTarget(.{
123
+ .cpu_arch = .wasm32,
124
+ .os_tag = .freestanding,
125
+ .cpu_features_add = if (opts.features) |features| std.Target.wasm.featureSet(features) else std.Target.Cpu.Feature.Set.empty,
126
+ });
127
+ const mode = if (opts.mode) |m| m else b.standardReleaseOptions();
128
+ lib.setBuildMode(mode);
129
+ if (mode == .ReleaseSmall or mode == .ReleaseFast) lib.strip = true;
130
+ const pkgs = PkgGraph.init(.{ .base = opts.base, .packages = opts.packages });
131
+ defer pkgs.deinit();
132
+ pkgs.addAllTo(lib);
133
+ lib.setOutputDir(opts.out);
134
+ return lib;
135
+ }