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