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