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