-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathbuild.zig
138 lines (118 loc) · 5.11 KB
/
build.zig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
const std = @import("std");
const Backend = enum {
ncurses,
crossterm,
};
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const user_options = Options.init(b);
const module_options = b.addOptions();
module_options.addOption(Backend, "backend", user_options.backend);
const module = b.addModule("tuile", .{
.root_source_file = b.path("src/tuile.zig"),
.target = target,
.optimize = optimize,
});
const lib_unit_tests = b.addTest(.{
.root_source_file = b.path("src/tests.zig"),
.target = target,
.optimize = optimize,
});
module.addOptions("build_options", module_options);
lib_unit_tests.root_module.addOptions("build_options", module_options);
const zg = b.dependency("zg", .{});
module.addImport("grapheme", zg.module("grapheme"));
module.addImport("DisplayWidth", zg.module("DisplayWidth"));
lib_unit_tests.root_module.addImport("grapheme", zg.module("grapheme"));
lib_unit_tests.root_module.addImport("DisplayWidth", zg.module("DisplayWidth"));
switch (user_options.backend) {
.ncurses => {
module.link_libc = true;
module.linkSystemLibrary("ncurses", .{});
lib_unit_tests.linkLibC();
lib_unit_tests.linkSystemLibrary("ncurses");
},
.crossterm => {
const build_crab = @import("build.crab");
var crossterm_lib_path: std.Build.LazyPath = undefined;
if (user_options.prebuilt) {
const rust_target = build_crab.Target.fromZig(target.result) catch @panic("unable to convert target triple to Rust");
const prebuilt_name = b.fmt("tuile-crossterm-{}", .{rust_target});
const prebuilt_opt = b.lazyDependency(prebuilt_name, .{});
if (prebuilt_opt == null) {
return;
}
std.log.info("Using prebuilt crossterm backend for target {}", .{rust_target});
const prebuilt = prebuilt_opt.?;
crossterm_lib_path = prebuilt.path("libtuile_crossterm.a");
} else {
const tuile_crossterm_opt = b.lazyDependency("tuile-crossterm", .{});
if (tuile_crossterm_opt == null) {
return;
}
std.log.info("Building crossterm backend from source", .{});
const tuile_crossterm = tuile_crossterm_opt.?;
crossterm_lib_path = build_crab.addRustStaticlibWithUserOptions(
b,
.{
.name = "libtuile_crossterm.a",
.manifest_path = tuile_crossterm.path("Cargo.toml"),
.cargo_args = &.{
"--release",
"--quiet",
},
},
.{ .target = target, .optimize = .ReleaseSafe },
);
}
module.link_libcpp = true;
module.addLibraryPath(crossterm_lib_path.dirname());
module.linkSystemLibrary("tuile_crossterm", .{});
lib_unit_tests.linkLibCpp();
lib_unit_tests.addLibraryPath(crossterm_lib_path.dirname());
lib_unit_tests.linkSystemLibrary("tuile_crossterm");
},
}
const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests);
run_lib_unit_tests.has_side_effects = true;
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&run_lib_unit_tests.step);
}
pub const Options = struct {
backend: Backend = .crossterm,
prebuilt: bool = true,
pub fn init(b: *std.Build) Options {
var opts: Options = .{};
opts.backend = requestedBackend(b) orelse opts.backend;
opts.prebuilt = b.option(bool, "prebuilt", "Use prebuilt crossterm backend") orelse opts.prebuilt;
if (opts.prebuilt and opts.backend != .crossterm) {
@panic("prebuilt option is only available with crossterm backend");
}
return opts;
}
fn requestedBackend(b: *std.Build) ?Backend {
const backend_str = @tagName(b.option(Backend, "backend", "Terminal manipulation backend") orelse return null);
var backend: Backend = undefined;
if (std.ascii.eqlIgnoreCase(backend_str, @tagName(Backend.ncurses))) {
backend = .ncurses;
} else if (std.ascii.eqlIgnoreCase(backend_str, @tagName(Backend.crossterm))) {
backend = .crossterm;
} else {
const names = comptime blk: {
const info = @typeInfo(Backend);
const fields = info.Enum.fields;
var names: [fields.len][]const u8 = undefined;
for (&names, fields) |*name, field| {
name.* = field.name;
}
break :blk names;
};
@panic(b.fmt(
"Option {s} is not a valid backend. Valid options are: {}",
.{ backend_str, std.json.fmt(names, .{}) },
));
}
return backend;
}
};