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