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