@pkmn/engine 0.1.0-dev.3a273268 → 0.1.0-dev.3d09f03a
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 +121 -75
- 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 +27 -5
- package/build/pkg/addon.js +41 -72
- package/build/pkg/addon.js.map +1 -1
- package/build/pkg/data/ids.json +12 -12
- package/build/pkg/data/layout.json +40 -5
- package/build/pkg/data/protocol.json +84 -13
- package/build/pkg/data.d.ts +27 -5
- package/build/pkg/data.js.map +1 -1
- package/build/pkg/gen1.d.ts +18 -20
- package/build/pkg/gen1.js +76 -51
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/index.d.ts +57 -103
- package/build/pkg/index.js +23 -70
- package/build/pkg/index.js.map +1 -1
- package/build/pkg/protocol.d.ts +24 -3
- package/build/pkg/protocol.js +127 -104
- package/build/pkg/protocol.js.map +1 -1
- package/build/tools/debug.js +69 -74
- 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 +335 -167
- package/package.json +71 -120
- package/src/bin/install-pkmn-engine +57 -26
- package/src/bin/pkmn-debug +1 -1
- package/src/lib/bindings/c.zig +200 -0
- package/src/lib/bindings/node.zig +117 -0
- package/src/lib/bindings/wasm.zig +50 -0
- package/src/lib/common/array.zig +70 -0
- package/src/lib/common/battle.zig +17 -0
- package/src/lib/common/data.zig +19 -31
- package/src/lib/common/debug.zig +51 -20
- package/src/lib/common/js.zig +114 -0
- package/src/lib/common/optional.zig +61 -0
- package/src/lib/common/options.zig +18 -3
- package/src/lib/common/protocol.zig +1072 -497
- package/src/lib/common/rational.zig +440 -0
- package/src/lib/common/rng.zig +31 -24
- package/src/lib/common/util.zig +44 -0
- package/src/lib/gen1/calc.zig +975 -0
- package/src/lib/gen1/chance.zig +1222 -0
- package/src/lib/gen1/data/moves.zig +203 -193
- package/src/lib/gen1/data/species.zig +6 -8
- package/src/lib/gen1/data/types.zig +12 -13
- package/src/lib/gen1/data.zig +100 -89
- package/src/lib/gen1/helpers.zig +138 -51
- package/src/lib/gen1/mechanics.zig +1308 -864
- package/src/lib/gen2/calc.zig +150 -0
- package/src/lib/gen2/chance.zig +896 -0
- package/src/lib/gen2/data/items.zig +15 -23
- package/src/lib/gen2/data/moves.zig +665 -573
- package/src/lib/gen2/data/species.zig +3 -5
- package/src/lib/gen2/data/types.zig +141 -36
- package/src/lib/gen2/data.zig +136 -100
- package/src/lib/gen2/generated.zig +801 -0
- package/src/lib/gen2/helpers.zig +58 -45
- package/src/lib/gen2/mechanics.zig +3582 -30
- package/src/lib/napi.h +2 -0
- package/src/lib/node.zig +14 -0
- package/src/lib/pkmn.zig +174 -19
- 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 -382
- package/build/test/display.js.map +0 -1
- package/src/lib/binding/node.zig +0 -229
- package/src/lib/binding/wasm.zig +0 -10
- package/src/lib/gen1/README.md +0 -791
- package/src/lib/gen2/README.md +0 -309
- package/src/test/display/pkmn.html.tmpl +0 -368
package/build.zig
CHANGED
|
@@ -1,17 +1,28 @@
|
|
|
1
|
-
const std = @import("std");
|
|
2
1
|
const builtin = @import("builtin");
|
|
2
|
+
const std = @import("std");
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
fn ArrayList(comptime T: type) type {
|
|
5
|
+
return std.array_list.Aligned(T, null);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
pub const Options = struct {
|
|
9
|
+
showdown: ?bool = null,
|
|
10
|
+
log: ?bool = null,
|
|
11
|
+
chance: ?bool = null,
|
|
12
|
+
calc: ?bool = null,
|
|
13
|
+
};
|
|
5
14
|
|
|
6
15
|
pub fn module(b: *std.Build, options: Options) *std.Build.Module {
|
|
7
|
-
const dirname = comptime std.fs.path.dirname(@src().file) orelse ".";
|
|
8
16
|
const build_options = b.addOptions();
|
|
9
17
|
build_options.addOption(?bool, "showdown", options.showdown);
|
|
10
|
-
build_options.addOption(?bool, "
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
18
|
+
build_options.addOption(?bool, "log", options.log);
|
|
19
|
+
build_options.addOption(?bool, "chance", options.chance);
|
|
20
|
+
build_options.addOption(?bool, "calc", options.calc);
|
|
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 });
|
|
15
26
|
}
|
|
16
27
|
|
|
17
28
|
pub fn build(b: *std.Build) !void {
|
|
@@ -21,140 +32,191 @@ pub fn build(b: *std.Build) !void {
|
|
|
21
32
|
const node_headers = b.option([]const u8, "node-headers", "Path to node-headers");
|
|
22
33
|
const node_import_lib =
|
|
23
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;
|
|
24
39
|
const wasm = b.option(bool, "wasm", "Build a WASM library") orelse false;
|
|
25
40
|
const wasm_stack_size =
|
|
26
41
|
b.option(u64, "wasm-stack-size", "The size of WASM stack") orelse std.wasm.page_size;
|
|
27
42
|
const dynamic = b.option(bool, "dynamic", "Build a dynamic library") orelse false;
|
|
28
|
-
const strip = b.option(bool, "strip", "Strip debugging symbols from binary")
|
|
29
|
-
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");
|
|
30
45
|
const emit_asm = b.option(bool, "emit-asm", "Output .s (assembly code)") orelse false;
|
|
46
|
+
const emit_ll = b.option(bool, "emit-ll", "Output .ll (LLVM IR)") orelse false;
|
|
31
47
|
|
|
32
48
|
const cmd = b.findProgram(&.{"strip"}, &.{}) catch null;
|
|
33
49
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
var repository = std.mem.split(u8, tree.root.Object.get("repository").?.String, ":");
|
|
50
|
+
const json = @embedFile("package.json");
|
|
51
|
+
var parsed = try std.json.parseFromSlice(std.json.Value, b.allocator, json, .{});
|
|
52
|
+
defer parsed.deinit();
|
|
53
|
+
const version = parsed.value.object.get("version").?.string;
|
|
54
|
+
const description = parsed.value.object.get("description").?.string;
|
|
55
|
+
var repository = std.mem.splitScalar(u8, parsed.value.object.get("repository").?.string, ':');
|
|
41
56
|
std.debug.assert(std.mem.eql(u8, repository.first(), "github"));
|
|
42
57
|
|
|
43
58
|
const showdown =
|
|
44
59
|
b.option(bool, "showdown", "Enable Pokémon Showdown compatibility mode") orelse false;
|
|
45
|
-
const
|
|
60
|
+
const log = b.option(bool, "log", "Enable protocol message logging") orelse false;
|
|
61
|
+
const chance = b.option(bool, "chance", "Enable update probability tracking") orelse false;
|
|
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");
|
|
46
64
|
|
|
47
65
|
const options = b.addOptions();
|
|
48
66
|
options.addOption(?bool, "showdown", showdown);
|
|
49
|
-
options.addOption(?bool, "
|
|
67
|
+
options.addOption(?bool, "log", log);
|
|
68
|
+
options.addOption(?bool, "chance", chance);
|
|
69
|
+
options.addOption(?bool, "calc", calc);
|
|
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
|
+
}
|
|
50
87
|
|
|
51
88
|
const name = if (showdown) "pkmn-showdown" else "pkmn";
|
|
52
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
|
+
|
|
53
97
|
var c = false;
|
|
54
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));
|
|
55
105
|
const addon = b.fmt("{s}.node", .{name});
|
|
56
|
-
const
|
|
106
|
+
const path = b.path("src/lib/node.zig");
|
|
107
|
+
const lib = b.addLibrary(.{
|
|
108
|
+
.linkage = .dynamic,
|
|
57
109
|
.name = addon,
|
|
58
|
-
.
|
|
59
|
-
|
|
60
|
-
|
|
110
|
+
.root_module = b.createModule(.{
|
|
111
|
+
.root_source_file = path,
|
|
112
|
+
.optimize = optimize,
|
|
113
|
+
.target = target,
|
|
114
|
+
.strip = strip,
|
|
115
|
+
.pic = pic,
|
|
116
|
+
}),
|
|
61
117
|
});
|
|
62
|
-
lib.addOptions("build_options", options);
|
|
63
|
-
lib.
|
|
64
|
-
lib.
|
|
65
|
-
lib.linkLibC();
|
|
118
|
+
lib.root_module.addOptions("build_options", options);
|
|
119
|
+
lib.root_module.addImport("napi", translate_c.createModule());
|
|
120
|
+
lib.root_module.link_libc = true;
|
|
66
121
|
if (node_import_lib) |il| {
|
|
67
|
-
lib.addObjectFile(il);
|
|
68
|
-
} else if (
|
|
69
|
-
|
|
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");
|
|
70
126
|
std.process.exit(1);
|
|
71
127
|
}
|
|
72
128
|
lib.linker_allow_shlib_undefined = true;
|
|
73
129
|
maybeStrip(b, lib, b.getInstallStep(), strip, cmd);
|
|
74
|
-
if (pic) lib.force_pic = pic;
|
|
75
130
|
// Always emit to build/lib because this is where the driver code expects to find it
|
|
76
|
-
// TODO
|
|
131
|
+
// TODO: ziglang/zig#2231 - using the following used to work (though was hacky):
|
|
77
132
|
//
|
|
78
133
|
// lib.emit_bin = .{ .emit_to = b.fmt("build/lib/{s}", .{addon}) };
|
|
79
134
|
// b.getInstallStep().dependOn(&lib.step);
|
|
80
135
|
//
|
|
81
136
|
// But ziglang/zig#14647 broke this so we now need to do an install() and then manually
|
|
82
137
|
// rename the file ourself in install-pkmn-engine
|
|
83
|
-
|
|
138
|
+
b.installArtifact(lib);
|
|
84
139
|
} else if (wasm) {
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
.target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
|
|
93
|
-
});
|
|
94
|
-
lib.addOptions("build_options", options);
|
|
95
|
-
lib.setMainPkgPath("./");
|
|
96
|
-
lib.stack_size = wasm_stack_size;
|
|
97
|
-
lib.rdynamic = true;
|
|
98
|
-
lib.strip = strip;
|
|
99
|
-
if (pic) lib.force_pic = pic;
|
|
100
|
-
const opt = b.findProgram(&.{"wasm-opt"}, &.{"./node_modules/.bin"}) catch null;
|
|
101
|
-
if (optimize != .Debug and opt != null) {
|
|
102
|
-
const out = b.fmt("build/lib/{s}.wasm", .{name});
|
|
103
|
-
const sh = b.addSystemCommand(&.{ opt.?, "-O4" });
|
|
104
|
-
sh.addArtifactArg(lib);
|
|
105
|
-
sh.addArg("-o");
|
|
106
|
-
sh.addFileSourceArg(.{ .path = out });
|
|
107
|
-
b.getInstallStep().dependOn(&sh.step);
|
|
108
|
-
}
|
|
109
|
-
lib.install();
|
|
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);
|
|
110
147
|
} else if (dynamic) {
|
|
111
|
-
const
|
|
148
|
+
const path = b.path("src/lib/c.zig");
|
|
149
|
+
const lib = b.addLibrary(.{
|
|
150
|
+
.linkage = .dynamic,
|
|
112
151
|
.name = name,
|
|
113
|
-
.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
152
|
+
.root_module = b.createModule(.{
|
|
153
|
+
.root_source_file = path,
|
|
154
|
+
.optimize = optimize,
|
|
155
|
+
.target = target,
|
|
156
|
+
.strip = strip,
|
|
157
|
+
.pic = pic,
|
|
158
|
+
}),
|
|
117
159
|
});
|
|
118
|
-
lib.addOptions("build_options", options);
|
|
119
|
-
lib.
|
|
120
|
-
lib.addIncludePath("src/include");
|
|
160
|
+
lib.root_module.addOptions("build_options", options);
|
|
161
|
+
lib.root_module.addIncludePath(b.path("src/include"));
|
|
121
162
|
maybeStrip(b, lib, b.getInstallStep(), strip, cmd);
|
|
122
|
-
|
|
123
|
-
lib.install();
|
|
163
|
+
b.installArtifact(lib);
|
|
124
164
|
c = true;
|
|
125
165
|
} else {
|
|
126
|
-
const
|
|
166
|
+
const path = b.path("src/lib/c.zig");
|
|
167
|
+
const lib = b.addLibrary(.{
|
|
168
|
+
.linkage = .static,
|
|
127
169
|
.name = name,
|
|
128
|
-
.
|
|
129
|
-
|
|
130
|
-
|
|
170
|
+
.root_module = b.createModule(.{
|
|
171
|
+
.root_source_file = path,
|
|
172
|
+
.optimize = optimize,
|
|
173
|
+
.target = target,
|
|
174
|
+
.strip = strip,
|
|
175
|
+
.pic = pic,
|
|
176
|
+
}),
|
|
131
177
|
});
|
|
132
|
-
lib.addOptions("build_options", options);
|
|
133
|
-
lib.
|
|
134
|
-
lib.addIncludePath("src/include");
|
|
178
|
+
lib.root_module.addOptions("build_options", options);
|
|
179
|
+
lib.root_module.addIncludePath(b.path("src/include"));
|
|
135
180
|
lib.bundle_compiler_rt = true;
|
|
136
181
|
maybeStrip(b, lib, b.getInstallStep(), strip, cmd);
|
|
137
|
-
if (
|
|
138
|
-
|
|
139
|
-
|
|
182
|
+
if (emit_asm) {
|
|
183
|
+
b.getInstallStep().dependOn(&b.addInstallFileWithDir(
|
|
184
|
+
lib.getEmittedAsm(),
|
|
185
|
+
.prefix,
|
|
186
|
+
b.fmt("{s}.s", .{name}),
|
|
187
|
+
).step);
|
|
188
|
+
}
|
|
189
|
+
if (emit_ll) {
|
|
190
|
+
b.getInstallStep().dependOn(&b.addInstallFileWithDir(
|
|
191
|
+
lib.getEmittedLlvmIr(),
|
|
192
|
+
.prefix,
|
|
193
|
+
b.fmt("{s}.ll", .{name}),
|
|
194
|
+
).step);
|
|
195
|
+
}
|
|
196
|
+
b.installArtifact(lib);
|
|
140
197
|
c = true;
|
|
141
198
|
}
|
|
142
199
|
|
|
143
200
|
if (c) {
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
.header,
|
|
147
|
-
"pkmn.h",
|
|
148
|
-
);
|
|
201
|
+
const path = b.path("src/include/pkmn.h");
|
|
202
|
+
const header = b.addInstallFileWithDir(path, .header, "pkmn.h");
|
|
149
203
|
b.getInstallStep().dependOn(&header.step);
|
|
150
204
|
|
|
151
205
|
const pc = b.fmt("lib{s}.pc", .{name});
|
|
152
|
-
const
|
|
153
|
-
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);
|
|
154
216
|
|
|
155
217
|
const dirname = comptime std.fs.path.dirname(@src().file) orelse ".";
|
|
156
|
-
|
|
157
|
-
try writer.print(
|
|
218
|
+
var writer = pkgconfig_file.writer(b.graph.io, &.{});
|
|
219
|
+
try writer.interface.print(
|
|
158
220
|
\\prefix={0s}/{1s}
|
|
159
221
|
\\includedir=${{prefix}}/include
|
|
160
222
|
\\libdir=${{prefix}}/lib
|
|
@@ -166,26 +228,32 @@ pub fn build(b: *std.Build) !void {
|
|
|
166
228
|
\\Cflags: -I${{includedir}}
|
|
167
229
|
\\Libs: -L${{libdir}} -l{2s}
|
|
168
230
|
, .{ dirname, b.install_path, name, repository.next().?, description, version });
|
|
169
|
-
defer pkgconfig_file.close();
|
|
170
231
|
|
|
171
232
|
b.installFile(file, b.fmt("share/pkgconfig/{s}", .{pc}));
|
|
172
233
|
}
|
|
173
234
|
|
|
174
|
-
const config = .{
|
|
235
|
+
const config: Config = .{
|
|
175
236
|
.target = target,
|
|
176
237
|
.optimize = optimize,
|
|
177
238
|
.pic = pic,
|
|
178
239
|
.strip = strip,
|
|
179
240
|
.cmd = cmd,
|
|
180
241
|
};
|
|
242
|
+
|
|
243
|
+
// TODO: tests can be run multiple times due to @imports
|
|
181
244
|
const tests = TestStep.create(b, options, config);
|
|
182
245
|
|
|
183
|
-
var exes
|
|
246
|
+
var exes: ArrayList(*std.Build.Step.Compile) = .empty;
|
|
184
247
|
const tools: ToolConfig = .{
|
|
248
|
+
.options = .{
|
|
249
|
+
.showdown = showdown,
|
|
250
|
+
.log = log,
|
|
251
|
+
.chance = chance,
|
|
252
|
+
.calc = calc,
|
|
253
|
+
},
|
|
254
|
+
.module = pkmn,
|
|
185
255
|
.general = config,
|
|
186
256
|
.tool = .{
|
|
187
|
-
.showdown = showdown,
|
|
188
|
-
.trace = trace,
|
|
189
257
|
.tests = if (tests.build) tests else null,
|
|
190
258
|
.exes = &exes,
|
|
191
259
|
},
|
|
@@ -194,39 +262,121 @@ pub fn build(b: *std.Build) !void {
|
|
|
194
262
|
var benchmark_config = tools;
|
|
195
263
|
benchmark_config.general.optimize = .ReleaseFast;
|
|
196
264
|
benchmark_config.general.strip = true;
|
|
197
|
-
const benchmark = tool(b, "src/test/benchmark.zig", benchmark_config);
|
|
265
|
+
const benchmark = try tool(b, "src/test/benchmark.zig", benchmark_config);
|
|
198
266
|
|
|
199
267
|
var fuzz_config = tools;
|
|
200
268
|
fuzz_config.general.strip = false;
|
|
201
269
|
fuzz_config.tool.name = "fuzz";
|
|
202
|
-
const fuzz = tool(b, "src/test/
|
|
270
|
+
const fuzz = try tool(b, "src/test/fuzz.zig", fuzz_config);
|
|
271
|
+
|
|
272
|
+
const analyze = try tool(b, "src/tools/analyze.zig", tools);
|
|
273
|
+
const dump = try tool(b, "src/tools/dump.zig", tools);
|
|
274
|
+
const transitions = try tool(b, "src/tools/transitions.zig", tools);
|
|
275
|
+
|
|
276
|
+
// FIXME: serde randomly fails to build in some release configurations
|
|
277
|
+
var hack = tools;
|
|
278
|
+
if (optimize != .Debug) hack.tool.tests = null;
|
|
279
|
+
const serde = try tool(b, "src/tools/serde.zig", hack);
|
|
280
|
+
|
|
281
|
+
if (analyze) |t| b.step("analyze", "Run LLVM analysis tool").dependOn(&t.step);
|
|
282
|
+
if (benchmark) |t| b.step("benchmark", "Run benchmark code").dependOn(&t.step);
|
|
283
|
+
if (dump) |t| b.step("dump", "Run protocol dump tool").dependOn(&t.step);
|
|
284
|
+
if (fuzz) |t| b.step("fuzz", "Run fuzz tester").dependOn(&t.step);
|
|
285
|
+
if (serde) |t| b.step("serde", "Run serialization/deserialization tool").dependOn(&t.step);
|
|
286
|
+
b.step("test", "Run all tests").dependOn(&tests.step);
|
|
287
|
+
b.step("tools", "Install tools").dependOn(&ToolsStep.create(b, &exes).step);
|
|
288
|
+
if (transitions) |t| {
|
|
289
|
+
b.step("transitions", "Visualize transitions algorithm search").dependOn(&t.step);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
203
292
|
|
|
204
|
-
|
|
205
|
-
|
|
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
|
+
});
|
|
206
343
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
const
|
|
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;
|
|
211
350
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
b.
|
|
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
|
+
}
|
|
219
370
|
}
|
|
220
371
|
|
|
221
372
|
fn maybeStrip(
|
|
222
373
|
b: *std.Build,
|
|
223
|
-
artifact: *std.Build.
|
|
374
|
+
artifact: *std.Build.Step.Compile,
|
|
224
375
|
step: *std.Build.Step,
|
|
225
|
-
strip: bool,
|
|
376
|
+
strip: ?bool,
|
|
226
377
|
cmd: ?[]const u8,
|
|
227
378
|
) void {
|
|
228
|
-
|
|
229
|
-
if (!strip or cmd == null) return;
|
|
379
|
+
if (!(strip orelse false) or cmd == null) return;
|
|
230
380
|
// Using `strip -r -u` for dynamic libraries is supposed to work on macOS but doesn't...
|
|
231
381
|
const mac = builtin.os.tag == .macos;
|
|
232
382
|
if (mac and artifact.isDynamicLibrary()) return;
|
|
@@ -238,111 +388,129 @@ fn maybeStrip(
|
|
|
238
388
|
}
|
|
239
389
|
|
|
240
390
|
const Config = struct {
|
|
241
|
-
target: std.
|
|
391
|
+
target: std.Build.ResolvedTarget,
|
|
242
392
|
optimize: std.builtin.OptimizeMode,
|
|
243
|
-
pic: bool,
|
|
244
|
-
strip: bool,
|
|
393
|
+
pic: ?bool,
|
|
394
|
+
strip: ?bool,
|
|
245
395
|
cmd: ?[]const u8,
|
|
246
396
|
};
|
|
247
397
|
|
|
248
|
-
const TESTS = .{
|
|
249
|
-
"src/lib/common/test.zig",
|
|
250
|
-
"src/lib/gen1/test.zig",
|
|
251
|
-
"src/lib/gen2/test.zig",
|
|
252
|
-
};
|
|
253
|
-
|
|
254
398
|
const TestStep = struct {
|
|
255
399
|
step: std.Build.Step,
|
|
256
400
|
build: bool,
|
|
257
401
|
|
|
258
|
-
pub fn create(b: *std.Build, options: *std.Build.
|
|
402
|
+
pub fn create(b: *std.Build, options: *std.Build.Step.Options, config: Config) *TestStep {
|
|
259
403
|
const coverage = b.option([]const u8, "test-coverage", "Generate test coverage");
|
|
260
|
-
const test_file = b.option([]const u8, "test-file", "Input file for test");
|
|
261
|
-
const test_bin = b.option([]const u8, "test-bin", "Emit test binary to");
|
|
262
404
|
const test_filter =
|
|
263
405
|
b.option([]const u8, "test-filter", "Skip tests that do not match filter");
|
|
264
|
-
const test_no_exec =
|
|
265
|
-
b.option(bool, "test-no-exec", "Compiles test binary without running it") orelse false;
|
|
266
406
|
|
|
267
407
|
const self = b.allocator.create(TestStep) catch @panic("OOM");
|
|
268
408
|
const step = std.Build.Step.init(.{ .id = .custom, .name = "Run all tests", .owner = b });
|
|
269
|
-
self.* =
|
|
270
|
-
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
.name = std.fs.path.basename(std.fs.path.dirname(path).?),
|
|
276
|
-
.root_source_file = .{ .path = path },
|
|
409
|
+
self.* = .{ .step = step, .build = test_filter == null };
|
|
410
|
+
|
|
411
|
+
const path = b.path("src/lib/test.zig");
|
|
412
|
+
const tests = b.addTest(.{
|
|
413
|
+
.root_module = b.createModule(.{
|
|
414
|
+
.root_source_file = path,
|
|
277
415
|
.optimize = config.optimize,
|
|
278
416
|
.target = config.target,
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
}
|
|
290
|
-
if (coverage) |c| {
|
|
291
|
-
tests.setExecCmd(&.{ "kcov", "--include-pattern=src/lib", c, null });
|
|
292
|
-
}
|
|
293
|
-
self.step.dependOn(if (test_no_exec) &tests.step else &tests.run().step);
|
|
417
|
+
.single_threaded = true,
|
|
418
|
+
.strip = config.strip,
|
|
419
|
+
.pic = config.pic,
|
|
420
|
+
}),
|
|
421
|
+
.filters = if (test_filter) |filter| &.{filter} else &.{},
|
|
422
|
+
});
|
|
423
|
+
tests.root_module.addOptions("build_options", options);
|
|
424
|
+
|
|
425
|
+
maybeStrip(b, tests, &tests.step, config.strip, config.cmd);
|
|
426
|
+
if (coverage) |c| {
|
|
427
|
+
tests.setExecCmd(&.{ "kcov", "--include-pattern=src/lib", c, null });
|
|
294
428
|
}
|
|
429
|
+
self.step.dependOn(&b.addRunArtifact(tests).step);
|
|
430
|
+
|
|
295
431
|
return self;
|
|
296
432
|
}
|
|
297
433
|
};
|
|
298
434
|
|
|
299
435
|
const ToolConfig = struct {
|
|
436
|
+
options: Options,
|
|
437
|
+
module: ?*std.Build.Module,
|
|
300
438
|
general: Config,
|
|
301
439
|
tool: struct {
|
|
302
|
-
showdown: bool,
|
|
303
|
-
trace: bool,
|
|
304
440
|
tests: ?*TestStep,
|
|
305
441
|
name: ?[]const u8 = null,
|
|
306
|
-
exes: *
|
|
442
|
+
exes: *ArrayList(*std.Build.Step.Compile),
|
|
307
443
|
},
|
|
308
444
|
};
|
|
309
445
|
|
|
310
|
-
fn tool(b: *std.Build, path: []const u8, config: ToolConfig)
|
|
446
|
+
fn tool(b: *std.Build, path: []const u8, config: ToolConfig) !?*std.Build.Step.Run {
|
|
447
|
+
if (!try exists(b, path)) return null;
|
|
311
448
|
var name = config.tool.name orelse std.fs.path.basename(path);
|
|
312
449
|
const index = std.mem.lastIndexOfScalar(u8, name, '.');
|
|
313
450
|
if (index) |i| name = name[0..i];
|
|
314
|
-
if (config.
|
|
451
|
+
if (config.options.showdown orelse false) name = b.fmt("{s}-showdown", .{name});
|
|
315
452
|
|
|
316
453
|
const exe = b.addExecutable(.{
|
|
317
454
|
.name = name,
|
|
318
|
-
.
|
|
319
|
-
|
|
320
|
-
|
|
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
|
+
}),
|
|
321
462
|
});
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
463
|
+
|
|
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
|
+
|
|
328
470
|
if (config.tool.tests) |ts| ts.step.dependOn(&exe.step);
|
|
329
|
-
config.tool.exes.append(exe) catch @panic("OOM");
|
|
471
|
+
config.tool.exes.append(b.allocator, exe) catch @panic("OOM");
|
|
330
472
|
|
|
331
|
-
const run =
|
|
473
|
+
const run = b.addRunArtifact(exe);
|
|
332
474
|
maybeStrip(b, exe, &run.step, config.general.strip, config.general.cmd);
|
|
333
475
|
if (b.args) |args| run.addArgs(args);
|
|
334
476
|
|
|
335
477
|
return run;
|
|
336
478
|
}
|
|
337
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
|
+
|
|
338
488
|
const ToolsStep = struct {
|
|
339
489
|
step: std.Build.Step,
|
|
340
490
|
|
|
341
|
-
pub fn create(b: *std.Build, exes: *
|
|
491
|
+
pub fn create(b: *std.Build, exes: *ArrayList(*std.Build.Step.Compile)) *ToolsStep {
|
|
342
492
|
const self = b.allocator.create(ToolsStep) catch @panic("OOM");
|
|
343
493
|
const step = std.Build.Step.init(.{ .id = .custom, .name = "Install tools", .owner = b });
|
|
344
|
-
self.* =
|
|
345
|
-
for (exes.items) |t| self.step.dependOn(&b.addInstallArtifact(t).step);
|
|
494
|
+
self.* = .{ .step = step };
|
|
495
|
+
for (exes.items) |t| self.step.dependOn(&b.addInstallArtifact(t, .{}).step);
|
|
346
496
|
return self;
|
|
347
497
|
}
|
|
348
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
|
+
}
|