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