@pkmn/engine 0.1.0-dev.47dcb76c → 0.1.0-dev.47f842bf
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 +65 -15
- 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 +25 -3
- 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 +25 -4
- 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 +20 -1
- package/build/pkg/protocol.js +109 -107
- package/build/pkg/protocol.js.map +1 -1
- package/build/tools/debug.js +53 -78
- package/build/tools/debug.js.map +1 -1
- package/build/tools/display/debug.jsx +152 -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 +359 -0
- package/build/tools/display/ui.jsx.map +1 -0
- package/build/tools/display/util.js +33 -0
- package/build/tools/display/util.js.map +1 -0
- package/build.zig +309 -79
- package/package.json +55 -135
- package/src/bin/install-pkmn-engine +19 -8
- package/src/bin/pkmn-debug +1 -1
- package/src/lib/bindings/c.zig +255 -0
- package/src/lib/bindings/node.zig +117 -0
- package/src/lib/bindings/wasm.zig +59 -0
- package/src/lib/common/array.zig +77 -0
- package/src/lib/common/data.zig +8 -8
- package/src/lib/common/debug.zig +39 -8
- package/src/lib/common/js.zig +4 -6
- package/src/lib/common/napi.zig +4 -0
- package/src/lib/common/optional.zig +13 -9
- package/src/lib/common/options.zig +6 -0
- package/src/lib/common/protocol.zig +50 -44
- package/src/lib/common/rational.zig +406 -166
- package/src/lib/common/rng.zig +5 -7
- package/src/lib/common/util.zig +65 -1
- package/src/lib/gen1/calc.zig +695 -159
- package/src/lib/gen1/chance.zig +415 -290
- package/src/lib/gen1/data/moves.zig +2 -4
- package/src/lib/gen1/data/species.zig +1 -3
- package/src/lib/gen1/data/types.zig +2 -3
- package/src/lib/gen1/data.zig +38 -41
- package/src/lib/gen1/helpers.zig +92 -548
- package/src/lib/gen1/mechanics.zig +342 -245
- package/src/lib/gen2/calc.zig +37 -27
- package/src/lib/gen2/chance.zig +90 -502
- 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 +28 -30
- package/src/lib/gen2/generated.zig +18 -23
- package/src/lib/gen2/helpers.zig +46 -25
- package/src/lib/gen2/mechanics.zig +199 -141
- package/src/lib/node.zig +4 -121
- package/src/lib/pkmn.zig +17 -18
- package/src/lib/wasm.zig +13 -9
- package/src/tools/display/dom.ts +93 -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/test/display/pkmn.html.tmpl +0 -368
package/build.zig
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const std = @import("std");
|
|
2
1
|
const builtin = @import("builtin");
|
|
2
|
+
const std = @import("std");
|
|
3
3
|
|
|
4
4
|
pub const Options = struct {
|
|
5
5
|
showdown: ?bool = null,
|
|
@@ -8,6 +8,17 @@ pub const Options = struct {
|
|
|
8
8
|
calc: ?bool = null,
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
+
const Step = if (@hasDecl(std.Build, "Step")) std.Build.Step else .{
|
|
12
|
+
.Compile = std.Build.CompileStep,
|
|
13
|
+
.Options = std.Build.OptionsStep,
|
|
14
|
+
.Run = std.Build.RunStep,
|
|
15
|
+
};
|
|
16
|
+
const has_path = @hasField(std.Build.LazyPath, "path");
|
|
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
|
+
|
|
11
22
|
pub fn module(b: *std.Build, options: Options) *std.Build.Module {
|
|
12
23
|
const dirname = comptime std.fs.path.dirname(@src().file) orelse ".";
|
|
13
24
|
const build_options = b.addOptions();
|
|
@@ -15,25 +26,39 @@ pub fn module(b: *std.Build, options: Options) *std.Build.Module {
|
|
|
15
26
|
build_options.addOption(?bool, "log", options.log);
|
|
16
27
|
build_options.addOption(?bool, "chance", options.chance);
|
|
17
28
|
build_options.addOption(?bool, "calc", options.calc);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
.
|
|
21
|
-
|
|
29
|
+
|
|
30
|
+
const root_source_file: std.Build.LazyPath =
|
|
31
|
+
.{ .cwd_relative = dirname ++ "/src/lib/pkmn.zig" };
|
|
32
|
+
const Import = if (@hasDecl(std.Build.Module, "Import"))
|
|
33
|
+
std.Build.Module.Import
|
|
34
|
+
else
|
|
35
|
+
std.Build.ModuleDependency;
|
|
36
|
+
const imports: []const Import =
|
|
37
|
+
&.{.{ .name = "build_options", .module = build_options.createModule() }};
|
|
38
|
+
return b.createModule(if (@hasDecl(std.Build, "CreateModuleOptions"))
|
|
39
|
+
.{ .source_file = root_source_file, .dependencies = imports }
|
|
40
|
+
else
|
|
41
|
+
.{ .root_source_file = root_source_file, .imports = imports });
|
|
22
42
|
}
|
|
23
43
|
|
|
24
44
|
pub fn build(b: *std.Build) !void {
|
|
25
45
|
const target = b.standardTargetOptions(.{});
|
|
26
46
|
const optimize = b.standardOptimizeOption(.{});
|
|
27
47
|
|
|
48
|
+
const default: ?bool = if (force_pic) false else null;
|
|
28
49
|
const node_headers = b.option([]const u8, "node-headers", "Path to node-headers");
|
|
29
50
|
const node_import_lib =
|
|
30
51
|
b.option([]const u8, "node-import-library", "Path to node import library (Windows)");
|
|
52
|
+
const demo = if (try exists("src/tools/demo.zig"))
|
|
53
|
+
b.option(bool, "demo", "Build the demo library") orelse false
|
|
54
|
+
else
|
|
55
|
+
false;
|
|
31
56
|
const wasm = b.option(bool, "wasm", "Build a WASM library") orelse false;
|
|
32
57
|
const wasm_stack_size =
|
|
33
58
|
b.option(u64, "wasm-stack-size", "The size of WASM stack") orelse std.wasm.page_size;
|
|
34
59
|
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");
|
|
60
|
+
const strip = b.option(bool, "strip", "Strip debugging symbols from binary") orelse default;
|
|
61
|
+
const pic = b.option(bool, "pic", "Force position independent code") orelse default;
|
|
37
62
|
const emit_asm = b.option(bool, "emit-asm", "Output .s (assembly code)") orelse false;
|
|
38
63
|
const emit_ll = b.option(bool, "emit-ll", "Output .ll (LLVM IR)") orelse false;
|
|
39
64
|
|
|
@@ -44,14 +69,22 @@ pub fn build(b: *std.Build) !void {
|
|
|
44
69
|
defer parsed.deinit();
|
|
45
70
|
const version = parsed.value.object.get("version").?.string;
|
|
46
71
|
const description = parsed.value.object.get("description").?.string;
|
|
47
|
-
var repository = std.mem.
|
|
72
|
+
var repository = std.mem.splitSequence(u8, parsed.value.object.get("repository").?.string, ":");
|
|
48
73
|
std.debug.assert(std.mem.eql(u8, repository.first(), "github"));
|
|
49
74
|
|
|
75
|
+
const fast = try std.SemanticVersion.parse("0.12.0-dev.866+3a47bc715");
|
|
76
|
+
const patched = std.mem.endsWith(u8, builtin.zig_version_string, "patched");
|
|
77
|
+
if (optimize != .Debug and fast.order(builtin.zig_version) == .lt and !patched) {
|
|
78
|
+
std.log.warn("Release builds are ~10-20% slower than before Zig " ++
|
|
79
|
+
"v0.12.0-dev.866+3a47bc715 due to ziglang/zig#17768", .{});
|
|
80
|
+
}
|
|
81
|
+
|
|
50
82
|
const showdown =
|
|
51
83
|
b.option(bool, "showdown", "Enable Pokémon Showdown compatibility mode") orelse false;
|
|
52
84
|
const log = b.option(bool, "log", "Enable protocol message logging") orelse false;
|
|
53
85
|
const chance = b.option(bool, "chance", "Enable update probability tracking") orelse false;
|
|
54
86
|
const calc = b.option(bool, "calc", "Enable damage calculator support") orelse false;
|
|
87
|
+
const extra = b.option([]const []const u8, "option", "Enable extra option");
|
|
55
88
|
|
|
56
89
|
const options = b.addOptions();
|
|
57
90
|
options.addOption(?bool, "showdown", showdown);
|
|
@@ -59,30 +92,67 @@ pub fn build(b: *std.Build) !void {
|
|
|
59
92
|
options.addOption(?bool, "chance", chance);
|
|
60
93
|
options.addOption(?bool, "calc", calc);
|
|
61
94
|
|
|
95
|
+
if (extra) |opts| {
|
|
96
|
+
for (opts) |opt| {
|
|
97
|
+
if (std.mem.indexOfScalar(u8, opt, '=')) |i| {
|
|
98
|
+
options.addOption(?bool, opt[0..i], if (std.mem.eql(u8, opt[i + 1 ..], "true"))
|
|
99
|
+
true
|
|
100
|
+
else if (std.mem.eql(u8, opt[i + 1 ..], "false"))
|
|
101
|
+
false
|
|
102
|
+
else {
|
|
103
|
+
std.log.err("Invalid option: {s}\n", .{opt});
|
|
104
|
+
return error.InvalidOption;
|
|
105
|
+
});
|
|
106
|
+
} else {
|
|
107
|
+
options.addOption(?bool, opt, true);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
62
112
|
const name = if (showdown) "pkmn-showdown" else "pkmn";
|
|
63
113
|
|
|
114
|
+
const pkmn: ?*std.Build.Module = if (@hasDecl(std.Build, "CreateModuleOptions"))
|
|
115
|
+
null
|
|
116
|
+
else
|
|
117
|
+
b.addModule("pkmn", .{
|
|
118
|
+
.root_source_file = if (has_path)
|
|
119
|
+
.{ .path = "src/lib/pkmn.zig" }
|
|
120
|
+
else
|
|
121
|
+
b.path("src/lib/pkmn.zig"),
|
|
122
|
+
.optimize = optimize,
|
|
123
|
+
.target = target,
|
|
124
|
+
.imports = &.{.{ .name = "build_options", .module = options.createModule() }},
|
|
125
|
+
});
|
|
126
|
+
|
|
64
127
|
var c = false;
|
|
65
128
|
if (node_headers) |headers| {
|
|
66
129
|
const addon = b.fmt("{s}.node", .{name});
|
|
67
|
-
const
|
|
130
|
+
const path = if (has_path) .{ .path = "src/lib/node.zig" } else b.path("src/lib/node.zig");
|
|
131
|
+
const lib = b.addSharedLibrary(if (force_pic) .{
|
|
132
|
+
.name = addon,
|
|
133
|
+
.root_source_file = path,
|
|
134
|
+
.optimize = optimize,
|
|
135
|
+
.target = target,
|
|
136
|
+
} else .{
|
|
68
137
|
.name = addon,
|
|
69
|
-
.root_source_file =
|
|
138
|
+
.root_source_file = path,
|
|
70
139
|
.optimize = optimize,
|
|
71
140
|
.target = target,
|
|
72
141
|
.strip = strip,
|
|
73
142
|
.pic = pic,
|
|
74
143
|
});
|
|
75
|
-
lib.root_module.addOptions("build_options", options);
|
|
76
|
-
lib.addSystemIncludePath(.{ .path = headers });
|
|
144
|
+
(if (root_module) lib.root_module else lib).addOptions("build_options", options);
|
|
145
|
+
lib.addSystemIncludePath(if (has_path) .{ .path = headers } else b.path(headers));
|
|
77
146
|
lib.linkLibC();
|
|
78
147
|
if (node_import_lib) |il| {
|
|
79
|
-
lib.addObjectFile(.{ .path = il });
|
|
80
|
-
} else if (target.
|
|
148
|
+
lib.addObjectFile(if (has_path) .{ .path = il } else b.path(il));
|
|
149
|
+
} else if (detect(target).os.tag == .windows) {
|
|
81
150
|
try std.io.getStdErr().writeAll("Must provide --node-import-library path on Windows\n");
|
|
82
151
|
std.process.exit(1);
|
|
83
152
|
}
|
|
84
153
|
lib.linker_allow_shlib_undefined = true;
|
|
85
154
|
maybeStrip(b, lib, b.getInstallStep(), strip, cmd);
|
|
155
|
+
if (force_pic and pic orelse false) lib.force_pic = pic;
|
|
86
156
|
// Always emit to build/lib because this is where the driver code expects to find it
|
|
87
157
|
// TODO: ziglang/zig#2231 - using the following used to work (though was hacky):
|
|
88
158
|
//
|
|
@@ -93,69 +163,61 @@ pub fn build(b: *std.Build) !void {
|
|
|
93
163
|
// rename the file ourself in install-pkmn-engine
|
|
94
164
|
b.installArtifact(lib);
|
|
95
165
|
} else if (wasm) {
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
.
|
|
104
|
-
.
|
|
105
|
-
.
|
|
166
|
+
const path = "src/lib/wasm.zig";
|
|
167
|
+
try buildWasm(b, name, path, optimize, strip, pic, wasm_stack_size, null, options);
|
|
168
|
+
} else if (demo) {
|
|
169
|
+
const path = "src/tools/demo.zig";
|
|
170
|
+
const n = if (showdown) "demo-showdown" else "demo";
|
|
171
|
+
const mod = pkmn orelse module(b, .{
|
|
172
|
+
.showdown = showdown,
|
|
173
|
+
.log = log,
|
|
174
|
+
.chance = chance,
|
|
175
|
+
.calc = calc,
|
|
106
176
|
});
|
|
107
|
-
|
|
108
|
-
exe.root_module.export_symbol_names = &[_][]const u8{
|
|
109
|
-
"SHOWDOWN",
|
|
110
|
-
"LOG",
|
|
111
|
-
"CHANCE",
|
|
112
|
-
"CALC",
|
|
113
|
-
"GEN1_CHOICES_SIZE",
|
|
114
|
-
"GEN1_LOGS_SIZE",
|
|
115
|
-
};
|
|
116
|
-
exe.entry = .disabled;
|
|
117
|
-
exe.stack_size = wasm_stack_size;
|
|
118
|
-
const opt = b.findProgram(&.{"wasm-opt"}, &.{"./node_modules/.bin"}) catch null;
|
|
119
|
-
if (optimize != .Debug and opt != null) {
|
|
120
|
-
const out = b.fmt("build/lib/{s}.wasm", .{name});
|
|
121
|
-
const sh = b.addSystemCommand(&.{ opt.?, "-O4" });
|
|
122
|
-
sh.addArtifactArg(exe);
|
|
123
|
-
sh.addArg("-o");
|
|
124
|
-
sh.addFileArg(.{ .path = out });
|
|
125
|
-
b.getInstallStep().dependOn(&sh.step);
|
|
126
|
-
} else {
|
|
127
|
-
b.getInstallStep().dependOn(&b.addInstallArtifact(exe, .{
|
|
128
|
-
.dest_dir = .{ .override = std.Build.InstallDir{ .lib = {} } },
|
|
129
|
-
}).step);
|
|
130
|
-
}
|
|
177
|
+
try buildWasm(b, n, path, optimize, strip, pic, wasm_stack_size, mod, options);
|
|
131
178
|
} else if (dynamic) {
|
|
132
|
-
const
|
|
179
|
+
const path = if (has_path) .{ .path = "src/lib/c.zig" } else b.path("src/lib/c.zig");
|
|
180
|
+
const lib = b.addSharedLibrary(if (force_pic) .{
|
|
181
|
+
.name = name,
|
|
182
|
+
.root_source_file = path,
|
|
183
|
+
.version = try std.SemanticVersion.parse(version),
|
|
184
|
+
.optimize = optimize,
|
|
185
|
+
.target = target,
|
|
186
|
+
} else .{
|
|
133
187
|
.name = name,
|
|
134
|
-
.root_source_file =
|
|
188
|
+
.root_source_file = path,
|
|
135
189
|
.version = try std.SemanticVersion.parse(version),
|
|
136
190
|
.optimize = optimize,
|
|
137
191
|
.target = target,
|
|
138
192
|
.strip = strip,
|
|
139
193
|
.pic = pic,
|
|
140
194
|
});
|
|
141
|
-
lib.root_module.addOptions("build_options", options);
|
|
142
|
-
lib.addIncludePath(.{ .path = "src/include" });
|
|
195
|
+
(if (root_module) lib.root_module else lib).addOptions("build_options", options);
|
|
196
|
+
lib.addIncludePath(if (has_path) .{ .path = "src/include" } else b.path("src/include"));
|
|
143
197
|
maybeStrip(b, lib, b.getInstallStep(), strip, cmd);
|
|
198
|
+
if (force_pic and pic orelse false) lib.force_pic = pic;
|
|
144
199
|
b.installArtifact(lib);
|
|
145
200
|
c = true;
|
|
146
201
|
} else {
|
|
147
|
-
const
|
|
202
|
+
const path = if (has_path) .{ .path = "src/lib/c.zig" } else b.path("src/lib/c.zig");
|
|
203
|
+
const lib = b.addStaticLibrary(if (force_pic) .{
|
|
148
204
|
.name = name,
|
|
149
|
-
.root_source_file =
|
|
205
|
+
.root_source_file = path,
|
|
206
|
+
.optimize = optimize,
|
|
207
|
+
.target = target,
|
|
208
|
+
} else .{
|
|
209
|
+
.name = name,
|
|
210
|
+
.root_source_file = path,
|
|
150
211
|
.optimize = optimize,
|
|
151
212
|
.target = target,
|
|
152
213
|
.strip = strip,
|
|
153
214
|
.pic = pic,
|
|
154
215
|
});
|
|
155
|
-
lib.root_module.addOptions("build_options", options);
|
|
156
|
-
lib.addIncludePath(.{ .path = "src/include" });
|
|
216
|
+
(if (root_module) lib.root_module else lib).addOptions("build_options", options);
|
|
217
|
+
lib.addIncludePath(if (has_path) .{ .path = "src/include" } else b.path("src/include"));
|
|
157
218
|
lib.bundle_compiler_rt = true;
|
|
158
219
|
maybeStrip(b, lib, b.getInstallStep(), strip, cmd);
|
|
220
|
+
if (force_pic and pic orelse false) lib.force_pic = pic;
|
|
159
221
|
if (emit_asm) {
|
|
160
222
|
b.getInstallStep().dependOn(&b.addInstallFileWithDir(
|
|
161
223
|
lib.getEmittedAsm(),
|
|
@@ -175,11 +237,9 @@ pub fn build(b: *std.Build) !void {
|
|
|
175
237
|
}
|
|
176
238
|
|
|
177
239
|
if (c) {
|
|
178
|
-
const
|
|
179
|
-
.{ .path = "src/include/pkmn.h" }
|
|
180
|
-
|
|
181
|
-
"pkmn.h",
|
|
182
|
-
);
|
|
240
|
+
const path =
|
|
241
|
+
if (has_path) .{ .path = "src/include/pkmn.h" } else b.path("src/include/pkmn.h");
|
|
242
|
+
const header = b.addInstallFileWithDir(path, .header, "pkmn.h");
|
|
183
243
|
b.getInstallStep().dependOn(&header.step);
|
|
184
244
|
|
|
185
245
|
const pc = b.fmt("lib{s}.pc", .{name});
|
|
@@ -209,7 +269,7 @@ pub fn build(b: *std.Build) !void {
|
|
|
209
269
|
b.installFile(file, b.fmt("share/pkgconfig/{s}", .{pc}));
|
|
210
270
|
}
|
|
211
271
|
|
|
212
|
-
const config = .{
|
|
272
|
+
const config: Config = .{
|
|
213
273
|
.target = target,
|
|
214
274
|
.optimize = optimize,
|
|
215
275
|
.pic = pic,
|
|
@@ -220,7 +280,7 @@ pub fn build(b: *std.Build) !void {
|
|
|
220
280
|
// TODO: tests can be run multiple times due to @imports
|
|
221
281
|
const tests = TestStep.create(b, options, config);
|
|
222
282
|
|
|
223
|
-
var exes = std.ArrayList(*
|
|
283
|
+
var exes = std.ArrayList(*Step.Compile).init(b.allocator);
|
|
224
284
|
const tools: ToolConfig = .{
|
|
225
285
|
.options = .{
|
|
226
286
|
.showdown = showdown,
|
|
@@ -228,6 +288,7 @@ pub fn build(b: *std.Build) !void {
|
|
|
228
288
|
.chance = chance,
|
|
229
289
|
.calc = calc,
|
|
230
290
|
},
|
|
291
|
+
.module = pkmn,
|
|
231
292
|
.general = config,
|
|
232
293
|
.tool = .{
|
|
233
294
|
.tests = if (tests.build) tests else null,
|
|
@@ -266,13 +327,127 @@ pub fn build(b: *std.Build) !void {
|
|
|
266
327
|
}
|
|
267
328
|
}
|
|
268
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 entry = @hasDecl(Step.Compile, "Entry");
|
|
342
|
+
const mode = switch (optimize) {
|
|
343
|
+
.ReleaseFast, .ReleaseSafe => .ReleaseSmall,
|
|
344
|
+
else => optimize,
|
|
345
|
+
};
|
|
346
|
+
// https://webassembly.org/features/
|
|
347
|
+
var features = std.Target.wasm.featureSet(&.{
|
|
348
|
+
.atomics,
|
|
349
|
+
.bulk_memory,
|
|
350
|
+
// .exception_handling,
|
|
351
|
+
.extended_const,
|
|
352
|
+
// .half_precision,
|
|
353
|
+
// .multimemory,
|
|
354
|
+
.mutable_globals,
|
|
355
|
+
.nontrapping_fptoint,
|
|
356
|
+
.reference_types,
|
|
357
|
+
// .relaxed_simd,
|
|
358
|
+
.sign_ext,
|
|
359
|
+
.simd128,
|
|
360
|
+
// .tail_call,
|
|
361
|
+
});
|
|
362
|
+
if (builtin.zig_version.order(try std.SemanticVersion.parse("0.12.0")) != .lt) {
|
|
363
|
+
features.addFeature(@intFromEnum(std.Target.wasm.Feature.multivalue));
|
|
364
|
+
}
|
|
365
|
+
const freestanding = if (@hasDecl(std.Build, "resolveTargetQuery"))
|
|
366
|
+
b.resolveTargetQuery(.{
|
|
367
|
+
.cpu_arch = .wasm32,
|
|
368
|
+
.os_tag = .freestanding,
|
|
369
|
+
.cpu_features_add = features,
|
|
370
|
+
})
|
|
371
|
+
else
|
|
372
|
+
ResolvedTarget{
|
|
373
|
+
.cpu_arch = .wasm32,
|
|
374
|
+
.os_tag = .freestanding,
|
|
375
|
+
.cpu_features_add = features,
|
|
376
|
+
};
|
|
377
|
+
const path = if (has_path) .{ .path = root_src_file } else b.path(root_src_file);
|
|
378
|
+
const bin = if (entry) bin: {
|
|
379
|
+
const exe = b.addExecutable(if (force_pic) .{
|
|
380
|
+
.name = name,
|
|
381
|
+
.root_source_file = path,
|
|
382
|
+
.optimize = mode,
|
|
383
|
+
.target = freestanding,
|
|
384
|
+
} else .{
|
|
385
|
+
.name = name,
|
|
386
|
+
.root_source_file = path,
|
|
387
|
+
.optimize = mode,
|
|
388
|
+
.target = freestanding,
|
|
389
|
+
.strip = strip,
|
|
390
|
+
.pic = pic,
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
var file = try std.fs.cwd().openFile(root_src_file, .{});
|
|
394
|
+
defer file.close();
|
|
395
|
+
const bytes = try file.readToEndAlloc(b.allocator, std.math.maxInt(usize));
|
|
396
|
+
(if (root_module) exe.root_module else exe).export_symbol_names = try exports(b, bytes);
|
|
397
|
+
exe.entry = .disabled;
|
|
398
|
+
break :bin exe;
|
|
399
|
+
} else bin: {
|
|
400
|
+
const lib = b.addSharedLibrary(.{
|
|
401
|
+
.name = name,
|
|
402
|
+
.root_source_file = path,
|
|
403
|
+
.optimize = mode,
|
|
404
|
+
.target = freestanding,
|
|
405
|
+
});
|
|
406
|
+
lib.rdynamic = true;
|
|
407
|
+
break :bin lib;
|
|
408
|
+
};
|
|
409
|
+
if (import) |i| {
|
|
410
|
+
if (root_module) {
|
|
411
|
+
bin.root_module.addImport("pkmn", i);
|
|
412
|
+
} else {
|
|
413
|
+
bin.addModule("pkmn", i);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
bin.stack_size = wasm_stack_size;
|
|
417
|
+
if (@hasDecl(@TypeOf(bin.*), "strip")) bin.strip = strip orelse false;
|
|
418
|
+
if (force_pic and pic orelse false) bin.force_pic = pic;
|
|
419
|
+
(if (root_module) bin.root_module else bin).addOptions("build_options", options);
|
|
420
|
+
|
|
421
|
+
const opt = b.findProgram(&.{"wasm-opt"}, &.{"./node_modules/.bin"}) catch null;
|
|
422
|
+
if (optimize != .Debug and opt != null) {
|
|
423
|
+
const out = b.fmt("build/lib/{s}.wasm", .{name});
|
|
424
|
+
const sh = b.addSystemCommand(&.{ opt.?, "--enable-bulk-memory", "--enable-simd", "-O4" });
|
|
425
|
+
sh.addArtifactArg(bin);
|
|
426
|
+
sh.addArg("-o");
|
|
427
|
+
if (@hasDecl(@TypeOf(sh.*), "addFileSourceArg")) {
|
|
428
|
+
sh.addFileSourceArg(if (has_path) .{ .path = out } else b.path(out));
|
|
429
|
+
} else {
|
|
430
|
+
sh.addFileArg(if (has_path) .{ .path = out } else b.path(out));
|
|
431
|
+
}
|
|
432
|
+
b.getInstallStep().dependOn(&sh.step);
|
|
433
|
+
if (!entry) b.installArtifact(bin);
|
|
434
|
+
} else if (entry) {
|
|
435
|
+
b.getInstallStep().dependOn(&b.addInstallArtifact(bin, .{
|
|
436
|
+
.dest_dir = .{ .override = std.Build.InstallDir{ .lib = {} } },
|
|
437
|
+
}).step);
|
|
438
|
+
} else {
|
|
439
|
+
b.installArtifact(bin);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
269
443
|
fn maybeStrip(
|
|
270
444
|
b: *std.Build,
|
|
271
|
-
artifact: *
|
|
445
|
+
artifact: *Step.Compile,
|
|
272
446
|
step: *std.Build.Step,
|
|
273
447
|
strip: ?bool,
|
|
274
448
|
cmd: ?[]const u8,
|
|
275
449
|
) void {
|
|
450
|
+
if (@hasDecl(@TypeOf(artifact.*), "strip")) artifact.strip = strip orelse false;
|
|
276
451
|
if (!(strip orelse false) or cmd == null) return;
|
|
277
452
|
// Using `strip -r -u` for dynamic libraries is supposed to work on macOS but doesn't...
|
|
278
453
|
const mac = builtin.os.tag == .macos;
|
|
@@ -285,7 +460,7 @@ fn maybeStrip(
|
|
|
285
460
|
}
|
|
286
461
|
|
|
287
462
|
const Config = struct {
|
|
288
|
-
target:
|
|
463
|
+
target: ResolvedTarget,
|
|
289
464
|
optimize: std.builtin.OptimizeMode,
|
|
290
465
|
pic: ?bool,
|
|
291
466
|
strip: ?bool,
|
|
@@ -296,7 +471,7 @@ const TestStep = struct {
|
|
|
296
471
|
step: std.Build.Step,
|
|
297
472
|
build: bool,
|
|
298
473
|
|
|
299
|
-
pub fn create(b: *std.Build, options: *
|
|
474
|
+
pub fn create(b: *std.Build, options: *Step.Options, config: Config) *TestStep {
|
|
300
475
|
const coverage = b.option([]const u8, "test-coverage", "Generate test coverage");
|
|
301
476
|
const test_filter =
|
|
302
477
|
b.option([]const u8, "test-filter", "Skip tests that do not match filter");
|
|
@@ -305,8 +480,14 @@ const TestStep = struct {
|
|
|
305
480
|
const step = std.Build.Step.init(.{ .id = .custom, .name = "Run all tests", .owner = b });
|
|
306
481
|
self.* = .{ .step = step, .build = test_filter == null };
|
|
307
482
|
|
|
308
|
-
const
|
|
309
|
-
|
|
483
|
+
const path = if (has_path) .{ .path = "src/lib/test.zig" } else b.path("src/lib/test.zig");
|
|
484
|
+
const tests = b.addTest(if (force_pic) .{
|
|
485
|
+
.root_source_file = path,
|
|
486
|
+
.optimize = config.optimize,
|
|
487
|
+
.target = config.target,
|
|
488
|
+
.filter = test_filter,
|
|
489
|
+
} else .{
|
|
490
|
+
.root_source_file = path,
|
|
310
491
|
.optimize = config.optimize,
|
|
311
492
|
.target = config.target,
|
|
312
493
|
.filter = test_filter,
|
|
@@ -314,8 +495,13 @@ const TestStep = struct {
|
|
|
314
495
|
.strip = config.strip,
|
|
315
496
|
.pic = config.pic,
|
|
316
497
|
});
|
|
317
|
-
tests.root_module.addOptions("build_options", options);
|
|
498
|
+
(if (root_module) tests.root_module else tests).addOptions("build_options", options);
|
|
499
|
+
|
|
318
500
|
maybeStrip(b, tests, &tests.step, config.strip, config.cmd);
|
|
501
|
+
if (force_pic) {
|
|
502
|
+
tests.single_threaded = true;
|
|
503
|
+
if (config.pic orelse false) tests.force_pic = config.pic;
|
|
504
|
+
}
|
|
319
505
|
if (coverage) |c| {
|
|
320
506
|
tests.setExecCmd(&.{ "kcov", "--include-pattern=src/lib", c, null });
|
|
321
507
|
}
|
|
@@ -327,35 +513,48 @@ const TestStep = struct {
|
|
|
327
513
|
|
|
328
514
|
const ToolConfig = struct {
|
|
329
515
|
options: Options,
|
|
516
|
+
module: ?*std.Build.Module,
|
|
330
517
|
general: Config,
|
|
331
518
|
tool: struct {
|
|
332
519
|
tests: ?*TestStep,
|
|
333
520
|
name: ?[]const u8 = null,
|
|
334
|
-
exes: *std.ArrayList(*
|
|
521
|
+
exes: *std.ArrayList(*Step.Compile),
|
|
335
522
|
},
|
|
336
523
|
};
|
|
337
524
|
|
|
338
|
-
fn tool(b: *std.Build, path: []const u8, config: ToolConfig) !?*
|
|
339
|
-
|
|
340
|
-
error.FileNotFound => return null,
|
|
341
|
-
else => |e| return e,
|
|
342
|
-
};
|
|
525
|
+
fn tool(b: *std.Build, path: []const u8, config: ToolConfig) !?*Step.Run {
|
|
526
|
+
if (!try exists(path)) return null;
|
|
343
527
|
var name = config.tool.name orelse std.fs.path.basename(path);
|
|
344
528
|
const index = std.mem.lastIndexOfScalar(u8, name, '.');
|
|
345
529
|
if (index) |i| name = name[0..i];
|
|
346
530
|
if (config.options.showdown orelse false) name = b.fmt("{s}-showdown", .{name});
|
|
347
531
|
|
|
348
|
-
const exe = b.addExecutable(.{
|
|
532
|
+
const exe = b.addExecutable(if (force_pic) .{
|
|
533
|
+
.name = name,
|
|
534
|
+
.root_source_file = if (has_path) .{ .path = path } else b.path(path),
|
|
535
|
+
.target = config.general.target,
|
|
536
|
+
.optimize = config.general.optimize,
|
|
537
|
+
} else .{
|
|
349
538
|
.name = name,
|
|
350
|
-
.root_source_file = .{ .path = path },
|
|
539
|
+
.root_source_file = if (has_path) .{ .path = path } else b.path(path),
|
|
351
540
|
.target = config.general.target,
|
|
352
541
|
.optimize = config.general.optimize,
|
|
353
542
|
.single_threaded = true,
|
|
354
543
|
.strip = config.general.strip,
|
|
355
544
|
.pic = config.general.pic,
|
|
356
545
|
});
|
|
357
|
-
exe.root_module.addImport("pkmn", module(b, config.options));
|
|
358
546
|
|
|
547
|
+
if (root_module) {
|
|
548
|
+
const import = if (config.module) |m| m else module(b, config.options);
|
|
549
|
+
exe.root_module.addImport("pkmn", import);
|
|
550
|
+
} else {
|
|
551
|
+
exe.addModule("pkmn", module(b, config.options));
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
if (force_pic) {
|
|
555
|
+
exe.single_threaded = true;
|
|
556
|
+
if (config.general.pic orelse false) exe.force_pic = config.general.pic;
|
|
557
|
+
}
|
|
359
558
|
if (config.tool.tests) |ts| ts.step.dependOn(&exe.step);
|
|
360
559
|
config.tool.exes.append(exe) catch @panic("OOM");
|
|
361
560
|
|
|
@@ -366,10 +565,18 @@ fn tool(b: *std.Build, path: []const u8, config: ToolConfig) !?*std.Build.Step.R
|
|
|
366
565
|
return run;
|
|
367
566
|
}
|
|
368
567
|
|
|
568
|
+
fn exists(path: []const u8) !bool {
|
|
569
|
+
std.fs.cwd().access(path, .{}) catch |err| switch (err) {
|
|
570
|
+
error.FileNotFound => return false,
|
|
571
|
+
else => |e| return e,
|
|
572
|
+
};
|
|
573
|
+
return true;
|
|
574
|
+
}
|
|
575
|
+
|
|
369
576
|
const ToolsStep = struct {
|
|
370
577
|
step: std.Build.Step,
|
|
371
578
|
|
|
372
|
-
pub fn create(b: *std.Build, exes: *std.ArrayList(*
|
|
579
|
+
pub fn create(b: *std.Build, exes: *std.ArrayList(*Step.Compile)) *ToolsStep {
|
|
373
580
|
const self = b.allocator.create(ToolsStep) catch @panic("OOM");
|
|
374
581
|
const step = std.Build.Step.init(.{ .id = .custom, .name = "Install tools", .owner = b });
|
|
375
582
|
self.* = .{ .step = step };
|
|
@@ -377,3 +584,26 @@ const ToolsStep = struct {
|
|
|
377
584
|
return self;
|
|
378
585
|
}
|
|
379
586
|
};
|
|
587
|
+
|
|
588
|
+
fn detect(target: anytype) std.Target {
|
|
589
|
+
if (@hasField(@TypeOf(target), "result")) return target.result;
|
|
590
|
+
return (std.zig.system.NativeTargetInfo.detect(target) catch unreachable).target;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
pub fn exports(b: *std.Build, bytes: []const u8) ![][]const u8 {
|
|
594
|
+
var symbols = std.ArrayList([]const u8).init(b.allocator);
|
|
595
|
+
|
|
596
|
+
var it = std.mem.splitSequence(u8, bytes, "export ");
|
|
597
|
+
_ = it.next();
|
|
598
|
+
while (it.next()) |s| {
|
|
599
|
+
if (std.mem.startsWith(u8, s, "const ")) {
|
|
600
|
+
const i = std.mem.indexOf(u8, s[6..], " ").?;
|
|
601
|
+
try symbols.append(s[6 .. 6 + i]);
|
|
602
|
+
} else { // "fn "
|
|
603
|
+
const i = std.mem.indexOf(u8, s[3..], "(").?;
|
|
604
|
+
try symbols.append(s[3 .. 3 + i]);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
return symbols.items;
|
|
609
|
+
}
|