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