@pkmn/engine 0.1.0-dev.d56bdadd → 0.1.0-dev.d73cd76c
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 +66 -32
- 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/layout.json +15 -2
- package/build/pkg/data/protocol.json +23 -9
- 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 +28 -19
- 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 +109 -107
- 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 +357 -135
- package/package.json +61 -132
- 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 +4 -4
- package/src/lib/common/debug.zig +45 -29
- package/src/lib/common/js.zig +3 -7
- package/src/lib/common/optional.zig +27 -23
- package/src/lib/common/options.zig +6 -0
- package/src/lib/common/protocol.zig +565 -552
- package/src/lib/common/rational.zig +340 -253
- package/src/lib/common/rng.zig +7 -9
- package/src/lib/common/util.zig +53 -1
- package/src/lib/gen1/calc.zig +724 -175
- package/src/lib/gen1/chance.zig +486 -300
- package/src/lib/gen1/data/moves.zig +2 -4
- package/src/lib/gen1/data/species.zig +2 -4
- package/src/lib/gen1/data/types.zig +3 -4
- package/src/lib/gen1/data.zig +29 -32
- package/src/lib/gen1/helpers.zig +113 -561
- package/src/lib/gen1/mechanics.zig +611 -488
- package/src/lib/gen2/calc.zig +35 -28
- package/src/lib/gen2/chance.zig +111 -511
- package/src/lib/gen2/data/items.zig +1 -3
- package/src/lib/gen2/data/moves.zig +2 -4
- package/src/lib/gen2/data/species.zig +1 -3
- package/src/lib/gen2/data/types.zig +7 -5
- package/src/lib/gen2/data.zig +27 -29
- package/src/lib/gen2/generated.zig +22 -29
- package/src/lib/gen2/helpers.zig +68 -39
- package/src/lib/gen2/mechanics.zig +504 -430
- 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 -894
- package/src/lib/gen2/README.md +0 -329
- 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
|
-
|
|
72
|
-
|
|
124
|
+
.root_module = b.createModule(.{
|
|
125
|
+
.root_source_file = path,
|
|
126
|
+
.optimize = optimize,
|
|
127
|
+
.target = target,
|
|
128
|
+
.strip = strip,
|
|
129
|
+
.pic = pic,
|
|
130
|
+
}),
|
|
73
131
|
});
|
|
74
|
-
lib.addOptions("build_options", options);
|
|
75
|
-
lib.
|
|
76
|
-
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;
|
|
77
135
|
if (node_import_lib) |il| {
|
|
78
|
-
lib.addObjectFile(.
|
|
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,59 +151,50 @@ 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
|
-
},
|
|
104
|
-
.target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
|
|
105
|
-
});
|
|
106
|
-
lib.addOptions("build_options", options);
|
|
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
|
-
|
|
128
|
-
|
|
166
|
+
.root_module = b.createModule(.{
|
|
167
|
+
.root_source_file = path,
|
|
168
|
+
.optimize = optimize,
|
|
169
|
+
.target = target,
|
|
170
|
+
.strip = strip,
|
|
171
|
+
.pic = pic,
|
|
172
|
+
}),
|
|
129
173
|
});
|
|
130
|
-
lib.addOptions("build_options", options);
|
|
131
|
-
lib.addIncludePath(.
|
|
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
|
-
|
|
142
|
-
|
|
184
|
+
.root_module = b.createModule(.{
|
|
185
|
+
.root_source_file = path,
|
|
186
|
+
.optimize = optimize,
|
|
187
|
+
.target = target,
|
|
188
|
+
.strip = strip,
|
|
189
|
+
.pic = pic,
|
|
190
|
+
}),
|
|
143
191
|
});
|
|
144
|
-
lib.addOptions("build_options", options);
|
|
145
|
-
lib.addIncludePath(.
|
|
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 (pic) lib.force_pic = pic;
|
|
149
198
|
if (emit_asm) {
|
|
150
199
|
b.getInstallStep().dependOn(&b.addInstallFileWithDir(
|
|
151
200
|
lib.getEmittedAsm(),
|
|
@@ -160,42 +209,59 @@ pub fn build(b: *std.Build) !void {
|
|
|
160
209
|
b.fmt("{s}.ll", .{name}),
|
|
161
210
|
).step);
|
|
162
211
|
}
|
|
163
|
-
b.
|
|
212
|
+
const install = b.addInstallArtifact(lib, .{});
|
|
213
|
+
b.getInstallStep().dependOn(&install.step);
|
|
214
|
+
maybeRanlib(b, lib, &install.step);
|
|
164
215
|
c = true;
|
|
165
216
|
}
|
|
166
217
|
|
|
167
218
|
if (c) {
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
.header,
|
|
171
|
-
"pkmn.h",
|
|
172
|
-
);
|
|
219
|
+
const path = b.path("src/include/pkmn.h");
|
|
220
|
+
const header = b.addInstallFileWithDir(path, .header, "pkmn.h");
|
|
173
221
|
b.getInstallStep().dependOn(&header.step);
|
|
174
222
|
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
const pkgconfig_file = try std.fs.cwd().createFile(file, .{});
|
|
178
|
-
|
|
179
|
-
const dirname = comptime std.fs.path.dirname(@src().file) orelse ".";
|
|
180
|
-
const writer = pkgconfig_file.writer();
|
|
181
|
-
try writer.print(
|
|
182
|
-
\\prefix={0s}/{1s}
|
|
223
|
+
const content = try std.fmt.allocPrint(b.allocator,
|
|
224
|
+
\\prefix=${{pcfiledir}}/../..
|
|
183
225
|
\\includedir=${{prefix}}/include
|
|
184
226
|
\\libdir=${{prefix}}/lib
|
|
185
227
|
\\
|
|
186
|
-
\\Name: lib{
|
|
187
|
-
\\URL: https://github.com/{
|
|
188
|
-
\\Description: {
|
|
189
|
-
\\Version: {
|
|
228
|
+
\\Name: lib{0s}
|
|
229
|
+
\\URL: https://github.com/{1s}
|
|
230
|
+
\\Description: {2s}
|
|
231
|
+
\\Version: {3s}
|
|
190
232
|
\\Cflags: -I${{includedir}}
|
|
191
|
-
\\Libs: -L${{libdir}} -l{
|
|
192
|
-
, .{
|
|
193
|
-
defer pkgconfig_file.close();
|
|
233
|
+
\\Libs: -L${{libdir}} -l{0s}
|
|
234
|
+
, .{ name, repository.next().?, description, version });
|
|
194
235
|
|
|
195
|
-
|
|
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
|
+
}
|
|
196
262
|
}
|
|
197
263
|
|
|
198
|
-
const config = .{
|
|
264
|
+
const config: Config = .{
|
|
199
265
|
.target = target,
|
|
200
266
|
.optimize = optimize,
|
|
201
267
|
.pic = pic,
|
|
@@ -206,7 +272,7 @@ pub fn build(b: *std.Build) !void {
|
|
|
206
272
|
// TODO: tests can be run multiple times due to @imports
|
|
207
273
|
const tests = TestStep.create(b, options, config);
|
|
208
274
|
|
|
209
|
-
var exes
|
|
275
|
+
var exes: ArrayList(*std.Build.Step.Compile) = .empty;
|
|
210
276
|
const tools: ToolConfig = .{
|
|
211
277
|
.options = .{
|
|
212
278
|
.showdown = showdown,
|
|
@@ -245,22 +311,105 @@ pub fn build(b: *std.Build) !void {
|
|
|
245
311
|
if (dump) |t| b.step("dump", "Run protocol dump tool").dependOn(&t.step);
|
|
246
312
|
if (fuzz) |t| b.step("fuzz", "Run fuzz tester").dependOn(&t.step);
|
|
247
313
|
if (serde) |t| b.step("serde", "Run serialization/deserialization tool").dependOn(&t.step);
|
|
248
|
-
b.step("test", "Run all tests").dependOn(
|
|
249
|
-
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);
|
|
250
316
|
if (transitions) |t| {
|
|
251
317
|
b.step("transitions", "Visualize transitions algorithm search").dependOn(&t.step);
|
|
252
318
|
}
|
|
253
319
|
}
|
|
254
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
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
255
405
|
fn maybeStrip(
|
|
256
406
|
b: *std.Build,
|
|
257
|
-
artifact: *std.Build.
|
|
407
|
+
artifact: *std.Build.Step.Compile,
|
|
258
408
|
step: *std.Build.Step,
|
|
259
|
-
strip: bool,
|
|
409
|
+
strip: ?bool,
|
|
260
410
|
cmd: ?[]const u8,
|
|
261
411
|
) void {
|
|
262
|
-
|
|
263
|
-
if (!strip or cmd == null) return;
|
|
412
|
+
if (!(strip orelse false) or cmd == null) return;
|
|
264
413
|
// Using `strip -r -u` for dynamic libraries is supposed to work on macOS but doesn't...
|
|
265
414
|
const mac = builtin.os.tag == .macos;
|
|
266
415
|
if (mac and artifact.isDynamicLibrary()) return;
|
|
@@ -272,47 +421,48 @@ fn maybeStrip(
|
|
|
272
421
|
}
|
|
273
422
|
|
|
274
423
|
const Config = struct {
|
|
275
|
-
target: std.
|
|
424
|
+
target: std.Build.ResolvedTarget,
|
|
276
425
|
optimize: std.builtin.OptimizeMode,
|
|
277
|
-
pic: bool,
|
|
278
|
-
strip: bool,
|
|
426
|
+
pic: ?bool,
|
|
427
|
+
strip: ?bool,
|
|
279
428
|
cmd: ?[]const u8,
|
|
280
429
|
};
|
|
281
430
|
|
|
282
431
|
const TestStep = struct {
|
|
283
|
-
step: std.Build.Step,
|
|
432
|
+
step: *std.Build.Step,
|
|
284
433
|
build: bool,
|
|
285
434
|
|
|
286
|
-
pub fn create(b: *std.Build, options: *std.Build.
|
|
435
|
+
pub fn create(b: *std.Build, options: *std.Build.Step.Options, config: Config) *TestStep {
|
|
287
436
|
const coverage = b.option([]const u8, "test-coverage", "Generate test coverage");
|
|
288
|
-
const test_file = b.option([]const u8, "test-file", "Input file for test");
|
|
289
437
|
const test_filter =
|
|
290
438
|
b.option([]const u8, "test-filter", "Skip tests that do not match filter");
|
|
291
439
|
|
|
292
440
|
const self = b.allocator.create(TestStep) catch @panic("OOM");
|
|
293
|
-
const step = std.Build.Step.init(.{ .id = .custom, .name = "Run all tests", .owner = b });
|
|
294
|
-
self.* = .{ .step = step, .build = test_filter == null };
|
|
295
441
|
|
|
296
|
-
const path =
|
|
442
|
+
const path = b.path("src/lib/test.zig");
|
|
297
443
|
const tests = b.addTest(.{
|
|
298
|
-
.
|
|
299
|
-
|
|
300
|
-
|
|
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,
|
|
301
451
|
}),
|
|
302
|
-
.
|
|
303
|
-
.root_source_file = .{ .path = path },
|
|
304
|
-
.optimize = config.optimize,
|
|
305
|
-
.target = config.target,
|
|
306
|
-
.filter = test_filter,
|
|
452
|
+
.filters = if (test_filter) |filter| &.{filter} else &.{},
|
|
307
453
|
});
|
|
308
|
-
tests.addOptions("build_options", options);
|
|
309
|
-
|
|
454
|
+
tests.root_module.addOptions("build_options", options);
|
|
455
|
+
|
|
310
456
|
maybeStrip(b, tests, &tests.step, config.strip, config.cmd);
|
|
311
|
-
if (config.pic) tests.force_pic = config.pic;
|
|
312
457
|
if (coverage) |c| {
|
|
313
|
-
|
|
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 };
|
|
314
465
|
}
|
|
315
|
-
self.step.dependOn(&b.addRunArtifact(tests).step);
|
|
316
466
|
|
|
317
467
|
return self;
|
|
318
468
|
}
|
|
@@ -324,15 +474,12 @@ const ToolConfig = struct {
|
|
|
324
474
|
tool: struct {
|
|
325
475
|
tests: ?*TestStep,
|
|
326
476
|
name: ?[]const u8 = null,
|
|
327
|
-
exes: *
|
|
477
|
+
exes: *ArrayList(*std.Build.Step.Compile),
|
|
328
478
|
},
|
|
329
479
|
};
|
|
330
480
|
|
|
331
|
-
fn tool(b: *std.Build, path: []const u8, config: ToolConfig) !?*std.Build.
|
|
332
|
-
|
|
333
|
-
error.FileNotFound => return null,
|
|
334
|
-
else => |e| return e,
|
|
335
|
-
};
|
|
481
|
+
fn tool(b: *std.Build, path: []const u8, config: ToolConfig) !?*std.Build.Step.Run {
|
|
482
|
+
if (!try exists(b, path)) return null;
|
|
336
483
|
var name = config.tool.name orelse std.fs.path.basename(path);
|
|
337
484
|
const index = std.mem.lastIndexOfScalar(u8, name, '.');
|
|
338
485
|
if (index) |i| name = name[0..i];
|
|
@@ -340,32 +487,107 @@ fn tool(b: *std.Build, path: []const u8, config: ToolConfig) !?*std.Build.RunSte
|
|
|
340
487
|
|
|
341
488
|
const exe = b.addExecutable(.{
|
|
342
489
|
.name = name,
|
|
343
|
-
.
|
|
344
|
-
|
|
345
|
-
|
|
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
|
+
}),
|
|
346
497
|
});
|
|
347
|
-
exe.addModule("pkmn", module(b, config.options));
|
|
348
498
|
|
|
349
|
-
|
|
350
|
-
|
|
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", .{});
|
|
503
|
+
}
|
|
504
|
+
|
|
351
505
|
if (config.tool.tests) |ts| ts.step.dependOn(&exe.step);
|
|
352
|
-
config.tool.exes.append(exe) catch @panic("OOM");
|
|
506
|
+
config.tool.exes.append(b.allocator, exe) catch @panic("OOM");
|
|
353
507
|
|
|
354
508
|
const run = b.addRunArtifact(exe);
|
|
355
509
|
maybeStrip(b, exe, &run.step, config.general.strip, config.general.cmd);
|
|
356
|
-
if (
|
|
510
|
+
if (@hasDecl(std.Build, "FindProgramOptions")) {
|
|
511
|
+
run.addPassthruArgs();
|
|
512
|
+
} else {
|
|
513
|
+
if (b.args) |args| run.addArgs(args);
|
|
514
|
+
}
|
|
357
515
|
|
|
358
516
|
return run;
|
|
359
517
|
}
|
|
360
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
|
+
|
|
361
527
|
const ToolsStep = struct {
|
|
362
|
-
step: std.Build.Step,
|
|
528
|
+
step: *std.Build.Step,
|
|
363
529
|
|
|
364
|
-
pub fn create(b: *std.Build, exes: *
|
|
530
|
+
pub fn create(b: *std.Build, exes: *ArrayList(*std.Build.Step.Compile)) *ToolsStep {
|
|
365
531
|
const self = b.allocator.create(ToolsStep) catch @panic("OOM");
|
|
366
|
-
|
|
367
|
-
|
|
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
|
+
}
|
|
368
553
|
for (exes.items) |t| self.step.dependOn(&b.addInstallArtifact(t, .{}).step);
|
|
554
|
+
|
|
369
555
|
return self;
|
|
370
556
|
}
|
|
371
557
|
};
|
|
558
|
+
|
|
559
|
+
pub fn exports(b: *std.Build, bytes: []const u8) ![][]const u8 {
|
|
560
|
+
var symbols: ArrayList([]const u8) = .empty;
|
|
561
|
+
|
|
562
|
+
var it = std.mem.splitSequence(u8, bytes, "export ");
|
|
563
|
+
_ = it.next();
|
|
564
|
+
while (it.next()) |s| {
|
|
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
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
return symbols.items;
|
|
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
|
+
}
|