@pkmn/engine 0.1.0-dev.b05836cd → 0.1.0-dev.b14f2221
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/LICENSE +1 -3
- package/README.md +56 -21
- package/build/pkg/addon/browser.d.ts +3 -0
- package/build/pkg/addon/browser.js +47 -0
- package/build/pkg/addon/browser.js.map +1 -0
- package/build/pkg/addon/node.d.ts +3 -0
- package/build/pkg/addon/node.js +110 -0
- package/build/pkg/addon/node.js.map +1 -0
- package/build/pkg/addon/wasm.d.ts +2 -0
- package/build/pkg/addon/wasm.js +53 -0
- package/build/pkg/addon/wasm.js.map +1 -0
- package/build/pkg/addon.d.ts +26 -4
- package/build/pkg/addon.js +39 -71
- package/build/pkg/addon.js.map +1 -1
- package/build/pkg/data/layout.json +15 -2
- package/build/pkg/data/protocol.json +23 -9
- package/build/pkg/data.d.ts +27 -5
- package/build/pkg/data.js.map +1 -1
- package/build/pkg/gen1.d.ts +15 -18
- package/build/pkg/gen1.js +28 -19
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/index.d.ts +42 -91
- package/build/pkg/index.js +23 -70
- package/build/pkg/index.js.map +1 -1
- package/build/pkg/protocol.d.ts +20 -1
- package/build/pkg/protocol.js +109 -107
- package/build/pkg/protocol.js.map +1 -1
- package/build/tools/debug.js +69 -76
- package/build/tools/debug.js.map +1 -1
- package/build/tools/display/debug.jsx +152 -0
- package/build/tools/display/debug.jsx.map +1 -0
- package/build/tools/display/index.js +152 -0
- package/build/tools/display/index.js.map +1 -0
- package/build/tools/display/ui.jsx +359 -0
- package/build/tools/display/ui.jsx.map +1 -0
- package/build/tools/display/util.js +33 -0
- package/build/tools/display/util.js.map +1 -0
- package/build.zig +256 -122
- package/package.json +62 -134
- package/src/bin/install-pkmn-engine +47 -21
- package/src/bin/pkmn-debug +1 -1
- package/src/lib/bindings/c.zig +200 -0
- package/src/lib/{binding → bindings}/node.zig +15 -32
- package/src/lib/bindings/wasm.zig +50 -0
- package/src/lib/common/array.zig +70 -0
- package/src/lib/common/data.zig +4 -4
- package/src/lib/common/debug.zig +32 -11
- package/src/lib/common/js.zig +3 -7
- package/src/lib/common/optional.zig +12 -18
- package/src/lib/common/options.zig +6 -0
- package/src/lib/common/protocol.zig +209 -178
- package/src/lib/common/rational.zig +340 -253
- package/src/lib/common/rng.zig +7 -9
- package/src/lib/common/util.zig +33 -1
- package/src/lib/gen1/calc.zig +724 -175
- package/src/lib/gen1/chance.zig +453 -291
- package/src/lib/gen1/data/moves.zig +2 -4
- package/src/lib/gen1/data/species.zig +2 -4
- package/src/lib/gen1/data/types.zig +3 -4
- package/src/lib/gen1/data.zig +29 -32
- package/src/lib/gen1/helpers.zig +91 -549
- package/src/lib/gen1/mechanics.zig +417 -294
- package/src/lib/gen2/calc.zig +35 -28
- package/src/lib/gen2/chance.zig +85 -503
- package/src/lib/gen2/data/items.zig +1 -3
- package/src/lib/gen2/data/moves.zig +2 -4
- package/src/lib/gen2/data/species.zig +1 -3
- package/src/lib/gen2/data/types.zig +7 -5
- package/src/lib/gen2/data.zig +27 -29
- package/src/lib/gen2/generated.zig +19 -26
- package/src/lib/gen2/helpers.zig +45 -26
- package/src/lib/gen2/mechanics.zig +234 -180
- package/src/lib/napi.h +2 -0
- package/src/lib/node.zig +14 -0
- package/src/lib/pkmn.zig +125 -29
- package/src/lib/wasm.zig +13 -0
- package/src/tools/display/dom.ts +93 -0
- package/src/tools/display/ui.css +354 -0
- package/build/test/display.js +0 -400
- package/build/test/display.js.map +0 -1
- package/src/lib/binding/wasm.zig +0 -12
- package/src/lib/gen1/README.md +0 -894
- package/src/lib/gen2/README.md +0 -329
- package/src/test/display/pkmn.html.tmpl +0 -368
package/build.zig
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
const std = @import("std");
|
|
2
1
|
const builtin = @import("builtin");
|
|
2
|
+
const std = @import("std");
|
|
3
|
+
|
|
4
|
+
fn ArrayList(comptime T: type) type {
|
|
5
|
+
return std.array_list.Aligned(T, null);
|
|
6
|
+
}
|
|
3
7
|
|
|
4
8
|
pub const Options = struct {
|
|
5
9
|
showdown: ?bool = null,
|
|
@@ -9,16 +13,16 @@ pub const Options = struct {
|
|
|
9
13
|
};
|
|
10
14
|
|
|
11
15
|
pub fn module(b: *std.Build, options: Options) *std.Build.Module {
|
|
12
|
-
const dirname = comptime std.fs.path.dirname(@src().file) orelse ".";
|
|
13
16
|
const build_options = b.addOptions();
|
|
14
17
|
build_options.addOption(?bool, "showdown", options.showdown);
|
|
15
18
|
build_options.addOption(?bool, "log", options.log);
|
|
16
19
|
build_options.addOption(?bool, "chance", options.chance);
|
|
17
20
|
build_options.addOption(?bool, "calc", options.calc);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
|
|
22
|
+
const root_source_file = b.path("src/lib/pkmn.zig");
|
|
23
|
+
const imports: []const std.Build.Module.Import =
|
|
24
|
+
&.{.{ .name = "build_options", .module = build_options.createModule() }};
|
|
25
|
+
return b.createModule(.{ .root_source_file = root_source_file, .imports = imports });
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
pub fn build(b: *std.Build) !void {
|
|
@@ -28,12 +32,16 @@ pub fn build(b: *std.Build) !void {
|
|
|
28
32
|
const node_headers = b.option([]const u8, "node-headers", "Path to node-headers");
|
|
29
33
|
const node_import_lib =
|
|
30
34
|
b.option([]const u8, "node-import-library", "Path to node import library (Windows)");
|
|
35
|
+
const demo = if (try exists(b, "src/tools/demo.zig"))
|
|
36
|
+
b.option(bool, "demo", "Build the demo library") orelse false
|
|
37
|
+
else
|
|
38
|
+
false;
|
|
31
39
|
const wasm = b.option(bool, "wasm", "Build a WASM library") orelse false;
|
|
32
40
|
const wasm_stack_size =
|
|
33
41
|
b.option(u64, "wasm-stack-size", "The size of WASM stack") orelse std.wasm.page_size;
|
|
34
42
|
const dynamic = b.option(bool, "dynamic", "Build a dynamic library") orelse false;
|
|
35
|
-
const strip = b.option(bool, "strip", "Strip debugging symbols from binary")
|
|
36
|
-
const pic = b.option(bool, "pic", "Force position independent code")
|
|
43
|
+
const strip = b.option(bool, "strip", "Strip debugging symbols from binary");
|
|
44
|
+
const pic = b.option(bool, "pic", "Force position independent code");
|
|
37
45
|
const emit_asm = b.option(bool, "emit-asm", "Output .s (assembly code)") orelse false;
|
|
38
46
|
const emit_ll = b.option(bool, "emit-ll", "Output .ll (LLVM IR)") orelse false;
|
|
39
47
|
|
|
@@ -44,7 +52,7 @@ pub fn build(b: *std.Build) !void {
|
|
|
44
52
|
defer parsed.deinit();
|
|
45
53
|
const version = parsed.value.object.get("version").?.string;
|
|
46
54
|
const description = parsed.value.object.get("description").?.string;
|
|
47
|
-
var repository = std.mem.
|
|
55
|
+
var repository = std.mem.splitScalar(u8, parsed.value.object.get("repository").?.string, ':');
|
|
48
56
|
std.debug.assert(std.mem.eql(u8, repository.first(), "github"));
|
|
49
57
|
|
|
50
58
|
const showdown =
|
|
@@ -52,6 +60,7 @@ pub fn build(b: *std.Build) !void {
|
|
|
52
60
|
const log = b.option(bool, "log", "Enable protocol message logging") orelse false;
|
|
53
61
|
const chance = b.option(bool, "chance", "Enable update probability tracking") orelse false;
|
|
54
62
|
const calc = b.option(bool, "calc", "Enable damage calculator support") orelse false;
|
|
63
|
+
const extra = b.option([]const []const u8, "option", "Enable extra option");
|
|
55
64
|
|
|
56
65
|
const options = b.addOptions();
|
|
57
66
|
options.addOption(?bool, "showdown", showdown);
|
|
@@ -59,32 +68,67 @@ pub fn build(b: *std.Build) !void {
|
|
|
59
68
|
options.addOption(?bool, "chance", chance);
|
|
60
69
|
options.addOption(?bool, "calc", calc);
|
|
61
70
|
|
|
71
|
+
if (extra) |opts| {
|
|
72
|
+
for (opts) |opt| {
|
|
73
|
+
if (std.mem.indexOfScalar(u8, opt, '=')) |i| {
|
|
74
|
+
options.addOption(?bool, opt[0..i], if (std.mem.eql(u8, opt[i + 1 ..], "true"))
|
|
75
|
+
true
|
|
76
|
+
else if (std.mem.eql(u8, opt[i + 1 ..], "false"))
|
|
77
|
+
false
|
|
78
|
+
else {
|
|
79
|
+
std.log.err("Invalid option: {s}\n", .{opt});
|
|
80
|
+
return error.InvalidOption;
|
|
81
|
+
});
|
|
82
|
+
} else {
|
|
83
|
+
options.addOption(?bool, opt, true);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
62
88
|
const name = if (showdown) "pkmn-showdown" else "pkmn";
|
|
63
89
|
|
|
90
|
+
const pkmn: *std.Build.Module = b.addModule("pkmn", .{
|
|
91
|
+
.root_source_file = b.path("src/lib/pkmn.zig"),
|
|
92
|
+
.optimize = optimize,
|
|
93
|
+
.target = target,
|
|
94
|
+
.imports = &.{.{ .name = "build_options", .module = options.createModule() }},
|
|
95
|
+
});
|
|
96
|
+
|
|
64
97
|
var c = false;
|
|
65
98
|
if (node_headers) |headers| {
|
|
99
|
+
const translate_c = b.addTranslateC(.{
|
|
100
|
+
.root_source_file = b.path("src/lib/napi.h"),
|
|
101
|
+
.target = target,
|
|
102
|
+
.optimize = optimize,
|
|
103
|
+
});
|
|
104
|
+
translate_c.addSystemIncludePath(b.path(headers));
|
|
66
105
|
const addon = b.fmt("{s}.node", .{name});
|
|
67
|
-
const
|
|
106
|
+
const path = b.path("src/lib/node.zig");
|
|
107
|
+
const lib = b.addLibrary(.{
|
|
108
|
+
.linkage = .dynamic,
|
|
68
109
|
.name = addon,
|
|
69
|
-
.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
110
|
+
.root_module = b.createModule(.{
|
|
111
|
+
.root_source_file = path,
|
|
112
|
+
.optimize = optimize,
|
|
113
|
+
.target = target,
|
|
114
|
+
.strip = strip,
|
|
115
|
+
.pic = pic,
|
|
116
|
+
}),
|
|
73
117
|
});
|
|
74
|
-
lib.addOptions("build_options", options);
|
|
75
|
-
lib.
|
|
76
|
-
lib.
|
|
118
|
+
lib.root_module.addOptions("build_options", options);
|
|
119
|
+
lib.root_module.addImport("napi", translate_c.createModule());
|
|
120
|
+
lib.root_module.link_libc = true;
|
|
77
121
|
if (node_import_lib) |il| {
|
|
78
|
-
lib.addObjectFile(.
|
|
79
|
-
} else if (
|
|
80
|
-
|
|
122
|
+
lib.root_module.addObjectFile(b.path(il));
|
|
123
|
+
} else if (target.result.os.tag == .windows) {
|
|
124
|
+
var err = std.Io.File.stderr().writer(b.graph.io, &.{});
|
|
125
|
+
try err.interface.writeAll("Must provide --node-import-library path on Windows\n");
|
|
81
126
|
std.process.exit(1);
|
|
82
127
|
}
|
|
83
128
|
lib.linker_allow_shlib_undefined = true;
|
|
84
129
|
maybeStrip(b, lib, b.getInstallStep(), strip, cmd);
|
|
85
|
-
if (pic) lib.force_pic = pic;
|
|
86
130
|
// Always emit to build/lib because this is where the driver code expects to find it
|
|
87
|
-
// TODO
|
|
131
|
+
// TODO: ziglang/zig#2231 - using the following used to work (though was hacky):
|
|
88
132
|
//
|
|
89
133
|
// lib.emit_bin = .{ .emit_to = b.fmt("build/lib/{s}", .{addon}) };
|
|
90
134
|
// b.getInstallStep().dependOn(&lib.step);
|
|
@@ -93,70 +137,48 @@ pub fn build(b: *std.Build) !void {
|
|
|
93
137
|
// rename the file ourself in install-pkmn-engine
|
|
94
138
|
b.installArtifact(lib);
|
|
95
139
|
} else if (wasm) {
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
},
|
|
104
|
-
.target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
|
|
105
|
-
});
|
|
106
|
-
exe.addOptions("build_options", options);
|
|
107
|
-
exe.export_symbol_names = &[_][]const u8{
|
|
108
|
-
"SHOWDOWN",
|
|
109
|
-
"LOG",
|
|
110
|
-
"CHANCE",
|
|
111
|
-
"CALC",
|
|
112
|
-
"GEN1_CHOICES_SIZE",
|
|
113
|
-
"GEN1_LOGS_SIZE",
|
|
114
|
-
};
|
|
115
|
-
exe.entry = .disabled;
|
|
116
|
-
exe.stack_size = wasm_stack_size;
|
|
117
|
-
exe.strip = strip;
|
|
118
|
-
if (pic) exe.force_pic = pic;
|
|
119
|
-
const opt = b.findProgram(&.{"wasm-opt"}, &.{"./node_modules/.bin"}) catch null;
|
|
120
|
-
if (optimize != .Debug and opt != null) {
|
|
121
|
-
const out = b.fmt("build/lib/{s}.wasm", .{name});
|
|
122
|
-
const sh = b.addSystemCommand(&.{ opt.?, "-O4" });
|
|
123
|
-
sh.addArtifactArg(exe);
|
|
124
|
-
sh.addArg("-o");
|
|
125
|
-
sh.addFileSourceArg(.{ .path = out });
|
|
126
|
-
b.getInstallStep().dependOn(&sh.step);
|
|
127
|
-
} else {
|
|
128
|
-
b.getInstallStep().dependOn(&b.addInstallArtifact(exe, .{
|
|
129
|
-
.dest_dir = .{ .override = std.Build.InstallDir{ .lib = {} } },
|
|
130
|
-
}).step);
|
|
131
|
-
}
|
|
140
|
+
const path = "src/lib/wasm.zig";
|
|
141
|
+
try buildWasm(b, name, path, optimize, strip, pic, wasm_stack_size, null, options);
|
|
142
|
+
} else if (demo) {
|
|
143
|
+
const path = "src/tools/demo.zig";
|
|
144
|
+
const n = if (showdown) "demo-showdown" else "demo";
|
|
145
|
+
const mod = pkmn;
|
|
146
|
+
try buildWasm(b, n, path, optimize, strip, pic, wasm_stack_size, mod, options);
|
|
132
147
|
} else if (dynamic) {
|
|
133
|
-
const
|
|
148
|
+
const path = b.path("src/lib/c.zig");
|
|
149
|
+
const lib = b.addLibrary(.{
|
|
150
|
+
.linkage = .dynamic,
|
|
134
151
|
.name = name,
|
|
135
|
-
.
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
152
|
+
.root_module = b.createModule(.{
|
|
153
|
+
.root_source_file = path,
|
|
154
|
+
.optimize = optimize,
|
|
155
|
+
.target = target,
|
|
156
|
+
.strip = strip,
|
|
157
|
+
.pic = pic,
|
|
158
|
+
}),
|
|
140
159
|
});
|
|
141
|
-
lib.addOptions("build_options", options);
|
|
142
|
-
lib.addIncludePath(.
|
|
160
|
+
lib.root_module.addOptions("build_options", options);
|
|
161
|
+
lib.root_module.addIncludePath(b.path("src/include"));
|
|
143
162
|
maybeStrip(b, lib, b.getInstallStep(), strip, cmd);
|
|
144
|
-
if (pic) lib.force_pic = pic;
|
|
145
163
|
b.installArtifact(lib);
|
|
146
164
|
c = true;
|
|
147
165
|
} else {
|
|
148
|
-
const
|
|
166
|
+
const path = b.path("src/lib/c.zig");
|
|
167
|
+
const lib = b.addLibrary(.{
|
|
168
|
+
.linkage = .static,
|
|
149
169
|
.name = name,
|
|
150
|
-
.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
170
|
+
.root_module = b.createModule(.{
|
|
171
|
+
.root_source_file = path,
|
|
172
|
+
.optimize = optimize,
|
|
173
|
+
.target = target,
|
|
174
|
+
.strip = strip,
|
|
175
|
+
.pic = pic,
|
|
176
|
+
}),
|
|
154
177
|
});
|
|
155
|
-
lib.addOptions("build_options", options);
|
|
156
|
-
lib.addIncludePath(.
|
|
178
|
+
lib.root_module.addOptions("build_options", options);
|
|
179
|
+
lib.root_module.addIncludePath(b.path("src/include"));
|
|
157
180
|
lib.bundle_compiler_rt = true;
|
|
158
181
|
maybeStrip(b, lib, b.getInstallStep(), strip, cmd);
|
|
159
|
-
if (pic) lib.force_pic = pic;
|
|
160
182
|
if (emit_asm) {
|
|
161
183
|
b.getInstallStep().dependOn(&b.addInstallFileWithDir(
|
|
162
184
|
lib.getEmittedAsm(),
|
|
@@ -176,20 +198,25 @@ pub fn build(b: *std.Build) !void {
|
|
|
176
198
|
}
|
|
177
199
|
|
|
178
200
|
if (c) {
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
.header,
|
|
182
|
-
"pkmn.h",
|
|
183
|
-
);
|
|
201
|
+
const path = b.path("src/include/pkmn.h");
|
|
202
|
+
const header = b.addInstallFileWithDir(path, .header, "pkmn.h");
|
|
184
203
|
b.getInstallStep().dependOn(&header.step);
|
|
185
204
|
|
|
186
205
|
const pc = b.fmt("lib{s}.pc", .{name});
|
|
187
|
-
const
|
|
188
|
-
const
|
|
206
|
+
const cwd = try std.process.currentPathAlloc(b.graph.io, b.allocator);
|
|
207
|
+
const file = try std.Io.Dir.path.relative(
|
|
208
|
+
b.allocator,
|
|
209
|
+
cwd,
|
|
210
|
+
&b.graph.environ_map,
|
|
211
|
+
cwd,
|
|
212
|
+
try b.cache_root.join(b.allocator, &.{pc}),
|
|
213
|
+
);
|
|
214
|
+
const pkgconfig_file = try std.Io.Dir.cwd().createFile(b.graph.io, file, .{});
|
|
215
|
+
defer pkgconfig_file.close(b.graph.io);
|
|
189
216
|
|
|
190
217
|
const dirname = comptime std.fs.path.dirname(@src().file) orelse ".";
|
|
191
|
-
|
|
192
|
-
try writer.print(
|
|
218
|
+
var writer = pkgconfig_file.writer(b.graph.io, &.{});
|
|
219
|
+
try writer.interface.print(
|
|
193
220
|
\\prefix={0s}/{1s}
|
|
194
221
|
\\includedir=${{prefix}}/include
|
|
195
222
|
\\libdir=${{prefix}}/lib
|
|
@@ -201,12 +228,11 @@ pub fn build(b: *std.Build) !void {
|
|
|
201
228
|
\\Cflags: -I${{includedir}}
|
|
202
229
|
\\Libs: -L${{libdir}} -l{2s}
|
|
203
230
|
, .{ dirname, b.install_path, name, repository.next().?, description, version });
|
|
204
|
-
defer pkgconfig_file.close();
|
|
205
231
|
|
|
206
232
|
b.installFile(file, b.fmt("share/pkgconfig/{s}", .{pc}));
|
|
207
233
|
}
|
|
208
234
|
|
|
209
|
-
const config = .{
|
|
235
|
+
const config: Config = .{
|
|
210
236
|
.target = target,
|
|
211
237
|
.optimize = optimize,
|
|
212
238
|
.pic = pic,
|
|
@@ -217,7 +243,7 @@ pub fn build(b: *std.Build) !void {
|
|
|
217
243
|
// TODO: tests can be run multiple times due to @imports
|
|
218
244
|
const tests = TestStep.create(b, options, config);
|
|
219
245
|
|
|
220
|
-
var exes
|
|
246
|
+
var exes: ArrayList(*std.Build.Step.Compile) = .empty;
|
|
221
247
|
const tools: ToolConfig = .{
|
|
222
248
|
.options = .{
|
|
223
249
|
.showdown = showdown,
|
|
@@ -225,6 +251,7 @@ pub fn build(b: *std.Build) !void {
|
|
|
225
251
|
.chance = chance,
|
|
226
252
|
.calc = calc,
|
|
227
253
|
},
|
|
254
|
+
.module = pkmn,
|
|
228
255
|
.general = config,
|
|
229
256
|
.tool = .{
|
|
230
257
|
.tests = if (tests.build) tests else null,
|
|
@@ -263,15 +290,93 @@ pub fn build(b: *std.Build) !void {
|
|
|
263
290
|
}
|
|
264
291
|
}
|
|
265
292
|
|
|
293
|
+
fn buildWasm(
|
|
294
|
+
b: *std.Build,
|
|
295
|
+
name: []const u8,
|
|
296
|
+
root_src_file: []const u8,
|
|
297
|
+
optimize: std.builtin.OptimizeMode,
|
|
298
|
+
strip: ?bool,
|
|
299
|
+
pic: ?bool,
|
|
300
|
+
wasm_stack_size: u64,
|
|
301
|
+
import: ?*std.Build.Module,
|
|
302
|
+
options: anytype,
|
|
303
|
+
) !void {
|
|
304
|
+
const mode = switch (optimize) {
|
|
305
|
+
.ReleaseFast, .ReleaseSafe => .ReleaseSmall,
|
|
306
|
+
else => optimize,
|
|
307
|
+
};
|
|
308
|
+
// https://webassembly.org/features/
|
|
309
|
+
var features = std.Target.wasm.featureSet(&.{
|
|
310
|
+
.atomics,
|
|
311
|
+
.bulk_memory,
|
|
312
|
+
// .exception_handling,
|
|
313
|
+
.extended_const,
|
|
314
|
+
// .half_precision,
|
|
315
|
+
// .multimemory,
|
|
316
|
+
.mutable_globals,
|
|
317
|
+
.nontrapping_fptoint,
|
|
318
|
+
.reference_types,
|
|
319
|
+
// .relaxed_simd,
|
|
320
|
+
.sign_ext,
|
|
321
|
+
.simd128,
|
|
322
|
+
// .tail_call,
|
|
323
|
+
});
|
|
324
|
+
if (builtin.zig_version.order(try std.SemanticVersion.parse("0.12.0")) != .lt) {
|
|
325
|
+
features.addFeature(@intFromEnum(std.Target.wasm.Feature.multivalue));
|
|
326
|
+
}
|
|
327
|
+
const freestanding = b.resolveTargetQuery(.{
|
|
328
|
+
.cpu_arch = .wasm32,
|
|
329
|
+
.os_tag = .freestanding,
|
|
330
|
+
.cpu_features_add = features,
|
|
331
|
+
});
|
|
332
|
+
const path = b.path(root_src_file);
|
|
333
|
+
const exe = b.addExecutable(.{
|
|
334
|
+
.name = name,
|
|
335
|
+
.root_module = b.createModule(.{
|
|
336
|
+
.root_source_file = path,
|
|
337
|
+
.optimize = mode,
|
|
338
|
+
.target = freestanding,
|
|
339
|
+
.strip = strip,
|
|
340
|
+
.pic = pic,
|
|
341
|
+
}),
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
var file = try std.Io.Dir.cwd().openFile(b.graph.io, root_src_file, .{});
|
|
345
|
+
defer file.close(b.graph.io);
|
|
346
|
+
var reader = file.reader(b.graph.io, &.{});
|
|
347
|
+
const bytes = try reader.interface.allocRemaining(b.allocator, .unlimited);
|
|
348
|
+
exe.root_module.export_symbol_names = try exports(b, bytes);
|
|
349
|
+
exe.entry = .disabled;
|
|
350
|
+
|
|
351
|
+
if (import) |i| {
|
|
352
|
+
exe.root_module.addImport("pkmn", i);
|
|
353
|
+
}
|
|
354
|
+
exe.stack_size = wasm_stack_size;
|
|
355
|
+
exe.root_module.addOptions("build_options", options);
|
|
356
|
+
|
|
357
|
+
const opt = b.findProgram(&.{"wasm-opt"}, &.{"./node_modules/.bin"}) catch null;
|
|
358
|
+
if (optimize != .Debug and opt != null) {
|
|
359
|
+
const out = b.fmt("build/lib/{s}.wasm", .{name});
|
|
360
|
+
const sh = b.addSystemCommand(&.{ opt.?, "--enable-bulk-memory", "--enable-simd", "-O4" });
|
|
361
|
+
sh.addArtifactArg(exe);
|
|
362
|
+
sh.addArg("-o");
|
|
363
|
+
sh.addFileArg(b.path(out));
|
|
364
|
+
b.getInstallStep().dependOn(&sh.step);
|
|
365
|
+
} else {
|
|
366
|
+
b.getInstallStep().dependOn(&b.addInstallArtifact(exe, .{
|
|
367
|
+
.dest_dir = .{ .override = std.Build.InstallDir{ .lib = {} } },
|
|
368
|
+
}).step);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
266
372
|
fn maybeStrip(
|
|
267
373
|
b: *std.Build,
|
|
268
|
-
artifact: *std.Build.
|
|
374
|
+
artifact: *std.Build.Step.Compile,
|
|
269
375
|
step: *std.Build.Step,
|
|
270
|
-
strip: bool,
|
|
376
|
+
strip: ?bool,
|
|
271
377
|
cmd: ?[]const u8,
|
|
272
378
|
) void {
|
|
273
|
-
|
|
274
|
-
if (!strip or cmd == null) return;
|
|
379
|
+
if (!(strip orelse false) or cmd == null) return;
|
|
275
380
|
// Using `strip -r -u` for dynamic libraries is supposed to work on macOS but doesn't...
|
|
276
381
|
const mac = builtin.os.tag == .macos;
|
|
277
382
|
if (mac and artifact.isDynamicLibrary()) return;
|
|
@@ -283,10 +388,10 @@ fn maybeStrip(
|
|
|
283
388
|
}
|
|
284
389
|
|
|
285
390
|
const Config = struct {
|
|
286
|
-
target: std.
|
|
391
|
+
target: std.Build.ResolvedTarget,
|
|
287
392
|
optimize: std.builtin.OptimizeMode,
|
|
288
|
-
pic: bool,
|
|
289
|
-
strip: bool,
|
|
393
|
+
pic: ?bool,
|
|
394
|
+
strip: ?bool,
|
|
290
395
|
cmd: ?[]const u8,
|
|
291
396
|
};
|
|
292
397
|
|
|
@@ -294,9 +399,8 @@ const TestStep = struct {
|
|
|
294
399
|
step: std.Build.Step,
|
|
295
400
|
build: bool,
|
|
296
401
|
|
|
297
|
-
pub fn create(b: *std.Build, options: *std.Build.
|
|
402
|
+
pub fn create(b: *std.Build, options: *std.Build.Step.Options, config: Config) *TestStep {
|
|
298
403
|
const coverage = b.option([]const u8, "test-coverage", "Generate test coverage");
|
|
299
|
-
const test_file = b.option([]const u8, "test-file", "Input file for test");
|
|
300
404
|
const test_filter =
|
|
301
405
|
b.option([]const u8, "test-filter", "Skip tests that do not match filter");
|
|
302
406
|
|
|
@@ -304,22 +408,21 @@ const TestStep = struct {
|
|
|
304
408
|
const step = std.Build.Step.init(.{ .id = .custom, .name = "Run all tests", .owner = b });
|
|
305
409
|
self.* = .{ .step = step, .build = test_filter == null };
|
|
306
410
|
|
|
307
|
-
const path =
|
|
411
|
+
const path = b.path("src/lib/test.zig");
|
|
308
412
|
const tests = b.addTest(.{
|
|
309
|
-
.
|
|
310
|
-
|
|
311
|
-
|
|
413
|
+
.root_module = b.createModule(.{
|
|
414
|
+
.root_source_file = path,
|
|
415
|
+
.optimize = config.optimize,
|
|
416
|
+
.target = config.target,
|
|
417
|
+
.single_threaded = true,
|
|
418
|
+
.strip = config.strip,
|
|
419
|
+
.pic = config.pic,
|
|
312
420
|
}),
|
|
313
|
-
.
|
|
314
|
-
.root_source_file = .{ .path = path },
|
|
315
|
-
.optimize = config.optimize,
|
|
316
|
-
.target = config.target,
|
|
317
|
-
.filter = test_filter,
|
|
421
|
+
.filters = if (test_filter) |filter| &.{filter} else &.{},
|
|
318
422
|
});
|
|
319
|
-
tests.addOptions("build_options", options);
|
|
320
|
-
|
|
423
|
+
tests.root_module.addOptions("build_options", options);
|
|
424
|
+
|
|
321
425
|
maybeStrip(b, tests, &tests.step, config.strip, config.cmd);
|
|
322
|
-
if (config.pic) tests.force_pic = config.pic;
|
|
323
426
|
if (coverage) |c| {
|
|
324
427
|
tests.setExecCmd(&.{ "kcov", "--include-pattern=src/lib", c, null });
|
|
325
428
|
}
|
|
@@ -331,19 +434,17 @@ const TestStep = struct {
|
|
|
331
434
|
|
|
332
435
|
const ToolConfig = struct {
|
|
333
436
|
options: Options,
|
|
437
|
+
module: ?*std.Build.Module,
|
|
334
438
|
general: Config,
|
|
335
439
|
tool: struct {
|
|
336
440
|
tests: ?*TestStep,
|
|
337
441
|
name: ?[]const u8 = null,
|
|
338
|
-
exes: *
|
|
442
|
+
exes: *ArrayList(*std.Build.Step.Compile),
|
|
339
443
|
},
|
|
340
444
|
};
|
|
341
445
|
|
|
342
|
-
fn tool(b: *std.Build, path: []const u8, config: ToolConfig) !?*std.Build.
|
|
343
|
-
|
|
344
|
-
error.FileNotFound => return null,
|
|
345
|
-
else => |e| return e,
|
|
346
|
-
};
|
|
446
|
+
fn tool(b: *std.Build, path: []const u8, config: ToolConfig) !?*std.Build.Step.Run {
|
|
447
|
+
if (!try exists(b, path)) return null;
|
|
347
448
|
var name = config.tool.name orelse std.fs.path.basename(path);
|
|
348
449
|
const index = std.mem.lastIndexOfScalar(u8, name, '.');
|
|
349
450
|
if (index) |i| name = name[0..i];
|
|
@@ -351,16 +452,23 @@ fn tool(b: *std.Build, path: []const u8, config: ToolConfig) !?*std.Build.RunSte
|
|
|
351
452
|
|
|
352
453
|
const exe = b.addExecutable(.{
|
|
353
454
|
.name = name,
|
|
354
|
-
.
|
|
355
|
-
|
|
356
|
-
|
|
455
|
+
.root_module = b.createModule(.{
|
|
456
|
+
.root_source_file = b.path(path),
|
|
457
|
+
.target = config.general.target,
|
|
458
|
+
.optimize = config.general.optimize,
|
|
459
|
+
.strip = config.general.strip,
|
|
460
|
+
.pic = config.general.pic,
|
|
461
|
+
}),
|
|
357
462
|
});
|
|
358
|
-
exe.addModule("pkmn", module(b, config.options));
|
|
359
463
|
|
|
360
|
-
|
|
361
|
-
|
|
464
|
+
const import = if (config.module) |m| m else module(b, config.options);
|
|
465
|
+
exe.root_module.addImport("pkmn", import);
|
|
466
|
+
if (config.general.target.result.os.tag == .windows) {
|
|
467
|
+
exe.root_module.linkSystemLibrary("advapi32", .{});
|
|
468
|
+
}
|
|
469
|
+
|
|
362
470
|
if (config.tool.tests) |ts| ts.step.dependOn(&exe.step);
|
|
363
|
-
config.tool.exes.append(exe) catch @panic("OOM");
|
|
471
|
+
config.tool.exes.append(b.allocator, exe) catch @panic("OOM");
|
|
364
472
|
|
|
365
473
|
const run = b.addRunArtifact(exe);
|
|
366
474
|
maybeStrip(b, exe, &run.step, config.general.strip, config.general.cmd);
|
|
@@ -369,10 +477,18 @@ fn tool(b: *std.Build, path: []const u8, config: ToolConfig) !?*std.Build.RunSte
|
|
|
369
477
|
return run;
|
|
370
478
|
}
|
|
371
479
|
|
|
480
|
+
fn exists(b: *std.Build, path: []const u8) !bool {
|
|
481
|
+
std.Io.Dir.cwd().access(b.graph.io, path, .{}) catch |err| switch (err) {
|
|
482
|
+
error.FileNotFound => return false,
|
|
483
|
+
else => |e| return e,
|
|
484
|
+
};
|
|
485
|
+
return true;
|
|
486
|
+
}
|
|
487
|
+
|
|
372
488
|
const ToolsStep = struct {
|
|
373
489
|
step: std.Build.Step,
|
|
374
490
|
|
|
375
|
-
pub fn create(b: *std.Build, exes: *
|
|
491
|
+
pub fn create(b: *std.Build, exes: *ArrayList(*std.Build.Step.Compile)) *ToolsStep {
|
|
376
492
|
const self = b.allocator.create(ToolsStep) catch @panic("OOM");
|
|
377
493
|
const step = std.Build.Step.init(.{ .id = .custom, .name = "Install tools", .owner = b });
|
|
378
494
|
self.* = .{ .step = step };
|
|
@@ -380,3 +496,21 @@ const ToolsStep = struct {
|
|
|
380
496
|
return self;
|
|
381
497
|
}
|
|
382
498
|
};
|
|
499
|
+
|
|
500
|
+
pub fn exports(b: *std.Build, bytes: []const u8) ![][]const u8 {
|
|
501
|
+
var symbols: ArrayList([]const u8) = .empty;
|
|
502
|
+
|
|
503
|
+
var it = std.mem.splitSequence(u8, bytes, "export ");
|
|
504
|
+
_ = it.next();
|
|
505
|
+
while (it.next()) |s| {
|
|
506
|
+
if (std.mem.startsWith(u8, s, "const ")) {
|
|
507
|
+
const i = std.mem.indexOf(u8, s[6..], " ").?;
|
|
508
|
+
try symbols.append(b.allocator, s[6 .. 6 + i]);
|
|
509
|
+
} else { // "fn "
|
|
510
|
+
const i = std.mem.indexOf(u8, s[3..], "(").?;
|
|
511
|
+
try symbols.append(b.allocator, s[3 .. 3 + i]);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
return symbols.items;
|
|
516
|
+
}
|